技術メモ

プログラミングとか電子工作とか

YouTube Data API (v3)を利用する為のAPIキーを取得する

基本的に下記の公式リファレンスを参照すれば大丈夫なんですが、よくわからんかった!という方がいらっしゃったら参考にして下さい。

developers.google.com

Googleアカウントの作成

詳しくは解説しませんが、こちらが参考になるかと。

office-hack.com

Google開発者コンソールの認証ページを開く

YouTube Data APIGoogleの1サービスとして提供されているものです。
基本的に設定はGoogleの開発者コンソールからいろいろ設定します。下記にアクセスしてください。

console.developers.google.com

ログイン情報が求められた場合はメールアドレスとパスワードを入力してログインしましょう。
初めてコンソールにアクセスする場合は利用規約などの表示がでると思いますので、利用規約を一読しチェックを入れます。

f:id:ysmn_deus:20200819174540p:plain

その後、右下の「同意して続行」を押すとGoogle Cloudプラットフォームの「認証情報」の画面が表示されるかと思います。

f:id:ysmn_deus:20200819174731p:plain

なにはともあれプロジェクトを作成しないことには作業ができないようになっています。
まずはプロジェクトを作成しましょう。

プロジェクトの作成

左上の「プロジェクトの選択」をクリックします。

f:id:ysmn_deus:20200819175334p:plain

「プロジェクトの選択」モーダルが表示されると思いますので、右上の「新しいプロジェクト」をクリックします。

f:id:ysmn_deus:20200819175427p:plain

「新しいプロジェクト」と表示されたページに移動すると思います。
プロジェクト名に適当な名前(後で見て分かりやすい名前、ここでは YouTube Live Calendar Sync としておきますが、なんでもいいです)

f:id:ysmn_deus:20200819175725p:plain

「場所」は特に変更しなくて良いと思います。「作成」をクリックしてプロジェクトを作成します。

f:id:ysmn_deus:20200819175907p:plain
ぐるぐるがでて・・・

下記のような画面になれば、プロジェクトの作成は完了です。

f:id:ysmn_deus:20200819175925p:plain

APIキーの作成

ようやく本題です。「認証情報を作成」から「APIキー」を作成します。

f:id:ysmn_deus:20200819180512p:plain

f:id:ysmn_deus:20200819180616p:plain

あら簡単!APIキーができました。

f:id:ysmn_deus:20200819180857p:plain

上記の画像では黒で塗りつぶしていますが、なにか文字列が並んでいると思います。
これがAPIキーです。たぶんこの記事を見ている方はなにがしかに使うのでメモっておいてください。
また、基本的にこの文字列は公開しないようにしましょう。めんどくさいことになります。
一応「キーを制限」というボタンをクリックして、名前だけ変更しておきます。

f:id:ysmn_deus:20200819181204p:plain

f:id:ysmn_deus:20200819181323p:plain

YouTube Data API を有効にする

前までの項目でAPIキーは作成できてるのですが、YouTube Data APIが利用できる状況ではありません。
YouTube Data APIが利用できるようにしましょう。

同じ画面の「APIとサービスを検索します」というところに「youtube」と入力しましょう。

f:id:ysmn_deus:20200819181546p:plain

YouTube Data API v3」と書かれた箇所をクリックすると、YouTube Data API v3が表示されたページに移動すると思います。

f:id:ysmn_deus:20200819181700p:plain

「有効にする」というボタンがあるので、それをクリックします。
ぐるぐるが終わったらYouTube Data API v3の利用状況が表示されたページに移動します。

f:id:ysmn_deus:20200819181845p:plain

基本的にこれで作業は完了です。

ためしにAPIを使ってみる

APIキーがちゃんと有効になっているか確かめてみます。
ひかえてあるAPIキーで下記のURLを書き換えてブラウザでアクセスしてみて下さい。

https://www.googleapis.com/youtube/v3/search?part=id,snippet&q=youtube&key=[APIキー]

例えば、APIキーが ABCDEFG なら https://www.googleapis.com/youtube/v3/search?part=id,snippet&q=youtube&key=ABCDEFG です。

f:id:ysmn_deus:20200819182922p:plain

なにかゴチャゴチャと表示されていれば成功です。
一応上のAPIは、「youtube」というキーワードで検索したときの動画の結果になっています。
(上記の画像ではヒカキンさんの動画がヒットしている)

以上で大丈夫なはず!

f:id:ysmn_deus:20200819183342p:plain

NanoPi R2Sのリモートセットアップ(たぶんRaspberry Piとかでもいける)

所用でVPNブリッジのマシンを選定しておりまして、NanoPi R2Sである程度パフォーマンスが出ると導入しやすいし嬉しいなぁと言うことでNanoPi R2Sを複数台調達しました。
とりあえず現段階でのセットアップ方法をメモしておきます。
VPNブリッジにする記事は気が向いたら書きます。

なんでリモートでセットアップ?

NanoPi R2Sにはディスプレイ接続できないからです。
Raspberry Piもセットアップの時にディスプレイじゃまくさくないですか?

必要なもの

f:id:ysmn_deus:20200817135236j:plain

  • NanoPi R2S本体
    自分はFRIENDLY ELECから直接購入しました。
    NanoPi R2S
    1個だけ購入するなら本体代22 usd + 送料(8.9 usd ~ 27 usd、オススメはSF-Express)なので、1個だけにしろ基本的に公式から買うのが安いです。
    一応Amazonにも何種類かありますが、何故かケースありの方ケース無しより安かったのでそちらがオススメです。

  • ACアダプタ(USB電源でも可)
    よくラズパイとかとセットになっている、USB-microのACアダプタが妥当です。
    専用に購入するならこんなやつ
    こういうスマホを充電するUSB-ACアダプタでも問題無いかと思いますが、1ポートあたり2Aは確実に流せるものを準備しましょう。

  • SDカード
    今回は公式で用意されているイメージを利用しますので、少なくとも8GBぐらいは必要です。
    たぶん8GBだと詰むのでミニマム16GBのものとかでしょうか。(自分はよく32GBを利用します)
    SDカードは意外と破損しやすいので謎メーカーを避けるとして、SanDiskのもので十分かと思います。
    ちょっと心配な人なら東芝製とかがオススメです。(どっちも使ってて壊れたことないですが)

  • LANケーブル これは適宜。VPNブリッジとして利用するので少なくとも2本ぐらいはいると思います。

SDカードにイメージを書き込む

NanoPiの公式サイトから専用のイメージをダウンロードしてきます。
図の「download link」というところから保存できます。

f:id:ysmn_deus:20200817140215p:plain

BaiduとGoogle Driveの2択ありますが、無難にGoogle Driveで良いと思います。(Baidoはパスワード入力などが必要)

f:id:ysmn_deus:20200817232940p:plain

f:id:ysmn_deus:20200817232952p:plain

zipファイルが保存されるので、解凍して「rk3328-sd-friendlycore-bionic-5.4-arm64-20200707.img」を準備します。
通常のRaspberry PiであればRaspbianなどで良いと思います。 Linuxならマウントしてddコマンドでいいですが、Windowsの場合は

  • フォーマット
  • ファイルコピー

が必要になります。

フォーマット

無難にSDメモリカードフォーマッターを利用してフォーマットするのが良いと思いますが、たぶんWindowsの標準機能でフォーマットしてもいいんじゃないかと思います。

www.sdcard.org

利用方法などは上記ウェブサイトのユーザーマニュアルなどを参考にして下さい。

ファイルコピー

結構「Win32 Disk Imager」を利用している例が多かった(公式もそう)のですが、Windows10でうまく動かなかったのでUSBWriterを利用しました。

www.gigafree.net

たぶん使い方は起動すれば分かると思います。

f:id:ysmn_deus:20200817233655p:plain

上記2項目を行えば、SDカードの準備は完了です。

初期設定

とりあえず上記までで事前準備は完了なので、SDカードを挿してWAN側にLANケーブルを挿し、ルーターなどに接続します。
基本的にここまで行けばあとは全てSSH経由で行うので、電源が入っていれば手の届かない所にあっても良いと思います。

IPの確認

基本的にNanoPi R2SはDHCPでIPが割り当てられる環境にいるとします。
(普通にルーターを使っている環境であれば、どっかのポートに挿せばIPが割り当てられます)
NanoPi R2Sにはディスプレイポートなどはないので、IPはルーター側のIPリリース情報から取得します。
これは、ルーターによって異なるので割愛しますが、たぶん管理画面の「DHCP」の設定項目みたいな箇所で確認できます。
(もしくはログ?)

SSHでログイン

ちょっとここで躓きました。公式サイトには「rootでログイン」と書かれており、実際/etc/ssh/sshd_configにも

...
#LoginGraceTime 2m
PermitRootLogin yes
#StrictModes yes
...

となっているのでrootでログインできそうなもんですが、どうもうまくいきません。
(ブラウザからのアクセスもうまくいきませんでした)
とりあえず

  • ユーザー名: pi
  • パスワード: pi(通常のRaspberry Piの場合はraspberry)

でいけたので、これでSSHでログインします。
(Friendly Elecで販売されている「NanoPi」シリーズは、大体ユーザー名がpiでパスワードもpiなので、試してみたらいけました)

ssh pi@[前項目で確認したIPアドレス]

本当はとっととrootにパスワードを付けたい所ですが、念のためIPの固定からやっていきます。

IPの固定

これは色々方法(ルーター側からMACアドレスとIPを紐付けるなど)があると思いますが、とりあえず家のネットワークは基本マシン側からIPを固定しているのでNanoPi R2Sの設定で対応します。
中に乗ってるディストリはUbuntuですので、Ubuntuの公式ネットワーク設定に従います。

ネットワークインターフェースの確認

まずどのインターフェースがWANとLANに割り当てられているか見てみます。

pi@NanoPi-R2S:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether ba:88:4f:97:b2:26 brd ff:ff:ff:ff:ff:ff
    inet [前項目で確認したIPアドレス]/24 brd 192.168.x.255 scope global eth0
...

[前項目で確認したIPアドレス]があるインターフェースがWAN側のポートになります。
ここではeth0が該当します。

設定ファイルの作成

/etc/netplan/99_config.yamlを作成して、そこに設定を追記します。

pi@NanoPi-R2S:~$ sudo vi /etc/netplan/99_config.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: false
      addresses: [[前項目で確認したIPアドレス]/24]
      gateway4: 192.168.x.1
      nameservers:
          addresses: [192.168.x.1, 8.8.8.8, 8.8.4.4]

とりあえずGoogle Public DNS(8.8.8.8, 8.8.4.4)も適応しておきます。お好みでCloudflareにしてもいいでしょう。
ファイルを作成できたら

sudo netplan apply

で適応します。
たぶんこれでIPは変わらない筈。

パスワードの変更

とりあえずrootがパス無しなのと、デフォルトユーザーのpiがpiという脆弱極まりない環境が気になるので変更しておきます。

pi@NanoPi-R2S:~$ sudo passwd
Enter new UNIX password:  <- パスワード入力
Retype new UNIX password: <- もう一回入力
passwd: password updated successfully

一応あってるか確認

pi@NanoPi-R2S:~$ su -
Password: <- 先ほど設定したrootのパスワード入力

ユーザーが切り替わればrootのパスワードは変更完了です。
piも変更しておきます。(たぶんこっちをメインに使う事になる)

pi@NanoPi-R2S:~$ passwd
Changing password for pi.
(current) UNIX password: <- 現在のパスワード入力、今は「pi」
Enter new UNIX password: <- 新しいパスワード入力
Retype new UNIX password: <- もう一回入力
passwd: password updated successfully

ログアウトして確認しておくといいでしょう。
(現段階では最悪SSHのrootログインが有効になっているので、パスワードミスって入れなくなった場合はrootでパスワードを変更するとよさげ)

公開鍵認証でログインできるようにする

とりあえずサーバーにパスワードログインのまま放置するのは気持ち悪いので公開鍵認証でログインできるようにしておきます。
鍵の生成や詳しいことに関しては割愛します。(長くなるので)

公開鍵の追記

ログインするユーザーのホームディレクトリに.sshディレクトリを作成してauthorized_keysを追加しておきます。

pi@NanoPi-R2S:~$ mkdir .ssh
pi@NanoPi-R2S:~$ vi .ssh/authorized_keys <- 自分の公開鍵を追記
pi@NanoPi-R2S:~$ sudo chmod 600 .ssh/authorized_keys 
pi@NanoPi-R2S:~$ sudo chmod 700 .ssh/ 

SSHの設定

SSHの設定を変更しておきます。

pi@NanoPi-R2S:~$ sudo vi /etc/ssh/sshd_config

とりあえず個人的に変えておきたい場所だけ記載しておきます。

Protocol 2
Port [22以外の任意のポート]
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
#X11Forwarding yes <- デフォルト値はnoなのでコメントアウト

上記を反映させるためにsshをリスタートします。

pi@NanoPi-R2S:~$ sudo /etc/init.d/ssh restart

とりあえず再起動しなければSSHは繋がりっぱなしになってると思うので、今のうちに別クライアントか別窓で鍵認証でSSHログインできるか確かめます。
もしできない場合は上記の設定をしていたウィンドウで設定画面を確かめて下さい。

LPCXpresso4337のCortex-M4/Cortex-M0マルチコアのサンプルプロジェクトをビルド+書き込みしてみる

お恥ずかしいことにLPC4337を使ったボードをよく開発しているにもかかわらず、マルチコア開発はしたことがありませんでした。
ただ最近になってマルチコアの需要がでてきた(とはいえ要求スペック的にはシングル処理でも間に合ってはいるんですが・・・)のでマルチコア開発の一歩としてサンプルプロジェクトをビルド+書き込みしてみます。

f:id:ysmn_deus:20200612183508j:plain

環境

前提としては

  • 使用するマイコンはLPC4337で、サンプルなのでボードはLPCXpresso4337を使用する
  • 上記につき、デバッガプローブはボード上にあるLPC-Link2相当のものをそのまま利用する
  • 開発IDEはMCUXpresso IDE v11.1.1

という感じです。
LPC-Link2を使ってもいいんですが、まぁ最初は軽い気持ちでやりたいので。

プロジェクトの作成

LPCOpenからインポート

NXP製のマイコンをいじるならいまだとLPCOpenを使って開発することが多いと思います。
ここでは郷に従ってLPCOpenからライブラリとサンプルプロジェクトをインポートします。

MCUXpressoのおそらく左下にある「Quickstart Panel」から「Import projetc(s) from file system...」を選択します。

f:id:ysmn_deus:20200612171407p:plain

出てくるウィンドウの「Project archive (zip)」から「Browse」でLPCOpenのzipファイルを選択します。

f:id:ysmn_deus:20200612171453p:plain

f:id:ysmn_deus:20200612171739p:plain

f:id:ysmn_deus:20200612171749p:plain

f:id:ysmn_deus:20200612171759p:plain

今回はマルチコアのLチカのみ利用するので、LPC43xxのチップ用のプロジェクト(lpc_chip_43xx(m0))とLPCXpressoボード情報のプロジェクト(lpc_board_nxp_lpcxpresso_4337(m0))とマルチコアのサンプルプロジェクト(multicore_mc_sa_blinky_m4(0app))の6プロジェクトをインポートします。

f:id:ysmn_deus:20200612172257p:plain

「Finish」を選択すればIDEに戻り、Project Explorerにプロジェクトが6つ増えていると思います。

f:id:ysmn_deus:20200612172411p:plain

プロジェクトの設定を調整する

チップとボードのプロジェクトには手直しが必要ありませんが、サンプルプロジェクトはそのままではビルドが通らないのでマルチコアの設定を行っていきます。
最初にCortex-M0側から設定します。

Cortex-M0側のプロジェクト(Slave)

メモリ設定

こちらから設定するのは、Cortex-M4のプロジェクトでこちらのビルド済みオブジェクトファイルを指定する必要があるためです。
まずはプロジェクト設定を開きます。

f:id:ysmn_deus:20200612172801p:plain

C/C++ Build」→「MCU settings」の箇所を修正します。
一見「Cortex-M0」などを選択されてるのでよさそうですが、メモリ設定が適応されていないようです。
設定をインポートするため、下の方にある「Import」でメモリ設定をインポートします。

f:id:ysmn_deus:20200612173025p:plain

インポートするファイルはデフォルトの設定でIDEをインストールしている場合は「C:\nxp\MCUXpressoIDE_11.1.1_3241\ide\Wizards\MemConfigs\NXP」にある「LPC43x7-M0_BankB.xml」を読み込みます。
(MCUXpressoIDE_11.1.1_3241の箇所はバージョン毎に違います。)
メモリの設定が写真の様に変わっていればたぶん大丈夫です。(Cortex-M0のプログラム領域はLPC43x7では0x1b000000からなのでよさそう)

f:id:ysmn_deus:20200612173401p:plain

「Apply」を選択して適応しておきます。

MCU Linkerの設定

あとはMCU Linkerの設定だけしておきます。
同じ様にプロジェクトの設定で「C/C++ Build」→「Settings」→「MCU Linker」→「Multicore」を参照します。

f:id:ysmn_deus:20200612173931p:plain

デフォルトでは「None」になっていると思いますが、「M0APP」にしておきます。
設定は以上なので「Apply and Close」で設定ウィンドウを閉じておきます。

以上の設定を行い、プロジェクトのビルドをしておきます。
プロジェクトを右クリックし、「Build Project」を選択します。

f:id:ysmn_deus:20200612174159p:plain

関連プロジェクトは勝手にビルドされると思います。
問題なければCortex-M0の方のプログラムのオブジェクトが「Debug」下に生成されているかと思います。

f:id:ysmn_deus:20200612174359p:plain

ここまで出来ればCortex-M0の方は終わりです。

Cortex-M4側のプロジェクト(Master)

基本的な動作としてはCortex-M4側のプログラムが起動し、Cortex-M0を起動するという流れなので、こちらのプロジェクトがメインになります。

メモリ設定

基本的にデフォルトの設定で問題ありません。
念のためCortex-M0に割り当てるFlashの領域が0x1b000000になってるかぐらいはチェックしましょう。
該当箇所は先ほどと同様にプロジェクトの設定を開いて「C/C++ Build」→「MCU settings」です。

f:id:ysmn_deus:20200612174705p:plain

MCU Linkerの設定

こちらも上記と同様に「C/C++ Build」→「Settings」→「MCU Linker」→「Multicore」を参照します。

f:id:ysmn_deus:20200612174856p:plain

先ほどとはちょっと表示が違います。
この「M0APP」にチェックを付け、残り二項目も設定します。

f:id:ysmn_deus:20200612175120p:plain

f:id:ysmn_deus:20200612175132p:plain

設定できたら「Apply and Close」で設定を適応させてウィンドウを閉じます。

Cortex-M4側のプロジェクトのビルド

プロジェクトのビルドはこちらから行います。
上記までの設定をしていれば、通常のビルドで問題無い筈です。プロジェクトを右クリックし、「Build Project」しましょう。
M0APP execute address differs from address provided in source imageと怒られる場合はCortex-M0側のメモリ設定ができていない可能性が高いです。

問題無くビルドができれば実際にデバッガを起動して書き込んでみます。
簡単な動作なのでGUI Flash Toolを使って書き込みだけするのでも良いと思います。

f:id:ysmn_deus:20200612175705p:plain

接続しているデバッガが出てくるので、該当するデバッガを選択してOKします。

f:id:ysmn_deus:20200612175916p:plain

とりあえずマルチコアデバッグもしたいのでJTAGがいいです。

f:id:ysmn_deus:20200612180045p:plain

以上でM4の方のデバッガが起動し、書き込みまで完了しています。
ここでM0のほうもマルチコアデバッグする場合は、デフォルトのデバッグ設定に一箇所設定を追加します。
Cortex-M0側のプロジェクトを右クリックして「Debug Configurations」を開きます。

f:id:ysmn_deus:20200612181713p:plain

開かれた時にはM4のデバッグ設定しかないと思いますので、「C/C++ (NXP Semiconductors) MCU Application」をダブルクリックします。

f:id:ysmn_deus:20200612182026p:plain

ダブルクリックするとプロジェクト名でデバッグ設定が新しく追加されます。

f:id:ysmn_deus:20200612182102p:plain

このままではデバッグできないので、「Search Project」から対象ファイルを選択します。

f:id:ysmn_deus:20200612182242p:plain

更に、「LinkServer Debugger」のタブで「LinkServer Options」の「Debug Cnnection」にある「Attach only」にチェックを付けておきます。

f:id:ysmn_deus:20200612182430p:plain

まず最初にCortex-M4側のデバッグを開始してから、デバッグを停止せずにCortex-M0のデバッグ(上記で設定したやつ)を開始します。
基本的にはメニューバーの虫ボタンをクリックすればデバッグできると思いますが、Cortex-M0側のデバッグの初回は表示されてないかもしれないので再度「Debug Condiguration」を開いてみてください。たぶん先ほど設定したものがありますので、そちらを選択して「Debug」すれば大丈夫だと思います。

Debugのウィンドウに2個スレッドが表示されていればマルチコアデバッグ出来てると思います。

f:id:ysmn_deus:20200612182935p:plain

リモートワーク蔓延る世の中になったので、改めてRedmineを導入してみる

f:id:ysmn_deus:20200503142752p:plain

学生の頃に団体でのタスクを管理するためにRedmineを導入していたのですが、正直活用しきれていなかったのとPassengerのエラーにおびえていたので今まで前向きにRedmineの活用を検討してきませんでした。
(正直作業も一人で完結することが多いので・・・)
しかし、昨今の情勢に有効活用できる対象の方々が増えてるんじゃないかと思い、防備録を兼ねて記事にしてみます。

そもそもRedmineとは?

もしかしたらRedmineを知らずに見て下さっている方の為にざっくりと説明しておきますと、Redmineとはブラウザ上で利用できるプロジェクト管理アプリケーションです。
具体的な説明などは公式サイトを一読して頂ければ有り難いです。

redmine.jp

デモなんかもあります

my.redmine.jp

どういう人におすすめ?

基本的に複数人で一つのプロジェクトを進める人は活用を検討するのが良さそうです。

一人での進捗管理にも使えるかもしれませんが、Redmine特有の癖というか運用に対して色々と学ばねばならない点がありますので、正直面倒だと思います。
(本記事では余り言及しない予定です)

導入

前提

基本的に

  • 複数人で使うので外部からアクセスできるサーバーにセットアップ
  • 小規模(2~10人程度?)のアクセスを想定

という想定でセットアップします。
小規模なので今回はAWSのLightsailを選定しました。
中規模や転送量が多い場合はさくらのVPSなどもいいかもしれませんが、外向けの転送量は1TBまでは込みで3.5ドル(初月は無料)なので試してみる分にはワンコイン以下で運用できると思います。

サーバーのセットアップ

LightsailにはBitnamiによるセットアップが可能となっています。
本来であればデータベースなどセットアップがいるんですが、この機能を利用することで基本的なセットアップに関しては何も考えなくてもよくなります。

※ ただし、2021年4月以降も含む長期運用まで考えている方はLightsailのBitnamiでセットアップされる環境がUbuntuの16.04なのでバックアップとリストアの方法も合わせて確認しておいた方が良いかもしれません。

Lightsailでインスタンスの作成

Lightsailのコンソールから「インスタンスの作成」からインスタンスの作成画面に映ります。

f:id:ysmn_deus:20200502183720p:plain

「設計図の選択」のところで「Redmine」を選択します。
ロケーションは日本の方を想定しているのでデフォルトの東京リージョンから変更してません。

f:id:ysmn_deus:20200502184215p:plain

初めてLightsailを利用する方はSSHキーペアが設定されていないと思いますので新規作成して下さい。

f:id:ysmn_deus:20200502184418p:plain

インスタンスプランは一番最小の3.5USDのプランを選択してます。
リソース名は分かりやすい名前を設定しておいて下さい。(よく分からない人はデフォルトの「Redmine-1」で問題無いかとおもいます。)

f:id:ysmn_deus:20200502184623p:plain

これで「インスタンスの作成」をすると、基本的なセットアップが全て完了します。
なんと便利な・・・

f:id:ysmn_deus:20200502185038p:plain

ホームに先ほど設定したリソース名のインスタンスが作成されていると思います。

IPの固定

今のままだとサーバーのIPが変わって鬱陶しいです。
IPを固定してドメインを割り当てる(割り当てなくても利用はできますが)場合にはIPを固定しておく必要があります。
LightsailでDNSゾーンを作成してドメインを割り当てる方法もありますが、今回DNSの設定は別途することとしてIPだけ固定します。

ホーム画面から作成したインスタンスの設定画面にいきます。

f:id:ysmn_deus:20200502190251p:plain

ネットワーキングのタブに移動します。

f:id:ysmn_deus:20200502190605p:plain

IPアドレス」と書いてある項目から「静的IPのアタッチ」を選択します。

f:id:ysmn_deus:20200502190905p:plain

他に静的IPのリソースが余っていない場合は「静的IPアドレスの作成」画面へ移動すると思います。
ロケーションはそのままで、インスタンスは先ほど設定したリソース名(ここでは「Redmine-1」)を選択して、「静的IPの指定」と書かれた項目のリソース名は分かりやすい名前を付けておきます。
画像では「StaticIp-1」となっていますが、「Redmine-1-StaticIp」などRedmine-1に利用している事を明示しておくのが良いと思います。

f:id:ysmn_deus:20200502191238p:plain

「作成」を選択すると静的IPが作成完了します。
とりあえずホームに戻り、先ほどと同様「Redmine-1」の設定画面の「ネットワーキング」を確認します。

f:id:ysmn_deus:20200502191521p:plain

画像のように「静的IPのデタッチ」が表示されていれば、IPの固定は完了しています。

IPへドメインを設定する

ドメインを何で運用しているかによりますが、基本的にDNSレコードにAレコードとして該当するIPを設定すると良いかと思います。
自分はRoute53を利用していますが、基本的になんでもいいとは思います。
(要望がありましたら記事化しますが、ここでは割愛します。)

基本的にHTTPSでの運用を考えてない人はココまでで問題ないかと思います。
(基本設定は公式サイトのドキュメントなどをご参照ください。)

redmine.jp

Redmineのセットアップ

管理者ユーザーでログイン

とりあえずHTTPS化したいのでその準備をします。
まずは管理ユーザでログインします。ドメインを指定した場合はそのドメインに、指定していない場合は http://[固定したIPアドレス]/ にアクセスして下さい。

f:id:ysmn_deus:20200503134438p:plain

たぶんこんな画面が表示されると思います。
右上の「ログイン」からログインします。
上記のようにBitnamiの機能でセットアップした場合は、ログインIDは「user」、パスワードはSSHでログインしたホームディレクトリにある"bitnami_application_password"というファイルに記載されているものを利用します。
Windows10であれば、コマンドプロンプトからSSHが使えますので、下記で取得可能です。
(キーペアはユーザーフォルダC:\Users\ユーザー名の直下の.sshというディレクトリに保存したとします。)

C:\Users\username> ssh bitnami@[設定したドメインor固定したIPアドレス] -i .\.ssh\[保存したキーペア].pem
$ cat bitnami_application_password

取得したパスワードでログインします。

f:id:ysmn_deus:20200503135614p:plain

ログインが完了すると、左上の項目に「管理」などが追加されています。
この「管理」を選択し、管理画面を表示します。

f:id:ysmn_deus:20200503135733p:plain

管理画面の「設定」を選択します。

f:id:ysmn_deus:20200503135944p:plain

この画面の「プロトコル」をHTTPからHTTPSにしておきます。

Bitnami HTTPS Configuration Toolを利用したHTTPS化

勿論この設定だけでHTTPS運用できるわけではないです。今回はLet's Encryptを活用したSSLを想定していますが、一応AWS Certificate ManagerとAmazon CloudFrontを利用した運用もできると思います。AWS信者の自分としては後者の方が安心安全な気がしますが、極力ミニマムに始めるという想定でLightsail上で完結する方法を採っています。

基本的なツールはなんと最初から入っており、一発で自動更新コマンドまで追加してくれます。
SSHでセットアップしたサーバーにログインしてコマンドを実行します。

sudo /opt/bitnami/bncert-tool

最初にドメイン名を聞かれるのでSSL化したいドメイン名を入力します。

Domain list []: redmine.hogefuga.com

次にwwwの扱いをどうするか(マルチドメインとして運用するのか否か)を聞かれるのでnでキャンセルしておきます。
(あんまりwww.redmine.hogefuga.comのような運用をしたい人はいないと思いますので)

The following domains were not included: www.hogefuga.com. Do you want to add them? [Y/n]: n

次にHTTPへのアクセスがあった場合にHTTPSにリダイレクトするか聞かれますので、yで許諾しておきます。

Enable HTTP to HTTPS redirection [Y/n]: y

次に設定のステップが表示され「これでええんか?」と聞かれますのでyで許諾しておきます。

Do you agree to these changes? [Y/n]: y

次に期限切れになりそうなときに通知が来るメールアドレスを登録しておきます。

E-mail address []: hoge@hogefuga.com

ここまで来たら基本の設定は完了です。最後に利用規約に同意するか否か聞かれるのでyで許諾します。

Do you agree to the Let's Encrypt Subscriber Agreement? [Y/n]: y

これでSSL化は完了です。
このツールは基本的に自動更新のコマンドも登録してくれています。一応確認する場合は、そのまま

crontab -e

とcronを確認するとコマンドが追加されていることが分かります。

オンラインでの外部とのやりとりが増えてきたので、GW中にチケット駆動など開発手法を学習しておきたいところです。
Redmineの運用に関してはド素人なので・・・(:3 」∠ )

3Dプリンタでマスクを作る「PITATT 3D print mask」を試してみた

普段はAirinum Urban Air Maskを利用しているのですが、正直フィルターが枯渇しそうです。
6月ぐらいに在庫復活する、と公式サイトに記載がありますがあやしいところ。
そこで、3Dプリンタで出力可能なマスク「PITATT 3D print mask」が公開されているという事で、これを試してみることに。

公式ウェブサイトからSTLファイル(インナーとアウターの2つのデータ)をダウンロードしてきて、スライサーで処理して出力するだけ!簡単!
と思っていましたが、アウターの出力がどうしてもサポート無しだと最後の方の積層で失敗するのでサポートありで出力しました。
(フィラメントは三菱ケミカルメディア Verbatimの白PLAを利用しました。今は白はないみたいです。)

f:id:ysmn_deus:20200418161431j:plain
実際に出力したマスク

このマスクは2個の部品に分かれており、インナーを外すことでフィルターを交換することができます。

f:id:ysmn_deus:20200418161609j:plain

フィルターはティッシュやガーゼを使って下さいとのこと。
この辺ならまだ手に入るのでありがたいです。

想像してたよりきっちり密着します。
相当試行錯誤したんではないでしょうか?頭が下がります。

医療従事者や専門職の方には不適だと思いますが、それ以外の方の応急対応としてはありだと思います。
コレを機に3Dプリンタを購入してみたいな~なんて思う人は、少なくとも150mm x 100mm x 100mm の造形エリアが確保できる3Dプリンタを購入する事をオススメします。
(最近は造形エリア広いのでだいたい大丈夫だと思いますが)

AWS Lambdaのローカル開発で環境変数を取り扱うとき(SAM テンプレート利用)

f:id:ysmn_deus:20190318182949p:plain

Lambdaで他サービスのAPIを度々利用したくなると思います。
(例えば、S3にアクセスしたり、DynamoDBからデータを取り出したり等)
ローカルでは権限を設定したIAMユーザーの認証情報を利用して実行し、運用時にはロールをLambdaに設定して走らせたいところです。
TypeScriptのwebpackでのコンパイル分岐の為にdotenvを利用しているので、そこに設定してもいいんですが、SAMのテンプレートに記述する方法もあるのでそちらをまとめておきます。

テンプレートを分ける

開発環境と運用環境などを分けたくなるので、テンプレートと環境変数ファイルを複数用意したいです。
なのでディレクトリ(もしくはファイル)で分けておきます。
具体的には

プロジェクトディレクト
├ sam/
│├ develop/ ←開発用ディレクト
││├ env.json
││└ template.yaml
│├ test/ ←自動テスト用ディレクト
││├ env.json
││└ template.yaml
│└ deploy/ ←運用版ディレクト
│ ├ env.json
│ └ template.yaml
├ built/ ←TypeScriptのコンパイル
├・・・

のようなイメージです。
(全てに環境変数が要るかは状況次第だとは思いますが)
これでとりあえず.gitignore**/env.jsonとでも追記しておけばリポジトリにヤバイ情報をアップロードしなくて済みそうです。

テンプレートの修正

ここで、SAMのテンプレートファイルを修正しておきます。
テンプレートのResources関数名PropertiesCodeUriは、テンプレートからみた相対パスなので、上記のディレクトリ構成を取っている場合は

~
    Properties:
      CodeUri: ../../built/
~

となります。

試しにローカル実行してみる

とりあえず色々動かしたのでローカルで実行してみます。
テンプレートを何個か使い分けるので、プロジェクトのルートディレクトリからテンプレートを明示して実行します。

sam local start-api -p 3001 -t sam/develop/template.yaml

今回はポート(3001)も明示しました。(よくReactで3000番は使ってるので)
とりあえず今は動けばOKです。

環境変数の定義

早速環境変数を設定していきます。
SAMでローカル実行する際に環境変数を使うには

  1. テンプレート上で変数を定義する
  2. 読み込むJSONを作成する

という手順が必要です。
コマンドですんなり入ってくれればいいんですが、テンプレート上で変数を定義するということをお忘れ無きよう。

テンプレート上で変数を定義する

テンプレートに変数の情報を書き込んでいきます。
環境変数の適応には2通りあり

  • Globalsに記述してResources全てで適応できる変数を定義する
  • Resourcesの関数毎に変数を定義する

のどちらかになります。
自分の記憶では、以前は両方を両立できたと思うんですが、現状どちらかを選べば片方の環境変数がうまく注入されないような気がします。
(例えば、Globalsに環境変数を定義すると、Resourcesの環境変数がうまく変更できない)
基本的には公式ドキュメントで例のある後者をオススメします。

Globalsに記述してResources全てで適応できる変数を定義する

テンプレートには下記の様に記載します。

~
Globals:
  Function:
    Runtime: nodejs10.x
    Timeout: 3
    Environment:
      Variables:
        GLOBAL_ENV: DUMMY
~

注入する環境変数JSONファイルは下記のように作成します。

{
  "Parameters": {
    "GLOBAL_ENV": "hoge"
  }
}

Resourcesの関数毎に変数を定義する

テンプレートには下記の様に記載します。

~
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ../../built/
      Handler: development.lambdaHandler
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get
      Environment:
        Variables:
          FUNC_ENV: DUMMY
~

注入する環境変数JSONファイルは下記のように作成します。

{
  "HelloWorldFunction": {
    "FUNC_ENV": "fuga"
  }
}

環境変数を注入して実行

上記の2通りどちらでも実行方法は同じです。

sam local start-api -p 3001 -t sam/develop/template.yaml -n sam/develop/env.json

上記のコマンドをpackage.jsonに書いておけば、簡単にテストできます。
自分はnpm-run-allを利用してSAMのローカルサーバーとwebpackのwatchを走らせてますのでpackage.jsonscripts

~
  "scripts": {
    "dev:localhost": "sam local start-api -p 3001 -t sam/develop/template.yaml -n sam/develop/env.json",
    "dev:watch": "webpack --watch",
    "dev": "run-p dev:*",
~

としておけば、yarn dev でSAMとwebpackが走ります。

AWS LambdaをTypeScriptで開発する

f:id:ysmn_deus:20190318182949p:plain

JavaScriptはオワコン!とまでは言いたくないんですが、やはり普段からTypeScriptを利用していると極力JavaScriptは避けたいところ。
ということで基本JavaScriptで開発されているであろうAWS LambdaのNode環境ですが、TypeScriptで開発を始めるまでをまとめておきます。
Serverless Frameworkを使えば比較的容易にTypeScript環境を構築できるようですが、またそれは別途試してみます。
今回はSAM CLIで対応します。
(デプロイはJavaScriptと変わらないので割愛します)

SAM開発環境を整える

SAM CLIのインストール

まずはSAM CLIをインストールする必要があります。
Dockerのインストールも必要になってきますが、基本的には公式ドキュメント(Installing the AWS SAM CLI)に一通り書いてあるのでそちらを参照して下さい。

最終的に

sam --version

がきちんと動作すれば問題ないと思います。

(補足)IAMユーザー情報の登録

AWS CLIを普段利用していない方などはIAMユーザーの認証情報をPCにセットアップする必要があります。
AWSを利用していてLambdaだけしか使わない人も珍しいと思いますので、詳細は割愛しますが公式ドキュメント(Setting Up AWS Credentials)AWS CLIを利用しない認証情報のセットアップも掲載されておりますのでご参照ください。
個人的にはAWS CLIをセットアップすることをオススメしますが。

SAM CLIでプロジェクトを作成する

SAMでプロジェクトを作成します。
とりあえずはHello World的なものを生成する所まではJavaScriptで対応します。

sam init --runtime nodejs10.x --name hello-sam

上記コマンドのオプションをとりあえず説明しておきますと、
--runtime:Lambdaの実行ランタイムを選択します。(python3.7とか)ホントはv12を使っていきたいんですが、一応安牌をとってv10で進めて行きます。
--name:プロジェクトのディレクトリ名です。Lambdaの関数名などは別途修正する必要があります。

上記コマンドを実行すると対話形式でウィザードが進みます。
とりあえず今回は1, 1をチョイスしました。

Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git

AWS quick start application templates:
        1 - Hello World Example
        2 - Quick Start: From Scratch
        3 - Quick Start: Scheduled Events
        4 - Quick Start: S3
        5 - Quick Start: SNS
        6 - Quick Start: SQS
        7 - Quick Start: Web Backend
Template selection: 1

-----------------------
Generating application:
-----------------------
Name: hello-sam
Runtime: nodejs10.x
Dependency Manager: npm
Application Template: hello-world
Output Directory: .

Next steps can be found in the README file at ./hello-sam/README.md

S3などの処理を書きたいときはその辺を選んだりするのが良いんでしょう。
とりあえず今回は無難なチョイスを選択しましたが、ウィザードが完了すると--nameで指定したディレクトリにファイルが出力されていると思います。

テストを実行する

SAM CLIでセットアップすると、mocha+chaiがセットアップできるようになっています。とりあえず走らせる為にpackage.jsonの情報でセットアップします。

cd .\hello-sam\
cd .\hello-world\
yarn

ドキュメントではnpmコマンドを利用している例が多いですが普段はyarnを利用しているのでそのまま使います。
基本問題無いのでそのままテストを走らせます。

yarn test

yarn run v1.22.0
$ mocha tests/unit/


  Tests index
    √ verifies successful response


  1 passing (7ms)

Done in 0.34s.

問題無さそうです。

ローカルで関数を実行する

SAMを利用すればローカルで関数を実行するのは非常に簡単です。
一応sam local invokeで関数を実行する方法と、sam local start-apiで実行する2種類の方法がありますが、大体後者かと思いますので後者で動かしてみます。
(Dockerが起動してないと怒られますので起動しておきましょう)

cd ..
sam local start-api

問題が無ければブラウザでhttp://127.0.0.1:3000/helloを入力するか、curlコマンドでGETリクエストを投げると{"message":"hello world"}が返ってきます。
基本的にJavaScriptのファイル群はここで不要となりますので、hello-worldディレクトリはこの段階で削除してしまって構いません。

ちなみに、Dockerをセットアップしただけの状態だとC:\Users以下以外のディレクトリは権限がなくてマウントされないので、プロジェクトのディレクトリがC:\Users以下でない場合はsam local Error: Cannot find module 'app' docker toolboxのようなエラーが発生します。
対処法としましてはDokcer Toolboxでは下記のサイトを参考にさせていただきました。

coffee-nominagara.com

ToolboxでないDokcerでは警告が出てきちんと設定していた気がします。

TypeScript

tsconfig.jsonの作成

まずはプロジェクトのルートディレクトリにtsconfig.jsonを作っておきます。
特にこだわりのない人は

tsc --init

tsconfig.jsonを作成するのが良いと思います。
一応今回用意しているtsconfig.jsonは下記の通りにしました。

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6",
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "outDir": "./built",
    "allowJs": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "esModuleInterop": true
  },
  "include": [
    "./src/**/*"
  ],
    "exclude": ["node_modules"]
}

入力対象を./src/以下、出力先を./builtにしています。

パッケージを追加

TypeScriptを使っているので型が必要です。開発用の型をまずは追加していきます。

yarn add -D @types/aws-lambda

最小限のパッケージはこれだけでOKです。

index.tsを編集

index.tsを編集します。基本的にはデフォルトのapp.jsを踏襲して作成してみます。

import {APIGatewayEvent, Context} from "aws-lambda"

const lambdaHandler = async (event: APIGatewayEvent, context: Context) => {
    let response: any
    try {
        response = {
            'statusCode': 200,
            'body': JSON.stringify({
                message: 'hello ts world',
            })
        }
    } catch (err) {
        console.log(err)
        return err
    }

    return response
}

export {lambdaHandler}

とりあえずという意味ではeventcontextanyで受けてしまえばいいんですが、まぁそんぐらいは・・・
これでコンパイルしてみます。tsconfig.jsonを設定してるのでルートディレクトリでtscコマンドを実行します。

tsc

これでbuiltディレクトリが作成され、index.jsが生成されたかと思います。

template.yamlの修正

JavaScriptの時との差異はコンパイル後のファイル名ファイルの場所です。
これをtemplate.yamlに修正していきます。

~
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: built/
      Handler: index.lambdaHandler
~

CodeUriHandlerを修正しました。

ローカルで関数を実行する

これでローカル関数を実行してみます。

sam local start-api

JavaScriptの時と同様にブラウザかcurlコマンドで確認してみて下さい。
返ってくるのが{"message":"hello world"}のままの人はもしかするとsam buildして.aws-samディレクトリに履歴が残ってる可能性がありますので消しちゃって下さい。
無事{"message":"hello ts world"}が返ってきたら最低限度の環境構築はできたのではないでしょうか。

その他

ESLint + Prettier

基本的にはReactの設定と同じなのですが、ReactのJSXなどは不要です。
一応eslintrcなどを掲載しておきます。

パッケージの追加

yarn add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
yarn add -D prettier @types/prettier @types/eslint-plugin-prettier eslint-config-prettier eslint-plugin-prettier

eslintrc.js

module.exports = {
  env: {
    browser: true,
    node: true,
    es6: true
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    sourceType: "module"
  },
  plugins: [
    'prettier',
    '@typescript-eslint'
  ],
  extends: [
    "eslint:recommended",
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
    'prettier/@typescript-eslint'
  ],
  rules: {
    'prettier/prettier': [
      'error',
      {
        'semi': false,
        'trailingComma': "all"
      }
    ]
  },
};

.eslintignore

node_modules/
*.config.js
built/

webpack

今回はwebpack+ts-loaderで構成します。

パッケージの追加

yarn add -D ts-loader webpack webpack-cli dotenv

今回は.env環境変数を管理する想定でdotenvを利用しています。
直で書いたりする場合はこの辺は必要無いと思います。
とりあえず.envを作っておきます。

NODE_ENV=development

webpack.config.js

const path = require("path")
const dotenv = require("dotenv")
dotenv.config()

const BUILT_PATH = path.resolve(__dirname, "./built")
const BUILD_VARIANT = process.env.NODE_ENV

module.exports = {
  target: "node",
  mode: BUILD_VARIANT === "production" ? "production" : "development",
  resolve: {
    extensions: [".ts", ".js"],
  },
  entry: "./src/index.ts",
  output: {
    filename: `${BUILD_VARIANT}.js`,
    path: BUILT_PATH,
    library: "[name]",
    libraryTarget: "commonjs2",
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: "ts-loader",
      },
    ],
  },
}

これで、ファイルを分割して開発することができます。