tp-link Archer BE400(WiFi7)

Amazon プライム感謝祭先行セールで安くなっていたのでtp-linkのArcher BE400(WiFi7)を買ってみた。12,280円なり。色々言われてるtp-linkですが、もういいかなと思うくらい素晴らしいい。

今まではRTX1210 + Archer C4000(WiFi5)で使っていたのだが、RTX1210が頻繁にオーバーフローを起こしていてちょっとパワー不足な感じでした。結構、CPUを80%以上使っちゃってるのでmap-eって重いの?

RTX1210を使っていたのはSNMPでいろいろ情報が取れるからなのですが、速度が出ないので本末転倒なので。。。

今回はインターネット接続もWiFiもBE400にまとめました。ポート数が足りないのと、せっかく2.5Gbpsのポートがるので、以前買って使ってなかった、FOXNEO 2.5gbps スイッチングハブに繋いでみました。

優先接続の速度比較

RTX1210 + PC(1G接続)

最高速度が改善しているようです(^_^)

無線接続の比較

RTX1210 + Archer C4000(WiFi5) + iPhone 16
Archer BE400 + iPhone 16

無線も回線速度分出ているようです。しかしパケットロスが20.3% !?使ってる感じ特に不具合は感じないのですが、この数値ほんとか?

まぁ、しばらく使ってみます。

それと、Archer BE400はトラフィックレポート機能があります。SNMPには対応してないけどまぁ、これで十分かも。

OCI Standard.A1.Flexを試す

OCI無料枠で試していたのですが、いつまでたってもA1-Flexシェイプが立ち上がらないので、有償プランに切り替えました。有償プランに切り替えたからと言ってAlways Free枠は変わらないので実質、料金は発生しません。

有償(個人)にアップグレードしたらA1.Flex 4core 24GBメモリのインスタンスがサクッと立ち上がりました(笑)

という訳で、早速ベンチマークをしてみました。

素晴らしい! Standard.E2.1.Microの20倍! GCP e2-microの72倍のパワー \(^_^)/

System Benchmarks Index Score OCI Standard.A1.Flex 4ocpu 24GB Memory: 5512.4
OCI Standard.E2.1.Micro 1/8ocpu 1GB Memory: 268.1
GCP e2-micro 0.25vCPU 1GB Memory: 76.3

BYTE UNIX Benchmarks (Version 6.0.0)

   System: a1-test: GNU/Linux
   OS: GNU/Linux -- 6.14.0-1009-oracle -- #9~24.04.1-Ubuntu SMP Mon Jun 30 18:20:41 UTC 2025
   Machine: aarch64 (aarch64)
   Language: en_US.utf8 (charmap="ANSI_X3.4-1968", collate="ANSI_X3.4-1968")
   CPU 0: ARM Neoverse-N1 (50.0 bogomips)
          CPU Features: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
   CPU 1: ARM Neoverse-N1 (50.0 bogomips)
          CPU Features: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
   CPU 2: ARM Neoverse-N1 (50.0 bogomips)
          CPU Features: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
   CPU 3: ARM Neoverse-N1 (50.0 bogomips)
          CPU Features: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
   07:22:19 up 15 min,  1 user,  load average: 0.19, 0.08, 0.03; runlevel Sep

------------------------------------------------------------------------
Benchmark Run: Fri Sep 19 2025 07:22:19 - 07:50:14
4 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       46864852.7 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     8586.2 MWIPS (9.9 s, 7 samples)
Execl Throughput                               3146.3 lps   (29.8 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks       1137974.0 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          320778.0 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       2427991.5 KBps  (30.0 s, 2 samples)
Pipe Throughput                             1814774.8 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 101618.6 lps   (10.0 s, 7 samples)
Process Creation                               5683.8 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   9340.7 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   3161.0 lpm   (60.0 s, 2 samples)
System Call Overhead                        1403721.6 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   46864852.7   4015.8
Double-Precision Whetstone                       55.0       8586.2   1561.1
Execl Throughput                                 43.0       3146.3    731.7
File Copy 1024 bufsize 2000 maxblocks          3960.0    1137974.0   2873.7
File Copy 256 bufsize 500 maxblocks            1655.0     320778.0   1938.2
File Copy 4096 bufsize 8000 maxblocks          5800.0    2427991.5   4186.2
Pipe Throughput                               12440.0    1814774.8   1458.8
Pipe-based Context Switching                   4000.0     101618.6    254.0
Process Creation                                126.0       5683.8    451.1
Shell Scripts (1 concurrent)                     42.4       9340.7   2203.0
Shell Scripts (8 concurrent)                      6.0       3161.0   5268.4
System Call Overhead                          15000.0    1403721.6    935.8
                                                                   ========
System Benchmarks Index Score                                        1551.3

------------------------------------------------------------------------
Benchmark Run: Fri Sep 19 2025 07:50:14 - 08:18:11
4 CPUs in system; running 4 parallel copies of tests

Dhrystone 2 using register variables      187363319.6 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                    34304.4 MWIPS (9.9 s, 7 samples)
Execl Throughput                               9255.9 lps   (29.8 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks       4417831.3 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks         1283904.0 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       7855700.9 KBps  (30.0 s, 2 samples)
Pipe Throughput                             7317913.7 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 962856.6 lps   (10.0 s, 7 samples)
Process Creation                              20808.0 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                  26487.7 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   3423.5 lpm   (60.0 s, 2 samples)
System Call Overhead                        5606134.9 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0  187363319.6  16055.1
Double-Precision Whetstone                       55.0      34304.4   6237.2
Execl Throughput                                 43.0       9255.9   2152.5
File Copy 1024 bufsize 2000 maxblocks          3960.0    4417831.3  11156.1
File Copy 256 bufsize 500 maxblocks            1655.0    1283904.0   7757.7
File Copy 4096 bufsize 8000 maxblocks          5800.0    7855700.9  13544.3
Pipe Throughput                               12440.0    7317913.7   5882.6
Pipe-based Context Switching                   4000.0     962856.6   2407.1
Process Creation                                126.0      20808.0   1651.4
Shell Scripts (1 concurrent)                     42.4      26487.7   6247.1
Shell Scripts (8 concurrent)                      6.0       3423.5   5705.9
System Call Overhead                          15000.0    5606134.9   3737.4
                                                                   ========
System Benchmarks Index Score                                        5512.4

これが無料ですからね。暇を見てサーバ引っ越そうかな 🙂 難点は、x86アーキじゃないのでバイナリ互換ないんですよね。設定はほぼ引き継げると思うけど。作ってデータ移行が必要だからちょっとめんどい。

UGREEN NASync クラウドバックアップ

はじめに

QNAPからUGREENに乗り換えてそんなに困ってないというか、結構気に入っているのですが、最大の問題がバックアップの弱さでした。 QNAPではHBS3という強力なツールでNASのデータをAmazon S3などのクラウドストレージにバックアップできたのですが、UGREENにはそういう機能はありません。

という訳で、dockerで実現してみました。 docker最高!

方針

  • 利用するツールはbackrest
  • 保存先はAmzon S3 Standard
  • Amazon S3ではライフサイクルポリシーで7日後にDeepArchiveに移動する

いろいろ検討した結果、resticというツールが良さげです。resticは重複排除や圧縮に対応しているのにOSSという素晴らしさ。resticを使ったdockerコンテナも複数公開されているのですがその中でも、WEBUIで操作できるbackrestを使うことにしました。

インストール

  1. Dockerアプリのプロジェクトから「作成」を選んでプロジェクト名(backupなど)、保存パス(デフォルトでOK)、Compose設定に以下のYAMLファイルを貼り付けて「今すぐデプロイ」
version: "3.8"
services:
  backrest:
    image: garethgeorge/backrest:latest
    container_name: backrest
    hostname: backrest
    ports:
      - "9898:9898"              # 外部アクセス用
    volumes:
      - ./backrest/data:/data
      - ./backrest/config:/config
      - ./backrest/cache:/cache
      # バックアップ対象フォルダ
      - /volume1:/volume1:ro   
      - /volume2:/volume2:ro
    environment:
      - BACKREST_DATA=/data
      - BACKREST_CONFIG=/config/config.json
      - XDG_CACHE_HOME=/cache
      - TMPDIR=/tmp
      - TZ=Asia/Tokyo
    restart: unless-stopped
  1. コンテナが立ち上がってきたら、WEBUIにアクセス(Dockerアプリのコンテナでbackrestを選んで→マークからクイックアクセスが楽)して、初期設定
 Instance ID: なんでもいいですが(dxp2800とか)
 User: なんでもいいけど(hogeadminとか)
 Password: 強いの付けてね
  1. Add Repoでリポジトリ設定(前提として先にAWS上にS3バケットを作っておく必要あり。あと、アクセスキーを発行しておく必要あり)
 Repo Name: S3とか
 Repository URI: s3:s3.us-east-1.amazonaws.com/<バケット名> ※S3 URIではないので注意。私はコストが安いus-east-1を使ってる
 Password: Generateで作ればOK
 Env Vars: 環境変数をいくつか追加
   AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEYは最低必要。
   私はAWS_STORAGE_CLASS=STANDARD_IAも入れてる
その他の設定は変える必要なし
  1. Add Planでバックアップ対象を追加
 Plan Name: nas backupとか
 Reposotory: さっき作ったリポジトリ名 S3とか
 Paths: ここにバックアップしたいパスを足していく
  私は /volume1/@homeとかdockerとか。
 Backup Schedule: 私はCron、Local、Every mounth on 1 at 2:00にしてます。差分取れるので毎日とってもいいけど。

これでOK。作ったプランのBackup Nowで試し取りしておくと良いでしょう。

最後に、docker/backup/のファイルは別途どっかにちゃんと保存しておきましょう。設定したパスワードが分らないとデータ復元できません。。。

以上

### 2025/10/3 追記
デフォルトでRepositoriesポリシーで月1回のPrune(削除)とCehckがスケジュールされているのだが、Checkは実際にS3のデータを読みに行くようで、ライフサイクルポリシーでDeep Archiveに送ってしまうと、失敗する。必ずCheckを実施しないといけないのか?というと、まぁ保険なので実施しないことにしました。削除は、Deep Archiveに送られていても問題なくできるようです。

UGREEN NASync DXP2800省エネチューン

チューンって程のことはないのですが、パフォーマンスが上がる確かめるためにNVMe SSDをキャッシュとして追加してみたのですが、安物のgen3 x2レーンではHDDと大差なかったので、dockerのバックエンドストレージとして分離しようと思います。

【プール分け】

  1. HDD コールドプール(Volume1) – 基本的にはユーザーホームなのでユーザーが使わなければアクセスされない
  2. SSD ホットプール(Volume2) – dockerなど常にアクセスするもののバックエンドとして利用。基本アプリはこちらに入れることにする

インストール済みのアプリや、dockerコンテナを移動するには基本入れ直しが必要です。写真アプリなんかはインデックスが消えそうで嫌だったのと、そもそも写真はHDDに入ってるので移動しませんでした。DockerとHome Assistant以下の通り。それ以外はアンインストールとインストールの繰り返しでOK。

【Dockerの移動】

  1. コンテナを全部止める
  2. docker内のファイルを全て適当な場所にへコピーする
  3. docker-composeの内容をメモっておく(まぁ、同じフォルダをしていると出てきますけど念のため)
  4. dockerアプリ削除(HomeAssistantアプリも同時に削除される)
  5. dockerフォルダーを削除する(これをしないとVolume1に再度作られてしまうようだ)
  6. Volume2を指定してdockerアプリインストール
  7. 退避したdockerディレクトリのファイルを新たに作成されたdockerフォルダ内にコピーする
  8. 管理 – データ移行(コンテナインスタンスは移行されない)
  9. HomeAssitantアプリをVolume2/docker/homeassistantのフォルダを指定してインストールする(これでHomeAssitantは元通りに動くはず)
  10. その他のコンテナもdocker-composeで再生成

余談ですが、dockerは共有フォルダーに出てくるdockerフォルダーと@dockerというシステムが勝手に作るdocker動作に必要なフォルダがあります。dockerをアンインストールすると、@dockerは削除されますが、特にコピーしておく必要はなさそうです。もしかしたらローカルリポジトリに自前のコンテナを置いてる場合はコピーしておいた方がいいかも。

結果

常時28W程度食っていたものがHDDがアイドル停止するようになって12Wまで下がりました。静かだし。 🙂

たった16W削減ですが、1か月に換算すると 11.5kWhも減るんですよね。今、kWhあたり35円程度なので、403円/月の削減ですね(^_^)

実はそれ以外にも、RTX810からRTX1210に変更したのを機に、SWX2200-8Gと2.5GのHUBの電源も普段落としています。私の用途では2.5Gbps必要なことなんて滅多にないので。その結果、常時稼働しているものが48W程度ほどに下がり、全体で25W減、月額にして630円/月の削減となりました。

Home Assistant on UGREEN NASync DXP2800

はじめに

UGREEN NASync DXP2800を購入して、アプリセンターにHome Assistantというものがあって初めて知ったのですが、これ優れものですね!

https://www.home-assistant.io

Home AssistantはOSSでIFTTTのようなことをローカルで実現します。Raspberry Piなんかで実装してる人が多いようです。

Home Assistantはdockerコンテナとしても提供されていて、UGREEN NASync DXP2800ではそれを使ってアプリとして提供しているようです。なので、NASyncではアプリをインストールするだけで使えます。

iPhoneやAndroid用のアプリも出ていてとても使い勝手がいいのですが、ローカルで動いているのでVPNなどで自宅にアクセスする必要があります。(クラウドサービスもあるのですがそれは有償です)

私は前に書いた、TailScaleで自宅に接続して使っています。

私は今まで、主にSwitchBot + Amazon ALEXAでエアコン制御なんかをやってたんですが、HEMSやEcoFlowの電池なんかとの連携はできませんした。それぞれ違う規格で動いているためです。それがHome Assistantを使うことでかなり連携可能になります。

ECHONET Lite Matter IFTTT Alexa GoogleHome CloudEdge Home Assistant
Panasonic AiSEG2 × × × × × 〇*1
Panasonic ホームユニット VL-HB1000-W × × × × × × ×
QCELLS 太陽電池 × × × × × × 〇*1
SwitchBot × ×
EcoFlow Delta2 × × × × × × 〇*1
TP-LINK tapo × ×
RATOC RS-WFIREX3 × × × 〇*1
監視カメラ(COOAU) × × × × × ×

*1 カスタムコンポーネント導入で可能

例えば、HEMS Panasonic AiSEG2から発電、使用電力を取得して余力がある時だけ何をを実行といったオートメーションが組めるようになります。

今回実現したこと

  1. Panasonic AiSEG2(HEMS)から発電量と消費量を取得して発電余力を求める
  2. 余力がある時にEcoFlow delta2を充電する
  3. 夜間充電した電力でサーバを稼働させる
  4. この一連のサイクルをオートメーション化する

はい。できました(笑)

iPhone Home Assistant

iPhoneのHome Assistantアプリからアクセスするとこんな感じです。

実現方法

Home Assistantがあらかじめ対応している機器に関しては何もしなくても認識させられるのですが、残念ながら日本ローカルの AiSEG2は対応していません。そういう時はカスタムコンポーネントというのを作ることによって自由に機能を追加できます。AiSEG2から現在の発電量等を抜いてくるコンポーネントは無かったのでchatGPTさんにお願いして作りました(笑)

https://github.com/realktmr/hass_aiseg2_solpwr

GitHubを使ったのもPyhonでプログラムを書いたのも初めてだったのですが、AI素晴らしいですね。chatGPTとGeminiさんに教えてもらいながら作ってみました。

インストール方法

  1. GitHUBからCode -> Download ZIPでファイルを全部ダウンロードする。
  2. Home Assistantのconfigディレクトリにアサインしたフォルダにcustom_components/aiseg2_solpwrごとフォルダもファイルも置く。
  3. Home Assistantの設定-> … -> Home Assistantを再起動で再起動する
  4. 上がってきたら設定 -> デバイスとサービス から +統合を追加 を選んで、AiSEG2 Solar Powerを探して追加。IP、Username(aiseg固定)、Password(あなたがつけたもの)を入力して追加

これで、「発電量」「消費量」「余力」が出ているはずです。

EcoFlow delta2へのアクセスは Ecoflow-Cloudというカスタムコンポーネントが公開されており、これを使うことで簡単にアクセスできます。

EcoFlowアプリでも手動で設定できる【エネルギー管理】-> 【バックアップ予約】を有効にして、電池を利用するレベルを設定できます。例えばこの設定を20%に設定すると、入力ACプラグを挿していてもバッテリー残量が20%になるまで、電池から出力してくれます。20%を切ると充電を開始します。が20%まで充電するとパススルーでAC入力から出力します。

この機能を利用して、以下のようなオートメーションを組んでいます。

【前提】 DELTA2のエネルギー管理設定で充電限度 90%、放電限度 10%に設定。

【充電開始】 発電余力が 1.0kWhを超えたとき、Delta2のBackup Reserve EnabledがONだったらBackup Reserve EnabledをOFFにする。(これによって90%までAC入力から充電されるようになる)

【放電開始】 18:00になった時、DELTA2のMain Battery Level が80%以上あったら、Backup Reserve EnabledをONにしてDELTA2の Backup Reserve Level を 20%に設定にする(これによって、20%までは電池から放電する。20%を下回ったら20%まで充電する。しかし基本的には20%の時点でパススルー運転になるので次の日の充電開始までパススルー運転を実現している、ちなみに、OFFにしてONにするとデフォルトの50%に戻ってしまうようだ。また、ONにしてからじゃないとReserve Levelの設定ができない)

はい。これで太陽光発電の余力を使って充電し、DELTA2を普段使いするといった使い方が実現できました 🙂

蛇足

本当は、余力が0を切ったら電池から放電って設定にもできるのですが、これをやると頻繁に電池運転に切り替わり、そのたびにリレーがカチカチ切り替わりなんか壊れそうな気がして(笑)

蛇足ですが、DELTA2はUPSではないので電池出力とACパススルーの切り替えに時に数ミリ秒切れてしまうのでPCなんかは電源落ちてしまいます。私はもともと使ってたAPCのRS550というUPSを嚙ましているので問題はないですが、それでも頻繁な切り替えは寿命を著しく縮めると思います。

そんな訳で、ちょっと妥協したオートメーションを組んでいますが、まぁ、十分かと。

他に、NASyncを置いてる部屋の温度計と連携して部屋の温度が32℃を超えたら自動でエアコンを掛けて30℃を下回ったら止めるオートメーションを組んだり。電力余力がなくなったら、29℃以下だったらエアコンを止めるオートメーションを組んだり。いろいろできるかと。

面白い使い方を思いついたらぜひ教えてください。

ポート開放が要らないVPN

背景

自宅回線をMoneyForwd 光に変更した結果、v6Plus接続になりダイナミックDNS等でのVPN接続は難しくなったしまったので、別の方法を探していました。

やりたいこと

  • 自宅のHEMSなどにiPhoneからアクセスしたい
  • UGREEN NASyncのdockerコンテナで実現したい

TailScale

探した結果、TailScaleというサービスがあることを知りました。イメージとしてはクラウド上にあるルーターにVPN接続したい機器がVPNを張りに行ってそこでルーティングしてもらう感じですね。なので、OUT方向が通れば固定IPやポート開放ができなくてもOKです。

TailScaleはPersonalプランという無償プランがあります。 3 Users 100 Devicesまで無料というなんとも太っ腹なサービス! 素晴らしい(笑)

早速やってみる

  1. iPhoneでTailScalアプリをダウンロード
  2. 新規にアカウント作成してVPN接続!
  3. PCからTailScalの管理ページに入りSettings -> Keysで Auth KeysをGenerate Auth keyをポチっとと押してキーを払い出しコピーしておく
  4. UGREEN NASyncでdockerアプリからプロジェクト作成で適当なプロジェクト名(vpnなど)と保存パス(docker様にアサインした共有フォルダがいいでしょう)を指定して、以下の内容をCompose設定に記載して今すぐデプロイ!
version: "3.8"

services:
  tailscale:
    image: tailscale/tailscale:latest
    container_name: tailscale
    hostname: nasync
    network_mode: "host"
    privileged: true
    volumes:
      - /var/lib:/var/lib
      - /dev/net/tun:/dev/net/tun
    environment:
      # Tailscale 管理画面で作成した AuthKey を入れる
      - TS_AUTHKEY=tskey-auth-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      # LAN 全体 (192.168.1.0/24) を iPhone に広告
      - TS_EXTRA_ARGS=--advertise-routes=192.168.1.0/24
    restart: unless-stopped
  1. TailScaleの管理ページからMachinesを見ると、iPhoneとnasyncが繋がってるはず!nasyncの…からEdit route settingsを選んで目的のサブネットにチェックを入れて保存すればそのサブネットに行けるようになります。

Machines Edit Route Settings

超簡単で素晴らしい!(^_^)/

HP ProNote Aero G8 Bluetoothが見えなくなる

原因は定かではないのですが、Windows 11 24H2累積更新(KB5062553)を適用したあたりからBluetoothホストが完全に見えなくなり、一切のBluetoothが使えなくなりました。

とりあえず、BIOSで有効になっているかの確認をしたり、HP System Diagなど掛けたりした結果、いつの間にか見えてました。。。(恐らく、タイミング的にはSystem Diagだと思います。詳細モードでテストした結果オールクリアでした。)

まぁ、釈然としないですが、以前にもUSB給電での充電ができないという問題があったなぁ。。。

HP ProBook 635 Aero G8でtype-c給電できない | Lamb EDEN

SoftBank光からマネーフォワード光に乗り換えた話

値上がりを機に脱SoftBank完了です。移行先はMoneyForward光という家計簿サービスマネーフォワードのコラボ回線で USEN NETWORKSが運営しているUSEN光01というサービスのコラボ商品です。PPPoEは払い出さず、v6プラスのみの提供にある代わりに戸建てで税込み4950円しかもMoneyForward MEのプレミアムサービス・スタンダード(月額500円)が無料になるという私にとってはとても嬉しいサービスです 🙂

切り替えすったもんだ

切り替えは以下の手順で進んでいくんですが、切り替え当日、SoftBank光が終了せず、USEN側の作業が進まずビビりました。。。

  1. MoneyForward光に仮申し込みする
  2. SoftBank光に事業者変更承諾番号を発行してもらってUSENに連携
  3. 当日にSoftbankのモデムを外しておく?(これが必要?私は繋いだままだったらいつまで経っても切り替わりませんでした。。。)
  4. SoftBankのユーザページ(解約手続きすると開設される)でステータスを確認
  5. ルーターの再起動(IPv6アドレスが変わるのでrenewコマンド叩くか、まぁ、再起動した方が楽)

以上

速度は?

SoftBank光PPPoE接続( 7/31 19:00ごろ)
MoneyForward光(USEN光01) (8/1 20:00ごろ)

MoneyForward光の方が微妙に遅い気もするけど、まぁ、誤差レベル?これで、MoneyForward料金込みだと月千円くらい下がるなら全然いいです。しかし、なんでISPがauとでてるんだろう?昔auのアドレス空間だったとかですかね。まぁ、そもそもJPIXのv6プラスサービス使ってるのでJPIXのIPな気がしますが。

注意点

MoneyForward光はv6プラス形態の接続です。ユニークGlobalはアサインされず、ポート番号をいくつか割り振られる感じのようです。なので、公開サーバとかしたい人には向かないです。

ちなみに、UGREEN NASはUGREEN Linkサービスを使えば普通に使えます 🙂

QNAP TS-230 to UGREEN DXP2800 番外編

前回の記事で書いていたHEIC写真とJPGファイルの重複を何とかできないものかとNASyncの重複写真・類似写真検索やPCツールのDupFileEliminatorなどを試した見たのですが、検出されなかったので、chatGPTに相談した結果、何度かやり取りをした結果スクリプトが完成しました(^_^)/

ただし、もっと簡単な方法はUGREENが取ったバックアップからQNAP QuMagieでバックアップしていた日以前のHEICファイルを消してしまうことです。そうすれば、それ以前のデータはJPGで残っているわけですが重複は発生しません。まぁ、これが一番楽だと思います。

今回は、HEICとJPGの同じ写真を同じ写真として区別できるのかをテーマに実験してみました。

Pythonを使ったプログラムなのですが、Windows版Pythonだと HEICの処理がうまくいかなかったのでWSLのUBUNTU 22.04上で実行しました。

一発で目的の物が出てくることは稀ですがうまくいかない場合はエラー内容などをChatGPTに伝えれば対策を教えてくれます。素晴らしい。

方針

  1. 方針 HEICと JPG をハッシュ比較1して同じ写真を検出する
  2. 比較して同じ写真のペアを作る
  3. 確認用にファイルをコピー
  4. 人が確認して2問題なければ削除実施3

脚注

  1. フォーマットが違うのでハッシュ比較するために一旦、どちらの画像もPIL.Imageという形式に変換してハッシュを取っているようです。 ↩︎
  2. 比較用に./compare_outputフォルダにcompare.htmlと対象写真のコピーを作成してくれる仕様なんですが、写真が大きいので大量に読み込むとブラウザが固まってしまって使いもにならなかったので比較はExplorerで特大アイコンモードで見比べました。1つも間違ってませんでした。素晴らしい。 ↩︎
  3. 削除は比較スクリプトが吐き出したmatched_files.txtというリストをもとに削除します。 ↩︎
比較スクリプト
import os
from PIL import Image
import pyheif
import imagehash
from pathlib import Path
import shutil

# === 設定 ===
HEIC_ROOT = Path("<HEICファイルのパス>")
JPG_ROOT = Path("<JPGファイルのパス>")
OUTPUT_DIR = Path("compare_output")
MATCH_LIST_FILE = Path("matched_files.txt")
HASH_FUNC = imagehash.phash

# === 準備 ===
OUTPUT_DIR.mkdir(exist_ok=True)
heic_hashes = dict()
matched_pairs = []
heic_total = 0
jpg_total = 0
heic_errors = 0
jpg_errors = 0

print("🔍 HEICファイルをスキャン中...")
#print(f"📁 HEICルート: {HEIC_ROOT}")
#if not HEIC_ROOT.exists():
#    print("❌ 指定したHEICフォルダが存在しません。パスを確認してください。")
#    exit(1)
#else:
#    print("📂 HEICフォルダ一覧:")
#    for path in HEIC_ROOT.rglob("*"):
#        print("   ", path)

#for heic_file in HEIC_ROOT.rglob("*.heic"):
for ext in ["*.heic", "*.HEIC"]:
    for heic_file in HEIC_ROOT.rglob(ext):
        try:
            heif = pyheif.read(heic_file)
            image = Image.frombytes(heif.mode, heif.size, heif.data, "raw", heif.mode)
            h = str(HASH_FUNC(image))
            heic_hashes[h] = heic_file
            heic_total += 1
        except Exception as e:
            print(f"⚠️ HEICエラー: {heic_file} → {e}")
            heic_errors += 1

print(f"📸 HEIC読み込み成功: {heic_total} 件 / エラー: {heic_errors} 件")

print("📋 JPGファイルと照合中...")
for ext in ["*.jpg", "*.JPG"]:
    for jpg_file in JPG_ROOT.rglob(ext):
        try:
            with Image.open(jpg_file) as image:
                h = str(HASH_FUNC(image))
                if h in heic_hashes:
                    matched_pairs.append((jpg_file, heic_hashes[h]))
                jpg_total += 1
        except Exception as e:
            print(f"⚠️ JPGエラー: {jpg_file} → {e}")
            jpg_errors += 1

print(f"📸 JPG読み込み成功: {jpg_total} 件 / エラー: {jpg_errors} 件")
print(f"🔗 一致したペア数: {len(matched_pairs)}")

# === HTMLと画像出力 ===
html_lines = [
    "<html><head><meta charset='utf-8'>",
    "<style>body{font-family:sans-serif;} img{max-width:300px; margin:5px;} .pair{margin-bottom:40px;}</style>",
    "</head><body><h1>HEIC vs JPG 比較結果</h1>"
]

with open(MATCH_LIST_FILE, "w", encoding="utf-8") as f:
    for i, (jpg_path, heic_path) in enumerate(matched_pairs):
        base = f"pair_{i}"
        jpg_out = OUTPUT_DIR / f"{base}_jpg.jpg"
        heic_out = OUTPUT_DIR / f"{base}_heic.jpg"

        try:
            shutil.copy2(jpg_path, jpg_out)

            heif = pyheif.read(heic_path)
            heic_img = Image.frombytes(heif.mode, heif.size, heif.data, "raw", heif.mode)
            heic_img.save(heic_out, "JPEG")

            html_lines.append(f"<div class='pair'><h3>{base}</h3>")
            html_lines.append(f"<p><b>JPG:</b> {jpg_path}<br><b>HEIC:</b> {heic_path}</p>")
            html_lines.append(f"<img src='{jpg_out.name}' alt='JPG'>")
            html_lines.append(f"<img src='{heic_out.name}' alt='HEIC'>")
            html_lines.append("</div>")

            f.write(str(jpg_path) + "\n")
        except Exception as e:
            print(f"⚠️ 出力失敗: {jpg_path} / {heic_path} → {e}")

html_lines.append("</body></html>")
with open(OUTPUT_DIR / "compare.html", "w", encoding="utf-8") as f:
    f.write("\n".join(html_lines))

print(f"✅ 完了!{len(matched_pairs)} ペアを {OUTPUT_DIR}/ に保存しました。")
print("🖼 `compare_output/compare.html` をブラウザで開いて確認してください。")
print(f"📝 削除対象候補リスト: {MATCH_LIST_FILE}")

削除スクリプト

from pathlib import Path

MATCH_LIST_FILE = Path("matched_files.txt")
deleted = 0

if not MATCH_LIST_FILE.exists():
    print("❌ matched_files.txt が見つかりません。先に比較スクリプトを実行してください。")
    exit(1)

with open(MATCH_LIST_FILE, "r", encoding="utf-8") as f:
    jpg_paths = [Path(line.strip()) for line in f if line.strip()]

print(f"🗑 削除対象 JPG 数: {len(jpg_paths)}")
for jpg_path in jpg_paths:
    if jpg_path.exists():
        try:
            jpg_path.unlink()
            print(f"✅ 削除: {jpg_path}")
            deleted += 1
        except Exception as e:
            print(f"⚠️ 削除失敗: {jpg_path} → {e}")
    else:
        print(f"⚠️ ファイル存在しない: {jpg_path}")

print(f"✅ 削除完了: {deleted} 件")

まとめ

Python書けない私ですがChatGPTを使えば実用的なものができてしまうという素晴らしいですね。ただし、HEICとJPGではアルゴリズムの違いにより復元したRAWデータに差異が出てしまい完全には拾いきれず、結構違う写真として判断されてしまってるものが残ってしまいます。これは中々難しい問題です。まぁ、実用的には撮影情報からその日以前のHEICファイルを消した方が速いと思います(あるいは逆の方法でJPGを)

蛇足

何枚かHEICファイルじゃないってエラーが出たので調べてみたのですが、iPhoneの画像ファイルで.HEICなのにJPGなものがあるようです。iPhoneのBUG?

$ file IMG_xxxx.HEIC: ISO Media, HEIF Image HEVC Main or Main Still Picture Profile

$file IMG_yyyy.HEIC: JPEG image data, JFIF standard 1.01, aspect ratio, density 72×72, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=12, manufacturer=Apple, model=iPhone 12, xresolution=174, yresolution=182, resolutionunit=2, software=16.6, datetime=2023:09:11 15:33:46, hostcomputer=iPhone 12], baseline, precision 8, 4032×3024, components 3

さらに蛇足ですが、Pythonってループとかの構造を{}で囲ったりせず、インデントで判断するんですね。。。新鮮でした。インデントずれてたらエラーになったのでビビりました。

中華製無線802.11ahブリッジを買ってみた

我が家のガレージにはWiFiは届かない。まぁ、携帯電波は入るのでそれでもいいのだが。ふと、Amazonで900MHz帯のIEEE 802.11ah(Wi-Fi HaLowtm)を見つけたのでつい買ってしまった(笑)

早速、接続テスト

TXとRXと書いた見た目同じ箱が2つ。TXからRXを複数繋ぐこともできる様だ。設定は特に要らず、ただ電源とLANケーブル繋ぐだけ。今回はTP-LinkのRE200という中継器をAPとして繋いで測定しました。

結果、1F-2F間で普通にWiFi飛ぶ範囲なのにアンテナ強度「中」。

通信速度は下り 8.42Mbps、上り 7.53Mbps。理論値が16Mbpsなので、まぁ、こんなもんか。にしても1F-2Fはアンテナ強度「高」になって欲しかった。。。

で、問題のガレージへ。アンテナ強度「低」、写真撮り忘れた。。。速度は倉ぢ2.45 Mbps、上り1.47Mbps。まぁ、通信できてるっちゃできてるんだけど。

ちなみに、楽天モバイルでの通信はこんな感じです。

結論

まぁ、使えるっちゃ使えるけど、これ、7000円くらいするんだよね。。。あんまりコスパよくないかも。。。

徒然なるままに。。。