0

irkitコマンドで家の外からIRKitを操作する

前:赤外線学習リモコンIRKitのrubygemを作った


irkit gemに付属のirkitコマンドは、Internet APIも使えるので家の外からIRKitを操作できます。
解説しておく。

インストール

% gem install irkit
% irkit --help

デバイスをirkitコマンドに登録する

最初のこの設定だけはIRKitと同じLANの中にいなければならない。

% irkit -device:add デバイス名

なお2つ以上IRKitを持っている場合は、-addressでIPアドレスを指定すればそれぞれ保存できる。
% irkit -device:add デバイス名 -address 192.168.1.123

登録されているか確認

デバイスリストと赤外線データのリストが見れる。LAN内のIRKitもbonjourで探す。
% irkit -list

なおこのデータはホームディレクトリ直下にjson形式で保存されている。
Ruby使ってるならirkit gemをrequireすればこのように取り出せる。普通学習は1回しかしなくて、発射ばかりするはずなので、学習とデータ管理はirkitコマンドに任せてもいいと思う。
require 'irkit'

IRKit::App::Data["IR"] ## 赤外線データ
IRKit::App::Data["Device"] ## デバイスデータ
もちろんRuby以外の言語でも、ホームディレクトリ下の.irkit.jsonを直接読める。


外に出る

ここからはIRKitを家に置いて、外にでても操作できる。

赤外線を学習する

% irkit -get 赤外線データ名 -device デバイス名


赤外線を発射する

% irkit -post 赤外線データ名 -device デバイス名


おわり。

0

MakezineのRSS全文

jpとcomそれぞれ、全文配信されてなくて記事読むのがクソ面倒臭かったのでpipes作った

Pipes: Make: fullfeed

Pipes: Make: Japan fullfeed

1

赤外線学習リモコンIRKitのrubygemを作った

IRKitはよく「iOSから操作できる赤外線リモコン」と説明されるけど、そのAPIはHTTPなのでiOS以外からももちろん使えます。
というわけでRubyから使いやすいようにした。

ソースコードはgithubにある。不具合等はissuetwitterにお願いします。

irkitコマンドという便利ツールも入れておいた。
bonjourでLAN内のIRKitを発見する機能や、赤外線データのgetとpost(と保存)、家のLANの外からIRKitを操作するInternet API関連が実装されているので
プログラムを書かなくてもirkit gemをインストールすればすぐIRKitが使える。


なんでこういうツールが付いているかというと、デバイス系はコマンド一発で全部実行できるテストコードが書きにくい部分がかなりあって、しょうがないから各機能をテストしやすい実行可能コマンドを作るぐらいしかない。

IRKit


先週買った。うちのエアコンの赤外線はデータが長くて、既存の学習リモコンで学習できない事が多いんだけどIRKitだとokだった。
置き場所もカーテンレールの上に適当に置いてるだけなんだけど、エアコンの赤外線受光部は死角のはずなのに壁で反射してるのかちゃんと届いてる。よくできてると思う。


インストール

https://rubygems.org/gems/irkit
実行にはRuby2.0.0以上が必要。1.8.7は非サポート。(1.9.3でももしかしたら動くかもしれない)
% gem install irkit

なおubuntuやdebianでは事前にavahiをインストールしておく必要がある。これはLAN内のIRKitを見つけるのにbonjourを使っている為。
% sudo apt-get install libavahi-compat-libdnssd-dev

使い方


https://github.com/shokai/ruby-irkit#usageに書いた。サンプルコードもある。

BonjourでLAN内のIRKitを見つけて、赤外線が読み書きできる。
require 'irkit'

irkit = IRKit::Device.find.first
ir_data = irkit.get_messages

irkit.post_messages ir_data

また、Internet APIというプロキシを使うとLAN外からも操作できるんだけど、そのためのclientkeyやdeviceid等の発行もできる。

くわしくはgithubのREADMEとサンプルコード見てほしい。


irkitコマンド

gemをインストールすると実行可能コマンドも付いてくる。
普通のHTTP APIとInternet API両方とも使える。
コマンドからリモコン操作できるので、crontabで朝あらかじめ暖房をつけるとかできる。
エアコンのリモコン探すよりCUI使ったほうが速いので、shellの履歴から「暖房」で検索して「irkit -post 居間エアコンOFF」を探してenter押せば暖房が消せる。

% irkit --help
% irkit --get tv_on # tv_onという名前を付けて赤外線データを保存
% irkit --post tv_on # tv_onを赤外線発射
% irkit --list # デバイスやデータのリストを見る
% irkit --post tv_on --address 192.168.0.123 # IPアドレスを指定してtv_on赤外線発射
% irkit --device:add myhouse # myhouseという名前でInternet APIのclientkey等を保存
% irkit --device myhouse --post tv_on # 自宅のIRKitをLAN外からtv_on発射

1

895円の超小型Ardunoクローン DigiSparkを買った

とにかく小さくて安いのに、ほぼArduinoとして使える。
そしてズボンのコインポケットに入れて持ち歩けるので電車内hackに便利。

DigiSpark


ソースコードはここに置いておいた。
デジタル出力・アナログ出力・アナログ入力・Mac上のRubyとのUSB通信を試した。
https://github.com/shokai/digispark-study

「webサービスと連動したちょっとしたハードウェア」にはArduinoはオーバースペックだと思うので、DigiSparkちょうどいいと思う。





普通のArduinoとの違い

詳しくは digispark:tutorials:basics [Digistump Wiki]

多少制限はある。
  • IOピン数が6本、PCとUSB通信する場合は4本しか無い
  • プログラムを書き込めるメモリ領域が6Kbyteしかない
  • PCからは仮想シリアルポートではなくただのUSB-HID(ヒューマンインタフェースデバイス)として認識される

内部のソースコード読んだらすごかった。
DigiSparkはマイコン上のプログラムを工夫する事で部品点数を減らし、価格と基盤サイズを抑えている。

ここの一番下にある回路図を見ればわかるが、DigiSparkはATTiny85という安い8ピンマイコンと、抵抗・ダイオード・三端子レギュレータしか使っていない。部品点数が少なく基板も片面実装なので安い。

ATTiny85にはUSB機能は付いていないが、micronucleusというDigiSparkのファームウェアがArduinoブートローダとソフトウェアUSBを同時に実装しているから、たったこれだけの部品でArduinoになれる。

micronucleusはV-USBというUSB1.1のソフトウェア実装を取り込んでいる。

V-USBは、10年ぐらい前に流行った「12MHz以上のAVRマイコンならUSB-HIDになれる」というhackを綺麗に書きなおしてオープンソースで公開されているライブラリ。

実際に使う上で一番大きい違いは仮想シリアルポートではなくUSB-HIDとして使わなければならない所だけど、これはDigiSparkを単体で使う場合は関係ないし、PCと通信させて使う場合もRubyならdigiusbというgemを使えば普通のシリアルデバイスの様に使える。
digiusbの実装を見ると普通にlibusbを使っているだけなので、他の言語でもたぶんなんとかなるんじゃないかと思う。

誰かnode.jsのC拡張くわしい人、digiusb npm作ってください


購入

注文して1週間ぐらいで届いた。

Digispark USB Development Board – Digistump

日本円でも決済できる。
単体で9ドル、現時点で895円。
発送方法は色々選べるけど安いUSPS First Class Package Insuredの965円にした。14+ daysって書いてあったけど1週間ぐらいで来た。

最低でもこのUSB Development Boardだけあれば良いが、シールドなども色々あるのでまとめていろいろ買った。
DigiSparkをUSBポートに接続し、PC/Mac上のソフトで自作プログラムを書き込めば動くので特に別途マイコン書き込み器等は必要ない。

他に頼んだもの

Stackable Headersはシールドを2階建以上積むる時に使う。
Starter KitはUSB Development boardにRGB Shield KitPrototype Shield Kitが付いたもので、壊した時の為にもう一枚DigiSpark欲しかったから買った。バラで買うより100円安い。
Temperature Sensor Shieldは1-wireで温度が計れる。


ボードへのプログラムの書き込み

DigiSpark用のIDEを使う。

Arduino IDEはJavaで実装されていて、Mac/PC/Linuxで使える。それにDigiSparkへの書き込み機能とDigiSprak用のマイコン側のライブラリを追加したものがこれ。

タイトルバーにArduino IDEって書いてあるけど、[ツール]→[書込装置]にDigiSparkが追加されている。
また、スイッチサイエンスが作って本家Arduino IDEに取り込まれた日本語化も有効になっている。


とりあえず使う

プログラムの書き込みはArduinoと同じを押すだけ。
しかしボード上にリセットボタンが無いのでUSBポートを抜き差しする事で代替する。
Arduinoのファームウェアは電源が入ってから数秒はプログラム書き込み待ち状態になり、特にプログラムが送られてこない場合は今持っているプログラムを実行するようになっている。

基板上のLEDを点滅させる


基板上にテスト用のLEDがあるが、基盤のリビジョンによりpin0にあったりpin1にあったりする。とりあえず500ミリ秒ごとに両方点滅させた。

led_blink.ino
bool led_stat = false;

void setup(){
pinMode(0, true);
pinMode(1, true);
}

void loop(){
digitalWrite(0, led_stat);
digitalWrite(1, !led_stat);
led_stat = !led_stat;
delay(500);
}


LEDをぼんやり点滅させる

analogWriteを使った。なおanalogWriteにはpinModeの設定はいらない(arduino.cppが勝手にやってくれる)


led_fade.ino
void setup(){
}

void loop(){
for(char i = 0; i < 26; i++){
analogWrite(0, i*10);
analogWrite(1, i*10);
delay(20);
}
for(char i = 25; i > 0; i--){
analogWrite(0, i*10);
analogWrite(1, i*10);
delay(20);
}
}


Macと通信する

Rubyでやる場合、libusbのラッパーのdigiusb gemをインストールする
% brew install libusb
% gem install digiusb
digitermという実行コマンドも付いている。


アナログセンサーを読んでMacに送る

analogReadしてUSBでMacに送る

SerialライブラリのかわりにDigiUSB.hを使う。delayもDigiUSB.delayにしないと通信できなくなる。
adb_usb.ino
#include <DigiUSB.h>

void setup(){
DigiUSB.begin();
}

void loop(){
DigiUSB.println( analogRead(1) );
DigiUSB.delay(100);
}

なおLEDを点滅させながらanalogReadしたら値がブレまくるけど、キャパシタを入れれば大丈夫だと思う(まだ試してない)

digitermで見る


センサーつないでないけどanalogReadは取れてる。


Rubyで受信する

adc_usb.rb
require 'digiusb'

spark = DigiUSB.sparks.first

loop do
recv = spark.gets.strip
puts "analog value: #{recv}"
end

digiusb gemは普通にIOっぽく使えるので、serialport gemからの移行も楽だと思う。


Macから基盤上のLEDを点灯・消灯する

今度はMacからDigiSparkに命令を送る。

‘o’が来たら点灯、’x’が来たら消灯するプログラムを書いた
usb_led.ino
#include <DigiUSB.h>

void setup(){
pinMode(1, true);
DigiUSB.begin();
}

void loop(){
if(DigiUSB.available()){
char recv = DigiUSB.read();
switch(recv){
case 'o':
digitalWrite(1, true);
break;
case 'x':
digitalWrite(1, false);
break;
}
}
DigiUSB.delay(10);
}

digitermを起動して、oやxを入力しenterキーで送信で操作できる。


RubyからLED点灯・消灯命令を送る


1秒ごとに点灯消灯

usb_led.rb
require 'digiusb'

spark = DigiUSB.sparks.first

led_stat = false

loop do
puts led_stat
spark.write( led_stat ? 'o' : 'x' )
led_stat = !led_stat
sleep 1
end


このように簡単に使えるし、安いし、ズボンのコインポケットにピッタリはいるから電車内hackに便利。
arduino_firmataのdigispark版を作ろうと思う。けど6Kbyteのプログラムメモリに入れるために機能を削らないとならないかもしれない。
node用のdigiusb npmも欲しい。

あと、AndroidとArduinoを接続したりした時も思ったけど、もうUSB上で仮想シリアルポート使うのやめたほうがいいんじゃないかと思う。DigiSparkのようにUSB-HIDならドライバいらないし、libusb使えば自作プログラムとマイコンの通信も簡単だし、シリアル通信を115200bpsとかいう速度で読み書きするのもなんかおかしい気がする。

0

JRuby+jnativehookでMacのキーボード・マウス入力を取得

JRubyでグローバルフックとかグローバルホットキーと呼ばれる、OSの機能を使う。

普通のホットキーはアプリがアクティブの時しかキー入力やマウス入力を取得できないが、jnativehookというjavaのライブラリを使うとアクティブじゃなくても取得できる。


コードはgistに置いた。
global keyhook with JRuby

下の方に書いたけどマウスはちゃんと取れるけどキーボードがshiftとctrlとcommandしか取れず、しかも全部shift扱いになる。
まあ今考えてる用途には十分なので別にいいか・・

jnativehookのインストール

jnativehook – A library to provide global keyboard and mouse listeners for Java. – Google Project Hosting
からJNativeHook-1.1.4.zipをダウンロードして解凍し、JNativeHook.jarをget

Macの場合
/Library/Java/Extensions/
にjarを置けばパスが通る。


アプリケーションにコンピュータの制御を許可する

Macの場合、グローバルフックへのアクセス権限をアプリに許可する必要がある。
システム環境設定から許可するけど、先にプログラムを動かさないとチェックボックスが現れないと思う。


プログラム書く

Ruby好きなのでJRubyで書く。
JRubyの場合includeでjavaのインタフェースをimplementできる。
examplesを参考に、キーボードとマウス両方を取得した。

hook.rb
require 'java'
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;

class KeyHook
include NativeKeyListener

def nativeKeyPressed(e)
puts NativeKeyEvent.getKeyText e.getKeyCode
end

def nativeKeyReleased(e)
puts NativeKeyEvent.getKeyText e.getKeyCode
end

def nativeKeyTyped(e)
puts NativeKeyEvent.getKeyText e.getKeyCode
end

end

class MouseHook
include NativeMouseInputListener

def nativeMouseMoved(e)
puts "#{e.getX}, #{e.getY}"
end

end

GlobalScreen.registerNativeHook
GlobalScreen.getInstance.addNativeKeyListener KeyHook.new
GlobalScreen.getInstance.addNativeMouseMotionListener MouseHook.new

loop do
sleep 1
end
すごいすっきり書けた。

なおマウスはクリックなども取れるけど省略した


動かす


% jruby hook.rb



マウスの動きはちゃんと取れた。
キーボード入力がctrlとshiftとcommandしか取れないし、全部shiftになる。
Javaのサンプルでもshiftしか取れないし、同じことをissueで質問してる人がいるのでバグだと思う。