SublimeText in Windows で TabNine
評判がいいのでTabNineを入れてみた。 Rubyの Semantic Completion を有効にするところでハマったのでメモ
TabNineのインストール
Package Manager
から普通にインストールrubyのLanguage Serverをインストール
> gem install solargraph
TabNineのコンフィグディレクトリを検索 Sublimeのエディタ画面で、
TabNine::config_dir
と入力するとディレクトリが補完される。 このディレクトリにTabNineSample.toml
ファイルがあるので、同じフォルダのTabNine.toml
にコピーする。TabNine.toml ファイルを修正 Rubyの場合下記のようにgem実行ファイルがbatになるので、フルパスでbatファイルを指定してやるようにすると動いた。
[language.ruby] command = "C:\\Ruby25-x64\\bin\\solargraph.bat" args = ["stdio"] install = [["gem", "install", "solargraph"]]
- Semantic Completion 有効化
エディタ画面で
TabNine::sem
と入力。 これで動くはず。
海外に置いたAppleTVで日本のNetflixを見る - Raspberry Piで作るVPN切り替え機
やりたいこと
- USの家に置いてあるAppleTVで、日本のIPからしか使えないサービスを使いたい。
- AbemaTV
- Netflix(日本版)
- 常時日本経由のインターネットだと速度面、レイテンシ面で不利なので任意に切り替えられるようにしたい。
実装の方針
- RaspberryPiで日本の実家においてあるサーバへVPNを張り、日本側の出口とする。
- RaspberryPiの
wlan0
を家庭内LAN、eth0
を切り替え用LANにして、eth0
の先にAppleTVをぶら下げる。 - RaspberryPiにて
eth0
にDHCPサーバ立てて、IP配るようにするeth0
→wlan0
の転送設定を入れる- デフォルトゲートウェイ(DGW)をJP側とUS側の間で切り替えることで、出口を制御する
- DGWの切り替えはコマンド入力だと家族が使えないので、Homebridgeを使ってiPhoneから制御できるようにする
実際の構築
VPNを張る
SoftEther VPN Serverを使った拠点間VPN。これはまぁ色んな所に参考情報が記載されているので簡単に。
- 実家側はNIC2枚刺しのCentOSに
SoftEther VPN Server
のVPNサーバを用意- 仮想HUBを作成し、2枚めのethにブリッジするようにする
- これでこの仮想HUBへアクセスすると、実家のLANにL2接続できるようになる
USのRaspberryPiに
SoftEther VPN Bridge
をインストール- 仮想HUBを作成して実家の仮想ハブにカスケード接続を設定する。
tap
デバイスにローカルブリッジするように設定する。(ここではtap_jikka
とした)
この時点でうまくローカルブリッジが動いていれば、数百msec遅延のping、すなわち日本経由でのpingが返ってくるはず。
$ ping -I tap_jikka 8.8.8.8
ラズパイのネットワークの設定
IPアドレスを固定
/etc/dhcpcd.conf
で、下記行を追加して、eth0
とwlan0
のIPアドレスを固定する。
interface eth0 static ip_address=10.0.0.1/8 interface wlan0 static ip_address=192.168.50.111/24
udhcpd設定
DHCPサーバをインストールしてセットアップ。
udhcpd
をインストール。/etc/udhcpd.conf
をデフォルトの設定を参考にしながら編集。
start 10.0.0.2 #default: 192.168.0.20 end 10.0.0.254 #default: 192.168.0.254 option subnet 255.0.0.0 interface eth0 #default: eth0 opt dns 8.8.8.8 opt router 10.0.0.1 option domain local option lease 864000 # 10 days of seconds
- 自動起動とかを設定
# systemctl enable udhcpd # systemctl restart udhcpd
ルーティングやNATの設定
/etc/rc.local
のexit 0
より前に下記記載を追加する。
これにより起動時にこれらのコマンドが実行され、再起動後も有効になる。
# パケット転送を許可 echo 1 > /proc/sys/net/ipv4/ip_forward # 実家サーバへのアクセスは、常にUS側のゲートウェイを通るようにスタティックルートを設定 jikka_ip=$(ping <実家サーバドメイン> | head -n1 | awk 'BEGIN{FS="\\(|\\)"}{print $2}') route add -host ${jikka_ip} gw 192.168.50.1 wlan0 # iptablesで転送の許可と、10.0.0.0/8 ネットワークへのIPマスカレード設定 iptables -I FORWARD -j ACCEPT iptables -t nat -I POSTROUTING -s 10.0.0.0/8 -j MASQUERADE
ここまでで、eth0
に繋がっている装置からインターネットに出ていこうとすると、10.0.0.1
を経由して、192.168.50.1
のルータ経由での通信となる。
ここでデフォルトゲートウェイを下記コマンドで変更すると、日本のルータ192.168.0.1
からインターネットに出ていくようになる。
# route add default gw 192.168.0.1 tap_jikka # route del default gw 192.168.50.1 wlan0
Homebridgeで切り替えできるようにする
HomebridgeはApple HomeKitの装置を模倣するオープンソースプロダクト。 これを使って電球と同じような感じでiPhoneから切り替えられるようにする。
Homebridgeは導入済みとする。
- cmdswitch2プラグインを導入する。
# npm -g install homebridge-cmdswitch2
- config.json を編集する。
on_cmd
には日本ルータをデフォルトゲートウェイにする設定を入れる。off_cmd
にはUSルータをデフォルトゲートウェイにする設定を入れる。また、VPNサーバへのスタティックルートが落ちる事があるので、ここで改めて追加するようにする。state_cmd
には、日本ルータを向いているときに終了コード0を返すようなコマンドを設定する。
{ "platform": "cmdSwitch2", "name": "JP-US switch", "switches": [ { "name": "JP net", "on_cmd": "sudo sh -c 'route add default gw 192.168.0.1 tap_jikka; route del default gw 192.168.50.1 wlan0; true'", "off_cmd": "sudo sh -c 'route add default gw 192.168.50.1 wlan0; route del default gw 192.168.0.1 tap_jikka; true'", "state_cmd": "ip route | grep default | grep jikka", "polling": true, "interval": 5 } ] }
これでHomebridgeをrestartするとこんな感じにiPhoneに表示されるようになり、切り替えられるようになる。
Apple TVリモートを使えるようにする
この構成だとApple TVは10.0.0.0/8
のネットワークにあり、iPhoneは192.168.0.50/24
のネットワークにあるので、Apple TVからのBonjourのマルチキャストDNS配信がiPhoneから見えないことになる。iOSにはAppleTVのリモコンとして動く機能があるが、この機能はBonjourに依存しているため、このままでは使えないことになる。
Bonjourの実装のひとつであるAvahi-daemonがRaspbianにはプリインストールされており、これのreflector機能を使って、プロキシとして機能して他のネットワークに伝播させることができる。
設定は、/etc/avahi/avachi-daemon.conf
のenable-refrector
をyes
にして有効にすればOK。
enable-reflector=yes
ただしこれだけでは10.0.0.0/8
への経路がiOSからは分からないので、家のルータにLAN側のスタティックルートを設定してやる必要がある。うちのASUSのルータだとこんな感じ。
複数インタフェースのサーバでHomebridgeがうまく動かないときの対処
TL;DR
config.json
の一番上の階層に、mdns
プロパティを作って、HomebridgeにつなげるiOSデバイスが居るネットワークに繋がっているインターフェースに割りあたっているIPアドレスを指定してやる。
{ "bridge": { "name": "Homebridge", "username": "CC:22:33:44:55:66", "port": 51826, "pin": "031-45-155" }, "mdns": { "interface": "192.168.50.123" ←ココ }, .... }
詳細
RaspberryPiで、VPNサーバとHomebridgeをセットアップしようとしたところ、eth0とwlan0を両方使うと、wlan0側のネットワークからHomebridgeが見えなくなる現象が発生した。
avahi-browse -a
でデバイスのアドバタイズがどうなっているのかを検索すると、Homebridgeのデバイスはeth0にしか流れていない。
どうやらデフォルトだと、先頭(?)のネットワークにしかmDNSのアドバタイズをしてくれないようで、eth0側にしか情報が流れていないらしい。
解決法
ソースを掘ると、配信はmulticast-dns
モジュールでやっている事がわかる。
multicast-dns
のコードを見ると、UDPのリスンはココでやっているので、interface
オプションにインターフェースを示すIPを与えればいいことがわかる。
ここにオプションを渡すための変更が、このコミットで行われていたので、それに従って、config.json
に設定を入れることで、うまく接続できるようになった。
Amazon Echo Wall Clock買ってみた
今年9月のイベントで発表されたAmazon Echo Wall Clockが発売されたのでポチってみたやつが届いた。
付属品はペラいマニュアルと単3電池4本。電池はAmazon Basicのものだった。
デザインはシンプルで、文字盤がカバーで覆われておらず、むき出しになっているタイプの時計。
電池をセットして、マニュアルにかかれている通り、Alexaに「Setup Echo Wall Clock」というと、裏面の青いボタンを押すように言われる。
言われるがままに青いボタンを押すと文字盤中央のLEDが光り、ペアリング状態になる。しばらくするとAlexaがペアリングが完了したことを知らせてくれる。
この時計の機能は、普通の掛け時計に加えて下記の2つの機能しかない。
- 時刻を自動で合わせる
- タイマーが動いている場合、残り時間をLEDで示す
つまり時計だけではAlexaの操作もできないし、スピーカーにもならないということになる。
Alexaを使って5分タイマーを設定すると、下記のように0時から1時までの間のLEDが光り、残り時間が5分間であることを示してくれる。
残り時間が1minを切ると下記のように一周分を使ってカウントダウンしてくれる。
機能としては非常に少ないが、現在Alexaの一番の利用用途がタイマー機能なので、十分ペイすると考えている。 また、サマータイムがあるアメリカでは、時刻を自動で合わせてくれる時計は非常にありがたい。電波時計も試してみたが、家のあたりは電波が良くないようでうまく動かなかったので、これは嬉しい。
単3電池を4本も使うのはちょっと気になるところではある。使用頻度にもよると思うが、あまりに電池の持ちが悪かったりするとちょっと悲しい。。。 #初代ゲームボーイを彷彿させる。。。
また、日本に持っていけばそのまま動きそうなので、日本での発売もそれほど遠くないのではないだろうか?
Whole Foods Marketで生牡蠣Get
Wholefoods Marketの生鮮食品売り場カウンターで、生牡蠣が殻付きで1個1ドルで売られているのを発見した。
生牡蠣は好物なので生で食べれるか聞いてみたところ大丈夫らしい。
4個ほど買ってみた。殻は剥くか聞かれたので剥いてほしいと頼んだところ、お店で出てくるような氷満載のバットに並べて渡された。
Wholefoods Market内にはバーコーナーも設けられているので「そこのバーで食べていってもいいよ」と至れり尽くせり。
家まで持ち帰って、ポン酢をかけて白ワインと頂く。身はしっかりしているし、以前近所のシーフード屋で食べたときのような消毒液の匂いもしない。非常に良いものを見つけた。
夏はバーベキューで焼いても良さそうだ。
なお、今の所食中毒の症状は出ていない。。。
D&Dやコピペでファイルアップロードできるtextareaをサクッと作る
GithubやQiitaなんかで使えるような、使い勝手の良い画像やファイル添付のTextareaをサクッと作った
使ったライブラリは Inline Attachement。 今回はレガシーWebAppに使ったので、JQueryで実装。
設定はドキュメントに掲載されているが、実はここに書かれている以上に拡張性があるので、コード自体を読むことをおすすめする。これによりやりたかったことは全て実現できた。
やりたかったこと
どんなファイルでも添付できるようにしたい
デフォルトだと画像ファイルに制限されているが、どんなファイルでも受け付けるようにしたかった。
コードを読んで、allowedTypes: ['*']
とすれば良いことがわかったのでそのようにした。
アップロードされたファイルの名前が、サーバサイドでわかるようにしたい
デフォルトだと、サーバサイドから見えるファイル名は、image-タイムスタンプ.拡張子
となり、もとのファイル名がわからない。
ドキュメントに記載は無いが、remoteFilename
というプロパティに関数を入れてやると、引数にファイルオブジェクトを渡してくれるので、ファイルオブジェクトの内容を使ってファイル名を作成して返してやることで、サーバサイド側ではそのファイル名で見える。
例えば下記のようにすると、もともとのD&Dされたファイル名がサーバサイドに送付される。
remoteFilename: (file)=>{return file.name}
ファイルの種類によって、埋め込まれるコードを変えたい
Markdown形式で入力するテキストエリアだったので、ファイルの種類によって埋め込まれるコードを修正したかった。
![image.png](url to image) ←画像ならこっち [document.docx](url to file) ←ドキュメントならこっち
埋め込まれるコードは、urlText
プロパティで静的に設定できるが、このプロパティに関数を与えることで好きなデータに編集できる。
ファイルの種類はサーバサイドで判定したMIMEをJSONに入れて返し、これを読んで画像ファイルか普通のファイルかどうかの判別がつくようにしてある。
また、リンク文字列ももともとのファイル名にしたかったので、同じくサーバサイドからオリジナルのファイル名を返して埋め込むようにしている。
urlText: (filename,result)=>{ if(result.mime.match(/image/)) { return `![${result.orig_file_name}](${filename})` } else { return `[${result.orig_file_name}](${filename})` } }
マウスオーバしたときにドロップできる感じを出す
ファイルをドラッグしてきたときに、textareaに点線で枠線を表示することで、ドロップできますよー感を出した。
textarea.dragover { border: dashed 6px #ccc; padding: 12px 6px 0px; }
$('textarea').on('dragenter dragover', function() { $(this).addClass('dragover') }) $('textarea').on('drop dragleave dragend', function() { $(this).removeClass('dragover') })
最終型
JSはこんな感じ。
$(function(){ // ファイル貼り付け $('textarea').inlineattachment({ uploadUrl: 'upload_attachment.php', allowedTypes: ['*'], remoteFilename: (file)=>{return file.name}, urlText: (filename,result)=>{ if(result.mime.match(/image/)) { return `![${result.orig_file_name}](${filename})` } else { return `[${result.orig_file_name}](${filename})` } } }); $('textarea').on('dragenter dragover', function() { $(this).addClass('dragover') }) $('textarea').on('drop dragleave dragend', function() { $(this).removeClass('dragover') }) });
CSSはこんなん。
textarea.dragover { border: dashed 6px #ccc; padding: 12px 6px 0px; }
PHPはこんなもんで。
$response = array(); $upload_directory = "/data/"; if (isset($_FILES['file'])) { $file = $_FILES['file']; // MIMEタイプの取得 $finfo = new finfo(FILEINFO_MIME_TYPE); $mime_type = $finfo->file($file['tmp_name']); // ファイルのID(=MD5ハッシュ)を計算 $file_md5 = md5_file($file['tmp_name']); // ファイルの移動 move_uploaded_file($file['tmp_name'], $upload_directory . "/" . $file_md5); $response['filename'] = "file_get.php?id=".$file_md5; $response["mime"] = $mime_type; $response["orig_file_name"] = $file["name"]; } else { $response['error'] = 'Error while uploading file'; } echo json_encode($response);
BIABをAnovaでやってみた
個人でのビール自家醸造のやり方にBIAB(Brewing in A Bag)というのがある。これはビール醸造の最初の手順である麦芽の糖化(マッシング)にて、袋に麦芽を入れてそれをティーバックの要領で煮出すというやり方になる。使う鍋の量が少ないので、利便性が高く人気がある。
マッシング中は1時間以上に渡って温度を一定に保つ必要があるので、通常は定期的に温度を確認して、必要に応じて火にかけたりする必要がある。
要するにある程度の時間、水温を一定に保てばよいということなので、みんな大好き低温調理器Anovaが使えるんじゃないか?と思い、実際にやってみた。
Anovaは水を吸いこんでヒータで温度を上昇させ、水を吐くという仕組みになっている。Anovaに麦芽が吸い込まれるのはあまりよろしくなさそうなので、麦芽の入った袋の外側にAnovaを取り付ける。
今回は5galを仕込むので、その1.5倍の7.5galの水で煮出すことにした。
まずは鍋に水を張り、バッグとAnovaを取り付けてスイッチ・オン。マッシング温度は65℃とした。水の容量が大きいためAnovaだけの熱量だとパワー不足のため、最初は電熱コンロも併用する。
65℃になった時点で麦芽を投入。最高水位線を超えてしまうことが懸念だったが、特に問題なかった。
初めは非常に順調だったが、30分ほど経ったときに水量不足の警告音を出してAnovaが停止するようになってしまった。もちろん水量不足になるほど、鍋内の水は減っていない。誤検知かと思い、何度かスイッチをオンにしてもすぐに止まってしまう。
試行錯誤の上、Anovaの水を吸い込む口の部分にバッグと麦芽がへばりついて、水がうまく吸えなくなったので、水量不足という表示をしているのではないかと思いあたった。そこで、Anovaの水を吸い込む口のあたりにトングを突っ込んでバッグをブロックしてやったところ、うまく動作するようになってくれた。
次回は水を吸い込む口のところに、何らかのつっかえ棒などを取り付けて、バッグがへばりつくようなことが無いように工夫してみるつもり。
とにかくマッシングの工程は、多少エラーがでてまごついた部分はあったが、ほぼ全自動で完了させることが出来た。 比重も1052でほぼ狙い通りまで行けた。