2017年1月31日

総務省指定の番号は検索できないのか?

今年になって、PN7150の評価キットプレゼントに当選した。
規格は、こちらだ。
https://twitter.com/nxpfan/status/802067660779327488

弱いけど、一応無線を出すのだが、展示されていた写真(こちらはArduino用)には、総務省指定のシールが貼られていた。
「第AC-16082号」と書かれている。
https://twitter.com/nxpfan/status/802070209028702208

貼ってあるのは、Arduinoへの変換ボードでは無くてPN7150の載ったボードの方だし、FCC IDも一致しているので、うちのRaspberry Pi用でも同じ番号になると思っていて良いのだろうか?

ちなみに、こちらがうちの子だ。

image」

技適の番号と違って、総務省指定の番号を検索する方法が分からないのよね。。。
PaSoRiなんかも総務省指定のシールが貼られているけど、探せていないのだ。
twitterで@nxp_fanさんにリプライで質問してみたけど、そういう場所でするような質問でも無かったかな。
まあ、製品にするわけでも無いし、周囲に無線が飛び散っているわけでも無いので、あの写真をもって指定されているということにする。

2017/01/31 23:05更新

返信いただきました!
うちの子も、この総務省指定の番号でよいそうです。
https://twitter.com/nxpfan/status/826424981324079105

 

しかし、@nxp_fanさんの写真に出ているArduinoは、うちにあるやつと見栄えが違うな。
LEDも載ってるし、小さいボタンはリセットか?
Raspberry PiでもBBBでもなさそうだからArduinoだと思っているのだけど、こういうのもあるんですな。

クラウドは近い方がよい

小ネタです。

今年から、お仕事用にAzureを使い始めました。
便利よねー。
Azureだけじゃないと思うけど、「鉄人、Ubuntu 16.04だ!」とリモコンを操作するだけで、Ubuntu 16.04が使えるようになるのですよ(若い人は『鉄人28号』を調べてみよう)。

 

Pythonで作ったアプリで、MQTTを使って、Azureで立てたUbuntu VM間で通信していたのだけど、何だか遅い。
まあ、Pythonってスクリプト言語だし、しょうが無いよねぇ、と、放置していた。
TeraTermでコンソールを入力するのももたつくけど、クラウドってそういうもんなんだろう。

とは思ったものの、速くする方法がるのかもしれないと思い検索していると「リージョンを日本にする」というのが見つかった。
リージョン? 領域ってこと?
そういえば、VMを作るときに、米国とか何とかがデフォルトだったので、そのままにしていたが、あれのことだろうか?

BizSparkという、多少制限があるものの無料枠が毎月更新されるスタートアップ企業向けのサブスクリプションで、日本に一番近いのは「東南アジア」だった。
リージョンの変更、ということはできないらしいので、新しくVMを「東南アジア」で作って、まだ大したファイルを置いていなかったのでscpでコピーした。

は、速いじゃないか・・・・・・・・。
TeraTermの文字入力も、ローカルでコンソールをたたくときに比べれば少しラグがあるように感じるものの、ストレスなど感じるような速度ではない。
あの、入力しても文字がすぐに表示されなかったのを我慢していたのは、なんだったんだ。。。
Pythonでの通信速度も、トータルで秒単位の短縮ができたし。。。

 

いや、米国を選んでいたのは気付いていたのだけど、「西日本」は選べなかったので、米国でもそげん変わらんやろう、と思っていたのだよ。
ちなみに、無料試用版は1ヶ月までしかVMなんかは使えないようだけど、これは「西日本」も選択できる。
使わないまま終わってしまいそうなので、慌てて作ってみたが、もうローカルでコンソールをたたいているのと変わらんくらいの速度だ。
"F1S"という、そこそこよいサイズのものを選んでいるというのもあるだろうが、いやはや。

2017年1月29日

[android][nfc]Beamアプリを作る

HCE, Reader modeと来たら、P2Pをやらねばならぬのぅ。
というわけで、Android Beamの、NDEFを投げたり取ったりするだけのアプリを作る。
大きいファイルのやりとりをするサンプルもあるが、今回はNDEFだけだ。
Sharing Files with NFC | Android Developers


Androidで使えるO2O技術まとめ解説(終):AndroidビームとPush通知で最強のO2Oアプリを作る (3/3) - @IT
ここら辺にサンプルがあるので、見れば分かるだろう。
あと、NFC Hacksも読みながらやっている。

createNdefMessage()が呼ばれるタイミングは、端末を向かい合わせて、星が流れる画面になったところだ。
LLCPのデータ交換が行われるようになったところ、といえば良いだろうか。
この状態で小さく表示されているアプリをタップすると、相手にデータが送られる。
タップというよりは、相手の方に押すというイメージだろうか。
そして、相手にPUSHされるとonNdefPushComplete()が呼ばれる。

 

まずは、ここまでをコミットしておく。
EditTextに文字を入れ、別のAndroid端末と向かい合わせ、星が流れる画面になったらサムネイル画面をタップする。
そうすると、相手に送られるであろう。
https://github.com/hirokuma/AndroidBeamSample/tree/ca064f1c87acfd396e4ca6eef4832ef847911087

ButtonやTextViewは使っていないので、気にしないでおくれ。


受信する方は、NDEFタグの読み取りと同じだそうだ。

今回はNDEF Textを送受信している。
Textのところは、こちらからお借りした。
なっぴーさんもともきーさんも、お二人とも元気だろうか。。。
ReadRTDText/HomeActivity.java at master · bs-nfc/ReadRTDText

 

Textの送受信まで取り付けたのが、こちら。
https://github.com/hirokuma/AndroidBeamSample/tree/69b3c0eca2016386cb30a5d1a86a987c4d245281

NDEFなんだけど、IntentではactionがTECH_DISCOVEREDでやってくるのよねぇ。

NDEF Textで文字列を送ったが、バイナリデータを送りたい場合はcreateExternal()がよいのだろうか?
気になるところだが、今回はおしまい。

[android][nfc]Reader modeアプリを作る (2)

私も、AndroidのNFC reader modeサンプルを作った。
hirokuma/AndroidReaderSample

まねしたつもりはないのだが、前回参考にしたサイトと同じような内容になってしまった。
androhi/NFCReaderModeSample: NdefAdapter.ReaderCallbackのサンプル

まあ、API呼んで、コールバックされるだけなので、IDを取得するだけであれば、そんなに差が出ないだろう。

 

Nexus5で動かしているのだが、普通のタグ(HCEじゃないやつ)は読めるのだが、Android BeamしているNexus7をかざすとNFC機能自体がおかしくなるのか、普通のタグも読めなくなってしまう。
時間が経てばよくなるわけでも無く、一度Reader modeをdisable-->enableさせないと動かないようだった。
うーん・・・・・・・。

 

ただ、AndroidのCardReaderサンプルは、そういうことが起きていないような気がする。
私のアプリだと、AndroidのCardEmulationサンプルにかざすとNFCタグが読めなくなるのだが、CardReaderサンプルでは何かしているのだ。

面倒だが、サンプルが何をしているか調べるか。


まずは、CardEmulationから。

AndroidManifest.xmlの<service>で、HOST_APDU_SErVICEやxmlでAIDリストの指定をしている。
Activityでは、AccountUpdateというクラスが文字入力の監視と、変更時にHCEが返す値の更新なんかをやっているのだろう。

CardServiceがHCE動作をしている。
processCommandApdu()が入り口になっていて、SELECT FILEで自分のAIDが指定されていれば処理して、そうでなければ処理しない、というだけのようだ。

 

では、CardReaderを見ていく。

AndroidManifest.xmlで<intent-filter>が設定されている。
「Filtering for NFC Intents」によると、NFCタグをかざされたときに自アプリを起動される対象として選んでほしいときにつけるようだ。
優先度を読み解く図があったように思うが、今回は関係ないのでよかろう。

ActivityでReader modeを有効にしているのは、ここ。
対象はNFC-Aで、NDEFチェックをしないようにしている。
処理本体は、LoyaltyCardReader。

 

うーん?
私のReader modeサンプルがAndroid Beamを受けると動かなくなるというほどの違いはなさそうだが。。。


あ、CardReaderサンプルでenableReaderMode()に与えるフラグにNfcAdapter.FLAG_READER_NFC_Fを追加したら同じ動作になった!
これって、何らかのバグじゃなかろうか。。。

HCEしている方には、こういうログが出た。

E/BrcmNfcNfa: llcp_link_activate (): Failed to parse general bytes

そのあとで「--------- beginning of system」と出ている。
Reader側はかざしたときのログは出ないが「beginning of system」のログは出ている。
確か、このログはserviceが起動しているときに出るような気がするので、もしかしたらNfcServiceなどが再起動しているのかもしれない。

FLAG_READER_NFC_Fを追加しても、ちゃんとNFC-Fのタグは読めるのだ。
単に、LLCPを受けるとうまくいかない、というだけである。
そういえば、AndroidのLLCPはNFC-Fでやっていたような気がするので、そこら辺が影響しているのかも。

 

うちにはNexus5と7しか端末がないが、どちらもBroadcomのチップだったように思う。
だから、Android側なのかドライバ側なのかは切り分けができんな。

とりあえずの回避策は、HCEのタグを読みたくてenableReaderMode()を使うのであれば、相手がNFC-Fになることは(Android6までは)ないので、FLAG_READER_NFC_Fは付けないようにする、だろう。

Android7ではHCE-Fがあるらしいから、さすがに直っているのかもしれんが、じゃあReader modeになる方もAndroid 7じゃないといけないのか?という疑問が出てくる。
が、うちにはAndroid7が使える端末がないので、確認できんな。

ひとまず、githubに置いておくサンプルからは、NFC-Fを外しておこう。
https://github.com/hirokuma/AndroidReaderSample

2017年1月28日

[android][nfc]Reader modeアプリを作る (1)

HCEは動いているようだが、Reader Modeになるアプリを作ったことがないことに気付いた。
ならば、やらねばならぬのぅ。

 

Android 4.4で追加されたNFC reader mode - Qiita
「盛り上がっているのか盛り上がっていないのか」で始まるこの記事は、だいたい3年前のようだ。
当時からそうだったのだけど、未だによくわからないですな。。。
私も、バスや電車に乗るときはnimocaを使っているけど、買い物をするときは現金だし。

ただ、技術者にできる特権として、技術を提供できる、というものがある。
それが、たとえマイナーだったとしても。。。
まあ、私はNFCという技術がけっこう気に入っているので、なるべく使っているというしだいだ。

 

さて、脱線はここまでにして、Reader modeを見ていこう。
ActivityがReader modeになって、Android Beamなどに対応しなくなるという動作らしい。


このBeamを止める動作は、HCE側が同じことできないだろうか。。。
HCEしても、Windowsにかざすと、こちらはP2Pされたと思ってSNEPしてしまうのだ。
Reader modeとHCEが両立できるなら、Windowsでもタグとして認識してくれそうな気がする。
設定画面でAndroid Beamを止める設定はあるのだが、これは下回りとしては止まっていなさそうなのだ。
SNEPはしないものの、LLCPの何もしないやりとり(BLEでいえば、Empty PDUだけのやりとり)はしていそうな気配がある。

 

こういうときは、PN7150だ!
AndroidのCardReaderサンプルを起動させて、nfcDemoApp pollしたPN7150にかざすと、Android Beam(LLCP)を検知していない。
しかし、同じくAndroidのCardEmulationサンプルを起動させてかざすと、LLCPしているログが出続けている。

設定画面でAndroid Beamを無効にしてもLLCPしているログは出た。
NFC自体を無効にすると、出なくなる。
しかし、そこからNFCを有効にすると、私のHCE Sampleタグが読めた。
Android Beamを有効にしても、まだ読めている。
そして、何かをトリガにしてAndroid Beamが有効になるようなのだが、トリガが何かは分からなかった。
けっこう放置したけどHCEタグしか読めず、Google Mapアプリを立ち上げたらLLCPログが出始めた。
ポイントは、NFCを無効にする前にAndroid Beamだけを無効→NFC無効→NFC有効→Android Beam有効、の順番だ。
Android Beamだけを有効にしてもLLCPは始まらず、NFC有効時にBeamが有効なら同時に動かすし、SNEPするアプリが起動すればそれはそれで動かす、という動作か。
まあ、ホーム画面をBeamしてもうれしくはないしな。

私が作ったHCESampleサービスも入っているのだが、これはロック画面以外では読み取れなかった。
これは、作り方がよろしくないだけかもしれないので、また考えるとしよう。


軽くLLCP/SNEP/Android Beamの動作を書いておこう。

NFCは、R/WであるInitiatorがTagであるTargetにリクエストを送り、Targetがレスポンスを返す、という通信になっている。
TargetがInitiatorに対して自発的に送信することができないのだ。
しかし、P2Pのようなデータ交換ではどちらがデータを送りたくなるか分からないので、通信している間は常にInitiatorがTargetに何かを送信し、TargetがInitiatorに何かを返信する、ということをやっている。

InitiatorがR/Wとして動作するのか、P2Pの親として動作するのかは、ISO/IEC 18092に書いてあったと思う。
Targetを捕捉してすぐにその判断が行われ、動作分岐するのだ。
RC-S620/SのリファレンスマニュアルではP2Pになるときの動作が書かれているのだが、違う分岐に行くとHCEすることができるだろう。

SNEPは、LLCPでNDEFのタグを投げる、Simple NDEF Exchange Protocolのことだ、。
Android BeamはSNEPでアプリの情報(AAR)を送信していたはず(昔は、Android Pushというプロトコルもあった)。

 

だから、P2Pとして動作せずにR/Wとして動きたいときは、どちらかがLLCPしないようにすればよいのだけど、HCEはバックグラウンドで動くから、いつLLCPをやめる/戻すのタイミングがわからないということで、R/W側がやらざるを得なくなったというところか。
だって、他のアプリがAndroid Beamするつもりで動いているのに、裏で動いているHCEのせいで動作しなかったら「なんで??」ってなるよねぇ。

じゃあ、HCEがサービスじゃなくてアプリの一部として動作するのであればBeamはしなくていいやん、と思ったのだが、このAndroidサンプルはタグを読んでReaderアプリが起動していなかったら起動させる、ということをやっているようなのだ。
ただ、Google Playアプリが起動するだけなのでよくわからないのだが。。。
HCEするアプリの方に数字を打ち込むようになっているから、それがGoogle Playのアプリに関連づけられているのかもしれん。

すまん、サンプルがどういう動きをするのかは読んでいないのだ。。。
しかし、相手のアプリを起動させるためにBeamをしているだけであれば、HCE側もなんとかできるかもしれない。
希望だけ持っておこう。


サンプルを作ろうと思ったが、Qiitaの記事を書かれた人のサンプルがシンプルなので、それを見るのがよいだろう。
とはいえ、私も自分で実装しておかねば、今後使うときに困るので、自分なりに作っておこう。

 

機能として必要なのは、NfcAdapter.enableReaderMode()と、その引数で指定するNfcAdapter.ReaderCallbackクラスの派生クラスのインスタンスだ。
NfcAdapter.ReaderCallbackには、onTagDiscovered()だけがあればよさそうだ。

こちらのサンプルも、AndroidのサンプルもenableReaderMode()の最後の引数がnullだった。
何かと思ったら、reader modeの追加設定などができるみたい。
なんだろう、onTagDiscovered()が呼ばれたときに渡すデータを設定できるのかな?

また、APIの説明文に「disabling any peer-to-peer and card-emulation modes」と書いてあるので、HCEしているときにBeamを止める、というのは、少なくともこれではできないということになる。。。
この辺りは、やはりどうしようもないな。
やりたいなら、利害関係が発生しないように専用端末を作るしかないだろうか。
HCEする自アプリが起動していたせいで、他のアプリがSNEPする機会を失った、などと訴えられても困るものだ。

[android]レイアウト再び

Androidアプリを作っていて、格好がよいのは求めていないのだが、とにかく文字の入力をさせたいとか、文字列を表示させたいとか、そういう気持ちがある。
が、たったそれだけのことをしたいだけでもレイアウトをちゃんと作らないと、そもそも表示されてくれない。。。

何度やっても覚えないレイアウトの作り方なので、今回は趣向を変えて、以下に絞りたいと思う。

  • EditTextが1つと、それを確定するボタン1つ
  • 履歴用のTextViewが2つで、文字を追記していくことで履歴を残していく。スクロールで過去のものも見える。
  • 1画面に収める

image

TextViewもスクロールできたような気がするけど、ScrollViewの中に入れ込むサンプルを以前作ったことがあるから、今回もそうする。


縦に3段、1段目は横に2列。
だから、全体はLinearLayoutのvertical、1段目はLinearLayoutのhorizontal、2段目と3段目はScrollViewにすればよいだろう。

image

image

1段目が全領域を占有してしまった。。。
たぶん、どれもlayout_heightのデフォルトがmatch_parentだからだろう。
これをwrap_contentにすれば。。。

image

1段目は中身があるから高さができるけど、2段目と3段目は中身(content)が空なので、それにwrapすると高さが0になってしまうのだろう。

2段目と3段目の、デフォルトでLinearLayoutが入っていたものを、TextViewに変更する。
先にLinearLayoutを削除してからTextViewを追加しないと、「ScrollViewは子供が1人しか入れられません」と怒られる。

image

image

うーん、ましになったが、期待したものではないな。
1段目の高さはwrap_contentのままでよいのだけど、2段目と3段目は残りの領域を半分ずつ使ってほしいのだ。

そういうときは、1段目はそのまま、2段目と3段目のlayout_heightをmatch_parentにしたままlayout_weightに0以外の同じ数字を入れてみた。

image

layout_weightは、0.5でも1でも100でも、単に比率を見ているようだ。
ただ、数値の比率がそのまま自分の比率になるのではなく、相手の比率になる・・・?
以下は、2段目を1、3段目を2とした場合だ。

image

https://developer.android.com/training/basics/firstapp/building-ui.html#Weight

weight 値は、兄弟ビューが使うスペースと比較して、それぞれのビューが使う必要がある残りのスペースの分量を指定する数値です。

納得いかん。
URL先の例では、レイアウトの方向が水平で、Buttonはwrap_content、残りをEditTextが使い切りたい、というパターンだ。
だから、EditTextはlayout_width="0dp"で、layout_weight="1"になっている。0以外だったらなんでもよいのだろう。

うちの例は、事情が違う。
まず、contentに影響しないので、match_parentになる。
お互いがmatch_parentだったら分割してくれないか、と思ったが、おそらく上から順に評価されるので、2段目がmatch_parentで全部使ってしまい、3段目は高さがなくなってしまう。

 

と思ったが、layout_heightというか、layout_weightが計算される方向は0dpにしておくみたいだ。
https://developer.android.com/training/basics/firstapp/building-ui.html#Weight

2段目と3段目のlayout_heightを0dpにすると、layout_weight通りの比率になった。

image

content_wrapは残った余白をベースに計算するけど、match_parentは全部占めたところから計算するから方向がマイナスになるというか、比率が逆になるというか、そういうことになったのだろうか。

 

よし、実機(Nexus5)に焼いてみよう。

image

比率は合っているのだけど、キーボードが出てきて、そのまま圧縮されてしまった・・・。
こういうのが良い場合もあるかもしれないが、今回は上に載っていてほしい。

<activity> | Android Developers
AndroidManifest.xmlの<activity>の中にandroid:windowSoftInputModeを"adjustPan"にすると、メインウィンドウのサイズは変更されないとのこと。
layoutのXMLでは解決できないのね。。。

<activity android:name=".MainActivity" android:windowSoftInputMode="adjustPan">

image


Nameの高さが、横のButtonと同じ高さになってほしい気もするが、気にしないことにしよう。
EditViewの背景を、LinearLayoutの背景色と同じにしてしまえば気付かないのだろうけど、私としては「入力はここ!」というのが目に見えてほしいのだ。

LinearLayoutの中にpaddingだかmarginを設定して、中のlayout_heightをmatch_parentにすればいけるような気もする。
いけるのか・・・。
・・・うーん、いけなくもないけど、Buttonはああいう画像を使っているだけなので、見た目の高さと一致しないようだ。

 

というわけで、このままにしておく。
activity_main.xmlを記録として載せておきたいところだが、うちのブログエディタ(Open Live Writer)がプラグインなどにまだうまいこと対応してなくて、ソースが貼れないのだ。
Gistに貼っておこう。
https://gist.github.com/hirokuma/077a821563242c921cda4ae64b5f1fed

[勉]go (1)

しかさんに、Pythonからgoに変換する、というものを教えてもらった。
が、goなんて試して大丈夫だろうか?
Pythonを使ってから、Cに戻っても文字列をシングルクオーテーションで囲もうとしたり、セミコロンを付け忘れたりと、多少困ったことになっているのだ。

が、ソースファイルの一部を見て「あ、これはgoだね」くらいは言えるようになっておきたいというのはある。
Hello World程度はやっておこう。


まず、インストール。
Ubuntu on Windowsで試そうとしたのだが、困ったことに、なぜかgoがインストールされていた。
したっけ。。。最近、別の作業でインストールしたような気がしなくもない。

$ go version
go version go1.6 linux/amd64
$ ls -l /usr/bin/go
/usr/bin/go -> /etc/alternatives/go*

今日の時点では、最新版は「go1.7.5 (released 2017/01/26)」なので、aptでupdateしたり、purgeしてinstallし直したりしたが、そもそもpurgeしてもgoコマンドが使える。
なんなんだ、一体。。。

 

https://golang.org/doc/install#uninstall
goディレクトリを削除、という方法なのか。

$ ls -l /usr/bin/go
/usr/bin/go -> /etc/alternatives/go*
$ ls -l /etc/alternatives/go
/etc/alternatives/go -> /usr/lib/go/bin/go*
$ ls -l /usr/lib/go/bin/go
/usr/lib/go/bin/go*

たらい回しにされたが、/usr/lib/goディレクトリが本体のようだから、それを削除すれば良いことになるのかな。

そして、wgetでtar.gzファイルを取ってきて、tarで展開すると、goディレクトリが出てくる。
これを/usr/localに移動させて、/usr/local/go/binにPATHを通せばよい。

$ go version
go version go1.7.5 linux/amd64

~/.profileに追加するよう書かれているが、.profileを見ると~/.bashrcがあれば読込んでいるので、今回は.bashrcでよいだろう。

そして、/usr/local/go以外に置くのであれば、GOROOTを設定する必要があるらしい。
では、さっきまで/usr/lib/goに入っていたのだが、その場合はGOROOTは/usr/lib/goだったのだろうか。。。
gccなんかは、実行ファイルさえ動けば位置の設定などせずに使えるけど、ああはならなかったのだろうか?
あるいは、なにか便利なことがあるのかもしれない。

 

そしてGOPATHだ。
これを設定しておかないと、なんか、いろいろうまくいかなかった記憶がある。
今回は、~/Prog/golangにしておこう。
Progはシンボリックリンクで、lxssではなく普通の場所にしている。
テキストエディタを使うのは、lxss以下だとやりづらい。


https://golang.org/doc/install#testing

動作確認。
GOPATHを設定して、src/github.com/user/helloにhello.goというファイルを作るらしい。
なんだよ、github.comって。。。
変に反発して、~/Prog/golang/hello/hello.goという構成にしてみた。

$ go install hello
can't load package: package hello: cannot find package "hello" in any of:
        /usr/local/go/src/hello (from $GOROOT)
        /home/xxx/Prog/golang/src/hello (from $GOPATH)

ちっ。
$GOPATH/src以下にないとだめなんだ。
つまり$GOPATHの中には、binとsrcがいるということだ。

あらためて、~/Prog/golang/src/hello/hello.goという構成でやってみる。

$ go install hello
go build hello: /usr/local/go/pkg/tool/linux_amd64/link: read |0: interrupted system call

ん??
これ、前回もなったな。。。
確か、2回同じことをするとビルドできたような。

$ go install hello
$

できた。
・・・これでよいのか?

$ ls $GOPATH/bin
hello*
$ hello
Hello, world!

動いた。

$ file $GOPATH/bin/o
/home/xxx/Prog/golang/bin/hello: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), statically linked, not stripped
$ ls -l$GOPATH/bin/hello
-rwxrwxrwx 1 root root 1642158 Jan 28 11:44 /home/xxx/Prog/golang/bin/hello*

意外と大きいな。

$ strip $GOPATH/bin/hello
$ ls -l $GOPATH/bin/hello
-rwxrwxrwx 1 root root 1028488 Jan 28 11:47 /home/xxx/Prog/golang/bin/hello*

まあ、static linkしているから、こんなもんか。
gccだと共有ライブラリを使うのがデフォルトだから、実行ファイル自体は小さくなるだろう。
Execution Modeというのが関係しそうな、しなさそうな。。。まあ、忘れよう。
Go Execution Modes - Google ドキュメント


動いたものの、気になるのはinterrupted system call。

go build command-line-arguments: read |0: interrupted system call · Issue #349 · Microsoft/BashOnWindows

uowの問題で、Build 15019では直るのだとか。
これがWindows Updateのようなものなのか、Anniversary Updateみたいなものなのかは、よくわからんな。

 

動かないことはないので、次回がいつになるか分からないが、そのときはもう少し見ることにしよう。

2017年1月27日

[rpi]Pi1/2のどちらでも動かしたいときはコンパイルオプションに注意

Raspberry Piのgithubでは、クロスコンパイラが4種類置いてある。
どれを使うのがよいかは、むかし調べて、どれでもいいんじゃないの、で終わらせた。
hiro99ma blog: [rpi]クロスコンパイラはどれがよいのだろう

 

しかし、先日、ちょっと考えねばならんことがあった。
「ARM版」ということでバイナリ公開されているツールがあってダウンロードしたのだが、Raspberry Pi2では動くものの、Pi1ではちらりとも動かなかったのだ。

Illegal instruction

結局ソースからビルドし直し、動くものはできた。
このときは「arm-rpi-4.9.3-linux-gnueabihf」を選んだのだが、その理由はちょうどcommitコメントに「with Pi 1 support」と入っていたからだった。

 

Pi1はARM11、Pi2はCortex-A7のようだ。
ARM11はARMv6、A7はARMv7ということで、使える命令はv7の方がちょっと多い。
その部分が「命令不正」ということで、Illegal instructionを引き起こしているのだろう。

 

ARM Cortex-A Processors and GCC Command Lines - Blog - Software Tools - ARM Community

NEONというSIMDのコプロセッサみたいなものが載っていて、その命令が生成されたのか。
SIMDは1命令で複数の並列計算を行うようなイメージだ。
座標の変換に行列計算をしたりするけど、ああいうのを1命令でできるとか、そんな感じだ。
PentiumでいうところもMMXとでも思っておけばよいだろう。

 

こちらもリンクを載せておこう。
KMC Staff Blog:ARMのNEONのSIMD命令をgccのオートベクタライズの最適化で使う方法
-mfpu=neonと付けておけば、最適化オプションでうまいことやってくれたりするようだ。

 

ということは、くだんのバイナリは-mfpu=neonでビルドされていたということだろうか。
だったら、クロスコンパイラは好きなのを選んでよいという結論は変わらんのか。

[uow]mvで固まることが多いが、sourceの末尾スラッシュを除けばよい

"Bash on Ubuntu on Windows"という名称は、もうちょっとなんとかならんだろうか。。。
Bashだし、Ubuntuだし、Windowsなので、間違ってはいないのだけど、並べればよいというものでも無かろう。
頭文字だけ取って"bouow"というのも考えたけど、ちょっと長いし、今ひとつだ。
やるなら、

  • Bash on Windows
  • Ubuntu on Windows

くらいでよいんじゃなかろうか。

今回は、Ubuntu on Windows、を略して、uowで進めてみよう。


mvでディレクトリ移動をすると、uowではなく、mv自体が固まってしまうことが多いようだ。
Ctrl+Cなどでも終わらせられないし、ウィンドウもなかなか閉じない。
ウィンドウが閉じた後、uowを立ち上げても、ウィンドウだけ開いてbashが起動しない。

そして、これはどうやっても消えず、uowのコンソールを終了させても消えず、タスクマネージャでも「Mv」で消せず、再起動しようとしても固まってしまい、電源ボタン長押しで強制終了させるしかなくなってしまうようなのだ。。。

uowは開発目的だし、変なことしない方がよいとは分かっているのだけど、mvなんか無意識にやってしまうよねぇ。

 

https://github.com/Microsoft/BashOnWindows/issues/703

スラッシュが入っていると失敗する?
いま固まってしまっているので、後で試そう。。。

$ ls
RaspiKernel/ arm/
$ mv RaspiKernel arm
$

できた!
いつも、先頭だけ入力してTab補完してもらっていたから末尾に/がついていたのだけど、それを取り除けばよいのか。

おびえつつも、destinationの方にスラッシュを付けてみた。

$ mv RaspiKernel arm/
$

これもOKか。

ということは、source側の末尾にスラッシュがある場合のみ取り除けばよいのか。
スクリプトを書いてスラッシュを取り除くことも考えたが、まあ、移動させたいsourceの末尾にスラッシュがあるのも変な話だから、体で覚えていくようにしましょうかね。

2017年1月26日

[py][raspi]なるべくpythonを速く動かしたい

手軽にpythonを高速で動かす方法がないか調べた。
なお、主に速くしたいのは、Raspberry Piでの動作だ。


最初に見つかったのが、PyPy。
PyPy - Welcome to PyPy
かわいいなまえですね。

virtualenvとかいうのを使いそうに書いてあったけど、まだ使ったことが無い。。。
よくわからなかったので、apt-getしたらインストールできたと思う。

ただ、困ったことに、pipコマンドはpythonもpypyも"pip"なのだ。
パスが違いそうだけど、せめて名前は変えてほしかったところだ。
/usr/bin/pipがpythonのpipで、/usr/local/bin/pipはpypyのpipだったんじゃなかろうか。

あ、pypyのpipは、確かこちらを見ながらやったと思う。
pipをPypyから利用できるようにするよ!

「思う」が多くて済まんね。
あれこれやったので、記憶が残っていないのだ。。

 

pythonでpip installしたものも、pypyで動かすならpypyのpipでinstallがいる。
使っているものが標準でよく使われるものだったためか、pip自体はできた。

が、だ。
Raspberry Piを使ったのは拡張ピンヘッダで他の機器を制御するライブラリが既にあったためで、それはCで書いていた。
どうやら、インターフェースだけちょろちょろっと変更して共有ライブラリにすればimportできるらしいので、Python/C APIというやつで呼び出せるように作っていた。
PythonのC言語拡張モジュール作成ガイド — PythonのC言語拡張モジュール作成ガイド
このライブラリがimportできないのだ。

PyPyとしては、拡張モジュールはCFFIというやつでやるのを推奨しているらしい。
Writing extension modules for pypy — PyPy documentation
じゃあ、これで共有ライブラリをdlopen()すればよいか、とやってみようとしたが、dlopen()が失敗する。。。
pythonだと読めるので、pypyの問題だろう。
フルパスで書いても、なんかInitが付く名前のオブジェクトが見つからないとか、そんなエラーが出たので私は考えるのをやめた。


次に試したのは、cython。
なんて読むんだ?

cythonは、pyファイルの拡張子を変更して、数行のsetup.pyを書いてpythonを実行すれば動く。
動いて、そのpythonファイルをCソースに変換し、soファイルを作る。
それをimportして使うようだった。
チュートリアル基礎編 — Cython 0.17.1 documentation

やってみたが、かなり長い時間がかかって、ちゃんとsoファイルができた。
pythonでimportすると、読める。
おお。

が、だ。
私が変換したのはmainのところで、しかもコマンドラインで引数を渡して動かすタイプだった。
そういうものをimportすると、グローバルのところに書いたprintがちょろっと動くだけだ(当たり前)。
だから、cythonで変換するなら関数単位で使えるようなものがよいのだろう。
importするようなモジュールにしておくと、cythonしやすいだろう。

なんとかsys.argvを引き渡す形式の関数にして、pythonからはリスト形式で引数を渡すように書き換えた。
これはこれで動いたのだけど、別の箇所で例外が発生して動かなかった。
code_funcなんとかとか出てきてた気がするが、もう忘れた。

ダメなパターンがあるのか、チュートリアルの知識だけでやろうとしてるからダメなのかは調べてない。
計算だけしているモジュールもあって、そっちは動いているから、なんかあるのかもしれん。


やろうとしている速度向上が、時間関数を使わないとわからない、とかいうレベルではなく、声を出して「いーち、にーい、・・・」などと数えられるレベルなので、こんな小手先の技では無理だと分かってるんだけどね。

まあ、「あと数歩」という高速化を求めている場合には使えるかもしれんので、覚えておいて損はなかろう。