iOS push notification

首先您必須到 https://developer.apple.com/ 去新增一個 App,一般就是你要用 push notification 的應用程式

設定好名字,還有 ID ,記得要把 Push Notifications 的服務打勾

我這裡說明就用中文,因為英文的說明有一堆了

接下來就可以打開您的 Mac / 應用程式 / 工具程式 / 鑰匙圈存取

我們選憑證輔助程式,從憑證授權要求憑證




把他存下來,我舉的例子就叫 PushMsg ,把檔名改成 PushMsg 所以你會得到 PushMsg.certSigningRequest 這一個 CSR ,待會要到 apple 網站上面產生憑證



產生後,到鑰匙圈存取 應用程式,選鑰匙的地方,你會看到有 PushMsg 的公鑰和密鑰,點選專用密鑰,按下滑鼠右鍵輸出憑證,輸出成 PushMsg.p12 待會用










這時候,請用剛剛的 PushMsg.certSigningRequest 到 Apple 開發者網站的 App 設定 notification 的地方去產生憑證,可以下載後,

開發模式,你會得到 aps_development.cer ,實際部署模式,請依此類推



我們現在有 PushMsg.certSigningRequest , PushMsg.p12 , 還有 aps_development.cer 接下來,我們來產生,Server 端程式需要的憑證格式

這裡的程式,我們用 Golang 的範例,其他用 Python , Node.js 或是其他語言的朋友請依此類推

產生 cert.pem


openssl x509 -in aps_development.cer -inform der -out cert.pem

產生 key.pem 由於我很懶,key.pem 不想加密碼,程式不想再判斷密碼部分,我用這樣,如果你要加 pass phrase 就不要加上 -nodes 即可

openssl pkcs12 -in PushMsg.p12 -out key.pem -nodes

最後就是用 Apple 文件上面的 openssl 測試即可,沒有錯誤,就是 OK 了

openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert cert.pem -key key.pem

最後附上 golang 的測試程式,實際上已經有現成的 library 可以用 https://github.com/anachronistic/apns

只有連線的測試,有用 openssl 測試就可了,直接執行沒有錯誤,就是連線沒有問題了,送訊息可以直接用上面的 library


package main

import (
“crypto/tls”
“fmt”
“net”
“os”
)

func main() {

// load
cert, err := tls.LoadX509KeyPair("./cert.pem", “./key.pem”)
if err != nil {
fmt.Println(“key error: “, err)
os.Exit(1)
}
conf := &tls.Config{
Certificates: []tls.Certificate{cert},
ServerName: “gateway.sandbox.push.apple.com”,
}

// connect to APPLE
conn, err := net.Dial(“tcp”, “gateway.sandbox.push.apple.com:2195”)

if err != nil {
fmt.Println(“tcp error: “, err)
os.Exit(1)
}

tlsconn := tls.Client(conn, conf)

// be nice
err = tlsconn.Handshake()
if err != nil {
fmt.Println(“tls error: “, err)
os.Exit(1)
}

}




參考資料

http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1

https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html

http://bravenewmethod.com/2011/02/25/apple-push-notifications-with-go-language/

groupcache

這一個 golang 裡面非常帥氣的 library ,作者是原 memcached 的作者之一,主要就是讓 cache 機制再簡化

集群的部署能力也還不錯,完全不用再管 server instance ,我對這種,以簡單為名的 library 最沒有招架能力了

https://github.com/golang/groupcache

使用上也是非常的帥氣,可以參考 OSCON 的簡報

http://talks.golang.org/2013/oscon-dl.slide#1

詳細的使用上可以參考, source code ,或是 test case,還有很多種用法

以下是我用的範例,您可以用在很多地方,像是外部 url fetch ,或是很重的 query 或是檔案 IO 之類的
就是平常,你 cache 怎麼用,就可以怎麼用,cache 只有支援 拿,和寫,

以下的例子用這樣拿資料,我的 cache key 大概到小時,就用自己算每小時不同的 key
FileInfoCache.Get(nil, cacheFileInfo, groupcache.AllocatingByteSliceSink(&data))

另外,FileInfoFetch 就是另外一個做很多 disk IO 的工作
dest.SetBytes(FileInfoFetch(path))



// Example for groupcache
// snip from my code

var (
FileInfoCache *groupcache.Group
)

func init(){

//////////////////////////////////////////
// init book query cache
//cacheAddr := “127.0.0.1:55555”
//peers := groupcache.NewHTTPPool(“http://” + cacheAddr)
// the cache key is compose with timestamp hour
// 2006-01-02 15!!!url
getter := groupcache.GetterFunc(func(ctx groupcache.Context, key string, dest groupcache.Sink) error {
keys := strings.SplitN(key, “!!!”, 2)
//ts := keys[0]
path := keys[1]
dest.SetBytes(FileInfoFetch(path))
return nil
})


if FileInfoCache == nil {
// cache not been init
// allocate 64 MB memory for groupcache
FileInfoCache = groupcache.NewGroup(“FileInfo”, 64«20, getter)
}


}




你看,帥不帥氣,完全不需要另外跑,cache server daemon ,如果要組成 cluster 就直接在程式裡用 HTTPPool 的服務

bolt

記錄一下一些好用 golang library

blot 是一個純 golang 以簡單為美開發的 key value 資料庫,後來會用他,是因為一開始要存非常簡單的資料

想說就用 sqlite 來存就好了,反正欄位很少,資料結構簡單,開發環境是 Mac ,目標環境是 Linux ,部署的流程

就用 python 的 fabric 簡化,本地端編譯完 linux/amd64 的程式,複製到遠端 Linux,可是 github.com/mattn/go-sqlite3 有用到

CGO ,在 Mac 上面必須要用 gcc for linux 來編譯,編譯完後,到了目標機器上面又有 glibc 版本的問題,覺得這樣很花時間

不方便,另外就是 CGO 的編譯速度沒有很帥氣,立馬就決定找一個不依賴 CGO 的 key value store,目前覺得蠻合用了,這個專案的頁面的第一句話

就說服我了(我也太沒原則了吧) “Simple is the new beautiful.”

https://github.com/boltdb/bolt

使用簡單,由於我的 server  主要還是用簡單 JSON 格式,所以就先不用 gob 來 Encode 資料


// Example for bolt
package main

import (
“encoding/json”
“fmt”

“github.com/boltdb/bolt”
)

var (
db *bolt.DB
dbpath = “./user.db”
userbucket = []byte(“users”)
)

func main() {

db, _ = bolt.Open(dbpath, 0644, nil)

key := []byte(“unique_key_here”)
var value = struct {
Name string
Title string
}{“Somebody”, “Gopher”}

fmt.Println(key, value)

// in write transaction
err := db.Update(func(tx *bolt.Tx) error {
bucket, err := tx.CreateBucketIfNotExists(userbucket)
if err != nil {
return err
}
data, err := json.Marshal(value)

fmt.Println(“Please remember handle the error”, err)

if err == nil {
bucket.Put(key, data)
}

return nil
})

fmt.Println(err)
// in read
db.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket(userbucket)
if bucket != nil {
// if have a struct to restore it
//json.Unmarshal(bucket.Get([]byte(key)), &user)
fmt.Println(bucket.Get(key))
}

return nil
})

}


品嘗姊姊的手工蛋黃酥

請假一天,把櫥櫃的中島桌面完成,小聚時

姊姊帶來手工今天剛做好的無糖豆沙蛋黃酥,只有食材的味道,正港台灣口味

最近很不爭氣地把履歷打開

現在隨著時間,年紀的增長,也不確定自己想做的軟體或硬體服務,最後
到底能不能成功支持一間公司的運轉,目前所在的工作雖然非常的穩定,各方
面都是相對保守的,但是您也知道,越穩定的地方,就越少創意,沒有進步的環境,
除非自己成長


所以在自己成為自己的伯樂之前,也無限期開放自己個履歷

不知道,是自己先成為自己還有別人的伯樂,還是我先遇到我的伯樂

大家共勉之

乾淨的重裝 Mac

用官方的方式,做了 USB 開機碟,在蘋果的 App Store 下載讓強者更強的, Mavericks 後,先不急著點安裝

http://support.apple.com/kb/HT5856


sudo /Applications/Install\ OS\ X\ Mavericks.app/Contents/Resources/createinstallmedia –volume /Volumes/MyVolume –applicationpath /Applications/Install\ OS\ X\ Mavericks.app


MyVolume 就是你的 usb 隨身碟的名字

然後大概就是用 c9s 大大的調教方式
http://c9s.blogspot.tw/2014/04/mac-os-x-ssd-macbook-air-macbook-pro.html
Spotlight, timemachine 關,SSD mount noatime (不要最後讀取時間)



sudo mdutil -i off -a # spotlight 全關
sudo tmutil disablelocal # timemachine 關

sudo -i
cat > /Library/LaunchDaemons/com.disk.noatime.plist



<plist version="1.0">
<dict>
<key>Label</key>
<string>com.disk.noatime</string>
<key>ProgramArguments</key>
<array>
<string>mount</string>
<string>-vuwo</string>
<string>noatime</string>
<string>/</string>
</array>
<key>RunAtLoad</key>
<true>
</true></dict>
</plist>


sudo pmset -a hibernatemode 0 # 休眠不 snapshot 到硬碟





另外參考網友 RamDisk 的做法,做 RamDisk,把瀏覽器的 Cache 資料夾,掛在 RamDisk 下面
http://blog.roodo.com/jason1204/archives/25366852.html

開啟應用程式->工具程式->AppleScript編寫程式


do shell script “

if ! test -e /Volumes/RamDisk ; then

diskutil erasevolume HFS+ RamDisk hdiutil attach -nomount ram://$((2*1024*1024*2))

mkdir -p /Volumes/RamDisk/Chrome/Cache
mkdir -p /Volumes/RamDisk/Firefox/Cache
mkdir -p /Volumes/RamDisk/Safari/Cache

mkdir -p /Volumes/RamDisk/VMware

fi

"


儲存成應用程式後

到 “系統偏好設定” -> 使用者與群組 加到自己的登入啟動項目裡

Chrome:

rm -rf ~/Library/Caches/Google/Chrome/Default

ln -s /Volumes/RamDisk/Chrome ~/Library/Caches/Google/Chrome/Default


Safari:

終端機下:


rm -rf ~/Library/Caches/com.apple.safaridavclient
ln -s /Volumes/RamDisk/Safari/Cache ~/Library/Caches/com.apple.Safari


FireFox:


在網址上Key上: about:config
右鍵新增:browser.cache.disk.parent_directory 路徑就是 /Volumes/RamDisk/Firefox

馬達陣亡了

還是要小心,電壓輸出太大了,給小朋友玩坦克太久了

畢竟,電壓輸出長時間過載

記得要用 PWM 再降一點電壓



另外,有一點也要小心,電池模組的作法,如果是一般的乾電池,應該沒有關係

我是用 18650 鋰電池,所以,電池忌諱不可以過度充電,或是過度放電,也許要加一個電壓的 LED 燈,比較安全

另外藍芽遙控器,原始碼放在 github https://github.com/terryh/TankRemote

Arduino 藍芽遙控戰車

暑假到了,小孩也大一點了

以前哪些簡單的積木騙不了他了

現在一片 Arduino 的板子也是便宜到不像話,嘿嘿

我也可以順便作玩具來玩

Arduino 真的便宜又大碗,我用的是超值的 MEGA 版,要是不需要太多 IO 腳位的話,UNO版 就很夠用了,也有很多的懶人電源模組可以用,我要驅動的小坦克

是用田宮模型組裝的,很適合和小朋友一起做,樂趣無敵,另外電源的部份,我串兩顆 18650 的鋰電池,充完電,單顆有 4.12 ~ 4.18 Volt左右, 串兩顆,電壓大概有 8.3 ~8.4 V,驅動沒問題,不過,給田宮附的馬達,規格是說只吃到 3V,所以還是保守一點,我用 PWM 控制,再用電錶量一下,控制在 6 V 以下,算是很勉強,玩到目前還沒有燒焦味

電源模組用 L298D 就很夠了,但是,我用 L298P 少控制兩隻腳,HIGH ,LOW 就代表正向,反向了

藍芽模組用的是便宜好用的 HC-05

Android 手機遙控器,就自己刻一下,用寫 html5 遊戲的方式,直接用輕量過的 phaser 遊戲框架,包 cordova bluetooth serial 通信的模組

一個 android 的坦克搖桿就有了

編輯環境,當然是 VIM 直接用 ino 工具,測試馬達電機之前,都是先把訊號送麵包版的 LED 檢查程式先




Arduino http://www.arduino.cc/

Phaser http://phaser.io/

Android http://developer.android.com/

Cordova http://cordova.apache.org/

Cordova Bluetooth Serial Plugin https://github.com/don/BluetoothSerial

ino http://inotool.org/

Android TankRemote source https://github.com/terryh/TankRemote

TankRemote Google Play TankRemote

PS: 焊接馬達電線的時候,線的顏色放錯了,紅色變成反向了,最近桌子亂的太不像話

加稅

台灣政府這個最厲害的招式就是,加稅,不然就是漲價

國庫空虛呀,一大堆的議題,還製造加稅的理由

拜託醒一醒啦

目前,政府想一大堆加稅的理由,目的就是要打趴房價

我們今天來說這個假設,如果,最後房價還是沒有趴下去呢?

你已經一大堆新台幣跟著陪葬了,以後,換屋,還不是沒錢

如果,今天,政府拿出一樣的政策,對付企業,以後,企業盈餘

賺錢的部份,不加薪,我就加你稅的話,我想這個 633 應該很快就達成了

一大堆,企業,也都是土地利益,上下其手,一棟一棟,大樓在買賣賺錢的,

那幾間壽險公司,手上不是一缸子嗎?


台灣目前的生態是這樣

第一步,政府出面,跟農民,或是百姓說,這裡以後要做什麼建設,你要滾蛋,來吧,這一點錢給你去看醫生,不要太憂鬱

第二步,政府的機關,會規劃一大堆,相關的規劃啦,建設啦,變更地目,到時候,政府假如不想牽連太多,就直接高價釋出開發土地的時候,
價錢抬高賺一票,民意代表就用自己的在外面開的公司,明股,或是暗股來吃這個計畫,

第三步,政府,跟人民說,你的甘苦,我有聽到了,我們已經把這計畫發包出去(一定不能自己做,不然,出事就沒人背黑鍋了),不久就可以解決你的問題了

第四步,計畫完成了,這一輪,土地利益大家分完了,政府投入的經費,該入自己公司的也拿的差不多了,每個戶頭又多了好幾個 E

第五步,幹,問題還是沒解決,好吧,我們在玩一輪


你看那一些精華土地,國有才慘局釋出的價格,屈指一算,就知道,最後售價會到哪裡了,為什麼大家都天真的以為,房價太高是人民

或是財團的錯誤呢? 這不就是,一部政府自己自導的戲嗎,這個漲幅,不是都完全跟著你的建設走?


. 你可以不要賣出土地,廣建社會住宅,只租不賣給需要居住的人民. (他就是不作,因為政府絕對不能做事,不然作不好,沒人背黑鍋,外包也許還有點機會)
. 你可以有完善的造鎮計畫,轉移都會區就業,及居住需求的緊繃
. 資訊化公務單位,配合造鎮遷移出市中心,建築,或是機關用地,再利用,再開發,簡化流程,人事成本,不是再賤賣
. 完善的城鄉規劃,產業升級,紓緩都會區才有就業機會的情形
. 只有一種的社會福利,照顧,及醫療系統,不要成城鄉落差大,照成,全都只能往都會集中的情形
. 只有一種的退休年金制,沒有在什麼,公務人員,勞工,農民
. 政府笑能提昇,人事,組織再造
. 有完整的創業育成機構,除了不提供錢 (這不就是創業的人要解決的問題),但是其他的都提供,場地,網路,人脈匯集,幫台灣多一創造一些高毛利的產業




假日雜工

假日,修修補補,妝點新書架

浴室鏡櫃,還有一個量身訂做的迷你床頭櫃,剛好補一下牆面的段差

每一件都有缺點,還有自己的進步

浴室鏡,敗筆上蓋,上面都是釘孔,不美觀,雖然,吊上壁面
看不到,上蓋可以用接榫的方式結合,就可以美觀多了,另外鏡框
的作法不對,這樣側面,也露出接線,遜掉了



床頭櫃,敗筆,我鉸鍊挖錯邊了,挖到了櫃體上
真瞎



衣櫥,還沒做好,不過,我的滑軌溝,已經洗錯了一點

現在,會被笑的地方,就是每一件作品,都有缺點,不過也都有成長

進化的鋸台,可以的話,一定千萬用圓鋸去裁切,速度相差太大了,
需要大一點的板材,一定要先請建材行或是木材行裁切好,一刀 5元,10元 20元都有,千萬不要像我第一次,在網路上買材料,好像是一間叫
X幫手的賣家他用公分算裁切單價,兩塊 8尺 4 尺的木芯板材,大約快 6000 元,千萬不要
買那種用公分算的,貴了兩三倍的金額



現在叫料的超低調木材行,老闆沒有招牌,不是最便宜
但是老闆很親切,又是在地店家,一定要支持的啦