2016/12/29

[mbedtls]mpiのビット

mbedTLSを使おうとしている。
まずはBash on Windowsで動作確認だ。

サンプルを見ていると、mbedtls_mpiで大きい数字を取り扱うようだ。
元に戻すときはuint8_tなどで取得できるのだが、エンディアンはどうなっているのだろうか?

    mbedtls_mpi m;

    mbedtls_mpi_init(&m);
    mbedtls_mpi_read_string(&m, 10, "4660");        //0x1234
    for (int lp = 0; lp < 16; lp++) {
        if (mbedtls_mpi_get_bit(&m, lp) == 0) {
            printf("0");
        } else {
            printf("1");
        }
    }
    printf("\n");
    uint8_t u16[2];
    mbedtls_mpi_write_binary(&m, u16, 2);
    printf("%02x %02x\n\n", u16[0], u16[1]);

    mbedtls_mpi_free(&m);

結果

0010110001001000
12 34

 

ほう、そう来るか。
ビット0は、一番下のビットになるんだ。

[py]PythonのソースをAndroidで動かせないものか→今回はあきらめた

pythonでいくつかソースを書いて、テストしている。
ネットから情報を取得して加工するとか、コマンドラインからの入力を加工してネットに上げるとか、その手のソースだ。

今のところ、pythonはWindowsやLinuxでしか動かしていない。
が、Androidくらいなら動かせないだろうか?と思うではないか。
Androidで動くなら、もうちょっとやれることが増えるかもしれない、ということで、環境を調べてみた。

思ったよりも、色よい返事(検索結果)がない。。。
まあ、私もネイティブの言語で動かすのが筋だとは思っているのだが、とりあえず動けばよい、というレベルの場合、多少不具合があったとしても最初に書いたコードがそのまま使えるのがありがたいのだ。

 

出てきたのは、python for androidQPython
なんとなく、python for androidを試してみることにした。


python for android

開始記事を見ながらやるものの、なかなか難しい。
難しいというか、これを書いている時点ではまだうまくいっていない。
Getting Started — python-for-android 0.1 documentation

 

まず、Ubuntu on Windowsを起動。
Installing Dependenciesを見て、apt-get installなどを実行。
Arch Linuxの方はやっていないが、これはMac用なのかな?
続けて、pipを使ってcython、virtualenvをインストール。
python-for-androidはgitの方を使った(pipのだとrecipesでエラーが出たので)。

Android SDKとNDKがいるようなので、インストールする。
が、Bash on WindowsはGUIが使えないので、コマンドラインツールだけをダウンロードし、unzipする。
その後は、tools/androidコマンドを使ってSDKをインストールする。
コマンドライン (CUI) から Android SDK をインストールする | blog.tyye.net
APIは19にした。
21以上だと、ビルド時にチェックされて使えないようなのだ。

環境変数も書いてあるように設定して、p4aを実行。
オプションの指定は、こちらをまねした。
kivy/python-for-android: Turn your Python application into an Android APK

$ p4a apk --requirements=python2 –private $HOME/android/app/helloworld --package=com.blogpost.hiro99ma.helloworld --name="helloworld" --version=0.1 --bootstrap=sdl2

よくわからんが、テンプレートでも作ってくれるんじゃないのか?
"planewavessdl2"という名前のサンプルがあるのかと思ったけど、リポジトリを検索しても出てこないし。

これが、長い。。
いろいろとダウンロードしてビルドしてくれている。

 

そして、エラーが出た。
main.pyが無い、と。
Hello world — python-for-android 0.1 documentation
ドキュメント内を検索したら出てきたので、そのファイルを置いた。
が、ここって古いp4aのドキュメントだから、あやしいかも。

dxコマンドを実行しようとして、Javaのバージョンがあわないとかなんとか。
build-toolsは少し古いものを入れたのだが、どうもbuild-toolsフォルダに新しいのが入っているとそちらが使われるようだ。
linux - Remove Android SDK packages from command line - Stack Overflow
アンインストールは、単なる削除でよいらしい。

ビルドし直すと、またエラーが。
今度は、aaptが「Syntax error: "(" unexpected」といってくる。
バージョンの違いで文法が変わったのか?と思ってbuild-toolsをさらに古くしたが、変わらない。

場所は、~/.local/share/python-for-android/dists/unnamed_dist_1あたりで作業しているようなのだけど、フォルダ構成がeclipseでやっていたときの構成に似ている。
cdで移動して、"ant debug"とすると、やはりaaptのエラーで終わった。
tools/ant/build.xmlを見ると、"aapt –> R.java"というコメントがあるので、その関係だとは思うのだが、ちょっと動かしてみたいというだけでここまで苦労するのは作業的に厳しい気がする。
やはり、githubじゃなくてpipのpython-for-androidを使うべきなのだろうか。。。
Bash on Windowsを使っているというのも不安なところだ。

 

2016年現在の「Python を android で使う」 | site-hhs
こちらを読むと、今わたしが見ていたpython-for-androidはkivyというプラットフォーム関係のようだ。
たしかにビルド方法の説明でも「Kivyアプリ」「Webアプリ」「SDL2ベースアプリ」の3種類に分かれていた。
そこら辺がわからんとダメなんかなぁ。

というわけで、今回はあきらめた。
Cにでも移植しよう。

2016/12/27

[hw]FFC/FPCのコネクタ

薄い、ぺなぺなしたケーブルを挟む部品がある。

 

たとえば、RC-S730やRC-S620/Sだ。
これは、ケーブルを差し込むだけのコネクタ。

image

 

SB1602や、RC-S620/Sの反対側として購入したコネクタ。
これは、ケーブルを挿して、部品で押さえ込むようになっている。

image

 

これは、なんという名前なのだろう?

ケーブルの方は、フレキと呼んでいた。
フレキシブルケーブルの略だと思うのだが、一般的にはFPC/FFCなどと呼ばれるようだ。
FPC・FFCとは何ですか? | よくあるご質問(FAQ) | 制御機器 | 電子デバイス・産業用機器 | Panasonic

おそらく、RC-S620/Sなどに挿すタイプのケーブルは、FFCだ。
そして、SB1602の裏にある橙色のケーブルは、FPCだ。

 

では、そのコネクタはどういうものがあるのだろうか?
先ほどのページに関連する質問があった。
FPCコネクタにはどのような種類がありますか? | よくあるご質問(FAQ) | 制御機器 | 電子デバイス・産業用機器 | Panasonic

図で、図で教えてほしいのだけど。。。
他の人に聞いたら、こちらを教えてもらった。

コネクタの構造について | コネクタメーカー イリソ電子工業株式会社

タイプが列挙されているのだが、まずはケーブルとではなく、方向で分類されている。

  • ストレート
  • ライトアングル

次に、基板にどう取り付けるのか。

  • SMT
  • DIP

そして、ケーブルの挿し方。

  • ZIF
    • スライダーロック
    • フリップロック
  • NON-ZIF

上記で写真に載せたものは基板と平行になっていたので、ライトアングル。
基板の上にハンダ付けしているので、SMT。
部品で押さえ込む方がスライダーロックで、RC-S620/Sのように挿すだけなのがNON-ZIFか。

 

ここまでわかれば、部品検索も簡単かと思ったが、それが全然ダメだ。。。

まず、ケーブルのピン数(ポジション数)と、ピンの間隔(ピッチ)。
RC-S620/Sは6ピンで、間隔は0.5mmくらいだ。6ピンだと端と端の間が5つで2.5mmくらいだからだ。

ストレートでSMTの場合、基板に垂直に取り付けることになるからか、ピンの生え方が1列タイプと2列タイプがあるようだった。

そして、FFCの厚さやコネクタ自体の厚み、定格電圧、動作温度、材料、材質・・・・・・・・・

 

きーーー!

同じものを探してみようとしたが、形状が微妙に違ったり、色が違ったり。
詳細を見ると、写真ではなくカタログPDFを参照してください、などとあり、逆引きするのは難しいと思った。

2016/12/25

[esp8266][rtos]lwIPのSNTPを使う

ネットを使うと、何かと時間が取得したくなる。

時間といえば、NTP。
NTPから時間を取ってくるシンプルな手順が、SNTP。
SNMPとごちゃまぜに覚えてしまっていたのだが、Simple NTPと覚えよう。

 

ESP8266のRTOS SDKでも時間が取得したくなったので、RFC2030を見たり、他の人のまねをしながら実装したものの、どうやらlwIPのSNTPがあるようだった。
しまった。。。

非同期で時間を取ってくるため、取得できるまではsntp_get_current_timestamp()に0が返ってくるようだった。
これは、while()などで待たせればよいだろう。
lwIPにtime()も持っているのだが、これを使うとlibcの方と競合してしまうので、やめておいた。

#include "lwip/apps/sntp.h"

...
    sntp_setservername(0, "ntp.nict.jp");
    sntp_set_timezone(9);  //JST
    sntp_init();
    u32_t t;
    while ((t = sntp_get_current_timestamp()) == 0) {
        printf(".");
        vTaskDelay(1000 / portTICK_RATE_MS);
    }
    printf("\ntime=%d\n", (int)t);
...

NTPサーバにsendto()するのはsntp_init()を呼んだ場合のようだから、定期的に実行するならsntp_close()せずにsntp_init()を呼ぶだけでもよさそうだし、毎回sntp_close()してもよいのではなかろうか。
このモジュール自体は、再送などはしてくれるようだが、定期実行はしないように見える。

 

せっかくSNTPをsocketでやる部分も作ったので、GISTに置いておこう。
sntp client(socket)

Bash on Windowsでビルドして動いたので、Linux系だったら動くんじゃなかろうか(bind()のために実行時はsudoせんといかんが)。
ちょっと変更すれば、RTOS SDKでも動く。

[nrf51][mbed]BLE NanoのLED制御

久々にBLE Nanoを動かしたのだが、mbedのオンラインコンパイラでビルドできるようだった。
以前できなかった、というわけではなく、単に私がやったことがないだけだ。

実装が少なくてサービスを組み込めることは分かったのだが、もうちょっとmain()と切り離したかったので、サンプルを見ながら置き換えてみた。

BleNanoLed - a mercurial repository | mbed

 

ベースは、BLENano_SimpleControlsだ。
API仕様などは見ず、サンプルソースの配置を換えただけだ。

あとは、ここからテンプレートを作ればBluetooth Developer Studioのプラグインにできるんじゃないかなぁ、などと想像しているのだが、いかんせん最近はBLEをお仕事でやることがなくなってきたので、このまま放置になるかもしれん。

2016/12/24

[esp8266][rtos]socketでのTCP client

ようやく、ESP8266 + RTOS SDKでsocketを使ったTCP client試作ができた。

hirokuma/esp8266_rtos_tcp_client: TCP client for ESP8266_RTOS_SDK

何に時間がかかったかって、IPアドレスの文字列が間違っているということに気付かなくて1時間以上悩んでいたのだ。
間違っているとconnect()に失敗するのだけど、即座にエラーが返るんじゃなくて、時間がかかって返ってくるのだ。
だから、なんか通信がうまくいっていないんだろうかとか、いろいろな要因を探し回ってしまった。

 

とりあえず動かしてみたいのであれば、include/con_ap.hを自分のAPに変更し、include/tcp_client.hのIPアドレスとポート番号をTCPサーバのものに変更すればよいだろう。
今回も、TCPサーバとしてはWindowsのHerculesを使った。
接続できたらメッセージを飛ばすので、後はサーバからsendすると、そのままエコーバックするだけだ。

 

本体は、ここ。
esp8266_rtos_tcp_client/tcp_client.c at master · hirokuma/esp8266_rtos_tcp_client
受信をrecv()で同期待ちさせることができるのがありがたい。
これで、受信待ちタスクと送信タスクを別々にして、受信したら送信タスクに要求を投げる、という、よくあるsocketプログラミングができそうだ。

[nrf51][win][bds]Bluetooth Developer Studioを使う(2016/12/23)

ノートPCを買い替え、まだNordicの開発環境を作っていないので、作りながら記録を残しておく。

BLE peripheral側は、nRF51822が載っているBLE Nanoを使うことにしよう。
古いのと新しいのでRAMのサイズが違うようだが、まあ気にしないでおこう。
この子であれば、J-Linkなどがなくても、USB経由で焼けるんじゃなかろうか。
RedBearLab BLE Nano - スイッチサイエンス

先に言っておくことになるが、mbed環境は使わない。。
まだBluetooth Developer Studioのコード生成がmbedに対応していないというか、mbed用がないのだ(たぶん)。
コード生成はプラグインで、プラグインはJavaScriptで書けばよいから、そのうち誰かが作ってくれるのかもしれないが、まだ時代が追いついていないのだ。。

 

BLE central側は、AndroidのNexus5(Android 6.0.1)を使う。
たぶん、Android 5.1以上あれば動くんじゃなかろうか。

Android側は、Bluetooth Developer Studioが自動生成するくらいで、あまり説明しません。
説明するものが無いというか、他を読んだ方がよいというか。。

 

中身は、Bluetooth Developer Studioで作っていく。
大したものを作る気がないので、BLE Nanoに載っているLEDを制御する、ということにしておこう。
たぶん、Bluetooth Developer Studioでやるのが、一番簡単だと思う。
残念なのは、Windowsでしか動かないというところだろうか。


まず、Bluetooth Developer Studioをダウンロードする。
名前、会社名、メールアドレスの入力が必須なのはうっとうしいが、仕方ない。
https://www.bluetooth.com/download-developer-studio

今日2016/12/23は、DeveloperStudio_1_1_3135_0.exeがダウンロードされた。


起動する。
SIGN INなどあるし、Bluetooth SIGは無料で入会できるようにはなっているのだが、会社として登録することになる。
だから、無視だ。

image

 

「NEW」をクリック。
UUIDは勝手に決めてくれているので、変更したくなければそのままでよい。
今回は「NanoLed」という名前にしておこう。
なお、ここのNAMESPACE欄は、Androidアプリを作るときにも使われるので注意しておこう。

image

 

OKするとダイアログが閉じて、「New Profile」とだけ書かれた画面が出てくる。
そこをクリック。

image

ここは特に使わないので、New Profileのところを「NanoLed」に変更して、SAVE。
変更したけど、しなくてよいのかもしれん。

次は、右側にある「CUSTOM SERVICE」をクリック。
ここからが本番だ。


image

サービス名が「NanoLed new service」と長いので、newを削除することにした。
これは、後でソースを自動生成するときのファイル名になる。

 

左側にある「+」ボタンをクリック。
これはServiceにCharacteristicを追加するボタンだ。

今回は、1サービス、1キャラクタリスティック(書込みのみ)を作ってみよう。
書込みすると、それに応じてLEDが点いたり消えたりする、という目論見だ。
黄色で囲んだところを変更させる。

image

↓↓↓

image

適当に名前を付けて、WRITEをMANDATORYにする。
WRITEとWRITE WITHOUT RESPONSEの違いは、結果が返ってくるか来ないかだけの違いなので、今回はどうでもよい。

後から読み返して分かるようにしておきたければ、この下にあるINFORMATION TEXTなどにメモを残しておけばよいだろう。
他の画面にも、同じような欄があるから、丁寧にやるときは入力しておくと、人に渡すときに親切だったり、数ヶ月後の自分に親切だったりするかもしれない。

これで名前は付いたものの、このCharacteristicが何バイトなのかとか、どういう設定ができるのかが決まってない。
これはFIELDを入力していくことになる。
画面下左にある「ADD FIELDS」をクリックだ。

image

NAMEと、FORMATくらいは入力することになるだろう。
ONとOFFの設定ができればよいので、8bitあればよいだろう。
名前はonoffにした。
入力したら「DONE」をクリック。


image

戻るので、「SAVE」をクリック。

これで、サービスの入力が終わった。
お疲れ様でした。

他の項目もきれいに入力しておくと、レポート出力機能でそれっぽいものをHTMLで出すことができる。
まあ、気が向いたらやってみるのもよいだろう。


ここまでできたら、nRF51822とAndroidのソースの自動生成をさせたいのだが、プラグインがまだ入っていない。
プラグインは、Bluetooth SIGからダウンロードしたり、Nordicのサイトからダウンロードしたりする。

Bluetooth Developer Plugins | Bluetooth Technology Website

下の方にプラグインの一覧がある。
今回は、Android Plugin v1.0と、bds_plugin_1.2.2_nRF5_SDK_11.0.0.zipを使う。
nRF5 SDKはv12を使う予定だが、まあ使えるんじゃなかろうか。

Androidのプラグインは、解凍するとファイルがべたっと入っているので、Android_Client1.0とでも名前を付けたフォルダを作って移動させる。
そして、フォルダごとプラグインフォルダに移動させる。
Windows10 64bitのデフォルトだと、C:\Program Files (x86)\Bluetooth SIG\Bluetooth Developer Studio\Plugins、の中に移動させる。
Nordicのプラグインは、解凍するとpluginsフォルダがあるので、その中に入っているNordic Semiconductor v1.2.2を移動させる。
Program Filesの中におくので管理者権限がいるのだが、まあよかろう。

 

もしBluetooth Developer Studioを立ち上げたままだったのであれば、プロジェクトを保存して立ち上げ直そう。
立ち上げ直してプロジェクトを開き、メニュー「TOOLS > GENERATE CODE」を選ぶとダイアログが開く。

一番上の「GENERATE CODE FOR」で、Server側かClient側かを選ぶ。
今回は、PeripheralがServerで、CentralがClientになる。
BLE NanoがServerで、AndroidがClientだ。
データを持っている方がServerになるので、PeripheralがServerになることが多いだろう。

下の「SAVE TO」に書いているフォルダに出力するので、ServerとClientは出力先を変えた方がよい。

image

image

 

nRF5用の生成ソース

image

 

Android用の生成ソース

image


では、BLE Nano側のビルドを行う。
オンラインmbedコンパイラで楽々、と行きたかったのだが、無理そうなのでKeiliでビルドする。
https://www.keil.com/demo/eval/arm.htm

ここが一番面倒かも。
まあ、ほどほどに入力すればよいだろう。
今だと、MDK522.exeがダウンロードされた。

Keilは面倒、ということであれば、gccでもよいだろう。
私は普段gccを使っているのだが、今回はなるべく手動を減らすことを目的にしているので、Keilにしたのだ。
まあ、gccを使える人であれば、ここから先は雰囲気さえ分かれば対応できると思う。

Keilをインストールし終わると、Packageのデータをダウンロードするので、待つ(下にプログレスバーが出る)。
終わったら、終了させよう。

次に、nRF5 SDKをダウンロードする。
v13はまだalpha版なので、v12.2.0をダウンロードし、適当な場所に解凍した。
あ、「適当な場所」というのは、フォルダ名に日本語とかスペースとか入っていないような、あまり深すぎない場所、という意味だ。
私は「C:\Prog\nrf5\nRF5_SDK_12.2.0_f012efa」という場所に置いた。
developer.nordicsemi.com:/nRF5_SDK/nRF5_SDK_v12.x.x/

解凍したフォルダの中に「examples\ble_peripheral」があり、そこに「experimental_bluetoothds_template」がある。
これをフォルダごとコピーして、同じ場所に別名でペーストしよう。
今回は「experimental_bluetoothds_nanoled」という名前にした。

そして「examples\ble_peripheral\experimental_bluetoothds_nanoled\pca10028\s130\arm5_no_packs」という場所に「bluetoothds_template_pca10028_s130.uvprojx」というファイルがある。
たぶん、緑色のアイコンになっていると思うので、それをダブルクリックするとKeilが立ち上がってくれる。
そうすると、おそらく足りないものをダウンロードするよう要求してくるので、YesYesいっておく。

ここまでやって「examples\ble_peripheral\experimental_bluetoothds_nanoled」を見ると、こうなっていると思う。

image

この中に、先ほど生成されたソースをコピーする。
上書きも気にせずやってしまう。

image

service_if.c,hは上書きになるが、ble_nanoled_service.c,hは新規なので、プロジェクトに追加が必要だ。
Keilの左側にあるツリーのApplicationで右クリックし「Add Existing Files to Group 'Application'...」をクリックし、追加しよう。

image

 

そして、ビルド!
・・・service_if.cでエラー発生。
これは、ログ周りが変更になったためと思われる。
どうせログは今回見ないので、こんな感じで無効にしておこう。

#include "app_trace.h"
  ↓
//#include "app_trace.h"
#define app_trace_log(...)

これでビルドすると、".\_build\nrf51422_xxac.axf"というファイルができたらしい。
axf、というのは、ARMのELF形式みたいなものだろう。
ARM社のコンパイラでビルドすると、axfファイルができるのだ。


まずは、ここまででBLEのCharacteristicが見えるかどうかを確認しておこう。

 

mbedは、USB接続するとファイルシステムとして見えて、そこにファイルを置くと焼いてくれる、というしくみになっている。

「components\softdevice\s130\hex」においてある「s130_nrf51_2.0.1_softdevice.hex」をD&D。
そうすると、親基板のLEDが高速点滅して、勝手にアンマウントして再接続された。
続けて、「examples\ble_peripheral\experimental_bluetoothds_nanoled\pca10028\s130\arm5_no_packs\_build」にある「nrf51422_xxac.hex」をD&D。
これも同じく。
焼き終わったら、一度はずして、付け直した方がよいのかな?

 

BLEのperipheralが動いているかどうかは、スマホアプリを使って確認するのが簡単だ。
私はnRF connectというNordicのアプリを使っている。
nRF Connect for Mobile - Google Play の Android アプリ

が、iOSだったらLightBlueに軍配が上がるかも。
LightBlue Explorer - Bluetooth Low Energyを App Store で

まあ、いろいろ使ってみるとよいだろう。
Android版の場合、動いていると「Nordic_BDS」という機器がAdvertisingしているので、CONNECTするとCharacteristicが見える。

image

矢印が上向きは、WRITEの意味。
UUIDは作ったときのものなので、ここまで同じ手順で作っていても別の番号になっていることだろう。

 

あっさり書いているが、実は焼くのに手間がかかっていた。
というのも、うちのBLE Nanoはいろいろやっていたためか、ファームウェアがmbedで使うものになっていなかったのだ。

RedBearLab BLE Nano | mbed
ここの回路図の下にある「Interface Firmware」の手順に従ってファームウェアを書き換えると、SoftDeviceのHEX→ビルドしたHEXの順に焼いて動くようになった。

HEXファイルをマージすると安心ではあるのだが、SoftDeviceを書き換えることはめったにないので、一度このようにして動くのが確認できれば、あとはビルドしたHEXだけをD&Dで焼けばよいはずである。
まとめるのは、mergehexというツールがあるようだが、上記手順までではインストールされなかったので、nRF Toolsに入っているのかもしれん。

動かなかったとしても、フォローできないので先に進もう。


ここまでで、BLE NanoのCharacteristicが見えていたなら、残っているのはCentralからの書込に応じてLEDの点灯状態を変更する、というところだけが残っていることになる。

Centralから書込まれると、service_if.cのon_nanoled_service_evt()が呼ばれ、case文のBLE_NANOLED_SERVICE_LED_EVT_WRITEに分岐することになる。
BLE Nanoに載っているLEDを変更したかったら、このcase文に書けばよいだ。

書込まれた値は、Bluetooth Developer StudioのFIELDで「onoff」という名前を付けたので、それでgrepしよう。
ble_nanoled_service_led_tというstructのtypedefに入っている。
そしてble_nanoled_service_led_tはble_nanoled_service_evt_t.paramsの中に入っている。
さっきのcase文が入っている関数はble_nanoled_service_evt_tが引数で渡されるので、そこからonoffを探せばよいだろう。

 

試したところ、BLE NanoのLEDは、GPIOの19番になっていた。
そして、アクティブLOになっていて、0で点灯、1で消灯のようだ。

service_if.cを以下のように変更すると、AndroidのnRF connectアプリでCharacteristic書込みを行うとLED制御できた。

  • bluetooth_init()
    • nrf_gpio_cfg_output(19);
  • on_nanoled_service_evt()
    • BLE_NANOLED_SERVICE_LED_EVT_WRITEの中
      • p_evt->params.led.onoffが0なら19番に1、0以外なら0書込み

 

static void on_nanoled_service_evt(ble_nanoled_service_t * p_nanoled_service, ble_nanoled_service_evt_t * p_evt)
{
    int onoff;
    switch (p_evt->evt_type)
    { 
        case BLE_NANOLED_SERVICE_LED_EVT_WRITE:
            app_trace_log("[Bluetooth_IF]: NANOLED_SERVICE_LED evt WRITE. \r\n");
            if (p_evt->params.led.onoff == 0) {
                onoff = 1;
            } else {
                onoff = 0;
            }
            nrf_gpio_pin_write(19, onoff);
            break; 
        default:
            // No implementation needed.
            break;
    }
}

 

uint32_t bluetooth_init(void) { ... nrf_gpio_cfg_output(19); nrf_gpio_pin_write(19, 1);

  ... }

修正したらKeilでビルドして、できたHEXファイルをBLE Nanoに書込む。
SoftDeviceは、消さない限りは前のが残っているようだ。

焼いた後は立ち上げ直して、スマホアプリからCONNECTし、Characteristicに0x00かそれ以外を書込めば、LEDが消えたり点いたりするはずだ。

BLE Nanoはここまで。


Androidアプリは・・・力尽きたので省略だ。

自動生成した中にbatファイルがあるので、Android Studioで新規生成したプロジェクトのフォルダを引数に指定して実行すると、ファイルがコピーされるようになっている。

以前のここを参照しておくれ。
http://hiro99ma.blogspot.com/2016/02/bleandroidbluetooth-developer.html

2016/12/23

[esp8266][rtos]RTOS版サンプル(TCP Client)はsocketを使ってない

TCPで通信するRTOS版のサンプルを動かしてみようとインストール先を見たが、なかった。
rtos_sdk_programming_guideを見るとsocket()が使えるようで、lwipらしいのだが、RTOS版のAPIドキュメントにはそこら辺は載っていないようだ。
socketが使えるのはRTOS版のよい点だと思うので、そこから見ていきたい。

 

名前からすると、githubのここでよいのだろうか?
espressif/esp8266-rtos-sample-code

これの、04Protocal/TCP_Client_Demoを動かそう。
たぶんProtocolの誤記だとは思うけど、キーボードで打ち込むときは間違えそうだ。

  • tcp_client/tcp_client.h
    • tcp_server_ipをサーバのIPに変更
    • ポート番号も、気に入らなければ変更
  • tcp_client/conn_ap.c
    • DEMO_AP_SSIDとDEMO_AP_PASSWORDを自分のAPに変更

このくらいで動く。
UARTログをデフォルト速度以外で見たいなら、uartのドライバを入れてuser_main()などで変更しよう。
デフォルトが中途半端な速度なのをなんとかしてくれんだろうか。。。

 

ビルドはできたものの、TCP clientとして動くので、サーバ側を用意しなければならん。
今回はStackoverflowで紹介されていたツールを使ってみよう。

RS232 terminal, serial port terminal, udp terminal, tcp/ip client server – Hercules

image

最初、APの設定を「隔離モード」にしていたので、PC側につながらずにRECONNECTを繰り返していた。

接続できると「Hello!This is a tcp client test」を受け取っている。
あとは、こちらが送信した文字列をエコーバックするだけのようだ。


本体は、ほとんどtcp_client.cに入っている。
しかしtcp_client.cの中には、UDPやらTCP serverやらも混ざっている。。。
tcp clientとしては、一番上からTcpLocalClient()までを使っていて、そこから下は不要のようだ。

じゃあ、ここからsocket()を見ていこうかと思ったら、無い!
PDFの書いてあるTCP clientの説明と違うじゃないか。。。

gitからcloneしたソースをgrepすると、openssl_demoとかmulticast_demoなどでsocket()を使っているようだったが、単純なサンプルには使っていなさそうだ。
だまされたのか。。。

 

よくわからんが、PDFにはコードも載っているし、書き換えてみるか。。

[win]c:\Windows\System32\bash.exeは特殊

やりたかったのは、ランチャアプリからBash on Ubuntu on Windowsのコンソールを起動したい、というだけのことだった。
それがここまではまることになろうとは。。。
そして、結果として動かすことができなかった。

 

WindowsのスタートメニューにBash on Ubuntu on Windowsのショートカットがあるのだが、

C:\Windows\System32\bash.exe ~

と単純なものだ。
しかし、これをランチャーに登録しても動かないというか、bash.exeが見えない。
cmd.exeの引数にしても、やはり見えない。
PowerShellでもダメだ。
でも、バッチファイルに書いてExplorerからダブルクリックすれば起動する。

Explorerでc:\Windows\System32を見るとbash.exeは見えるのだが、ランチャアプリの登録exeを探すOpenDialogみたいなダイアログからは見ることができなかった。
どうも、bash.exeは特殊な扱いのようだ。

 

このbash.exeはショートカットというよりも、Bashランチャーというものらしく、COMでうんたらかんたらと説明されていた。
なんかわからんが、exec系のAPIからは呼べないようになっているとか、そういうことじゃないかね。

テキストエディタから起動させて、今編集しているファイルと同じ場所に移動したbashコンソールを開きたいだけなのだ。。。
コンテキストメニューから起動させるというやり方のページはあったのだが、そこまではしなくてもよいのだ。

libusbも動かないし、やはりcygwinしかないのか。

 

ただ、c:\Windows\WinSxSの深いところにbash.exeがある。
これは単体で起動できるし、ランチャからも見える。
ちょっと困ったことに、今の私の環境ではbash.exeが2つある。。。
フォルダにバージョンらしき数字があるので、大きい方を使っているが、そもそもこれを使ってよいものかどうかもわからん。
アップデートされたら別フォルダになるだろうし、おすすめはできんな。

2016/12/21

[py]コンソールログを出力させたい

多少pythonにも慣れてきて、ことあるごとに出力させていたprintが邪魔になってきた。
が、全部消してしまうと困るかもしれないし、大幅に変更させるときにはまた復活させたくなるかもしれない。

そうなると、デバッグレベルに応じて出力させたりさせなかったりを制御したい。


「python ログ」で検索すると、こちらが出てきた(私はまだpython2.7を使っているのだ)。

Logging HOWTO — Python 2.7.x ドキュメント

「ロギングレベルをコマンドラインオプションから~」とあるので、pythonにそういうオプションがあるのかと思ったが、単に引数を解析してからやるだけのようだった。
もしかしたら、getoptみたいな関数があるのかもしれんが、調べる気力が無いので、第1引数をそのままロギングレベルと見なすように書いてみた。

import logging
import sys

loglevel = sys.argv[1]
# print 'getattr=', getattr(logging, loglevel.upper(), None)
numeric_level = getattr(logging, loglevel.upper(), None)
if not isinstance(numeric_level, int):
    raise ValueError('Invalid log level: %s' % loglevel)
logging.basicConfig(level=numeric_level)

logging.debug('debug')
logging.info('info')
logging.warning('warning')

INFO、とするとinfoが出るし、DEBUGとすればdebugも出てきた。
コンソール出力を「> log.txt」にしても空っぽで、「2>&1」を追加すると入ったところからすると、標準エラー出力がデフォルトのようである。
まあ、ファイルに保存する設定もあるから、そこまでリダイレクトしたいことはないのかもしれんがね。


これくらいは用は足りそうなのだが、loggingページのまだ最初の方だ。
もっと便利な何かがあるのだろうか?

変数の表示が%で指定するタイプだ、とか、時刻を入れるフォーマットにできるよ、とか、そういうのがちょっと書いてあって、あとは上級編になるようだ。

ちょっとだけ眺めてみたが、loggingは、logger, handler, filter, formatter、の4つから構成されているようだ。
こんなに複雑だったのか・・・。
自分でいろいろ指示することによって、カスタマイズできるようになっているようで、クックブックのページも用意されていた。

Logging クックブック — Python 2.7.x ドキュメント

 

まあ、そこまで踏み込まなくていいな。

  • 地の文:print
  • 普段はいらない、細かいデバッグ出力:logging.debug()
  • 問題ないかもしれないけど念のため忠告の出力:logging.info()
  • ちょっとないかもねー、バグってんじゃないの?の出力:logging.warning()
  • これはダメだー、の出力:logging.error()

私の場合は、debugとerrorがあればまだ足りるかな。
errorも、その後はquit()で終わらせるしかないなら、もうprintでもよい気がする。
ログ出力できるほど優雅じゃ無い環境が多いので、自由に出してよいといわれると困るのよねぇ。

2016/12/20

[sqlite]最後の行を更新するのに悩む

python経由でSQLite3を使っているのだが、直接pythonとは関係が無い話だ。

最後にINSERTしたデータの一部をUPDATEしたかったのだが、何だかうまくいっていない。。。
まったく失敗しているというわけでもないようだが、期待したところが更新されていないので、うまくいっていないのだろう。

 

やっていたのは、どこかのページで見つけたやりかただ。

UPDATE tbl SET data1=? WHERE rowid=last_insert_rowid()

?のところは、pythonだとexecute()の引数に書けるのだが、まあそこは関係ないので省略しよう。
ともかく、これがうまくいかない。

エラーは出ていないので、SQL文は間違えていないのだろう。
検索すると、last_insert_rowid()でうまくいかないというところも見つかったのだが、まずは根っこを探そう。

 

Last Insert Rowid

sqlite.orgのページだ。
WITHOUT_ROWIDしていないなら使える。
返すのは、rowid of the most recent successful INSERT、だ。
INSERTに成功していなかったら0を返す、とある。
でも、INSERTは何度かしているし、データを見ても列はあるから、INSERTしていないはずはないのだが。。。

と思ったら、読み飛ばしていた。

have ever occurred on the database connection D

接続してから、でよいのかな。
だったら、なんとなく納得だ。
どこかでクローズしたりしていた気がするのだ。

 

コマンドのsqlite3で見ておこう。

SELECT rowid,* FROM tbl

これで、tblに入っているデータがrowidと一緒に出力される。
そうか、rowidは1から始まるから、last_insert_rowid()が0を返すとどれにも引っかからないのだな。

SELECT rowid,* FROM tbl WHERE rowid=last_insert_rowid()

うん、出てこない。

SELECT rowid,* FROM tbl WHERE rowid=last_insert_rowid()+1

うん、1行目が出てきた。
ということは、やはり0が返ってきていたのだろう。

 

今回の私は、UPDATE文で使いたいので、たぶんWHRER節でやってやらないといかんだろう。
もっと便利なやり方があるのかもしれんが、知らん。

UPDATE tbl SET data1=? WHERE rowid=(SELECT max(rowid) from tbl)

うむ、これでよさそうだ。

2016/12/19

[esp8266][rtos]SmartConfig+ESP-TOUCHで接続できた

タイトル通りだ。
ESP-TOUCHはAndroidのAPKを、SmartConfigはRTOS版を使った。

image

 

ESP8266側は、立ち上げると何かコンソールに出るので、Androidの"Confirm"をタップすると勝手にやってくれた。

mode : sta(xx:xx:xx:xx:xx:xx)
add if0
SC version: V2.5.4
scandone
scandone
scandone
SC_STATUS_FIND_CHANNEL

TYPE: ESPTOUCH
T|AP MAC: xx xx xx xx xx xx
SC_STATUS_GETTING_SSID_PSWD
SC_TYPE:SC_TYPE_ESPTOUCH
T|pswd: xxxxxxxxxxxxxxx
T|ssid: xxxxxxxxxxxxxxx
SC_STATUS_LINK
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 1
pm open phy_2,type:2 0 0
cnt

connected with xxxxxxxxxxxxxxx, channel x
dhcp client start...
ip:192.168.xx.xxx,mask:255.255.x.0,gw:192.168.xxx.xxx
SC_STATUS_LINK_OVER
Phone ip: 192.168.xxx.xxx

 

SmartConfigの方は、AirKissの検出もあるようだから、WeChatクライアントでもつなげられるのかもしれない。

手軽でよいのだけど、特定のアプリからしか設定できないとか、そういうしくみを入れられるのだろうか?
どこまでやれば安全なのかは考えないといかんけど、違うAPに接続してしまう、というようなのは避けたいな。

2016/12/18

[esp8266]SmartConfig == ESP-TOUCH

ESP8266のAPIにSmartConfig APIというものがあり、設定に使えそうな感じがしている。
"SmartConfig"というドキュメントはなかったが、ESP-TOUCHというドキュメントを見ると、ESP-TOUCHというプロトコルがSmart Config技術を実装したものらしい。

http://espressif.com/sites/default/files/documentation/30b-esp-touch_user_guide_en_v1.1_20160412_0.pdf

image

スマホにESP-TOUCHアプリが載っていたら、APからSSIDとパスワードを取得し、それをESP8266に伝えられる、というような図に見える。

 

このESP-TOUCHもあるし、AirKissというプロトコルをWechatが作ってくれてるから、それでもよいんだとか。
Wechatって、中国でよく使われているLINEみたいなサービスがWeChatという名前なのだけど、それなのだろうか?
AirKiss APIにリンクがあり、そこを見る限りはそれっぽかった。
AirKissという名前は別のところで聞いたことがあるから、そういうプロトコルがあるのかもしれん(探しきらんかった)。

 

ESP-TCOUHアプリは、githubにソースごと載っている。
https://github.com/EspressifApp?tab=repositories
「ForRTOS」というのが別アプリになっているのだけど、RTOS版は開発を止めるようなことが書かれているので、付いていない方を見ておけばよいのだろう。

 

iOS版は、Espressifさんが出しているようだ。たぶんだけど。iTunes Previewって初めて聞いたわ。
Espressif Esptouch on the App Store

Android版は、IOTなんとかはあるけど、ESP-TOUCHがないのだな。。。
https://play.google.com/store/apps/details?id=com.espressif.iot&hl=ja

他の人がSmartConfigアプリをアップしているが、さすがにこの手のアプリを使うのは怖いから、せめてEspressifのダウンロードページから取得したものを使う方がよいか。。。
https://espressif.com/en/support/download/apks

でも、ダウンロードページの方はバージョンがV0.3.4.3で、iTunes PreviewはV1.2.0。
githubのForIOSはv0.3.5.2、forAndroidはV0.3.4.5と、なんかバラバラだ。
iOS版は、OSバージョンの都合で上がったりしているのかもしれんが、せめてiTunesにアップしている方とのつながりがわかるようにしてほしいものだ。


関係ないけど、半年前のことらしいが、ESP8266のオライリー本が出ているそうな。
マイコンで本が出たりするんだねぇ。

ESP8266 Joins the O’Reilly Animal Books Series | Espressif Systems

[esp8266]WPSがうまくいくAPといかないAPがありそう

ESP8266のAPIにWPS関係のものがあるので試してみたのだが、どうもうまくいかない。

実装が悪いのかを切り分けるため、ATコマンドの方でやってみた。
Factory Resetして、AT+CWMODE=1でstation modeにして、AT+WPS=1で開始。

 

Buffaloのほうはつながったのだが、NECのほうはつながらなかった。。。
WR4100Nという、もうずいぶん前のAPではあるのだが、つながる/つながらないがあると困るのだ。
SSIDを指定すればつながっていたので、WPSだけの話だろう。
念のためAndroidでやってみたが、接続できたし。
まあ、BuffaloのAPを買うまでは主力として使っていたのだから、使えるはずなのだ。

 

そうなると、ESP8266ではWPSよりもSmartConfigとかいうやつを使った方が確実なのかもしれん。

2016/12/17

[esp8266][rtos]サンプルを斜め読み

そろそろ、何か作ってみないと、正月を迎えてしまうと何もしないまま年度末の慌ただしさに巻き込まれてしまうに違いない。。
特に作りたいものがあるわけではないので、まずはサンプルを眺めてみよう。
眺めるだけで、深入りはしない。

 

NonOS版のexamples。

image

RTOS版のexamples

image

たぶん、RTOS版でFreeRTOSの機能を使わなければ、NonOS版と同じ動きになるのだと思う。
今日(2016/12/17)の時点では、NonOS版はV2.0.0(patchあり)、RTOS版はV1.5.0が最新となっている。
なお、RTOS版は1.5.0のタグが作られていない(コメントで1.5.0になっている)ので、確定じゃ無いのかもしれない。

ここに貼ってるgithubのリンクは、今日の最新のcommit(2016/11/09)にしているので、今の最新版では無いかもしれない。
そこはご注意くだされ。


project_template

これはシンプルで、実際の動作としてはSDKバージョンをprintf()するだけだ。
さすがテンプレート。

 

smart_config

昔から気になっていたものの、動かしたことがないsmart_config。
名前からすると、設定ができそうなのだが。。
SmartConfigはNonOS版でも専用APIがあるくらいなので、ドキュメントも充実しているのでは?

ドキュメントの一覧を見たが、よくわからん。
APIしか出てこないのだろうか。

ESP8266はモードとして、STATIONモード、APモード、その両方、の3種類がある。
STATIONモードはAPにつなぐモード。APモードは自分がAPになるモード。
SmartConfigは、STATIONモードでしか動作しない。
私のイメージでは、自分がAPになって「誰か接続して設定しておくれ~」という動作なのかと思っていたのだが、そうじゃないんだなぁ。

説明を読む限りでは、つなぐ先の情報をブロードキャストしていたらESP8266が接続してくれる、というように感じた。
WPSみたいなものか?

しかし、WPSと絡めて検索しても情報が出てこない。。。
Smart Plugなんてものすら出てきてしまったので、これは後日調べよう。

 

spiffs_test

名前からすると、SPIでつながっているFlashにFileSystemを作ろう、というところだろうか。
大したサイズではないのだけど、自前で管理するとやはりめんどうなのだ(ああ、めんどうだったさ)。
ぎりぎりまで使わないと足りない場合は、自分でやらんといかんだろう。

元はこれらしい。
pellepl/spiffs: Wear-leveled SPI flash file system for embedded devices

が、これだけで終わらず、SSC APIというものもspiffs_testに関わっているようだ。
SSCは、Simple Serial Commandの略。

サンプルもファイル数が多いので、必要があるときまで忘れておこう。

 

websocket_demo

まず、websocket、というものがあるらしい。
検索するといろいろ出てくる。。。が、ここではIPAのリンクを載せておこう。
一番下に"2007"とあるので、たぶん2007年に書かれたものなのだろう。

IPA ISEC セキュア・プログラミング講座:Webアプリケーション編 第9章 Web関連技術

とりあえず、サーバとクライアントの間で双方向通信したいためのプロトコルらしい。
だいたい、サーバは待ち、クライアントがアクションを掛ける、というイメージがあるのだが、サーバからも送りつけたい場合なのだろう。

サンプルではSTATIONモードになっているから、自分はクライアントということか。
なんか、STATIONって駅だから、電車が来るのを待っている姿をイメージして、APの動作になると勘違いしてしまうのだよなぁ。

このサンプルは、SSIDやパスフレーズがべた書きになっているから、それなりに書き換える必要があろう。
しかし、それ以前に、どういうアプリを用意したらよいのだろう?


すまん、この辺で私が力尽きた。

websocketがサーバからの通知に注力してるのだったら、常に接続状態にしていないといけないだろうから、それだったらBLEでいいやん、と思ってしまったせいかもしれない。
WiFi-AP用のBLE規格、みたいなものがあればよいのだけど、多少マニアックな感じがするから、そういうのは出てこないだろうねぇ。

 

さて、この中で何をRTOS版でやってみたいかというと。。。特にないな。
かろうじて、SmartConfigが気になっているというところか。
今はソースにSSIDやパスフレーズを埋め込んでいるのだけど、外部から設定できるようにしたいのよねぇ。

[esp8266][rtos]driver_libのビルド

UoWでビルド環境は作ったが、RTOS版のサンプルがビルドできるかを確認していなかった。

examples/project_templateをどこかにコピーして、SDK_PATHとBIN_PATHを環境変数として設定し(gen_misc.shを変更するよりも、環境変数設定用のスクリプトを用意してsourceなどで読ませた方が都合がよさそう)、実行するたびにQIOとか40MHzなどの入力をするのが面倒だからgen_misc.shを変更。

githubのESP8266_RTOS_SDKはNTFS側にcloneしているが、ビルドはできた。
project_templateはSDKバージョンをprintfするだけのようなので動かしたのだが・・・化ける。
そう、ESP8266のUARTはデフォルトで変な速度なので、USBシリアル変換チップがその速度に対応していないうちの環境では見るのがめんどくさい(ロジアナなどで見ることはできるが)。

UARTの速度変更はuart_init()でできるのだが、使うにはUARTドライバがいる。
というわけで、driver_libをビルドすることにした。


以前はuart.cだけをプロジェクトにコピーして使っていたが、今回はdriver_libに入っているmake_lib.shを使うことにした。
README.mdを読むと、これでビルドできるそうだ。

$ ./make_lib.sh driver

 

が、最初はビルドに失敗していた。。。
どうも、includeパスなどが見えていないようで、コンパイルしている様子を見ても確かにパスがおかしい。

で、環境変数SDK_PATHの設定が必要だった、ということに気付いたわけだ。
gen_misc.shに設定して使っていたので、いっそのこと設定用のスクリプトを作るようにした。

そうすると、コンパイルは進むようになったが、i2c_master.cでまたエラーになった。
これは、RTOS版とNonOS版のバージョン違いによるものかもしれないが、今回はRTOS版のdriver_libにあるi2c_master.cに以下を追加することで対応した。

#include "esp8266/eagle_soc.h"
#include "esp8266/gpio_register.h"

 

これでlibdriver.aができ、RTOSのlib/にコピーされた。


では、これでuart_init()が使えるかと思ったが、リンクでエラーになった。
uart_init(SPEED0, SPEED1)の形式はNonOS版のドライバで、RTOS版はそういうのがないのだ。

やるなら、uart_init_new()をまねして、UART_ParamConfig()を使うほうがよさそうだ。

void user_init(void)
{
    UART_ConfigTypeDef uart_config;

    UART_WaitTxFifoEmpty(UART0);
    uart_config.baud_rate    = BIT_RATE_115200;
    uart_config.data_bits    = UART_WordLength_8b;
    uart_config.parity       = USART_Parity_None;
    uart_config.stop_bits    = USART_StopBits_1;
    uart_config.flow_ctrl    = USART_HardwareFlowControl_None;
    uart_config.UART_RxFlowThresh = 120;
    uart_config.UART_InverseMask = UART_None_Inverse;
    UART_ParamConfig(UART0, &uart_config);
    printf("\n\n\n");
    for (int lp = 0; lp < 10; lp++) {
        printf("SDK version:%s\n", system_get_sdk_version());
    }
}

なんでforで回しているかというと、最初の「SDK」が出力されなかったので、どこから速度が変わったのか確認するためだ。

version:1.5.0-dev(950076a)
SDK version:1.5.0-dev(950076a)
SDK version:1.5.0-dev(950076a)
SDK version:1.5.0-dev(950076a)
SDK version:1.5.0-dev(950076a)
SDK version:1.5.0-dev(950076a)
SDK version:1.5.0-dev(950076a)
SDK version:1.5.0-dev(950076a)
SDK version:1.5.0-dev(950076a)
SDK version:1.5.0-dev(950076a)

10個は出ているので、最初の数文字分が間に合っていないというところか。

しかし、TXFIFOのemptyを待っているのにダメということは、最初がHWフロー制御になっているということだろうか?
この、システムが勝手に出力するというやつがやっかいなのよねぇ。

[uow]TABを押すとbeep音が鳴るのを止めたい

Bash on Windowsのコンソールで、ファイル名補完などでTABを押すと、ビープ音が鳴る。
うるさい。。。。

Disable beep of Linux Bash on Windows 10 - Stack Overflow

たぶんLinux系全般なのだろうけど、鳴っていなかったので気にしたことがなかった。
私は、/etc/inputrcを変更する方で対応できた(もう片方は試していない)。

[esp8266]BoUoWでesp-open-sdkはほどほど動く

Bash on Ubuntu on Windows。
もう、何と略してよいのかわからん。。。
今回は、BoUoWとしたが、これだと「ばうわう」と犬の吠える声っぽくなってしまうぞ。

 

ともかく、BoUoW上でesp-open-sdk環境をビルドした。
今回はノートPC環境で行ったためか、BoUoWだからかわからないが、倍の時間がかかった。
i5/6200U 2.3GHzで40分くらいだったんじゃなかろうか。

 

まずは、前回作った、sdkディレクトリ内に置けばビルドできるプロジェクトで試した。
これはビルドできた。
焼いても動いたように思う。

ただ、BoUoWのディレクトリ内にファイルがあるとエディタが使いづらいので、NTFS側にソースを置いて、xss側はシンボリックリンクしてみたら、それはビルドができなかった。
makeがうまく進まないのだ。

シンボリックリンクしたディレクトリに入ってからls ..しても、1つ上のディレクトリが見えないのが気になる。
Linuxでもそうだったっけ・・・?
位置としては、../binにフォルダがあるのだけど、それもNot Foundになってしまう。

じゃあ、別のxss内にコピーして、そこをln -sしたらよいのでは?と思ったが、そうでもない。
その場合、lnしたフォルダにcdしてからls ..すると、オリジナルの場所からls ..したのと同じものが見えるようなのだ。
最近、Linuxで作業していなかったから、ルールが変わってしまったのだろうか?

なんにせよ、これはけっこう面倒な話だ。

じゃあ、NTFS側にsdkの元フォルダごとNTFS側にコピーして、そこをシンボリックリンクしてみた。
・・・ダメだ。
lsすると見えるフォルダにcdで入ろうとしても、入っていかない。
なんじゃこりゃ?

 

だが、シンボリックリンクを張らずに、直接/mnt/c/xxxに置いたフォルダにcdで移動してしまえば、それはうまくいった。
シンボリックリンクがうまくいっていないというだけかもしれない。

2016/12/16

Git Extensions 2.49でcloneのフォルダが前と違う

http://hiro99ma.blogspot.com/2016/11/gitwingitextensions-249.html

Git Extensionsがv2.49になって使っているが、cloneが以前と違うので多少困っている。

 

たとえば、D:\Prog\tmp\abc、というフォルダの下にcloneしたかったとしよう。
シェルと統合していれば、コンテキストメニューから「Clone」を選ぶことができる。

image

以前は、Destinationに選択しているフォルダ名が入っていたように思うが、1つ上のパスになったようだ。

ここでリポジトリを入力すると、こうなる。

image

Subdirectory to createがリポジトリ名になるのは以前からなのだが、このままやってしまうとabcというフォルダの下ではなく、その上にcloneされてしまうのだ。

何回かcloneしても場所が違っていて、操作を間違えたかと思ったのだが、そういうことらしい。

 

せめて、Subdirectory to createがカレントディレクトリのままであれば、選択したフォルダにそのままcloneするようになる、という解釈もできたのだが、コンテキストメニューで使うコマンドが変更されたりしたのだろうか?

解決してないので、なんかわかったら追記しよう。

2016/12/15

[win10]Home版でもwuauservを止めればWindows Updateは動かないようだ

Windows10 Homeで、ネットにつないだままにしたいけどWindows Updateが走って再起動されたら困る、に対応したい話の続きだ。

http://hiro99ma.blogspot.com/2016/11/win10homewindows-update.html

今週は水曜日がWindows Updateの日だったので、月曜日くらいからwuauserv(Windows Update Service)を止めて様子を見ていた。
スリープ復帰したり、再起動したりしたが、Windows Updateは動作しなかった。
しなかったと思う。
再起動しなかったし、「更新とセキュリティ」を開いても何もならなかったので、あれでよいのだろう。

 

なんというか、喜びも何もない。。。
えん罪で捕まって、何もかも失った後に裁判で勝利したが、何も残らなかった、という話を聞いたことがあるが、そこまではないにしても、作業中に有無を言わさず再起動されて失ったものは、もう元に戻らないのだ。

自分(Windows)を安全に保とうとするばかりに過剰な反応をしてしまうという点では、アレルギー反応に近いのかもしれない。
その防御機能であるwuauservを止めるのは、本末転倒ではあるけれども、他にどうしようもないようだ。

 

ちなみに、アップデートが済んで、再起動待ちの状態でwuauservを停止しても、それはダメでした。
再起動時間を指定していたせいかもしれませんが、時間が来ると再起動された。
ということは、スケジューラの方に何か登録されていたのだろうか?

今となっては、知るよしもなかった。。。

2016/12/14

Android Things ?

Google、新IoTプラットフォーム、Android Thingsをデベロッパー向けにプレビュー公開 | TechCrunch Japan

なんだろうね、IoTって・・・。

 

もう、そういう話をするのはやめて、中身だけ見ていこう。
Android Things | Android Things

 

SDKのOverviewに載っている図がわかりやすい。

""

Linuxだ。

そして、今のところ、こういうのに向けたプラットフォームが出ているようだ。
Developer Kits | Android Things

  • Intel Edison
  • NXP Pico i.MX6UL
  • Raspberry Pi 3

 

というところからもわかるように、けっこうなスペックがいる。
とりあえず、Linux上で動く、というところが既に壁が高い。
もう少し時代が進んで、電池で数ヶ月動くLinuxがマイコン内で動く、というところまでいけばよいのかな。
あるいは、備え付けられるような機器であればすぐにでもよいのかも。

一昔前のAndroid端末で動かす、というのもありなのか?
端末と言っても、BeagleBoardとかBoneのような、Android2くらいだったらかろうじて動かせたような組み込み機器だろうけど。
でも、今出ている上記3つはCortex-Aだから、スペックが足りないかもなぁ。。。

Bluetooth5.0 FAQ (3) - capacity

Bluetooth5.0 FAQを読むシリーズの最終回。
bandwidth x 2、range x 4ときて、最後にcapacity x 8だ。

 

うまいこと伝えられない気がするので、FAQの原文を載せておく。

Up to 8x the broadcasting message capacity over Bluetooth 4.2, with support for larger data packets: 31-octet to 255-octet packages.
Ability to offload advertising date from the 3 advertising channels to up to 37 broadcasting channels.

タイトルでは「capacity」と書いたが、実際には「broadcasting message capacity」だ。
そして、31バイトが255バイト(octetだけど、バイトでいいや)となっていることからもわかるが、どうもAdvertisingのことを話しているようなのだ。

また、その次にチャネル数のことが出ているが、Advertisingするチャネル数が3つから37に増えた、と。
以前見た、Secondary Advertisingとかいう、あれだろう。

 

バイト数もチャネル数もBluetooth 4.2までの仕様とずいぶん違うので、使い分けるようになっているはずなのだが、どうやるのだろう?
Advertisingなんて、まだ相手がいないときだから、使い分けるも何もあったもんじゃ無いように思うのだ。


まずチャネルだが、いつものAdvertising(表ではPrimary Advertisingになっている)はいつものチャネルで、新しいSecondary AdvertisingのチャネルはPrimaryと重ならないようになっている。

image

Primary Advertisingは、データで使うチャネルやWiFiの周波数と重ならないように選ばれていたはず。
どういうことになっているかというと、[Vol 6, Part B]4.5.8 Data Channel Index Selectionあたりに書いてあるそうだ。

・・・ごめん、長いので読むのはあきらめた。。。

[Vol 6, Part  D]4.6 Acrive Scanning on the Secondary Advertising Channelを見ると、どうやらADV_EXT_INDというものが増えているようだ。
そういう目線で見てみると、[Vol 6, Part B]4.6.12章にLE Extended Advertisingという章があり、追加されたと思わしきPDUが載っていた。
そして、255octetという文字もあることから、新しく追加されたものは新しいPDUで行うようになっているということだろう。
新しいPDUはBluetooth4.2までのBLEでは処理されずにスルーされるだろうから、別に問題ないのかな。
新しい酒は新しい革袋に、か。

 

しかし、チャネルがデータチャネルとぶつかるので、邪魔なんじゃなかろうか?
こういうAdvertisingを使うときは、データではなくAdvertisingが目的の環境で使うことを前提にしているのか。。。

 

いかんいかん、こういうことはすぐに結論を出してはいかんな。
もう少し調べてからにするのがよいだろう。

ともかく、Bluetooth5.0にありそうな大きい変更内容はわかったんじゃないかと思う。
仕様変更というよりも追加なので、誰がどのように5.0の機能を使ったデバイスを出すかは興味深いな。

2016/12/11

[esp8266]接続

ビルドまでできたので、接続して確認しよう。

うちは、スイッチサイエンスさんから買った、小さい方のボードを使っている。
ESP-WROOM-02ピッチ変換用基板《シンプル版》 (基板のみ) - スイッチサイエンス

image

基板の裏にチップ抵抗10kΩを2つハンダ付けしているので、あとはFLASHを焼くときのためにGNDに落とすためのスイッチを2つつないでいる。
GPIO2はGND、GPIO15は3.3Vにしておき、GPIO2だけでブートか焼くのかを決める。

 

電源がUSBから取ってくる程度では足りないので、ACアダプタを使うようにした。
3.3V 1.2Aのが転がっていたのでつないでみたら、動いた。
使わなくなった機器も、ACアダプタだけは捨てずに残しておくと、こういうときに使える。

コンデンサがあると消費電力が一瞬上がった場合にも安心できるが、1.2Aもあれば大丈夫なんじゃないのか?
そういうときはexceptionで動けなくなるから、わかるだろう。
レギュレータとかがあればUSBからの電源でなんとかなるのかもしれんが、あまりそういうのは詳しくない。。

 

焼くためのツールは、ここからダウンロードした。
Tools | Espressif Systems
うちはWindowsなので、V3.4.4を使っている。

image

今回は初回だったので全部焼いたが、開発中は2番目のだけ焼けばよいだろう。

 

gitに置いていたものを焼いた(もちろん、SSIDなどは変更してビルド)ら、ちゃんと動いた。
まあ、コンパイル環境が変わっただけなので、当たり前といえば当たり前だ。

RTOS版として動かすには、ちゃんと中身を作り替えねば。
これはもう来週かなぁ。

2016/12/10

[esp8266]Non-OS用のプロジェクトをesp-open-sdkに変更

以前作っていたNon-OS用のプロジェクトを、esp-open-sdkでビルドできるようにした。
が、いろいろ制限がある。

https://github.com/hirokuma/esp8266_httpget/tree/opensdk

 

まず、置く場所。
esp-open-sdkの中にsdkディレクトリができていると思うが、その中に置くことになる。
ビルド中に相対パスで見に行くところがあって、動かせなかった。
sdk内のMakefileを書き換えるとたぶんどこでも置けるようになると思うが、試していない。

もう1つは、ファイルの削除。
これはesp-open-sdkをビルドした後に1回だけやればよいのだが、esp-open-sdkの直下にあるMakefileを削除するなりリネームするなりしておくこと。
これもsdk内のMakefileと関係するのだと思うが、上位ディレクトリにあるMakefileを自動的に実行しようとしてしまうのだ。
そうすると、またesp-open-sdkをビルドしようとして失敗するので、Makefileがない状態にしておけばよい。

それ以外は、環境変数になる。
前回ビルドしたとき、最後にincludeパスとlibパスが表示されたと思うが、あれをXTENSA_INCLUDEとXTENSA_LIBに設定しておくようにしている。
気に入らなければ、gen_misc.shやMakefileを変更してもらえばよかろう。

 

これでビルドはできるが、動作確認はしていない。
まあ、動くんじゃないの?程度だ。
こういうのは、だいたい後で「やっておけばよかった。。。」と思うのだけど、まあいいや。

Bluetooth5.0 FAQ (2) - range

Bluetooth5.0のFAQ[pdf]を読んでいくシリーズ2回目。

  • 2x bandwidth
  • 4x range
  • 8x broadcasting message capacity

よく見たら、前回のbandwidthも今回のrangeも「with low energy」と書いてあったので、BLEだけの話なのだな。


rangeだと「範囲」と読んでしまうのだが、どちらかといえば距離っぽい気がする。
同じ送信パワーでも4倍のlonger rangeでいけるぜ、というところか。

 

Bluetooth SIGのホームページに、range関係らしきドキュメントがあった。
Range Whitepaper[pdf]
技術資料ではあるが、BL600などの名前が柱に出てきているので、企業が作ったもののようだ。
こういう団体が出すようなドキュメントは中立的なものかと思っていたけど、「ホワイトペーパー」というものは企業が自社宣伝も兼ねて作るものらしい。

これを眺めたら、4倍になる理由が分かるかと思ったけど、それっぽい比較表がなかった。
ちゃんと読めばわかるのかもしれんが、計算によって理論的な距離が出せるという読みものではないかと思われる。

 

こういうときは、再びsilexさんのブログを読もう。
Bluetooth 5 のはなし|Wireless・のおと|サイレックス・テクノロジー株式会社

「無線通信の世界に魔法はありません」。
まったくです。
基本的には計算であれこれやって、あとはノイズとか反射とかの外乱が出てくるけど、プロトコルによって距離が変わるということはあり得ないはず。
あるとしたら、ノイズに4倍強い(計算上)方式になったとか?

もうちょっと読むと、4.2での上限が-20~+10dBmだったものが、5.0から-20~+20dBmになったんじゃないの?という推測になっていた(記事の時点では、まだCore_v5.0が出ていないため)。

さっきのPDFの表が、こうなってました。

image

ちなみに注釈1は「Minimum output power at maximum power setting」とのことで、最大出力設定時の最小出力、だと思うのだけど、技術用語的に微妙な違いがあるのかも。

 

計算のことはわからんので、Core_v5.0の変更で範囲が変わっているか確認しよう。

まず、v4.2から。
[Vol 6, Part A]3. Transmitter Characteristicに表があった。

image

では、v5.0の同じ章を。

image

ふむ、そのようだ。
また、以下の表が追加されていた。

image

これが、ホワイトペーパーに載っていた表ですな。
BR/EDRのようにclassができたということか?
v4.2までの最大は、class1.5に相当するのだろう。

 

なので、仕様上(かつスペック上)、v4.2と比べて4倍の距離が出せるような送信パワーを許容した、というところか。
距離を出したければ頑張れ、ということだろう。

前回のbandwidthもそうだけど、技術的革新で!というわけではなく、仕様の枠を広げたというところだ。
いや、難癖を付けているわけじゃないし、これはこれでよいと思うのだ。
ただ、同じハードを持ってきて「Bluetooth5にして距離を伸ばせ!」とか言われても、いやいやそうじゃないんですよ、という話はできないといかんので、実装する人は概要を把握しておいた方がよいだろう。

また、周波数帯とかパワーが変わるとなると、技適も取り直しになるのかな?
そこら辺は詳しくないのだが、出力する内容が変わるのだったら、再提出くらいはいりそうな気がする。

[py]sqlite3のNoneは文字列のNone

久々のpythonで、ちょっとはまってしまった。
コードを先に示した方がよいだろう。


import sqlite3

dbconn = sqlite3.connect('dbtest.db')
dbcur = dbconn.cursor()
dbcur.execute('CREATE TABLE test(id1 INTEGER, id2 INTEGER)')
dbcur.execute('INSERT INTO test(id1) VALUES(?)', (1234,))
dbcur.execute('SELECT * from test')
items = dbcur.fetchall()

print 'item[0]=', str(items[0][0]).encode('hex')
print 'item[1]=', str(items[0][1]).encode('hex')


id1とid2というカラム(でよいのかな?)を作り、id1にだけ値を設定する。
そしてSELECTして、id1とid2をencode('hex')して見てみる、というだけだ。

encode('hex')だから、ASCII文字はASCIIコードで出力される。
id2には何も設定していないが、どうなるだろうか?

item[0]= 31323334
item[1]= 4e6f6e65

さあ、予想通りだっただろうか?

item[0]はよそうどおりだったけど、item[1]は「そうくるか!」というのが正直な感想だ。
まさか、"None"を文字列としてASCIIコードにするとはなぁ。。。。

 

おかげで、"None"と出てくるか、エラーになるだろうと思ってやっていたので、発見が遅れてしまった。。。

2016/12/08

Bluetooth5.0 FAQ (1) - bandwidth

FAQって、発音の仕方に悩むよねぇ、というのはさておき、Bluetooth5.0のFAQがあったので眺めてみよう。

そういえば、もともとBluetooth4は、BLEだけじゃなく、今までのBR/EDRが入っていたのだが、それが5になってどうなったのだろうか?

image

変わらないのね。。。
共通になっている内容もあるのだけど、検索して読むと同じキーワードで使われ方が違ったりすることもあって、面倒なのよねぇ。


まず、increased bandwidth、ということが出てくる。
バンド幅が広がったということは、周波数帯が広がってチャネルが増えたのだろうか?

[Vol 6, Part B]1.4.1の表を見ると、少なくともBLEについては40chのままのようだ。

image

なんだ、Secondary Advertisingって??
まあ、そういう細かいところは見ないようにしないと、終わらん。

 

そもそも、bandwidthと書いているが、出ているのは速度についてだ。
複数chを同時に使うことで、一度に転送できる量を増やすということだろうか?

[Vol 6, Part A]1.Scopeに「LE 2M」という言葉が出てくる。
1M sym/sのモジュレーションは、以下の2つがあり、LE 1Mの方はshallだから必須。

  • LE 1M
  • LE Coded

そして、2M sym/sのモジュレーションは、LE 2Mだけで、これは必須かどうかはここに書いていなさそうだ。

比較のためCore_v4.2の同じところを見てみたが、そもそもLE 1Mという用語がない。
"4.6 Reference Signal Definition"に、かろうじてBit Rate=1Mb/sという言葉が出てくる程度だ。
なお、Core_v5.0の4.6章には、LE 1MPHYが1Mb/sで、LE 2M PHYが2Mb/sとなっている。

雰囲気からすると、このLE 2Mというのが、bandwidthがx2になったというやつなんじゃなかろうか。
しかし、私は変調方式とかそういうのはさっぱりわからんのだ。。。

 

こういうときは、silexさんのブログを読むに限る。
Bluetooth 5 のはなし|Wireless・のおと|サイレックス・テクノロジー株式会社

このブログ自体は5.0が出る前なので情報をたどる形になっているが、速度2倍については、変調方式がPSK変調ではなくGFSK変調のままにすることで実現した、ということらしい。
なんとなく、PSK変調というのはGFSK変調の2倍大変だから、GFSK変調だったら2倍送れるやん、ということのように読み取ったのだが、どうだろうか。。

そしてCore_v5.0の4.6章の最初に、確かに「変調方式はGFSK」と書かれている!
・・・と思ったが、Core_v4.2にもGFSKと書いてあった。
3.1章には、1M sym/sの場合は185kHz以上で、2M sym/sの場合は375kHz以上でやらんといかんよ、と書いているようだが、何の条件なのかがわからん。。。

 

さすがに、GFSKとかのことが少しわからないとまずかろうと思い、検索すると出てきたのはやはりsilexさんのところだった。

変調のはなし(1)|Wireless・のおと|サイレックス・テクノロジー株式会社

周波数の違いで1/0を表すのがFSKで、その一種がGFSKらしい。
[Vol 6, Part A]3.1章に図があるが、なんかよくわからんね。
たぶん、A/D変換するときのように、プラスとマイナスが切り替わる瞬間、つまりゼロクロス間隔を見ることで1か0か見分けて、その間隔の監視周期が185kHzだの375kHzだのと言っているのではなかろうか。
無線やってると、ゼロクロスって言葉はよく聞くよねぇ。

 

まあ、あまり調べてないので上記は間違ってるかもしれないが、とにかくGFSKは周波数の違いで1/0を表す方式で、LE 2Mの場合は今までの倍の速度で変調を扱うから2倍の速度を出せる、ということじゃなかろうか。
2倍の速度を出したければ、2倍頑張れ、ということか。
そして、bandwidthがx2というのは、GFSK変調で1/0を表す周波数が倍まで許容されるようになったという意味か。

 

気になるのは、ここが倍の速度になることによる消費電力の増加と、転送時間が半分になることの省電力効果のどちらが大きいか、ということだ。
まあ、チップで違うのだろうけど。

それに、今までBLEで送っていた程度のデータ量を倍の速度で送りたいかというと、あんまりそういう気持ちがしないかもしれん。
どちらかといえば、電源はプラグから取っているからガンガン送るぜ!みたいなときに使うのかも。

2016/12/07

CryptoCell

発表されたnRF52840に載っているCryptoCell-310
CryptoCell-310なのか、CryptoCell-CC310なのかわからないが、長いのでCC310としよう。

ものとしては、ARMCryptoCell-300シリーズというものがあるらしい。


これは、暗号化のコプロセッサらしい。
コプロセッサということは、データを突っ込めば、マイコン側は使わずに計算してくれるということだろう。

暗号化か。。。
JTAGデバッガなどで強引にデータを見られても大丈夫、というよりも、暗号化してデータ保存するのが容易になるよ、というところだろうか?
しかし、暗号化するキーを埋め込んでいたら、それを読み取られると意味がないしなぁ。

 

Nordicのサイトの方には、CC310が提供する特徴として「Key Management Infrastructure」という項目がある。
このKeyは、暗号化キーのことだろうか。

一覧にKey agreementという項目もあるが、この方面に詳しくないので、ぱっと見てわからん。
DHは鍵交換のやり方だったと思うので、これのことを指しているのか。。

 

 

【後藤弘茂のWeekly海外ニュース】ARMの新セキュリティアーキテクチャ「ARMv8-M TrustZone」 - PC Watch

【後藤弘茂のWeekly海外ニュース】ARMがセキュリティ機能を統合した新プロセッサ「Cortex-M23/M33」を発表 - PC Watch

この辺りを読むと、ARMv8-Mにならないとメモリの暗号化までは行かないようだ。
そこまでやりたければ、Cortex-M23/33を使ったマイコンの登場を待つしかないか。

[nrf52]nRF52840

まだnRF52832をあまり使っていないのだが、それに+8したnRF52840というチップがリリースされたようだ。

nRF52840 / Products / Home - Ultra Low Power Wireless Solutions from NORDIC SEMICONDUCTOR

Cortex-M4Fで64MHzというところは同じで、Flashが512KB→1MB、RAMが64KB→256KBと増えている。
電圧は、1.7~3.6V→1.7V~5.5Vと広がっている。

TrustZoneと書いてある。
無理やりデータを引っこ抜かれるときの対策をどうしようか?というときに話題として出てくるのだけど、最近Cortex-M23やM33が出てきたというくらいしか知らない。
一部の機能が使えるとかだろうか?

USBもちょっと気になる。
まあ、自分でUSB対応することはないだろうけど、USBシリアル変換のケーブル無しでデバッグできたりするとちょっと楽かもしれない。

そして、SoftDeviceだが、S140になるらしい。
いつの間にか、nRF5 SDKもv12.2.0がリリースされていたが、その中には入っていないようだ。

 

早くも、Preview-DKができている。

nRF52840 Preview DK / Products / Home - Ultra Low Power Wireless Solutions from NORDIC SEMICONDUCTOR

まあ、早くもというか、Preview-DKが無いとモジュールメーカーが困るからだろうかね。
nRF52832のときは買ったけど、やっぱり一般人が買うものではないな。チップもまだ1.0じゃないので、改版によってすぐ使えなくなるし。

2016/12/06

[esp8266]esp-open-sdkのmake後

あれだけ時間がかかったesp-open-sdkのmakeだが、いったい何ができたのだろうか?
追いかけるつもりはないので、ディレクトリの中身だけ眺めておこう。

image

ああ・・・Non-OS SDKを取り込んでいたのね。

他にも、crosstool-NGやxtensa-lx-106-elfなどコンパイラっぽいディレクトリがあるが、make後に出てきたメッセージではsdkディレクトリ以下に-Iや-Lするディレクトリがあると書かれていた。

sdkディレクトリの中は、Non-OS版と同じようなフォルダ構成になっていた。
こういうときは、WinMergeで比較だ。
えいっ。

image

差分なし。

xtensa-lx-106-elfをビルドするためにNon-OS版が必要だったということもないと思うので、単にAPIが使えるようにしてあげているだけかもしれん。

 

esp-open-lwipは、lwipのESP版なのか。
lwIP - A Lightweight TCP/IP stack - Summary [Savannah]
lwIPは使ったことが無いのだが、keilで使えるライブラリの一覧で見たことがある。
どうやら、Non-OS版で使われているらしい。

が、使われているということは、ライブラリがあるということだ。
Non-OS版のlibを見ると、liblwip.aとliblwip_536.aが入っている。
sdkと比較して差分がなかったということは、ビルドしてまったく同じものができたか、単にNon-OS版のファイルをコピーしたかだ。
まあ、後者だろう。

では、一体なぜ・・・とmakefileを眺めて、理由が分かった。

lwip: toolchain sdk_patch
ifeq ($(STANDALONE),y)
    make -C esp-open-lwip -f Makefile.open install \
        CC=$(TOOLCHAIN)/bin/xtensa-lx106-elf-gcc \
        AR=$(TOOLCHAIN)/bin/xtensa-lx106-elf-ar \
        PREFIX=$(TOOLCHAIN)
    cp -a esp-open-lwip/include/arch esp-open-lwip/include/lwip esp-open-lwip/include/netif \
        esp-open-lwip/include/lwipopts.h \
        $(TOOLCHAIN)/xtensa-lx106-elf/sysroot/usr/include/
endif

そう、デフォルトであるSTANDALONE=yの場合のみビルドされるものなのだ。

 

STANDALONE=nの場合は、バイナリ提供されているものはバイナリのまま使う方式だと思うから、気にせずよいということか。

2016/12/04

[esp8266]esp-open-sdkのビルド(STANDALONE=n)

やる気が起きないので、久々に仕事と何の関係もなくESP8266のことをやろう。
特に目的が無いので、githubに移動したというRTOS版を動かすことにする。

espressif/ESP8266_RTOS_SDK: Latest ESP8266 SDK based on FreeRTOS


まずは、コンパイル環境を作るところから始めるようだ。
以前、Ubuntu on Windowsでやろうとして、提供されたコンパイラが32bit環境でしか動かないようだし、参照しようとしたコンパイル環境がEspressifから出ていなかったので止めた。

RTOS版のRequirementsで紹介されているページも結局は同じコンパイル環境なのだけど、Espressifが紹介しているから、お仕事で使うことになったとしても納得できるだろう。
仕事とは関係なく、といいつつも、やっぱり考えてしまうよねぇ。

pfalcon/esp-open-sdk: Free and open (as much as possible) integrated SDK for ESP8266/ESP8285 chips

今回は、Ubuntu on Windowsではなく、VMware上のXubuntu16.04(64bit)でやる。
普段立ち上げていることが多いのでね。

 

書いてあるとおりに、cloneして、apt-getして、makeする。
モードとして、STANDALONE版とそうでない版があるらしい。
デフォルトはSTANDALONE版になるのだけど、ライセンスがどうのとあるので、そういうグレーなところはなるべく持ち込まないよう、STANDALONE=nで行う。
リンクするくらいだから、なんかうまいことやってくれればうれしいのだがね。

 

VM環境とは言え、そこそこましなビルド環境だと思っているのだが、15分経ってもmakeが終わらない。。
20分くらいかかったようだ。
最後に、コンパイラへのPATHと、includeとライブラリへのパス(-Iと-L)が表示されるので、メモして置いた方がよいだろう。スクリプトにしておくとよいのではないかな。
たぶん、STANDALONE=yだと不要なんじゃなかろうか。


ここまでやっておいてなんだが、なぜRTOS版にはコンパイラが別途必要なのだろう?
Requirementsにxccでもgccでもよい、と書いてあるので、実はNon-OS版の環境を持っていれば不要なのだろうか。

いつもgen_misc.shを実行するだけなので、どういうコンパイラを使っているかすら把握してなかったのだな。

[hw]1.27mmシングルを2つ並べてもデュアルにはできなかった

デバッガとして、SEGGERのJ-Link Liteをしばしば使っている。
相手に1.27mmのソケットがある場合はよいのだが、たまにないときがある。
RedBearのBLE nanoなんかがそうだ(mbedとして使う場合が多いのだろうけど)。
前回は無理やりピンを曲げたり、ピンだけ挿したりしてつないだのだけど、どうにも見栄えが悪い。

別の用事で、1.27mmのシングルラインのピンヘッダを折る用事があって、ちょうど5ピンが2つ残っていた。
これを挿せば目的を達するのではないだろうか?

image

はい、ダメでした。
2.54mmだとできるけど、1.27mmだからか、買ったピンヘッダがそうなのかわからないけど、厚みがあるようだ。

 

こういうのがちょうどよいのだけど、わざわざこれだけ買うというのもなぁ。。。

SWD (2x5 1.27mm) Cable Breakout Board ID: 2743 - $1.95 : Adafruit Industries, Unique & fun DIY electronics and kits

 

あるいは、2列のピンヘッダを自分でハンダ付けして2.54mmで使えるようにするか。
それだったら、J-Link LITEの根っこから生やせばよいのだけどね。

ピンヘッダ 2×5(10P) 表面実装用 1.27mmピッチ: パーツ一般 秋月電子通商 電子部品 ネット通販

2016/12/02

[勉]meteorのclient非同期はセッション変数で対応できそう

http://hiro99ma.blogspot.com/2016/12/meteor.html
まさかの続き記事だ。

 

client側で、結果が非同期に戻ってくるので、returnした値を表示させることができない。
どうやって更新したらよいのだろう?というのが前回の疑問だった。

いろいろ調べたが、Meteorには値が更新されると自動的に表示まで更新される機能があるから、コールバックが戻ってきたときに値を更新すれば、無理して同期とか非同期とか考えなくてよいんじゃ無かろうか、というのが今のところの結論だ。

以前はsetInterval()などで監視していたよなぁ、という部分を隠蔽してくれていると思えばよいか。

 

Meteorで初めてのセッション変数 - Meteor Fan (日本語情報)
よくわからないながらも、こちらをまねしながらやると、コールバック関数内でSession.set()すると、その内容が画面に反映された。
うひゃっほう。

 

どうも「returnで値を返すように作り替えないと」と思っていて、Meteorの特徴とも言えるリアクティブというものが見えていなかったようだ。

[勉]Meteor? 非同期?

急きょ、お仕事でほんのちょっとだけ触ることになりそうなmeteorのことを調べておこう。
「めてお」と発音するようだ。
どうしても、CodeSourceryのMentor社が頭をよぎってしまう。。。

 

https://www.meteor.com/

ブラウザで見るサイトを作るときにはだいたいJavaScriptを使うが、そういうアプリを作るためのフレームワークらしい。
・・・済まん、この世界のことが分かっていないので、用語が正しいかすらわからん。

 

私がJavaScriptを使ったときは、動的なHTML画面を作る、という場合だけだった。
定期的に監視して、値が変わったら更新する、とか。
だから、クライアント側で動くJavaScriptと呼ぶことができるだろう。

Meteorの紹介を読むと、サーバサイドもクライアントサイドも両方書ける、というところが利点としてあげられていた。
むかーし、JavaScriptが導入されたときは、サーバで処理するとクライアント数に応じて負荷がかかるから、できることはクライアント側でやってあげましょう、みたいな話を聞いていた。
時代は変わったのね。

 

ともかく、このmeteorというのをインストールして、決まった場所にHTMLやらJavaScriptやらのファイルを置いておくと、自動的に閲覧用の構成を作ってくれるらしい。
ちょっと試したところでは、特にApacheなどもインストールしていないのに3000番ポートにブラウザでアクセスできた。

 

私は一から環境を作るわけでも、サイトを作るわけでもなく、気分転換したいときにサイトを見て不具合があったら修正してくれると助かる、という程度なのだ。
だから、それほど真面目に調べたいわけではない。


で、その不具合の1つで聞いているのが、値が非同期で返ってくる処理結果を画面に反映させる処理をまだ書いていない、というやつだった。
あまり分かってないが、JavaScript側に関数を書いておき、そのreturnで戻ってきた値をHTML側で{{value}}みたいな感じで参照することができるようなのだが、処理が非同期なのでreturn時には値がまだない、ということのようだ。

以前、結果が動的に変わる画面書いたときは、setInterval()とかで定期的に結果を監視して、画面表示が変更になりそうだったらelementなんとかに代入して更新させていたように思う。
今回の箇所はコールバックで結果が戻ってくるようだから、そのタイミングで同じようなことをやるのだろうか。

Meteorの説明を読むと、非同期のところを同期にすることでさっぱりさせた、という項目があった。
ならば、JavaScriptでなんとかするんじゃなくて、Meteorのしくみを使ってなんとかするのだろうか?

こういうフレームワークを使うと、解決するのにフレームワークでのやり方があるのか、一般的なやり方でよいのか、そこの見極めが難しいことがあるよなぁ。

 

ざっと検索すると、サーバ側に書いた処理が非同期だった場合のやり方が出てきた。
ただ、今回は、たぶんだけど、非同期なのはサーバ側の処理ではなさそうな気がしている。

Promiseというのを使う例も出てくるが、async/awaitをPromiseの代わりに使うという記事もあった。
Async.wrap()というのはサーバ側だけらしい。

なんとなく、Promiseというのはコールバックを連結して処理を行うようにするのを避けるためのやり方で、コールバックで得られた結果を画面反映させたいというのとはちょっと違うような気もする。

もしクライアント側だけで非同期だったとしても、それをサーバ側に持っていけば、サーバ側なら同期で返す方法があるらしいので、それで済ませてしまうものなのだろうか。。。

だいたい、非同期で処理するということはコンテキストが別になるということだから、コールバックされたコンテキストは関数で呼ばれたときと異なると思うのだ。
Linuxとかだとselect()で待たせる、みたいなやり方があるけど、関数が呼ばれた経路はHTMLのメインスレッドに相当するはずだから、returnせずにコールバックを待たせるとブラウザが固まってしまうんじゃないかと思う。

 

よくやりたいことのような気がするので、探し方が悪い気がしている。。。

→続き記事

2016/12/01

[c/c++]strncatはあふれても\0付加しない

一番使っているのはC/C++だが、文字列を扱うことがあまりないので、標準関数が苦手だ。
特に、バッファがぎりぎりしかないときの扱いは、いつも不安なので事前にテストコードを書いている。

昨日書いていて、気付かないままバッファあふれしていたので、調べておこう。
cygwinのgcc 5.4だ。


#include 
#include 

int main(int argc, char *argv[])
{
    static char str[3];

    memset(str, '*', sizeof(str));
    snprintf(str, sizeof(str), "123456");
    printf("snprintf=[%s]\n", str);

    memset(str, '*', sizeof(str));
    strncpy(str, "123456", sizeof(str));
    printf("strncpy=[%s]\n", str);

    strncat(str, "123456", sizeof(str));
    printf("strncat=[%s]\n", str);

    return 0;
}

さて、結果はおわかりだろうか?

 

 

snprintf=[12]
strncpy=[123]
strncat=[123123]

strncpy()やstrncat()が\0を付加しないというのは覚えていたのだが、strncat()のnは追加する文字列に対してのもので、バッファ全体に対してのものじゃないのだな。。。
ポインタの先頭から\0を探して、そこから追加していくから、その時点でnに達していたら追加は行わないかと思っていた・・・。
危ないところだった。

 

その回避をしたい場合は、C11から追加された_s系の関数になる。
strncpy_s()やstrncat_s()だ。
こっちはsnprintf()のように、第2引数にバッファのサイズを指定するのだ。

試してみたかったのだが、このgccではc11オプションを付けてもダメだった。
strcpy, strcpy_s - cppreference.com
__STDC_WANT_LIB_EXT1__を1に定義してからコードを書き始めるのだが、__STDC_LIB_EXT1__が未定義だから、そもそも使用できないようだ。

2016/11/29

[py]buffer()とbytearray()の違いはなんだろう?

よくわからないまま、どこかからコピーしたコードを使うことがしばしばある。
それによって、これってなんだろう?という疑問が湧くこともしばしば。

 

いま、paho-mqttでpublish()するところを見ていたのだが、こんな書き方をしていた。

publish(topic, buffer(data1) + bytearray(data2))

なんとなく、buffer()もbytearray()も似たようなことをしてくれそうだ。
何が違うのだろう?

 

以前、16進数の配列を作る際に、こういうやり方があることを知った。

cmd = bytearray([0x03, 0x12, 0x34, 0x56])

これだと、cmd[1]などで数値が取ってこれるので、そのままif文や添字として使える。
bytearrayは組み込み型で、バイト配列を返すシーケンスとのこと。

 

一方、bufferは毛色がなんか違う。
bufferオブジェクト、なのだ。
CのAPIを使うときなどに出てくるようなので、素のバイト配列なのだろう。

 

data1 = 15
data2 = '1234abcd'.decode('hex')

buf = buffer(chr(data1)) + buffer(data2)
print 'buf=', buf.encode('hex')

dat1 = ord(buf[0])
dat2 = buf[1:]
print 'dat1=', dat1
print 'dat2=', dat2.encode('hex')

buf= 0f1234abcd
dat1= 15
dat2= 1234abcd

data1 = 15
data2 = '1234abcd'.decode('hex')

buf = bytearray(chr(data1)) + bytearray(data2)
print 'buf=', str(buf).encode('hex')

dat1 = buf[0]
dat2 = buf[1:]
print 'dat1=', dat1
print 'dat2=', str(dat2).encode('hex')

buf= 0f1234abcd
dat1= 15
dat2= 1234abcd

 

bytearrayはencode('hex')がないし、str型ではないからstr()で囲んだり、ord()が不要だったりという違いがある。

 

data1 = 15
data2 = '1234abcd'.decode('hex')

buf = buffer(chr(data1)) + bytearray(data2)
print 'buf=', buf.encode('hex')

dat1 = ord(buf[0])
dat2 = buf[1:]
print 'dat1=', dat1
print 'dat2=', dat2.encode('hex')

buf= 0f1234abcd
dat1= 15
dat2= 1234abcd

混合できて、その場合はstr型と同じ扱いになるようだ。

 

paho-mqttのpublish()は、payloadとして文字列を使いたいようだ。
intとか送りたかったらstruct.pack()してくれ、と書いているし。
bytearray型を引数にして使えているのだが、これはpahoがstr()で囲んだりしてくれているからかもしれん。

・・・と思ったが、違った。
bufferを与えると例外が発生したのだ。

TypeError: payload must be a string, bytearray, int, float or None.

bytearrayは許可してたのね。。。
そしてintはstruct.pack()してくれ、だと思ったのだけど、例外の内容を見るとintも許可しているような感じだな。
まあ、使わないから調べないけど。

2016/11/28

[py3]2to3ではdecode/encode('hex')などは変換してくれないようだ

さて、いま作っているプロジェクトもpython3対応しようと、2to3.pyにかけてみた。
ワイルドカードで指定できなかったので、cygwinでxargsを使ったが、printがprint()になっているので変換できたのだろう。
よし、とpyCharmの設定もpython3にして開いてみると、指摘がたくさん。。。

こんなのが指摘されている。

struct.pack('<H', length).encode('hex')

bytes = lenstr.decode('hex')

 

hiro99ma blog: [py]python3は16進数の扱いが違うんだ

違うんだ、を実感した瞬間である。


decode/encodeはstr型用だから、bytes型だと使えない。
struct.pack()はbytes型で返すようになっている。
だから、bytes型の扱いに変換すればよいだけのことだ。

文字.decode('hex')は、bytes.fromhex(文字)にすればよいはずだ。
そこはそれで済みそうだが、"\xab\x12"のようにして作っていた文字列をbytes型に変換しないと、fromhex()したデータとの足し算というか連結ができないことがわかった。
これは、文字列の前に「b」を付けるだけでよいようだ。

と、やってみたのだが、bytesの要素をord()したりstruct.unpack()すると怒られる。。。

ord(cmd_bytes[0])

strがほしいのにintが渡されている、ということだった。
デバッガで見てみると、bytes配列の要素はint型になっていた。
そうか、ord()しなくてもいいんだ。。。

が、これはこれで別の問題が起きた。
辞書のkeyとして"\xab"のような値を使っていたのだが、これをbytes型にしないと検索できなくなった。
しかし、検索するのはbytesから1バイト取ってきたデータなので、そのままだとint型になってしまう。
よくわからんので、cmd_bytes[0].to_bytes(1, byteorder='little')、などとしてbytes型に変換して、動きはしたのだけど、ダサい。。。

4. 組み込み型 — Python 3.5.2 ドキュメント
なるほど、要素として取り出すとintになるから、サイズ1の配列として取り出せばよいのか。

cmd = cmd_bytes[pos: pos+1]

こんなのでよい。
数値にしたければ、cmd[0]とすればよいだけなので、こっちの方が扱いやすいな。

 

encode('hex')するのは目で読める文字にするとき、decode('hex')するのは実際のデータにするとき、という使い分けをしていた。
これは、bytes型にhex()というメソッドがあり、それでよかった。


私がbytes型を使うときのやり方をまとめると、こう。

  • 文字列でエスケープシーケンスを使って16進数を表していた→あたまに「b」を付ける
  • decode('hex')していた→bytes.fromhex()にする
  • ord()していた→bytesを1要素として取り出す(data[3]など)
  • bytes型として切り出したい→配列として取り出す(data[3:4]など)
  • encode('hex')していた→hex()にする

struct.pack/unpack()は、to_bytes()もあるし、あまり使わないかも。
to_bytes()の逆はなさそうだから、unpack()は使うことになるか。。。あ、int.from_bytes()というのもあるようだ。
to_bytes()はメソッドなのに、from_bytes()はstaticメソッドなのはなんでだろう?

 

pyCharmで指摘が出ているのは、あからさまにbytes型になったと分かる箇所だけだ。
型指定がないから、引数でもらったものをdecode('hex')などとしていても、そこは出てない。
だから、たくさん指摘が出ていると思ったけど、氷山の一角なのだ。
2to3でやってくれよーと思ったのだが、これはちょっと無理だな。

 

また、変換しようとしていたpythonプロジェクトは、str型のbytearrayで扱う場合と、str型で16進数文字列を扱う場合が混在していて、あっちではstruct.pack/unpack、こっちではdecode/encode('hex')と、実にまとまりがない。

今回は、python3にするのだったら、もう一度書き直した方が早そうだ。。。

2016/11/27

[pyCharm]フォルダが表示されなくなったら、Content Rootを疑う

なぜか、pyCharmのプロジェクトツリーにフォルダが表示されなくなった。
先週は普通に使っていた気がするのだが、何をしたのか記憶にない。。。

 

あれこれ見てみたが、Settingsダイアログを開き、「Project:xxx > Project Structure」を見ると、Add Content Rootのところが赤文字になっていた。
よくわからないながらも、一度削除して、また追加すると直った。

 

困ったことに、これはUNCパスの場合はうまくいかなかった。
結局、一度Windowsのローカルフォルダに移動させ、pyCharmの設定を修正して、またUNC上に戻すことになった。

まあ、推奨していないから仕方ないんだけどね。

[c/c++]Cクイックリファレンス第2版

オライリーの、Cクイックリファレンス第2版を買ってきた。
2016年11月に出たばかりだ。

O'Reilly Japan - Cクイックリファレンス 第2版

C11準拠ということで、私の知らないことがいろいろ出ているのだろう。
まあ、使うときになら無いと読まないような気がするのだが、もしマルチスレッド処理が標準で書けるのならば「RTOS採用するほどのことでもないしなぁ。でも後から使った方が良くなるかも」と迷ったときに、労力が少ないから最初からマルチスレッドで書いておこう、という選択肢が出てくるかもしれない。

 

さて、まえがきのコラム欄に、日本語版だけだと思うがコーディング規約ESCRのことが書かれていた。
ESCRが何なのか知らなかったが、Embedded System development Coding Referenceの略で、IPAが出している資料にもあるやつだった。

「【改訂版】組込みソフトウェア開発向けコーディング作法ガイド[C言語版]Ver.2.0(ESCR Ver.2.0)」PDF版と付録データの公開:IPA 独立行政法人 情報処理推進機構

私も、いくつかこれを読んだときの記事を書いている。
検索して3つ出てきたが、たぶんまだあるだろう。

 

このESCRだが、PDFでダウンロードできるものを読んだ範囲では、pythonのPIP-8とはちょっと違う。
「コーディングスタイル」ではなく「コーディング規約」なので、インデントはどうの、改行はどうの、というようなルールは書いていない。
保守性4で「統一した書き方にする」という決まりを作っているだけで、どう書くべきかというところには踏み込んでいない。

まあ、C言語の人にそういうのを強要すると、嫌がるよねぇ。
私も嫌だ。
本のコラム欄では、astyleなどの自動整形ツールに任せると効率がよい、とあり、私も賛成だ。

ただ、期待するastyleのオプションを決めるのは、なかなか難しい。
私は最近、タブをスペースで書くようになってきたので、こうしている。

--style=k/r --indent=spaces=4 -j

正解はないので、自分のプロジェクトなら自分のスタイルに、他のプロジェクトに参加するならそのスタイルにしていくことになるだろう。

 

これがテキストエディタと連携して動的に表示されると書いている間に修正するだろうけど、書いているリズムが狂ってしまうので嫌かもしれない。
難しいねぇ。

2016/11/26

[py2]feature無きprint()は、タプル扱い

「動力無きK村」(炎色反応の覚え方)みたいだが、その話ではない。

python2ではステートメントのprintがあるから、組み込み関数のprint()が使いたい場合にはimport文を書くように、となっている。
28.4. future_builtins — Python 3 のビルトイン — Python 2.7.x ドキュメント

が、python2.7でprint()とprintを両方書いたが、どちらも動いた。
なぜだろうか?

 

PEP 3105 -- Make print a function | Python.org
featureのimportを書いていない場合は、print()の関数、ではなく、printステートメント+タプル、という動作になっているということか?

print('Hello! I\'m Python2', 'not feature')

これをpython2.7.12で実行すると、こうなった。

("Hello! I'm Python2", 'not feature')

python3.5.2だと、こうなる。

Hello! I'm Python2 not feature

なるほどねぇ。

[py3]2to3で変換してみよう

作業場にて。。

Aさん「このpython、バージョンは何で書いてるの?」
私「2.7です」
Aさん「3じゃないんだ。。。」

というわけで、そろそろpython3を視野に入れないといかんようだ。

 

python2.7をインストールすると、Tools\Scriptsの中に2to3.pyというスクリプトがある。
これがpython2をpython3に変換してくれるツールらしいので、試してみよう。


print 'Hello! I\'m Python2'


単純すぎで済まん。。。
私が思いつくpython2と3の違いは、printで括弧がいるかどうかなのだ。

これを「python2.py」というファイル名で保存して、2to3にかけてみる。
うちはWindowsで、python2.7はC:\Winappli\Python27というフォルダにインストールしている。


C:\Prog\python\py3test>python C:\Winappli\Python27\Tools\Scripts\2to3.py python2.py
RefactoringTool: Skipping optional fixer: buffer
RefactoringTool: Skipping optional fixer: idioms
RefactoringTool: Skipping optional fixer: set_literal
RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: Refactored python2.py
--- python2.py  (original)
+++ python2.py  (refactored)
@@ -1 +1 @@
-print 'Hello! I\'m Python2'
+print('Hello! I\'m Python2')
RefactoringTool: Files that need to be modified:
RefactoringTool: python2.py


オプションを付けないと、差分だけ表示するが、-wを付けるとファイルに書き込んでくれる。
前のファイルは.bakを付けて残される。


print('Hello! I\'m Python2')


まあ、予想通りの結果だ。
python3で実行しても動く。
めでたしめでたし。

 

ではあるのだが、これをpython2で動かしても、ちゃんと動くのだ。
じゃあ、最初からprintも括弧を付けて書いておけばいいのに、なんでそういうサンプルになっていなかったのだろう?

軽く調べたところ、python2で括弧無しのprintは、passやbreakと同じ「print」というステートメントという扱いらしい。
6. 単純文 (simple statement) — Python 2.7.x ドキュメント

そして、2.7の方で動いたのは組み込み関数のprint()なのだが、これは2.6から追加されているようだ。
2. 組み込み関数 — Python 2.7.x ドキュメント

python2では当初print()関数がなかったから、ステートメントのprintで書いているため、それを見て覚えた人がまたステートメントのprintを使って。。。ということで、脈々と受け継がれたということだろう。

ああ、新参者の私には分からぬ事情であったことだよ。

2016/11/25

[git][win]GitExtensions 2.49

Windows用のgit GUIツール(フロントエンド?)の1つであるGit Extensionsが、16日前にバージョンアップしていた。

Release Version 2.49 · gitextensions/gitextensions

 

ばりばりに使う人だったら、コンソールからgitコマンドを使うのだろうけど、自信がないのでツールにお任せしている。
おかげで、サーバにSSHで接続してやるときはコマンドが分からず苦労するのだけどね。。。

 

こういうツールは海外製が多いのだが、日本語に差し替えができるものもある。
GitExtensionsもできる。
が、gitの使い方を検索するとだいたいコマンドを使うやり方なので、コマンドが日本語に訳されているとわからなくなるのだ。
まあ、だいたいカタカナになっているだけなのでわかるのだけど、本当に英単語をカタカナにしただけなのか心配になるので、英語表記のまま使っている。

 

個人的には、gitで困ったことをやらかしたときの対処がツールにほしいところだ。
普通にcommitするとかだったら私でもできるし、GUIツールでもできるのだが、「○○してしまった!」みたいな場合はコンソールでやらないと戻せないことが多い。

そして、そういうやり方は覚えていないので、ネットで検索する。
やり方はコマンドを使う方法なので、コンソールになる、ということになる。
汎用性があってよいのだけど、手軽にやれるとよいなぁ、とも思うのだ。

そういうツールこそ自分で作ればよいのだろうけど、gitコマンドに対する技術が向上しないので作ることができない、という悪循環だ。。。

2016/11/24

Google Playにあげていたアプリを非公開にしました

数年前にアップしたままにしていたAndroidのアプリだが、今日は「動かない」というメールが来ていた。
アプリは「ニモカ残高」というアプリで、PaSoRiが必要なのだが、たぶんPaSoRiをつないでいないのだと思う。

が、これは私のタイトルの付け方が悪かった。。。
あたまに「PaSoRiで」くらい付けておかないと、中身なんて普通は読まないのだ。
私も今回指摘されて「そういえば読まない」と気付いた。

 

これは私が悪かったので、ついでにアプリを全部非公開にした。
もう改造する気力もないので、さっさと非公開にしておけばよかったのだよ、私。。。

 

メールをくれた人、ありがとうございます!
来ないと気付きませんでした。

 

なお、nimocaなど交通系でSuicaと相互に使えるものは、たぶんSuicaを読むアプリで使えるので、そのアプリを使うのがよいと思う。

[py]pyCharmでUNCのパスを開くのは推奨していないそうだ

冬になり、デスクトップ環境だと足が寒くなった。
そうなると、自然とコタツ開発になってくる。

image

 

今作っているpythonスクリプトはLinux上で動かす前提だ。
うちはWindowsメインなので、VirtualBox上でLinuxを動かしている。
そして、そこにpythonスクリプトも置いている。

コタツにはノートPCがあり、そこからVirtualBox上の環境にアクセスするには、VirtualBoxのネットワーク設定を「ブリッジアダプター」にせねばならなかった。
「ホストオンリー」だとデスクトップ環境からしかアクセスできないのだ。

 

そうやってノートPCからVirtualBox上のLinux環境にアクセスできるようになった(Linux上ではSambaを動かしている)。
pyCharmで作ったプロジェクトも、ごそっとLinux上に移動させた。

そこまではよかったのだが、Windowsでネットワーク上のファイルアクセスする場合は\\serverのようなUNC名でアクセスすることになるのだが、pyCharmのプロジェクトを開くダイアログでUNCのパスを入力してもアクセスできないのだ。

 

検索したところ、pyCharmというかJetBrain系のツールかもしれんが、UNCでのアクセスは推奨していないようだった。
ネットワークドライブを設定してくれ、というような回答が見つかった。

しかし、それはめんどうなので、UNCでアクセスすることにした。


やり方は難しくなくて、ExploreからUNC先のフォルダを開き、そのpythonファイルをpyCharmで開くだけだ。
UNCのところには、あらかじめpyCharmのプロジェクトファイルを置いていなくてはならないだろう。
だから、一度ローカルでプロジェクトを作って、UNC先にコピーすることになるかな。

pyCharmで開くのは、pyファイルに関連づけていなければ、コンテキストメニューの「プログラムから開く」で選べばよいだろう。

一度開くと、pyCharmのプロジェクト一覧にはUNCの名前でも残るので、それをアクセスすればよい。
まあ、推奨されていないので正しく動かなくても知らんけどね。
うちの場合は実行がローカル環境じゃないので、単なるエディタとして使っているが、今のところ問題なさそうだ。
もちろん、Linux先のpython環境を参照するわけではないので、importでローカルに入っていないものがあればエラーが出てしまうが、そういうのはなんとかしよう。

2016/11/23

[py]1バイト分のstrを数値に変換するならord()が使える

先頭にデータ長が付いたstr型のデータを扱うことが多い。
こんなのだ。

cmd = '\x03\x12\x34\x56'

Cだったら、先頭のデータ長を取ってきたい場合、こうするだろう。

cmd = "\x03\x12\x34\x56";
uint8_t length = (uint8_t)cmd[0];

pythonだと、いつもこうやっている。

cmd = '\x03\x12\x34\x56'
length = struct.unpack('B', cmd[0])[0]

 

これが、ぱっと頭に思いつかない。。
そして、長い。
他に方法はないのだろうか?


1つ私が勘違いしていたのは、16進数でデータを突っ込んだ文字列はbytearray型だと思い込んでいたことだ。
文字列は、文字列だ。だからstr型になる。

これがッ、bytearray型だッ!

cmd = bytearray([0x03, 0x12, 0x34, 0x56])

まあ、他に記述方法があるのかもしれんが、見つけたのがこの書き方だった。
Cの書き方に近い。

この書き方の利点は、数値を取ってくることが可能なところだ。

cmd = bytearray([0x03, 0x12, 0x34, 0x56])
print 'cmd[0]=', cmd[0]

期待通り!

ただ、str型ではないので、こういうのはできない。

print 'cmd=', cmd.encode('hex')

が、これならいける。

print 'cmd=', str(cmd).encode('hex')

 

そうか。。。SQLiteで取ってきたBLOB型をstrして使っていたが、こういう意味だったのか・・・。
そういえば、BLOB型にINSERTとかするときも、bytearrayで囲んでいるし。

 

今はstrベースでやっているので、こういう感じで使うのがよさそうだ。

cmd = '\x03\x12\x34\x56'
print 'cmd=', cmd.encode('hex')
length = bytearray(cmd)[0]
cmd_byte = cmd[1: 1 + length]
print 'cmd_byte=', cmd_byte.encode('hex')

これだと、3バイト分表示されるので、これでいこう。

lengthに代入するのが「bytearray(cmd[0])」だとダメだった。
1バイト分取ってくるという意味では同じそうに見えるのだが。。。


などとごにょごにょ調べていたら、もう1つ別の方法を見つけた。
ord()だ。

length = ord(cmd[0])

こういうのを求めてたんだよ!

 

逆のパターンの、数値を文字列化する場合はchr()だそうだ。
今までこうやって書いていたのだけど、

%02x' % length

これでよいことになる(lengthの範囲によるけど)。

chr(length)

こう書くと、「cmd2= 02789a」となる。

cmd2 = chr(2) + chr(0x78) + chr(0x9a)
print 'cmd2=', cmd2.encode('hex')

 

組み込み関数は、私が求めているものが多そうなので気に掛けておかねば。

2016/11/22

[py]python3向けに書いた方が良いのか?

本屋さんでpythonの本を探していた。
だが、入門書か、えらく難しいものしかなさそうだった。
私が使う内容が今のところバイナリを作るだけなので、本を買うほどでもないというところかもしれん。

 

何冊かぱらぱらと眺めたのだが、その中に「python3で書く」というような項目があった。
もう、焦点がpython3に移っているので、まだpython2は数年くらい使われると思うけれども、3の方がいいよ、というような内容だったと思う。

 

今のところ、python2.7.12を使っているのだが、python3にした方がよいのだろうか?
コマンドラインで動かすスクリプトしか作っていないし、サーバに持っていきたいとしてもサーバから作ることになるから、バージョンは特に気にしていなかったのだ。
適当にインストールしたら2.7だった、という程度である。

 

前にスコープのことを調べたとき、ブロックスコープがないということを逆手に取り、importして例外が発生したらcatch...じゃなくてexceptで受けて別のimportを行う、という手法が紹介されていた。
Community Blog - Python の名前空間とスコープ

そんな感じで、置き換えはできるのかもしれない。
こんなのもあるし。
25.4. 2to3 - Python 2 から 3 への自動コード変換 — Python 2.7.x ドキュメント

 

が、ようやく少し慣れてきたところで、似ているけどちょっと違うものをやり始めると、混乱してしまいそうな気がしているので、やるのはもう少し後にしよう。

2016/11/21

[py]処理は小分けにした方がよさそうだ

前回、pythonのスコープのことを書いた。
いつも使っているC/C++と違って、関数やモジュールの単位しかないので、何気なく変数を使ってしまうと、それがスコープを外れないまま使われてしまうことになる。

まあ、通常はスコープ外と思って代入から始めるから問題はないのだけれども、思っていない変数が再利用されているというのは気持ちが悪いし、pyCharmも指摘してくるのでなんとかしたい。

 

ひとまず、グローバルにしたい、と思った変数は、大文字にしてしまうか、可変な場合は「g_」をつけて、まずは見た目で分かるようにした。
なんというか、自分がC/C++で書くときと同じルールを採用したということだ。

できれば、staticみたいなものがあるとよいのだけど、pythonにあるのかわからん。
たぶん、アンダーバーをつけるというのが、そういうやつなのだろう。
大文字の名前を付けるのと同じようなものか。

今のところ、まだモジュール間で変数を持ち合いたいような処理がないのでこうしているが、そうなっても問題ないように「g_」じゃなくて「_」だけにした方がよかったかもしれん。
まあ、検索のしやすさを考えて「_g_」とかか?
キャメルでの変数名は推奨されていないようだから、アンダーバーでつないで長くなってしまうけど、そこは仕方あるまい。

 

ただ、こうやっても名前を見て分かるだけで、「g_」がついていない変数はローカルスコープのつもりで扱うように、という管理をしなくてはならん。
これだと、pyCharmで指摘されるのは避けられないから、

  • 代入しなくてよい変数は作らず、直接引数に渡す
  • 処理単位ごとに関数に分ける

というのがよいのではないかと思った。

pydocで平文があると実行されるから「if __name__ == '__main__'」にしましょう、という記事見かけるが、スコープの観点からもそうした方がよさそうだ。
処理を関数に分けてしまえば、変数もその中だけになるので、使い回しにはならなくて安心だ。

 

という、理屈は分かるのだ!
わかるのだけど、言語に対する理解が足りていないので、処理をだらだらと書いてしまう。。
あれだな、C言語初心者の書いたコードを読んで「ここら辺は関数にすればよいのに」と思うのと同じことだろう。
頭で分かっていても、コードが付いていかないということがあるのだな。

 

こういうのは新しい言語を覚えるときにしか出てこないので、いろいろ言語を使い分けられるようになると、その言語自体に慣れる前に対応できるかもしれない。
その域に達することができるだろうか。。。

2016/11/19

[py]スコープはモジュールと関数しかないそうだ

pythonのスコープが全然理解できていない。
初出場の変数でエラーになるかと思えば、別の場所で使っている同じ変数名で「また使ってますよ」みたいな警告が出たりする。

なんなのだ、いったい!

 

Community Blog - Python の名前空間とスコープ

python 2.7.2の記事だが、スコープはモジュールと関数しかない、と書かれている。
それって、ブロック内の変数という見方ができない、ということか。。。
if文の中で使った変数が、他のところで同じ名前を使うと警告される理由が分かった。

変数をもっと局所的にしたいときは、関数の中に関数を書くことができるから、それで分離するとよいらしい。

val1 = 10


def func1():
    val2 = 20
    print 'val1=', val1
    print 'val2=', val2

    def func1in(v):
        if v == val1 * 2:
            return val1 * 4
        else:
            return -1
    val2 = func1in(val2)
    print 'val2=', val2
func1()

結果

val1= 10
val2= 20
val2= 40

func1in()の引数をなくして、これでもいける。

val1 = 10


def func1():
    val2 = 20
    print 'val1=', val1
    print 'val2=', val2

    def func1in():
        if val2 == val1 * 2:
            return val1 * 4
        else:
            return -1
    val2 = func1in()
    print 'val2=', val2
func1()

ただ、func1in()の中でval2への代入を行うと、ifで使っているval2がエラーになる。

val1 = 10


def func1():
    val2 = 20
    print 'val1=', val1
    print 'val2=', val2

    def func1in():
        if val2 == val1 * 2:
            val2 = val1 * 4
        else:
            val2 = -1
    func1in()
    print 'val2=', val2
func1()

じゃあ、func1in()の中に「global val2」を書けばよいかというと、これは実行時エラーになってしまう。
もしかして「globalじゃなくてlocalでは?」とやってみたが、そんなキーワードはなかった。。。

できなさそうな感じがするけれども、根拠の情報は出てこなかった。
まあ、初出場のグローバルじゃない変数は代入した時点でローカル変数になるらしいから、これも同じことか。

2016/11/18

[py]モジュールがあるフォルダのファイルを指定したい

SQLiteを使ってデータ管理をしている。
単独で使いたいこともあるので、ファイルを別にして、関数にして呼べるようにした。

そこまではよかったのだが、SQLiteへはファイル名しか指定していないので、pyファイルが別のフォルダにあると、そのフォルダでDBファイルを作ってしまうのだ。
これではDBにしている意味が無い。。

 

どこか固定のフォルダにした方がよいのだろうけど、フォルダを設定するのも面倒なので、SQLiteの処理を関数化したファイル(モジュール、でよいのか?)がある場所にDBファイルを作ることにした。

FULLPATH = os.path.realpath(__file__)
PATH, FNAME = os.path.split(FULLPATH)
DBFILE = PATH + os.sep + 'txlist.db'

os.sepは、パスのデリミタらしい。
「/」とか「\」とか。
Windowsもスラッシュだったらいろいろ楽だったのにねぇ。

 

pythonは、const/final/readonlyのような定数がないので、慣れないといろいろ気を遣ってしまう。
スコープも私が思っているような範囲と違うので、スクリプト言語ならではなのかもしれん。