code

2017年1月18日 星期三

Nodejs取得銀行匯率


要取得銀行匯率,需要對網頁原始碼做一些轉換,這裡使用cheerio,因此一開始要先安裝這個套件:
npm install cheerio

匯率方面,採用玉山銀行的匯率網頁。為什麼選擇玉山?因為它的網頁原始碼比較容易抓匯率。

首先取得匯率網頁的全部原始碼:
var request = require("request");
// 玉山銀行匯率
var url = "https://www.esunbank.com.tw/bank/personal/deposit/rate/forex/foreign-exchange-rates";
// 取得網頁資料
request(url, function (error, response, body) {
    if (!error) {        
        console.log(body);  // body是網頁原始碼 
    } else {
        console.log("擷取錯誤:" + error);
    }
});

玉山銀行的匯率表格叫做inteTable


其中貨幣資料在inteTable下的<tr class="tableContent-light">

現在用cheerio抓出各貨幣的資料:
// 用 cheerio 解析 html 資料
var $ = cheerio.load(body);
// 搜尋各種貨幣的匯率
var queryResult = []
$('.inteTable tr.tableContent-light').each(function(i, elem){
    queryResult.push($(this).text().split('\n')); // 把搜尋結果存到array
});
其中".inteTable tr.tableContent-light"的意思是「抓取class名字為inteTable下的tr標籤,這個tr標籤class名字是tableContent-light」
如果這時候把queryResult輸出結果如下:

[ [ '\r',
    '                \r',
    '                    美元(USD)\r',
    '                31.54\r',
    '                31.64\r',
    '\r',
    '                31.34\r',
    '                31.79\r',
    '            ' ],
...(下略)
可以看到輸出很雜亂,有很多不必要的空格,所以要再整理一下。這邊就不單獨列出程式碼了。

完整程式碼如下:
var request = require("request");
var cheerio = require("cheerio");

// 玉山銀行匯率
var url = "https://www.esunbank.com.tw/bank/personal/deposit/rate/forex/foreign-exchange-rates";
// 取得網頁資料
request(url, function (error, response, body) {
    if (!error) {
        // 用 cheerio 解析 html 資料
        var $ = cheerio.load(body);
        // 搜尋各種貨幣的匯率
        var queryResult = []
        $('.inteTable tr.tableContent-light').each(function(i, elem){
            queryResult.push($(this).text().split('\n')); // 把搜尋結果存到array
        });

        // 整理搜尋結果
        var output = []
        for(var i=0; i<queryResult.length; i++) {
            output.push({
                coin: queryResult[i][2].replace(/\s/g, ""), // 貨幣
                in: queryResult[i][6].replace(/\s/g, ""), // 現金買入
                out: queryResult[i][7].replace(/\s/g, "") // 現金賣出
            });
        }
        console.log(output); 
    } else {
        console.log("擷取錯誤:" + error);
    }
});
輸出:

[ { coin: '美元(USD)', in: '31.34', out: '31.79' },
  { coin: '人民幣(CNY)', in: '4.558', out: '4.688' },
  { coin: '港幣(HKD)', in: '4.013', out: '4.133' },
  { coin: '日圓(JPY)', in: '0.2757', out: '0.2817' },
  { coin: '歐元(EUR)', in: '33.26', out: '34.26' },
  { coin: '澳幣(AUD)', in: '23.49', out: '24.29' },
  { coin: '加拿大幣(CAD)', in: '23.75', out: '24.55' },
  { coin: '英鎊(GBP)', in: '38.39', out: '39.39' },
  { coin: '南非幣(ZAR)', in: '', out: '' },
  { coin: '紐西蘭幣(NZD)', in: '', out: '' },
  { coin: '瑞士法郎(CHF)', in: '', out: '' },
  { coin: '瑞典幣(SEK)', in: '', out: '' },
  { coin: '新加坡幣(SGD)', in: '', out: '' },
  { coin: '墨西哥披索(MXN)', in: '', out: '' },
  { coin: '泰銖(THB)', in: '', out: '' } ]

如果要取值出來用,以日圓買進為例:
output[3]["in"]
輸出會是
0.2757
以上就是NodeJS取得銀行匯率的教學。

2017年1月10日 星期二

Smart7688Duo-使用Arduino控制UVC Camera

聯發科的Smart 7688 DUO要使用UVC camera來做影像監視串流很簡單,不過網路上搜尋到的資料大都兩種教學:
  1. 透過終端機輸入指令
  2. 用聯發科的MCS網頁完成
第一種不實用。第二種自己使用還可以,但若要變成產品的話,不太可能依靠別人的網頁來生產。

一般監視產品,應該會透過兩種方式開啟監控:
  1. 硬體觸發
  2. 網路啟動
硬體觸發指的是有直接連接到Smart7688的按鈕開關或是感知器(如人體感知器),透過電位的High/Low來啟動監視。網路啟動則是透過例如手機傳遞指令,來開關監控。

這篇主要介紹硬體觸發,不過為了簡單,不會真的連接感知器,而是透過Serial Port輸入0/1模擬電位的High/Low。

程式主要是Arduino完成的。

首先需要知道開啟camera的Shell指令;
mjpg_streamer -i "input_uvc.so -f 20 -d /dev/video0" -o "output_http.so"
網路上一般7688教學文章都是透過終端機輸入的,我們要想辦法透過Arduino輸入這串指令。

整個程式架構大概長這樣;
sensorValue = Serial.read() # 讀取輸入
if sensorValue == 1 {
    # 使用上面Shell command開啟camera
} else {
    # 關閉camera
}

接下來要知道Arduino怎麼執行Shell指令:
Process p;
p.runShellCommand(Shell Command);

不過用Process之前要先透過終端機開啟bridge,不然無法用Arduino控制
root@mylinkit:~# uci set yunbridge.config.disabled='0'
root@mylinkit:~# uci commit
root@mylinkit:~# reboot


完整Arduino程式碼:
#include <Bridge.h>

void setup() {
  Bridge.begin();
  Serial.begin(115200);
  while (!Serial);
}

void loop() {
  int c = Serial.read();  
  if (c != -1) {
    switch(c) {
    case '0':      
      disableCamera();
      break;
    case '1': 
      enableCamera();
      break;
    }    
  }  // End if
}

void enableCamera() {
  Serial.println("Enable UVC camera");
  
  Process p;
  p.runShellCommand("mjpg_streamer -i \"input_uvc.so -f 20 -d /dev/video0\" -o \"output_http.so\" &");    
}

void disableCamera() {
  Serial.println("Disable UVC camera");
  
  Process p;
  p.runShellCommand("killall mjpg_streamer");  
}