2014/12/29

[nfc]NFCの復習

NFC(Near Field Communication)の復習をしよう。
定期的にやらないと忘れそうだからだ。

NFCは、企業主体で進んでいる規格だと思っている。
なので「これがNFCだ!」というものは特にない。
以下は私の主観なので、「思う」とか「考えている」とかは省略するが、全部に点いていると思ってもらって問題ない。
技術と金融が密接になっているので、切り離して考えられないのだけど、私は金融関係がさっぱりわかってないから推測が多分に入ってしまうのだ。

「NFC」と大ざっぱに書いているけど、時代や文脈によって少し意味合いが異なることがある。
(おっと、スポーツのNFCは別としてだよ。)
興味ある人は少ないと思うが、私の主観で書いていくので、物事の見方の1つと思ってもらえると幸いだ。


NFCの歴史

日本では、FeliCaが大半を占める。
海外では、Type-AやType-Bがほとんどだ。

Type-A、Type-Bという呼び方は、規格で言えばISO/IEC-14443の呼び名になる。
これは日本工業規格で言うところの、JIS-X6322にあたる。
14443はNFCに関する最初の国際規格だろう。
14443-1~4まであるのだが、ここではひっくるめて14443と呼ぶ。

Type-AとType-Bは、周波数のような大きなところは同じなのだけど、物理的な方式は異なるし、プロトコルも異なる。
なのになぜ同じ規格になっているかというと、近接通信という統一した規格書を作ろうとしていたからだと思う。
企業としては、Type-AはNXP,Type-BはMotoloraらしい。
聞いた話によると、ここにType-CとしてSonyのFeliCaを入れ込もうと努力していたけど、Suicaというセキュリティを含んだ方式にしようとしていたので仕様公開できずに断られたとか何とか。
実状はわからないけれども、とにかくISO/IEC-14443にFeliCaは組み込まれなかった。
これが「FeliCaは日本仕様」と呼ばれてしまう原因じゃないかと思ってる。
Wikipediaでは、2008~2011年になっているが、初版はまだ早かったと思う。
ISO/IEC 14443
ISOサイトにはISO/IEC 14443-1:2000があったから、15年くらい前には存在していたことになる。

image

 

「あ~あ、FeliCaは入れてもらえんかった~」で終わらせられるわけもなく、経緯はよく知らないが、Type-AとFeliCaがまとまった規格ができた。
それがISO/IEC 18092。
これには別称があり、それが「NFCIP-1」。
ここで初めて「NFC」という単語が出てきた。

image

その後、ISO/IEC 15693という規格ができた。
・・・ごめん、それよく知らない・・・・・。
そして、それらを全部取り込むようなISO/IEC 21481ができた。
WikiPediaによれば、ここまでで2005年になったようだ。
近距離無線通信 - Wikipedia

image

これじゃあいかんね、と思ったかどうかは知らないが、"NFC Forum"という規格団体を作り、そこで商業的なNFC規格をまとめよう、ということになったようだ。
N-Markのようなマークのわかりやすさや、認証制度なども行っているので、私はNFC Forumで謳っているものを「NFC」と呼んでることが多い。

image

まあ、人それぞれだと思うけどね。


ひとやすみ

便宜上、「FeliCa」と書いたが、正確にいえば違うことになる。
NFCの場合、金融関係と一緒に成長してきたこともあり、セキュリティを除外できない。

例えば、Suicaには交通の記録やチャージした金額情報なんかが載っているけど、「チャージした料金が勝手に書き換えられると困る」というのは同意してもらえるだろう。
いや、書き換えて偽造できたらうれしいとかは抜きとしてね・・・。
でも、チャージされている料金を確認したいだけなのに、JRの駅内に行ってユーザ情報を入力しないといけない、となると不便な人も多かろう。

ここら辺のアクセスできる・できないがセキュリティの分野になる。
そしてセキュリティにはコスト、つまりお金のかかりかたも出てくる。
Suicaとかは薄いカードでできてるけど、これに指紋認証とかネットを経由した認証方式とか採用するとどうなるか。
薄くできないし、電源がいるし、認証するためのサーバとか何とかもろもろかかる。
「それができるようになってから販売しろよ」と思う人がいるかもしれないが、今の技術では現実的ではない。

NFC Forumの中でも、今のところセキュリティのところは対象外になっている。
まあ、仕方ないんだけどね。。。
NFC-Aもいくつか種類があるけど、セキュリティ有りの製品も多いし。
(いかん、抜き出すと図が日本列島っぽくなってしまった・・・)

image

NFCのセキュリティは企業としての肝だから、規格には取り込めないだろうと思ってる。
そこを破壊しかかっているのが、HCE,Host Card Emulationだ。


NFCでセキュリティを破られでもしたら、もう大ごとである。
FeliCaがISO/IEC 14443で渋ったのもそこだろうから、仕方ない気はする。
(NXPはどこまで公開してるんだろう?)

それに、FeliCaが国際的に載らないのには、国際規格のこともあると思う(Featured Content » Smart Card Allianceだっけ?)。
確か、USIMにSecureElement(SE)を載せる方式を推奨する、とかだったような。
FeliCaは今のところOnBoardタイプのSEしかないので、海外では使われなかったんだと思う。

SEは利権というか、一種の不動産みたいなもののようだ。
特にOnBoardタイプはそうだと思う。
SIMにSEが搭載されたタイプを使ったことがないので何とも言えないが、OnBoardタイプのSEを持った機種から別の機種に移動するのが大変なのはわかると思う。
移動できないわけではないが、キャリアの手を使わないと移動できないと思う(昔のFeliCaは移動できなかったかもね)。
SEがSIMに載っているなら、SIMだけ別の機種に載せればよいだけだ。

もしかすると、SEがSIMに載らないということで、端末自体の値段が安くなるのかもしれない。
あるいは、アドレス帳みたいなSIMへのアクセスと競合するのを嫌ったのかもしれない。
単になんかコンプライアンスか何かあるのかもしれないけど、移動はしにくいと思う。
GSMAとかの団体は、そういうのをやらせたくないような気がする。


仕事でやってるわけじゃないので、あんまり推測だけ書くのはやめておこう。
変な雰囲気になるのはやだからね。

私が嫌なのは「FeliCaは日本仕様だからだめだ」みたいな流れになることだ。
理解されない技術は魔術と同じだ、みたいな言葉が昔からあるが、よっぽどの新技術でも無い限りは、理屈がわかれば理解できるものである。
だから、聞いて理解できないものについては反発を覚えるし、反発しないといけないだろうと思っている。
その反発は、その技術に反発するのではなく、技術を理解できないことに対する反発だ。

時期的に(2014年12月)、STAP細胞がどうのこうのという季節になっている。
残念ながら、私では内容を理解できない。
できないけど、検証とか再現性とかはどの分野でも同じなので、気にはしている。
(ああ、バグとかもそういえば同じようなもんだな。)

一応、このブログは政治的なものには関与しないつもりだし、芸能関係にも関与しないつもり。
その観点で行くと、STAP細胞の件は、意図的にデータを作ったのであればNG、そうじゃないならOK、としか言えない。
もうちょっと言えば、これはマスコミがやーやー言ってしまったから表面化しただけであって、「自分が期待するような実験をして」「自分が期待するような結果が出た」という論文を作って発表して、ちょうど通ってしまっただけなんじゃないかという気がしている。
よいことじゃないんだけど、別に今さら騒ぎ立てることでもないような・・・。

なーんとなくだけど、マスコミが勝手に騒ぎ立てて神輿に乗ったけど、はしごを下ろされてしまってあたふたしてる、という気がしますな。
ちっせぇ。

この件は、マスコミがいなくても正常化されてるような感じが、なんとなくですが、しますな。
学生が卒業するために書こうと、お金もらって博士が書こうと、論文は論文なんだけどね。


と、Yahooニュースの情報だけで書いたけど、「よくわからん」ということしかわからんかった。
私が知りたいとしたら、こんなところかなぁ。

  • 意図的かどうか
  • 意図的なら、何人が行ったのか
  • 意図的ではないなら、どのくらいの確率で発生しそうか

意図的だったら、個人か集団かが気になる。
個人でも気になるけどさ。。。
うーーーん・・・・

とりあえず、うちのサイトでは技術の取り扱いはこうかな。

  • よい技術は、よい
  • よい技術を持つ人が、よい人とは限らない
  • だめな技術は、だめ

よいものはあれこれできるけど、だめなものはだめですわ。
残りはがんばってもらうしかないですな。

2014/12/19

[uml]ユースケース図がうまく描けない

以前から、ユースケース図がうまく描けないという自覚がある。
普段作るような自分用ツールだと、自分で仕様を決めて作るだけなので必要性はないのだけど、お仕事だと曖昧なところがあると困るので、使えるものは何でも使いたい。

自分で書いていて思うのは、油断すると変に細かく書きすぎてしまう、ということだ。
例えば、いま作ろうとしているBLEとFeliCa Plugをつなげたようなシステムは、こんな感じだ。

image

これは、かなりがんばって削ってみた結果だ。
その少し前は、「搬送波を・・・」とか「割込が・・・」とか、要求仕様と機能仕様と実装観点がごちゃまぜになっていたのだよ。

 

なんでそうなるかというと、何を作りたいのか私もよくわかっていない、というところがあるか。
ハードのところや、ミドルのところまで、アプリも少しは考えているんだけど、全体として「何をやりたいか」が決めきれていないのだ。
今回で言うと、使うのはBLEとFeliCa Plugなんだけど、そこから出た最初の企画が「BLEとFeliCa Plugをつなげてみたい」で、それ以上のものが何もないのだ。
「FeliCa Plugだから、相手はNFC R/Wしかない」とか「とりあえずスマートフォンにはつながないとな」とか、そういうぼんやりとした考えしかないのが、ユースケース図にも現れているような気がしてならない。

よくある例だと、自動販売機。
使う人は「商品を買う」が目的なので、それをユースケースにする、という紹介があった。
うーん、これは自動販売機というものの仕様がかなり確定してからじゃないと出てこない気がする。
それまでは、要求したい仕様自体の洗い出しを先にやるのかね。

2014/12/17

[ble]Serviceの位置

気になることがあると、そっちをある程度調べるまで気が済まないので、なかなか進まない。。
ともかく、WireSharkの件も私の中では落ち着いたので、BLEを普通に使ってみよう。

「普通に」というのは、今までが「BLEのサービスを使ってみる」をやっていた状況に対してのものだ。
何かをするためにBLEを使う、というのをやりたい。
まずは以前動かしたことのある、FeliCa Plugをつないでみようと思う。

何をするか考えてはいないが、軽く設計をしておこう。

image

ま、まずはここからだ。
ほら、山の上から麓を見下ろすような気分で設計しないと、ね。

FeliCa Plugと接続するのが目的なので、ServiceはFeliCa Plugのミドルから使える階層にした方がよいのかとも思ったが、ミドルに引っ付け過ぎすぎるのもどうかな、と思い、アプリ経由でしか通信できないイメージにした。


そういう設計のことを考えると、凝集とか結合とか、そういう話が出てくる。
が・・・苦手なのよね、その手のものが。

とりあえず、直接関係ないものは分けておこう、くらいでよいと思う。
あと、関係あるものはまとめておきましょう、かな。
マイコンの性能が上がってきたおかげで、ずいぶんと余裕あるコーディングができるようになってきたものだ。
まあ、苦手なことには変わりが無いんだけどね。


さらに関係ない話になるが、こういうレイヤーを図にするときの、私の中の配色ルールが決まっていないのが気になっている。
今のところ、アプリが暖色系で、ハードに近くなるほど寒色系、みたいなイメージでやってる。

あとは、濃淡とか。
背景が濃い方がよいか、前景が濃い方がよいか、とか。

image

今回はExcelで作っていて、Excelの標準で持ってる効果を使っている。
補色にするようなシーンでもないと思うので、同じレイヤーは同系色がよかろうと思う。

他の人はどうかな、と、Androidのアーキテクチャ図を見てみた。

http://developer.android.com/images/system-architecture.jpg

私とは逆で、アプリが寒色、ハードが暖色みたい。
背景と前景はグラデーションの方向が逆で、前景はそこまで暗くならないようにされてるみたいだ。

こういうのも参考にしながら、自分の配色を決めたいものだな。

2014/12/16

[ble]CC2540 USB Dongleから直接WireSharkで見る

WireSharkでリアルタイムの流れが見えてもしょうが無かろう、などと言っていたが、だんだん気になってきた。
もしかして、私は技術的に難しそうだから逃げただけじゃないだろうか。。。
えぇい、作ってしまえ!

というわけで、luaを作った。
https://sites.google.com/site/hiro99ma/ble/files/ble_cc2540dongle.lua?attredirects=0&d=1

USB CC2540 Dongleのポートを見て、WireSharkのBT LE LLプロトコルに流しているだけだ。
あんまり動かしてないけど、Advertisingくらいは取れていそうだ。
フィールドとかは気にしないでおくれ(練習の消し忘れ)。

短いluaファイルなので大したことないのかもしれないが、ここまで至るまでが大変だったのだ。
特に、BLEのDissectorをどうやって指定するのかがわからなくてね。。。
UDPとかTCPはやり方がよく出てくるけど、DissectorTable.get()の引数がわからんかったのだ。
メニューの「Internals > Dissector tables」で一覧は出てくるけど、BLEっぽいのがないし、検索もできない。
やむなく、1つ1つツリーを開いて探し、ようやく見つけた次第だ。

最後は、Dissectorに渡すサイズがどこから計算してよいかわからず、いくつかパケットを見て、-10すればよさそうだ、という手抜きで済ませてしまった。

 

まあ、一番の問題は、単にUSBのバルク転送を見ているだけなので、何でもかんでもBLEのデータだと思ってしまうところだろうな。

2014/12/14

[ble]NotificationはATT_MTU-3まで

勘違いしていた、というお話。

データ量を多くしたかったので、256byteのAttributeを作った。
読み出しの方では256byte読めたのだが、Notificationだと20byteまでしかできていない。

image

sd_ble_gatts_hvx()に渡している値も確認したが、256byteになっている。
なぜだ・・・。

そこでようやくCore_V4.1を確認した。
Vol.3 Part F "ATT"の"3.4.7.1 Handle Value Notification"。
読むと、先頭からATT_MTU-3までが上限とのこと。
nRF51822というかS110というか、とにかく今はATT_MTUは23byteなので、20byteまでというのは仕様通りだ。
なるほどねぇ。

それ以上のデータが読みたいならRead Brob Requestを使えとのこと。
つまりまあ、Notificationだから通知だけが目的ってことですな。

[nrf51]GNU ARM Eclipse Plug-ins

nRF51822をJ-Link LITEでデバッグしている。
うちはEclipseでやっているのだが、私がGDBに詳しくないので、なんとなくで使っている。
まあ、BLE通信しているときはステップ実行してもすぐに死んでしまうので、ブレークポイントとウォッチが使えれば問題ないのだが。

ただ、止めて、死んだあとの対処がよくわかっていなかった。
FLASHに焼かずにリセットしたいだけなのだけど、手順がわからない。。
しばらくは、Loadしないデバッグ設定を別に用意してたんだけど、本当に焼いてないのか不安が残った。

調べると、GDBコマンドでリセットできそうだった。
monitor reset
monitor halt
こんな感じでコンソールに打つと、リセットしているようだ。

そして、慣れてくると手で打つのも面倒になってきた。
なんか方法はないだろうかと見てみると、J-Link plug-inなるものがあることがわかった。
http://gnuarmeclipse.livius.net/blog/jlink-debugging/

インストール方法はこちら。
http://gnuarmeclipse.livius.net/blog/plugins-install/

これを使うと、右クリックに「Restart」が出てきて、コマンドを打たずに済むようだ。
また、今まであれこれしないとmainに止まってくれなかったりする件が解決されていそうな気がする。
よかったよかった。

 

J-Linkのプラグインだけじゃなく、OpenOCDのもあるようだ。
他にもコンパイラやテンプレートなんかも提供されているので、気にしておきましょうかね。

2014/12/13

[ble]どうせならWireSharkで直接パケットを見られないだろうか

なんか、いつものことながら、道を外れつつある・・・。
いや、人の道は外れないけど、やろうとしてたことを外れるというか。
まあ、より道は子供の頃から楽しいものだから、仕方あるまい。

前回、PSDファイルをPCAPに変換してWireSharkで見る、という作業を行った。
接続の構成は、こんな感じ。

image

ソフトまで含めると、こうなる。
前回やったのは、黒い矢印のところだけ。

image

WireSharkは「ネットワークインターフェース」のデータを取り扱うソフトなので、ネットワークインターフェースじゃないものは扱うことができない。
だから、BLEのデータもWireSharkで見ることができないから、一度PSDファイルにしたものをWireSharkで読めるPCAP形式に変換してみた、というのが前回の話だ。

 

だから、ネットワークインターフェースで見えるようにさえしてしまえば、どんなデータもWireSharkで見ることができる、というのもまた真である。
今回で言えば、CC2540 DongleとPC間はUSBで接続されているので、USBの通信をネットワークインターフェースで見えるようにすればよいだけのことだ。
「USBはネットワークとは別だろう」と思うかもしれないが、そんなことを言ってしまうと「ネットワークのデータは画像データじゃないじゃないか」と言ってるようなもので、ノイマン型コンピュータの中で生きている我々にとっては「データはメモリに載っかってしまえばみんな同じ」なのだ。
あとは、どう扱うか、だけ。

WireSharkもそれをわかっていて、USBを解析する方法が書かれている。
私はWindowsだったので、USBPcapを使ってみた。
tourのStep1~3で、Dongleのデータをpcapファイルに保存し、WireSharkで見てみた。
うん、Bulk転送でそれっぽいデータが受信できている。
Dongleの操作はWireSharkではできないので、これはTI Packet Snifferで操作した。
Step4のlive captureも同じ要領で試して、それっぽいデータが受信できていた。
(USBPcap2となっている箇所は、自分のスニファしたいUSB Host番号に合わせること!)

あとは、これをリアルタイムで解釈するようにがんばるかどうか。。。
この記事を書き始める前までは、LUAでプラグイン書いてやってみよー、と思ってたんだけど、今のところリアルタイムのWireSharkで見る必要性がほとんどないのだな。
自分でスニファアプリを作ったとかすれば必要になってくるけど、今使っているBVMCNDT52はUSBを電源供給で使うだけなので、そういうのがいらない。COMポート経由とかでも同じことはできると思うけど、そんなことを考えるのが面倒だからDongleを買ったのだよ。

そんなわけで、「TIのドングル出力を直接WireSharkで見られるか?」という問に対してはYesなんだけど、「今からがんばりたいか?」という問に対してはNo、と答えてしまうな。

[ble]TI Sniffer(BLE)のPSDファイルをpcap形式に変換

TIのBLE Sniffer Dongleを使っている。
解析してくれるので重宝するのだが、フィルタのかけ方がよくわからない・・・。
WireSharkだったら何とかわかるのだが、と思って検索すると、Zigbeeの変換をしているツールがあった。
説明を読むと、どうやらPSDファイルのフォーマットは公開されているようだ。
ならば、BLE版を作らねばならぬのぅ。

swru187g.pdfというのが、そのドキュメント。ユーザーズマニュアルだ。
パケットの種類によってデータ構造が若干異なり、ZigbeeとBLEも異なっていた。
この資料と、pcapのフォーマットを見ながら、ごにょごにょと作成。

cygwinで動いたので、先日インストールしたVisual Studio community 2013でビルドした。
gccとの互換性が高く、#pragma packも含めてまるまるビルドできた。
(tchar解決が面倒だったので、unicode指定は外したが。)

2014/12/13 18:35 GUI版も追加しました(.NET Framework4)
https://sites.google.com/site/hiro99ma/ble/files/psd2pcap.zip?attredirects=0&d=1

第1引数にpsdファイル、第2引数に出力ファイル名を入れるだけ。
WireShark 1.12.2で確認した。
プロトコルはWireSharkに入ったものを使っているだけなので、Link Layerまで。
自分用にやりたければ、ここからLUAでプラグインを書くとよいんじゃなかろうか。
とりあえず変換できたというレベルなので、そこまで調べてない。

チャネルとRSSI値を「Bluetooth Low Energy RF Info」のところで見えるようにしている。
PSDに入っている値をそのまま放り込んでいるだけなので、妥当な値なのかどうかあんまりわかってない。

気が向いたら、C#でGUI版も作ってしまいたいところだ。


気が向いたので、作って同じZIPファイルの中に突っ込んだ。
C#は使い慣れていないので、「構造体にデータを突っ込んで、パディング無しにして全部書込む!」みたいなやり方がわからず、素直に1データずつ書込んでいった。
まあ、データがメモリ上にどう展開されるのかを考えながら実装する方が今では異端なのかもしれんな。

2014/12/11

[nrf51]Notifyを受けられるようにするとSYS_ATTR_MISSINGが起きない

先日、こんなのを書いた。
hiro99ma blog: [nrf51]BLE_ERROR_GATTS_SYS_ATTR_MISSINGが起きる

このときはBlueLightだとエラーにならないのよねぇ、で終わった。
しかし、少しいじってみたのだが、どうもnRF Master ControlでもNotifyを受け付ける状態にしてから送信すると、エラーが発生しないのだ。

ということは、BLE周りのドライバとかがどうのこうのではなく、Notifyを受けると設定したときか、Notifyを受ける状態にしてNotifyを受けたときのどちらかで、Peripheralに返す値が違うようになって、SYS_ATTR_MISSINGが発生しなくなったと考えるのが妥当だろう。

 

そこまではわかるけど、このBLEスニファで調べるのは非常につらい。
WireShark形式にログを変換してくれるようなしくみがあれば、検索などがやりやすいんだけど。

[android]Android Studio 1.0がうちでも動いた!

以前、こんな記事を書いた。
hiro99ma blog: Android StudioがうちのWin8.1(32bit)+2GBメモリでヒープが足りんらしい

あれこれ試したつもりだったけど、ダメだったのだ。
「統合開発環境なんて!」と切り捨てたい気持ちもなくはないが、ツール無しで開発できるとはとても思えない。
それに、今後はEclipse環境はこのまま置いていかれそうなので、いずれは移行せねばなるまい。

ええぃ、やってしまえ!
と、以前の環境を全部捨てて、Android Studio 1.0をインストールした。
そうすると・・・あっさり動いた。
エラーも出ない。
ビルドしても、エラー無し。
デバッグとかまではやっていないけど、今までだめだったところが動いている。
なんだったんだ・・・。

まあ、過去は過去、今は今。
以前の設定が悪かっただけかもしれないけど、正式版で動くことが確認できたので満足だ。

2014/12/10

[nrf51]BLE_ERROR_GATTS_SYS_ATTR_MISSINGが起きる

BLEの対抗機をNexus5にして、調査を進めることにした。
調査といっても、転送できるデータ量を増やしたいというだけのことだ。
ちゃちゃっとやって次に進もうと思ったのだが・・・ASSERTが発生した。
(ASSERTが発生すると、LEDが点灯するようにしている。)

やったのは、ボタンを押すとNotifyで256バイトのデータを送りつける、という動作だ。
1バイトの時には何もなかったのに。。。

エラーコードは0x3401。
BLE_ERROR_GATTS_SYS_ATTR_MISSINGらしい。
「System Attributes missing」とあるが、はてさて・・・。


検索すると、すぐ出てきた。Nordicの資料なので、ログインしていないと見えないのかも。
GATTS Handle Value Indication or Notification with System Attributes Missing

なんとなく見覚えがあると思ったら、以前調べていた。
hiro99ma blog: [nrf51]BLEスタックのイベントハンドラを見る (6)

一番最後に「サンプルでは、このエラーが発生すると、単にエラーという扱いにしている」と書いているとおり、私もエラーにしている。
sd_ble_gatts_sys_attr_set()を呼んでやりさえすればよいようなんだけど、疑問が残る。

  • なぜサンプルではsd_ble_gatts_sys_attr_set()を呼ぶようにしていないのか
  • なぜイベントとしてではなく戻り値でエラーを返すルートがあるのか
  • なぜ送信データが多くなった場合に発生したのか

これを調べる前の想像では、Notifyで送信しているデータを送信しきっていないのにsd_ble_gatts_hvx()を呼んだからじゃないだろうか、と思ってたんだが、どうなんだろう?
だって、「System Attributeが見当たらない」というのは、データ量に依存しなさそうではないか。
また、IndicationやNotifyのときにわざわざこのエラーを返すというのは、何かしらSystem Attributeと通知の関連が深いことを意味しているのだと思う。
それに、通知のためのインターフェースなら"hvx"などというよくわからない単語は使わないでよいはず。
"send_notify"とか、もっとわかりやすい言葉があるだろうに。

このあたりの理屈がわかることで、BLEかnRF51についての理解が深まるんじゃないか、と勝手に期待している。
では、1回で終わるかどうかわからないが見ていこう。


正常時のシーケンスによると、sd_ble_gatts_hvx()によってATTテーブルを更新し、それによってSoftDeviceがピア側に通知するようだ。
エラーを返す場合、ATTテーブルは更新されない。
だから、sd_ble_gatts_hvx()を呼んでSYS_ATTR_MISSINGが返ってきたときには、sd_ble_gatts_sys_attr_set()を呼んで終わりではなく、またsd_ble_gatts_hvx()を呼ばないと行かんはず。

 

"hvx"は、GATT HVx、らしい。
Core_V4.1を検索したが・・・High quality Voice、くらいしか相当しそうなものが無かった。
と、思ったらNordicの造語か。
what does "HVx" stand for ? [closed] - Nordic Developer Zone
"Handle Value x"で、xは"Indication or Notification"とのこと。
わかるかー。

 

次はSystem Attribute Missingとの関係か。
検索すると出てきた。
nRF51 SDK: Bluetooth Low Energy Pairing Guide
このNordicドキュメント、SDK4, 6, 7にはなく、SDK5に入っている。。。
バージョンごとに入っていたりいなかったりすると、どうしようもない。

大ざっぱに読んだ感じでは、System AttributeというのはGATT Server側が接続しに来たClientごとに持っておくようなデータで、切断前にFLASHに保存するようだ。
Bonding Managerが管理するようなので、Just WorksのBonding無しとかだと関係ないような気がするな。

あ、Bonding有りにしてた・・・。
しかし、無しに戻しても同じエラーが発生した。


よくわからないので、BlueLightを使ってみたら、こっちはエラーにならなかった。
クライアント側の問題??
でも、そこから続けてMaster Controlを使ってもエラーにならなかった。

普通の無線通信だから、パケットを拾って比較していけば違いはわかるんだろうけど、その根気が私にあるかどうか。
接続開始のチャネルが毎回変わるので、スニファで拾うのが大変なのよね・・・。
受信機を3つ用意すればいいんだけど、そんなブルジョアジーなことはしたくないし。

2014/12/08

[nfc]Android5にはWiFi設定をタグに書き出す機能がある

こんな記事があった。
Android 5.0に対応したスマホ・タブレットなら「かざす」だけでWi-Fi接続がスグ可能に! - IO DATA

Android標準でできるということは、独自のフォーマットじゃなくて、Static Handoverでやってるんじゃないだろうか。

ネットで調べると、これが引っかかった。
Android "L" Feature Spotlight: Write Wi-Fi Passwords To NFC Tags Directly From Android
(日本語がわかる身としては、右上のTwitterにリンクしているアイコンが怖い・・・。)
考えてみれば当たり前ではあるが、タグに書き出す機能も標準で入っていた。
WiFi設定のところで、書き出したいSSIDをロングタップするとメニューが出てくる。
image


タップするとパスワード入力画面が出るので、SSIDのパスワードを打ち込む。
image


そうするとタグに書き込めるようになる。
image  image

タグをタップさせたら終わり。
image  image

読込むときは、タグをタップするだけ。
ダイアログが出てきて確認を求められるので、接続をタップすると接続できる。
image


はじめてAndroidの設定をするときはWPSが使えなさそうなので、タップでできると便利なのだが、どうだろうね。

 

タグの方だが、ざっと見た感じでは、やはりStatic Handoverで使う形式っぽい。
パスワードも平文なので、共通で使う場所のようなパスワードが広まっても問題が無いところで使うのがよいかな。
公衆Wi-Fiなんかは向いてそうだ。

2014/12/07

[ble]Nexus7(2013)できれいに動かない

なんとなくGATTがわかって気になってきたので、とりあえずnRF51822を動かしてみることにした。
送受信できるデータサイズを256byteまで増やして、どんな感じか見てみようとも思ったのだ。

が、Connectしてからの動きが何かおかしい。
いつの間にか勝手にAdvertisingに戻ってしまうのだ。
BLEスニファで見ていくと、通信が止まっていた。
サイズを増やしたことが原因かとも思ったが、そうではなさそうだ。

これを試していたのがNexus7(2013) + Android5.0 + nRF Master Controlだったので、iPad mini(old) + LightBlueで試してみた。
うん、問題ない。
じゃあAndroidがよろしくないのかと、Nexus5 + Android5.0 + nRF Master Controlで試してみた。
問題ない。

・・・ということは、Nexus7(2013)で動きがよろしくないということか?
ソフト要因かハード要因かはわからんが、あまり気にしたくない部分なので、当面はNexus5を使うようにするか。

2014/12/06

[ble]ATT_MTU

Core_V4.1によると、AttributeのPDUはこんな構成になっている。

image

 

図に注釈を付けると、こんな感じだ。

image

 

じゃあ、ATT_MTUはどういう値なんだろう?

これは、GATT(Vol. 3 Part G)の5.2章に書かれていた。
デフォルト値は23で、これは"not less than the default value"と書いてあるので、下限値のようだ。
つまり、デフォルトでのAttribute Paramsは22oct。

MTUのサイズを知るために、Exchange MTU Requestなるものがある。
Requestを投げるのはClient側で、まず自分の受信可能なMTUサイズ(Client Rx MTU)を投げる。
そのResponseとして、Server Rx MTUが返ってくる。
どちらもサイズが2octなので、65535byteまで可能・・・なのかしら?
しかし、これは「私はこれだけしか受信できませんのであしからず」というご挨拶なので、相手ができないことをできるようにするわけではない。
なので、1回に送る量が23octより大きくできる、という期待はしない方がよいだろう。

Packet index: 226
Length: 23
Raw data (hex): 58 AF 2C EB 0A 0E 0A 00 04 00 05 01 47 00 02 29 48 00 01 29 CE B4 D0
RSSI [dBm]: -58
CRC OK: 1

SensorTagのパケットを受信して、23byteのものを見てみた。

image

違う・・・。
これは、L2CAPも含んで23byteだ。
こういうのもあった。

58 AF 2C EB 0A 1B 17 00 04 00 09 15 49 00 0A 4A 00 00 00 00 00 00 00 00 B0 00 40 51 04 32 AA 00 F0 27 36 FF

image

これは、ATT Lengthが21byte(0x15)なので、ATT_MTUがデフォルトだったなら最大長になる。
青文字の範囲がATTだ。
ということは、それより外側はL2CAPになるのかな。

いやあ、バイナリが読めるようになってくると、興奮してきますな。


あれ・・・最後の一言だけで、よい記事のはずが台無しになった気がする。

 

s110/ble_gatts.hでは、こうなっていた。
23byte固定だそうな。
/** @brief Only the default MTU size of 23 is currently supported. */
#define GATT_RX_MTU 23

 

同じファイルに、ATTの最大データ長定義も書かれていた。
実は、これを探してたのだ。

[ble]GATTが少しわかった気がする

hiro99ma blog: [ble]GATTがもやもやしてよくわからない

あれから2ヶ月が過ぎた。
少しは進化したんじゃないかと思う。


ATTとGATTの関係

GはGeneralのG、なのだ。
あまり深く考えていなかったが、Attribute(以下、ATT)の使い方を一般化しましょう、そしてそれを共通ルールとしてしまいましょう、という意味のGeneralだ。

ATTの構成は、こう(Core_V4.1より)。

image

こういう入れ物があるので、それに論理的な意味を付けるのがGATTの役割だ。
それがつまり、Characteristicだの、Serviceだのになる。

Characteristicが持つプロパティの、WriteだとかIndicateだとかも、GATTの話だ。
ReadOnlyとかWRとかは、ATTの話になる。

 

GATTとAdvertisingの関係

関係ない。
Advertisingは接続する前の段階の話で、GATTは出てこないのだ。
ここはL2CAPが主にやっているような気がする。

 

GATTとGAPの関係

GAPは、いろいろ。

よく見る、CentralやPeripheralみたいなRoleはGAPだ。
これはL2CAPのMasterやSlaveと関連している。

StandbyやAdvertising、Connectionのような接続もGAPだ。
実際にやるのはL2CAPみたいだが。

Bondingのこともあるかと思えば、Securityも入っている。もちろんGATTも。
なんかもう、「GAPとはこれだ」という定義ができなさそうだ。
あえてつけるなら、GAPはBluetoothプロトコルスタックだ、みたいな感じになるんだろうか。。。


まあ、あんまりここは突っ込まなくても、プロトコルスタックは実装されているものを使うから、任せておけばよいだろう。

2014/12/02

[vs]ビルド結果のコンソール出力に慣れない

日本語化したVisual Studio Community 2013で、以前作っていたSDK for NFC Starter Kitのビルドだけやってみた。
動くかどうかは別として、まずはビルドできないと不安ではないか。

結果としては、特に問題なくビルドできた。
問題は無いんだけど、そういえばビルド結果のコンソール出力をいつになっても見間違えて慣れない、ということを思い出した。

========== ビルド: 1 正常終了、0 失敗、0 更新不要、0 スキップ ==========

ソリューションのビルドを行ったので、プロジェクトごとに成功・失敗が出るんだと思う。
それはわかっているのだが、どうしても「ビルド:1」と読んでしまうのだ。。。
だから、その次は「正常終了、0」と見てしまい、ええっ!とあせってしまうのだ。

なんでだろうか?と少し考えてみたが、たぶん「正常終了」が単位だと認識できていないからだろう。
gccとかだと「1 errors」みたいな結果なので、たぶんこれはそのまま日本語にしたのだろうが、なんかねー、なんかねー。

2014/12/01

Visual Studio Community 2013をインストールしてみた

してみただけだ。

image

ExpressをインストールしたままCommunityをインストールしたが、特に怒られることもなかった。
が、紛らわしくなりそうなのでExpressはアンインストールすることにした。
インストールも時間がかかるから、余裕があるときにやるとよいだろう。

 

インストールすると、コントロールパネルのインストールしたアプリ一覧が増えていた。
かなり増えていた。
数えると、40以上も何かしらインストールされているようだった。
Windows Phone SDKなんかも入ったけど、これはいらないなぁ。。。

アンインストールしようとしたが、候補に出てこなかった。
よく見ると、MFCが使えるんだな。
Visual Studio6で作ったプロジェクトは、まだ読めるだろうか・・・。

image


日本語言語パックは、これのようだ。
英語慣れするためにも、なるべく開発環境は英語のまま使うことが多いのだけど、Visual Studioはメニューが多くて探すのが大変な気がするから、日本語にしておこう。
本当は、日本語になったのを確認してからブログをアップしようと思ったが、日本語パックのインストールを始めてから30分経っても終わらないので、あきらめた。
違ってたら、すまん。
http://www.microsoft.com/ja-jp/download/confirmation.aspx?id=40783

 

そういえば、Visual StudioってリボンUIじゃないんだな。
やっぱり無理、とか思ったんだろうか。

2014/11/29

[nrf51]ADCにチップバージョンでの差違あり

Blogs - Nordic Developer Zone - Using the ADC with the S110 SoftDevice

今のところ予定はないが、センサーを扱いたいとなるとAD変換を使うこともあろう。

制約としては、まず以下があるとのこと。

  • ADCの割り込み優先度をLOWにする
  • PPIチャネルで0~7を使う(8~15はSoftDeviceが使っている)
    SoftDeviceの初期化前に自分で直接設定するか、nRF51 SDKのsdppiラッパAPIを使う

 

これだけでなく、nRF51の第2世代と第3世代のハードウェアには制限があるとのこと。
世代は、ドキュメントのPANを見ると、チップの表面に書いてあるとのこと。
しかし、私が持っているのはモジュール製品で、nRF51822はカバーに覆われて見ることができない・・・。

どうも、ドキュメントのPSのバージョンとハードウェアのバージョンが一致しているように見える。
今はnRF51822_PS v3.1が最新なのだけど、それはrevision 3、つまり第3世代のドキュメントのようだ。
最新版が出たからって、前のドキュメントは捨てたらいかんな。

たぶん、時期的に、うちのはrevision 2だろう。
BLEの1パケットでだいたい1msecブロックするらしい。なので、例えば6パケット送信するのであれば6msecブロックするので、

1 / 6msec = 0.1667kHz = 167Hz

ということか(ブログでは、だいたい150Hzって書いてる)。

ここでの表現が「sampling frequency」なんだけど、アプリがADCできる間隔じゃなくて、本当にサンプリング周波数がこうなるってことだろうか?
Nordicのサンプルプロジェクトを見たが、時間に関する設定はなさそうで、100msec間隔でADCする、くらいのことしかないみたいなので、あまり周波数が高くないものだけにするか、速くしたいんだったら外部に任せるかになりそうだ。

[keil]32KBの壁はどこにある?

「keilのフリー版は32KB制限がありますよね」という記事を書いていたのだが、読んでくださった方々から情報をいただいた。
ありがたやありがたや。
私があんまり社交的じゃないためか、このブログはマイナーなんですよ。
ときどき、閉鎖して本業に集中しようかとも思うけど、見てくださる方がいるのであれば、もうちょっと続けようかという感じでやっとります。


さて、本題。

hiro99ma blog: [ble]BLEモジュールを使った場合のがんばりどころは?

コメントをいただいた中で、誰もが「32KBを超えても大丈夫だった」ということだった(2人しかコメントがないが、これを「誰もが」と書くことで、すごく多くの人がコメントをくれたようなイメージを与えるテクニックだ)。

では、試してみなくてはならぬ。

まず、32KB、がどこを指しているのか。
ARM KEIL組み込み開発システム 統合開発環境 <MDK-ARM 正規代理店>|横河ディジタルコンピュータ株式会社
こちらの表を見ると、デバッガ、シミュレータ、そしてコンパイラが32KBとのこと。
しかし、コンパイルのどこら辺が32KBかは、見てもわからない。

セカンド・オピニオン (412) MCUで遊ぼう Part2 (3) | マイナビニュース
これを読むと、コード/データが32KBとある。
プログラムは基本的にROMとRAMの2つに分かれるが、ROMもデータとプログラムに分かれる。
RAMも、初期値があるものと、ないものに分かれる。
初期値があるものは、その初期値自体はROMに置かれることになる。じゃないと、初期値を保持しておくところがないからね。
C言語では、初期値を持つ変数というのは、staticなものしかない。
そのstaticな変数の中でも、初期値を代入しているものは「初期値あり」だが、代入していないものは「ゼロ」になる。
だから、staticな変数であっても、初期値の有無でROMのサイズが変わってくる。

なんでこんなことをごにゃごにゃ書いたかというと、32KBのROMをどうやったら作り出せるか、ということを考えていたからだ。
プログラムを書いて32KB作るのは、けっこう難しい。
できれば、var[32768]みたいな感じで、楽に32KBを作りたい。
でも、staticとかvolatileとかつけても、単に宣言しただけだとRAM領域の話になるので、コードサイズにならない。
初期値がないから、ゼロになるだけだ。
私が見たことのあるコンパイラだと、main()が呼ばれる前にmemset()とか、あるいはアセンブラなどでゼロ埋めするものがほとんどだったが、オプションによってゼロ埋めする処理すら省略するものもあった。

我々が求めているのは、ゼロ以外の初期値を持つ変数だ。
そうなると、初期値の部分がROMに配置されるので、今回のコードサイズ制限を調べるのに役立つ。

#include <nrf51.h>
#include <stdint.h>
#define FILL16 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
#define FILL256 FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16
#define FILL1K FILL256,FILL256,FILL256,FILL256
static const uint8_t mem[256 * 1024 * 1024] = {
    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,
    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K
};
int main(void)
{
    uint8_t jan = mem[256];
    __wfe();
    return 0;
}

16byteのFILL16を、16個並べたFILL256を、4つ配置。これでFILL1K。
とりあえずエラーを見てみたいので、これを16個並べたら、16KBだからよさそうだけど、エラーになった。

Build target 'Target 1'
compiling main_32k.c...
main_32k.c(15): warning:  #177-D: variable "jan" was declared but never referenced
        uint8_t jan = mem[256];
main_32k.c: 1 warning, 0 errors
linking...
.\Objects\test.axf: error: L6047U: The size of this image (268436284 bytes) exceeds the maximum allowed for this version of the linker
Finished: 0 information, 0 warning, 0 error and 1 fatal error messages.
".\Objects\test.axf" - 1 Error(s), 1 Warning(s).
Target not created.

でたー。
これが、maximumなエラーメッセージらしい。
少し満足。

まあ、256 * 1024 * 1024だと、どの環境でもエラーになりそうよねぇ、ということで、32KB制限近くでやってみた。

#include <nrf51.h>
#include <stdint.h>
#define FILL16 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
#define FILL256 FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16
#define FILL1K FILL256,FILL256,FILL256,FILL256
static const uint8_t mem[31 * 1024] = {
    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,
    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K
};
int main(void)
{
    uint8_t jan = mem[256];
    __wfe();
    return 0;
}

これのビルド結果は、こう。

Rebuild target 'Target 1'
compiling main_32k.c...
main_32k.c(15): warning:  #177-D: variable "jan" was declared but never referenced
        uint8_t jan = mem[256];
main_32k.c: 1 warning, 0 errors
assembling arm_startup_nrf51.s...
compiling system_nrf51.c...
linking...
Program Size: Code=598 RO-data=31970 RW-data=4 ZI-data=4196  
FromELF: creating hex file...
".\Objects\test.axf" - 0 Error(s), 1 Warning(s).

この、memの31を32にすると、リンクエラーになった。

Rebuild target 'Target 1'
compiling main_32k.c...
main_32k.c(15): warning:  #177-D: variable "jan" was declared but never referenced
        uint8_t jan = mem[256];
main_32k.c: 1 warning, 0 errors
assembling arm_startup_nrf51.s...
compiling system_nrf51.c...
linking...
.\Objects\test.axf: error: L6047U: The size of this image (33596 bytes) exceeds the maximum allowed for this version of the linker
Finished: 0 information, 0 warning, 0 error and 1 fatal error messages.
".\Objects\test.axf" - 1 Error(s), 1 Warning(s).
Target not created.

こっちが、warningだけだったコード。

#include <nrf51.h>
#include <stdint.h>
#define FILL16 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
#define FILL256 FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16
#define FILL1K FILL256,FILL256,FILL256,FILL256
static const uint8_t mem[31 * 1024] = {
    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,
    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K
};
int main(void)
{
    uint8_t jan = mem[256];
    __wfe();
    return 0;
}

こっちが、エラーになったコード。

#include <nrf51.h>
#include <stdint.h>
#define FILL16 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
#define FILL256 FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16,FILL16
#define FILL1K FILL256,FILL256,FILL256,FILL256
static const uint8_t mem[32 * 1024] = {
    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,
    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K,    FILL1K
};
int main(void)
{
    uint8_t jan = mem[256];
    __wfe();
    return 0;
}

違いは、memの添字になっている値が、31か32か、だ。

こうやって見る分には、ちゃんと32KBで制限がかかっていると感じます。


翌日。
飲みながら調べると、なんかいろいろ馬鹿なことやってるなー、と反省(したふり)。

リンクができる境界を調べて、以下のソースになった。
配列の202を203にすると、リンクエラーになる。

static const unsigned char mem[31 * 1024 + 202] = {0};
int main(void)
{
    return mem[0];
}

image

mapファイルのお尻だけ拾うと、こんな感じ。

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   
       594         88      32170          4       4196       7352   Grand Totals
       594         88      32170          4       4196       7352   ELF Image Totals
       594         88      32170          4          0          0   ROM Totals
==============================================================================
    Total RO  Size (Code + RO Data)                32764 (  32.00kB)
    Total RW  Size (RW Data + ZI Data)              4200 (   4.10kB)
    Total ROM Size (Code + RO Data + RW Data)      32768 (  32.00kB)

配列の要素数は、1024 * 31 + 202だから、31946。
mapでは32170になってるから、あと224バイトはコード以外のROMデータがあるらしい。

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
        84         36        192          0       4096        648   arm_startup_nrf51.o
        12          6      31946          0          0       2055   main_32k.o
       232         30          0          4          0       4241   system_nrf51.o
    ----------------------------------------------------------------------
       328         72      32170          4       4096       6944   Object Totals
         0          0         32          0          0          0   (incl. Generated)
         0          0          0          0          0          0   (incl. Padding)

incl. Generated、というのが32バイトあるらしい。
ARMのヘルプを見ると、これはリンカが生成したオブジェクトらしい。

ともかく、うちで試した限りでは32KB制限というのは発生していることが確認できた。

 

{0}なのに初期値ありとみなされるんだ、というのが多少ショックだった。
前見たコンパイラは、{n}のような感じでnに数値を入れるとmemset(0)で勝手に0初期化してたのだ。
組込用のコンパイラだったから、それを正とみなしてたらいかん、という教訓を得た。

2014/11/28

[android]AndroidStudio 1.0 RC2が出ていた

Windowsにも、Android Studio 1.0 RC 2が出ていた。

image

前がどんなのか忘れたけど、あか抜けた感じがしますな。
あか抜けてない私が言っても説得力ないですが。

image

 

既存のプロジェクトを開くと、エラーが出た。
こちらを参考に修正すると、よさそうだった。
Android Studioでmethod not found: 'runProguard()'発生 電脳羊(Android Dream)/ウェブリブログ

ファイルを開いて、runProguard を minifyEnabledに変更し、設定をrecommendのものにしただけで、ビルドは通った。
動かしてはいないけど、まあいいや。

2014/11/26

[c/c++]enumはプリプロセスでは評価できません

「何を当たり前のことを」と言われそうだが、まあ聞いておくれ。

今、BLEの再履修をしているところだ。
一通り小さなサービスを動かしてきたことになるので、始めた当時にはよくわからなかったものが、今では理解できるようになったかもしれない。
私の場合、学習→試作→学習→試作、を繰り返すような感じで物事を把握することが多い。
なんというか、覚えるときは紙に目一杯書き込まないと覚えられないような、体で感じるタイプらしい。

 

まあそんなわけで、BLEのことを調べ直しているのだが、設定できる値の範囲が気になってきた。
例えば、connIntervalは7.5msec~4secの間だ。
これをS110とかでは、こんな表し方になる。

#define CONN_MAX_INTERVAL               MSEC_TO_UNITS(1000, MY_UNIT_1_25_MS)

MSEC_TO_UNITS()はapp_util.hにあるマクロで、こんな定義だ。

#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))

なんでこんな式かというと、connIntervalは7.5 + 1.25n、というBluetoothの仕様になっているからだ。
TIMEはmsec単位なので、それを1000倍して割る。
ということは、全体としてはμsecになってしまうので、そうならないようにRESOLUTIONも1000倍された値を使う。
「どうせconnIntervalなんて固定値でしか持たないだろうから、そこまでやらなくていいんじゃないの」と思ったが、実装にも仕様にも固定じゃないといかんというわけではなく、もしかしたら普通は曜日や時間帯に合わせて可変にするものだけど、サンプルだから固定にしているだけなのかもしれん。

 

前置きが長くなって済まん。
nRF51で使うconnInterval値の範囲は6~3200になるのだが、そういうマクロ値が既に定義されていることを知った。
BLE_GAP_CP_MAX_CONN_INTVL_MINが6で、BLE_GAP_CP_MAX_CONN_INTVL_MAXが3200とか。
ならば、コンパイル前に定義値の範囲チェックをしておけば、変なバグで悩むことが減るんじゃなかろうか、と思ったのだ。

それで、こんなチェックマクロを埋め込んだ。

#if (CONN_MAX_INTERVAL < BLE_GAP_CP_MAX_CONN_INTVL_MIN)
#error connInterval_Max(Connection) too small.
#elif (BLE_GAP_CP_MAX_CONN_INTVL_MAX < CONN_MAX_INTERVAL)
#error connInterval_Max(Connection) too large.
#endif  //CONN_MAX_INTERVAL

 

メモリを消費するでもなく、ビルド段階で範囲チェックができてよかろう、と満足したのだが、これがgccでエラーになるのだ(他のは知らん)。
さんざん悩んだが、結果としてはこのせいだった。

enum {
    UNIT_0_625_MS = 625,
    UNIT_1_25_MS  = 1250,
    UNIT_10_MS    = 10000
};

えっ、ここにenum使ってたの??
なんでまた・・・。

#defineはプリプロセス段階で展開されるけど、enumはコンパイル時に展開される。
だからプリプロセスとしては、MSEC_TO_UNITS(1000, MY_UNIT_1_25_MS)みたいなenumを含む式を見つけると、展開できないという扱いにしてしまい、ここではゼロとみなして「ゼロで割ってます」というエラーになっていたのだ。

まあ、enumにするとデバッガなどで値が見やすくなるのはあるけど、ここでは使ってほしくなかったなぁ。
せっかくdefineがあるけど、ここは自分で7.5msecとか4secとかの定義値を作って、値でチェックする方式に置き換える方がよさそうだ。
時間かかったわー。

2014/11/24

Excel2013のコンテキストメニューが薄い

何も解決しない話になるが、Excel2013のコンテキストメニューの文字色が薄い。

image

使えるのは濃いグレーで、使えないのは薄いグレー。
どうにもコントラストが低く、最初見たときは全部ディセーブルなのかと思ったくらいだ。

テーマを変えても色が変わらないので、どうしようもなさそうだ。
Window自体も、アクティブと非アクティブでタイトル文字色しか変わらないので見分けづらい。
Excelの機能に不満はないけど、ちょっとこれはねぇ・・・。

2014/11/23

[nrf51]iBeaconとNordic

別にNordicに限定したことじゃないが、iOS8からiBeaconの仕様が変わったらしく、今のところNordicのVendor IDはCore Location Frameworkではじかれているらしい。

Nordic beacons and iOS

 

iBeaconのパケット仕様は、もともとAppleからは出てなくて、どちらかというと「こういうAdvertisingデータを流すと反応してくれた」みたいな感じだったのではなかっただろうか。
少なくとも私は、Appleの技術ドキュメントからは見つけられていない。

んで、いつしかMFi対象になってた。
あんまりわかってないけど、Advertisingのデータに書いてあるだけで、それが平文だったら、普通にスキャンしてまねすればだませてしまいますわな。
なので、自由度はなくなってしまうけど、まあAppleなら仕方ないかな、というところか。

2014/11/22

[android]LollipopのFOTAがNexus5に来たが、TeamWinだったので失敗した

白いNexus5を使っているのだが、昨日の朝、出勤前にLollipopのアップデートが来ていることに気付いた。
ヨドバシの480円SIMを使っているので、外に出てしまえば200kbpsになるため、家の中でダウンロードだけしておきたい。

そう思ってダウンロードは成功して再起動させたのだが、アップデートは始まらずにteamwinって出てきた。
よくよく思い出すと、SMS無しの契約のためセルスタンバイが気になり、root化して押さえ込んでいたのだった。
こういうときは、どうしたらいいんだろう?

 

調べると、recovery領域をオリジナルに戻せばよいようだった。
では、と、Lollipopのイメージを持ってきて解凍し、recovery.imgを焼いて再起動!
そしてリカバリモードにしたのだが・・・ドロイド君が横たわって赤い三角が出てる。
ネットだと、ここにメニューが出てくるような感じで書かれているのに。。。

やっぱり今インストールされてるのと同じじゃないとだめなのか、とKitkatのイメージからrecovery.imgを持ってきて、焼いて再起動してリカバリモード!
・・・同じだ。

もうあきらめて全部焼き直そうかと思ったが、よくネットに書いてあることを読むと、ボタンの操作をしないとメニューが出てこないとか。
昨日なのでうろ覚えだが、確か電源+音量上ボタンの同時押しだったと思う。
そうすると、出てきた。
まあ、私がリカバリモードで何かしたいわけでもないので、焼くものが間違っていなければよいだけだ。

普通にAndroidを起動させ、システムアップデートを促す画面に行くと再起動ボタンがあったので、タップ。
そしたら、自動的に再起動して、今度はごにょごにょとアップデート作業が始まった。

初めてだから、仕方ないよね。


Lollipopだが、あのイースターエッグ画面というか、あそこに入っているLollipopゲーム。
あれは、Nexus5の方がNexus7よりもやりやすかった。
私でもN5なら3点取れた! (レベル低い。。。)

2014/11/18

[nrf51]UARTログを使い、bonding時のイベントが見えたような気がした

BLEイベントハンドラの各caseにログを埋め込んだところ、bondingしたときに通知されるイベントの順番がわかった。
こんなに簡単に使えるなら、最初からやっときゃよかった。

advertising start
BLE_GAP_EVT_CONNECTED
BLE_GAP_EVT_SEC_PARAMS_REQUEST
BLE_GAP_EVT_AUTH_STATUS

ただ、すぐにDISCONNECTが通知されてしまった。
私の予想では、続けてSEC_INFO_REQUESTが来るはずだったんだが・・・。

そして、その次のCONNECTでは、すぐにSEC_INFO_REQUESTが通知された。
んんん?

advertising start
BLE_GAP_EVT_CONNECTED
BLE_GAP_EVT_SEC_INFO_REQUEST

何度か試したが、これはnRF Master Control Panelアプリを使ったときの動作のようだ。
CONNECTする画面があるのだが、そこで「bond」を選択すると、bondingだけ行うようなのだ。
だから、すぐに切断しているのだろう。

その状態で接続しに行くと、SEC_INFO_REQUESTが来ているような気がするのだけど、そうじゃなくても元々CONNECTできるということもあり、なんだか訳がわからなくなってきた。
ここら辺は、資料からお勉強することになりそうだ。

2014/11/17

[nrf51]何故simple_uartは38400bps固定なんだろうか

nRF51822の動作をデバッガでブレークポイント使って止めながら見ていたのだが、そろそろ限界になってきた。
SDKがassertionを起こすのだ。
src/rem.cなるファイルだと言ってくるのだが、SDKの中にはなさそうなので、よくわからん。

それに、通信系のデバッグで片方が止まってしまうと、相手側も無応答とみなしてエラー扱いにするだろうから、ログを出しながら確認するのがよいだろう。
そういうわけで、デバッグ用にUARTを組み込むことにした。


ざっとSDKを見ると、simple_uart.hというものがあり、実装例もあったので、それを使うことにした。
configのパラメータでピン設定すると、あとはput/getすれば使えるというシンプルさ。

しかし・・・なぜか通信速度の設定などがない。
ソースを見ると、38400bpsで動くように実装されていた。
いくらシンプルとはいえ・・・。

動作クロックのつごうかとも思ったが、リファレンスマニュアルを見てもあまりそんな感じがしない。
嫌だったら自分で組めばいいやん、ということにはなるけど、でもこの実装になっているのは何か意図があるのか・・・。

気になるが、寝よう。

2014/11/16

[nrf51]bondingされないけどconnectできる

BLEイベントとしてBLE_GAP_EVT_SEC_PARAMS_REQUESTが来たとき、sd_ble_gap_sec_params_reply()でbondingありを返しているのだが、どうもbondingなしでconnectできているようだ。

デバッガで試したが、そもそもBLE_GAP_EVT_SEC_PARAMS_REQUESTが来ていない。
このイベントはconnect後に必ず来るものと思っていたが、別にそういうものでも無いようだ。

つまり、bondingしてないとアクセスできない、という処理をするのはアプリ側の仕事ということか。
相手がセキュリティとか何も気にせず、こちらも何も気にしなかったら、connectするだけで使えるから注意がいるな。

[nrf51]core_cm0.hはincludeしないほうがよい

eclipseでエラー扱いされないようにincludeを変更したが、ついでに順番も整理していた。
整理と言っても、「bleとs110だったら、bleが上にあった方がいいよね」「common系はその上がよさそう」くらいなものだ。

が、コンパイルエラーになった。
整理する際に、core_cm0.hを読込むようにして、それを一番上に配置したのだが、それがよくないようだ。
doxygenでつくったincludeグラフを見てみよう。

core__cm0_8h__dep__incl

core_cm0.hはnrf51.hとnrf51_bitfields.hだけがincludeしていて、普通の人はnrf51.hをincludeするもののようだ。

nrf51.hをざっと見てみたが、割込の定義みたいなnRF51系の固有設定はこのファイルに書かれているから、勝手にcore_cm0.hをincludeしてしまうと未定義でエラーになるのだった。

 

じゃあ、どこまでincludeを整理できるか、とやってみたら、こんな感じになった。
まあ、こういうのに正解はないんだろうけど、とりあえずね。
https://github.com/hirokuma/nrf51822_templete

[android]Android Studioを入れなおした

昔なら「無駄話」ラベルも付けるような話だ。

Android Studioを久しぶりに起動すると、アップデートがあると言ってきた。
ほうほう、とアップデートすると、「SDKの場所は別の場所で頼むよ」とか言い出した。
『あんたが勝手にそこにインストールしたんやん!』と突っ込みつつも、別の場所に移動。

もしかすると、この移動の前にダイアログをExitだかNextだか、とにかくRetry以外のを実行したのがよくなかったか。
ダイアログには「次に起動したらSDKの場所を聞きますね」とか言ってたはずなのに、そのまま進んだ。
そして、ExplorerでAndroidStudioがインストールされているフォルダを開いていたせいか、「なんか削除できん」と言われ、旧バージョンで再び立ち上がった。
もちろん、SDKは移動しているので、SDK Managerなんかはグレーアウトのままだ。

「そういえば、ネットにSDKの場所を移動させたときのやり方が書いてあったな」と調べて、その手順で変更しようとしたのだが、なぜかSDKのパスを保存してくれず、どうにもこうにもならない。
設定ファイルを直接いじるとかあるんだろうけど、この辺でめんどうになってきた。

えーい、全部消して入れ直してしまえ!


環境は、Windows7 64bitだ。

まず、WindowsのコントロールパネルからAndroid Studioを削除。
これは普通に消えた。

手動で残骸を削除。
c:\User\xxxの中にある、.androidとか.AndroidStudioBetaとかを削除。
c:\User\xxx\AppData\Localの中にあったAndroidも削除。

あとはAndroidStudioを入れ直すだけだが、DevelopersにあるボタンだとSDKも入ってきそうだ。
それはめんどうなので、Android Tools Projectを見ると、こんな感じでzipファイルがあった。
"not contain an embedded SDK"とあるので、目的にあう。

解凍して動かすと、無事に動いたようだ。
やれやれだぜ。

2014/11/15

[nrf51]CDTの設定

nRF51822でビルドするとき、eclipse + gccで行っている。
Keilも便利なのだけど、仕事でeclipse環境を使っているので、慣れておこうという意味合いもある。

 

eclipseでC/C++を扱うときは、CDTというプラグインというかパッケージというか、そういうものになる。
今の私は、バージョンがLUNAのCDTを使っている。
CDTをデフォルトで使うと、いろいろとコードの指摘をしてくれる。
こんな感じだ。

image

マクロや関数の宣言や文法を確認して、おかしいと思ったらマークを付けてくれる。
ただ、Makefileに書いた設定を読んでくれるわけではないので、ビルド上問題が無くてもeclipseはわからずにマークを付けてしまうのだ。

無視しても特に問題は無いので、ちょっとした開発であれば目をつぶるし、邪魔なら設定をオフにすることもできる。
でも、BLEは長くやるつもりなので、ここらで設定を合わせておいた方がよいんじゃなかろうか、ということで設定をし直すことにした。

なお、環境はWindowsでやってます。


環境変数

コンパイラの場所や、SoftDeviceの場所は変わりやすいので、Windowsの環境変数に設定することにした。
名前は何でもよいので、ARM_HOMEにコンパイラを、NORDIC_NRF51にSoftDeviceの場所をそれぞれ設定。

ARM_HOME : C:\xxxxxx\CodeSourcery\arm-none-eabi
NORDIC_NRF51 : C:\xxxxx\nrf51_sdk_v6_1_0_b2ec2e6\nrf51822

パスは、自分のところに合わせておけばよい。

SoftDeviceはzipを解凍したものだからよいとして、なんでARMはCodeSourceryにしたんだっけ・・・。

 

eclipse

includeパスの追加

eclipseの設定はプロジェクト単位のようだ。
プロジェクトで右クリックして、コンテキストの一番下にあるプロパティを選択。
C/C++ General > Paths and Symbolsにインクルードパスの設定を行う。

image

最初は、includeの下のフォルダも追加していったのだけど、面倒になってきたのでCソース側にフォルダを書くようにしてしまった。
まあ、どのincludeをしているのか明確に把握しておくのも大切だろう、うんうん。

gccだけフォルダを掘っているのは、次に関係している。

 

Symbolsの追加

今回のソースで、こんな書き方をしている。
まねしただけなんだけどね。

__attribute__( ( always_inline ) ) __STATIC_INLINE void led_on(int pin);

最初のattributeは、強制インライン関数化だ。
__forceinlineでもよいらしい。
C++のinlineはコンパイラの動作依存になるから、「どうしてもインラインにしたい」という場合はマクロにするしかない。
このオプションはgccのARM用らしいのだけど、それをやってくれるのだ。

後ろの__STATIC_INLINEは、単にstatic inlineと書きたいところだけど、コンパイラの種別でcore_cm0.hが使い分けるようになっていた。
このcore_cm0.hがgccフォルダの中にあるので、ここだけincludeパスに追加したという次第だ。

こんなコンパイラ依存の内容をeclipseが知るわけもないので、適当に無視してもらうよう設定する。
このやり方は、stackoverflowに書いてあった。

image

上が、__attribute__(xxx)という書き方をしたものを置換するもので、次が__STATIC_INLINEを解決するために定義したものだ。


とりあえずこんな感じでやっておけば、警告的なものは出なくなる。

2014/11/13

[android]fplutil (2)

fplutilを動かすのに、いくつかインストールしてある必要がある。
Windowsでやっているから、それベースで書くが、他のプラットフォームでもそれほど変わるまい。

  • Android SDK
  • Android NDK
  • ant
  • python

コマンドラインで動かすためにパスを通す必要があるが、それはパスが通ってなかったときに考えよう。
足りてるかどうかは別として、以下は動いていることが確認している。

  • javac, javaw
  • adb
  • android
  • ant
  • python
  • ndk-build

overview

ここに、ライブラリで出来ることが書いてある。

libfplutilは、main()やprintf()で書いたような普通の(traditional)アプリをAndroidで開発できる

意味がわからない・・・。
まだ動きを試していないので、想像だけしてみよう。

きっと、AndroidアプリにTextViewがぺたっと貼られたアプリができあがるのだろう。
やはり、その背景色は黒で、文字が白。
pythonとかを絡ませるところを考えると、C/C++のプリプロセスの前にソースファイル自体の変換を行い、main()やprintf()をうまいこと置き換えるのだろう。

さて、ではサンプルを動かしてみようか。


Using libfplutil_main

libfplutilは、libfputil_mainとlibfputil_printの2つからできているらしい。
どちらもstatic libraryのようだ。
NDKがshared libraryだから、組み込みやすくしているのかな?

まずはmainの方だが、これはNativeActivityとして実装されるらしい。
名前は聞いたことがあるようなないような・・・。
まあ、書いてあるソースを見てみよう。

#include <android/log.h>
int main(int argc, char *argv[]) {
    __android_log_print(ANDROID_LOG_VERBOSE, "test", "Hello World");
    return 0;
}

これって、native層のログの書き方やん!
よい例が出てこないけど、OESFで「__android_log_print」を検索すると、いろいろ出てくるだろう。
ともかく、知ってる人には知っている書き方が使えるようだ。

また、標準のC/C++だけではマルチスレッドのようなしくみがないため、イベント待ち、みたいな処理を書くことができない。
大ざっぱに言えば、イベントを待つというのは、どこかのメモリを眺め続ける作業になる。
変化がなければ、イベントが来ていないので何もしない。
変化があれば、イベントが来たとみなして処理を進める。

それだけといえばそれだけなのだが、「ずっと何かする(ここではメモリの変化を見る)」という作業は、かなり電力を使うということが問題になる。
例えば、CPUが(コアが、というべきか)1つだけの場合、プロセスがイベントが来るかどうかをずっと待っていた場合、CPU使用率は100%になるだろう。
「待つ」という処理を、一生懸命やっているのだ。けなげではないか。
コンピュータとしては、一生懸命むずかしい計算をしているのも、一生懸命待っているのも、あまり変わりは無く電力を消費することになる(違うマイコンもあるが)。


Using libfplutil_print

標準出力(stdout)を、terminalに出力するようだ。
libfplutil_printは、libfpl_mainには依存していないらしく、単独で使える。


入れてみよう

githubからclone。
cloneしたが・・・configureとかがないな。
わからんので、exanplesを見る。

build_all_anrdoidというコマンドがあるらしいので、書いてある通りに打ってみた。
Androidまで接続していると、ビルドしてアプリ転送までやってくれる。

いろいろログが出てしまうが、こんな感じでlogcatに出てきた(logcat -s main、でフィルタできるらしい)。

I/ActivityManager(  535): Start proc com.google.fpl.libfplutil.example for activity com.google.fpl.libfplutil.example/android.app.NativeActivity: pid=24609 uid=10068 gids={50068, 9997} abi=armeabi-v7a
I/art     (24609): Late-enabling -Xcheck:jni
V/PhoneStatusBar(  651): setLightsOn(true)
V/threaded_app(24609): Creating: 0xac370b60
V/threaded_app(24609): Config: mcc=440 mnc=0 lang=ja cnt=JP orien=1 touch=3 dens=320 keys=1 nav=1 keysHid=3 navHid=0 sdk=21 size=3 long=1 modetype=1 modenight=1
I/main    (24609): Hello, World!


できることの最初だけしか見ていないが、Javaを何も書かなくても、とりあえずログだけではあるが動かせるというのは面白い。
どこまでどうできるのかわからないけど、自分でandroid OSをビルドするようなシステムを作っている場合、アプリから自分で組み込んだ下回りを動かすようなことができるかもしれんな。

アプリに組み込むというのも説明されているが、あとは各人でご参照下され。

2014/11/12

[android]fplutil (1)

Android Developersを見ていると、C/C++のユーティリティが出ていることに気付いた。
Utilities for C/C++ Android Developers: fplutil 1.0

最近はLinuxが使える組込み環境も増えてきたので、便利そうなものは知っておきたいところだ。
以前、Pocoというライブラリを使って、便利さに感激したのと同時に、知らなかったらどうなってたんだろうという恐怖も感じたため、そこら辺に積極的になってきている。


fplutilは、Fun Propulsion Labsの頭文字から来ているようだ。
"propulsion"は、推進、とか、推進力、とかの名詞。
楽しいこと推進研究室、みたいな訳でよいのかな?

ただ、この単語で検索するとあれこれ出てくる内容を見ると、「自分たちが楽しければいいから適当にやろうや」という"楽しい"ではなく、「この方面の楽しみ方にかけては、俺たちが一番だ」みたいなイメージがある。
まあ、そうかどうかは知らないが、とにかくそういう研究室なんだろう。


とりあえず、環境の作り方を見てみよう。

まず、普通にAndroid SDKが動かせる環境を作るようだ。
Javaなんかもそろえる。

そして、C/C++なので、Android NDKも。

さらに、Pythonが動かせる環境がいるようだ。
Windowsだと、2.7らしい。


今日はここで時間切れ。
すまぬ。。。

2014/11/10

[nrf51]sd_ble_gap_conn_param_update()はPeripheralなら呼ばずともよい?

相変わらずサンプルソースを見ている。
私も飽きない人だ。

ようやく定義値の意味を考え始めたところだ。
コメントに「sd_ble_gap_conn_param_update()を呼び出してから~」のようなものがあった。
ソース中では呼んでいないのだが、よいのだろうか?

この関数は、自分がCentralなのかPeripheralなのかで意味が違い、Peripheralの場合はCentralからの要求を待つ状態にするように読めた。
そして、パラメータにNULLを指定した場合はPPCPキャラクタリスティックを使う、とある。

確かにPPCPの設定は初期化時に行っている。
私の理解としては、PPCPの設定をしておくと、接続したときにConnection Parameter Update要求を送信せずに済むから楽でよいな、くらいだった。
しかしsd_ble_gap_conn_param_update()を説明を読んでから考え直すと、

  • デフォルトではsd_ble_gap_conn_param_update()でNULL指定されたのと同じ状態
  • だからPPCPの設定をしておかないといけない

ということのように思えてきた。

このあたりは、Core_v4.1の中でAdvertisingから接続するときの説明があったような気がする。
気が向いたら読んでおこう。

2014/11/08

[wsh]JScriptで改行ごと消し去りたい

前回、HTMLに書いた文字を置換するJScriptのことを書いた。
そのとき、「もういやだ」の行は文字だけ置換したのだけど、やはり行ごと消し去りたい。

 

inText = inText.replace(/もういやだ/g, "");

じゃあ、改行コードまで見るにはどうしたらよかろうかとmicrosoftのJScript.NETのページを見た。
ドット「.」の説明に、

'\n' を含む任意の 1 文字に一致させるには、'[.\n]' などのパターンを使用します。

とあるので、そう書いてみたのだが・・・だめっぽい。

こちらのサイトで、そうじゃないと書いてあった。
ありがたや。

 

var inFile = "test.html";
var outFile = inFile + ".html";
//読込み
var inStream = new ActiveXObject("ADODB.Stream");
inStream.Type = 2;      //text
inStream.charset = "utf-8";
inStream.Open();
inStream.LoadFromFile(inFile);
var inText = inStream.ReadText(-1);       // -1:全部 -2:1行ごと
inStream.Close();
//置換
inText = inText.replace(/<value2>/g, "abc");
inText = inText.replace(/<value1>/g, "-1");
inText = inText.replace(/^.*もういやだ.*[\s\S]/mg, "");
WScript.Echo(inText);
//console.log(inText);
//書き込み
var outStream = new ActiveXObject("ADODB.Stream");
outStream.Type = 2;
outStream.charset = "utf-8";
outStream.Open();
outStream.WriteText(inText, 0);    // 0:改行無し 1:改行有り
outStream.SaveToFile(outFile, 2);  // 1:なければ新規作成 2:新規作成かつ存在すれば上書き
outStream.Close();

[wsh]JScriptはShift-JIS + CR/LFっぽい

Windows上でJavaScriptを動かすときは、どうやらJScriptと呼ぶらしい。
JavaScriptともちょっと違った書き方ができるというか、何かルールがあるようだ。

ファイルを読んで、置換して、別ファイルに書き込む、というものを書いてみた。

var inFile = "test.html";
var outFile = inFile + ".html";
//読込み
var inStream = new ActiveXObject("ADODB.Stream");
inStream.Type = 2;      //text
inStream.charset = "utf-8";
inStream.Open();
inStream.LoadFromFile(inFile);
var inText = inStream.ReadText(-1);       /* -1:全部 -2:1行ごと */
inStream.Close();
//置換
inText = inText.replace(/<value1>/g, "-1");
inText = inText.replace(/<value2>/g, "abc");
inText = inText.replace(/もういやだ/g, "");
WScript.Echo(inText);
//console.log(inText);
//書き込み
var outStream = new ActiveXObject("ADODB.Stream");
outStream.Type = 2;
outStream.charset = "utf-8";
outStream.Open();
outStream.WriteText(inText, 1);    /* 0:改行無し 1:改行有り */
outStream.SaveToFile(outFile, 2);  /* 1:なければ新規作成 2:新規作成かつ存在すれば上書き */
outStream.Close();

読み込むファイルは、これ。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8" />
    <title>Hello</title>
</head>
<body>
    <script language="JavaScript">
        var foo = <value1>;
        document.write("寒い<value2>。");
        もういやだ
    </script>
    Hello World!
</body>
</html>

<value1>に「-1」を、<value2>に「abc」を、「もういやだ」を空行にしたい。
「もういやだ」は行ごと削除したいけど、まあHTMLだからいいだろう。

これを実行したのだが・・・。
結果がこれ。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8" />
    <title>Hello</title>
</head>
<body>
    <script language="JavaScript">
        var foo = <value1>;
        document.write("寒いabc。");
        もういやだ
    </script>
    Hello World!
</body>
</html>

中途半端に<value2>だけ置換されている。
よくわからんので、jsの方で<value1>と<value2>の順番を入れ替えた。
そうすると、<value1>が置換された。

ここら辺で、Windowsだから、ということに気付いた。
文字だけではわからないところだが、HTMLファイルはUTF-8/LF、JSファイルもUTF-8/LFで保存している。
やっぱりCR/LFじゃないとわからないってことか?ということで、JSファイルをUTF-8/CRLFにした。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8" />
    <title>Hello</title>
</head>
<body>
    <script language="JavaScript">
        var foo = -1;
        document.write("寒いabc。");
        もういやだ
    </script>
    Hello World!
</body>
</html>

<value1>と<value2>は置換された。
そして日本語が残った。。。
ということは、Shift-JISじゃないとだめなのか?ということで、JSファイルをShift-JIS/CRLFで保存。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8" />
    <title>Hello</title>
</head>
<body>
    <script language="JavaScript">
        var foo = -1;
        document.write("寒いabc。");
        
    </script>
    Hello World!
</body>
</html>

はー、そういうことなんですな。

結論としては、こう。

WindowsのJScriptは、Shift-JIS + CR/LFで保存しよう

 

ちなみに、このJSをそのまま動かすと、出力したファイルの最後にCR/LFの改行が入る。
「ちっ」と思っていたが、WriteText()で改行有りにしていたからだった・・・。