0

Android4.4のメーラでさくらレンタルサーバのメールが読めない件

たしか6月ごろのAndroidのOS 4.3から4.4へのアップデートだったと思う。メール読みたくないので放置してた。

さくらレンタルサーバのIMAPメールの本文が読めなくなった。件名や差出人は見れる。
本文を読もうとすると「不明なエラー」と表示され、メールヘッダを見ようとすると強制終了する。

さくら以外のサーバーのメールは見れるのと、
Nexus5とNexus7両方同時に見れなくなって、OSアップデートが来ないauのHTC One J (Android 4.1.1)は読めてるのでAndroidのメーラーがおかしくなったんだと思う。


対処

K-9 mailインストールしたら万事解決した。

K-9には定期的にメールサーバーにチェックに行く機能はデフォルトでOFFになっていて(ONにもできるが)、
代わりにIMAP4 IDLEが使える。
TCP接続しっぱなしにして新着ごとにEXISTSが送られてくるので、サーバにメール届いたらしたらすぐスマホに通知される。

1

Hubotで読めるRSSリーダー作った

チャットのチャンネル(部屋)毎にRSSを登録して、RSSリーダーにできるhubot scriptを作った。

https://github.com/shokai/hubot-rss-reader

去年nikezonoが「人の読んでるRSS読みたい、むしろRSSのリスト作ってお前コレ読めって薦めたり、他人にRSSの購読を追加してもらったりしたい」というような事を言ってた気がしたので、最近hubotが楽しいし作った。


こんなの


チャットはSlack.comで、HubotはHerokuに置いてつないでる。

「hubot rss add (URL)」とコマンドを発言すると部屋にRSSを追加できるようになっていて、チャットルームごとにRSSが購読できる。

Slackではプロジェクト毎に部屋を作ってGithubやTravisの通知を流すように運用している。

  • そのプロジェクトに関連あるリポジトリのRSSを流す
  • 研究室全員のgithubのfeedを流す部屋を作っておいて、個人活動を共有する
  • 技術系のblogを誰でも何でも登録していいよという部屋を作っておく

とかすると便利だと思う。若者のRSS離れを抑止できる。


インストール


https://www.npmjs.org/package/hubot-rss-reader

npmでhubotにインストールして

% npm i hubot-rss-reader --save

external-scripts.json に
["hubot-rss-reader"]
を追加すれば使える。


環境変数で色々設定できるが、しなくても適当に動く。
export HUBOT_RSS_INTERVAL=600      # 600秒ごとに更新チェック
export HUBOT_RSS_HEADER=:sushi: # RSS Header Emoji (デフォルトで寿司)
export DEBUG=hubot-rss-reader # debug printを有効にする


なおチャットルーム毎のfeedはredisに保存するようになっている。
hubotはデフォルトでredisを使うので、ふつうにredis-server起動しておけば特に必要ない。
herokuなら
% heroku addons:add redistogo:nano
でok


コマンド


追加と削除とリストしか今のところ無い。

hubot rss add https://github.com/shokai.atom
hubot delete add https://github.com/shokai.atom
hubot rss list

0

mongooseにschema関係なくなんでも保存する

mongooseはスキーマで宣言されていないkey:valueは保存してくれない。MongoDBっぽくないけど安全ではある。
でも、webhookで色々なjsonがサーバープッシュされてくるAPIのデータを全部保存したい場合に困る。例えばtwitterやjawbone upのstream APIとかを、mongooseでスキーマレスになんでも保存したい。


方法1 Mixedを使う


調べると、Schema.Types.Mixedを使えとか書いてある。

var Any = new Schema({ any: Schema.Types.Mixed });
ただこの方法だと、なんでも保存できるanyの中に保存しろって事なんだけど、documentの中の深い部分を検索する事になってめんどい。


方法2 mongo driverを直接使う


mongoose.connections配列がnode-mongodb-nativeなので、ここに直接insertすればschema無いデータも保存できる。

例として、jawbone-up24がwebhookでプッシュしてくるjsonを全部eventsというcollectionに保存する。


model定義

## 空のschemaを作る
eventSchema = new mongoose.Schema

## 直接insert
eventSchema.statics.insert_webhook = (data, callback = ->) ->
mongoose.connections[0].collection('events').insert data, callback

mongoose.model 'Event', eventSchema
スキーマ関係なく直接保存するメソッドをmongooseのmodelに生やした。
mongooseのmodel Eventにスキーマ登録すると、mongoでは複数形のevents collectionになる


expressでwebhook受信してmongo driverに直接保存

Event = mongoose.model 'Event'
app.use bodyParser.json()

app.post '/webhook', (req, res) ->

## jawboneはevents[0]にデータが入ってるので、それを保存する
Event.insert_webhook req.body.events[0], (err, res) ->
console.log "保存した" unless err

return res.end "ok"


この方法だとcontroller側から使う部分もmongooseっぽいし、query投げるのもmongoose風に普通に書ける

eventSchema.statics.last_move_of_user = (user_id, callback) ->
@find
user_xid: user_id
type: 'move'
.sort
timestamp: 'desc'
.limit 1
.exec callback

0

socket.io-client-simple gemをsocket.io 1.0.x対応した

5月末にでたSocket.IO 1.0に、socket.io-client-simpleを対応させた。

1.0対応は2週間ぐらい前にだいたいできてたんだけど、切断の検知と自動再接続する処理のあたりがうまくいかなくてリリースできてなかった。rubyのthreadの闇は深い。


うまく動くようになったのでどうぞ

% gem install socket.io-client-simple

変なところあったらgithubにissue立てたり、@shokaiにお知らせください


経緯


socket.io meetupに行ったら意識が高まったので、プレゼンとか聞きながらデバッグしてたらできてきて、意識高まりすぎて寿司とビールスルーして帰って電車の中でgem pushした。


socket.io 0.9 → 1.0の変更点メモ

ソースを読んだりして挙動を調べた。
研究室のwikiに書いたのメモのコピペで、たぶんgeta6とかnekobatoが書いてくれた情報も含まれる

クライアント作者としてはping-pongがサーバー→クライアントだったのがクライアント→サーバーになったおかげで切断検知しやすくなってうれしい感じした。


engine.io 1.1 -> 1.2に上がった

むしろこっちの変更の方が多いような気もする、あんまりちゃんと追えてない


初期化プロセスが変わった

最初に接続可能なプロトコル一覧を取るところから違う
xhr(comet?)で最初つないで、websocket使えるならwsに移行する

ということはrubyのsocket.ioクライアントはwebsocketだけのシンプル実装じゃだめ?
と思ったけど、いきなり/socket.io/?transport=websocket にwebsocket接続すればokだった。transportオプションがキモ

node.jsでもクラスターを取るとupgradeリクエストの後で400を返してしまう
クライアントの接続オプションにtransports: [‘websocket’, ‘polling’]を渡して以前と同じ挙動にできる
io.connect window.location.host, {transports: [‘websocket’, ‘polling’]}

failするユーザが高速につなげるようにするためにxhr-pollingを先行させている
開発するもののターゲットにレガシーブラウザが入っていなければwsを先行していいと思う

バージョンが混ざったらやばい

1.0のクライアントを0.9のサーバーに接続させようとするとサーバーで大量の”unhandled socket.io url”エラーが出る


通信データの格納方法が違う

server/client両方で環境変数 DEBUG=* を付けて通信させてみるとわかりやすい
頭に数字(制御コード)が付いたjsonをやりとりする。v0.9までは、”数字:::JSON” だった

“0” – 接続時にsession idなどを通知
0{"sid":"tOqSjGeyyhBo5x3vAAAA","upgrades":[],"pingInterval":25000,"pingTimeout":60000}

“41” – 切断
サーバーで明示的にsocket.disconnect()した時にクライアントに送られてくる
ただ “41” だけが送られてくる。


“42” – data
サーバーでemit(‘chat’, {msg: “hello”}, {foo: “bar”})した場合
42["chat",{"msg":"hello"},{"foo":"bar"}]
が送られてくる
送信時も42を付けて配列のJSONで送る


“1:6” – fast upgrade
はやくwebsocketにupgradeしろって指示をサーバーからクライアントに送る


“2” – ping
clientからserverへのping


“3” – pong
pingを受けての、serverからclientへのpong。これがすぐ返ってこなかったら、前段のnginxか何かにsocketがつながっているだけで、バックエンドのsocket.ioサーバーが息してないと判断できる


“2probe” – ajax ping
“3probe” – ajax pong

“5” – upgrade
ajax-pollingからwebsocketにupgradeする時にクライアントからサーバーに送る


heartbeatの手順が変わった

v0.9まで
サーバーが “2::” を送ってくるので、clientはすぐに”2::”を返す

v1.0以降
clientが”2″を送るとサーバーがすぐに”3″を返す
clientは接続してからすぐにサーバーに2を送らないと数秒で切られる

接続時の”0″で指定されたpingIntetrval(ミリ秒)毎に”2″を送ればok

この変更はすごく良い。普通TCP socketだとクライアントはなにかパケットを送ってみないと切断を検知できないので、今まで切断検知の為だけにnull送ってて無駄だった。

サーバーは何もしなくてももともと切断検知できるできる


io.configureが無くなった

log levelの設定はdebug npmを使う


io.connected

クライアントライブラリ側で接続状態を確認するio.socket.connectedがio.connectedに移動してた


シングルトン

client libは複数インスタンスを作っても、同じサーバーへの接続ならコネクションが共有される(単にキャッシュされた同じインスタンスが返ってくる)


client npmのIPアドレスが取得できない

socket.io-client npmからの接続のみ、サーバー側でクライアントのIPアドレスが取得できない
v0.9ではsocket.handshake.address.addressに入っていた
ブラウザjsからの場合、socket.handshake.address.address に入っている
client npmからだとaddressがnull


encoding

全体がUTF-8でエンコーディングされるようになった

0

太陽電池でBlendMicro動いた

秋月の外のレジの下の棚にある350円のソーラーパネル2枚でBlendMicroが起動し、BLEが動いた。




Macからble-firmataでanalogReadとかもできた。
何しよう。