2013年10月31日 星期四

請支持無障礙E道沿用Sita陳僖儀的聲音

http://www.ipetitions.com/petition/sitachan/

以下轉發至Sita媽咪

致入境處及失明人協進會:

有鑑於 Sita 生前亦曾是失明人士助跑領行員,也可算是她和失明人士一種愛的聯繫,故此希望她的聲音能再陪他們同行,作為 e 通道的領行員。妹妹聲音酷似家姐,故沒錄的聲段,才再由妹妹補上。可能此舉是會令你們增添麻煩,加重你們的工作,但仍希望 Sita 的聲音能在空氣中傳播,延續她永遠想替人做到最好的理念。

Sita 媽媽

2013年10月30日 星期三

兩年半的堅持

公司成立至今己經兩年半。一直堅持在每周第一個工作天的早上召開例會,檢討工作進度、分享學到的知識、讓同事了解公司的發展;當然亦希望同事在群眾壓力下會準時上班、準時完成工作。這個堅持在今天結束了。

事與願遺,十時開始的會議,同事們總是要遲到十五分鐘才回來;回來後又得點時間準備需要展示的內容;甚至要在會上吃早餐;足以表達他們對會議的冷漠。會議過程中,同事交代進度,基本上只有我和當時人在交流,其他人都不專心聆聽。分享環節總只得我分享,間中才會有同事願意把所學到的東西分享出來。總總因素,使我認為開會只是浪費大家的時間,那就不如算了。

我有想過用鬧來改善狀況,一想到大家都是成年人,清楚知道自己的崗位,不用要「鬧」才改吧!況且我也討厭「被鬧」。己所不欲,勿施於人。心底裡也怕「鬧」走了,又要招人...。既然大家都不願意開會,那就節省少少吧!

2013年10月29日 星期二

成功安裝 ESXi


安裝了新買的 Intel Pro/1000 MT 之後,能成功在 Asus P5K SE 上安裝 ESXi。

可是,到安裝 OS 上出了問題。在公司把 CentOS 的影像檔拷到 ESXi Datastore 時,236MB 的檔案竟然要上傳 140 分鐘,實在「痴線」。想用機器內的 DVD 光碟機,ESXi 又偵測不到;想透過 USB 又是偵測不到;最後還是放棄了,把整台機搬回家。家中的 LAN 線已經提升至 CAT 6,所有接線的機器都支援 Gigabit,一切準備就緒,只欠那台伺服器的設定成功。幸好,家中上傳那個 CentOS 影像檔只需 5 秒,傳個 4GB 檔也慢不了多少。

我把 ESXi 劃分成兩台機:一台 CentOS 6,另一台則是 Windows 7。前者用來作為網頁伺服器,後者則是影片串流、IE、BT 之用。之後的安裝都很順利,只是在 Windows 內卻找不到聲效卡,無法把聲音輸出...。

2013年10月28日 星期一

再試 ESXi

Setup ESXi Again

網友指 Intel Pro/1000 系列最能兼容 ESXi。之前鎖定了 CT 版本,所以昨天到深水埗高登電腦中心找卡。找到兩家小店有這款卡發售。價錢約為 HK$380。由於未能確定添加此卡後能否順利安裝 ESXi 5.5,於是繼續看看有沒有更好的方案。皇天不負有心人,找到另外兩家小店出售 Intel Pro/1000 MT,價錢更只需 HK$168。在網上查看資料,發現有外國朋友成功使用雙頭版的 MT 安裝 ESXi 5.0,相信單頭版的也沒問題,於是付錢購買。

今早,在我的 ASUS P5K SE 底板上裝上 LAN 卡後,再次安裝 ESXi,今次真的成功了!由於今天實在很忙,未有時間安裝虛擬電腦,留待明天繼續...。

2013年10月26日 星期六

MacBook Pro Late 2013


在星期三零晨的發佈會推出升級版後,再次引起我購買新版 MacBook Pro with Retina Display 的慾望。第二天跟「果農」聯絡後,得悉平時要等三個月才能以優惠價購買蘋果產品的他,今次竟然能第一日便能購買!我當然不能錯過這次大好機會,立即跟他落單!花了三天,新機已經到手。能用比初階版更便宜的價錢買到中階版,實在很高興!

2013年10月22日 星期二

初試 ESXi

Setup ESXi

我的家中只剩一台十年前買的 Fujitsu 手提電腦及五年前買的桌面電腦是使用 Windows;其他的都是 Mac 系電腦。手提電腦是給內子看韓劇,而桌面電腦原本是用來開發 iOS 應用,現在則留給女兒做功課。因為出版商的網上練習一直都停留在只有 Internet Explorer 6 才能正常運作。友人分享了他家中 ESXi 服務器的佈局,引起了我的興趣。回家後立即動手修改。

我想把 ESXi 安裝到桌面電腦後,同時設定 Linux 及 Windows 系統。Linux 給我作為網頁及數據服務器;而 Windows 則用作韓劇影片串流服務器。同時女兒也能透過 iPad 連接服務器,打開 IE6 做功課,不用把整台電腦硬塞到細小的書枱上。這個佈局很好用,能同時滿足三位使用者的需要。可是 ESXi 並不容易安裝,在我的華碩 P5K-SE 底板中出現「找不到網絡卡」的問題而無法繼續。在網上找過很多不同的方法,都無法修正問題。看來一是買張 Inter Pro 1000 系網絡卡來解決;或是改為 Linux 底,在 VirtualBox 跑 Windows。後者當然的效能較慢...。

2013年10月20日 星期日

Sita Chan @Chivas




替《Chivas》開發的 iPad App 在昨天的晚會第一次使用,今日需要把 iPad 拍下來的照片從服務器取回來並發給客人。在客人的 Facebook 粉絲頁內無意中找到了一個包含 Sita 陳僖儀的照片。我從未看過這批照片,看來是 Sita 想要給我看的。當時已跟客戶合作第二個應用,再一次在生命中跟 Sita 擦肩而過...。

2013年10月19日 星期六

Chivas 18: The Dream City


上周五,客人找我們開發一款 iPad 應用,在本周五使用。開發及測試時間只有三天半,實在急趕。然而,部份功能(如:把相片貼到 Facebook Fan Page 內)還是第一次製作;在這麼短的時間完成,已經是很有效率。然而,急趕換來一點點不穩定;這是理想與實際的落差所造成的。幸好,還是有解決問題的方法;簡單地修改一下,總算渡過難關。多謝負責的朋友,Objective-C 經驗不多但品質好。

2013年10月18日 星期五

下載 OnTV 影片

Searching Sita's News on Oriental Daily

昨晚編寫的程式,只要稍微改動一下,便能擷取《東方日報》的新聞。

不過,在擷取的同時,更想下載 OnTV 的影片。由於影片被 Flash 包裹,無法直接看到它的位置,不像《蘋果日報》般容易地找到,需要花點時間及工具,才能找到影片的網址。最終找到網址的格式是:

http://202.125.90.194/Video/[yyyyMM]/[id]_ipad.mp4?&msect=150&ssect=yahoo
* [yyyyMM] 是影片的拍攝年份及月份,如:201304
* [id] 是影片的編號,如:OBK-130417-12286-07M2

影片編號是以 XML 格式發送到瀏覽器,以下是它的內容:

2013年10月17日 星期四

《蘋果日報》搜聞

Searching Sita's News on Apple Daily

今晚不想搞《AMIGO Controller》,反而想搜尋一下 Sita 在《蘋果日報》的新聞及動新聞。於是寫了一個 PHP 程式,把搜尋到的新聞標題及連結顯示在畫面上,我再人肉地把新聞擷圖及影片下載。程式不難寫,原理都是遂天讀取目標頁,搜尋有沒有「陳僖儀」出現,再把連結顯示出來而已。程式雖然簡單,但卻幫得上忙。

2013年10月16日 星期三

拉闊圖書館.十:認識八個字

BeyondZ Library 10

到了第十課的拉闊圖書館。我再次成為講者。今次的題目是《認識八個字》。向同事講解術數中的八字。

要在短短一小時交代術數的複雜理念,根本是不可能,只好講解一些必須要知的事情,如:天干地支、陰陽五行、十神代表、八字中哪個字是自己、批命看生剋制化。由於要記的事實在太多,大家都不會記得,最後還是就著喜歡的事情提問及解答。足足花了兩個半小時才完成今次的課堂,證明大家對命理也很有興趣。

2013年10月12日 星期六

把 PHP 程式放在背景執行

Execute PHP in Background

之前開發的「《頭條日報》自動剪報系統」起初是在 SSH Terminal 下執行,但過不久便會因逾時而被終止。解決辦法是把 PHP 放在背景中執行,可使用「nohup php index.php &」指令。這樣,所有輸出到畫面的內容都會存入 nohup 檔案內。只要利用「tail -f nohup.out」便能觀看最近幾行輸出的內容。

2013年10月11日 星期五

設定 VPN

VPN Settings in QNAP TS-210

早幾天把 QNAP TS-210 的韌體升級後,發現服務器被黑中,每天有數個 IP 地址的電腦不斷嘗試 SSH 的登入名稱及密碼。有見及此,的起心肝設定 VPN,減少服務器直接對外的接口數目。

上一版本的控制台沒有 VPN 選項,是目前版本新增的,方便我這種不懂設定服務器的人。設定十分簡單,朋友說 OpenVPN 安全但 iOS 無法連接,建議使用 PPTP,所以就只在 Enable PPTP VPN server 前打勾,除最大連接上限外,其他的都選用預設值。儲存後便能立即使用。在 iPhone 5 及 MacBook Air 中簡單設定一下 VPN 的地址及帳號,便能順利使用!

2013年10月10日 星期四

為已有的項目加入 Git 控制

Adding Git Control to Existing Xcode 5 Projects

朋友示範了本地 Git 的用法,實在很方便。於是想把開發了一年之久的《AMIGO Controller》加入 Git 代碼控制。可是選項中找不到加入 Git 的方法。這是因為在正常情況下,只有在新建項目時才有得選擇。

要對現有項目加入 Git 的話,步驟如下:
  • 關閉 Xcode 5
  • 打開 Terminal
  • 跳轉到項目的資料夾,如:AMIGO_Controller
  • 建立一個名為 .gitignore 的檔案
  • 把以下內容加到 .gitignore 檔案內:
        UserInterfaceState.xcuserstate
        build
        *.pbxuser
        *.perspectivev3
        *.mode1v3
        *~
        *~.nib
        *~.xib
        .DS_Store
        xcuserdata/
  • 輸入 git init 後拍 Enter 鍵
  • 輸入 git add . 後拍 Enter 鍵
  • 輸入 git commit -m "Initial commit" 後拍 Enter 鍵

    這樣的改動之後,重新打開 Xcode 及項目,便能見到 Source Control 內的選項。如在執行 git 時出現問題,可到 http://git-scm.com/downloads 下載 Git 程式。安裝後要重啟 Terminal 才會生效。
  • 2013年10月9日 星期三

    iBeacon 示範程式


    從一位專門製造 Bluetooth BLE 產品的朋友手上借來了一顆 iBeacon 硬件。在 Apple 公開 iBeacon 規格前,他已經能利用《逆向工程》製作出 iBeacon 硬件,實在利害。比起最便宜的 iOS 裝置,它的售價便顯得更加便宜,相信能讓市場接受。

    既然硬體準備好,那就由我公司開發軟件部份。朋友最近有空,來了我公司幫忙數星期,這個項目就交給了他負責。花了一天時間已經按要求完成 iBeacon 示範程式,可在日後的展覽場合使用。

    2013年10月8日 星期二

    解決 Google Analytics iOS SDK 3.0 的組譯錯誤

    Linker Error in Google Analytics iOS SDK

    《AMIGO Controller》上架在即,為了更加了解用戶的習慣,決定加入 Google Analytics。

    按照 Google 的指引一步一步地把 .h 及 Frameworks 加入到項目中。可是在組譯時卻出現問題。解決方法是加入 AdSupport.framework。這是 Google 指引中遺漏了的地方,要小心留意。

    2013年10月7日 星期一

    解決 ITMS-9000 錯誤

    ERROR ITMS-9000: Invalid Code Signing Entitlements

    《AMIGO Controller》要在十一月前上架,於是我把目前較為穩定的版本提交到 Apple App Store。可是卻出現了一堆錯誤。起初認為是 Xcode 5 新增的改動導致問題,改了幾個地方,警告的句子少了,但錯誤地方依舊。看清楚警告內容,似乎是跟 Bundle ID 有關。到 iOS Dev Center 查看,Bundle ID 後半段是正確,不過前方的 Prefix 則不對。我重新下載所有 Provisioning Profile 仍然解決不了事情...。

    我的電腦有多個 iOS Developer License,項目最初是使用 License A 的 App ID,到最近決定了上架的帳號後才改到 License B。查看 License A 的 Prefix,竟然跟現在的一樣,難怪會有這樣的錯誤。既然主因出現了,那就可以對症下藥。然而,找遍了 Xcode 也找不到能修改的地方,只好使用絕招。手動地打開 AMIGOController.xcodeproj/project.pbxproj,找到了那條錯誤的 Prefix,把它改回新的 Prefix 後儲存,再次啟動 Xcode。生成出來的版本就能解決以上問題!

    2013年10月4日 星期五

    iOS 7 又一彈鴨問題...

    AMIGO Controller for iOS 7 介紹的狀態欄解決方法,今天發現當使用 Dropbox SDK 的登入視窗後會打回原形。花了點時間仍然無法修正問題,最後只好用最笨的方法。在 iOS 7 下把所有 UIView 類的垂直位置都加上 20 pixels。雖然方法蠢,但勝在有效。不過,一波既平,一波又起。今次輪到 Google SDK 的登入視窗導致彈鴨...。

    2013年10月3日 星期四

    Post Test

    今天為公司一個新項目進行數據搜集,印證概念能否變為真實,需要到不同的網頁擷取資料。為了方便工作,寫了一個簡單的 Javascript + PHP 程式去讀取資料。
    <script>
    function PHLog(message)  {
     var now = new Date();
     var hours = now.getHours();
     var minutes = now.getMinutes();
     var seconds = now.getSeconds();
     var currentTime = hours+":"+minutes+":"+seconds;
     var postResult = document.querySelector("#postResult");
     postResult.value = currentTime+" "+message;
    }
    
    function postRequest()  {
     PHLog("Sending request...");
     var urlString = "http://www.pacess.com/blog_files/postTest.php";
     var parameterString = "url="+encodeURIComponent(document.querySelector("#postFunction").value)+
            "&param="+encodeURIComponent(document.querySelector("#postParameter").value);
    
     var http = new XMLHttpRequest();    
     http.open("post", urlString, true);
     http.setRequestHeader("content-type", "application/x-www-form-urlencoded");
     http.setRequestHeader("content-length", parameterString.length);
     http.setRequestHeader("connection", "close");
     http.onreadystatechange = function()  {
      PHLog(http.responseText+"\r\n~End~");
     };
     http.send(parameterString);
    }
    </script>
    
    <input id="postFunction" type="text" placeholder="http://www.facebook.com/" style="width:300px;" value=""></input><br>
    <input id="postParameter" type="text" placeholder="param=1234&time=4567" style="width:400px;" value=""></input>
    <button onClick="JavaScript:postRequest();">讀取內容</button>
    <br><textarea id="postResult" rows="40" style="width:580px;"></textarea>

    2013年10月2日 星期三

    《頭條日報》自動剪報系統

    Sita Recognition in Headline Daily

    在 Sita 過身後我才認識到香港有這樣好的歌手,也才開始留意她的消息...。在《陳僖儀補完計劃》的剪報方面,我希望能納入她生前的內容,至少是《頭條日報》及《am730》這些有著大量舊報重溫的報導。但要逐日逐日去查,我又花不起這樣的時間。那麼最好又是交給電腦替我去做!

    為了試行構想的可行性,我先以《頭條日報》作為實驗,事關它每頁的內容是圖文分開成 JPG 及 PNG;編寫程式讀取 PNG 層的文字,較容易檢測到正確文字,如:僖、Sita。當發現文章出現以上關鍵字時,便進一步下載 JPG 圖片層,並合併成為單一高清 PNG 影像。花了一晚時間,做了點簡單測試,證實程序能成功抓出關鍵字後,便進行全面性的搜尋工作。電腦花了三小時能完成一個月份量的檢查。由於 Sita 是 2010 年出道,大約 40 個月,整個運作大約需要 120 小時。上圖便是電腦找出來的其中一張結果。那是 2013 年 3 月 18 日在《頭條日報》第 25 頁的部份內容。那頁沒有 Sita 的照片,只有在報導中出現過一次「陳僖儀」關鍵字。要是由我人手檢查,相信不會留意到這篇報導...。以下是偵測關鍵字的代碼:
    //-----------------------------------------------------------------
    //  Character recognition
    //  僖(細明體)
    $characterPattern = array(
     1,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,1,
     1,1,1,0,0,0,1,1,1,1,0,0,1,1,0,0,0,
     1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     1,1,1,0,0,1,1,1,1,1,0,0,1,1,0,0,1,
     1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,
     1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,
     1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,
     1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,
     0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,
     0,0,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,
     1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,1,
     1,1,1,0,0,1,1,0,0,1,1,1,1,0,0,0,1,
     1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,1,
     1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,1,
     1,1,1,0,1,1,1,0,0,1,1,1,1,0,0,1,1);
    $patternWidth = 17;
    $patternHeight = 17;
    
    $sx = 50;
    $sy = 50;
    $width = imagesx($image);
    $height = imagesy($image);
    
    for ($y=$sy; $y<$height-$sy; $y++)  {
     for ($x=$sx; $x<$width-$sx; $x++)  {
    
      //  40, Transparence index
      $x1 = $x;
      $y1 = $y;
      $colorKey = imagecolorat($image, $x1, $y1);
    
      $offset = 0;
      $notMatch = 0;
      for ($py=0; $py<$patternHeight; $py++)  {
       for ($px=0; $px<$patternWidth; $px++)  {
    
        $x1 = $x+$px;
        $y1 = $y+$py;
        $colorIndex = imagecolorat($image, $x1, $y1);
        if ($colorIndex == $colorKey)  {$flag2 = 1;}
        else  {$flag2 = 0;}
    
        $flag1 = $characterPattern[$offset];
        if ($flag1 != $flag2)  {
         $px = $patternWidth;
         $py = $patternHeight;
         $notMatch = 1;
        }
    
        $offset++;
       }
      }
      if ($notMatch == 1)  {continue;}
    
      //-----------------------------------------------------------------
      //  Match with pattern
      echo("\nMatch at ($x, $y)");
    
      //  Download JPG and merge to a single PNG image
     }
    }

    2013年10月1日 星期二

    《am730》剪報

    am730 Old Issues

    am730 也是其中一家能找到自己舊報章的數碼版,日子可追索到 2005 年 7 月 30 日。今次抓取的也是網頁版圖檔。

    網頁版的構造很特別,它不像《頭條日報》的圖還圖、字還字。全是 JPG 格式,而且還最多把一頁分成十六個 JPG 檔,不用一次過提取大面積的連續記憶體空間,減輕設備的負荷。下載頁面的步驟如下:
  • 打開 Wireshark 並擷取自己電腦的資料進出
  • 打開瀏覽器並跳到《am730》官網
  • 打開想要的報章及報導的頁面
  • 停止 Wireshark 的記錄
  • 找查日期數字,如「20130418」便很容易找到報頁的連結
  • 在連結中最後的數字是格仔編號,由 0 開始
  • 如果是 4x4 劃分的頁面,最大是 15 號

    不過,要手動逐個 JPG 下載,又要把 16 張圖合拼,實在很花時間。這種工作最適合電腦來做。於是簡單寫了個 PHP 來達成,方便在任何地方都能使用。下載方面用 file_get_contents 及 file_put_contents 就可以。以下是把 JPG 合拼的部份:
     $newspaperDate = "20130418";
     $blockHeight = 590;
     $blockWidth = 462;
     $folder = "__files__/";
     $height = $blockHeight*4;
     $width = $blockWidth*4;
    
     //  Merge 4x4 images to single PNG
     $x = 0;  $y = 0;
     $image = imagecreatetruecolor($width, $height);
     for ($i=0; $i<16; $i++)  {
    
      $filename = $newspaperDate."_am730_p".$page."-".$i.".jpg";
      $filePath = $folder.$filename;
      $blockImage = imagecreatefromjpeg($filePath);
      if ($blockImage === false)  {
       echo("<br>Error loading image block $filePath...skip");
       continue;
      }
    
      //  Draw block image to big image
      imagecopy($image, $blockImage, $x, $y, 0, 0, $width, $height);
      imagedestroy($blockImage);
    
      $x += $blockWidth;
      if (($i%4) == 3)  {
       $x = 0;
       $y += $blockHeight;
      }
     }
    
     //  Save PNG image of whole page
     $filename = $newspaperDate."_am730_p".$page.".png";
     $filePath = $folder.$filename;
     imagepng($image, $filePath);
     imagedestroy($image);
     echo("<br><img src='$filePath'>");