2016年6月9日

[cygwin]ldでIs a directoryがしばしば出るが、ジャンクションのせいかも

Windows10 Pro 64bitにCygwin 64bit版をインストールしている。
以前、32bitにしてうまく動かなかったので、64bit版にしたのだ。

リンクのldで、「cannot open output file」で「Is a directory」がしばしば出る。
-o は「ディレクトリ/オブジェクト名」という構成。
動かし方は、シェルスクリプトの中でmakeを呼んで、makeの中でgccしている。

毎回出るならともかく、エラーの頻度が高いとはいえ発生しないときもあるのだ。
別にgccでビルドしているだけで、特殊なことはしていないのに。。。

 

 

特殊なことはしていない、と書いたが、そういえばジャンクションしているフォルダだった。
CドライブがSSDでDドライブがHDDで、本体は大きいのでDドライブに置いているのだが、いろいろな都合でCドライブで処理をしたかったため、ジャンクションを張ったのだ。

 

もしや、とDドライブの方で実行すると、エラーも出ずに終わった。
まだ1回しかやっていないので、はっきりとは言えないけれども、ちょっとあやしいかもしれんね。

[nrf51]デフォルトでBLEのNotificationを有効にすることができない場合がある

地味な記事なのにアクセス数がそこそこ多いので、もしかしたらAndroidのNotificationで検索に引っかかってしまうことがあるのかも。
ごめんなさい、そっちじゃないです!

 

BDSのサンプルでBleAdapterServiceというものがあるのだが、そこにsetNotificationsState()はあってもgetする方が無かった。

CCCDってReadできるのだけど、なんでsetだけ別APIになってるのだろう?
readDescriptor()がないのかと思ったが、そうでもない。
めんどうだっただけかもしれない。

 

そこでPeripheralの方がどうなっているか気になった。
CCCDのデフォルト値ってどうなってるんだろう?

Is there any to set CCCD's default value to be 1(i.e. enabling the notification of an attribute)? - Nordic Developer Zone

デフォルト値は設定できないんだ!
へー。
Bondingしている場合はCCCDの値を保持する仕様になっているから、できるらしい。

そして、S110の用語で「system attribute」はCCCD値のことを表しているんだと。
へー!
以前わからないままになっていたのが、ここでわかるとは。。。

2016年6月8日

[android]ダイアログ上のラジオボタンの何番目が選択されているのか?

BLE接続しようとしたのだが、もう1つ手前があった。
今回はラジオボタンで選択したあと、接続ボタンを押してBLE接続させようとしている。
ダイアログ上のラジオボタンの何番目が選択されているのかを知らねばならぬのだ。


これが前回までのソース。
PeripheralSelectDialogFragment.java
選択されている情報を取得したいのは56行目。

 

ラジオボタンを選択するためにタップしたときは、OnItemClick()を通るのだろう。
そこの引数にpositionがあるから、それを保持するようにしておく、ということもできるだろう。

でも、そこの中を見る限りではListViewっぽいので、ListViewをfindViewById()で取ってきてgetCheckedItemPosition()を使う、ということもできそうな気がする。

この2つしか思いつかなかったので、やってみよう。


タップした位置を覚えておく場合は、onItemClick()からmOnCheckboxClickListener.onClick()が呼ばれるようだ。

ああ、これがAlertDialogにsetOnItemSelectedListener()したら呼ばれるやつか。
・・・呼ばれんやん。
呼ばれているのはsetSingleChoiceItems()でoverrideしたonClick()だけだ。
ソースは、前のdismiss()する手前のところだ。
つまり、第2引数がpositionだ。

int型のprivate変数でも用意して、onClick()の第2引数を覚えるようにしておき、setPositiveButton()のonClick()で使うようにすればいけるだろう。

 

次は、ListViewそのものを取ってくる方法か。
dismiss()とかで見ているAlertParamsクラスもListViewを使っているけど、dialog.mListLayoutなんか使って取得しているから私のところでは無理な気がするのよねぇ。

あ、AlertDialogにgetListView()なんてものがある。
onClick()の引数はDialogInterfaceだから、

ListView lv = ((AlertDialog)dialog).getListView();

でListViewが取ってこれるようだ。
lv.getCheckedItemPosition()とすると、positionと同じものが取れているように見える。
「見える」としているのは、確信が持てないからだ。
BLE端末が2つしか無いのだけど、今のところはこれでうまくいっている。


今回までのコミットはこちら。
PeripheralSelectDialogFragment.java

次こそ、次こそはBLE接続を。。。

2016年6月7日

[android]AlertDialogをsetAdapter()しても閉じたくない

前回の続き。

ダイアログに表示される項目をラジオボタンにすることはできたのだが、AlertDialog.BuilderにsetAdapter()するとタップしてダイアログが閉じてしまう。
これをsetSingleChoiceItems()でやると、閉じなかった。

実装を見てみよう。


setSingleChoiceItems()は、こんなやつ。
setAdapter()は、こんなやつ。
違いは、p.mCheckedItemとp.mIsSingleChoiceだ。
p.mCheckedItemはどのアイテムを選択状態にして開始するかだから、たぶん関係ないだろう。

となると、p.mIsSingleChoiceか。
AlertControllerのここがあやしいな。
どうたどったらここに着くのかわからないが、BuilderのpはprivateだからmIsSingleChoiceを設定することはできないだろう。

見た感じ、悪さをしそうにも見えないから、もうこれでいいんじゃないかね。
まっとうにやるなら、同じようにonItemClick()なんかをやってやるんだろうけど、これはcreateListView()の中だから、ListViewの生成からやってやることになるのか。。。

よし、やめよう。
1つだけ選択したいしたいという気持ちは、setSingleChoiceItems()も私も一緒だから、大丈夫なはずだ!

 

今のところ、ここまで。
https://github.com/hirokuma/AndroidTwoSpinners/tree/72528714e76ac02881104ee74c0b046ecb1934a9

ようやく次回は、BLE機器の接続になるかな。

[android]私のAndroid Studioは2.1.2じゃなかったのか??

Android Studio 2.1.2のstable版が出たのでアップデートしますか?というようなダイアログが出たので、はいはいと進めた。

が、私は今まで2.1.2を使っていたはずなのだけど、違ったのだろうか?
ダイアログには「2.1.2」と出ていたから、てっきりそう思っていたのだが。。。
こちらは、アップデート後のバージョンだ。

image

前が無いので、どうにもわからん。。。
アップデートしたらしたで、プロジェクトを開いたらGradle Pluginのバージョンが古いのでアップデートしますか?と聞かれるし。

 

もしかして、β版もアップデート対象にしていたのでは、と思ったが、そうでもなさそうだ。

image

 

 

大丈夫なのだろうとは思うが、ときどきビルドできないくらい内容が変わることがあるから、せめてビルドできているときのバージョンは把握しておかんといかんだろう。

ほら、私もAndroidのお仕事もちょっとくらい取ってこれるようになろうとしているではないか(気付かないと思うが、しているのだ)。
組み込み側はやるけど、スマホ側ができないので、ちょっと損している気がするのだ。
もしスケジュールに余裕があるなら「どっちもいけますよ(iOSはやらないけど)!」と、仕様を把握する期間を減らして安くできるという点をアピールできるんじゃ無かろうか、と目論んでいるのだ。

組み込み側は、だいたいコンパイル環境などは決め決めでやるのでソースから同じバイナリはできるのだけど、スマホ側ってなんとなく不安だ。
ダウンロードしてくるものがあると、それがダウンロードできなくなったらどうしよう、とか、バージョンが変わってしまったらどうしよう、とか、そういう心配が出てきてしまう。

まあ、スマホのアプリって、組み込み機器みたいに同じバージョンが長生きすることも少ないだろうし、組み込み機器だってDFU載せてバージョンアップしやすくなっていることを考えると、ビルドできる間はバージョンアップし続ける必要がある、ということになるのだろうか。。。

おそるべし、IT業界!

2016年6月6日

[android]ダイアログがリストだが、ラジオボタンには自分でせんといかんのか

前回は、ここまでだった。

image

確か、私の目論見では、ここでラジオボタンタイプの表示が出てきて、どれかを選択してボタンを押す、だったと思う。

別にこれでも目的は果たせるのだが、せっかく目標を立てているのだから、解決した胃ではないか。


たぶん、BaseAdapterをextendsしているクラスで、getLayoutInflater().infrate()でandroid.R.layout.simple_list_item_1を渡していて、このsimple_list_item_1が持っているのがTextViewだから、ラジオボタンじゃなくて文字だけになってるんじゃないだろうかね。

ソースだと、ここ。
L.114もTextViewなのだけど、これは代入するだけなので、元がラジオボタンになってくれなくては。

ダイアログを作るとき、「setSingleChoiceItems()」を使っているけど、実は自分でAdapterを指定してるから、意味をなしていない気がする。。。
ネットでsetSingleChoiceItems()を使った例を見るとラジオボタンになっていたからね。

 

じゃあ、私もここで、simple_list_item_single_choiceをレイアウトとして使えばよいのではなかろうか。

image

おー。
出た出た。
見栄えがこれでよいのかどうかは別として、期待通りだ。
setSingleChoiceItems()も、setAdapter()に変更して、影響がなかった。

 

が、アイテムをタップするとダイアログが閉じてしまう。。。
setCancelable(false)も効果ない。
setOnItemSelectedListener()しても効果ないというか呼ばれない。

あ、setAdapter()からsetSingleChoiceItems()に戻したら閉じなくなった。
なんか、まっとうな修正方法ではないという感じだけは伝わってくるのだけど、回避方法がわからん。

[hw]ZEROPLUSロジアナのカーソルのつかみ方

すごく今さら感が強いのだが、数年使ってようやくZEROPLUSロジアナのカーソルを期待通りにつかむ方法がわかった。

カーソルと呼んでいるのは、このAとかBとかだ。
ツール上はBarと書いてあるので、A BarとかB Barが正式名称だろう。

image

 

画面に見えているときは、マウスカーソルを持っていくと手の形になるので、つかんで移動させて、離せばそこに設定される。

image

ただ、いつも画面の中にあるわけはなく、スクロールして画面外にある場合は、端っこにちょろっと見えている。

image

こういう状態でも、同じようにマウスカーソルで動かすのだが、どのカーソルが持ち上がるのかがよくわからなかったのだ。

最近気付いたのは、マウスカーソルの位置をちょっと下にずらしたりすると、つかむ予定のカーソル名が出てくるようだ、ということ。
これは、Bをつかめる場合。

image

ただ、ここで私がAを使いたかった場合にどうしたらよいのかがわからなかった。
だから、スクロールしてAが表示されるようにして、がんばってドラッグして移動させていたのだ。

 

しかし先ほど気付いたのだが、グレーの濃い部分をダブルクリックするとダイアログが表示されるのだ。

image

これで、Aを選択すると・・・・

image

おお、Aがアクティブになった!
やるやん、私!!


と思ったら、右クリックして「Place」を選ぶと、好きなカーソルを右クリックした場所に配置させることができた。

image

・・・。
Go ToとAdd Barは見てたんだけどねぇ。。。

ツールはいろいろ使ってみないとダメですな。

2016年6月5日

[esp8266]NFCIDをFirebaseにPOST

せっかくFirebaseにPOSTすることができるようになったので、前回作ったNFCIDを取得してTCPで送信するやつをFirebaseにPOSTするようにした。

hirokuma/esp8266_rcs620s at ce246cc89cd207f4f3cc2ddde72f8f36a417f66e

image

あまりちゃんと作っていないので、コンソールにはログがいろいろ出てしまうし、RC-S620/Sをうまいことやってないのでエラーが出てしまう。
InListPassiveTargetでカードがなかったときの処理がよくないのよねー。

また、Firebaseからのレスポンスを待っていないので、それまでに送信してしまうとあまりよろしくないようだ。
POSTの結果はあまり大きなサイズではないので、全部受信をためてから解析してもよいかもしれない。

 

せっかくなのでESP8266のDeep Sleepも使ってみようかと思ったが、復帰させるトリガを持っていないのでやめた。
Initiatorだと搬送波をガンガン出すことになるし、カードが近づいたらDeep Sleepから復帰させたいとしてもかなり時間がかかると思うので、この使い方だとDeep Sleepさせても仕方なかろう。

Deep Sleepの解除は割込みかタイマだったと思うので、あまり応答性がよくなくてよいか、定期処理のときに使うのがよいのかな?

2016年6月4日

[android]FirebaseのNotificationを受けるアプリも作りたいが、うまくいかん

うまくいかんシリーズだ。

 

ESP8266からPOSTしたら、たぶんNotificationしてAndroidアプリで受け付けることができるんだろう。

よくわからんなりに、Firebaseのコンソール画面から左側の「Notifications」を選び、Androidを選択。
そして、適当に項目を埋めた。
そのときにアプリのパッケージ名がいるようなので、同じ名前で作る。
親切にも、Android Studioでどうしたらいいかのガイドが出てくるので、従う。

  • ダウンロードしたJSONファイルをドラッグ&ドロップ
  • build.gradleを、プロジェクト直下とapp内の両方を書いてあるとおりに変更

が、送ってこないね。。。

こちらを見ると、「firebase-core:9.0.2」も追加するようなのだけど、見つからないと怒られる。
Add Firebase to your Android Project  |  Firebase
「firebase」でライブラリを検索するといくつか出てくるのだが、「firebase-core」だと出てこない。。。

 

あ、やりたいことによって追加するライブラリが違うんだ。
https://firebase.google.com/docs/android/setup#available_libraries

と思ったが、そもそも候補に出てこないのだ。

 

ん?

image

2.2 preview?
でも、これはInstant Runだけの話だよなぁ。
Google Play services 9.0.2以降がインストールされていればよいっぽいのだが。

あら、今気付いたが、インストールしているGoogle Play servicesのバージョンは「30」だ。

よくわからんが、Standaloneの方のSDK Managerを使ってインストールして再起動すると、エラーが出なくなった。
まあいいや。

compile 'com.google.firebase:firebase-messaging:9.0.2'

を追加した。
コンソール画面で出てくる説明は、全体としての説明で、ここのサービスについては必要なライブラリを組み込むことになるようだ。
まあ、1行だけなんだけどね。

 

が、Notificationは飛んでこない。
JSONファイルは読んでいるようなのだが、signature not valid、なんて言われている。

うーん。。。

android - GoogleSignatureVerifier signature not valid message (not using the google maps api) - Stack Overflow

「バグで偽のログが出てるけど、動作には影響しないので修正するまで我慢して」と言っているのかな?


アプリを新しく作って、build.gradleに埋め込んでおけば通知バーに何か出てくるのかと思ったけど、そんなに甘いものじゃないのかな?

Receive and handle notifications

フォアグラウンドで動くときは何もいらないかと思っていたけど、何か追加しなさいと言っているな。。。

FirebaseMessagingServiceをextendsして、onMessageReceived()をoverrideしてログを出すようにしてみたが、呼ばれんな。


あれ、Nexus5で動かなかったのでNexus7でやっていたのだが、いま見たらNexus5の方にはNotificationが出ている。

image

Nexus5の方は、まだFirebaseMessagingServiceなどを追加する前だ。
じゃあ、別に今のままでもよいということか?
ううーん。。。


送信して1時間ほど放置したが、届かなかったので、Nexus5を再起動させた。
そのおかげかどうかわからないが、送信したら届くようになった。

・・・あら、来ない。
次に送ったら、来たけど、受け取れてないのもあるな。
うーん。。。
本体がスリープ状態(LCD消灯)してるけど、電源ボタンを押すと通知が来ているのよね。

通知が受け取れると言うことは、アプリは別にこのままでよいということなのか?
わっからーん。

[esp8266]FirebaseからincludeSubDomainsが返ってくるが、そういうものだ

前回、ESP8266からFirebaseへPOSTした。
200OKは返ってくるのだけど、JSONデータが載っていない。

HTTP/1.1 200 OK
Content-Length: 31
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache
Strict-Transport-Security: max-age=31556926; includeSubDomains; preload

 

まだなにか足りないのだろうか?
なんとなく、Content-Typeにcharsetを追加して見たのだが同じだった。
うーむ。


curlに--verboseを付けるとヘッダも見えるということで、やってみた。

 

$ curl --verbose -X POST -d ~~~
(中略)
< HTTP/1.1 200 OK
< Content-Length: 31
< Content-Type: application/json; charset=utf-8
< Cache-Control: no-cache
< Strict-Transport-Security: max-age=31556926; includeSubDomains; preload
<
* STATE: PERFORM => DONE handle 0x600057850; line 1955 (connection #0)
* multi_done
* Connection #0 to host xxxx.firebaseio.com left intact
{"name":"-KJONbf8kDuFbF5AOcVs"}

同じやん。

順番を見ると、このincludeSubDomainsのあとでユニークIDが送られてきている。
つまり、私が初回のTCP受信ですぐに切断しているのがだめなのだな。

----------
HTTP/1.1 200 OK
Content-Length: 31
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache
Strict-Transport-Security: max-age=31556926; includeSubDomains; preload


----------
{"name":"ふにふに"}
----------

はいはい、私が悪うございました。

ちゃんとContent-Length分を取得するまでは受信を止めてはいけないということだ。
かといって、データが全部来るとも限らないからタイムアウトの設定もいるだろうな。

この辺りをArduinoでやると楽なのかもしれん。
ESP8266のNon OS向けHTTPクライアントライブラリがあるといいのだけどね。
まあ、POSTするだけだったら、失敗しても気にしないということにして受信は読み捨ててしまうというのもありだとは思う。