それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

RuntimeException: SplFileInfo::getSize(): stat failed for php://temp となり、getSize出来ない

php8.1 までで起こる

SplFileInfo / SplFileObject / SplTempFileObject で php://memory php://stream を使うとエラーになる。

<?php
    $sf= new \SplTempFileObject();
    $sf->fwrite($ret);
    $sf->getSize(); // =>Error
    

対応

fstat は動くのでそっちを使う。

<?php
    $sf= new \SplTempFileObject();
    $sf->fwrite($ret);
    $sf->fstat()['size']; // => ok
    

こんなの気づかないよねぇ。

すでにパッチは投稿されていた

https://github.com/php/php-src/pull/4186

パット見だとClosedになっているので、そのうち使えるようになると思う。

exiftoolで写真をフォルダ(月日・年月・カメラ)に入れる。

写真の整理はexiftoolが確実です。

WindowsだとVector窓の杜にソフトウェアが紹介されていますが、あれはうまく動きません。

Exifの名前でフォルダに仕分けられるの

カメラで仕分けたり、日付で仕分けたりできる

写真を「年・月」に仕分ける。

写真を年月のフォルダに仕分ける。

exiftool '-Directory < DatetimeOriginal' -d '%Y/%m' *.jpg

実行例

このように散らばったファイルがあるとき

takuya@:sample$ ls
2022          IMG_6824.JPG  IMG_6827.JPG   IMG_6831.WEBP  IMG_6839.MOV  IMG_6844.PNG
IMG_6821.MOV  IMG_6825.JPG  IMG_6828.JPG   IMG_6833.JPG   IMG_6841.PNG  IMG_6856.PNG
IMG_6823.JPG  IMG_6826.JPG  IMG_6830.WEBP  IMG_6834.JPG   IMG_6842.PNG  IMG_6857.PNG

コマンドを実行すると

exiftool '-Directory < DatetimeOriginal' -d '%Y/%m' *.jpg

次のように、YYYY/MMのフォルダに仕分けられる。

takuya@:sample$ find
.
./IMG_6856.PNG
./IMG_6823.JPG
./IMG_6825.JPG
./IMG_6830.WEBP
./2022
./2022/06
./2022/06/IMG_6859.jpg
./2022/06/IMG_6858.jpg
./2022/06/IMG_6838.jpg
./2022/06/IMG_6848.jpg
./2022/06/IMG_6854.jpg
./2022/06/IMG_6845.jpg
./2022/06/IMG_6843.jpg
./2022/06/IMG_6820.jpg

DatetimeOriginal がないJPGファイルは、iPhoneスマートフォンの場合、スクショだったりWEBから保存したものだったり、アプリで編集(モザイク加工)したもの、誰かから送られた写真を保存したもの(LINEやFBなどSNS系はプライバシーのためExif削除される)だったりするので、DatetimeOriginalがあるものが自分の写真だとはっきりわかるので便利だったりする。

カメラで仕分ける例

たとえば、ExifのModelには、カメラの名前が入ってるので、そっれを使って仕分けたり

exiftool '-Directory < Model'  *.jpg

exif の値使って仕分けるの便利

exif のタグなら仕分けに使えるので便利ですね。

GPSでいい感じに絞れたらいいんだろうけど、調べたけど厳しそうだった。

関連資料

その他、exiftool に関する記事です。参考にしてください

https://takuya-1st.hatenablog.jp/search?q=exiftool

参考資料

  • man exiftool

exiftoolで写真の日付を修正する

写真の日付を修正したい

写真ファイルをバックアップしたら、ファイルの更新日時が撮影日にならない。

ファイルシステム上のタイムスタンプも撮影日にしておくと、エクスプローラーやFinderで見るときにべんりなので、写真のファイル更新日時を撮影日合わせたい時がある。

exiftool でファイル更新日時=撮影日にする

exiftool  '-FileModifyDate<DatetimeOriginal' IMG_6862.jpg

一括で変更する

ワイルドカードを使えば、対象ファイルをまとめて更新できる

exiftool  '-FileModifyDate<DatetimeOriginal' *.jpg

_original ファイル

exiftool でファイルを更新すると、_original のバックアップファイルが作られることがある。

ファイルをスクリプトで処理していると バックアップファイルも書き換えにいき、バックアップのバックアップ( IMG_6862.jpgIMG_6862.jpg_originalIMG_6862.jpg_original_original ) が作成されてしまうので、自動化処理には注意が必要だ。

バックアップを自動で削除するより、ちゃんと手作業でコマンドを打ち込みファイルの修正前後をしっかり確認したほうが無難だと思う。

日時の確認

日時の確認は、次のようになる。

exiftool -s -filemodifydate -datetimeoriginal IMG_6862.jpg

まとめてやるときは、-Tをつけると楽

exiftool -T -s -filemodifydate -datetimeoriginal *.jpg

関連資料

その他、exiftool に関する記事です。参考にしてください

https://takuya-1st.hatenablog.jp/search?q=exiftool

参考資料

  • man exiftool

exiftool で日付・時刻の確認する。

exiftool でタイムスタンプを確認する

exif に設定された写真の日時・タイムスタンプを確認する。

exiftool -time:all -s IMG_6862.jpg

次のような出力が得られる。

takuya@mac:~ $ exiftool -time:all -s IMG_6862.jpg
FileModifyDate                  : 2022:06:07 22:59:13+09:00
FileAccessDate                  : 2022:06:16 00:47:35+09:00
FileInodeChangeDate             : 2022:06:13 20:02:41+09:00
ModifyDate                      : 2022:06:07 22:58:57
DateTimeOriginal                : 2022:06:07 22:58:57
CreateDate                      : 2022:06:07 22:58:57
OffsetTime                      : +09:00
OffsetTimeOriginal              : +09:00
OffsetTimeDigitized             : +09:00
SubSecTimeOriginal              : 301
SubSecTimeDigitized             : 301
ProfileDateTime                 : 2017:07:07 13:22:32
SubSecCreateDate                : 2022:06:07 22:58:57.301+09:00
SubSecDateTimeOriginal          : 2022:06:07 22:58:57.301+09:00
SubSecModifyDate                : 2022:06:07 22:58:57+09:00

ただし、FileModifyDate・FileInodeChangeDate・FileAccessDateについてはファイルシステムから取得した値で、写真ファイルに埋め込まれた値ではない。

名前に空白を入れない -s

空白を入れるとコマンドから再利用しにくいので -s を使って、出力をCamelCaseにしている。

-s を点けない場合

-sなしでは、次のような出力になった

exiftool -time:all IMG_6862.jpg

名前に空白が含まれる。

File Modification Date/Time     : 2022:06:07 22:59:13+09:00
File Access Date/Time           : 2022:06:16 00:47:35+09:00
File Inode Change Date/Time     : 2022:06:13 20:02:41+09:00
Modify Date                     : 2022:06:07 22:58:57
Date/Time Original              : 2022:06:07 22:58:57
Create Date                     : 2022:06:07 22:58:57
Offset Time                     : +09:00
Offset Time Original            : +09:00
Offset Time Digitized           : +09:00
Sub Sec Time Original           : 301
Sub Sec Time Digitized          : 301
Profile Date Time               : 2017:07:07 13:22:32
Create Date                     : 2022:06:07 22:58:57.301+09:00
Date/Time Original              : 2022:06:07 22:58:57.301+09:00
Modify Date                     : 2022:06:07 22:58:57+09:00

-a をつけると重複を取れる

Exifはタグで書き込まれているだけなので、同じキーに複数回の値を設定することができる。編集ソフトを使って冗長に何度も書き込まれている場合もあるので、それを確認する。

exiftool -a -s -time:all IMG_6862.jpg

上記のコマンドだと、DatetimeOriginalやCreateDateが何回も出力されることがある。EXIF編集を追記追記で適当にやった場合にそのようなミスがわかるので便利。

特に写真の日付は撮影者から人手を経るたびに何らかの編集ソフトでうっかり同じKEY-VAULEを書き加えてしまうことがあるので、日付がおかしいなと思ったら -a でチェックするのも手だ。

特定の値(撮影日)だけを見たい

撮影日だけ見たいとき

exiftool -datetimeoriginal -s *.jpg

作成日だけ見たいとき

exiftool -creatdate -s *.jpg

ファイルシステム上の更新日を見たいとき

exiftool -FileModifyDate -s *.jpg

複数を指定もできる。

複数個書いて、見たいものだけ指定するのもありだ

exiftool -FileModifyDate -DatetimeOriginal -s *.jpg

mov の場合

mov ファイルはQuicktimeなので、createDateでなくCreationDateで入ってることがある。

exiftool -CreationTime -s *.jpg

参考資料

  • man exiftool

exiftool でカラム表示で撮影日とファイル名を一覧する

exiftoolでファイル名とカラム表示したい

ls -alt 的な感じでexiftools で写真のEXIFデータを見たい

-T でカラム表示

exiftool -T にすると、カラム(タブ区切り)で表示できる

ファイル名を表示したい

exiftool -filename でファイル名を表示できる

写真のタイムスタンプ(日時)を表示したい

DateTimeOriginal がシャッターを押した日付になる。

exiftool -DatetimeOriginal

lsコマンドみたいに撮影時刻を見る

すべてまとめて、次のようにコマンドを作ることができる。

takuya@mac:~/Photos/2022/06$ exiftool -T -filename  -datetimeoriginal *.jpg
IMG_6820.jpg    2022:06:01 01:22:12
IMG_6829.jpg    2022:06:01 19:55:41
IMG_6832.jpg    2022:06:02 14:44:53
IMG_6836.jpg    2022:06:03 14:32:40
IMG_6837.jpg    2022:06:04 15:48:09
IMG_6838.jpg    2022:06:04 15:48:11
IMG_6840.jpg    2022:06:04 23:12:00

通常のexiftoolの場合

カラム(縦方法)に1行に表示しない場合は、複数行に記載されてしまい、コマンドから非常に扱いにくい。

takuya@mac:~/Photos/2022/06$ exiftool -s -filename -datetimeoriginal IMG_6838.jpg
======== IMG_6860.jpg
FileName                        : IMG_6860.jpg
DateTimeOriginal                : 2022:06:07 22:58:26
======== IMG_6861.jpg
FileName                        : IMG_6861.jpg
DateTimeOriginal                : 2022:06:07 22:58:40
======== IMG_6862.jpg
FileName                        : IMG_6862.jpg
DateTimeOriginal                : 2022:06:07 22:58:57
   22 image files read

ファイルの生成日・更新日・撮影日を一覧する

exiftool -T -Filename  -DatetimeOriginal -CreateDate -FileModifyDate -file *.jpg 

このコマンドは大文字小文字を区別しないようですね。

exiftool -T -filename  -datetimeOriginal -createDate -filemodifydate -file *.jpg 

このコマンドを使って、ファイル更新日と撮影日がずれているファイルを見つけたり、撮影日が未設定のファイルを探す事ができる。便利

xargs と組み合わせて処理を高速化

xargs のマルチプロセス機能を組み合わせて、限界までCPUを使って演算を高速化する。

ls *.jpg | xargs -P10 -I@ exiftool -T -filename  -datetimeoriginal @

写真フォルダには数千枚のファイルがあるので、xargs と組み合わせるとすこし速いかもしれない。

ただし、プロセス生成のオーバーヘッドがあるのでexiftool に複数ファイルを引数に渡すのと比べて、遅くなる場合も多い。

exiftool コマンドのインストール

sudo apt install libimage-exiftool-perl

参考資料

  • man exiftool

journald がログエラーで無限ループになってサーバーが応答なしになった。journald の上限を決める

サーバーの容量不足で無限ループになった

知らない間に、サーバーにDockerのキャッシュを溜めすぎて、残容量が底をついた。

気づかずに発生した

journald が無限ループ

journld は閾値をもっていて、一定量以上のログを書き込みしないはずだが、容量不足なってエラーになり、エラーログを書き込もうとしてまたエラー、そのエラーを書き込もうとして更にエラーになった

journald の設定を明示的に書いておくことにした。

自動設定ではjournald は無限ループになってしまうことがわかったので。 /etc/systemd/journald.conf に設定を明示することにした。

/etc/systemd/journald.conf

[Journal]
SyncIntervalSec=10m
RuntimeMaxUse=5G
RuntimeKeepFree=10G

こちら(https://isleofhoso.com/journald-conf/)を参考にいくつか設定を書いた。

設定を反映

sudo systemctl restart systemd-journald

docker を整理

sudo docker image prune -a 
sudo docker volume prune -a 
sudo docker container  prune

image がいい感じに消えてくれないので 明示的に消した。

docker 怖いよ。。。

2022-06-20 追記

また、エラーになった。SSDがぶっ壊れか、XFSがエラーになったかどちらかだと思う。

XFSをリペアして様子見する。

phpでThe server requested authentication method unknown to the client.

php で次のようなエラーが出る

The server requested authentication method unknown to the client

原因 php-mysql の接続でエラー

エラーの原因は mysql の認証方式の変更に対応できないエラー

いままで、mysql は mysql_native_password だったが、mysql8 あたりで caching_sha2_password になっている

対処方法

候補は次の通り、

mysql 8 の caching_sha2_password を殺し、mysql_native_password を使う。

または、

mysql_native_password 時代に対応した mysql 5.x 系を使う。

mysql 5.x 系を使う場合

ubuntu / debianmysql を併存させるのは苦労でしかないので docker を使う

docker run -d --rm \
   --name mysql-5 \
   -p 3304:3306 \ 
   -v /data/mysql5-server/data:/var/lib/mysql \ 
   -e MYSQL_ROOT_PASSWORD=**PASS** \
   mysql:5

あえて古いUbuntuDebianを用意してもいいけど、基本的に非推奨だし、Dockerに閉じ込めればいいわけですから、これでいいでしょう

mysql8 に mysql_native_password を使わせる

これは、ちょっと茨の道。いくつかのポイントを抑える必要がある。

ユーザーの現在の認証方式を確認する。 以下のユーザの通り、mysql_native_password にしていると、mysql_native_passwordを使って認証することになる。

mysql > select User, Plugin from mysql.user;
mysql root@(none):(none)> select User, Plugin from mysql.user;
+---------------------------------+-----------------------+
| User                            | Plugin                |
+---------------------------------+-----------------------+
| connect_test                     | mysql_native_password |
| takuya                          | caching_sha2_password |
| mysql.infoschema                | caching_sha2_password |
+---------------------------------+-----------------------+

mysql_native_password を使う設定

my.cnf で設定を変更する

[mysqld]
default_authentication_plugin=mysql_native_password

再起動する

systemctl restart mysql

注意点。デフォルト値の変更

デフォルト値を変更すると、mysql_native_passwordが優先される。

接続時に mysql_native_password がクライアントに通知される。

caching_sha2_password は使えるけど、トラブルが多い。mysql_native_passwordが先に通ってしまうので。クライアントはmysql_native_passwordを送ってくる。

なので、mysql_native_password と caching_sha2_passwordを混ぜた運用はしないほうがいい。

また caching_sha2_password に未対応のphp といえば、php5.6 や php7.0 なので、そのような古いPHPでしか動かないコードを最新版のMySQLで動かそうとするほうが無茶なので、素直にphpソースコードをアップデートしてパッチを當てるか、古いものは古いものと合わせてDocker環境に閉じ込めて動かしたほうが素直だと思います。

参考資料

https://improve-future.com/mysql-php-the-server-requested-authentication-method-unknown-to-the-client.html

iCloudフォトのデータを全部取り出す方法(エクスポート)

Windows版のiCloud を使って iCouldの写真データを取り出す。

これ駄目です「iPhone をUSBにつないでデータ取り出したらいいじゃん?」

iCloudサブスクリプションを契約したiOSのデバイスは、端末に写真を持っていません。

大事なので繰り返します。iphoneは端末に写真を持っていません。しかも画質とサイズを劣化させたファイルを持っています。なので、DCIMフォルダからUSB経由で取り込んでも、無駄です。ごく一部しか取り込めません。iphone取り込みはicloud契約後は機能していません。

iPhoneサブスクリプションの広告を出すが、Apple ははエクスポートについて大事なことは知らせてくれないのです。

WEBダウンロードすればいいじゃん→出来ません。

「WEB版 iCloud.com からバックアップ」 をしようとして、iCloudフォトにアクセスし、データをダウンロードしようとすると、次のようになる。

写真は、個人でも軽く3000枚を超えることでしょう。項目を選択してダウンロードは事実上不可能なのです。

エキスポート機能(取り出し)はありません。

icloudサブスクリプションを契約して、icloud photo にデータをアップロードしたアップロードデータを纏めて取り出す機能は、現在(2022-06-10)のところ存在しません。

Googleアカウント・Googleフォトであればエクスポート機能があり、一括ダウンロードと分割ダウンロードができるようになっていますが、Appleにはありません。

繰り返します。WEB版 icloud.com には「取り出し・一括ダウンロード」はありません。

無茶を言うAppleiPhone にダウンロードで取り込め」

Appleの公式サイトを見ると、取り出し方の指示が書いてある。

Appleの指示は「iphoneにダウンロードでicloudから取り出せ。」です。むちゃくちゃです。

Appleの公式にある手順を見ると、次のようなマニュアルになっています。

iOSでPhoto.appを開き、 写真をすべて選択、 メニューからダウンロードを選ぶ、 ダウンロード完了を待て。

このようにと書いてある。しかし、この手法は絶対に実現不可能です。なぜならiOSが容量不足になるからです。

iCloudの容量よりiPhone端末容量のほうが圧倒的に小さい。

AppleiPhone写真をiCloudに移動して容量を節約と言って売り込んでいる。だから根本的にダウンロードは不可能なはずだ。なのにiPhoneへダウンロードを推奨される。完全に詰みである。

では、どうするのか。

解決策。Windowsicloudで取り出す。

Windowsicloudアプリケーションを使うと確実に取り出すことが出来ます。

icloudをダウンロードしてログイン

iCloudアプリケーション(win)は、Microsoftストアに用意されています。これをダウンロードし、インストールし、AppleIDでログインします。

iCloud 写真」フォルダを開く

Apple IDでログイン後に、iCloud photoを有効にすると、WindowsiCloudフォルダの「同期フォルダ」が出来ます。

この専用フォルダ(仮想フォルダ)を通してファイルが一覧できるようになります。

ただし、これはクラウドのファイルをWindowsエクスプローラで見ているに過ぎない(仮想フォルダ・同期フォルダ)。ファイル自体は、Windowsにまだ同期されていません。

次の手順で、iCloudからファイルをダウンロードします。

ファイルを選択肢「このデバイスに保存」

ファイルを選択し、右クリックから「Alaways Keep On This Device」を選びます。すると、iCloudのサーバーからダウンロードが始まります。

ファイルの一覧が同期中の例

注意点。枚数に注意

icloud.com にアクセスし、「写真の枚数」と「ビデオの本数」を確認します。

このファイル数と同じファイルが、Windowsに一覧表示されるのを待ちます。

同じ枚数分の一覧がウィンドウズに出てくるまで待ちます。(icloudのファイル・リストがWindows同期されるのに1時間かかります。)

すべて選んでダウンロード

すべて選択し、枚数が同じになることを確認したら、ダウンロードです。

ファイルの一覧が「すべて同期」された状態で、ファイルの中身をダウンロードします。

繰り返しになりますが、ファイルの一覧が動機済み状態で、ファイルのダウンロード(このデバイスに保存 / Always keep on this device ) を選びます。

タスクトレイから同期状況を確認

Windowsのタスクトレイに、iCloudアイコンがあります。クリックしてダウンロードの状況を確認します。ダウンロードはすごく時間がかかります。3時間位は覚悟してください。

転送エラーになる。でも辛抱強く

大量にダウンロードすると、Appleサーバーからキックされて、接続エラーが出ます。また、短時間に大量にダウンロードするのでISPからコネクションを切断されることもあります。

スリープに注意

ダウンロードを予約して、Windowsを放置すると、Windowsがスリープします。Windowsがスリープすると、ダウンロード転送も止まるので注意が必要です。

ダウンロードが完了した状態

次のように、ファイルに✔がついたら、ダウンロードは完了です。

ただ、この状態は、iCloudと「同期」した状態、且つ、ローカルコピーを作った状態です。

この状態では、icloudで写真が追加削除されると、その状態に同期されてしまいます。

デスクトップに取り出す。

iCloud 写真」から「デスクトップ」に写真をコピーしてください。

これで、同期を解除してもデータが喪失することはありません。

以上の手順まとめ

  • windowsicloudを使う
  • icloud写真フォルダを開く
  • ローカルコピーを作る
  • 同期を辛抱強く待つ
  • 同期が終わったら別の箇所へコピーして保存

です。

エクスポート機能がない、同期フォルダを経由しないといけない。という点が必須知識ポイントです。

同期フォルダに馴染みがある人にはわかりやすく、馴染みのない人には全く理解できない手順になっています。

初心者には理解が無理な仕様

AppleiCloud photo は、安いです。130円です。円ドルレートを考えても安いです。

 しかし、漁師の定置網漁のようなものです。定置網に誘導されたお魚は一生そこから脱出することが出来ず、漁師(Apple)にすくい上げられるのです。

 ダウンロードはここまで述べたような注意点に留意が必要です。スマホしか触ってない世代には、このようなデータ取り出し方法は理解も実行も困難です。

 PC初心者が、データ取り出してiCloud photoの課金停止は不可能です。課金停止しようとしたら、「データを諦める」のが最有力の選択肢に出てきます。データを諦めるほうが優先されてしまうことでしょう。

 本文中で述べたように、Appleの指示はわかりにくく、詰みが発生します。そもそも初心者に課金停止後の安全なデータの取り出し方法の「手順」がまともに提供されてません。そんなAppleicloud photo に一生課金続けますか?それとも今すぐやめますか?

 今すぐiCloud課金をやめて、データを自分の手に取り戻し、同期先を変えるべきだと考えます。nextcloud などほかサービスに転送すべきだと考えます。

 年間2500円程度の支出を気にし過ぎだろ。と思うかもしれません。

 そんなあなたに言いたい、また次のiPhoneを買うんですか。データを取り出せないために、乗り換えが心理的負担になっていませんか。お金で換算できない価値を失っていませんか。選択肢も所有権も私達にあるべきです。  また、古い写真は捨ててしまってもいいと思いますよ。整理されてない情報は持っていても無意味です。

その判断も、私たちの管理下にあってこそ意味があります。方法が分からずデータを捨てるなんて悔しくないですか?私たちの管理下に取り戻し、自分で決断し捨てる行為に意味があるのではないでしょうか。

HTMLのリセット(reset)ボタンで検索条件をクリアのときに、すでにデータがあるとクリアされない

html で検索フォーム

HTMLのFormで検索フォームを作ると、検索条件のリセットが欲しくなる。

とくにテストしているとリセットボタンが欲しくなる。

フォームのリセット

フォームのリセット、とても簡単です。HTMLの遺物を使えばいいんです。

<form action=search method=get>
<input type=search name=user value='' >
<input type=submit value=search>
<input type=reset value=reset >
</form>

とても簡単です、ボタンを一つおけばいいのですから

<input type=reset value=reset >

問題点:リセットはクリアじゃない

WEB側のCGI*1でHTMLを生成するとき

サーバー側でHTMLレンダリングを行っていると

<input type=search name=user value='takuya' >

サーバー側から送られた状態にリセットされます。

リセットボタンは、ユーザーの入力による変更を破棄であり、フォームのクリアではない。

解決策1

input[type=search] を使えばいい。検索フォームに input[type=text] は使わない

なぜか?input[type=search] はMDNに記載があるように、ブラウザ側でフォームの値を持ち回してくれる。なんちうHTML要素だ。

phpなどでecho が不要になるのである。

search なら次は書く必要がない。

よく見る、検索文字列のHTML代入だけど、これが不要。

<input type=search name=user value='<?php echo $cond;?>' >

type=search ならこれだけ

ブラウザが勝手にやります。

<input type=search name=user  >

これを使っておけば、input[value]は常に空っぽの状態になる。そのためリセットボタンは正しく動作する。

できる限りsearch を使っておく

できる限りsearchを使っておくと、リセットボタンが正しく動作する(HTMLにデフォルト値を入れないため)ということなので、type=searchがうまく使えるようにdisplay:noneと組み合わせて組み立ててあげればいい。ただし、ブラウザ次第で戻るボタンで値が戻る場合があり、ブラウザごとの挙動を調べ上げるのがちょっと不便。

解決策2

古のオーパーツ(FormElements)のAPIを使う。

ボタンにセレクトやチェックボックスが混じってるとDOM操作でフォームのインプットの各要素のValueを設定しておくのは面倒すぎる。

そこで、太古の昔に存在したFormElementsを使う。

var myForm = document.getElementById("#btn").form
myForm.elements[0].value='';
myForm.elements[1].value='';

ちょっとだけ、最近のJSぽく書いて、クリアボタンを設定する。

document.addEventListener("DOMContentLoaded", () => {
    document.getElementById("form_clear_btn").addEventListener('click', ev=>{
      const form = ev.target.form;
      Array.from(form.elements).forEach( e => e.value='' )
    });
})

MDN にドキュメントが残されていて、HTMLFormElement.elements の使い方が見れる。DOMにアクセスして値を書き換えるのだが、アクセス方法はHTMLFormElementsであり、HTMLFormElementを介してアクセスする。

JSのこの仕様を久しぶりに使ったんだぜ。この form.elements 関連のAPIって未完成だけど、React/Angularのように、フォームとDOMの分離を企図したような残滓(?)を感じる。

方法3

リセットボタンで、フォームの書き換えは諦めて、GETのquery_string ( ?name=value)を除去し、ブラウザを移動させてしまえばいい。

location.href=location.href.split('?')[0]

何も検索条件が入力されてない状態のURLを読み込めば、リセットボタンと同じ効果が得られるのである。実にシンプルな解決方法である。

リセットボタンの扱い

リセットボタンは、デフォルト値にリセットするわけです。

デフォルト値は<input value=123456 >のようにHTMLに仕込まれた値です。

リセットが効かない。フォームにリセットは無用ではありません。使いどころが大事なのである。

問い合わせフォームにクリアボタンを置くのは、たしかし無用の長物です。でも。検索フォームは違う。

「リセットボタンは検索時に使う」のです。データを検索しフィルタリングするときこそ、リセットボタンが役に立つのです。

リセットボタンは設置したたらだめ。と古い記事を見かけますが、それは”問い合わせフォーム”などPOSTするフォームの話であり、検索条件を入力するGETのフォームの話ではありません。「リセットボタンはだめ」と覚えていたなら、それは大きな間違いです。

といっても、問い合わせフォームで値をvalue=aaa で戻したときは不便です。

このようなめんどくさいところをさくっとJSON取得で解決できるので、ReactやAngularやVueが便利だと思うんだけどね。それら使ってないサイト・プロジェクトに、検索条件の維持とリセットのためだけにVueを埋め込むのもありえないよね。

ということで、検索系のHTMLをサーバーサイドレンダリングで十分なパフォーマンスが得られると考える場合、Vue・ReactでSPAする意味もあまりない気がするんですよねぇ。*2

参考資料

*1:あえてこういう古い言いまわしをている

*2:検索結果のHTML生成がキャッシュされ、多人数がリバプロ経由で再配信を受けとれる場合ね

Raspi Zero / WH をOTGで使う。

Raspi Zero / WH をOTGで使う。

OTGで使うと、pi zero がUSBデバイスのフリをすることができる。

こんな事ができる。

  • USBシリアルポートデバイス
  • USBネットワークデバイス
  • USBストレージデバイス
  • USBキーボード(HID)
  • USBマウス

のように、USBに挿し込んだPi ZeroがPCからUSB機器に見える。

対応機種

pizero と raspberry pi 4 以降がOTG対応

raspi3 もバージョン次第で大応してた気がする。

USB ガジェットモードの主な使い方 / PC → Pi zero へアクセス

主な使い方は、Pi Zeroをセットアップするための使います。

USBシリアルデバイスやUSBネットワークデバイスとしてPi ZeroをPCへ接続し、PC側からSSHで、Pi Zeroにログインして使うと便利です。

またPi Zeroを「USBストレージ」にしてPC側からファイルを書き換えたり送り込んだりするのに便利です。

Pi zero → PC にアクセスで使う(逆)

ネットワークで認識させた場合

Pi Zero WH はWifiを使えます。ノートPC→ Pi zero へWifi経由でSSHで接続したうえで、Pi ZeroからPCへUSB経由で接続すると、PCをリモート管理ができるようになりますが、あまり使いどころは無いと思います。

キーボードとして認識させた場合

USBキーボードとして認識させたうえで、Pi ZeroへSSHしてPCにキーを送り込むことが可能になります。これは便利かもしれません。PCをリモートで管理するときにUSBキーボードとしてショートカットを送り込んでしまえば、ほとんどの機器で自動化のツールとして使えるようになります。

出番は少ない

インストールで使うためにありましたが、現在では出番は少ないかもしれませんが

Raspi Imagerみたいな初心者向けツールを使わずに、昔からのdd / ddrescue などでサクッとイメージをコピーしてたら、初期設定ではまだまだ使います。Windowsとは限らないです専用ソフトもいらないので重宝します。

OTG有効にする

これらのUSB機能を有効にするには、cmdline.txt に書き込みます。

OTG 設定

modules-load=dwc2,g_cdc

dwc2 がOTGの有効化で、g_cdc はシリアルコンソール+イーサネットの略称です。

cmdline.txt の例

console=tty1 root=PARTUUID=055f10f4-02 rootfstype=ext4 fsck.repair=yes rootwait modules-load=dwc2,g_cdc

シリアルコンソールで通信

OTG(dwc2,g_cdc) でシリアルコンソールを有効にした場合、

pi zero 側にシリアルコンソールデバイス ttyGS0が生成

raspberry pi zero 側に ttyGS0 が生成される。

ls /dev/ttyGS0

[PC側] PCはシリアルコンソール /dev/ttyACM0 が生成される

USB経由で接続されたPC側には、 /dev/ttyACM0 が生成される(Linux)の場合

ls /dev/ttyACM0

あとは、これを使って、gettyがリッスンすればいい。

PC 側にログインする場合。

PC側でgettyを起動

sudo systemctl status serial-getty@ttyACM0.service
sudo systemctl start serial-getty@ttyACM0.service

pi-zero 側で screen を使って接続

takuya@pi-otg $  sudo screen  /dev/ttyGS0

逆にやれば、Raspi側にログインできる。

OTGつないだときだけ起動するとか。systemdで制御すればいい。(後で考える。)

イーサネットで通信

USBイーサネットは、初期設定がDHCPになっているのでDHCPでIPを渡してあげればいいはず。

pi zero側のデバイス

Pi Zeroからは、usb0の名前で見える

ip link show  dev usb0
2: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

PC側のデバイス

PC側からも usb0で見える(Linux)の場合。Windowの場合はイーサネットバイス

Raspberry Pi と PCがLANケーブル(クロス)でつながった状態になる。

pizero が usb0 経由して接続できるよう、PCのusb0 を 外部に接続してあげればいい

ネットワークの共有はOSや目的や手段によって異なる(Linuxの場合 btrctl など、詳細は割愛)

pi のOTG側から見たとき。

takuya@pizero-otg:~ $ ip link show dev usb0
2: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 56:bd:66:c1:06:02 brd ff:ff:ff:ff:ff:ff
takuya@pizero-otg:~ $ ip addr show dev usb0
2: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 56:bd:66:c1:06:02 brd ff:ff:ff:ff:ff:ff
    inet 169.254.39.187/16 brd 169.254.255.255 scope global noprefixroute usb0
       valid_lft forever preferred_lft forever
    inet6 fe80::e05d:3a75:e46a:83e1/64 scope link
       valid_lft forever preferred_lft forever
takuya@pizero-otg:~ $

USBキーボード(HID)

USBキーボードとして動作させることができる。

差し込むだけで、あれこれ自動入力をしてくれる機械の完成です。やったね。

USBキーボードを差し込んでリモートからコマンドを流し込んでー。。。とか出来ますね。Raspiにはカメラが付いてるので、カメラで画面出力を監視しし画面を学習してしまえば。。。リモートから大体のデバイスは制御できますね。

他のWebサイトにはg_hidというモジュールを使ってUSB入力機器化する情報が掲載されている可能性がある。これは古いOSでしかできない方法のようで、実際にやろうとしてもg_hidが見当たらず読み込めないハズ。最近のOSの場合にはlibcompositeを使う必要があるようだ。

https://qiita.com/exthnet/items/98aa9b6d6a606f8f2cf8

キーボードとして認識された時点で満足したので詳細は割愛。

USBストレージ

USBストレージ機器として振る舞う事ができます。

USBマスストレージに対応した機器にRaspiをつないでしまえばいいのです。

USBメモリになる。USBメモリ領域はRaspi側からも見えるので、リモートから書き換えができるUSBメモリが完成する。

ネットワーク非対応のフォトパネルやTVなど、家電にUSBメモリを差し込んで設定を流し込んだりするとき、いちいち抜き差しなどせずに、USBメモリの中身を書き換えるので便利。うちの機器でためしたときは、既存ファイルの再読み込みがUSB抜き差しタイミングで発生知るので、Raspi側でUSBストレージのオンオフしなくちゃいけなかった。そもそUSBメモリが機器の預かり知らないタイミング書き換わるなど想定されるはずもない。なので、意外と使い途はないかもしれない。

https://qiita.com/haniokasai/items/427b7481881e065ae2f2

USB マウス

コロナ禍でマウスを少し動かすUSBがガジェットがバカ売れしましたが、RaspberryPiがあれば、その機能を作ることができる。僕は監視されてないので、ここまでする必要なかかったけど、ゲームのマクロなどをUSBマウスで実行するととても楽になるかもしれない。ようはプログラマブルなマウス、自動化・マウスしかもUSBの正しいデバイスとして作ることができる。最高じゃん?ラグナロク・オンラインやメイプルストーリーが流行ってた頃にほしかったよ。

動かし方は、次のサイトを参考に動かした。 https://toki-blog.com/pi4-gadget-mouse/

マウス1ピクセル動かして飽きたので、詳細は割愛。

USBドングル化

USB-OTGを使えるデバイスとして挿しっぱなしで使えるようにした。

これで、Raspi zero W をPCに差し込んでしまえば、USB機器に見えるが

Raspi自体はWifi ( AP or Client ) でネットワークに接続されるので、PCにいろいろインジェクションできる機械の出来上がりである。

[f:id:takuya_1st:20220606223250p:plain]

動作時の注意(USBハブは使わない)

理由として、OTGの先にハブが接続されていた場合。 ここから想像するに、Zero にハブをいれたらOTGが無効になるのではないか

RaspberryにUSBハブを付けて、ドングルを挿し込む→PC側にUSBとして認識される。

dwc2 を指定したとき

RaspberryにUSBハブを付けて、ドングルを挿し込む→PC側にUSB機器が見えない。

takuya@pizero-otg:~ $ dmesg | grep -i otg
[    2.426245] dwc_otg: version 3.00a 10-AUG-2012 (platform bus)
[    2.426696] dwc_otg: FIQ enabled
[    2.426719] dwc_otg: NAK holdoff enabled
[    2.426733] dwc_otg: FIQ split-transaction FSM enabled
[    4.037631] systemd[1]: Set hostname to <pizero-otg>.
[   19.194164] dwc2 20980000.usb: DWC OTG Controller
[   19.195087] usb usb1: Product: DWC OTG Controller
[   19.195110] usb usb1: Manufacturer: Linux 5.10.92+ dwc2_hsotg

https://raspberrypi.stackexchange.com/questions/271/can-i-use-raspberry-pi-as-a-usb-peripheral-device#:~:text=Yes%20you%20can%20if%20you,class%20you%20want%20to%20implement.

Raspi A/B は OTGが無効になってる。

理由として、OTGの先にハブが接続されていた場合。 ここから想像するに、Zero にハブをいれたらOTGが無効になるのではないか

rasberry PI A/A+/B/B+ models have OTG mode disabled by variety of reasons:

  • USB port occupied with USB hub (ethernet),
  • missing OTG 5th pin (grounded), or
  • data pins are not connected (power port). You’d need Raspberry PI Zero for OTG or so called Gadget Mode. Data USB port can be used for OTG and “power”. As of time of this writing Serial and Ethernet were tested, but others should work with proper amount of efforts (keyboard, disk, camera, etc.) Composite devices should work as well. See more info at

ドングル化しているばあい、USBハブを開いてるからと繋いだら面倒くさい。

今回使った商品

参考資料

スタートメニューから検索できなくったWindowsを治す

プログラムがみつからないです・・・

プログラムがみつからないです・・・

スタートメニューから、Win-S(Cortana/Win search)からアプリを探しても何もありません。こんな状況初めてです。

Google Chrome もみつからないです・・・

再起動したら治った。

なんでかわからないが、再起動したら治った。

service.mscwindows インデックスを再起動したけどだめだった。

Explorer再起動(デスクトップ再起動・再ログイン)で治った。

Windowsってほんとに不思議なOSですね。

コントロールパネルを「コマンドから開く」、ネットワーク詳細を「コマンドから開く」

コントロールパネルをサクッと開きたい。

コントロールパネルは、とても簡単に開けます。

Windows10からコントロールパネルの設定が遠くなったので手軽に開く方法として覚えておく。

Win-Rから "control"

control をコマンドとして入れれば、すぐに開く。しかも覚えやすい。

開いた

ネットワーク詳細(接続)を開くncpa.cpl

ネットワークの接続画面を開くとき、コマンドプロンプトから開きたい

ネットワークの接続詳細は、よく使う割に、設定から開くのがめんどくさい。

Win-R から ncpa.cpl

ncpa.cpl でサクッと開く。

開いた

アドレスバー

Win-Rで呼び出さなくても、アドレスバーから同じことができる。

mac os で npm i がgyp エラーになるときのサクッとした対応

npm i がエラーになる

npm は利用しているmac のバージョンを見ていて、npm は該当のpython を呼びに行く 私の場合、最新版のmacOSはなるべく使わないことにしているので、python2 がないと怒られた。

takuya@~$ npm i
npm ERR! code 1
npm ERR! gyp verb check python checking for Python executable "python2" in the PATH
npm ERR! gyp verb `which` failed Error: not found: python2
(snip)
npm ERR! gyp ERR! stack   File "<string>", line 1
npm ERR! gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
npm ERR! gyp ERR! stack                       ^
npm ERR! gyp ERR! stack SyntaxError: invalid syntax

mac brew 環境での npm i の gyp 環境のエラーは、殆どの場合python パスのエラー

対応

python のバージョンを変えてあげる

pyenv local system
npm i

または、python2 を作ってあげる

ln -sr /usr/bin/python2.7 /usr/local/bin/python2

npm をどうやって入れたかによる。

再度インストール

rm node_modules/ -rf
npm i

node_modules に中途半端なコンパイルが残るので一回消しておくほうが無難。

それでもだめな場合

node のバージョンと、npm のバージョン、そしてパッケージのバージョンを見直す

要は、package.json に記載されたバージョンが古いままで、いまのnodeだとコンパイルが通らないとかある。

たとえば、node-sassの4.0x は最新のnodeだとインストール時にエラーになる。

npm -i # エラー(package.json が4 を指してる)
npm -i node-sass@4  # エラー
npm -i node-sass@6  # インストールできる

またはその逆で、nodeを古い方にあわせる

brew install node@14
brew unlink node
brew link node@14 --force-overwite 
npm i 
brew unlink node@14
brew link node

ruby gems をユーザ空間にインストールする

ユーザ空間を使う

sudo とかつかってグローバルを汚したくないし、bundler でプロジェクト単位にインストールも不便ってとき。

自分のユーザ空間の環境があるって最高ですよね。

ユーザ空間にgem をインストール

gem install --user-install PKG_NAME 

たとえば、nokogiri の場合

gem install --user-install nokogiri

また、この設定は、rbenv などでも使われていて普段意識することはないと思います。

デフォルトインストール先

現在の gem 環境設定を調べればいい

$ gem environment

私の場合は次のとおりだった。rbenv とruby-buildがあるのでちょっと複雑。

takuya@Desktop$ gem environment
RubyGems Environment:
  - RUBYGEMS VERSION: 3.1.2
  - RUBY VERSION: 2.7.1 (2020-03-31 patchlevel 83) [x86_64-darwin18]
  - INSTALLATION DIRECTORY: /Users/takuya/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
  - USER INSTALLATION DIRECTORY: /Users/takuya/.gem/ruby/2.7.0
  - RUBY EXECUTABLE: /Users/takuya/.rbenv/versions/2.7.1/bin/ruby
  - GIT EXECUTABLE: /usr/local/bin/git
  - EXECUTABLE DIRECTORY: /Users/takuya/.rbenv/versions/2.7.1/bin
  - SPEC CACHE DIRECTORY: /Users/takuya/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Users/takuya/.rbenv/versions/2.7.1/etc
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-darwin-18
  - GEM PATHS:
     - /Users/takuya/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
     - /Users/takuya/.gem/ruby/2.7.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
     - :sources => ["http://rubygems.org/"]
     - "benchmark" => false
     - "gem" => "--no-document"
     - "install" => "--no-ri --no-rdoc"
     - "update" => "--no-ri --no-rdoc"
  - REMOTE SOURCES:
     - http://rubygems.org/
  - SHELL PATH:
     - /Users/takuya/.rbenv/versions/2.7.1/bin
     - /usr/local/Cellar/rbenv/1.2.0/libexec
     - /Users/takuya/.rbenv/shims
     - /Library/Frameworks/Mono.framework/Versions/Current/Commands
     - /Users/takuya/.composer/vendor/bin
     - /Users/takuya/.lib/node/bin
     - /Users/takuya/.rbenv/shims
     - /Users/takuya/.pyenv/shims
     - /usr/local/share/dotnet
     - /Users/takuya/.go/bin
     - /Users/takuya/.bin
     - ~/.dotnet/tools
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/libexec
     - /opt/X11/bin
     - /usr/sbin
     - /usr/bin
     - /sbin
     - /bin

参考資料

phpstorm で scss-lintを行う

phpstorm でSCSSをチェックする

SCSSファイルを開くと、Lintの設定をレコメンドされる。配布元 →GitHub - idok/scss-lint-plugin: SCSS Lint plugin for intellij

ちなみにscss lint には npm もある。最近はnpmを使うことが多いハズ。そしてさらに最近はDartSassになってるはず。

ただし、このプラグインは設定が古いため、ruby 版を使うことになっている。

phpstorm のプラグインruby 版を想定してるので、想定通りに動かしてあげる。

私は更に想定して、古いバージョンのruby を使ってインストールしておいた。

scss-lintのインストール

gem install --user-install scss-lint

実行結果

Fetching scss-lint-0.38.0.gem
Fetching sass-3.4.25.gem
Fetching rainbow-2.2.2.gem
WARNING:  You don't have /Users/takuya/.gem/ruby/2.7.0/bin in your PATH,
      gem executables will not run.
Successfully installed sass-3.4.25
Building native extensions. This could take a while...
Successfully installed rainbow-2.2.2
WARNING: `scss-lint` has been renamed to `scss_lint` to follow proper RubyGems naming conventions. Update your Gemfile or relevant install scripts to install `scss_lint`.
Successfully installed scss-lint-0.38.0
3 gems installed

インストールされた場所

takuya@Desktop$ ls /Users/takuya/.gem/ruby/2.7.0/bin
sass  sass-convert  scss  scss-lint

設定

phpstorm などで、SCSSで設定を検索し、上記のパスを入れてあげる。

無事に動作した。

参考資料