2015/12/31

Raspberry Pi情報彙整(60)

我收集整理網路上看到的、感興趣的、跟Raspberry Pi相關的資訊,如果您發現任何新奇驚人的專案、新聞、活動等等,還請留言告知。

[活動] WoFOSS 2015/ 12月第65次聚會(Raspberry Pi 工作坊 - GPIO 遊戲機學習套件教學),呃,這篇太晚發了,已經結束啦。

Tingbot - Raspberry Pi made even more fun! by Tingbot —Kickstarter,嗯,看起來就是個裝置,提供開發平台與API,但我不太懂賣點在哪。
Has anyone seen my dog? — redpepper has ideas — Medium,剛打完一段程式碼,想摸摸寵物小狗的頭,卻發現牠又不知道跑去哪兒了;試著運用訊號強度與三角定位尋找牠的身影吧。
Creating and Kickstarting Slice, the Compute Module-Based Media Player - Raspberry Pi,以rpi計算模組打造的媒體播放器Slice,放上群眾募資平台,一路走來的心路歷程與經驗談,值得一看。
Watch the launch - Astro Pi,Astro Pi終於升空出發啦。看看rpi基金會官方的報導Astro Pi: Launch is tonight! - Raspberry Pi
Build a Wireless Water Meter for Your Home - IEEE Spectrum,珍惜水資源,打造監控系統吧。
內裝Raspberry Pi,可玩懷舊遊戲的復古風迷你遊戲筐體Starforce Pi | T客邦 - 我只推薦好東西,嗯,看起來滿不錯的。
Pi Wars 2015 gallery: the robots strike back - The Magpi Magazine,Pi Wars 2015結束囉,趕緊來看看有哪些作品;基金會部落格選出的作品
Using a Raspberry Pi + Camera to Monitor the Nocturnal Activities of Tropical Insects,觀察夜行性生物與熱帶昆蟲。
DOTs Board: on sale now! - Raspberry Pi,rpi基金會官方推出的DOTs板子,開始在The PiHut銷售,用電子油墨畫畫就可以連接電路,真棒。
ExaGear Desktop - Running Intel x86 applications on ARM-based Mini PCs,哇,在ARM上面跑x86的Linux,類似QEMU但更快,若安裝Wine還可以跑Windows軟體。
Light painting with a Raspberry Pi - Raspberry Pi,光畫,太強了吧。
Easily Distracted: BOM for sub-£15 Raspberry Pi robot,不知道組一台rpi機器人要多少預算嗎,看看這篇吧。
Turning a Pi Into a PDP 11 | Hackaday,想學習好久好久以前的迷你電腦PDP嗎,不必到博物館,自己做一台吧。
Raspberry Pi controlled oven | Gordons Projects,WiringPi作者的趣味專案,控制烤爐。
OpenRelief,開源計畫,開發各種技術、工具、無人機,在發生災難時,可以飛到現場,傳回第一手資訊,協助救災。
Issue #41 of The MagPi is out now.,MagPi實在太厲害啦,併入基金會,又能出紙本版,還另出了兩本專題書(Bash與遊戲)。
Good, Better, Beast!,還記得那集結120塊rpi板子嗎,看看該團隊接下來想做些什麼吧。
超越樹莓派的小板板!LattePanda 只有口袋大卻能完整運行 Win 10 | TechOrange,哇賽,可跑Windows 10喔,非任何縮減版本。

其他:

2015/12/29

【翻譯新作】 忍者:JavaScript開發技巧探秘(Secrets of the JavaScript Ninja)

嗨,我翻譯了一本書,在此敬告舊雨新知。

書名:忍者:JavaScript開發技巧探秘
原書名:Secrets of the JavaScript Ninja
作者:John Resig(jQuery程式庫創建者)、Bear Bibeault
譯者:我
出版社:博碩
出版日期:2015年12月30日
頁數:456

本書借用「忍者」一詞,是形容技巧高超的開發者,他們久經訓練、身懷絕技、並且通曉各樣知識,彷彿古代日本忍者一般。

本書將引領讀者重新認識JavaScript的函式、物件、閉包、正規表達式等項目,也就是那些可能已經一用再用,但卻未曾深刻瞭解其箇中精髓的事物。此外佐以實務性的觀點與提醒,讓開發者能夠以正確的架構開發出跨瀏覽器的應用程式、甚至是全新的框架或程式庫,成為名副其實的「忍者」。

書籍目錄

修業之前的準備

01 進入 JavaScript 忍者的世界
02 裝備測試與除錯工具

學徒修業

03 函式乃基本礎石
04 揮舞函式之劍
05 閉包封鎖之術
06 原型之物件導向
07 與正規表達式吵嘴
08 馴服執行緒和計時器

忍者修業

09 忍者煉金術: 執行期間程式計值
10 with 述句
11 跨瀏覽器開發策略
12 跨越屬性項、屬性與 CSS

大師修業

13 從事件中倖存
14 操控 DOM
15 CSS 選擇器引擎

2015/12/26

【翻譯新作】 Python 設計模式深入解析(Mastering Python Design Patterns)

嗨,我翻譯了一本書,不知為何忘記在此公布,趕緊補上。

書名:Python設計模式深入解析
原書名:Mastering Python Design Patterns
作者:Sakis Kasampalis
譯者:我
出版社:博碩
出版日期:2015年8月30日
頁數:208

Python是一門運用廣泛、物件導向的腳本式語言。在軟體工程中,所謂的設計模式即是用以解決軟體設計問題的推薦方案。儘管並非新事物,設計模式仍然是熱門議題,並且可作為軟體工程師解決常見問題的便捷參考資源。

本書將帶領讀者,深入解析每一種設計模式,並佐以真實世界中的範例。本書目標是透過更加低階的細節與概念、建構出符合Python精神的程式碼,而非只是承襲那些來自Java或C++的實作。

內容包含了疑難排解、最佳實踐、系統架構、以及設計的多種面向。藉由本書內容,讀者能夠充分瞭解Python設計模式的概念與框架,以及相關問題和解決方案。書內共有16種設計模式,能夠用來解決日常工作中的諸多問題。

適用讀者:

本書適用於中等程度的Python程式設計師,並且有意願將設計模式正確應用於Python程式語言。不過非Python使用者若是對Python有興趣,也能夠從本書獲益,只要先對Python的基礎有所瞭解即可。

你能夠從本書學習:

探索用來建立物件的工廠方法與抽象工廠。

利用原型模式複製物件。

藉由轉接器模式使不相容的介面變得相容。

利用代理模式來保障介面。

藉由策略模式來動態選擇演算法。

利用裝飾器模式對物件進行延展,卻無須使用子類別。

利用 MVC 模式保持 UI 與邏輯之間的分離。

目錄

01 工廠模式
02 建造者模式
03 原型模式
04 轉接器模式
05 裝飾器模式
06 外觀模式
07 輕量模式
08 模型-檢視-控制器模式
09 代理模式
10 責任鏈模式
11 命令模式
12 直譯器模式
13 觀察者模式
14 狀態模式
15 策略模式
16 模板模式

Arduino小冷門知識:char不一定是-128到127

當我宣告char變數、並把它當作整數來使用的話,我預期它的大小會是1位元組,而合法範圍是-128到127、或是0到255,因為char可能是signed或unsigned,由C語言實作決定。

但卻發現違反上述說法的例子。

程式碼如下:
char x_global = 0;

void setup(){
    Serial.begin(115200);
}

void loop(){
    char x_local = 0;
   
    while(1){
        Serial.print(int(x_global));
        Serial.print("  ");
        Serial.print(int(x_local));
        Serial.println("");
        x_global++;
        x_local++;
        delay(100);
    }
}


全域變數x_global、區域變數x_local,不斷地加1並印出。

x_global的值符合預期,從0、1、2、3...到127,然後會到-128,接著是-127、-126、-125...到-1,然後又回到0。

但x_local不如預期,從0、1、2、3...到127,然後到128、129、130、一直變大、可超過幾百、幾千。

Arduino 1.0.6會有上述奇怪的行為。不過在Arduino 1.6.7就不會有。

若改成signed char,行為同上。

若改成unsigned char,那麼兩個變數都會從0、1、2、3...到255,然後回到0、1、2...。

2015/12/25

Raspberry Pi:Raspbian編譯OpenCV原始碼

我的環境是Raspberry Pi 2、Raspbian Jessie(2015-11-21),自行編譯OpenCV(Open Source Computer Vision Library),我抓的版本是3.1.0。

先更新套件清單並升級:
$ sudo apt-get update
$ sudo apt-get dist-upgrade -y

若是直接安裝現成的套件,指令如下:
$ sudo apt-get install libopencv-dev

不過得到的OpenCV版本通常過舊,因此自行下載原始碼,手動建置編譯。從OpenCV官方的安裝步驟,得知需要先安裝一堆相依套件。

建置與編譯所需工具:
$ sudo apt-get install build-essential gcc cmake pkg-config

抓原始檔需要的工具:
$ sudo apt-get install git

Python相關:
$ sudo apt-get install python python-dev python-numpy

圖形視窗程式庫:
$ sudo apt-get install libgtk2.0-dev

音訊視訊的編解碼、錄製、轉換、串流:
$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev

圖檔格式(選用性):
$ sudo apt-get install libjpeg-dev libpng-dev libtiff-dev libjasper-dev

IEEE 1394相機介面(選用性):
$ sudo apt-get install libdc1394-22-dev

TBB(Intel's Threading Building Blocks)(選用性):
$ sudo apt-get install libtbb2 libtbb-dev
出現錯誤訊息:
E: Unable to locate package libtbb2
E: Package 'libtbb-dev' has no installation candidate

大都沒問題,但是Raspbian沒有libtbb2和libtbb-dev這兩個套件,於是也必須自己編譯;照理說這是選用性功能,可有可無,但TBB是C/C++平行處理程式庫,有了它,OpenCV的速度會較快。

到TBB網站,查詢原始碼檔案的網址,下載並解壓縮,得到含原始碼檔案的目錄,切換進去:
$ wget
https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb44_20151115oss_src.tgz
$ tar zxvf tbb44_20151115oss_src.tgz
$ cd tbb44_20151115oss

開始建置,根據這篇,應加上參數:
$ make tbb CXXFLAGS="-DTBB_USE_GCC_BUILTINS=1 -D__TBB_64BIT_ATOMICS=0"

然後進入子目錄build,裡頭會有兩個目錄存放建置結果,其一以debug結尾、另一個以release結尾,切換到release那一個:
$ cd build
$ cd linux_armv7_gcc_cc4.9.2_libc2.19_kernel4.1.13_release

執行tbbvars.sh這支腳本程式檔,它會設定許多環境變數,之後的OpenCV才知道TBB在哪:
$ source tbbvars.sh

搞定TBB後,接著是OpenCV,原始碼檔案約580 MB,建置後需要約1.6 GB,請先確認儲存空間是否足夠。

以git下載位於GitHub的OpenCV原始碼,得到目錄opencv,切換進去:
$ git clone https://github.com/Itseez/opencv.git
$ cd opencv

目前處於最新的版本分支,到OpenCV官網查詢後,得知目前釋出的正式版本為3.1.0,所以決定切換到該分支:
$ git checkout 3.1.0

新增目錄build存放建置結果,切換進去:
$ mkdir build
$ cd build

先執行cmake產生建置需要的設定檔:
$ cmake -DWITH_TBB:BOOL=TRUE -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..

其中「-DWITH_TBB:BOOL=TRUE「代表我們想要使用TBB,「-D CMAKE_INSTALL_PREFIX=/usr/local」代表之後要安裝的路徑,最後的「..」代表原始碼所在路徑。

然後開始建置:
$ make -j4

由於Raspberry Pi的CPU速度很慢,根據其他人的經驗,約需要10小時。但我使用Pi 2,可下參數「-j4」充分利用四個核心,我大概花了3小時。

最後終於出現完成的訊息:
...
Linking CXX executable ../../bin/opencv_test_calib3d
[100%] Built target opencv_test_calib3d
Linking CXX shared module ../../lib/python3/cv2.cpython-34m.so
[100%] Built target opencv_python3
Linking CXX shared module ../../lib/cv2.so
[100%] Built target opencv_python2

然後安裝:
$ sudo make install

執行指令更新程式庫:
$ sudo ldconfig

試著檢查OpenCV的版本:
$ pkg-config --modversion opencv
3.1.0

耶!

然後是是撰寫C++程式,顯示一張圖檔。新增檔案test.cpp,準備一張圖檔test.png,程式內容如下:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char **argv)
{
    Mat image = imread("test.jpg", CV_LOAD_IMAGE_COLOR);
    namedWindow("test", WINDOW_AUTOSIZE);
    imshow("test", image);
    waitKey(0);
    return 0;
}

以底下兩道指令之一進行編譯:
$ g++ -lopencv_core -lopencv_highgui -lopencv_imgcodecs tes.cpp
$ g++ `pkg-config --libs opencv` test.cpp

執行:
$ ./a.out

啊哈,成功囉。

試試Python程式,新增檔案test.py,與圖檔test.png放在一起,程式內容如下:
import cv2

img=cv2.imread('test.jpg')
cv2.imshow('test', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

然後執行:
$ python test.py

結果與先前的C++程式相同。

參考資料:

2015/12/12

Raspberry Pi:查詢IP位址

我的Raspberry Pi位於路由器之後,透過DHCP向路由器取得私有IP位址。

以瀏覽器登入路由器,查詢IP位址分配情況。

Raspbian開機後,可在主控台看到類似如下訊息:
My IP address is 192.168.1.15

Raspbian GNU/Linux 8 raspberrypi tty1

raspberrypi login: _

在rpi上執行指令ifconfig,可得知網路介面的狀態:
$ ifconfig
eth0      Link encap:Ethernet  HWaddr b8:27:eb:3c:ce:77
          inet addr:192.168.1.15  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::7814:89c2:cf8d:2018/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:68 errors:0 dropped:0 overruns:0 frame:0
          TX packets:97 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:7667 (7.4 KiB)  TX bytes:15216 (14.8 KiB)

在rpi上執行指令hostname加上參數-I,可直接得到IP位址:
$ hostname -I
192.168.1.15


從同一區域網路裡的其他台Linux電腦,使用指令nmap,查詢同網域內電腦的IP位址。參數-sn代表不掃描連接埠,192.168.1.0/24的24代表子網路遮罩部分有24個位元,因此會掃描256個IP位址,從.0到.255。
$ nmap -sn 192.168.1.0/24

Starting Nmap 6.47 ( http://nmap.org ) at 2015-12-10 14:23 CST
Nmap scan report for www.asusnetwork.net (192.168.1.1)
Host is up (0.0011s latency).
Nmap scan report for yehnanwinxp (192.168.1.2)
Host is up (0.00090s latency).
Nmap scan report for raspberrypi (192.168.1.15)
Host is up (0.00034s latency).
Nmap done: 256 IP addresses (3 hosts up) scanned in 2.57 seconds

若是Windows與Mac OS X,可到nmap.org下載nmap這支工具,也有圖形介面Zenmap。底下在Windows 7上的執行畫面。
從同一區域網路裡的其他台Linux電腦,使用指令fping,一次性ping多台電腦,在rpi開機前後執行此動作,便可得知rpi的IP位址。參數-a代表只秀出活著的電腦,參數-q代表安靜模式,不秀出額外的訊息,以參數-g指定想要ping的IP位址範圍。
$ fping -a -q -g 192.168.1.1 192.168.1.255
192.168.1.1
192.168.1.2
192.168.1.7


Windows版的fping,可到這裡下載。但參數不太一樣,-p代表使用多個執行緒,-g代表IP位址範圍(以斜線/隔開);沒有Linux版的-a參數,但一般來說,因為會比較快收到活著電腦的回應,所以fping指令就會先顯示這些電腦,然後顯示回應很慢或不存在的電腦。

> fping -p -g 192.168.1.1/192.168.1.255
Reply[101] from 192.168.1.101: bytes=32 time=5.4 ms TTL=64
Reply[110] from 192.168.1.110: bytes=32 time=5.2 ms TTL=128
Reply[1] from 192.168.1.1: bytes=32 time=8.2 ms TTL=64
192.168.1.146: request timed out
192.168.1.149: request timed out
192.168.1.179: request timed out
192.168.1.153: request timed out
...

使用Mac OS X的「IP Scanner」,執行畫面如下,也能掃描鄰近電腦的IP位址。
在Windows上使用指令arp,但因為種種原因(快取、有無連線、等等),不一定會完整顯示,其中B8-27-EB是Raspberry Pi的MAC起始位址。:
C:\>arp -a

Interface: 192.168.1.2 --- 0x2
  Internet Address      Physical Address      Type
  192.168.1.1           54-04-a6-5a-e9-78     dynamic
  192.168.1.7           a8-20-66-34-ec-5e     dynamic
  192.168.1.15          b8-27-eb-3c-ce-77     dynamic

在Mac OS X上有專門工具來尋找rpi的IP位址,叫做Pi Finder,尋找以B8:27:EB開頭的MAC位址。
其他:Adafruit的Adafruit-Pi-FinderAngry IP Scanner

2015/12/11

在Raspbian上安裝WordPress

安裝WordPress其實很簡單,照著Raspberry Pi基金會提供的文件,一步一步照做即可。所以這篇只是很簡單地記錄一下而已,分為四個部分:Apache、PHP、MySQL、WordPress。

我的環境是Raspberry Pi 2與Raspbian(2015-11-21)。

先更新套件清單,並升級原有套件:
$ sudo apt-get update; sudo apt-get upgrade -y

Apache的部份:

安裝Apache套件:
$ sudo apt-get install apache2 -y

安裝後,就會成為系統服務,開機後自動執行,以指令service可觀察其狀態:
$ service apache2 status
● apache2.service - LSB: Apache2 web server
   Loaded: loaded (/etc/init.d/apache2)
   Active: active (running) since Thu 2015-12-10 10:28:57 CST; 2min 1s ago
   CGroup: /system.slice/apache2.service
           ├─1785 /usr/sbin/apache2 -k start
           ├─1788 /usr/sbin/apache2 -k start
           └─1789 /usr/sbin/apache2 -k start

開啟瀏覽器,載入Apache所在電腦的IP位址或網址,譬如我的Pi 2的IP位址是192.168.1.15,應可看到如下畫面,該網頁檔位於/var/www/html/index.html,可試著修改。

PHP的部份:

安裝PHP 5與Apache的PHP模組:
$ sudo apt-get install php5 libapache2-mod-php5 -y

然後切換目錄到/var/www/html,刪除index.html,新增檔案index.php,內容如下:
<?php phpinfo(); ?>

開啟瀏覽器,載入Apache所在電腦的IP位址或網址,應可看到如下畫面:
MySQL的部份:

安裝MySQL資料庫伺服器,以及讓PHP能存取MySQL的功能模組:
$ sudo apt-get install mysql-server php5-mysql -y

安裝過程中,將會要求你為MySQL的帳號「root」設定密碼,這個帳號與密碼,之後將會交給WordPress使用:
安裝後,需要為WordPress建立資料庫,請執行指令mysql,指定帳號並輸入密碼:
$ mysql -uroot -p
Enter password: 在此輸入密碼

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 44
Server version: 5.5.44-0+deb8u1 (Raspbian)

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

看到提示符號「mysql>」後,輸入底下指令,建立名為wordpress的資料庫:
mysql> create database wordpress;
Query OK, 1 row affected (0.00 sec)

如此即可,然後按Ctrl + d跳出。

WordPress的部份:

進入放網頁的目錄,修改擁有者與群組,刪除所有東西(或移到別的地方):
$ cd /var/www/html
$ sudo chown pi: .
$ rm *

下載WordPress原始檔,底下以正體中文4.3.1版作示範,我也試過英文的4.4版。
$ sudo wget https://tw.wordpress.org/wordpress-4.3.1-zh_TW.tar.gz

解壓縮,得到目錄wordpress,把裡頭的東西通通搬移到/var/www/html之下,然後就可以刪除目錄wordpress(已經沒東西了)以及原始檔。
$ tar zxvf wordpress-4.3.1-zh_TW.tar.gz
$ mv wordpress/* .
$ rm -rf wordpress wordpress-4.3.1-zh_TW.tar.gz

看看WordPress到底有些什麼東西吧:
$ ls -l
total 176
-rw-r--r--  1 pi pi   418 Sep  3 11:33 index.php
-rw-r--r--  1 pi pi 19930 Sep  3 11:33 license.txt
-rw-r--r--  1 pi pi  7284 Sep 21 19:33 readme.html
-rw-r--r--  1 pi pi  4951 Sep  3 11:33 wp-activate.php
drwxr-xr-x  9 pi pi  4096 Sep 21 19:33 wp-admin
-rw-r--r--  1 pi pi   271 Sep  3 11:33 wp-blog-header.php
-rw-r--r--  1 pi pi  5007 Sep  3 11:33 wp-comments-post.php
-rw-r--r--  1 pi pi  4046 Sep 21 19:33 wp-config-sample.php
drwxr-xr-x  5 pi pi  4096 Sep 21 19:33 wp-content
-rw-r--r--  1 pi pi  3286 Sep  3 11:33 wp-cron.php
drwxr-xr-x 12 pi pi  4096 Sep 21 19:33 wp-includes
-rw-r--r--  1 pi pi  2380 Sep  3 11:33 wp-links-opml.php
-rw-r--r--  1 pi pi  3123 Sep  3 11:33 wp-load.php
-rw-r--r--  1 pi pi 34669 Sep  3 11:33 wp-login.php
-rw-r--r--  1 pi pi  8252 Sep  3 11:33 wp-mail.php
-rw-r--r--  1 pi pi 11062 Sep  3 11:33 wp-settings.php
-rw-r--r--  1 pi pi 25124 Sep  3 11:33 wp-signup.php
-rw-r--r--  1 pi pi  4035 Sep  3 11:33 wp-trackback.php
-rw-r--r--  1 pi pi  3055 Sep  3 11:33 xmlrpc.php

然後以瀏覽器載入,咦,怎麼出現錯誤訊息呢?

「你的PHP似乎缺少WordPress需要的MySQL擴充元件。」
(Your PHP installation appears to be missing the MySQL extension which is required by WordPress.)

代表應該要安裝套件php5-mysql,可是之前已經安裝了啊,原因不明,不過我重開機後就解決了。

以瀏覽器載入,看到如下畫面,按下「衝吧!」,開始進行設定:
然後要輸入資料庫的名稱(wordpress)、帳號(root)、密碼,按下「送出」:
接著出現如下畫面,代表WordPress沒辦法新增檔案wp-config.php。
只好由我們自己手動建立,在/var/www/html下新增檔案wp-config.php,複製內容後貼上。然後按下「開始安裝」。

接著要設定網站的基本資訊,請輸入網站標題(自選)、帳號與密碼(自選)、電子郵件,然後按下「安裝WordPress」。
搞定啦,已新增你剛剛指定的帳號,按下「登入」。
輸入帳號與密碼,按下「登入」。
哇,成功了,看到WordPress控制台的畫面囉。
以及預設的部落格畫面。
看起來很陽春,接下來就靠你花時間進行設定、客製化囉,想辦法讓你的網站美輪美奐吧。

2015/12/09

在Raspbian上安裝nginx、PHP、Django與uWSGI

這篇要在Raspberry Pi 2與Raspbian(2015-11-21)上頭,安裝nginx、PHP、uWSGI、Django,都不算是小軟體,設定都很複雜,執行選項與參數眾多,非三言兩語能道盡,這一篇僅是簡短記錄我的安裝經驗;若有問題,還請查閱官方文件。

輕量型網站伺服器nginx(發音engine x),比起龐大的Apache,更適合用於資源受限的機器,如Raspberry Pi。前端的網站伺服器nginx搞定後,接下來會安裝PHP,以及Django與uWSGI。 底下記錄如何自行下載原始碼並編譯安裝,因為若是打包好的套件,其版本往往過於老舊。

以下分成三個部分:nginx、PHP、Django與uWSGI,後兩個部分各自獨立。

nginx的部份:

首先是nginx編譯時以及使用時需要的套件。
$ sudo apt-get install gcc build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev openssl libssl-dev

其中gcc與build-essential是建置工具,libpcre3與libpcre3-dev是Perl Compatible Regular Expression(PCRE),zlib1g與zlib1g-dev是壓縮工具,openssl與libssl-dev則是SSL/TLS。

下載nginx原始檔並解壓縮。我下載的是1.9.7版(約865 KB),可到nginx官網查看最新版本。
$ wget http://nginx.org/download/nginx-1.9.7.tar.gz
$ tar zxvf nginx-1.9.7.tar.gz

然後進行組態設定,configure有很多參數可設定,此處都使用預設值,因此預設安裝路徑是/usr/local/nginx:
$ cd nginx-1.9.7
$ ./configure

但是最後卻出現底下訊息:
Configuration summary
  + using system PCRE library
  + OpenSSL is not used
  + md5: using system crypto library
  + sha1: using system crypto library
  + using system zlib library

呃,因為預設關閉SSL模組,所以把指令改成:
$ ./configure --with-http_ssl_module

訊息就會變成「+ using system OpenSSL library」。

然後進行編譯建置與安裝:
$ make
$ sudo make install

預設安裝到/usr/local/nginx,若欲修改,請在執行configure時加上參數--prefix,例如「--prefix=/usr/local/nginx-1.9.7」。

然後試著查詢看看吧,可看到版本編號與組態參數。
$ cd /usr/local/nginx
$ ./nginx -V
nginx version: nginx/1.9.7
built by gcc 4.9.2 (Raspbian 4.9.2-10)
built with OpenSSL 1.0.1k 8 Jan 2015
TLS SNI support enabled
configure arguments: --with-http_ssl_module

接著實際執行,若一切正常,nginx執行檔不會有任何輸出。
$ cd /usr/local/nginx
$ sudo ./nginx

然後請開啟瀏覽器,輸入nginx所在機器的IP位址,應可看到如下畫面,代表nginx動起來囉。

該網頁檔位於/usr/local/nginx/html/index.html,你可試著修改看看。

此時若再試著執行一次,將會出現錯誤,因為連接埠80已被佔用。
$ cd /usr/local/nginx
$ sudo ./nginx
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
...
nginx: [emerg] still could not bind()

透過其他參數控制nginx的啟動與停止:
$ cd /usr/local/nginx
$ sudo ./nginx -s stop

stop代表停止(使用TERM訊號),quit也是停止(使用QUIT訊號),reopen是重新開啟記錄檔,reload是重新載入組態檔。

如果stop與quit都無法停止nginx的話,可到/usr/local/nginx/logs/nginx.pid,檔案裡放的是nginx形成的pid(另可以指令ps -ax | grep nginx查詢),然後以指令kill殺掉行程。

因為是自己從原始碼檔安裝,所以沒有init腳本檔,開機時不會自動執行;請另行下載這支init腳本檔,把/opt的部份改成你的安裝路徑(本篇使用預設值/usr/local);檔名取為nginx,放在/etc/init.d/裡,修改擁有者以及執行權限。

然後便能以底下指令(其中一個即可),啟動nginx作為系統服務。
$ sudo /etc/init.d/nginx start

$ sudo service nginx start

其他參數還有stop、restart、status等等。

若想在開機時自動執行,指令如下。
$ sudo update-rc.d -f nginx defaults

然後重開機,看看nginx是否已成為服務在背景執行。

PHP的部份:

安裝PHP之前,先安裝相依套件:
$ sudo apt-get install libxml2-dev libevent-dev

接著要安裝PHP,並使用PHP的FastCGI process manager(PHP-FPM)。首先要下載PHP原始碼檔,並無直接的網址,請到官網找尋下載連結,我下載的是5.6.16版,檔名是php-5.6.16.tar.gz。然後解壓縮,切換目錄:
$ tar zxvf php-5.6.16.tar.gz
$ cd php-5.6.16

然後進行組態設定、建置編譯、測試與安裝:
$ ./configure --enable-fpm
$ make -j4
$ make test
$ sudo make install

執行configure時應加上參數--enable-fpm,啟用PHP-FPM。make指令加上參數-j4,因為Pi 2有四個處理器核心。make test測試通過後,進行安裝動作。

然後複製相關設定檔:
$ sudo cp php.ini-development /usr/local/php/php.ini
$ sudo cp /usr/local/etc/php-fpm.conf.default /usr/local/etc/php-fpm.conf

把PHP-FPM的執行檔複製到正確的目錄:
$ sudo cp sapi/fpm/php-fpm /usr/local/bin

修改PHP設定檔/usr/local/php/php.ini,找到cgi.fix_pathinfo並設為0,可避免安全漏洞。
cgi.fix_pathinfo=0

修改PHP-FPM設定檔/usr/local/etc/php-fpm.conf,設定正確的擁有者與群組:
user = www-data
group = www-data

然後便可執行PHP-FPM,預設應會使用埠號9000:
$ sudo /usr/local/bin/php-fpm
(本篇不讓它成為系統服務、重開機時不會自動執行,有興趣者請自行動手。)

然後要修改nginx的設定檔/usr/local/nginx/conf/nginx.conf,讓它能處理.php的請求,轉交給PHP-FPM,大致上應含有底下兩個區塊。溫馨提醒:修改前應先備份。
location / {
    root html;
    index index.php index.html index.htm;
}

location ~* \.php$ {
    fastcgi_index index.php;
    fastcgi_pass 127.0.0.1:9000;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}

然後重新啟動nginx:
$ sudo service nginx restart

$ /usr/local/nginx/sbin/nginx -s reload

在/usr/local/nginx/html/下建立檔案index.php,放入如下內容:
<?php phpinfo(); ?>

以瀏覽器載入,應可看到如下畫面:
接著要換成Python語言,可先把nginx的設定檔/usr/local/nginx/conf/nginx.conf改回原狀。

Django與uWSGI的部份:

WSGI(Web Server Gateway Interface)由PEP 333與PEP 3333制定標準,乃是Python網頁應用程式(譬如Django專案)與外界(網站伺服器)溝通的介面。很久以前,Python網頁應用程式開發框架,都只能連接特定的介面與API,譬如CGI、FastCGI、mod_python等,甚至只能與某種網站伺服器溝通,若兩端能夠遵從WSGI規格,開發人員便可自由地選用想要的網站伺服器(如nginx、Apache)與Python網頁應用程式開發框架(如Django、Flask)。

安裝開發Python程式的相關套件:
$ sudo apt-get install python python-dev python-pip

python應是Python 2.x版,python-dev包含建置Python模組所需的標頭檔、靜態程式庫與開發工具,python-pip是Python的套件管理工具。

我本來想先試試FastCGI,於是安裝了python-flup,包含三套WSGI伺服器(閘道器)實作,分別是FastCGI、AJP(Apache JServ Protocol 1.3)、SCGI(Simple CGI)。照理說應可使用Django的指令runfcgi(它會使用flup),便可啟動測試用的伺服器,可惜沒成功。Django自1.7版開始揚棄FastCGI,於1.9版移除。

接著使用指令pip來安裝Django,我安裝的是1.9.0版:
$ sudo pip install Django==1.9.0
Collecting Django==1.9.0
  Downloading Django-1.9-py2.py3-none-any.whl (6.6MB) 
    100% |████████████████████████████████| 6.6MB 7.0kB/s
Installing collected packages: Django   
Successfully installed Django-1.9

建立Django專案,取名為mysite:
$ django-admin startproject mysite

切換目錄,並且執行測試用伺服器,請把192.168.1.15換成你的IP位址。
$ cd mysite
$ python manage.py runserver 192.168.1.15:8000
Performing system checks...

System check identified no issues (0 silenced).

You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.

December 08, 2015 - 14:14:34
Django version 1.9, using settings 'mysite.settings'
Starting development server at http://192.168.1.15:8000/
Quit the server with CONTROL-C.

啟動瀏覽器,輸入網址並加上埠號,例如「192.168.1.15:8000」,應會看到如下畫面。
同時runserver那端應會輸出類似底下的訊息:
[08/Dec/2015 14:16:22] "GET / HTTP/1.1" 200 1767

哇,以上已經成功建立Django專案,並且執行測試用伺服器,從瀏覽器(客戶端)存取。

接下來要安裝uWSGI伺服器:
$ sudo pip install uWSGI

先撰寫符合WSGI規範的簡單Python程式,取名為uWSGI_test.py:
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return ["Hello World"] # python2
    #return [b"Hello World"] # python3
   
然後直接讓uWSGI伺服器同時擔任網站伺服器的角色,並執行uWSGI_test.py:
$ uwsgi --http :8000 --wsgi-file uWSGI_test.py

開啟瀏覽器,載入網址,譬如「192.168.1.15:8000」,應可看到「Hello World」字樣,代表成功了。

測試過簡單的程式之後,該讓先前建立的Django專案登場了吧:
$ cd mysite
$ uwsgi --http :8000 --module mysite.wsgi

同樣以瀏覽器載入網址,應也會看到先前成功執行Django專案、寫著「It worked!」的畫面。

以上的作法是瀏覽器經由HTTP協定與uWSGI伺服器溝通,它把請求轉成符合WSGI協定的形式,交由uWSGI_test.py或Django專案處理並回應。

接下來要把nginx放進去,由uWSGI擔任nginx與Django之間的中介角色。nginx早已加入uWSGI模組提供支援,nginx透過uWSGI伺服器原生支援的uwsgi協定與之溝通(效率最高),然後uWSGI伺服器透過轉接功能轉成WSGI形式,交給Django處理。

修改nginx設定檔/usr/local/nginx/conf/nginx.conf,把底下內容放在http區塊之內:
    upstream django {
        server 127.0.0.1:8001;
    }

    server {
        listen 8000;
        server_name localhost;
        charset utf-8;
        location / {
            uwsgi_pass django;
            include uwsgi_params;
        }
    }

其中將透過埠號8001與uWSGI伺服器(以及它之後的WSGI程式,如Django專案)溝通,另開啟埠號8000供外界存取。

然後重新啟動nginx、載入新設定值:
$ sudo service nginx restart

接著先試試小小的測試程式:
$ uwsgi --socket :8001 --wsgi-file uWSGI_test.py

再試試Django專案:
$ cd mysite
$ uwsgi --socket :8001 --module mysite.wsgi

以瀏覽器載入網址,如「192.168.1.15:8000」,確認可看到如同先前的畫面,「Hello World」與「It worked!」,耶。

也可讓瀏覽器載入網址「192.168.1.15:8001」,直接存取uWSGI伺服器,但應會失敗,因為此時它不是說HTTP協定,瀏覽器應出現錯誤畫面,而uWSGI端大概會出現類似的錯誤訊息「invalid request block size: 21573 (max 4096)...skip」。

上述作法使用TCP socket,但也可改用Unix socket,照理說負擔較低。請修改nginx設定檔/usr/local/nginx/conf/nginx.conf:

    upstream django {
        # server 127.0.0.1:8001;
        server unix:///home/pi/mysite/mysite.sock;
    }

存檔後重新啟動nginx:
$ sudo service nginx restart

接著是uWSGI的部份,指令應改為:
$ uwsgi --socket mysite.sock --module mysite.wsgi

$ uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=666

因為必須給予適當權限,才能讓nginx使用該socket。若成功的話,以瀏覽器載入,應會出現「It worked!」的畫面。

架構如下:
瀏覽器 - 網站伺服器(nginx) - socket(uwsgi協定) - uWSGI伺服器 - Python程式(Django專案)

uWSGI還能讀取.ini設定檔、以emperor模式執行,也應該成為系統服務,在開機時自動啟動(或可參考此處的init腳本檔)。

參考資料:

2015/12/07

Raspberry Pi:新版Raspbian更新之處(2015-11-21)

簡單記錄一下2015-11-21新版Raspbian的變化,內容來自官方部落格與實際操作經驗。

加入支援Pi Zero

Raspberry Pi組態設定,開機時可選擇要不要等待網路連線,因為有些程式需要有網路才能正常啟動,但這麼做會減慢開機速度,使用者應視情況而定。

可透過設定工具raspi-config來設定。

也可透過X視窗系統,到主選單-Preferences-Raspberry Pi Configuration進行設定。
新的圖形化套件管理工具,位於主選單Preferences-Add/Remove Software,修改自Gnome Packages。套件名pi-package。
Node-RED,IBM的物聯網開發方案,視覺編輯器。位於主選單-Programming-Node-RED,啟動後,開啟瀏覽器,輸入網址http://localhost:1880即可。套件名nodered。
Scratch,諸多更新,包括MIDI樂器、PiFace支援、等等。

Epiphany瀏覽器,改善YouTube與Vimeo影片播放能力。

GPIO Zero程式庫,套件名python-gpiozero與python3-gpiozero。

另外還有縮減版的Raspbian Lite,拿掉許多東西,更為精簡,太棒啦。沒有X Window與LibreOffice、沒有OpenSSL、等等,但可自行安裝。

2015-11-21-raspbian-jessie.zip,1.43 GB,解壓縮後3.93 GB。
2015-11-21-raspbian-jessie-lite.zip,393 MB。解壓縮後1.46 GB。

2015/12/02

Raspberry Pi Zero,$5

Raspberry Pi基金會官網發佈消息,推出價格僅$5的Raspberry Pi板子,取名為Zero。

主晶片跟Pi 1一樣,都是BCM2835,但ARM11核心頻率提升到1 GHz,GPU是VideoCore IV;記憶體512 MB LPDDR2 SDRAM。

下圖左方是Micro SD卡槽,左下方是mini-HDMI插槽,可輸出1080p60視訊,右下方是micro-USB埠,一個(右)接電源,一個(左)可傳資料。上方有40-pin GPIO腳位,其位置規格跟其他rpi板子(A+、B+、Pi 2)相同。電源只需要5V、160mA(即便連接高畫質螢幕也是如此)。

背面圖,所有零件都在正面,而且都是SMD元件,藉以降低製造費用。
尺寸超小,65mm x 30mm x 5mm。以前是信用卡大小,現在變成口香糖大小囉。下圖拿來跟Model B+比一比吧,一目了然。另外,若跟A+相比,大概是一半。
(以上照片取自Gareth Halfacree的相簿,可前往瀏覽其他特寫高解析度照片。)

另看看element14製作的示意圖吧,在右上方的腳位,可加裝Reset開關(標示為RUN),以及RCA複合視訊AV端子(標示為TV)。
因為主晶片與Pi 2相同,所以同樣可使用Raspbian,以及眾多既有的軟體,如Scratch、Minecraft與Sonic Pi,這點很不錯,保持相容性。當然也可運行其他作業系統,譬如RaspBMC、Arch Linux、Risc OS、OpenELEC、Pidora等等。

Zero沒有或拿掉的東西:CSI埠(相機)、DSI埠(螢幕)、類比音訊輸出埠(耳機孔)、以太網路插槽、AV端子(RCA)輸出埠、等。

價格這麼低,根據MagPi訪談(The making of Raspberry Pi Zero ),這是先前Eben Upton與Eric Schmidt交談後的決定,不應發展更昂貴、規格更高的板子,而是朝著更低價、更普及的方向,已經降到$5,短期內很難再下壓了。購買處:The Pi HutPimoroniAdafruitMicro Centerelement14Swag Store、其他。

還有推銷活動,購買MagPi第40期,就贈送Zero一片,哇!雜誌內容不僅介紹Zero,還有各種專案想法,並且訪談Zero板子設計者Mike Stimson。
官方也推出mini-HDMI與micro-USB轉接頭,以及GPIO的排針,可到官方Swag Store購買。
也已經有廠商為Zero製造外殼:AdafruitPimoroniC4Labs.buildModMyPi。或者自己3D列印外殼
在24小時之內,Zero已經賣光啦,不過我想沒關係,想必基金會與銷售商早已預料,應會儘快生產下一批。


媒體報導:
一般介紹: