古事連記帖

趣味のこと、技術的なこと、適当につらつら書きます。

Windows ストアに公開しているアプリが後から審査落ちした話

以前、位置情報共有アプリ「Mikaboshi」のお話をしました。

ayano.hateblo.jp

www.microsoft.com


これを公開してしばらく経ったある日、ふとアプリの更新をするべくデベロッパーセンターを開いたら、審査レポートが表示されていました。

f:id:ChiiAyano:20170310234134p:plain

10.2 Suspicious File Download

ストアポリシーで言う

10.2.3
望ましくないソフトウェアと悪意のあるソフトウェアに関する Microsoft の条件で定義されているマルウェアを、アプリに含めたり、アプリで有効にしたりすることはできません。

だと思うのですが、その辺あまり思い当たる節がなく、なんだろうなあ…というところ。
一つ考えられるのは、地図表示が WebView で、Google Maps を利用しているので、そのあたりだろうかと思ってはいます。
しかも期限内に申請しないと自動で取り下げられる上に、再公開にはメールで問い合わせろということが書かれています。こわい。

ひとまず何も考えずに次のバージョン 2.2 を更新申請しました。何かあったらまた記事書く予定です。


そういえば、最近は審査パスしたとかその辺の通知がメールで飛んできません。ちょっと困ってます。
これに気づくのもおとといとかそんな感じでした。ちょっとー。

あけましておめでとうございます

今週のお題「2017年にやりたいこと」

2017 年になりました。あけましておめでとうございます。
今年こそ音楽を頑張っていきたいと思っています。プログラミングも色んな事にチャレンジしていきたいですね。
せっかく UWP 触ってるので、Xamarin ちょっとやりたくないですか?地獄?今年 1 年あれば何かできるかな?

とにかく毎年言ってますがいろんなチャレンジをしていこうと思います。
今年 1 年よろしくお願いします。


f:id:ChiiAyano:20170101004220p:plain

このブログを作って4年が経ったらしいのと、冬コミのはなし

はてダも含めるともっと長い気がしますが(何年前だっけ…)
メールがきてました。メールしかよこさないらしく、なんかそれをこの記事に埋め込むとかそういうのができるのかなと思ったらそうじゃないらしいです?


今後もきっと気が向いたら書く、そんなブログになると思います。
今は冬コミの仕込みまっただ中です。頑張ります。ある程度形になったら告知します。いつも遅くてすんません。


一応お伝えできることだけ。
AncientChronicle は C91 の 1 日目、東レ-28b にて頒布します。
今回は初めてのアルバム CD を出します。C90 で頒布したものより 1 つ前までの曲を厳選したり、今回初めて入れる曲とかも入れてお届けする予定。あれもこれも詰め込んだら、2 枚組になるっぽいです。2 枚ですけど手焼きします。
細かいことはまた後ほど?

Bluetooth で OBD2 と接続して Mikaboshi で表示したい

この記事は、Windows 10 Mobile / Windows Phone Advent Calendar 2016 の 3 日目の記事です
www.adventar.org

先日の記事で、開発・公開している Windows 10 アプリ「Mikaboshi (みかぼし)」について書きましたが、きょうは今後予定している機能のうちのひとつを、開発手法とあわせて紹介します。

Mikaboshi のダウンロードはこちらからどうぞ
www.microsoft.com


Mikaboshi は、主に車載向け (自動車・バイク・自転車など) を想定して作っていますが、GPS の情報に頼る性質上、例えば高い建物の間を移動していたり、トンネル内を移動していたりしたときは地図の更新も、推定移動速度も更新されなくなります。そんな中でも、移動速度だけは更新させたいという気持ちから、OBD2 を使った移動速度の検知を試してみました。

OBD2 とは、いわゆる「自動車の自己診断機能」のことで、本来は自動車の故障個所などを検知する目的で使われるもののようですが、その情報の中には移動速度なども含まれており、また車からの情報なので即時性・正確性が高く、これを利用したアプリや車載機器*1が多くあります。


実装するにあたり、電話で使うので Bluetooth 接続できた方がありがたいですよね。Bluetooth 接続できる OBD2 アダプターデバイスは結構多く存在します。適当に Amazon でポチポチしてもいいと思いますが、なぜか当たりはずれの大きいものばかりなので、既に Windows Phone 向けにも OBD2 を使った情報収集できるアプリ「OBD Info-san!」を開発した がんち さんが紹介している OBD II マルチメーター M-OBD-V01 が割と安定して使えるかなと思います。ほかのやつと比べるとちょっと高いですけどね。

Mikaboshi で OBD2 検知機能を実装するにあたり、がんちさんのアプリには大変お世話になりました。

Bluetoothバイスを見つけて接続する

まず Bluetooth 接続を実装する前に、Package.appxmanifest で Bluetooth を使うように宣言します。
開いて、「機能」タブから「Bluetooth」にチェックを入れてください。これでアプリで Bluetooth が使えるようになります。

次に、使える Bluetoothバイスを列挙します。何が OBD2 アダプターなのかわかりませんからね。

使えるデバイスの一覧を拾うには、 Windows.Devices.Enumeration.DeviceInformation が使えます。
こんな感じ。

using Windows.Devices.Bluetooth.Rfcomm;
using Windows.Devices.Enumeration;

public async Task<DeviceInformationCollection> GetAvailableDevicesAsync()
{
    var services = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
    return services;
}

OBD2 アダプターがシリアルポートとして動くので、シリアルポートとして動くデバイスを探して列挙しておきます。

次に接続します。さきほど見つかったデバイスのうち、OBD2 アダプターデバイスを見つけておいてください*2。見つけたデバイスの DeviceInformation のインスタンスを保持しておきます。
そして接続します。こんな感じ。

using Windows.Devices.Bluetooth.Rfcomm;
using Windows.Devices.Enumeration;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

private StreamSocket socket;
private DataWriter writer;

public async Task ConnectAsync(DeviceInformation device)
{
    var service = await RfcommDeviceService.FromIdAsync(device.Id);

    this.socket = new StreamSocket();
    await this.socket.ConnectAsync(
        service.ConnectionHostName,
        service.ConnectionServiceName,
        SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
    this.writer = new DataWriter(this.socket.OutputStream);
}

StreamSocket.ConnectAsync() したとき、はじめての場合システムから許可を求められます。許可することで接続が確立します。2 回目以降は特にいわれませんので、ConnectAsync() してすぐに接続が確立します。

Bluetoothバイスとデータを送受信する (準備)

OBD2 アダプターデバイスは、データの送信と受信を一対一でおこないます。クライアントはデータを送信したら、OBD2 から受信を待機して、受け取った情報を解析するような流れをとります。
ですので、送信した後すぐ待機するようなコードを組むようにします。

using System.IO;
using Windows.Devices.Bluetooth.Rfcomm;
using Windows.Devices.Enumeration;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

// これらに、すでにインスタンスが上記コードを使って入ってるものとします
private StreamSocket socket;
private DataWriter writer;

public async Task SendCommandAsync(string message)
{
    // OBD2 のコマンド終端は \r
    var bytes = Encoding.ASCII.GetBytes(message + '\r');
    this.writer.WriteBytes(bytes);

    // OBD2 へここでデータを投げる
    var result = await this.writer.StoreAsync();

    if (result == bytes.Length)
    {
        // たぶん成功してる
        await AnalyzeAsync();
    }
}

private async Task AnalyzeAsync()
{
    var stream = this.socket.InputStream.AsStreamForRead();
    var result = new List<byte>();

    while (true)
    {
        var b = stream.ReadByte();

        if (b <= 0) continue;

        result.Add((byte)b);

        // > がきたら応答が終わったとみなす
        if ((char)b == '>') break;
    }
    // 以下省略、続きは次で
}

こんな感じ。これで形はできました。
OBD2 のインターフェースである ELM327 がプロンプト形式でやりとりするので、「>」はユーザーからの入力待ちモードになってるって感じです。ユーザーからコマンドと「\r」をもらったら、それに応じて情報を返して、「>」で終わるという具合。
なので、「>」がきたらデバイスからの応答は終わったとみなしてOKでしょう。

Bluetoothバイスとデータを送受信する (送信と解析)

実際に送信してみましょう。
コマンドについては ELM327 のデータシートも参考にしながら。
https://www.elmelectronics.com/wp-content/uploads/2016/07/ELM327DS.pdf

まずリセットコマンドを送信しておきます。
リセットコマンドは次の 3 つです。

at z
at l0
at e0

z は初期化コマンド、e0 はコマンドのエコーをするかどうか (これでエコーしないようになります)、l0 はラインフィードを追加するか (これで追加しないようになります) を設定します。

OBD2 へ送信するコマンドはいろいろあります。先ほどのデータシートにもありますが、英語版 Wikipedia にも一覧が載っています。

OBD-II PIDs - Wikipedia

速度情報は Mode 01 に書かれているので、コマンドはこんな感じ。

01 0D

これを送信することで、応答に速度情報が返ってきます。
これらを先ほどのコードで実装した SendCommandAsync() に投げます。

そしてこれらの応答を解析するコードを実装します。

// 上記コードからの続き

public int Speed { get; private set; }

private async Task AnalyzeAsync()
{
    var result = new List<byte>();
    // 省略
    result = /* OBD2 応答 */;

    // 応答をバイト配列から文字列にしておく
    var buffer = result.Where(w => w > 0).Select(s => (char)s).ToArray();
    var resultStr = new string(buffer);

    // 文字列にした応答を、半角スペースと改行で配列に分ける
    var data = resultStr.Split(new[] { ' ', '\r' }, StringSplitOptions.RemoveEmptyEntries).ToArray();

    // 初期化処理以外で 41 で始まるデータが返ってこなければ、それは失敗してる
    if (data[0] != "41")
        return;

    switch (data[1])
    {
        case "0D":
            // 速度情報
            break;
        default:
            return;
    }
}

private AnalyzeVehicleSpeed(string[] data)
{
    // 使うデータは 3 バイト目
    var speedData = data[2];
    var speedValue = 0;
    int.TryParse(speedData, NumberStyles.AllowHexSpecifier, CultureInfo.CurrentUICulture, out speedValue);

    this.Speed = speedValue;
}

こんな感じ。
初期化コマンドの応答については処理について特に書いてませんが、ちゃんと返ってきます。

> at z
ELM327 v1.5
> at l0
OK
> at e0
>

特に処理する必要もないですが、初期化してから各種コマンドを投げた方がいいです。初期化については「41」で始まる応答を返しませんが、エラー扱いにすると危ないので気を付けた方がいいです。

そして、送信した速度情報のコマンドの応答は

41 0D 28

となっています。成功を示す「41」と、速度情報に応答したと示す「0D」のあとに続く「28」を解析してやればOK。単に 16 進数ですので、数字に変換してやれば速度情報になります。
つまり、OBD2 で得られる速度情報は、0 ~ 255 km/h までということですね。


速度情報はたいていの車で返してもらえると思いますが、車によっては返してもらえなかったり、返す値が微妙に違う (同じ応答を 2 つ返すなど) するらしいので、その辺の情報がちょっとほしいなあと思ったりはしています。
また、ほかのコマンドを叩けば、その情報も得ることができますし、先述の Wikipedia の記事にはフォーマットもありますので、割と楽に取れるかと思います。
取得する車が何のコマンドが使えるかは、「OBD Info-san!」を使うと一覧化してくれます。試用版でもできるので、拾いたい情報をそこから探すという手もあります。


…というのを、Mikaboshi で実装していて、現在テスト中です。速度情報のほかにエンジン回転数も表示できるようにする予定でいます。
実際使ってみるとかなり楽しいというか、目指してたものが実現できたので割と満足しています。

割と古い開発中のころのスクリーンショットですが、こんな感じ。
f:id:ChiiAyano:20161202100208p:plain


少し気になるのが、OBD2 アダプターデバイスの個体差があるのかもしれませんが、OBD2 から得られる情報の更新頻度が急に落ちたり、応答がなくなったりすることがときたま起きます。
再接続したり、アダプターデバイスの電源を入れなおしたり、コマンド送信から受信までタイムアウト時間を設けて、一定時間返ってこなければ自動再接続したりするなど対策はしていますが、更新頻度の低下はうまく検知できてない状態です。
このあたりうまくやれる方法があれば教えていただけると助かります…。
また、まだテストしてる車が、家のホンダ フィット (GP6) しかなく、ほかの車でも動かせるかどうかを確認したいところです。
準備ができ次第リリースするので、協力いただける方がいればよろしくお願いします。

寄付をお願いします

1 日目に引き続いて恐縮ですが、アプリの「?」をタップして表示される「バージョン情報」に「作者に寄付する」ボタンがあります。実際に使ってみて、よければ寄付ください。アプリ内課金を利用しています。寄付額は選べませんが、寄付いただければ例えば Xamarin 使ったマルチプラットフォーム対応とかやる気が起きます。お願いします。

Advent Calendar でした

4 日目は od_10z さんです。誰もが息をのむような、すごい記事に期待しています。
twitter.com

*1:油圧メーターなどの付加メーターやレーダー探知機など

*2:先述のデバイスの場合、たいてい「SPP」といった名前で見つかると思います

Windows 10 アプリ「Mikaboshi (みかぼし)」の紹介

この記事は、Windows 10 Mobile / Windows Phone Advent Calendar 2016 の 1 日目の記事です
www.adventar.org

先日リリースしたアプリを、このブログで紹介してなかったので、Advent Calendar のネタとして投下します。


10 月 10 日に「Mikaboshi (みかぼし)」ってアプリを、Windows 10 PC / Mobile (主に Mobile 向け) でリリースしました。いわゆる位置情報を可視化するアプリです。

www.microsoft.com


主に自動車、バイク、自転車などにくくりつけて使うような想定で作ってますので、例えば Windows 10 Mobile デバイスだと GPS もついてるので使い勝手がいいかと思います。


やってることは簡単で、GPS などの位置情報センサーを使って、現在の位置を地図に出したり、GPS から割り出される航行速度を表示したり、移動距離ごとに住所を割り出して表示したりなどしています。割り出した住所と前に取得した住所を比較して、都道府県や市区町村が変化するようなときは、それを読み上げてくれる機能もあります。

上記ウェブサイトで載せてるような機能紹介をただ繰り返すだけじゃ面白くないので、紹介してない機能とか、表面的にしか紹介してない機能とかの深掘りしておきます。


住所読み上げ機能は、音声合成の性質上、漢字の読みなどを間違えることが多いです。そこで、Mikaboshi では「都道府県」と「政令指定都市の市と区」は漢字読み、それ以外はすべてひらがな読みにすることで、間違いを極力減らせるようにしました。それでも、政令指定都市でも漢字読みに失敗する例*1もあったり、また逆にひらがなだと「は・へ」の読み替えがうまくいかない例*2*3などがあるので、一度通った住所を端末で記録しておいて、あとから読み方を変えられるようにしました。
設定画面に [住所アナウンス設定] があるので、そこをタップ/クリックすると、これまで通った住所が一覧ででてきますので、読み方を変えたい項目を右か左にスワイプすることで、読み方を切り替えることができます。PC で変更する場合は右クリックで変更ができます。項目をタップ/クリックするとプレビュー再生するので、読み方が正しいかどうかも確認できます。
f:id:ChiiAyano:20161129101251p:plain
漢字読み/ひらがな読みで同じ読み方になる場合でも、読み上げのイントネーションに変化があったりするので、どっちがいいか選ぶことができます。ちょっと面白いです。音声合成の特性上、やっぱりたどたどしさというか、変な感じになるのは仕方ないです。Cortana さんの音声合成使わせてください。


何回かのバージョンアップで、地図表示のスタイルを少し更新しました。「マップモード」ができました。現在地の日の出・日没時刻を見て、日の出を過ぎると明るく、日没を過ぎると暗くなります。設定で抑止することもできます。が、現在バグで「日の出・日没をまたいでもしばらく地図が切り替わらない*4」問題がありますが、次リリースするバージョンで解決します。ごめんなさい。


Mikaboshi は、位置情報を共有するサービス Locapos (ろけぽす) にも対応しています。というか、 id:tmyt にお願いして作ってもらいました。
当初、 今ココなう!(β) を使って同じようなアプリを書いてリリースしてたことはあります*5が、サービスが事実上停止状態になり、新たなサービスを立ち上げる必要が出てきたわけです。

Mikaboshi を使ってできる Locapos の機能は、

  • 現在位置を送信する
  • 誰かの現在位置を地図表示上にプロットする (現時点では相手の名前は見えません)

の 2 点です。別端末で Locapos のポータルサイトを開いておくというスタイルを想定しています*6

locapos.com

今後やりたいこと

マルチプラットフォーム対応はぜひやりたいところです。Xamarin か…。厳しい闘いになりそうだ…。だれか教えてください。
他にもいくつかやりたいことがありますが、それは 3 日目の Advent Calendar に書きます。

寄付をお願いします

アプリの「?」をタップして表示される「バージョン情報」に「作者に寄付する」ボタンがあります。実際に使ってみて、よければ寄付ください。アプリ内課金を利用しています。寄付額は選べませんが、寄付いただければ例えば上記の Xamarin 使ったマルチプラットフォーム対応とかやる気が起きます。お願いします。


www.microsoft.com

Advent Calendar でした

2 日目は ipponshimeji さんです。

*1:[神奈川県]横浜市保土ヶ谷区は「よこはまし、ほつちけやく」と読んでしまう

*2:[神奈川県]秦野市は「わだのし」と読んでしまう

*3:「町」はすべて「ちょう」と読んでしまう

*4:日の出・日没をまたいだ次の時刻同期処理時に地図が切り替わります

*5:現在は公開停止

*6:これだとあまりよくない気がするので今後考えます

fitbit charge 2 買いました

2016年10月21日に発売になった fitbit charge 2。発売日にヨドバシ akiba で営業時間外店頭受け取りを利用して買いました。

以前から fitbit one を使っていましたが、リストバンドタイプを使うのは初めてで、腕時計代わりになればいいなということで。



fitbit ってなんぞや?というのは割愛します。仲間内と健康を競い合えるソーシャルフィットネスみたいなやーつです。


つけた感じはスタイリッシュな腕時計という感じで、割と好きです。そこまで重くないです。
心拍数がリアルタイムで見れるのは面白くて楽しいです。
モニターは日本語表記対応で、海外のアプリでよくあるようなたどたどしい日本語ではないのが好印象。この辺は fitbit アプリも同様です。アプリとペアリングすることで、時計表示はカスタマイズができます。今は時計表示と、歩数計・心拍数計が表示できるタイプにしました。


Windows 10 Mobile 版の fitbit アプリでもペアリング・同期ができますが、21日に試した段階では、システムが日本語設定だとうまくペアリングできず、英語設定に切り替えることでうまくいきました。
また、腕に装着するという仕組みからか、歩数は one よりもあいまいになり、例えばゲーセンで音ゲーするなどの腕を激しく動かすような動作をすると、それだけで歩数カウントされてしまうなどの問題はありました*1
one と charge 2 を併用できる場合、歩数は one で、心拍数は charge 2 で、という具合で役割分担ができるといいのですが…。

充電する際は腕から外す必要があり、内側から挟み込むクリップタイプです。その状態でも側面のボタンへはアクセスできますが、爪で押す必要がありました。充電中はそのボタンを押すことで充電状態を知ることができます。


僕としては、時計にもなる歩数・心拍数計というイメージです。時計は便利ですが、秒数が見れないので、その点で気になるかもしれません。
その点で、2万円ほどというのはもしかすると割に合わないかもしれないです。
歩数計だけほしいなら、one などにすると 1万円弱で買えるのでオススメです。心拍数も取りたいなら、fitbit では charge 2 が一番安いみたいです。
僕は charge 2 を買って満足してます。まずは one を買ってみるというのも手です。


(2016/10/24 19:10 追記)
はてブコメントより、設定により秒数が出せるという指摘をいただきました

fitbit charge 2 買いました - 古事連記帖

「時計の文字盤」でいちばん右の文字盤を選べば秒表示出来ますよ。

2016/10/24 12:42
b.hatena.ne.jp

試しにやってみました。確かにでてきましたね。

ただ、このデザインはあまり好きではないなあというところでした (´・ω・`)


【日本正規代理店品】Fitbit One Black ブラック FB103BK-JP

【日本正規代理店品】Fitbit One Black ブラック FB103BK-JP

*1:これは charge 2 に限った問題ではないと思います

AppxBundle ファイルを Windows 10 Mobile にインストールする方法

id:shiba-yan の記事を見て書きました

blog.shibayan.jp

Windows 10 Mobile で、AppxBundle ファイルをインストールする方法は、しばやん氏のやり方のほかに 2 つあります。

端末で実行してインストールする

HockeyApp などから、端末で AppxBundle ファイルをダウンロードし、そのファイルを直接実行することでもインストールができます。「開発者モード」を有効にする必要があり、インストールするときは確認のダイアログだけが出て、インストール状況は端末には出ません。また、端末上に必要とするライブラリパッケージがない場合、インストールに失敗します。インストールに失敗したかどうかも端末では確認できません。

バイス ポータルを使ってインストールする

「開発者モード」を有効にすると使用できる デバイス ポータル を使ってインストールすることができます。こちらを使うと、インストールの進捗やインストール中のエラーを見ることができ、またライブラリパッケージもあわせてインストールすることができますが、必要なパッケージは開発者側から受け取る必要があります。接続方法は以下の記事をご参照ください。

Windows Device Portal の概要


どっちもめんどくさいので、使えるなら Package Flight にしたほうが実はいいかもしれないです。