顯示具有 Raspberry PI 標籤的文章。 顯示所有文章
顯示具有 Raspberry PI 標籤的文章。 顯示所有文章

2016年10月9日 星期日

「Raspberry PI」啟用Webcam拍照

Raspberry 如果要啟用webcam拍照,除了用OpenCV之外,

還有一個簡單方法,安裝fswebcam這個套件。


 sudo apt-get install fswebcam  

安裝過程大致上長這樣

 pi@boywhy-pi2:~ $ sudo apt-get install fswebcam  
 Reading package lists... Done  
 Building dependency tree      
 Reading state information... Done  
 The following packages were automatically installed and are no longer required:  
  pypy-upstream-doc wiringpi  
 Use 'apt-get autoremove' to remove them.  
 The following NEW packages will be installed:  
  fswebcam  
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.  
 Need to get 44.0 kB of archives.  
 After this operation, 105 kB of additional disk space will be used.  
 Get:1 http://mirrordirector.raspbian.org/raspbian/ jessie/main fswebcam armhf 20140113-1 [44.0 kB]  
 Fetched 44.0 kB in 1s (35.9 kB/s)    
 Selecting previously unselected package fswebcam.  
 (Reading database ... 126790 files and directories currently installed.)  
 Preparing to unpack .../fswebcam_20140113-1_armhf.deb ...  
 Unpacking fswebcam (20140113-1) ...  
 Processing triggers for man-db (2.7.0.2-5) ...  
 Setting up fswebcam (20140113-1) ...  
 pi@boywhy-pi2:~ $   

拍一張,存成test.jpg (採用預設的解析度,大概是320*240 左右)

 fswebcam test.jpg  


指定拍照解析度(如果Webcam不支援的話,fswebcam會自動調整成最接近的解析度)

 fswebcam -r 1280x720 image2.jpg  

訊息大致上長這個樣子,注意 Adjusting resolution from 1024x720 to 640x480. 代表相機不支援1024x720,被強制改成640x480了
 pi@boywhy-pi2:~ $ fswebcam -p YUYV -r 1024x720 test.jpg  
 --- Opening /dev/video0...  
 Trying source module v4l2...  
 /dev/video0 opened.  
 No input was specified, using the first.  
 Adjusting resolution from 1024x720 to 640x480.  
 --- Capturing frame...  
 Captured frame in 0.00 seconds.  
 --- Processing captured image...  
 Writing JPEG image to 'test.jpg'.  
 pi@boywhy-pi2:~ $   


以上拍照後,相片上都會有個banner寫著拍照時間等等,如果不要的話,可以加上

--no-banner這個參數,相片就不會有多餘的資訊被打上去。

 fswebcam -r 1280x720 --no-banner image3.jpg  



如果拍照出來是黑黑的一片,注意一下是否有發生如下的訊息



GD Error: gd-jpeg: JPEG library reports unrecoverable error: Not a JPEG file: 

俺試了2支Webcam,羅技C310 是OK的,但是C 170 就會出現這個錯誤訊息。

俺查詢了相關資料後,做了一個嘗試,改變 palette format 為YUYV後正常,

推測應該是Webcam硬體支援上的問題。

 pi@boywhy-pi2:~ $ fswebcam -p YUYV test.jpg  
 --- Opening /dev/video0...  
 Trying source module v4l2...  
 /dev/video0 opened.  
 No input was specified, using the first.  
 Adjusting resolution from 384x288 to 352x288.  
 --- Capturing frame...  
 Captured frame in 0.00 seconds.  
 --- Processing captured image...  
 Writing JPEG image to 'test.jpg'.  
 pi@boywhy-pi2:~ $   

正常取得照片





















參考資料:

USING A STANDARD USB WEBCAM

fswebcam - gd-jpeg: JPEG library reports unrecoverable error

2015年8月2日 星期日

「Raspberry Pi」實作ibeacon發射器

看到網上用Pi做iBeacon發設器的應用,俺也想來試試。

iBeacon介紹



Beacon這項技術常見的應用就是室內定位。目前常見室內定位技術大致分為Wifi、

Zigbee及BLE三種,這三種技術大致上的共同點都是使用無線傳輸中RSSI

( Received Signal Strength Indication,接收信號強度指示 )的

dB值強弱來判斷距離。

Beacon與iBeacon的差別於廣播訊號頻率。

iBeacon 其實是基於BLE的訊號廣播設備,在架構中通常會有一個 iBeacon 發射器,

發射器有一個唯一的ID號碼其主要的內容包括內容 UUID(16 byte)、Major (2 byte)、

Minor (2 byte)及 Tx Power等資訊。通常發射器只有單向發射訊號的功能,

除非客製化成Dual-Mode iBeacon的服務否則沒有接收功能。

iBeacon定位


在室內定位技術部分,iBeacon的信號強度採用RSSI值表示。隨著距離的遠近,

RSSI值會產生變化透過校準發射功率 (txPower)就可以算出與發射器的距離。

當iBeacon接收器(手機或硬體裝置)接收到這組資料,就可以判斷所在位置。
由於訊號會因為一些物理或空間上的影響而改變,Apple定義了四種範值:
Immediate 很近,小於1公尺。
Near 附近,約1-3公尺。
Far 較遠。(或離開範圍)
Unknown 未知,一般出現在啟動階段,或者因為某些原因無法判斷。
至於定位方案則可以透過單點定位、兩點定位及多點定位方式以 

iBeacon 發射器的數量多寡來完成定位的精準。


iBeacon發射器環境建立

軟硬體環境:


Raspberry Pi 2
D-Link DWA-121 USB無線網卡

嘻哈佈落科技 CSR V4.0藍牙傳輸器

RASPBIAN Debian Wheezy 2015-05-05

安裝所需要的套件


sudo apt-get -y install libglib2.0-dev libudev-dev libical-dev libreadline-dev libdbus-1-dev

下載最新版bluez (BlueZ官網找找)

wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.33.tar.xz

解壓縮bluez( 注意它是.xz壓縮喔)


tar xvf bluez-5.33.tar.xz


Compiler bluez


cd bluez-5.33/

./configure --disable-systemd

make -j4  (pi 2 有4個核心)

sudo make install

檢查是否有捉到usb 藍芽卡

lsusb












看到 Cambridge Silicon Radio, Ltd Bluetooth Dongle(HCI mode) ,有捉到

藍芽USB卡,沒問題。

檢查藍芽是否被啟動

hciconfig












我的藍芽名稱是 hci0 ,目前是DOWN的狀態


啟動藍芽並關閉掃描功能

sudo hciconfig hci0 up
sudo hciconfig hci0 noscan






啟動BLE的廣播功能

sudo hciconfig hci0 leadv


測試發送 iBeacon 的資料封包

sudo hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0 00 00 00 00 C8 00


內容如下

0x08 BLE Controller Commands,

0x008 表示Advertising Data (length)廣播資料

1E Number of bytes that follow in the advertisement
02 Number of bytes that follow in first AD structure
01 Flags AD type
1A Flags value 0x1A = 000011010  
   bit 0 (OFF) LE Limited Discoverable Mode
   bit 1 (ON) LE General Discoverable Mode
   bit 2 (OFF) BR/EDR Not Supported
   bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
   bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
1A Number of bytes that follow in second (and last) AD structure
FF Manufacturer specific data AD type
4C Company identifier code LSB
00 Company identifier code MSB (0x004C == Apple)
02 Byte 0 of iBeacon advertisement indicator
15 Byte 1 of iBeacon advertisement indicator
接下去則是UUID(16 byte)、Major (2 byte)、 Minor (2 byte)及 Tx Power等參數

UUID 服務識別碼: 這裡用來區別不同公司不同的系統。
Apple在它們自家的iBeacon服務中定義了 Apple AirLocate 其UUID開頭為 

E2C56DB5 、5A4BCFCE 及 74278BDA。

上述的UUID就是採用 E2C56DB5 開頭的一組 Apple AirLocate UUID : 

E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0

Major ID: 在同樣 UUID 的一群 iBeacon 發射器中為了區隔不同分類

定義以此Major Number (2 byte),例如喜宴會場 A 就定義為0001、會場B就定義0002

Minor ID: 細分類,例如喜宴會場A的男方親友區為0001 ,女方親友區為0002

TX power:則是用來判斷使用者與beacon之間的距離遠近。















接下來可以拿支援BLE的裝置出來安裝 Locate Beacon 這個APP 

Anrdoid



AppStroe 








































房間的斜對角













































還算準確(房間小~_~)。

接下來我走到房間外面去看看距離的變化














































只是轉個角出門口,PI 放在門口旁邊的桌子上,距離就開始拉長了。

參考資料:

http://www.cheng-min-i-taiwan.blogspot.tw/2015/03/raspberry-pi-40ibeacon.html

http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing

ios ibeacon 接收軟體
https://github.com/relevante/ibeacon-tutorial


Android ibeancon接收軟體
https://github.com/Vinayrraj/Android-iBeacon-Demo


http://stackoverflow.com/questions/23483086/using-hcitool-to-set-ad-packets

http://stackoverflow.com/questions/22144098/understanding-ibeacon-data-the-power-field-and-other-bytes/22148306#22148306

[Raspberry pi] Enable BLE


我所使用的藍芽是這一支 dongle-sbd-40,參考網上資料,

它支援雙模(Bluetooth 4.0  && BLE)

依照以下步驟安裝

sudo apt-get install libdbus-1-dev libdbus-glib-1-dev libglib2.0-dev libical-dev libreadline-dev libudev-dev libusb-dev make
















mkdir -p work/bluepy
cd work/bluepy
wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.31.tar.xz
tar xvf bluez-5.31.tar.xz
cd bluez-5.31
./configure --disable-systemd
以下這一個指令執行會需要一段時間
make
sudo make install



到這裡程式己安裝完成,接下來是使用的部份


lsusb












找出藍芽的ID,我的是在0a12

查詢一下裝置的詳細訊息

sudo lsusb -v -d 0a12:


























開始使用藍芽囉


hciconfig

下完指令後,如果有如下圖的輸出,代表藍芽己正常運作。















看到上圖中第4行,如果顯示DOWN目前藍芽是被關閉的,執行以下指令打開

sudo hciconfig hci0 up

hci0 則為第2行開頭,請依實際情況修改,再執行一次

hciconfig

















狀態己經變成 UP  RUNNING


sudo hcitool lescan

掃描BLE裝置






參考資料:

https://www.raspberrypi.org/learning/robo-butler/bluetooth-setup/

http://www.elinux.org/RPi_Bluetooth_LE

2015年7月12日 星期日

「Raspberry Pi」螢幕輸出與 VNC 畫面不同。


wiki上這麼說


X Window系统X Window System,也常稱為X11X)是一種以位圖方式顯示的軟體視窗系統。最初是1984年麻省理工學院的研究,之後變成UNIX類UNIX、以及OpenVMS作業系統所一致適用的標準化軟體工具套件及顯示架構的運作協定。X Window系统透過軟體工具及架構協定來建立作業系統所用的圖形化使用者介面,此後則逐漸擴展適用到各形各色的其他作業系統上。現在幾乎所有的作業系統都能支援與使用X。更重要的是,今日知名的桌面環境——GNOMEKDE也都是以X Window系统為基礎建構成的。









它其實是新建立了一個X  desktop,所以會和你的HDMI輸出的

X desktop畫面並不相同。



2015年7月2日 星期四

[Raspberry pi ]安裝MJepg Stream

環境:


RASPBIAN Wheezy

Release date: 2015-05-05

Raspberry pi 2

羅技 c170


首先安裝相關的套件

sudo apt-get update

sudo apt-get install subversion

sudo apt-get install libjpeg8-dev

sudo apt-get install imagemagick

Download  MJepg-Streamer Source Code

sudo svn co https://svn.code.sf.net/p/mjpg-streamer/code /etc/mjpg-streamer


cd /etc/mjpg-streamer/mjpg-streamer

sudo make


sudo ./mjpg_streamer -i "./input_uvc.so -d /dev/video0 -y -r 640x480 -f 15 " -o "./output_http.so -p 8090 -w ./www"


-y 表示使用YUV格式。

-r 設定解析度

-f 設定FPS

-p 連接埠

-w 設定 www-folder-path.

執行後輸出訊息如下圖,表示正常執行

























此時打上Raspberry pi 的 ip 再配上:8090

http://192.168.0.102:8090  會出現如下的網頁


點左邊的Stream,即可看到自己的視訊畫面


 亦可由支援的手機APP來觀看,例如MJpeg Viewer,安裝後輸入網址



按下Show顯示畫面














































參考來源:

http://gsyan888.blogspot.tw/2013/04/raspberry-pi-webcam-mjpg-streamer.html





2015年6月28日 星期日

[Raspberry pi] 升級firmware

建議可以嘗試 sudo rpi-update 更新firmware來試著解決。

按下Y繼續做更新























共46.7MB稍候一下。
























等待更新完成,中途可能會瞬間沒有反應大約20秒,是正常的,稍候一下,不要急著拔電。

2015年6月25日 星期四

[Raspberry PI ] RASPBIAN Debian Wheezy-2015-05-05 在8G 16G SD卡有問題

安裝完系統重開後,都會出現錯誤,本以為是SD卡故障,買了二塊新的16G SD卡,分別在

B+  以及 Pi 2 做測試,皆發生一樣的情況。


































參考資料:

https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=85210&p=602257#p602257

2015年6月20日 星期六

[Mac] 燒錄Raspberry pi 的OS到SD卡

1.把SD卡插入讀卡機。


2.輸入以下指令查看磁碟資料


diskutil list

由容量我很明顯可以發現16G的記憶卡在/dev/disk1













3.缷載SD卡


diskutil unmountDisk /dev/disk1






4.把下載來的OS檔案解壓縮(檔名視情況修改)


unzip 2015-05-05-raspbian-wheezy.zip 

解壓縮會需要一點時間,大約幾分鐘。








5.燒錄
sudo dd bs=1m if=2015-05-05-raspbian-wheezy.img of=/dev/disk1



這個部份會耗上一些時間,小弟的SD HC Class 10 花了43分鐘,官網寫bs =1m  ,

但有看到其他教學是寫bs=2m ,小弟也試了一下,似乎,沒有比較快丫....


if 是輸入的img檔案(視自己下載的檔案而定)

of 是要寫到那一個磁碟 (參考第2點) 




參考來源:


2015年6月17日 星期三

[Raspberry pi]安裝vnc server


sudo apt-get update













sudo apt-get install tightvncserver















vncserver


第一次啟動會要求輸入連線時驗證用的密碼











以及是否要建立view only (只能看不能操作)的密碼



接著VNC Server就啟動囉

2015年6月8日 星期一

[Raspberry Pi] 安裝spice client

實作環境:

Hardware:

Raspberry Pi 2

OS:

RASPBIAN

Debian Wheezy
Release date:2015-05-05

Kernel version:3.18


流程:

1.下載原始碼(請先到官網看最新版本,2015.06.07時是0.28)

wget http://www.spice-space.org/download/gtk/spice-gtk-0.28.tar.bz2

2.安裝相依性套件

sudo apt-get install libogg-dev build-essential autoconf libtool intltool libspice-protocol-dev libgtk2.0-dev libssl-dev libpulse-dev gobject-introspection libgirepository1.0-dev libjpeg8-dev pulseaudio

3.編譯

  3.1  解壓縮
  tar xf spice-gtk-0.28.tar.bz2

  3.2 編譯
 cd spice-gtk-0.28≈

./configure --prefix=/usr --disable-maintainer-mode --disable-static --enable-introspection --without-python --without-sasl --disable-polkit --disable-vala --enable-smartcard=no --with-gtk=2.0

make

4.安裝
sudo make install
5.啟動
spicy
實作後確實可以連線成功,但還有許多可以調整的地方,例如改用gtk 3 

安裝方式如下

sudo apt-get install libgtk-3-dev
之後要修改./configure的參數如下



./configure --prefix=/usr --disable-maintainer-mode --disable-static --enable-introspection --without-python --without-sasl --disable-polkit --disable-vala --enable-smartcard=no --with-gtk=3.0


再重新make  -> make install

參考來源:

2015年1月21日 星期三

[Raspberry Pi] DIY 一個Raspberry Pi 上的webcam 影像分享

我自己弄了一個可以透過區網傳輸Raspberry Pi 的webcam影像觀看程式,不計較效能

以及流量問題 ,我只希望能夠用網頁觀看,在多個不同的裝置(PC ,平板,手機)。當然

也會有些許的延遲(幾秒鐘),接下來也會繼續嘗試用其他的方式,讓影像不要Delay那麼嚴

重,在此先做個筆記。


一、環境說明

(一)Raspberry Pi  B+

           os 為 wheezy ,使用python 2.7 搭配OpenCV 2.4.10 。

          網卡 Edimax EW-7811Un 

(二)WebCam 為Logitech C170

  (三)WebSocket Server 由 GlassFish 4.1 +  Java 實作。

  (四)觀看端由 Html + JavaScript 實作。


二、整體架構圖




三、架構說明:

(一) 輸入端由OpenCV開啟Webcam取得影像 ,以Jpeg作為壓縮格式後,轉成

       Base64字串,由WebSocket client端發送(為了節省頻寬,目前品質壓到30%)。

(二) websocket 由python 的websocket-client package ,安裝方式,請參考      

[Python] 用Python 做 WebSocket Client


(三)WebSocket Server在onMessage (收到圖片時)會傳給所有連線中的Client,
 除了發送圖片的Raspberry Pi


(四) 觀看端在網頁載入完成後,會連線到WebSocket Server,等待接收訊息。當觀看端的onMessage事件發生時,會解碼收到的圖片訊息,並且顯示在網頁上,並更新時間。


四、程式碼

(一) Raspberry Pi 上的發送圖片程式 Webcam.py

import sys
import cv
import cv2
import numpy
import base64
from websocket import create_connection
#connection to websocket server
ws = create_connection('ws://192.168.0.101:8080/DemoEchoServer/echo')
#JPEG encode_param
encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),30]
#select first VideoCapture 
capture = cv2.VideoCapture(0)
#set WebCame Frame Width
capture.set(3,640)
#set WebCam Frame Height
capture.set(4,480)
#defind function
def repeat():
    # Capture frame-by-frame
    ret, frame = capture.read()
    #encode to jpg
    if (type(ret)!=type(None)):
        result,imgencode=cv2.imencode('.jpg',frame,encode_param )
    # to numpy array
        data = numpy.array(imgencode)
    # tostring
        stringData = data.tostring()
    #encode to base64
        encoded = base64.b64encode(stringData)
    #send
        ws.send(encoded)
    #sleep 60millisecond
        cv2.waitKey(60)
while True:
    repeat()


(二)WebSocket Server EchoServer.java
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/echo")
public class EchoServer {
  
  //用來存放Session的集合
  private static final Set sessions = Collections
                     .synchronizedSet(new HashSet());  
 
    @OnOpen
    public void onOpen(Session session,EndpointConfig config) {        
        session.setMaxBinaryMessageBufferSize(1024*1024);
        session.setMaxTextMessageBufferSize(1024*1024);
        System.out.println(session.getId()+" open");
       //把session加入集合中  
       sessions.add(session);
    }   

    @OnClose
    public void onClose(Session session) {
        System.out.println(session.getId()+" close");
        //把session從集合中移除
         sessions.remove(session);
    }

    @OnMessage    
   public void onMessage(String message , Session session) throws IOException {       
      
       try
       {
         //sent Image 
        for(Session session2 : sessions)
       {
           if (!session2.getId().equals(session.getId()))
           {
            session2.getAsyncRemote().sendText(message);
           }
            //session2.getBasicRemote().sendText(message);
          
        }
       catch (Exception e)
        {
           e.printStackTrace();;
        }      
    }
   
    @OnError
    public void onError(Throwable t) {
        t.printStackTrace();
    }
}

(三)觀看端 display.html
1:  <html>  
2:    <head>  
3:      <title>TODO supply a title</title>  
4:      <meta charset="UTF-8">  
5:      <meta name="viewport" content="width=device-width, initial-scale=1.0">  
6:       <script language="javascript" type="text/javascript">   
7:      //echo server的網址   
8:      var wsUri = "ws://192.168.0.101:8080/DemoEchoServer/echo";   
9:      //定義元件   
10:      var outputElement;   
11:      //初始化function    
12:      function init()   
13:      {   
14:       outputElement = document.getElementById("output");   
15:       live();   
16:      }   
17:      //執行websocket
18:      function live() {   
19:       //連線到echo server   
20:       websocket = new WebSocket(wsUri);   
21:       //連線成功要執行的function   
22:       websocket.onopen = function (evt) {   
23:        onOpen(evt)   
24:       };   
25:       //連結結速要執行的function   
26:       websocket.onclose = function (evt) {   
27:        onClose(evt)   
28:       };   
29:       //收到echo server傳來的訊息要做的function   
30:       websocket.onmessage = function (evt) {   
31:        onMessage(evt)   
32:       };   
33:       //當發生錯誤時要執行的function   
34:       websocket.onerror = function (evt) {   
35:        onError(evt)   
36:       };   
37:      }   
38:      //連線成功後,在output Element顯示時間  
39:      function onOpen(evt) {   
40:        var currentdate = new Date();   
41:        var datetime = "Last Sync: " + currentdate.getDate() + "/"  
42:          + (currentdate.getMonth()+1) + "/"   
43:          + currentdate.getFullYear() + " @ "   
44:          + currentdate.getHours() + ":"   
45:          + currentdate.getMinutes() + ":"   
46:          + currentdate.getSeconds();  
47:       writeToScreen(datetime+" onOpen")  
48:      }   
49:      //當中斷連線時輸出訊息在outputElement上      
50:      function onClose(evt) {   
51:        var currentdate = new Date();   
52:        var datetime = "Last Sync: " + currentdate.getDate() + "/"  
53:          + (currentdate.getMonth()+1) + "/"   
54:          + currentdate.getFullYear() + " @ "   
55:          + currentdate.getHours() + ":"   
56:          + currentdate.getMinutes() + ":"   
57:          + currentdate.getSeconds();  
58:       writeToScreen(datetime+" onClose")  
59:      }   
60:      //收到訊息時顯示在螢幕上, 並且解密base64圖片資料   
61:      function onMessage(evt) {   
62:        var currentdate = new Date();   
63:        var datetime = "Last Sync: " + currentdate.getDate() + "/"  
64:          + (currentdate.getMonth()+1) + "/"   
65:          + currentdate.getFullYear() + " @ "   
66:          + currentdate.getHours() + ":"   
67:          + currentdate.getMinutes() + ":"   
68:          + currentdate.getSeconds()+" "  
69:          + currentdate.getTime();  
70:       writeToScreen(datetime+" onMessage")  
71:      document.getElementById("ItemPreview").src = "data:image/png;base64," + evt.data;   
72:      }   
73:      //發生錯誤時顯示訊息在outputElement上   
74:      function onError(evt) {     
75:         var currentdate = new Date();   
76:        var datetime = "Last Sync: " + currentdate.getDate() + "/"  
77:          + (currentdate.getMonth()+1) + "/"   
78:          + currentdate.getFullYear() + " @ "   
79:          + currentdate.getHours() + ":"   
80:          + currentdate.getMinutes() + ":"   
81:          + currentdate.getSeconds();  
82:       writeToScreen(datetime+" onError")  
83:      }   
84:      //發送訊息   
85:      function doSend(message) {   
86:       writeToScreen("己傳送 " + message);   
87:       websocket.send(message);   
88:      }   
89:      //輸出訊息在outputElement上   
90:      function writeToScreen(message) {   
91:       var pre = document.getElementById("myp");   
92:       pre.style.wordWrap = "break-word";   
93:       pre.innerHTML = message;   
94:       output.appendChild(pre);   
95:      }   
96:      //加入事件,當載入完成後執行init()   
97:      window.addEventListener("load", init, false);   
98:     </script>   
99:    </head>   
100:    <body>  
101:      <div id="output"> <p id="myp"></div>  
102:      <div>  
103:        <img id="ItemPreview" src="" />  
104:      </div>  
105:    </body>  
106:  </html>  

五、執行程式
 (一)先開啟WebSocket Server。
 (二)在Raspberry Pi上輸入 python Webcam.py
 (三)開啟display.html觀看。

 六、執行結果



七、待解決問題

 (一) 畫面延遲問題, 以目前看來至少會慢個約5秒,慢的主要原因是資料量,每一次
  都發送一張完整的圖片 (640 *480)  ,樹梅派只有單核心, 要一直取影像再壓成JPEG傳送,
可能會有點吃力。

(二) 透過websocket Server 再做一次分派,好處是可以讓多個裝置同時間做觀看。雖然每一個之間還是會有Delay。把傳送影像用的session2.getBasicRemote().sendText(message); 改成用session2.getAsyncRemote().sendText(message); 效能看起來些許的提昇。