Skip to content →

Category: Tech Blog

Here you can find my random notes on software design and development, software engineering, coding, and all other tech-related stuff.

Raspberry Pi as a toy web server

1. Tell my router to route certain traffic to the Raspberry Pi. For example, I route HTTP and SSH traffic to one of my Pi’s. I disabled password login for  SSH, using public key authentication instead: in /etc/ssh/sshd_config, use the following setting and restart SSH service using `sudo service ssh restart’.

2. Getting my IP address of the Raspberry Pi. I firstly created a PHP script on my domain to record the IP address in a text file.

Then tell the Raspberry Pi to report its IP address every 5 minutes, using crontab:

After a while the IP address is recorded in the text file and updated every 5 minutes.

3. Optionally create a DNS record for the Pi. I use Cloudflare to manage DNS settings by myself, so just add/update an entry in Cloudflare’s settings. I point to the IP address of one Pi. This can be done automatically in the future.

4. Install Flask on the Pi.

5. Install nginx and uwsgi on the Pi.

6. Set up nginx along with uwsgi and Flask.

Edit nginx config:

Edit uwsgi config:

Create a simple Flask app:

Start up uwsgi:

7. Done!

 Update on June 24, 2014:

Getting the external address in step 2 can be done by running this command in Raspberry Pi:


Leave a Comment

NumPy’s ndarray indexing

In NumPy a new kind of array is provided: n-dimensional array or ndarray. It’s usually fixed-sized and accepts items of the same type and size. For example, to define a 2×3 matrix:

When indexing ndarray, it supports “array indexing” other than single element indexing.  (See

It is possible to index arrays with other arrays for the purposes of selecting lists of values out of arrays into new arrays. There are two different ways of accomplishing this. One uses one or more arrays of index values. The other involves giving a boolean array of the proper shape to indicate the values to be selected. Index arrays are a very powerful tool that allow one to avoid looping over individual elements in arrays and thus greatly improve performance.

So you basically can do the following:

Besides, when you do equals operation on ndarrays, another ndarray is returned by comparing each element:

Leave a Comment

Statistics of insurance sold on on Valentine’s Day

On Feb. 14th Taobao launched a campaign to sell insurance products, which promises 7% yearly interest rate. The sales data is public, so I wrote a script to crawl them down and did a brief study on this data. Here’re the results.

On that day (actually sold out in less than two hours in total) more than 40,000 people participated, resulting a total sales of almost one billion CNY (the exact number: 980,270,000 CNY). Two companies participated in this sales campaign: Zhujiang and Tian’an. The sales statistics are:

Zhujiang Tian’an Total
# of Customers 13831 29092 42923
Sales mean (k CNY) 24.922059 21.847003 22.837872
Sales min (k CNY) 1 1 1
Sales 25% (k CNY) 1 2 2
Sales 50% (k CNY) 10 10 10
Sales 75% (k CNY) 20 25 22
Sales max (k CNY) 1000 900 1000
Sales total (k CNY) 344697 635573 980270

The histograms of how many people pay for each amount.


Zhujiang was extremely popular: in 2 minutes and 56 seconds it reached a sales of 200,212,000 CNY, that’s more than 1 million CNY sales PER SECOND! Indeed Chinese are crazy about online shopping. 😀

Leave a Comment

MapReduce in MongoDB

The MapReduce code I used to analyze the 20 million hotel reservation records:


Leave a Comment

Debugging Apache configuration files on Mac OS X

Sometimes I make some modification to my site’s apache config and apache stops functioning, but I cannot get enough information from /var/log/apache2/error.log. Here’s a command that will tell you where the problem is:

It starts apache for debugging and prints out the messages on screen, so that hopefully you can find something useful.

Leave a Comment

mod_wsgi and mod_xsendfile on OS X 10.9 Mavericks

Updated on Nov 4, 2013: The following tricks may still work, however I have found a much easier solution. Simply install Xcode command line developer tools and you should be able to compile source code without issues:

After upgrading my Mac from 10.8 to 10.9 Mavericks my apache stopped working, so I have to reinstall mod_wsgi and mod_xsendfile. However, tricks are needed to compile and install these mods successfully.

Upgrade Xcode

Upgrade Xcode in App Store. As mentioned by Valerie:

I had to manually upgrade Xcode (after Mavericks upgrade) from the App Store & agree to its license because ./configure hung forever until I did that.


For mod_wsgi installation, create a soft link to OSX10.9.xctoolchain:

Then run configure under mod_wsgi source code directory:

It will generate a Makefile similar as follows:

However, this Makefile is not correct and running ‘make’ the compiler will complain something like:

Prepend the following line to CPPFLAGS value:

Save the Makefile and it will look something like:

Then make && install:

Modify /etc/apache2/httpd.conf to enable mod_wsgi:


Use the following command to compile and install mod_xsendfile:

Enabling HTTPS/SSL

After upgrading OS X the apache configuration was reset, but your original config is save to /etc/apache2/httpd.conf.pre-update. I need to enable SSL in httpd.conf again by uncommenting the following line:

Restart Apache and everything should work fine


Solution: dd too slow on Mac OS X

When I was cloning SD cards on Mac OS X using dd', it takes ages to get things done. I was using the following command:

It takes much less time when using /dev/rdisk2 instead of /dev/disk2:

The reason is that rdisks are "raw" thus resulting in a higher R/W speed, according to man hdiutil` [1]:

/dev/rdisk nodes are character-special devices, but are “raw” in the BSD sense and force block-aligned I/O. They are closer to the physical disk than the buffer cache. /dev/disk nodes, on the other hand, are buffered block-special devices and are used primarily by the kernel’s filesystem code.



Facebook vs. Google advertisements

Since last week I’ve been investigating how to efficiently promote our website ( Our Facebook page got 139 likes a week ago, and now we have 175. Among the 36 new likes, 22 are from two Facebook campaigns. The first campaign cost 15 dollars and earned 20 likes, averaging 0.75 dollars per like with a click-through rate of 0.290%. In a way this is affordable and more efficiently than stand at international students’ dormitory in Shanghai and spread flyers. Three of us probably sent out around 100 flyers to international students but got nothing to our Facebook page nor website. The first campaign focused on gaining new likes and it went quite well; our second campaign cost 5 dollars, promoting a video post with a goal to earn new likes. This campaign boosted another 2,169 reach, 143 clicks and 2 new likes. Had the video been more engaging, probably we could have gotten more clicks, shares and likes. Since Facebook users nowadays are exposed more and more to various contents, it’s become increasingly difficult to get users engaged.

In the meanwhile, we also launched three campaigns on Google Adwords. So far we got 30 clicks and cost about 40 dollars. The average CPC is $1.36 — almost twice of that for FB, but the conversion rate is zero. No one has applied or enquired our pages (maybe due to the low volume). Google Adwords is different from Facebook. On Facebook you attract people to your FB page but not your website; whereas Google takes visitors directly to your website. FB leaves you a space for imagination, though. Once you get a page like from someone, he/she will be able to see the updates your page posts.

Suppose the Google CPC is twice of Facebook CPC, if one in two earned FB followers click one of our promoted posts, FB is doing better. That does not sound like a issue. I’d place all my bet on Facebook and maybe time to buy FB shares?

We also tried to promote on LinkedIn but failed to find appropriate ways. LinkedIn is mainly for serious jobs, not internships. Instagram neither, there seems to be a lot of robots on Instagram; it’s not clear for us to find a way to promote ourselves, either. So for the moment, we only consider Facebook and Google. Oh no, Facebook is our focus and Google is not helping much, but we still need to spend the remaining 90 dollars we got from a coupon, slowly.

Leave a Comment

A “normal” sed on Mac

The sed program on Mac is not a standard (GNU) one. To get the normal one, use brew:

After this, alter PATH. For example, add the following line to your ~/.bash_profile:

And now you have a normal sed!


Leave a Comment

A faster key repeat rate for Mac OS X

The fastest one can get via System Preferences is 2. You can set it to either 0 or 1, depending on your preferences.

To check your current repeat rate, issue the following command in Terminal:


Leave a Comment

Tastypie error handling with Unauthorized Exception

In Tastypie v0.9.15 unauthorized exception messages are not included in the response. The cause lies in the following code: (tastypie/, Line 601-602 in v0.9.15)

In the above snippet an empty response is returned, without including messages in exception.

In order to fix this, you can override this method in your model resources, for example:

Hi, the company I’m working for ( is hiring Website Backend and Frontend Developers to our platform team. We are building an open platform for youngsters to travel beyond boarders and we offer youngsters internship, language study, travel and volunteer opportunities. Please contact me if you are interested.

Leave a Comment

Upgrading Tastypie from v0.9.11 to v0.9.12 and above

Here are my notes on how to upgrade Tastypie from version 0.9.11 to 0.9.12, as there’re no release notes for v0.9.12. Release notes for 0.9.13 and above are available here:

1. override_urls() becomes prepend_urls(), the new name makes more sense since what the function does is to insert customized urls instead of replacing the default urls with your customized urls.

2. obj_* methods accepts different parameters. Before:

Now obj_get, obj_create, etc. accepts bundle as the parameter apart from keyword arguments. You can get request object from the bundle:

3. apply_authorization_limits is no longer in use and it’s replace with a finer grained authorization mechanism. For example:

Please note that *_list methods should return a list or raise exceptions; whereas *_detail methods should return boolean values or raise exceptions. For more information, see:

Hi, the company I’m working for ( is hiring Website Backend and Frontend Developers to our platform team. We are building an open platform for youngsters to travel beyond boarders and we offer youngsters internship, language study, travel and volunteer opportunities. Please contact me if you are interested.

Leave a Comment

OpenVPN client TLS-Auth problem on Windows

It seems that the OpenVPN Client on windows does not support TLS-Auth with a separate key file. So instead, you can paste your key contents in your openvpn client’s config file and use some thing like the following (inline ta.key):

When not using the above but using something like:

The server log shows something like:


funf smart phone data collecting


battery_life phone_temperature relative_activity screen_activity


老实说,收集了两天的数据,就能分析出这么点东西,着实让人失望。不过这个生成图像信息的程序是开源的,而且是用Python实现的,今后有空了也可以自己来分析一下收集到的数据。funf在我的手机上也经常不能响应,可以说这个app是十足的半成品。不过这个由来自MIT的团队开发的不仅仅是一个手机app,号称是一个Open Sensing Framework,前几天还刚刚被Google收购了。虽然是个半成品,但Google这个时候收购团队总比让他们羽翼丰满之后再收购所花的代价要小得多。

Leave a Comment