2016年10月31日

[py]はじめてのclass

pythonで何かするお仕事が止まっているので、ネタが切れかかっている。。。
えい、前回いっていた「文字列かbytearrayかを処理するだけのclass」を作ってみよう。

 

pythonにpublicやprivateというものを決めるキーワードは特になく、名前で決めるようだ。
でも、入門記事を見ていると、「こうだと思ってたんだけど」みたいな書き方で、言語仕様がどうなのか読んで書いているのかどうかわからんかった。
python2のドキュメントを読む。

  • __init__()は特別
    • コンストラクタ
  • プライベートな変数
    • 言語仕様としては無い
    • 慣習としてアンダースコアで始まる名前は、非publicとして扱う

 

python2.7で試す。

class StrBin:
name = ''

def __init__(self):
pass

def set_name(self, name):
self.name = name

def _hello(self):
print 'Hello, ' + self.name


sb = StrBin()
sb.set_name('yoshio')
sb._hello()

Hello, yoshio

 

pyCharmとしてはテキストエディタとして警告が出るものの、実行は問題ない。
当然、これもOKだ。

class StrBin:
_name = ''

def __init__(self):
pass

def set_name(self, name):
self._name = name

def _hello(self):
print 'Hello, ' + self._name


sb = StrBin()
sb._name = 'nitori'
sb._hello()
Hello, nitori

 

行儀はよくないだろうが、できる。


では、あっさりしたclassを作ってみよう。

class StrBin:
_value = ''
_type = -1 # 0:bytearray 1:string

def __init__(self):
pass

def set_bin(self, byte_array):
self._value = byte_array
self._type = 0

def set_str(self, string):
self._value = string
self._type = 1

def get_str(self):
if self._type == 0:
return self._value.encode('hex')
elif self._type == 1:
return self._value
else:
raise Exception('not set value')

def get_bin(self):
if self._type == 0:
return self._value
elif self._type == 1:
return self._value.decode('hex')
else:
raise Exception('not set value')

sb1 = StrBin()
sb1.set_str('ab12')
print 'get string: ' + sb1.get_str()

sb2 = StrBin()
val = b'\xab\x12'
sb2.set_bin(val)
print 'get bin: ' + sb2.get_str()

if val == sb1.get_bin():
print 'same !'
else:
print 'not same..'

 

まだソースコードをblogにうまく載せられないので、改行が消えてしまったようだ。。
ともかく、最初の代入で文字列かbytearrayかをちゃんと指定しておけば、あとはget_bin()なりget_str()なりで適切な方に変換してくれる。

2016年10月28日

[py]pyCharmでbytearrayを見たい

そうか、そういうことか。。。

pyCharmでbytearray型(という表現でよいのかよくわからんが、文字としてじゃなくてバイナリ値を扱いたいときの話)を使っているのだが、ブレークポイントで止めて値を見ても文字列で表示しようとして、化けて出てしまう。

そういうときは、「Evaluate Expression」のダイアログを開いて、そこで「encode('hex')」などと表示したいように入力してやれば、その形式で表示してくれるようだ。
さすがスクリプトだ。

2016年10月27日

NXPが買収される予定

Qualcomm to Acquire NXP

珍しくnxpからメールが来たと思ったら、これですよ。
マイコンとしてNXPのを使うことはそう多くないのだが、NFCの雄だ。

NFC worldも反応してます。
NXP to be bought by Qualcomm in US$47bn deal • NFC World

2020年ということなので、完了するまでは予定になるのだろうけど、大きいと思っているところもこうなるんですな。
Phillipsって、いまどうなってるんだろう。

 

 

ARM買収も驚いたけど、こっちもなかなかでした。

[py]pyCharmを使うことで改善されたか?

起動したときのアイコンが「PC」だったので、パソコンのことかと一瞬思ったが、略したらPCなんだな。

image

型がわからなくて困る問題がpyCharmを導入することで改善したかというと、そういうことはない。
まあ、bytearrayとstrの違いなんて、pyCharmだってわからないはずだ。
せめて、メソッドがないとかそういうレベルであれば、エディタの段階で気付かせてくれるだろうに。

新しくコードを書き始めれば、また目覚めるのかもしれないが、ちょうど一通りコードを書き終わった後なので、ソースの整形にしか使っていないのだ。
だから、使った方がよいかどうかは、また後日だな。

期待するのは、ブレークポイント。
今まではprintを埋め込んでいたのだが、やりやすくなるはず。
埋め込んだprintを削除する作業がけっこう面倒に感じているのだ。。。
Cで書いているときは、わざとインデントをずらしてprintf()を置くことで、ざーっとソースを眺めてデバッグ出力を見つけられたのだが、pythonだとインデントがずらせないので目印を付けておくくらいしかやれることがない。
少しだけやってみたが、bytearray型の変数が見づらい。
Cであれば、変数のアドレスを取ってきてメモリビューアなんかで見れば済むし、VisualStudioやIntelliJでも配列要素は1つずつ見られたのだが、ここはツールというよりも言語仕様の違いなのだろうか。

 

 

つらつらと書きながら思いついたのだが、decode('hex')とencode('hex')で書くのではなく、binasciiのa2b_hex()とb2a_hex()を使うようにしたらよいのでは無かろうか?
・・・関係なかった。
そもそも、「バイナリ」と「文字列」が同じ系列で扱えるんだから、関数になったって同じだ。

だから、別の「バイナリ型」があればよいのだ。
python3ではb'xxxx'というやり方になっていたと思うが、その辺が見分けられるようになったのかも。
16進文字列と文字列の変換 - Qiita
そんなことはなさそうだ。。
どっちも引数がb'xxxx'になっている。
うーん。。。。

 

まぬけな気がするけど、自分でclassを作って、チェック機構を付ける方が建設的かもしれない。

2016年10月26日

[py]pyCharmで見ると、かなり指摘された

変数の型がわからないのはIDEを使ってないからかも!ということで、有名そうなpyCharmをインストールして、作っていたライブラリを開いてみた。
テキストエディタのように普通に開けたのだが、スクロールバーが見づらいなぁ。

 

あ、これ全部指摘だ・・・。

 

全部は見ていないけど、PEP8という指摘が多い。
コメントがああだこうだ出ている。

Python のコーディング規約 PEP8 に準拠する - Qiita
ほう、そういうものがあるのか。
しかし・・・細かい。
無理に従うつもりはないのだけど、今から変な癖を付けたくもないので、理解できるところは対応しよう。

 

しかし、指摘はスクロールバーにしか表示してくれないのか?
あ、色設定がtwilightだから見えなかっただけのようだ。


・関数内の変数は小文字にしよう

ちっ、私にしては珍しくキャメルを使ってやったのに、この仕打ちか!

 

・関数名も小文字にしよう

えっ、そうなの?
アンダースコアでつなげるタイプなんだ。

 

・引数にlenとか使っちゃいかん

そんな短いのを標準で使わないでおくれ・・・。

 

・そこに括弧はいらないよ

tupleで値を返すのに括弧で囲んでいたのだけど、いらないんだ。。

 

・ブロックコメントは「#」で始めよう

?
ああ、「#こめんと」じゃなくて「# こめんと」とスペースを空けろということか。

 

・行末にセミコロンはいらん

習慣なんだよ、習慣!

 

・関数間は2行空ける

あー、はいはい。

 

・行が3行以上空いている

。。。

 

・docstringはダブルクオーテーション3つで

普通のところはシングルクオーテーション3つで何も言われないけど、ファイル先頭だけは指摘された。
pydocでコメント化されるからだろうか。

 

・1行が長い

改行するよ!

と改行したら、こんな警告が出てきた。

image

どうやら、改行後の位置まで指摘しているらしい。

a = abc + def + ghi + jkl

のghiとjklの間で改行したい場合は、

a = abc + def + ghi
        + jkl

のようにするとよいようだ。
やれやれ。。。

 

この辺をRefactorを使いつつ修正して、今まで作っていたサンプルを動かそうとしたら、動かない。
変更した関数名が、下々に反映されていないのだ。
Refactorを使ったのに、なぜ・・・。

そうか、プロジェクトの設定で、作ったライブラリが有効になるようにしていなかったから、下々は関連性がわからずに反映されていなかったということか。
確認欄に出てくるファイル名が少ないと思っていたんだ。。。

pyCharmの「File > Settings > Project:xxx > Project Structure」で、Add Content Rootをライブラリのあるフォルダにしたら見えたのだけど、何か設定が違う気がしている。
PYTHONPATHに追加するだけだったのだけど、Project StructureじゃなくてProject Interpreterの方に追加するのかしら。

でも、こっちでローカルのファイルを追加しようとするとエラーになるのよねぇ。
__init__.pyがないからかしら。
まあ、これは後日調べよう。


簡単な対応は上記くらいで、あとはコード部分になってきた。

 

まず、単なる足し算の行が指摘されている。
image
なんだよ・・・
あ、pythonって、「+=」が使えるんだ!
++が使えなかったので、+=も無いと思い込んでいたのだ。
不覚。。。

この指摘って、マウスカーソルを外すとすぐに消えてしまうのだが、なんとかならないだろうか。。
検索したくても消えてしまうのだ。

 

doxygen用の「##」も指摘されるのか。
pydocのものでも処理はしてくれるそうだ。
http://www.doxygen.jp/docblocks.html#pythonblocks

ただ、私がdoxygenを使いたいのは、引数の説明(型としてこれを取ります、など)を書きたいからなのだ。
だから、doxygen形式で書きたいのだけど、そうするとPEP8指摘が多数出てしまう。

特定のコメントを書くと無視してくれるらしいけど、うーん。。。。
How to disable a pep8 error in a specific file? - Stack Overflow

あ、#を連結しても、その後に文字列が続かなければ警告が出てこなかった。

##
# 関数のコメント
# @param[in] xxx aaa

こんなのでよいらしい。
ちゃんと先頭は@briefで拾ってくれているようだ。

 

最後に、そんな属性はない、という警告が残った。
検索すると、import文で出てくるという例はあったのだが、関数内の方は見つからなかった。
動いているから、ないってことはないと思うのだが、わからんので放置だ。


多少、口うるさいという印象を受けなくはないが、C言語もこのくらい規約がうるさければ、人によってソースの書き方がずいぶん違うと言うこともなかっただろう。
まあ、時代が違うから、C言語の自由さとその結果から得られたものだ、と思うことにしよう。

[py]型指定しない言語を使う人は、どうやって型を見分けてるのだろうか?

まあ、pythonだけではないのですが。

pythonを使い始めてかなり悩んでいるのが、変数を型宣言せずに使えることです。
なんというか、C言語で言えばすべてがvoidポインタ型になっていて、キャストせずに最後に代入した型として使える、という感じだろうか。

 

いま、プロトコルを解析したり作ったりしているのだが、decode('hex')とか、encode('hex')とか、struct.pack()とか、struct.unpack()とか、そんなのばかり使っている。
技がまだわからないので、bytearray型からprintするときはencode('hex')して、計算するときはdecode('hex')して、とパタパタやっている。

そうしていると、だいたいどこかで間違って、既にprintできる形でできている変数を、さらにencode('hex')して「1234」が「31323334」になったりしてしまう、という悲劇が起きている。
関数化して間違いを少なくしようとはしているのだけど、その関数に与えるのを間違えるのもしばしばだ。

 

だいたい、bytearrayでも、strでも、どっちも同じグループだから同じように扱えてしまうのがいかん!
いかん、と力強くいいたいのだけど、最近の言語はどっちかといえば型を強要しない方向が多かったように思う。
JavaScriptもそうだし、C#もvarが使えるようになったみたいだし。


ということは、使う人がそれに慣れればうまく使えるという意味ではないだろうか。
もしうまく使えないのであれば、そういう傾向は広がらないはずだからだ。

 

思いついたのは、変数の型名を決めることだった。
なんだっけ、なんかそういう名前ルールの名前があったはずだ(コロンブスとかコロンビアとか、なんかそういう感じだったような。。。)。
昔は評判が悪いという人もいた名前付けルールなのだけど、型のない時代にこそ生きてくるのか?

ただまあ、これはこれでけっこうめんどくさい。
関数名は、読んでわかりやすいように、文字列を返すときは「xxStr()」などとしているが、1つでも忘れてしまうと意味が無くなってしまうので、しんどい。

 

 

などと調べていたら、pythonでアノテーションのしくみが導入されるらしいという記事を見かけた。
Javaもそうだったけど、あれはよいよね。
まあ、統合開発環境じゃないと効果が少ないかもしれんが。

はっ、いまpythonをテキストエディタでやってるけど、IDEを使うと悩みが減るのだろうか?

2016年10月25日

[py]pydocとdoxygenの両立がうまくいかない

自分用にユーティリティ関数を作っていたのだけど、どうせしばらくすると忘れてしまうだろうからコメントを付けておこうと思う。

どうせコメントを付けるなら、いつものようにdoxygen形式にするか、と思ったのだが、どうもpythonにはpydocというしくみがあるようだ。
これもまたコメントにしたものをドキュメントにするツールなのだが、特殊な構文はないようで、それっぽい位置にコメントを書いておけばドキュメントになってくれるようだ。

 

それでもよいかと思っていたのだが、変数にドキュメントとしてのコメント付けができないらしく、定数がいくつかあるモジュールだったので、ちょっと寂しい。
まあ、pythonは定数というものがないようなので、安全に運用するなら関数化して置いた方が無難なのだろうが、練習だ。


#encoding:utf-8

## @file    doxy.py
## @brief   doxygenで書いてみよう


## すごい関数
# @param[in]    prm1    すごい引数
# @return       すごい結果
def func1(prm1):
    '''
    good function
    '''
    return prm1 + 'is very good !!'

こういうpythonファイルを書いておくと、pydocでこう見える。

Help on module doxy:

NAME
    doxy - #encoding:utf-8

FILE /cygdrive/d/Prog/python/study/doxy.py

FUNCTIONS
    func1(prm1)
        good function

 

これはまだよいのだが、doxygen出力の方だ。

image

関数内のコメントが映り込んでしまった。
なんか、技はないものか。。。

2016年10月24日

[py]classにしなくてもモジュールとして使える

JavaやC#は、classを作る。
classを作って、その中にメソッドやら何やらを詰め込む。

pythonもそういう言語なのだろうと思って、同じファイル内では関数(クラス内ではないメソッドという意味ね)が書けるけれども、importする場合はクラス名がいるんだろう、と思い込んでいた。

だから、自分用のユーティリティ関数を作っていたのだが、それはclassにして、@staticmethodを全部に付けていた。
そうすると、同じファイル内でメソッドを呼び出したくてもクラス名を書かなくてはならないので、面倒だなぁ、しょうが無いなぁ、と思いながらやっていた。

 

が、そういうことはしなくてよいのだ。
ファイル名がモジュール相当で、それをimportしたら「ファイル名.関数名()」という形で使うことができるんだな。。。
おじさん、気付かなかったよ。

いやあ、使うときに「from ファイル名 import クラス名」みたいにしていたけど、他のモジュールってそういう使い方してないよなぁ、とは思っていたのだ。
「クラス名は大文字から始めるのが基本ルールです」と書いてあるのに、小文字で始まっているものが多いから「まったくルールを守らずに・・・」とか思っていたけど、あれはモジュール名だったのね。

気付けばわかるんだけど、一人でやっているとなかなか気付かないものだ。

[nrf51]MTU長の変更APIは今のところ無い

よく調べていなかった・・・。

S130が使えるようにnRF51822のRAM32KB版を買ったのだけど、S130はバージョンが2.0.1が最新で、まだなのかどうかわからないけど、今のところMTU長の変更APIが無かった。

しまった。。。
予定では「MTUをマックスまで延ばしてみました! でもスループットが上がったかどうか実感できませんね」という記事を書くはずだったのに。。。

 

気を取り直して、S130 v2の特徴を調べておこう。

  • GAP
    • LE Secure Connectionサポート
  • L2CAP
    • sd_ble_l2cap_xxx() APIが23バイト以上のパケットをサポートした

新規はこの2つだが、むむ、23バイト以上を一番下がサポートしたんだったら、あとは上位層が対応すればよいのか?
nRF52だって、MTU長の変更サポートはv3からだし、まだ希望は捨てなくてよいだろう。

 

ただ、Core v4.1以下の機器しかない状況では、普及すんのか?というのがネックになる。
そのうちスマートフォンで4.2対応機種が出てくるかもしれないけど、それまではv4.2の機能を使った機器は出てこないだろう。
そしたら、4.2に対応したスマートフォンを出さなくていいや、と思ってしまうかもしれない。

 

それだったら、いっそのこと別の規格でもいいんじゃないか?という発想が出てくるかも。
今のうちに試せるものがあれば遊んでみたいのだが、うん、やっぱり2.4GHz帯以外となると、個人ではなかなか手が出せませんなぁ。

2016年10月23日

[ble]BLE nanoを使う

先月買ったまま放置していたRedBear社のBLE nano。
RAMが16KBタイプは持っていたのだが、S130はそれでは使えないようなので、32KBタイプを買ったのだ。
くっ、もったいない。。。

 

SWDとして線は出ているのだが、形状がJ-Linkのものと違うので、nRFgo Studioなどが使えない。
nrfjprogなんかもダメそうだ。

 

BLENano/USB-IF at master · RedBearLab/BLENano
まず、ここでMK20-USBに入り、MK20の基板バージョンにあった方をダウンロード。
うちのは、V1.0だった。

これを、書いてある手順で焼く。
USBに挿す前に、横にあるボタンを押したままにし、USB接続し、ドライブとして認識されたらボタンを離す。
そして、D&D(うちはWindows)。
10秒くらいしたら再起動してよいらしいので、そうするとドライブが「DAPLINK」という名前で見えるようになる。

 

これに、S130のHEXをD&Dし、KeilでnRF51822用の設定にしてビルドし、デバッグするとmainで止まってくれたから、動いているのだろう。
RUNするとAdvertisingもしていたから、たぶんよかろう。

Keilって、CPUの設定を変えるとメモリのマッピングが初期化されるから、スクリーンショットを撮ってから変更すると楽かも。


でもやっぱりJ-Linkでつなぎたい。
前もやった気がするが、むりやりつなげよう。

image

うーん、きれいに撮影できない。。
図で描くと、こうだ。

image

VTrefをつながないとダメなので、計4本。
1.27mmというのがつらい。。。
今回は、秋月で買っていた1.27mm--2.54mm変換と、1.27mmコネクタを切り離すときに割れてしまったピンを使った。
スズメッキ線やジュンフロン電線の細いのがちょうどよいようなのだが、手元にないのよねぇ。
そういうのがあれば、こんな変換コネクタなど使わずに済むのだ。

つなげば、nRFgo Studioで見ることができる。

image