2019年9月12日木曜日

RFC 7230 HTTPのABNF拡張を考えている

最近ABNF界隈のテストでRFCに書かれているABNFをいろいろ実装してみているのですが、ABNFを拡張したものがいくつかあり、RFC 7230 HTTPでは *の他に#というのが追加されていて、ABNFをわかっていないのか、なぜか中途半端なところまでしか書かれていない。
というわけでどうやって実装しようか悩んでみて拡張を投入してみた。

RFC 2373 IPv6
RFC 2396 URI
RFC 3986 URI
RFC 3987 IRI
RFC 6874
RFC 7230 HTTP
RFC 8259 JSON

このあたりのABNFを実装したりしなかったりしてGitHubへ投下してみたり。

NFCからIFTTTのIoTへ繋げるヒント

Google Homeなどで家電の操作ができ、ほとんどリモコンは必要なくなってきていたりしますが、素早く操作したいこともあるのでAndroidで操作画面を開いてアプリを開いてボタンを押す、みたいな長々とした操作をなんとかしたいところ。
というわけで、イベント駆動にNFCタグを使ってIFTTTをつつく方法を探してみたりしていました。IFTTTから先は連携できる機器が沢山あるので省略。
AndroidのIFTTTでもトリガーにNFCタグを読み取るという機能はないので、 NFCタグ側でなんとかしてみたいところです。
部屋の前で電気をつけたり、音楽を再生したり、音声操作が苦手でもNFCタグにタッチでできるようになったりならなかったり。

NFCタグ→URL→IFTTT


NFCに埋め込めるのは、アプリ固有の情報、URLなどいくつかあります。NFCからIFTTTに連携できそうなアプリはないようです。IFTTT側ではURLをトリガーにすることができるようなのでNFCタグにURLを埋め込み、タッチしてAndroidのブラウザで開くとIFTTTが動くという方向で考えてみます。
前提条件(制限事項)
  • FelicaではないのでAndroid画面が使える状態でしかNFCタグには反応しません。たぶん。
  • 数回操作があります。
  • ブラウザで開くので閉じるのが面倒です。

IFTTTのWebhooks

IFTTTをURLからつつくには、Webhooksというのがあるようです。IFTTTの画面が迷路のようなのでどこに何があるのかさっぱり…。

Appletにする

PCだと、IFTTTサイトのCreate でAppletを作ることができます。
If +This then That
  • ThisでWebhooksを探します。基本設定があるかもしれません。(Step 1 of 6)
  • ひとつしかないので Receive a web request を選び、英数で?イベント名を入力します。(Step 2 of 6)
  • Thatで操作対象サービスを選びます (Step 3 of 6)
  • 操作を選びます。(Step 4 of 6)
  • ボタンなどを選択します (Step 5 of 6)
  • できあがった機能に名前をつけて確認してFinish (Step 6 of 6)
追加したWebHooksの基本設定はMy services で確認することができます。
AppletはMy Applets で機能の有効/無効のON/OFFができます。

使う


Webhooksを追加できたらURLを使えるようにします。タグの機能にあわせててきとーに名前っぽいものをつけてON用とかOFF用とか用意します。
Applet? でIoT機器などと連携すればとりあえず完成。

NFCタグを作る

IFTTTで用意したURLをNFCタグに書き込みます。
標準的なURLを埋め込んだNFCタグを作ります。URLは共通仕様なので、書き込みアプリはどれでもいいです。サンワサプライのタグとアプリで書き込んでみました。
URLはIFTTTのMy servicesからWebHooksを選び、右上のDocumentationで書き方を確認できます。個人用のものは公開しないよう注意しましょう。
NFCのデータサイズはURLが入る程度なので小さいものでも問題なく書き込めました。

Androidでタッチ

URLを開きますか? と問われてブラウザが開きます。IFTTTが反応したらとりあえず成功です。あまりさくっと使えるものではないですが、使える場所にNFCタグを張っておくとリモコンがないときに便利かもしれません。

置き換えてみる

NFCタグの他に、QRコードでもURLを開くことはできますね。WindowsやAndroidのショートカットやブラウザのブックマークでもいいのですが、IFTTTのURLがつつければ、何でもできます。

2019年8月19日月曜日

Raspberry PiのTomcat 9にLet's Encryptを

Raspberry Piといえども最近はTLSが必要らしいので早々にTLS化する必要があります。
Let's Encryptを使用してみました。

# apt-get install python-certbot-apache
というのでいろいろインストールされた。
いろいろつついてしまった中で、最初はメールアドレスやライセンスの質問があった気がします。
とりあえず全部rootで実行してしまいましたがtomcatかなにかで使えるのかな?

何度か試してみた後…
# certbot certonly -d siisise.net
How would you like to authenticate with the ACME CA?
(認証方法どないする?)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Apache Web Server plugin (apache)
(Apacheのプラグイン使う)
2: Spin up a temporary webserver (standalone)
(仮の独立Webサーバ立ててサインアップする)
3: Place files in webroot directory (webroot)
(webのrootディレクトリにファイル置いて認証する)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3つの選択肢、サーバを止められるなら2、止められないなら3かな
とりあえず2と3で試してみた。ワイルドカード証明書はこれとは別でDNSを使うと取れるらしいです。

2の場合はポート80を使っているサーバを止めてから実行するだけ。
# service tomcat9 stop を先に実行しておく
仮のサーバが起動し、ドメイン接続確認後、 /etc/letsencrypt/live/siisise.net/ に各種ファイルを作ってくれました。developer.jpも同じように作成。

3の場合は
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for siisise.net
Input the webroot for siisise.net: (Enter 'c' to cancel):
webrootどこにある? と聞かれます。Tomcatの場合は webapps/ROOT/ のことです。
/var/lib/tomcat9/webapps/ROOT/ (マルチドメインにしていない場合)などフルパスで指定すると勝手にファイルを作って勝手に認証され、勝手にファイルを消すか何かで終わってくれます。

証明書とチェーン証明書は
/etc/letsencrypt/live/siisise.net/fullchain.pem
キーファイル(秘密鍵)は
/etc/letsencrypt/live/siisise.net/privkey.pem
2019年11月16日(3カ月くらい)で証明書は切れるよと。
新しい証明書とりたいときはcertbotを走らせるべし。
手動で全証明書更新するなら"certbot renew"を実行するべし。みたいな説明が出て完了。

最近の? Tomcat 9はJKSでもPKCS#11?でもPKCS#12でも使えますが、今回はApacheと同じcertbotが吐き出したPKCS#11かなにか(鍵と証明書が別ファイル)の形式のまま。PKCS12にまとめたりJKSに変換したりはしていないのでお手軽です。ディレクトリと/etc/letsencrypt/archive/ドメイン/privkey.pemのアクセス権をtomcatで利用可能なように調整。
# chgrp tomcat /etc/letsencrypt/archive
他いろいろ
tomcatのconfからシンボリックリンクを張り。使うのは証明書(cert.pemとchain.pem
 かfullchain.pem)と秘密鍵(privkey.pem)

# ln -s /etc/letsencrypt/live/siisise.net/fullchain.pem /etc/tomcat9/siisisenet-rsa-fullchain.pem
# ln -s /etc/letsencrypt/live/siisise.net/privkey.pem /etc/tomcat9/siisisenet-rsa-key.pem

Tomcatの /etc/tomcat9/server.xml を修正、起動。

HTTP/2の使えるport 8443の設定コメントを使ってport 443を設定してみた。(例によって<>括弧は全角)
< Connector port="443" protocol="org.apache.coyote.http11.Http11AprProtocol" maxThreads="150" SSLEnable="true" >
 <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol">
 <SSLHostConfig>
  <Certificate
 certificateKeyFile="conf/siisisenet-rsa-key.pem"
 certificateFile="conf/siisisenet-rsa-fullchain.pem"
 type="RSA" />
 </SSLHostConfig>
 <SSLHostConfig hostName="developer.jp">
  <Certificate
 certificateKeyFile="conf/developerjp-rsa-key.pem"
 certificateFile="conf/developerjp-rsa-fullchain.pem"
 type="RSA" />
 </SSLHostConfig></Connector>

とこんなかんじでマルチドメインでも使えます。SSLHostConfig デフォルト以外はhostNameを付けています。
certificateFileをfullchain.pem  にするとcertificateChainFileは要らないので省略しています。(Apache httpd 2.4.8以上と同じ、らしい)
# service tomcat9 restart かなにかで再起動。
使えないときは /var/log/tomcat9/catalina.2019-08-19.log などでエラーが出ていないかチェックします。
https://siisise.net/ や https://developer.jp/ にアクセスできることを確認。その他ドメインでもアクセスできますがドメインが違うと警告がでます。

Tomcatでサーバ運用は危険といわれていたこともありましたが、今は何が危険なのか。
自動更新までは試していないので、それはまたそのときかな。このまま更新を自動化してもアクセス権が死ぬかもしれない。秘密鍵は更新されない? さてどうでしょう。

2019年8月9日金曜日

Raspberry PiでTomcat 9とPostgreSQLをぐりぐりする

Raspberry Pi Zero WでJava SE 8が使えるようになったところでApache TomcatやPostgreSQLを使いたいのです。アクセス負荷に耐えられるようmicroSDカードは大容量や高耐久のものにしてみたのでした。

Tomcatは9だった

tomcatはパッケージを入れても動くのですが、常時動いてほしいのでaptで取ってくるとどうなるのかというお試し。最新のTomcat 9はJDK 8でも動きます。

# apt-get install tomcat9
で、だいたい入ります。tomcat9-admin も入れてみるといいのでしょうか。
他のパッケージはtomcat9-docs, tomcat9-examples, tomcat9-users とあるようです。
/usr/share/tomcat9 がCATALINA_HOME、/var/lib/tomcat9 がCATALINA_BASE となり、tomcatグループとユーザも作られ、サーバもtomcat権限で動いています。アプリ系のアカウントは基本rootやsudoで作業すればいいのでパスワードを設定してはいけません。
CATALINA_HOMEは基本的に触れません。CATALINA_BASEのconf内をいろいろカスタマイズすることで、いろいろと動いてくれます。/etc/tomcat9 にリンクされています。
初期ポートは8080なので、conf/server.xml でport 80にしたり、複数仮想サーバを作ったりできます。
サービス開始/停止は
# service tomcat9 start
# service tomcat9 stop
でできるようです。どこに設定があるのかよくわからない。 RedHat系で/etc/rc.d/init.d/ にあるようなものは /etc/default/ にあるのかな。
Webはオートデプロイにして、webapps相当のグループをtomcatにして書き込みもできるようにしておくと、管理も楽かもしれませぬ。

PostgreSQLはもう11か

Raspberry Pi Zero WとWH、ふたつあるのでTomcatとは別の方にPostgreSQL入れます。
# apt-get install postgresql だったかもう忘れた。
 rootではpsqlコマンドが使えなくなっているのでpostgresユーザでpsqlコマンドをたたきます。
# su - postgres
$ psql --version
psql (PostgreSQL) 11.4 (Raspbian 11.4-1)
これはrootでもできます。
$ psql
postgres=# \l
 でデータベースの一覧がでてきます。qで終わり? 基本的にいろいろ省略するとユーザ名と同じpostgresというPostgreSQLのユーザで同名のデータベースに繋がっています。
psqlから抜けるのは
postgres=# \q
です。\hでヘルプが出るかもしれません。
外部からのアクセスを許可するには、
/var/lib/postgresql/11/main/ がデータの位置、/etc/postgresql/11/main/ が設定ファイルの位置、らしいです。pg_hba.confで特定IPアドレスからのアクセスを許可します。アカウントも作っておきましょう。postgresql.confの設定も変える必要があるかもしれません。
雑に終了。

公開の際にはIPv4でフィルタリングしていてもIPv6で丸見えになることが予想されるので注意しましょう。

2019年8月7日水曜日

RazpberryPi Zero WでJavaを使おう

というわけでRaspberryPiどころか家でPCにも触ってなかったのですが最近Ryzen 5 2600XなPCを組んでからプログラミングやらいろいろ再開中で、RaspberryPiでWebサーバでもと思ったら2Bが行方不明なのでZero Wを買って挑戦してみることに。
いろいろ罠にはまります。
  • RaspberryPi Zero WとWHをスイッチサイエンスで1つずつ購入
  • microSDXCカード 128GBを2枚購入していた(危険 class 10、UHS-Ⅰ Speed Class 1、A1対応)
  • microSDHC 8~32GBが推奨
  • USBキーボードがなかった(Logiのワイヤレスドングルので可。SANWAのキーボードもあった)
  • てきとーなmicroUSBで繋がる電源
  • PuTTYとWinSCPでリモート接続

本体の選択

まずは本体の選択、初心者はできれば3B+かな。Zeroは2台目以降でもいいのかもしれない。
フルサイズUSB端子がある、有線LANがある、無線LANもある、HDMIがフルサイズ、などの理由です。変換ケーブル類も高いので予備がないなら3B+です。
Zero Wは、シングルコアARMv6、microUSB OTGがある、有線LANがない、無線LANがある、HDMIがminiサイズ、といろいろと不便です。Zeroになると無線LANまでないので別途用意しないといけません。
Javaを動かしたいならARMv7以降のCPUのものを選ぼう。NOOBSにはARMv7対応のJava11くらいが入っていた。Zero WはARMv6です。あとで対応したJavaを探します。

メモリーカード、OSの選択

メモリーカードの設定から入ります。microSDHC、microSDXCが使えますが、推奨は8GB以上のようです。microSDXCはフォーマットがFAT32ではないという理由で初心者にはおすすめしません。というわけで、初心者向けの容量は8GBから32GBの間で選びます。挑戦したい人はmicroSDXCも今は512GBくらいまであるので選び放題です。
速度など容量以外の選択基準では、class10、UHS不要、A1かA2対応のスマホ用に最適化されているようなものや、書き換えに高耐久なもの、がおすすめです。PCで最初に書き込むのが速い方がいいという理由でUHSスピードクラスの速いものを選んでも全然かまいません。

次にOS(インストーラ)ですが、NOOBSにしてみます。ファイルをコピーするだけで簡単です。OSは、Raspbianなども選択できます。

書き込んでみる(microSDXCで難儀)

64GB以上のmicroSDXCは特殊事情により標準のフォーマットがexFATです。RaspberryPiではこれをFAT32にする必要があります。
http://www.ridgecrop.demon.co.uk/index.htm?guiformat.htm
RasPiサイトでおすすめのフォーマッタはこれなのでこれでFAT32にフォーマットしてみました。
次にNOOBSのファイルをダウンロード、解凍して入れるだけ。Torrentも利用できるようです。とりあえずインストーラは完成。

繋ぐ+トラブル

RaspberryPi Zero WにmicroSDXCカード、miniHDMI、microUSB電源、キーボードを繋ぎ起動、インストーラ選択画面まで表示、操作できません。
原因は電源不足電源とデータの接続が逆。USBとPWRの刻印があるので注意しましょ。電源が外側の端子のようです。また、データ側のUSBを抜き差ししても再起動してしまうことがよくあるのでインストール用にUSB HUBなどをあらかじめ繋いでおきます。
無線LANを設定、OSを選んでインストールでなんとか進みます。インストーラの言語を日本語にしたりもできます。

OS入れた

インストールが進むと再起動、何かのOSがGUIで起動しました。このあとWi-Fi(選択するだけ、パスワードは設定済み?)など少し設定を進めます。言語のダウンロードなどがなぜか失敗。とりあえず完了のようなのでsshで繋ぐのとCUIで起動するくらいに少し設定を触ってみたりで再起動。
# java うごかない openjdk-11-jdkが入っていてARMv7以降に対応していました。RaspberryPi Zero WはARMv6のようですよ。なぜ。

設定が終わればキーボードマウスは使わないのではずしてしまっても安全です。
というわけで、いろいろ設定できるものを探してみるところからまたはじめようかと思います。
Bluetoothが繋がるタイミングも調べてみないとわかりませんね。

Javaを探す

Raspberry Pi Zero Wではopenjdk11が入っていても動かないのでバージョンを下げる対策が必要なようです。

# java -version
Error occurred during initialization of VM
Server VM is only supported on ARMv7+ VFP
javaコマンドを叩いてみるも、JDKが動きません。 server VMがARMv7用だとか。
何が入っているのか探してみます。
# which java
コマンドの位置を調べるコマンド which
 /usr/bin/java
# dpkg -S /usr/bin/java
ファイルのパッケージを調べるコマンド dpkg
反応がない…リンクされているのでその先をたどります。
# ls -l /usr/bin/java
最終的にたどりついたのは /usr/lib/jvm/java-11-openjdk-armhf/bin/java のようです
# dpkg -S /usr/lib/jvm/java-11-openjdk-armhf/bin/java
openjdk-11-jre-headless というパッケージに当たったので消し去ります。
openjdk-10-jre-headlessやopenjdk-9-jre-headlessも入っていたら消します。
# apt-get remove openjdk-11-jre-headless
openjdkとopenjreが消えてくれます。
# apt-get install openjdk-8-jdk
openjdk 8をインストール
# java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (build 1.8.0_212-8u212-b01-1+rpi1-b01)
OpenJDK Client VM (build 25.212-b01, mixed mode)
動いてくれました。

ここまでくれば、あとはてきとーに楽しめます。

2019年7月21日日曜日

Ryzen 5 2600XでAndroid Studio のx86エミュレータを使えないWindows May 2019 Update

WindowsのAndroid StudioではAndroidのエミュレータが使えるのですが、x86版のエミュレータにはIntelのVT-xかAMDのSVMをUEFI(BIOS)上で有効にする必要があります。
今回はAMD Ryzen 5 2600xなので初回セットアップでVT-xつかえないよといわれ、UEFI上でSVMを有効にしてみました。OSのバグかなにかで失敗したのですが、いろいろ調べた挙げ句のメモです。
AndroidエミュレータがAMD CPUとHyper-V に対応した、というニュースのAMD CPUとHyper-Vは別々の話なので混ぜるな注意です。Hyper-VはAMD CPUにたいおうしていないっぽいたぶん。

Android Studioでエミュレータを動かす条件 3種類
  • Intel VT-x
  • AMD SVM
  • Microsoft Hyper-V
どれかが必要、ということらしいので今回はAMD SVMを有効にする方法

今回の前提

AMD Ryzen CPU
Windows 10 Pro April 2018 Update 以降 (Homeでも可?)
Windows 10 バージョン 1903 (OS ビルド 18362.239) (失敗するバージョン)
Android Studio 3.4.2 (3.2 Beta以降)
Avastかなにかのソフト使ってないこと

状態の確認

Windowsのバージョンを確認します。
スタートメニューを右クリックで「システム(Y)」を開き、Windowsの仕様というところにバージョンとOSビルドがあります。
コマンドプロンプトでwinver と入力してもバージョンが確認できます。
バージョン1903 (OS ビルド 18362.239) と出てくればバグ持ちなのでエミュレータは動きません。(注 : 7月末のKB4505903のアップデートでOS ビルド 18362.267になり修正されました)
エミュレータが実行可能なのは現状では1803と1809です。
Windows Insider Programで18932を使用するとエミュレータが利用可能という情報もありますが、元には戻せません。

AMD RyzenでAndroid x86エミュレータの利用可能状況(1803以降対応)
○ バージョン 1803 April 2018 Update
○ バージョン 1809 October 2018 Update
× バージョン 1903 May 2019 Update (OSビルド 18362.239)
○ バージョン 1903 May 2019 Update + KB4505903 (OSビルド 18362.267)
○ ビルド 18932

コマンドプロンプトで systeminfo
最初にOSのバージョンなど、最後にHyper-Vの要件が4つ出てきます。

systeminfoのHyper-Vの項目で、ファームウェアで仮想化が有効になっています : いいえ
となっていれば、UEFIの設定を変更します。
4つとも有効になっていればWindowsでハイパーバイザーを有効にします。
ハイパーバイザーが検出されました。と出てくればWindowsの設定も済んでいるのでAndroid Studioの方へ

UEFIの設定

仮想化技術はふつう使わないのでUEFIの初期設定でも無効化されていることが多いようです。
今回はASUSのTUF X470-PLUS GAMINGというマザーボードです。
Windowsを再起動させ、起動する前にdelete(DEL)キーでUEFIに入ります。キーボードもマウスも使えます。メニューを日本語にすることもできます。
UEFIの詳細設定の方を開き、CPUのSVMという項目をなんとなく見つけてEnabled にします。他の項目は触らなくてもいいですがてきとーに設定して保存して再起動します。

Windowsの設定

Windows 10では設定のメニューがコンパクトになってしまったのですたーとメニューから[Windows システムツール]→ [コントロールパネル]と開きます。[コントロールパネル > すべてのコントロールパネル項目] と開いていればOK。
[プログラムと機能]を開き、左の[Windowsの機能の有効化と無効化]までたどりつきます。
関連する項目は2つ
 [Hyper-V]のチェックをはずします。もともとはずれているはずです。
 [Windows ハイパーバイザー プラットフォーム]をチェックします。
Windowsの再起動をします。
systeminfo でHyper-Vの要件にハイパーバイザーが検出されました。と表示されていればWindowsまでの準備は終了のはずです。

Android Studo

ToolsからSDK ManagerとAVD Manager を開き、環境を整えます。

SDK Manager


[SDK Tools]の Intel x86 Emulator Accelerator (HAXM installer) はAMD Ryzenには不要なので入れてしまったら削除します。
Android Emulator、Android SDK Platform-Tools、Android SDK Toolsなどが入っていれば大丈夫なのかもしれません。

AVD Manager

VT-xが有効ではありません、などのエラーメッセージがでたら、Windowsハイパーバイザーの設定までがうまくいっていないので、もう一度UEFI、Windowsの設定を見直してください。
ここまでで起動しない…。
Windows バージョン1903 (May 2019 Update)はバグ持ちのようなので、次のアップデートまで待つしかないようです。(7月末 Updateで修正済み)

Hyper-Vだとどうなる 

Android エミュレータはHyper-Vにも対応しています。試してみましょうか。Hyper-V側をチェックし、ハイパーバイザーをはずして再起動します。Android StuidoではVT-xか何かがないよというメッセージが表示されるだけで使えませんでした。

参考
 窓の杜 https://forest.watch.impress.co.jp/docs/news/1132197.html
 Android StudioとAMD製CPU https://blog.misatowater.com/entry/tech/amd-androidstudio

2019年7月15日月曜日

MavenでTomcatにJAX-RSのせるだけ

TomcatにはJava EE 改め Jakarta EEのWeb系の機能しか載っていないので、その他のサービスを利用するにはwarの中に封じ込めてあげるのが楽です。
とりあえずJDK 12 + Apache NetBeans IDE 11.0の場合
Mavenで構築、Tomcatに公開する場合です。
GlassFishのJAX-RSライブラリを使います。

MavenでWebつくる
JAX-RS の機能でRESTfulなものを作る

Servlet相当のクラスをひとつ作り、タグだけつけます。Applicationというクラスを継承するようです。@ApplicationPath で公開パスを決めます。

package net.siisise.example.rest;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/api")
public class RestSetup extends Application {
}

次に機能のclassを作ります。
@の機能は推測どおりかと思うので GET /api/menu/hello に公開されます。

package net.siisise.example.rest;

@Path("/menu")
public class Mmmmm {
    @Path("/hello")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String exHelloName() {
        return "おはよう";
    }
}

そのまま公開してもTomcatではライブラリ等不足しています。

web.xml の編集。GlassFishサーバの設定をしていると、<dependencies> にjavaee-web-api があるかもしれません。
(Bloggerの都合上XMLタグは全角で囲んでいます。)

<dependencies>
   <dependency>
       <groupid>javax</groupid>
       <artifactid>javaee-web-api</artifactid>
       <version>7.0</version>
       <scope>provided</scope>
   </dependency>
</dependencies>
これはコメントアウトします。

<dependencies>

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.29</version>
    </dependency>
    <dependency>
       <groupId>org.glassfish.jersey.inject</groupId>
       <artifactId>jersey-hk2</artifactId>
       <version>2.29</version>
    </dependency>
</dependencies>
とりあえずこのふたつがあれば動くようです。Servletを手動で設定する必要はありませんでした。
ビルドしてデプロイすれば /api/menu/hello で動いてくれます。
JAX-RS のMavenパッケージは jakarta.ws.rs-api というのに変わっていくっぽいです。

Web Application Description Language (WADL)

それから JAX-WS の SOAPにWSDL があるように、JAX-RSなRESTにはWADL というのがあるようで、これにはJAXBのライブラリも必要らしい。
仕様 https://www.w3.org/Submission/wadl/
<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.4.0-b180830.0359</version>
</dependency>
<dependency>
  <groupId>org.glassfish.jaxb</groupId>
  <artifactId>jaxb-runtime</artifactId>
  <version>2.4.0-b180830.0438</version>
</dependency>
少し省略して書く。
 /api/application.wadl が表示されればOK、エラーなら何か見直し。

JSONとかいうもの

しばらく前からJSONとかRESTとかいうものがプログラムとか通信とかの間で使われるようになってきていたけど、全然追ってなかったのでいまさら追いかけた。 追いかけた足跡だけで細かいことは省略。
OpenIDを開いてみた気がする…。

JSONを広げる

 避けていたのは認証とかそういうところにたどり着かなかったから。今なら簡単に見つかりそうな気もする。 とりあえず仕様を探せ。JSONはRFC 8259が最新で最終版ともいわれている。ECMAの方にもECMA-404 2nd Edition というのがあるのでそれまでにあった差異などが解消されているとか。 名と値を文字列で書いたオブジェクトっぽいのがJSONの書式で、配列のもある。それだけ。JavaScriptとの受け渡しで相性がいいらしい。

RESTから関連機能を探す


 RESTは何だろうというと、HTTPやら何やらでJSONを通信する方法とでもいうか、HTMLの代わりにJSONが飛び交う。 どこで使われているのかというと、いろんなところで。XMLが流行ってたのは今は昔とでもいう勢いで。 各種サービス提供に使われているのはREST APIがほとんどらしいよ。と噂に聞いている。IoTの分野でも手軽にRESTで通信できるようになってる。人が間に入らないサービスはこういう方向でどんどん増えてもらいたい。
 RESTを使うのをRESTfulとかいうらしいよ。 ここまでは知ってた範囲。それで認証とかどうなのよというところで思考が停止。PKI使うのかBASIC認証使うのか、いろいろもやもやしてた数年前かな。
認証に使うのはRFC 2617 BASIC認証? とかCookieとかいろいろあった時代もあるようで。 RFC 7515-7519 というのがようやく安定してきた認証方法なのかな。この中からまずは JSON Web Token (JWT)を知ってみよう。PKIの基礎知識が必要。OAuth やOpenID Connect とやらもあるのであわせて後で調べる。

ABNFとJSON作ってみた

Javaで使うにはライブラリもあるのだろうけど、たまたま作りかけていたABNF(RFC 5234)で作ってみようと思ったらJSONの読み書きは簡単にできてしまったのでそういうことにしておく。
ABNFが何かというと、RFCで定義されているデータや何かの書式を書くための仕様で、プログラムで使うことはあんまり想定されていないけど作ってみたら案外使えなくもないしろもの。元はBNFという使いにくいものなんだけどRFC版のABNFは案外いろいろ書けるのでお得。曖昧な解釈とかも若干あるけども。EBNFとかBNFの派生にもいろいろあるけどまとめて実装しておいても使えないくらい他のは何もできないのでABNFは優秀。
ABNF自体もABNFで定義されているのでおもしろい。 プログラム上でもABNFを簡単にJavaにした形かABNFそのものですべての定義を書いている。

rulelist       =  1*( rule / (*c-wsp c-nl) )

というABNFの定義の一部を抜き出したサンプルと自作ライブラリの機能の紹介。
Javaでも次のように書けるので一部制限はあるものの、何も迷わない。

static ABNF rulelist = REG.rule("rulelist = 1*( rule / (*c-wsp c-nl) )";

事前の定義など省略するが、次のような書き方もできるようにした。パースする手間がない分起動が速い。

static ABNF rulelist = REG.rule("rulelist", rule.or(cWsp.x().pl(cNl)).ix());

文字列(ABNFtext)
static ABNF CRLF = ABNF.text("\r\n");
または ABNF CRLF = new ABNFtext("\r\n");

a / b / c は a.or(b,c)
a b c は a.pl(b,c) a.plus(b,c)はちょっと長いので縮めた
*element は element.x(0,-1) 略 element.x()
1*element は element.x(1,-1) 略 element.ix()
[element] は element.x(0,1) 略 element.c()
とJava中に手軽に書ける構造にしてみた。組み合わせも自由にできる。
a b c の構造は解析順序でどこまでをbに振ってどこからをcに振るのかなど複雑になることもあったので厳密版も作ってみたりしているが、改良版では厳密版の出番はまだない。

a*b element は element.x(a,b) と書く。
() はJavaの処理順で。
比較 Packetというデータの入れ物を昔から使っているのでそれの例

Packet pac = new Packet(data);
String str = "abc";
CRLF.is(pac) 判定(前方一致)
CRLF.is(str) 判定(前方一致)
CRLF.eq(pac) 判定(完全一致)
CRLF.eq(str) 判定(完全一致)
文字列でもどちらでも好きな方でデータの連結を考えて前方一致が使いやすそうなのでそれを基本に組み立てる。
テストで作ってみたのはRFC 3986 URIかな。 Parserまではまだ書いてない。

次のような注意点もあるのでABNFそのまま使えるわけではない点に注意。

RFC 2396 3.2.2. にある toplabel は原文では繰り返しとその後ろに alphanum が出てきてどちらなのかURIのパースで判定に困ることがあるので次のように修正してみたり。力業で読むこともできるのだけど。

 
原文 toplabel      = alpha | alpha *( alphanum | "-" ) alphanum ; BNF?

修正 toplabel      = alpha *( alphanum / ( "-" alphanum ) )     ; ABNF
 
ABNFは一旦略。
次はJSONのライブラリか。

JSONなどもABNFで定義されているのでちょちょっと追加するだけでABNFに加えBNF,EBNF,JSON,URL,URI,IMFなども使えるようになるのでRFCを収集しているところ。
JSONも基本はJSON構造を読んでJavaなら最終的にMapやListの階層構造と相互に変換できればいい。そういう作り方でいいんだろうか。ついでにBeanっぽいけどFieldを直接変換する作りも加えておいた。RESTの準備も進む。

各構文組み立てのためのParserはJavaで若干書くのだけど。構文解析の方はABNFのライブラリだけで可能。9割ぐらいABNF文に戻すこともでき処理順も目にやさしくなる。
ABNFを作ってからBNFとEBNFをさくっと作れたので、これくらいにしてJSONへ。

JSONはJavaScript Object なんとか RFC 8259 が最終形態らしい
オブジェクト、配列、Booleanや数値、文字、これくらいをシンプルに扱える。JavaScriptの内部表現的なものを誰かが発見して広まった、という解釈。
RFC 8259の式をそのままJavaに起こすだけで半分完成。ABNFのrulelistに流し込むだけでも同じ。JSONObjectとJSONArray、JSONValueなんていうクラスを作ってしまうとだいたい使える。Parserもさくっと中身の取り出し方に迷うくらいかな。
JSON→JSONObject→JavaのMap/List/配列→Object の相互変換が可能なくらいに仕上げてみた。
RFC 6901 JSON Pointer、RFC 6902 JSON Patch も動いた。
XMLよりJSONなのがよくわかる。

難しいのは文字コードの処理などかもしれない。JavaはUTF-8かUTF-16くらいで、UCSに変換とかサロゲートペアとか畳みかけてくるといろいろ面倒くさいが文字として扱えるよう注意してみた。
最初コンパイラでいうところの2PASSで実装したらしいABNFを1.5PASSくらいで書き直してみたりはした。 その他もろもろで初期から比べるとかなり速いがどっちが高速なのかは謎。
ABNFの拡張もいくつかあり、Parser書けばどこまででも対応はできるが、差分くらいで書けるようにしようとしてみるとどこまで対応していけるのか謎。
いろいろ言語的なものがさくっと作れるようになる、と期待。


https://github.com/okomeki にて公開中
RFC 7515から7519も作ってみないと次に進まない

 RFC 5234 Augmented BNF for Syntax Specifications: ABNF
  4. ABNFによるABNFの定義
  B.2.  Core Rules
 RFC 6901 JSON Pointer
 RFC 6902 JSON Patch
 RFC 7515 JSON Web Signature (JWS)
 RFC 7516 JSON Web Encryption (JWE)
 RFC 7517 JSON Web Key (JWK)
 RFC 7518 JSON Web Algorithms (JWA)
 RFC 7519 JSON Web Token (JWT)
 RFC 8259 JSON (本体)

NetBeansからGitHubへ

GitやGitHubがよくわかっていないのでNetBeans IDEから公開してみるテスト
説明は日本語サイトもあるけどあまり読んでいない。
  1. GitHubのアカウントを作る http://github.com/okomeki
  2. PuTTYgenで公開鍵を作る
    1. 画面上のPublic key をGitHubに登録する
    2. 秘密鍵をOpenSSH key形式で保存する
  3. リポジトリを作る https://github.com/okomeki/SoftLib
  4. SSHのURLを確認 git@github.com:okomeki/SoftLib.git (鍵を登録するとHTTPは不可?)
  5. NetBeansでプロジェクトをgitに入れる
    1. ローカルで作る
    2. Git → Commit
  6. Pushする
    1. Git → Remote → Push
    2. URLと秘密鍵、パスフェーズを指定
CVS/Subversionとの違い、疑問点のまとめ
  1. Gitはどこに溜まるのか
    最小単位はソースディレクトリの.git フォルダ内だけ
    管理専用の場所は不要
    Commitもこの中で完結、ひとりで管理可能
    CVSのブランチのようなものを保存場所で持つ
  2. GitHubにHTTPSで繋がらない
    鍵を登録していると無理なのか?
    ライブラリが古いとHTTPSは無理らしい、どちらか謎。
  3. アカウント/パスワードで繋がらない
    同上
というわけで
https://github.com/okomeki にいろいろと公開してみるかもしれません。

2019年6月26日水曜日

Wi-FiのWPSが廃止、代替のNFCとQRコードで設定したくて1000年経った(Tap-to-Connect)

Android 9では疲れからかWi-FiのWPSが廃止されてしまい、簡単な接続はできなくなります。
代わりというのもなんですが、Android 5以降のWi-Fiは、アクセスポイントの情報をNFCタグに書き込む機能が付いています。NFCタグからWi-Fiの情報を読み込んで自動接続する機能はTap-to-Connectというらしいです。
Tap-to-ConnectはWPSボタンと同じように接続を簡単にするために作られたようで、WPS、WPS+番号、の次みたいな位置づけです。
で、早速Tap-to-Connectを試してみたのですが、書き込む方の機能が使えない。書き込めないので読み込みも試せない。2月ごろに調べたり問い合わせたりした気がするのだけど見つからないので再度調べてみる。
書き込みたいタグはサンワサプライなどから販売されていますが、まだこの用途では活用できていません。
書き込める条件
  1. Wi-Fiに接続している/接続していない
    au Xperia XZ1 (SOV36 / Andorid 9) では接続していないWi-Fiのみ選択できる
  2. パスワード (謎)
    何を入れても通らない
  3. NFCタグの種類 (144バイト/888バイト)
    そこまで進まない
というわけで、謎。
au Xperia XZ1 (SOV36) + IIJmio SIM パスワードが通らない。
au Xperia XZ (SOV34) はFelicaが壊れていてたぶん試せない。
SONY Xperia Z4 Tablet (SGP712)で書き込める…膝から崩れ落ちる。
書き込もうとするとバグに遭遇する、こわいこわい。

Tap-to-Connect 書き込み


Android 7.1.1 の場合は接続中のWi-Fiのみ書き込めるようです。Wi-FiとNFCを有効にしてWi-Fiを開き、接続中のWi-Fiを長押しします。
「NFCタグに書き込む」を選び、Wi-Fiのパスワードを入力(8文字以上くらい)、「書き込む」を選んだ後、AndroidのNFCかFelicaのマークの部分をNFCタグにタッチします。
au Xperia XZ1 (SOV36) Android 9では無理です。バグ?
  1. NFC、Wi-Fiが有効になっていること
  2. 接続状態
    1. 対象Wi-Fiに接続していること(Andorid 7 / Xperia Z4 Tablet)
    2. 接続していてもいなくても可(Android 8 / Xperia XZ)
    3. 対象Wi-Fiに接続していないこと (Android 9 / Xperia XZ1)
  3. Wi-Fiの種類 なんでもいい 5G/2.4G / 暗号化の方法など / パスワード8文字以上(推奨)
  4. NFCタグの種類 (144バイト/888バイト) どちらでも可
この書き込みではNFCタグを書き込み禁止にできないので書き換えられないよう注意してください。他のアプリで書き込み禁止でTap-To-Connectを書き込めるものがあるかもしれません。
書き込めない情報も書き込めた情報もないので難しかった…。
書き込めないときはスマホを売っているキャリア(DoCoMo/au/Softbank/MVNO各社)、SIMフリー機の場合は購入店/キャリアかベンダーにお問い合わせしましょう。

Tap-to-Connect 接続

NFCを有効にした状態でNFCタグにタッチ、ネットワーク[ネットワーク名]に接続しますか? と出てくるので「接続」するだけ。Wi-Fiは自動的に有効になりました。
Xperia Z4 Tablet,Xperia XZ1どちらでも5G Wi-Fiに接続できました。

QRコードも試してみよう

https://zxing.appspot.com/generator などでWi-Fi用QRコードを生成することもできます。こちらはiPhone (iOS11以降)のカメラで対応しています。
AndroidのGoogleレンズ(Xperiaカメラ内)、SATCH(Xperia XZ1のQRコードリーダ)では反応しませんでした。
ZXingの QRコードスキャナー というGoogleのワンタイムパスワードなどのQR読み取りに使われていたアプリでは対応していたのでおすすめです。
NFCかQRコードでQRコードスキャナーのURLを書き込んで、まわりくどい方法を試してみるのもおもしろいかもしれません。
中身はテキストで
WIFI:S:わいふぁいのなまえ;T:WPA;P:ぱすわーど;;
というふうにSとTとPを書くだけです。TはWEPかWPA、省略(暗号化なし)もできるようです。

結論


Xperiaのバグすぎる? NFC対応SIM、非対応SIMお餅の方、情報ください。
ちなみにGalaxy Watch ActiveはNFCを有効にしただけではスマホのNFCにもNFCタグにも反応しませんでした。 
NFCはアプリも使うといろいろできるのでちょろっと買っておくといいです。
NFCの仕組みは同じなのでもしかするとamiiboにも書き込めるかもしれません。144バイト相当らしいです。


2019年6月21日金曜日

最近の品々のなかからソーラーチャージャー

太陽光発電、バッテリーチャージ用に小さいのを持っていたりしたけど引っ越しのいろいろで見つからないのと、大きいバッテリーを入手したのとで、新たに購入してみることに。大きいのを入れると高価なのでポータブルくらいの60Wの大きさのものを買ってみた。値段は昔買ったものの倍くらいなものの、パネルも大きく発電量はたぶん数倍あるくらいでとても安くなっている。
ソーラーパネル、モバイルバッテリーなAnkerや大きめのバッテリーのsuaokiといったメーカーからセットにするといいですよみたいな感じで出ている。
今回はsuaokiの60Wのものを購入してみることに。
基準は曖昧。ポータブルサイズに折り畳めることと、USB以外の出力があるサイズ、変換アダプタなどが豊富そうなこと。
出力はUSBの他丸いACアダプタについているような端子が1つ。60Wは丸い方からのみだろう。
ケーブル類は豊富で、車(シガーソケット)、車のバッテリー用?、AC直接なケーブル2本(端子2種類)。変換コネクタ沢山(10種類)、suaokiのバッテリー用1本。と、何にでも繋がりそうな勢い。
折り畳める中で60Wというと大きく、9+1枚に折り畳めるタイプで鞄にも入れやすそう。カバンの外につけるには大きすぎるが旅先で広げるくらいなら問題ない?
で、またまた提供AmazonなJackeryの700Whバッテリーがあるので繋いでみたりしてみたくなり。AC-ACなケーブルの先に変換端子をつけるとそれっぽい端子に繋がったので狭いベランダにてきとーに広げて1日放置。少し光が入ってくるとソーラーパネルの出力LEDは青く光っているものの、電力が弱すぎて小型のUSBバッテリーくらいなら少し充電が進んでいるものの、大きいバッテリーの方の充電ははじまらず。朝7時頃から1Wくらいの充電がはじまる感じ。大容量すぎてフル充電はできなかったが5%ほどなので10000mAhは充電できているんじゃないかな。てきとーに置いてもそれくらい。直接太陽に当たるようにしながら計ってみればもう少し伸びるはず。
この調子で貯めてみてもスマホ等のモバイル機器では使い切れないのでディスプレイか何かAC出力のもので使ってみようかと思う。

2019年6月17日月曜日

Bluetooth 5拡張カードのせるとWi-Fiも最強に (Intel AX200NGW)

自作PCにBluetoothを載せる場合、大抵はUSBのアダプタで済みそうなのだがどこを探してもBluetooth 4.0くらいのものしかありません。 その他の拡張方法を探してみると、M.2 NGFF型のWi-Fi Bluetooth 兼用アダプタがIntelから出ていていろいろあるらしいので見てみることに。 いくつか世代があり最近のものはこんな感じ
  • 802.11ac wave 2 (Wi-Fi 5 1733Mbps 2x2 MU-MIMO HT160)
    • Intel Wireless-AC 9260 (型番 9260NGW)
    • Intel Wireless-AC 9560 (Intel CNVio(CNVi)対応チップセット専用)
  • 802.11ac/ax ? (Wi-Fi 6 2.4Gbps 2x2 MU-MIMO HT160)
    • Intel Wi-Fi 6 AX200 (型番 AX200NGW)
    • Intel Wi-Fi 6 AX201 (Intel CNVio(CNVi)対応チップセット専用) 
ぬ? というわけで最新のWi-Fi 6にも(事前)対応していて Bluetooth 5.0に対応しているAX200NGWを入手してみることに。3400~4000円くらい。探している間に日本からの発送のものがあったのでぽちっと。Bluetooth 5.0だけなら9260NGWでもいい。その他にAX201というのもあるようだが、こっちはCVVioとかいうチップセットの機能を利用するらしくIntel PC専用? まずマザーボードがこのタイプのカード(M.2 E Key)に対応していない(ASUS X470-PLUS TUF GAMING / M.2 M Key)のでPCIeをM.2に変換するついでにアンテナもついているカードも必要になる。変換カードへのBluetooth接続にはPCIeの他にUSBから別途ケーブルを引いているようなのでそちらの空きも要確認。 AsRock DeskMini A300 などでも使えるらしい。

Fenvi のFV102というNGFFカードがPCIeからWi-Fi用のM.2 E Keyに変換できるようなのでそれも購入。FV101という別のカードと説明が混ざっていて怖い。アンテナもついて1800円とお安いのか?
Wi-Fiの規格の方をちょっと見てみると HT160 という広すぎる帯域に対応したルータは少ないようなのでフルは期待しないほうがいいらしい。
おまけでAndroidのNFC用にWi-Fi情報が書き込めそうなNFCタグも買ってみる。144バイトでは書き込めなかったので888バイトの方。
届いたらスピードテストでもしてみるか。有線だと200Mbps超えくらいなので期待はできない。
追記
届いたので接続。
ルータ側(BUFFALO WSR-2533DHP2 1733+800Mbps)はIEEE802.11ac Wave 2 HT80 4x4、PC側(Intel AX200NGW)がIEEE802.11ax HT160 2x2なので最大IEEE802.11ac Wave 2 HT80 2x2ということに。最大866Mbps でしたよと。ぐぬぬ。
BluetoothはLE(Smart)側も正常に使えているようで、Microsoftのキーボードに接続できた。Wi-Fiはこんなものなので、めでたしめでたし?

2019年5月25日土曜日

Ryzen PC組んでみた

さて何年ぶりになるのかPCを組んでみた。最近あまり使っていなかったがそろそろWindows7の時代も終わりである。スティックPCやタブレットPCのWindows 10も買ってみたもののCPUが弱すぎて使う気にはならなかった。
というわけでPC組もうと思っていたタイミングでメモリの試供できる機会があったのとAMD界隈のCPUが勢力を増してお手軽なので。
構成は次のような感じ。SATA接続のドライブなしである。

CPU: AMD Ryzen 5 2600X
MB: ASUS TUF X470-PLUS GAMING
MEM: Kingston DDR4-3200 HyperX Predator RGB 8GBx2
NVMe: Transcend PCIe SSD 220s Gen 3 x4 TS1TMTE220S M.2 NVMe 1TB
GPU: PaLiT GeForce RTX 2070 JetStream
電源: 玄人指向 750W 80 GOLD 電源
BOX: ENERMAX 箱
OS: Microsoft Windows 10 Pro 64bit dsp
以下余りもの
DISC: Pioneer UHD BD USB外付け
KB: Logi K375s
MOUSE: Logi M590
BT: どこかの
ディスプレイ: BenQ GW2470 フルHD

でだいたいあってるか? 最近はCPUよりメモリで性能が決まったりする面も多々ある。

Amazonとドスパラで大半のを購入。
CPUは次が出てきそうなので交換してもいいように若干控えめ、マザーボードはクロック上がりそうなX470で安いのを。
メモリまわりが速いので全体的な速度アップは期待できそう。乗せられるならメモリは速いのにしておきたい。今回は試供品的なものを使った。
M.2 NVMeを使うのでSSDやHDDは無し。DVD/Blu-rayは外付けで使う。
GPUはVRなどに使うかもとオーバークロックできるものにしてみた。たぶん。パーツの中でも一番高価。GPUの選択はオーバークロックモデルと背面端子の違いに注意。RTX 2070だと4Kゲームのひとつ下WQHDぐらいのゲームが快適らしい。FHDならGTX 1660やRTX 2060、4KならRTX 2080が最高解像度でフレームレート伸ばすのに最適らしい。120fpsとか144fpsのディスプレイもそのうち用意してみたいか。
USB Type-Cがついていないのが増えているのでその点も注意。
OSは先に別のPCでインストーラを作って入れておき、ライセンスはNTT-X Storeでdsp版などを購入。
ネジのドライバは標準サイズのものとM.2用のが必要。
マザーボードはX470かB450かの選択でだいたい決まるので、詳細は好みに合わせて。端子の数とオーバークロックの機能が豊富なのはX470だがそれも若干の違いか。最近はB450でいいっぽい? ASUSのTUFは背面にUSB-Cがあるが、M.2にヒートシンクがついていなかったがしばらくなくてもいいかな。
次の世代ではPCIeも4.0になるので交換するかどうかも考慮するともう一台増えそうで困る。
ビデオ出力はGeForceなのでマザーボードの出力規格は気にしなくてもいいが、HDMI1.4のものとHDMI 2.0bのものがあるようなのでRadeon付きのAPUにする場合はそのへんも注意点。
M.2はTwitterで有名なトランセンドのそこそこ速い売れ筋。他で同価格帯同速度のものは1つあったかな。ドライブはこれと外付けだけで対応する予定。 ヒートシンクあった方がいいのかな?
ケースは安いだけで選んだが、USB3.xのコネクタは2つくらいあるといいかもしれない。USB2が2つ、USB3が1つのものだったのでややものたりず。
組み立ては久しぶりで若干手こずる。マザーボードにメモリ、M.2、CPUをセット。ケースからマザーボード用ネジを1本外し、裏蓋がはまらず手こずり。電源を配線していくと短いケーブルに難儀。
1回目の電源投入、失敗。マザーボードとGPUが光っているが、メモリ光らず。メモリもGPUもちゃんと刺さっていなかったっぽい。何度か抜き差し再度起動するとうまくいった。
キーボードとマウスはロジクールのワイヤレスのを使うのだがドングルが多すぎてどれとペアリングされているのかわからないのでUSBのマウスとPS/2端子のキーボードでなんとかセットアップまで持ちこたえる。
UEFIの設定でメモリのクロックアップだけして保存。あっさり3200で動いているようだ。
Windows 7のインストールDVDでもあれば余ってるWin7からアップデートできたのかもしれないがごたごたで見つからず。USB接続の別のM.2 SSDからWindows 10をインストール。でもそれほど速くない? アップデート数回で最新に。
まずはデバイスドライバなどの最新版をダウンロードしてみたり、Firefox入れたり。WebにないツールはCD/DVDから入れてみる。
といったところで一段落。