2020/04/27

VirtualBox 6.1.6にしたらMint Linuxのフルスクリーンが黒い

タイトル通り。

VirtualBoxを6.1.6にアップデートしたのだが、Mint Linuxをフルスクリーンにすると黒い画面になってしまうようになった。
フルスクリーンでも、最初に出てくるログイン画面は大丈夫なのだ。あそこまではVGAだかSVGAだかのサイズになっていて、画面の中央に表示される。
そこでログインすると、真っ黒なのだ。

 

一度フルスクリーンを解除すると表示されるので、またフルスクリーンに戻せば済む。
済むのだが、何度かやっていると面倒になってきた。

じゃあ1つ前のバージョンに戻すかというと、そうするとクリップボードの共有で問題が出てくる。
なので、6.1.2まで戻した。
そうすると、うん、ちゃんと表示されるね。

 

なんかMint Linuxにしてからあれこれ相性が悪いのだ。
もしかしたらcinnamonとかいうのを選択したからかもしれないが、LubuntuかXubuntuに戻そう。
ここは、最近出たばかりの20.04LTSを試すべきか。

2020/04/26

[golang]"local import "./xxx" in non-local package"はエラーなのか?

こそこそとgolangの勉強を続けている。
別にこそこそしなくてもよいのだが、成果が上がらないので書けるものが無い、というところだ。

 

golangの勉強をしていて一番嫌なのは、importについてだ。
基本的に公開しないプログラムを書くことが多いので(お仕事だからね)、localでgit管理はしていてもリポジトリを外部に公開しないことが多い。
でも、golangはローカルを参照するのは推奨しないとかいってるじゃないか。
なんか、もう、あー、うー、みたいな気持ちになってしまう。

 

そこで、golangのimportについては言語仕様ではない、と思い込むことにしようと考えた。
例えば、importする中に"yoyo"と書いていた場合、そんなものはないのでエラーになる。

package yoyo is not in GOROOT (/usr/lib/go-1.14/src/yoyo)

では、これを"./yoyo"にしてみる。

local import "./yoyo" in non-local package

まあ、実際にないので、これもわかる。
"mkdir yoyo"としても同じ。

では、ここでyoyoディレクトリを作って、その中にhoho.goを作り、"package yoyo"という1行だけのファイルを置く。

local import "./yoyo" in non-local package

うーーーん・・・。
バイナリができていないのでエラーなのだろうけど、ディレクトリつくってpackage指定までしてもimportで文句を言われるというのは、いったいなんなのだろうか?


あれこれやったのだけど、go.modでreplaceしているときはgo get -uじゃない方がよさそう、ということくらいしかわからなかった。

エラー?のようになってたのも、go.modのrequireのところに書いていたせいのような気がしなくもない。が、-u無しでgo getしてもgo.modが更新されてrequireに追加されているようだ。

わからない、わからない。。。

 

今回困っていたのは、github.com/xxxの下に2つディレクトリを作っていたのだ。
ディレクトリAの方は単体で動きつつサブディレクトリA/aでライブラリ的な使い方もできるようにしている。そしてAaは同じ階層にあるA/bをimportしている。
ディレクトリBの方はAのサブディレクトリA/aをimportして使っている。

ビルドしたいのはディレクトリB。
なので、B/go.modではrequireにAaを書いて、replaceでA/aを相対パスで指定していた。
が、そこでgo getすると、

cannot find module providing package github.com/xxx/A/b

のような怒られ方をしてしまう。
そこでreplaceでA/bを相対パス指定するようにするとgo getが通って、B/go.modのrequireにA/bも追加されていた。
ただ、これでもgo get -uするとgitがどうのこうのと怒られてしまった。

 

うん、よくわからんが、go get -uはgo.modよりも強い、ということなのかな。

2020/04/18

[golang]サブコマンドを使う

gitみたいなコマンドは、サブコマンドであれこれできる。
そんな感じのアプリを作りたい。

 

flagというパッケージがあるのだが、ピンとこなかったのでこちらを使ってみる。

google/subcommands: Go subcommand library.
https://github.com/google/subcommands

標準パッケージではないそうだ。まあいい。

 

Usageをそのまま貼り付けてコンパイル。

引数無しで実行。

$ go run subcmd.go
Usage: subcmd <flags> <subcommand> <subcommand args>

Subcommands:
         commands         list all command names
        flags            describe all known top-level flags
        help             describe subcommands and their syntax
         print            Print args to stdout.

exit status 2

コマンド名がsubcmdなのは、ディレクトリがsubcmdだから、subcmd.goというファイル名だからか。。
main.goにリネーム。

$ go run main.go
Usage: main <flags> <subcommand> <subcommand args>

Subcommands:
        commands         list all command names
        flags            describe all known top-level flags
        help             describe subcommands and their syntax
        print            Print args to stdout.

exit status 2

うーん。

$ go run .
Usage: subcmd <flags> <subcommand> <subcommand args>

Subcommands:
        commands         list all command names
        flags            describe all known top-level flags
        help             describe subcommands and their syntax
        print            Print args to stdout.

exit status 2

うーーーん・・・。
まだこの辺のルールが理解できていない私であった。
まあ、ここはgolangのことだからいいとしよう。

$ ./subcmd commands
help
flags
commands
print

`print`しか実装していないので、残りは自動でやっているのだろう。
表示する順番は、自動が先になっているのかソートされているのか。
`print`を`energy`に変更してみる。

$ go run . commands
help
flags
commands
energy

自動が先になっている。
追加した方がどういう順なのかはわからんな。

 

$ go run . help
Usage: subcmd <flags> <subcommand> <subcommand args>

Subcommands:
        commands         list all command names
        energy           Print args to stdout.
        flags            describe all known top-level flags
         help             describe subcommands and their syntax

ここはソートされるのか。
なお、オプション無しでやcommandsにないパラメータで実行するとhelpと同じ出力+exit status 2だった。

flagsは出力がなかった。
`print`にはあるから、ここのflagsはグローバルなフラグなのだろうか?

先に`print`を見ていこう。

$ go run . print

$ go run . print help
help
$ go run . print --help
print [-capitalize] <some text>:
        Print args to stdout.
     -capitalize
        capitalize output
exit status 2

最後のはエラー扱いなのか。
ということは、こうか。

$ go run . flags print
  -capitalize
        capitalize output

そういうことか。ただ"all known top-level flags"だから、違う使い方があるのかもしれん。

$ go run . print MomonGa -capitalize
MomonGa -capitalize
$ go run . print -capitalize MomonGa
MOMONGA

後ろに付けるとオプションではない扱いになるのか。


では、多少コードを変更してみよう。

 

まず、Register()の順序を変更して、`print`を先頭で行うようにする。

$ go run . commands
print
help
flags
commands

うむ、追加した順番なのだな。
helpも順番通りの方が良い気がするのだが、どうなんだろうね。
でも、CommandGroupというのがあるから、グループにできるのかもしれん。

Register()のところを、こうしてみた。

subcommands.Register(&printCmd{}, "ぷりんと")
subcommands.Register(subcommands.HelpCommand(), "よしお")
subcommands.Register(subcommands.FlagsCommand(), "よしお")
subcommands.Register(subcommands.CommandsCommand(), "ぷりんと")

そうすると、helpがこうなる。

$ go run . help
Usage: subcmd <flags> <subcommand> <subcommand args>

Subcommands for ぷりんと:
        commands         list all command names
        print            Print args to stdout.

Subcommands for よしお:
        flags            describe all known top-level flags
        help             describe subcommands and their syntax

第2引数はグループ名で、グループ内でソートされる、と。
たぶんグループ名でもソートされているのだろう。

2020/04/17

[golang]ifの1行で実行とエラー判定をしたい

golangのコードを見ていると、ifで実行しつつエラーの判定をしていることがある。

When Should I Use One Liner if...else Statements in Go? - Calhoun.io
https://www.calhoun.io/one-liner-if-statements-with-errors/

ここの最初に出てくるようなやつね。

01: if err := doStuff(); err != nil {
02:   // handle the error here
03: }

見た目から入っていきたいお年頃。こういう書き方はgolangっぽいという気がするのでまねしたい。

 

16進数の文字列が渡されたら処理をして、そうじゃなかったら別の処理、みたいなことをやろうとしていた。
0xで始まる数字であれば16進数と見なそうかと思ったが、そんなに急ぐ処理でも無いのでデコードしてエラーがなければ、という判定までしよう。
20byteなので、0xまで入れたら42文字。

01: if (len(mojimoji) == 42) && (_, err := hex.DecodeString(mojimoji[2:]); err == nil) {
02:     ...
03: } else {
04:     ...
05: }

syntax error: unexpected comma, expecting )

えっ、ダメなの??

ifを2つに分けると、大丈夫。

01: if len(mojimoji) == 42 {
02:     if _, err := hex.DecodeString(mojimoji[2:]); err == nil {
03:         ...
04:     }
05: } else {
06:     ...
07: }

golang以外だったら分けて書くだろうし、やっぱりセミコロンを挟む書き方はちょっと違うのだろう。

 

言語仕様を探し出せなかったのだが、ifにセミコロンがあると、セミコロン前が処理相当になるらしい。
じゃあ、ダメか。

 

先にhex.DecodeString()してしまえば、セミコロンの後ろに条件文を&&で書いてしまえば良いかもしれん。
が、それは嫌だ!
文字長の処理の方が16進数文字列のデコードより処理が軽いのは間違いなかろう。だったら、先に軽い処理で露払いをして、その壁を乗り越えてから本番を迎えるのがよかろう。

 

「急ぐ処理じゃあない」と書いておきながら矛盾している気もするが、譲れない線もあるのだ。
意味があるかどうかは別としてね。。。

2020/04/12

[linux][xubuntu]Mozcが使えなかったが、何かしたら使えた

タイトルからしてダメダメだな・・・。
そして、内容もその通りなのだ。
すまん。

ただ、記録として残しておきたいだけだ。


事の発端は、VirtualBoxのゲストOSを新しく作ることにしたことだった。

ubuntu系であることは決めていたのだが、それにするかは決めていなかった。
オリジナルもいいし、最近使っていたLubuntuもいい。
別のところでMintを初めて使ってみたのだが、ときどきMintだからうまくいかないと思われるところがあった。もちろん回避方法はあるのだが、今の作業がubuntu環境を前提としているので、ちょっと困る。
ならdockerとかでやりゃいいやん、となるのだが・・・まだうまく使えないのだ。

 

まあ、私の技術的に足りないところは置いておくとして。
今回はXubuntuを使うことにした。Xubuntu 18.04.4。
初めてUbuntu系でオリジナル以外を使ったのが、Xubuntuだったのだ。

そして、ようやく本題。
Xutuntuをインストールして、環境設定をした。
私の場合、全体的にはen_US.UTF8にして、日本語の表示と入力だけはできるようにしている。
英語が苦手なので、ソースのコメントはしばしば日本語で書いているのだ。

日本語を追加してMozcを有効に使用としたのだが、input methodに何も出てこない。
そう、Mozcだけでなく、他の項目も出てこないのだ。
そういえばLubuntuのときもそういうことがあった気がする。

あれこれいじったのだが、結局どれが有効だったかわからないまま、いつの間にかinput methodにリストが表示されるようになっていた。
これはたぶん、Mozcや日本語とは関係なく、リストを更新するところがうまくいかないままだったりとか、そういうものなのかもしれない。

 

ただ、最初に書いたように、何かしたら直った、というレベルなのだ。
今回はfcitxのmozc(という表現であってるのか?)を使っているのだが、im-config, fcitx, fcitx-configなどを最後の方で使った気がする。

さっぱりわからんのだが、input methodに候補が出てこないとダメということはわかった。

2020/04/08

[golang]slackのmentionに返信

slack-go/slackのeventサンプルは返信をするようになっている。
今できていないのだが、それはPermissionが足りないからだろう。

image

うん、この2つがあればmentionを受けられるし、それによる返信もできた。

 

できれば、特定のキーワードがあれば勝手に返信してくれるようにできるとよいのだが。
次回はそれを探そう。

[golang]mentionの戻りtext

こんな構造体を作った。

01: type MsgEvent struct {
02:     Event struct {
03:         Blocks []struct {
04:             Elements []struct {
05:                 Elements []struct {
06:                     Type string `json:"type"`
07:                     UserId string `json:"user_id"`
08:                     Text string `json:"text"`
09:                 } `json:"elements"`
10:             } `json:"elements"`
11:         } `json:"blocks"`
12:     } `json:"event"`
13: }

 

そして、slack-go/slackのeventサンプルでbodyがあるので、こんな感じでデコードした。

01:             var msgEvent MsgEvent
02:             if err := json.Unmarshal([]byte(body), &msgEvent); err != nil {
03:                 log.Fatalf("json: %v\n", err)
04:             }
05:             for _, item := range msgEvent.Event.Blocks {
06:                 for _, item2 := range item.Elements {
07:                     for _, item3 := range item2.Elements {
08:                         if item3.Type == "text" {
09:                             log.Printf("text=%s\n", item3.Text)
10:                         }
11:                     }
12:                 }
13:             }

 

気力が尽きたので、今日はここまで。

2020/04/07

[golang]slack-goのeventsサンプルを動かしたい

以前あきらめた、slackのbotをgolangで作る件だ。
そろそろやろう。

slack/events.go at master · slack-go/slack
https://github.com/slack-go/slack/blob/master/examples/eventsapi/events.go

"TOKEN"が2箇所あるので、そこだけ自分の"xoxb-"で始まるやつと、Verification Tokenというやつに置き換えれば済むはずだ。

しかし、何が悪いのか分からないけど、golang側で動いている形跡がない。
権限などの設定が足りないのか?

 

Basic Information

"Add features and functionality"は、3つ

* Event Subscriptions
* Bots
* Permissions

Verification Tokenはこのページに載っている。

 

OAuth & Permissions

Scopesは、"Bot Token Scopes"だけ。

* app_mentions:read

"xoxb-"出始まるTokenはこのページに載っている。

 

Event Subscriptions

ここのRequest URLが、なんだかすっきりしない。
events.goで"/events-endpoint"となっていたので、ここも"http://x.x.x.x:xxx/events-endpoint"にしたのだよ。あ、ポート番号はgoファイルの下の方で3000番になっていたのだけど、ちょうどiptablesで5000番が空いていたので変更したのだ。

これがよくわからないのだが、goサンプルをrunしていてもいなくても、ブラウザの方ではOKになるのだ。なのに、goの方にはログなども出ない。
あれこれやったところ、どちらも"/evt"にするとアクセスが飛んできた。

こんなbodyが飛んでくる。

{"token":"VTOKENの値","challenge":"ODiveSYjXafQWNBXY9PIIeNLP87Q5KM8gEUVD98rDNajxAebTrta","type":"url_verification"}

 

Subscrie to bot eventsは、"app_mention"を指定。

 

そうして、installなどして、どこかテスト用のチャネルにbotを追加してやって、メンションを投げるとイベントが飛んでくるようになった。
メンションと、Appsの一覧に出てきたアプリ名のところに書き込むのは同じかと思ってたけど、違うのだな。
app_mentionにしているからかもしれないけど、アプリ名以外のところで@つきでメッセージを投げないとダメなようだ。

 

まあいい。
あとは、ここからじわじわ変更していこう。

2020/04/05

[golang]NFC-AのUIDを読む

NFC-AのUIDを読むようにした。

https://github.com/hirokuma/go_pasori370/tree/13639388afe725696a6550cab07e760c9f5ce7b4

NFC-FとNFC-Aを順番にInListPassiveTargetして、先に見つかった方を返す。まあ、2つしかないので先も何もないのだが。

UIDの長さが、Single / Double / Trippleのどれかなのを確認すべきなのだろうが、仕様書を引っ張り出すのが面倒だったので4byte以上ならOKとしてしまった。

 

コードがきれいなのかどうかはまだ判断できないけど、そこまで悪くはないんじゃないかなぁ、どうかなぁ。。
他の人のコードなどを見て勉強するところまでやらないと、レベルは上がらんだろうな。

 

ともあれ、golangでNFC R/Wを動かすのはこれでおしまいだ。

2020/04/04

[golang]ようやくIDmを読む

ようやくgolang + RC-S370でIDmを読むところまでできた。

https://github.com/hirokuma/go_pasori370/tree/fed6133f67075d9dfc065274f71fc84391d38577

$ make
$ make run
2020/04/04 20:49:24 Opened
2020/04/04 20:49:24 write= 0000ff03fdd418011300
2020/04/04 20:49:24 read done: 6(0000ff00ff00)
2020/04/04 20:49:24 read done: 9(0000ff02fed5191200)
2020/04/04 20:49:24 write= 0000ff06fad43202000000f800
2020/04/04 20:49:24 read done: 6(0000ff00ff00)
2020/04/04 20:49:25 read done: 9(0000ff02fed533f800)
2020/04/04 20:49:25 write= 0000ff06fad43205000000f500
2020/04/04 20:49:25 read done: 6(0000ff00ff00)
2020/04/04 20:49:25 read done: 9(0000ff02fed533f800)
2020/04/04 20:49:25 write= 0000ff04fcd43281b7c200
2020/04/04 20:49:25 read done: 6(0000ff00ff00)
2020/04/04 20:49:25 read done: 9(0000ff02fed533f800)
2020/04/04 20:49:25 write= 0000ff09f7d44a010100ffff0101e000
2020/04/04 20:49:25 read done: 6(0000ff00ff00)
2020/04/04 20:49:25 read done: 31(0000ff18e8d54b01011401xxxxxxxxxxxxxxxx100b4b428485d0ff0003e600)
2020/04/04 20:49:25 IDm: xxxxxxxxxxxxxxxx
2020/04/04 20:49:25 PMm: 100b4b428485d0ff
2020/04/04 20:49:25 SystemCode: 0x0003
2020/04/04 20:49:25 Closed

なんとなくIDmは隠してみた。

 

Receiverはポインタ型が良いのかそうでない方が良いのか基準がよくわからなかったのだが、どこかのサイトで「実質は引数に与えられて呼ばれるのと同じ」と説明してあって理解できた。

 

あとは、NFC-AのID読み込みを作って、Pollingで両方実行して先に見つかった方を返す、というところを作ったら終わりかな。
いつもは汎用ライブラリみたいにしてたけど、あれは疲れるからな。

[golang]sliceの先頭に追加してみよう!

意味も無くタイトルでテンションを上げてみました。

データのパケットを作る関数を考えよう。
パケットの詳細を上位層に知らせないようにするため、パラメータをもらって中で加工するはずだ。
加工する際には、パケットの構造によってパラメータを切った貼ったすることだろう。

 

今回はNFCのtagでID読込だけすることにしたので、まずはInListPassiveTargetのパケットを作ろうとしている。
このパケットは汎用的といえばいいのか、NFC-A, B, Fの誰もが使うのだけど、パラメータに共通性はほとんどない。
まあ、このパラメータがほぼそのままRFで飛んでいくのだから仕方あるまい。

 

それはともかくとして、上位層からもらったデータをInListPassiveTargetの形式に収めるのに切った貼ったしたい。
RC-S956のパケットは可変長なのでsliceを使っている。
なので、sliceへの追加という処理が必要だ。


sliceにはappend()という関数があるので、それを使えば用は済む。
そう思っていたのだが、検索していると「遅い」という言葉がよく出てきた。
JavaでStringの処理をするような、そんな雰囲気だろう。

【Go言語】append使い分けのススメ 〜スライスの先頭へ要素を追加するとき、中身の型は固定長?可変長?〜
https://medium.com/eureka-engineering/go%E8%A8%80%E8%AA%9E-append%E4%BD%BF%E3%81%84%E5%88%86%E3%81%91%E3%81%AE%E3%82%B9%E3%82%B9%E3%83%A1-%E3%82%B9%E3%83%A9%E3%82%A4%E3%82%B9%E3%81%AE%E5%85%88%E9%A0%AD%E3%81%B8%E8%A6%81%E7%B4%A0%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D-%E4%B8%AD%E8%BA%AB%E3%81%AE%E5%9E%8B%E3%81%AF%E5%9B%BA%E5%AE%9A%E9%95%B7-%E5%8F%AF%E5%A4%89%E9%95%B7-dbf31fbf2f69

URL長いよ。。。

それはともかく、パケット生成程度では気にするものではなさそうだ。
たぶんデバイスとの送受信の方が時間かかるだろう。

 

私が思ったのは、コンパイラの限界についてだ。

ハードウェア制御をしていると、ここはアドレスバスを1本ずらしてRAMに接続しているから必ず16bitでアクセスしないとだめ、みたいな状況がしばしばある。
もちろん、コンパイラはそういう状況は知らないので、こっちがソースコードを書いたそのままコンパイルせざるを得ない。

 

そういう外部の状況であれば仕方が無いとして、C言語をメインで使っている人間としては、そういう使い分けを勝手にやってくれるようになってるんじゃないかと期待してしまう。

どうなんだろうか、どうなんだろうか。
私はgccを主に使っていたので、その範囲だとgcc4になって最適化が行いやすくなったような話を聞いた気がする。
しかし、関数単位でやっていると、そこは最適化しにくいだろう。inlineくらいか。

そういう下位層の部分はしかたないとしても、コピーしながら領域を拡張していくようなタイプだったら、うまいことやってくれてもいいのでは・・・。

もしかすると、append()は以前はなかったけれども、あまりにも使い勝手が悪いのでやむなく追加した、とかいう経緯があるのかもしれない。

 

まあいい、ともかく対処はいるのだ。

2020/04/01

[golang]NFCIDだけ読み取ろう、ということにした

設計が・・・とか考えて行動が止まっていたのだが、それくらいだったら適当に実装して作った方がよいだろう。
それを繰り返しているから設計がうまくならんのだ、といわれればそれまでなのだけど、深くは考えまい。

 

というわけで、今回はこういう構成にしよう。

image

 

pcdのところでdevを吸収して、devでRC-S370を受け持つ。
RC-S956を別に分けて、RC-S370ならUSB、RC-S620/SならUART、というようにしてもよいだろうが、今回はRC-S370だけでよい。

 

今はdev.IoCtlというインターフェースを作ってみたものの、まだ活躍していない。
一応、pcdはdev.IoCtlを持たせて、毎回devを呼ぶときに引数で渡して・・・あれ?

Linuxのドライバなんかはopen()してからclose()するまではファイルディスクリプタを使うけど、今回は特にそこまでしなくていいんじゃないのかね。
というわけで、グローバル変数を使うことにした。

 

図のdevでは省略しているが、これ以外にもコマンドごとに構造体を用意している。
それを使ってpcdから呼び出してもらっていたので、devは引数にしていたのだ。
まあ、それならコマンドの構造体メンバにdevを持たせるべきなのかもしれないが、それってあんまり意味がなさそうな冗長だと思ったのだ。

そういう余裕があればあとから改造が楽になる、ということもあるのだろうが。。。

 

とにかく、だ、あっさりした構成で作ることにしよう。

今日のできばえ
https://github.com/hirokuma/go_pasori370/tree/ec94e2dd82be08dd4020ddf285236058818a22c8