Chintax Sugar

個人用技術メモとか

IRKit で家電を操作してみた

巷で噂になっている IRKit、買ってみたのでいろいろ試してみました。
ちなみに以前から存在はなんとなく知っていたのですが、Rebuildfm のスポンサー枠で紹介されたのが決め手になって購入に踏み切りました。

IRKit is 何

赤外線で操作できる家電をネット経由で、スマホタブレットから操作できるようにするものです。 今回は基本的な使い方と、少し応用した使い方を紹介します。

準備~設置

必要な物は以下の通り。

  • IRKit 本体 (Amazonで購入可。\7,700)
  • 無線LAN環境
  • MicroUSBケーブル (本体の給電用)

まずは本体を買わないと始まりません。Amazon でポチー。
届いた箱の中身はこんな感じ。

f:id:sunlight0915:20151215222126j:plain

ケーブル等ごちゃごちゃした物は何も入っておらずシンプルです。
本体に MicroUSBケーブルを挿して給電してあげれば設置完了。

iPhone から家電を操作

本体に同梱されている説明書の通り、AppStore で IRKitシンプルリモコン をダウンロードします。
アプリを起動するとウィザード形式で設定が進みます。直感的に設定できるので詳細は省略します。
初期設定が終わった後は使いたいリモコンの信号を登録していきます。
こんな感じで

f:id:sunlight0915:20151215225105j:plain

本体にリモコンの信号を受信させてボタンを追加します。
出来上がった画面がこちら。とりあえずよく使いそうなものを登録してみました。

f:id:sunlight0915:20151220145605p:plain

エアコンON ボタンを押してみると…電源がついた!
iPhoneWiFi を OFF にして外部のネットワークから繋いでもちゃんと操作できます。これはすごい。

位置情報を利用

サードパーティー製のアプリもいくつか公開されています。
例えばこの Geo IR を使えば位置情報を利用して家に近づいたタイミングでエアコンの電源をON!なんてこともできそうです。

f:id:sunlight0915:20151220150638p:plain

なお寒くて外に出られなかったので試してません(テヘペロ

コマンドプロンプトから操作

IRKit はWebサーバーとしての機能を持っているため、HTTPリクエストを直接投げて操作することが可能です。 なので CURL を使えば Windowsコマンドプロンプトからもリモコン操作を行うことができます。

手順

1.IRKit のIPアドレスを取得

方法はいくつかあると思いますが、今回はルーターの管理画面から接続クライアントの一覧を見て調べました。 以下では仮に「192.168.11.123」としておきます。

2.送信したい信号の JSON を取得

本体にリモコンから信号を受信させた後、以下のコマンドを実行します。

curl -i "http://192.168.11.123/messages" -H "X-Requested-With: curl"

正しく取得できると以下のように信号データの JSON が返ってきます。data の部分は長いので省略。

HTTP/1.0 200 OK
Access-Control-Allow-Origin: *
Server: IRKit/3.0.0.0.g85190b1
Content-Type: text/plain

{"format":"raw","freq":xx,"data":[xx]}
3.取得した JSON を使って信号を送信

以下のコマンドを実行します。コマンドプロンプトから実行する場合、JSON 内のダブルクォーテーションはエスケープする必要があるので注意。

curl -i "http://192.168.11.123/messages" -H "X-Requested-With: curl" -d '{\"format\":\"raw\",\"freq\":xx,\"data\":[xx]}'

カチャカチャ…ッターン!すると、無事任意の信号を送信することができました。
こうやって操作できるのは楽しいですが、iPhone から操作したほうが確実に早いです。

タイマー設定

IFTTT と連携することでタイマー機能を実現することが可能です。
毎朝7時にエアコンをONにする、ということをやってみようと思います。

手順

1.IFTTT のアカウントを作成(ない場合)
2.ログインして「My Recipes」から「Create a Recipe」を選択
3.トリガーに「Date & Time」を選択
4.トリガーの種類から「Every day at」を選択
5.時刻を指定
6.アクションに「Maker」を選択
7.アクションの種類から「Make a web request」を選択
8.リクエストの詳細を記入

URL : https://api.getirkit.com/1/messages
Method : POST
Content Type : application/x-www-form-urlencoded
Body : clientkey=clientkey&deviceid=deviceid&message={“format”:”raw”,”freq”:xx,”data”:[xx]}

なお clientkey と deviceid はまず clienttoken を取得して、それをキーとすることにより取得できます。

clientkey 取得

curl -i "http://192.168.11.123/keys" -d '' -H "X-Requested-With: curl"

clientkey deviceid 取得

curl -i -d "clienttoken=xx" "https://api.getirkit.com/1/keys"
9.Create Action を選択し、レシピの説明文を書けば完成

実際に試してみたところ、2分ほどラグがありましたが無事指定の時刻にリモコン操作を行うことができました。

注意点、気になることなど

・設置位置は工夫が必要
→当然ながら間に障害物があったりすると信号が対象の機器に届かないので、使いたいボタンは一通りテストを行う必要があります。

・アプリは iOS 端末でしか使えない?
Android アプリもあるようです。IRKitシンプルリモコン

・自分でアプリは作れる?
SDKが公開されています。IRKit iOS-SDK

まとめ

今のところエアコン、テレビのONOFFしか主に使っていませんが、もっと応用すればいろいろなことができそうです。
例えば先日 Netflix が寝落ち検出機能を備えたリモコン靴下を発表していましたが、それと似たようなことをして寝落ちしたら部屋の照明をOFFにする、なんてこともできるかもしれません。

比較的安価、かつ導入が非常に容易ですので、是非お買い求めになって試してみてはいかがでしょうか。

Roslyn のコード解析機能を試してみる

Roslyn とは

Visual Studio 2015 から追加された新機能の一つです。
Roslyn を使うことで、コードを解析してエラーや警告を出したりコードの修正提案を行う機能を自作して追加することができます。
なおこの記事を書くにあたって neue先生の記事 をめっちゃ参考にしました。いつもお世話になります。

今回の題材

時々見かけるイケてないコードの1つに

if (collection.Count() > 0) { ~ }

のようなものがあります。これはAny()でいいですね。
ReSharper が入っている環境であれば警告が出るのですが、ただの Visual Studio では何も出ません。
今回はこのコードに警告が出るようにし、さらに修正提案を出すところまでをやってみようと思います。
ReSharper って何よ!という方は 真雪先生のスライド あたりを参考にどうぞ。

手順

  1. テンプレートから「Diagnostic with Code Fix」を選択し、新規プロジェクトを作成。
  2. Analyzer(コード解析)用クラスを作成
  3. CodeFixProvider(修正提案)用クラスを作成
  4. コンパイルしできたものを配布

これだけです。簡単そうですね?
次から実際のコードを見ていきます。

Analyzer

プロジェクトを作成した時点で必要なプロジェクト、ファイルは揃っているので後はその中身を書き換えていくだけです。
まずは Analyzer、コード解析用のクラスの中身を見てみましょう。

using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace UseAnyMethod
{
    [DiagnosticAnalyzer(LanguageNames.CSharp)]
    public class UseAnyMethodAnalyzer : DiagnosticAnalyzer
    {
        public const string DiagnosticId = "UseAnyMethod";
        internal const string Title = "Use method Any()";
        internal const string MessageFormat = "Use method Any()";
        internal const string Category = "Refactoring";

        internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true);

        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

        public override void Initialize(AnalysisContext context)
        {
            //SyntaxKindを今回検出したいものに変更
            context.RegisterSyntaxNodeAction(Analyze, SyntaxKind.GreaterThanExpression);
        }

        private static void Analyze(SyntaxNodeAnalysisContext context)
        {
            var syntax = (BinaryExpressionSyntax)context.Node;

            //左辺がCountメソッドかどうかを判定
            var leftExpressionName = ((syntax.Left as InvocationExpressionSyntax)?.Expression as MemberAccessExpressionSyntax)?.Name?.NormalizeWhitespace().ToFullString();
            if (leftExpressionName == null || leftExpressionName != "Count") return;

            //右辺が0かどうかを判定
            var rightValue = (syntax.Right as LiteralExpressionSyntax)?.Token.Value;
            if (rightValue == null || !rightValue.Equals(0)) return;

            var diagnostic = Diagnostic.Create(Rule, syntax.GetLocation());
            context.ReportDiagnostic(diagnostic);
        }
    }
}

重要なのはInitializeメソッドだけです。
ここで警告を出したい「~.Count() > 0」の検出を行うためのコードを書きます。
しかし書きます、といっても正直テンプレートにある記述だけでは何を書けばいいのか全くわかりません。
そこで役に立つのがneue先生の記事にもある「Roslyn Syntax Visualizer」です。
これを使えば構文をツリー上に可視化して見ることができます。神ツール

f:id:sunlight0915:20141208092915p:plain

構文を選択すると…

f:id:sunlight0915:20141208092947p:plain

こんな感じで表示されます。

ここまでで一度デバッグをしてみます。その結果、

f:id:sunlight0915:20141208093157p:plain

無事警告が表示されました。

CodeFixProvider

続いて CodeFixProvider、コードの修正提案用のクラスの中身を見ていきましょう。

using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace UseAnyMethod
{
    [ExportCodeFixProvider("UseAnyMethodCodeFixProvider", LanguageNames.CSharp), Shared]
    public class UseAnyMethodCodeFixProvider : CodeFixProvider
    {
        public sealed override ImmutableArray<string> GetFixableDiagnosticIds()
        {
            return ImmutableArray.Create(UseAnyMethodAnalyzer.DiagnosticId);
        }

        public sealed override FixAllProvider GetFixAllProvider()
        {
            return WellKnownFixAllProviders.BatchFixer;
        }

        public sealed override async Task ComputeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;

            //該当のNodeを検索
            var binaryExpression = root.FindNode(diagnosticSpan) as BinaryExpressionSyntax;

            //CodeActionを登録
            var codeAction = CodeAction.Create("ReplaceTo Any", c => ReplaceToAny(context.Document, root, binaryExpression, c));
            context.RegisterFix(codeAction, diagnostic);
        }

        private static Task<Document> ReplaceToAny(Document document, SyntaxNode root, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken)
        {
            //Countメソッドを使用している個所を検索
            var countSyntax = binaryExpression.DescendantNodes().OfType<IdentifierNameSyntax>().First(x => x.ToFullString() == "Count");
            //CountをAnyに置き換え
            var newSyntax = binaryExpression.Left.ReplaceNode(countSyntax, SyntaxFactory.IdentifierName("Any"));
            //比較式を左辺だけに置き換え
            var newRoot = root.ReplaceNode(binaryExpression, newSyntax);

            var newDocument = document.WithSyntaxRoot(newRoot);
            return Task.FromResult(newDocument);
        }
    }
}

ここでも重要なのは1点だけ、ComputeFixesAsyncメソッドの実装だけです。
やりたいことは「~.Count() > 0」の「~.Any()」への置き換えです。
コードの実装はひたすらトライアンドエラーを繰り返すしかありません。。
これをデバッグしてみると、

f:id:sunlight0915:20141208093026p:plain

こうなって、

f:id:sunlight0915:20141208093208p:plain

こうじゃ。(不要なスペースが残るのは謎…)

課題

うまくいったように見えるのですが、このプログラムには致命的な欠陥があります。
実はコード解析時に Count() メソッドのクラスを特定できていません。
本当は System.Linq.Enumerable の Count() メソッドだけを検出したいのですが、現状適当に作った Hoge クラスの Count() メソッドであっても警告が出てしまいます。
どなたか解決策ご存知ないですかね…。

解決できたら追記します。

まとめ

今回作成したものはプロジェクトの参照に追加したり、VSの拡張(VSIX)として配布することができます。
プロジェクトに含めておけば開発メンバーのローカル環境に依存せずに警告を表示することができるので、なかなか使えそうな機能ではないでしょうか?

なお冒頭にも書きましたがこの機能は「Visual Studio 2015」から使用可能で、現在 VS2015 は Preview 版のみが公開されています。
Azure の仮想マシンを使うと VS2015 が入った開発環境がサクッと用意できるのでオススメです。Azureゴイスー。

素人が Surface Pro でお絵描きしてみました

この記事は社内 Advent Calendar 12/9 用のゆるふわ記事です。
基本的に社外非公開のなんでもあり Advent Calendar ですが、公開されている記事も一部存在します。例えばこちらがそうです。
私の記事にも社外秘な内容は含まれないのでここに書き連ねることにします。

きっかけ

Surface Pro と付属のペンを使うと手描き感覚でお絵描きができるという話をよく聞いていたので、いつかやろうと思っていたのを実行に移しました。
しかしいざ描こうと思うとどのソフトを使ったら良いかわからなかったので、フリーのソフトをいくつか試してみました。使用したソフトは以下の3点です。

  • MSPaint
  • NekoPaint
  • FreshPaint

これらについて素人なりに感じた特徴を挙げます。
(本当はもっといろいろ試したかったのですが時間の都合上これが限界でした…)

準備

ドライバ

Surface Pro 付属のペンはなんと1024段階の筆圧レベルを検知してくれるのですが、ソフトによってはドライバのインストールが必要なものがあるそうです。
あらかじめワコムのサイトからドライバをダウンロードしてインストールしておきましょう。
入手先: Wacom Feel Driver | Wacom Americas

ディスプレイ表示サイズ

Surface Pro では150%が推奨サイズになっていますが、このままだとペンの検知がずれることがあるそうです。
コントロールパネル→デスクトップのカスタマイズ→ディスプレイ から表示サイズを100%に変更します。

題材

私は絵心が全くないので、某後輩が5秒くらいで描いたこちらのモケケを参考にします。

f:id:sunlight0915:20131208193508p:plain

これを元に実際にお絵描きを進めます。

MSPaint

f:id:sunlight0915:20131208200733p:plain

言わずと知れた Windows 標準ペイントソフトです。 出来上がった作品がこちら。

f:id:sunlight0915:20131208202336p:plain

クオリティはお察しです。

特徴

  • シンプルなので操作が簡単
  • ブラシによっては筆圧検知可能(今回は油彩ブラシを使用)
  • 線の描き終わりをきれいにするのが難しい
  • レイヤーは当然ないので、描き直しが大変

最初なので(?)残念感は否めませんね。次いきましょう。

NekoPaint

f:id:sunlight0915:20131208203322p:plain

公式: NekoPaint Project
シェアウェアっぽいのですが現在無期限で試用できます。作品がこちら。

f:id:sunlight0915:20131208203535p:plain

さっきのとほとんど一緒ですね。で、でも使用感は結構違いますよ!

特徴

  • ブラシサンプルの種類が豊富 カスタマイズも可能
  • 大半のブラシで筆圧検知可能
  • 線の描き終わりがスムーズ 実際の筆感覚に近い
  • (あんまり使わなかったけど)レイヤーも使用可能

全体的にMSPaintを高機能にしたような感じです。他にもいろいろ機能があるようです。

FreshPaint

f:id:sunlight0915:20131208205226p:plain

公式: Fresh Paint – the canvas for your big ideas
MS製のストアアプリです。UIがおしゃれですね。
作品はこちら。

f:id:sunlight0915:20131208205831p:plain

今までの2作品とは雰囲気が違う気がします。

特徴

  • ごちゃごちゃした細かい機能がない
  • 下地になる紙の種類が選択できる
  • 筆の種類が豊富(水彩絵の具、鉛筆、クレヨン など)
  • 絵の具の質感の再現度が高い
  • キャンパス上で乾いていない絵の具が混ざる(扇風機アイコンで乾かせる)
  • レイヤー機能はない

なかなか操作方法が掴めなかったのですが、慣れると実際に紙と絵の具を使って描いているようで楽しいです。さすがMS製。

~番外編~ Blend for Visual Studio 2013

f:id:sunlight0915:20131208211603p:plain

これは Surface Pro である必要は全くないのですが、おまけとして載せておきます。
その昔聴いたLTに触発されて描きました。作品はこちら。

f:id:sunlight0915:20131208211948p:plain

曲線がきれいに描かれてますね。 描き方など詳しくはLTの記事をご一読ください。

まとめ

お絵描き自体は慣れないので大変でしたが、手描き感覚で描けるというのは確かです。
今の時期であれば年賀状を手描きのイラストで作りたい場合などに最適ではないでしょうか。
タブレットでお絵描きを始めてみたい、という方の参考に少しでもなれば幸いです。

開設しました

ブログを開設しました。

社内 Advent Calendar 用の記事を公開するためのちょうどよい場所が社内になかったので、はてなブログを使用することにしました。

ゆくゆくは技術的なネタとかを書いていくブログにしたい気持ちもなくはないです。