とある Solution Architect の轍

とある Solution Architect の轍

Next.js + TypeScript の学習ログ

現在の状態は、ある程度 React, TypeScript の経験があるが Next.js は未経験。
目標は GitHub Pages を Next.js + TypeScript で書き換えること。

1. 公式ドキュメントを読む

Next.js::Getting Started がエントリーポイントとして最適でした。
静的サイト生成を推してたり、公式ドキュメントからも Next.js 開発者自身が持っている思想みたいなのが読み取れるので必読です。
ゼロコンフィグで開発できることをメリットとする裏に、ディレクトリ構成がルーティングと対応することや、動的ルーティングのためのファイル名の規則などを理解しておく必要があります。

2. サンプルコードを読む

最終的に TypeScript 導入してサイト構築したかったので、公式ドキュメントの端々にある情報を拾っていましたが、それを読み進めるよりもサンプルコードを読んで修正して実行する方が手っ取り早そうでした。

(絶賛作業中)

Visual Studio Code の基礎 (設定・キーボードショートカット・拡張機能)

よりよい VS Code ライフを楽しむために、設定と拡張機能のメンテナンスをすることにしました。
VSCode はなんとなく使っていたのですが、生産性を上げる拡張機能拡張機能自体の開発方法を知りたくて、
プログラマーのためのVisual Studio Codeの教科書 (Compass Booksシリーズ)」を読みました。

設定ファイル

プラットフォームごとにユーザ設定ファイルである settings.json は以下のパスに配置されています。

  • Windows %USERPROFILE%\.vscode\extensions
  • macOS ~/.vscode/extensions
  • Linux ~/.vscode/extensions

code.visualstudio.com

ワークスペース設定はフォルダ内の .vscode/settings.json に配置されます。 ワークスペース設定、ユーザ設定、デフォルト設定の順に設定値が優先されます。
デフォルト設定はこちらにあります。 code.visualstudio.com

キーボードショートカット

全部覚える必要はないけれど、あると便利なものを少しづつ使いながら覚えていくのが良さそうです。

  • ctrl+shift+P でコマンドパレットを開く
  • ctrl+shift+L で同じ単語の一括選択
  • ctrl+shift+F でプロジェクト全体での語句検索
  • shift+alt+マウス選択 or ctrl+alt+矢印 で矩形選択

code.visualstudio.com

拡張機能

code --install-extension <extension-id>
# or
code --install-extension <path-to-vsix>

でコマンドを使った拡張機能のインストールができます。
インストールした拡張機能は以下のパスに配置されます。

  • Windows %USERPROFILE%\.vscode\extensions
  • macOS ~/.vscode/extensions
  • Linux ~/.vscode/extensions

code.visualstudio.com

スクリプトで一括インストールできるようにしておくと便利です。
例えば以下のようなスクリプトを用意して、bash install-vscode-extensions.sh すると環境構築が楽です。

#!/bin/bash

extensions=(
  # Misc
  editorconfig.editorconfig
  streetsidesoftware.code-spell-checker
  # Document
  yzane.markdown-pdf
  redhat.vscode-yaml
  hediet.vscode-drawio
  jebbs.plantuml
  # Infrastructure
  ms-azuretools.vscode-docker
  ms-kubernetes-tools.vscode-kubernetes-tools
  amazonwebservices.aws-toolkit-vscode
  # Visual
  oderwat.indent-rainbow
  ibm.output-colorizer
  mechatroner.rainbow-csv
  vscode-icons-team.vscode-icons
  # Remote
  ms-vscode-remote.remote-wsl
  ms-vscode-remote.remote-containers
  ms-vscode-remote.remote-ssh
  ms-vsliveshare.vsliveshare
  # Git
  eamodio.gitlens
  # Go
  golang.go
  # Rust
  rust-lang.rust
  # Python
  ms-python.python
  ms-python.vscode-pylance
  # JavaScript
  eg2.vscode-npm-script
  dbaeumer.vscode-eslint
  esbenp.prettier-vscode
)

for i in ${extensions[@]}; do
  code --install-extension $i
done

Go 言語入門 (1) ~概要編~

Go 言語に入門してみます。
本記事では概要編と題し、プログラムのコードについては深入りせず、まずはざっくり概要を抑えてワークフローを一通り俯瞰してみます。
Go 言語によるプログラム開発を進めるにあたり、まずは用語や固有のルールを理解して開発環境を構築して単体テストを実施するところまで流してみました。

用語

GOROOT

Go のインストールパスのこと。以前は環境変数に設定する必要がありましたが、
現在は Go のバイナリに GOROOT の情報が含まれているため、明示的に環境変数を設定する必要はありません。
GOROOTはインストール方法によって自動で決定されます。

go env GOROOT

で確認できます。
Goをインストールする場所を手動で置き換えた場合などは GOROOT 環境変数を明示的に設定する必要があります。
試しに GOROOT 設定を意図的に見当違いな設定に書き換えてみたところ、確かに以下のエラーが出ました。

go: cannot find GOROOT directory

$GOROOT/bin に go の実行バイナリが配置されるので、以下のように PATH を通しておきます。

export GOROOT=$(go env GOROOT) # 必要に応じて適宜書き換え
export PATH=$PATH:$GOROOT/bin

GOPATH

外部パッケージのリソース等が配置されるパスです。

go env GOPATH

で確認できます。標準では $HOME/go が設定されます。
GOPATH 以下の bin に実行バイナリが配置されるので、以下のように PATH を通しておきます。

export GOPATH=$(go env GOPATH)
export PATH=$PATH:$GOPATH/bin

go get

外部パッケージをインストールするのに使います。
GOPATH/bin 以下に実行形式ファイルが配置されます。
URL 階層構造がそのままディレクトリのそれに対応し、ソースコード$GOPATH/src に配置されます。
(なお、Go1.13 以降は Go Modules が有効化されるので若干挙動が異なります。) git で管理されているパッケージは git clone しているのとほぼ同義です。
{Repository FQDN}/{Repository Path} という階層構造がそのままパッケージ構成になる点は Go 言語の特徴的な点なので覚えておきましょう。

Go Modules

go mod サブコマンドで利用できる依存管理の仕組みです。
Go1.11 から試験的に導入、Go1.13 から正式化されました。
$GOPATH/src ではなく $GOPATH/pkg/mod 以下にリビジョンごとにパッケージが配置されるようになりました。
$GO111MODULE で on/off 設定ができます。

export GO111MODULE=on # on|off で設定 

便利なツール・OSS

公式コマンドラインツール

godoc, goimports, gopls 等、Go 公式で開発されているツールはよく使うのでまとめてインストールします。

# ... はワイルドカード
go get golang.org/x/tools/...

ghq

リポジトリの clone を管理するツール。
Go が要求するリポジトリ階層構造に合わせた clone を ghq で統一的に管理します。

github.com

go get github.com/motemen/ghq

で $GOPATH/bin 以下に実行ファイル ghq が配置され、PATH を通して準備完了です。
ほかの言語プロジェクトでも同様の管理ができるので、Go に限らずリポジトリの clone 全般に使えます。
Go に合わせた階層構造にするため、$GOPATH/srcソースコードを配置する場合は以下の設定をします。

git config --global ghq.root $GOPATH/src

peco

ターミナル上で標準出力をインクリメンタルにフィルタするツールです。
単体で何かするというよりは、上述の ghq と組み合わせてパイプして使うユースケースが多いです。
UNIX という考え方」にも書いてありましたが、

  1. Small is beautiful. 小さいものは美しい

に通ずるものがありますね。 小さい CLI を組み合わせることで便利な方法が次々生まれる。
可能な限り独立した小さなドメインに区切って CLI を作ってパイプでつなぐ発想は常に意識しておきたいものです。

UNIXという考え方―その設計思想と哲学

UNIXという考え方―その設計思想と哲学

  • 作者:Mike Gancarz
  • 発売日: 2001/02/01
  • メディア: 単行本

peco は sudo apt install -y peco でインストールできました。
自分は zshrc に以下の関数を定義して、ctrl + ] で peco + ghq を使ったディレクトリ移動、ctrl + R でインクリメンタルな実行履歴サーチをしています。

# incremental search
#   ref. https://qiita.com/strsk/items/9151cef7e68f0746820d
function peco-src () {
  local selected_dir=$(ghq list -p | peco --query "$LBUFFER")
  if [ -n "$selected_dir" ]; then
    BUFFER="cd ${selected_dir}"
    zle accept-line
  fi
  zle clear-screen
}
zle -N peco-src
bindkey '^]' peco-src

# history search
#   ref. https://qiita.com/reireias/items/fd96d67ccf1fdffb24ed
function peco-history-selection() {
    BUFFER=`history -n 1 | tac  | awk '!a[$0]++' | peco`
    CURSOR=$#BUFFER
    zle reset-prompt
}
zle -N peco-history-selection
bindkey '^R' peco-history-selection

cobra

Cobra is both a library for creating powerful modern CLI applications as well as a program to generate applications and command files.

github.com

自分の場合、Go といえばシングルバイナリ、シングルバイナリといえば CLI(?) といった感じに最終的な成果物は CLI としてのインタフェースをもつことが多いです。
標準ライブラリに CLI 向けパッケージもありますが、

  • サブコマンド等の複雑なことをしたい
  • コマンドのテンプレートコードを自動生成してほしい

といったニーズにマッチしていて、kubectl や hugo といった著名 OSS でも採用実績のある安定と信頼の cobra を愛用しています。

Makefile

Go の OSS を見てみるとルートディレクトリに Makefile が置いてあることが多いです。
スクランナー的にコードフォーマットやリンター、性的解析等を行うためにオレオレ Makefile をよく見ます。
これは新しい知識を得たら日々改善していくもので日進月歩なところがあり汎用的なベストプラクティスはわかっていないのですが、
Makefile のコマンドヘルプを自動生成するコードはよく見ました。
自分は以下の記事を参考にしつつ、以下の help コマンドを定義しています。

marmelab.com

# https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
.PHONY: help
help:
    @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
.DEFAULT_GOAL := help

.PHONY: hoge
hoge: ## help for hoge
    echo hoge

として、make または make help を実行すると以下のようにヘルプが出力されます。

hoge                           help for hoge

Tips

リポジトリ構成

Standard Go Project Layout なるものがあるのでそれを読みます。

github.com

少しかいつまむと、、

  • CLI ツールのバイナリのみを成果物とする場合は、ルートディレクトリに main パッケージを配置する
  • ライブラリも成果物として提供したい場合は、ルートディレクトリにライブラリのパッケージを配置し、バイナリ(main パッケージ)は cmd/{repository name} に配置する

といったところが重要そうです。
後者のようにする理由としては、

  • go build はデフォルトで main パッケージが置かれるディレクトリ名を出力バイナリとして使う
  • cmd というディレクトリ名から CLI ツールであることが利用者から容易に想像できる

からだとか。

設定ファイル

大抵の CLI では設定を喰わせて実行することが多いですが、その置き場所に色々と流派があるようです。
UNIX では、

  • $HOME/.myapp
  • $HOME/.config

だったり、Windows では、

  • %USERPROFILE%.config\
  • %APPDATA%\my-app

だったり。
ホームディレクトリを取得する方法として真っ先に os/user が思い浮かびますが、一部の OS では cgo を使って実装されているため、
ロスコンパイルしたたおきに正しく動作しないケースがあるようです。
Go1.12 からは os.UserHomeDir() が追加されました。プラットフォームの違いに影響せず、cgo を使っていない API なので使いやすそうです(が、Windows はお作法が異なるので個別実装は避けられない)。
具体的には、runtime.GOOS == "windows" のケースだけ分岐するような実装になります。

バージョン番号の埋め込み

version サブコマンドでコミットハッシュを取得できると実行バイナリの詳細なバージョンがわかるので運用上便利です。

VERSION=$(git rev-parse --short HEAD)
go build -ldflags="-s -w -X 'github.com/ks6088ts/template-go/cmd.version=$VERSION'" -o outputs/template-go .

という感じに cmd パッケージの version 変数値をビルド時に埋め込みます。

単体テストの実行

testing パッケージと go test コマンドでテストを実施します。
テストコードは、Test から始まる関数として実装します。

func TestExample(t *testing.T) {
    fmt.Println("hello")
}

慣習としては hoge.go に対応するテストとして、hogte_test.go を配置します。(なお、*_test.go はテストコードのファイル名に関する規則)

go test -v hoge_test.go

でテストを実行できます。

参考書籍

Effective Python を読んだ

Effective Python 第二版が出ていて、Python3 に関する記述が増えていたので読んでみました。
書籍のリポジトリはこちら。

github.com

ざっと読んで学びがあった個所をメモしています。

Pythonic 思考

PEP8 = Python Enhancement Proposal #8 で提案されているスタイルガイドは通読してく価値があります。

www.python.org

Pylint 等のツールでエラー検出する習慣をつけておけば自然と PEP8 準拠になります。

pypi.org

Python3 では文字データを表すのに、 bytes と str の 2 種類があって、
bytes は生の符号なし 8 bit 値(通常 ASCII エンコーディング)、str のインスタンスはテキスト文字を表し Unicode コードポイントを含みます。
bytes はバイナリエンコーディング、str はテキストエンコーディング
bytes の decode メソッドで Unicode、str の encode メソッドでバイナリデータに変換できます。

https://github.com/bslatkin/effectivepython/blob/master/example_code/item_03.py

の実行結果がイメージできれば OK

  • Python 3.6 からはフォーマット済文字列(= f 文字列)を使え
  • 複数代入アンパックを使って、シーケンスへのインデックスによるアクセスをせずにコードを明確にする
  • range ではなく enumerate
  • イテレータ並列処理は zip(+itertools の zip_longest)
  • Python 3.8 で walrus演算子の新構文がサポートされる

リストと辞書

  • list 型の sort メソッドは key 関数や reverse 値でソート順の定義ができる
  • Python 3.6 以降から dict 型の挿入順序が保持される仕様に
  • 組み込み型の dict には get メソッドがあり、第二引数で第一引数が存在しない場合に返すデフォルト値を指定できる

関数

  • None を返さずに例外を送出し、呼び出し元が適切な例外処理を組めるようにする
  • def 文で *args を使うことで可変個数の位置引数を受けられるが、以下の点には注意すること
    • タプルに変換されて渡されるので、ジェネレータを引数指定するとメモリ消費してクラッシュする可能性
    • 位置パラメータを追加すると発見が困難なバグにつながるおそれ
  • 動的な値を持つキーワード引数にはデフォルト値として None を用いる
    • モジュールロード時に評価されて以降再度評価されることがないから
  • functools のデコレータ wraps を使う

参考書籍

Effective Python 第2版 ―Pythonプログラムを改良する90項目

Effective Python 第2版 ―Pythonプログラムを改良する90項目

  • 作者:Brett Slatkin
  • 発売日: 2020/07/16
  • メディア: 単行本(ソフトカバー)

UnitV AI Camera のセットアップ

UnitV AI Camera を購入したのでそのセットアップログを書き留めておきます。

クイックスタート

ドキュメントはこちら。

docs.m5stack.com

ドキュメントやツールの UI でところどころ M5StickV の記述がちらほらあるのはどういうことだろう。。
ひとまず M5StickV ≒ UnitV という脳内補完をしつつ、ハマりどころがいくつかあるはずなので注意して進めということという理解で進めます。

FTDI ドライバ

UnitV を Windows PC から認識できるようにするには、
FTDI のドライバを手動でインストールする必要があります。
自分の場合は、以下サイトでインストーラ経由でドライバをインストールしたところ、COM ポートで認識されました、めでたし。

ftdichip.com

Maixpy UI 環境の構築

docs.m5stack.com

やることとしては、

  1. Firmware を上記リンクからダウンロード
  2. Kflash_GUI ツールで上記 FW を指定して書き込み
  3. Maixpy-IDE をインストール
  4. Maixpy-IDE から接続

Tera Term 等でシリアル通信する場合は、Baud rate 設定を 115200 にしてください。
(それ以外だと文字化けします)

4 で Maixpy-IDE をインストールした直後、以下のサンプルコードがデフォルトで表示されていて、試してみると RGB のヒストグラムフレームバッファが表示されます。
ターミナルにはフレームレートがダンプされます。(自分の環境では大体 6fps 出ていました)

# Hello World Example
#
# Welcome to the MaixPy IDE!
# 1. Conenct board to computer
# 2. Select board at the top of MaixPy IDE: `tools->Select Board`
# 3. Click the connect buttion below to connect board
# 4. Click on the green run arrow button below to run the script!

import sensor, image, time, lcd

lcd.init(freq=15000000)
sensor.reset()                      # Reset and initialize the sensor. It will
                                    # run automatically, call sensor.run(0) to stop
sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.QVGA)   # Set frame size to QVGA (320x240)
sensor.skip_frames(time = 2000)     # Wait for settings take effect.
clock = time.clock()                # Create a clock object to track the FPS.

while(True):
    clock.tick()                    # Update the FPS clock.
    img = sensor.snapshot()         # Take a picture and return the image.
    lcd.display(img)                # Display on LCD
    print(clock.fps())              # Note: MaixPy's Cam runs about half as fast when connected
                                    # to the IDE. The FPS should increase once disconnected.

ひとまず動いた。
個人的には Maixpy-IDE を個別に入れる作業がイマイチで、
デフォルトで VSCode に extension を提供してくれるほうが今時の開発者フレンドリーなんだけどなぁ。。

f:id:shnj:20210222143342g:plain
maixpy-ide

M5Stack Core2 ESP32 IoT Development Kit for AWS IoT EduKit 入門 ~開発環境の構築~

AWS IoT 関連サービスの学習や、エッジデバイスの組み込みデバイス開発の入門のため、
M5Stack Core2 ESP32 IoT Development Kit for AWS IoT EduKit を購入し Hello World してみました。

環境

チュートリアル

AWS IoT EduKit に沿って読み進めます。

ドキュメントにもありますように M5Stack Core2 for AWS は日本からだと Switch Science で購入することができました。
自分の場合、ちょうど在庫があったので注文から納品まで大体 3日でした。

www.switch-science.com

事前準備

CP210x Universal Windows Driver

ターゲットデバイスWindows PC から接続するため、
USB to UART のブリッジ接続をするためのドライバをインストールします。
CP210x USB to UART Bridge VCP Drivers でリストアップされている、CP210x Universal Windows Driver をインストールします。
展開してインストーラ(CP210xVCPInstaller_x64.exe) を実行するだけです。
インストールが完了すると、デバイスマネージャーポート(COMとLPT)Silicon Labs CP210x USB to UART Bridge が確認できます。

f:id:shnj:20210222094819p:plain
CP201x Driver

VSCode 拡張: PlatformIO IDE

  1. コマンドパレットを開く(ctrl+shift+p)
  2. Install Extensions を選択
  3. platformio.platformio-ide をインストール

.platformio ディレクトリ以下に cmake 等のツール群がインストールされました。

スマホアプリ ESP RainMaker (任意)

スマホからターゲットデバイスの操作をする場合は、ESP RainMaker をインストールします。
Android 版はこちら -> ESP RainMaker

サンプルコードの実行

以下のリポジトリに幾つかサンプルコードがあるので実行してみます。

github.com

今回は Getting-Started プロジェクトを実行します。

ソースコードを clone して vscode を開く

Getting-Started をルートとして vscode を開きます。

git clone https://github.com/m5stack/Core2-for-AWS-IoT-EduKit.git
cd Core2-for-AWS-IoT-EduKit/Getting-Started
code .

シリアルポートの接続設定

platformio.ini の upload_port に接続ポートを入力します。
自分の場合は、COM4 で接続されていたので、

upload_port = COM4

に書き換えるだけです。

ビルドする

プロジェクトのカラムから Build を選択するとファームウェアがビルドされます。
ターミナルのログから .pio/build 以下にビルド成果物が生成されているのがわかります。
詳細は CMakeLists.txt を追う感じになりそうです。
接続設定が誤っているとこの時点でエラーを吐いていました。
一度エラーを吐いた後、接続設定を修正してビルドしても中途半端な生成物が残存して失敗することがあったので、Clean をしておくと良さそうです。

f:id:shnj:20210222100626p:plain
platformio

FW を書き込む

プロジェクトのカラムから Upload を選択するとファームウェアが M5Stack Core2 に書き込まれます。

スマホから制御する

ESP RainMaker を起動しターミナルに表示された QR コードを入力してスマホから制御できるようにします。
(QR コードが表示されたり表示されなかったりしてよくわからない挙動。。)

Raspberry Pi Pico で MicroPython を実行し対話的に L チカしてみた

最近 Raspberry Pi Pico を頂いたので L チカしてみました。
小型で 500 円。セットアップも簡単で組み込みデバイスの入門にはとても良いです。

https://www.raspberrypi.org/documentation/pico/getting-started/static/4e43e3d335a3769aa85da9519b67af89/MicroPython-FINAL.gif


  1. Getting started with MicroPython に従って、UF2 ファイルをダウンロードします。
  2. GIF 動画にあるような形で、BOOTSEL ボタンという基盤についたボタンを押下しながら PC にUSB 接続
  3. ストレージデバイスとしてマウントされるので、1 でダウンロードした UF2 ファイルを配置。自動で再起動されます。
  4. Tera Term 等のターミナルソフトで接続先の COM ポートを指定して接続すると REPL ターミナルに入る
  5. 下記コードを実行して LED が制御できることを確認
from machine import Pin
led = Pin(25, Pin.OUT)
led.value(1) # 点灯
led.value(0) # 消灯

無事に L チカできましたの図。 f:id:shnj:20210219144502j:plain