hsBoxで、ATOM Cam 2の映像をキャプチャしてNASに蓄積、さらにクラウドにアップロードする

先の記事「コンクリート劣化の原因調査」に関連して画像を撮影してアップロードする仕組みを構築しました。ここでは、構築までの手順を活用できる形で紹介していきます。事前準備がほぼ出来上がっているので意外と簡単に構築できました。

10分おきに自動更新している画像

※画像が更新されていない場合は、ブラウザキャッシュが効いていることがあります。F5キーで再読み込みするか、Ctrl+右クリックで画像を、別タブで開いてF5キーを押すと再読み込みされます。

キャッチ画像から作成した動画

動画化

このように、NASへの蓄積から動画生成や、クラウドへのアップロードも自動化できました。

使用した製品

10年前のノートPCで動いているhsBoxの他には、下の製品を使用して構築しています。

カメラ: アトムテック株式会社(ATOM tech Inc.) 製 ATOM Cam 2
https://www.atomtech.co.jp/products/atomcam2

NAS: BUFFALO 製 LS710D
https://www.buffalo.jp/product/detail/ls710d0101.html

camLS710D

実装方針、実装方法

できるだけ手間をかけず(つまりATOM Cam 2の改造など特殊なことはしない)、運用やhsBoxへの負荷も最低限になるように設計する。 ということで、hsBoxを使い10分間隔でrtspでATOM Cam2から画像を取得して、NASに保存、同時にクラウド上に送ることにしました。

事前準備

hsBoxに必要なライブラリが入っているかなど環境状況を確認します。 結果、必要なものはすべてこれまでの構築等でインストールされていることを確認しました。 インストールされていない場合インストールしてください。
※ 本記事内のRTSP URL、トークン、ユーザー名・パスワードはすべてダミーです。

■ATOM CAM2のrtspのURLを確認する
rtsp://<*user>:<*pass>@192.168.**.**/live ★


■hsBoxライブラリの確認
●FFmpeg (コマンドラインツール)
ffmpeg -version

●NFS / CIFS (NAS接続用ユーティリティ)
# インストールされているパッケージの確認
dpkg -l | grep -E 'nfs-common|cifs-utils'

●3. Python環境の確認
#hsBoxの制御コードを書くためのベースを確認します。
#Python はhsBoxで構築済みなので省きます

●マウントポイントの作成
#NASの画像を置くためのディレクトリをhsBox内に作成します。
#すでに作っていれば不要
sudo mkdir -p /mnt/nas_cam

●手動マウント
マウントは他の記事(proxy設定)も参考にしてください

アトムテックの製品のうち、rtspに対応しているのは公式にはATOM Cam 2のみです。ATOM Cam SwingやATOM Cam GPTは対応していないようです。 また、最初のころのATOM Cam2はrtspは公開されていなかったと記憶しています。ファームウェアバージョンにも依存するようです。対応状況やrtspのURL確認方法などの詳細はアトムテックのサイトを確認してください。

事前準備が終わったら、手動で画像が取れるか確認してみましょう。

ffmpeg -rtsp_transport tcp -ss 00:00:01 -i "rtsp://**:**@192.168.**.**/live" -vframes 1 -q:v 2 -y test_out.jpg

*マークの箇所は環境に合わせて修正してください。

これで、画像が撮れれば問題ありません。取れなければIPが変わっていないかなどネットワーク的な問題を確認・解決する必要があります。

 IPは動的に変わるので、MACからIPを確認する実装を組み込みます。そこで使用するMACアドレスを確認します。

# arp -a |grep 192.168.**.**
? (192.168.**.**) at 7c:dd:e9:**:**:** [ether] on enp1s0

MACアドレスが確認できました。 ここまで準備できればほぼ完成です。

サンプル実装(hsBox側実装)

★印の箇所は環境に合わせって設定してください。
コードは、Windows、hsBox (Linux) 共用です。
※ 実運用では、環境変数や設定ファイルを用いてコード外に分離してください。

import os
import subprocess
import sys
import re
import base64
from datetime import datetime

# --- 設定項目 ---
# Windowsで試す際は、ここをカメラのIP等に書き換えてください
#RTSP_URL = "rtsp://**:**@192.168.*.*:554/live"
# 確認したMACアドレスをここに(ハイフンでもコロンでもOK)
TARGET_MAC = "7c-dd-e9-**-**-**" # ★要更新
RTSP_USER = "**" # ★
RTSP_PASS = "**" # ★
# 保存先設定
# 保存先設定
#SAVE_DIR = "/mnt/nas_cam" if os.name != 'nt' else r"C:\temp\atom"
SAVE_DIR = r"\\192.168.**.*****" if os.name == 'nt' else "/mnt/nas****" # ★
#
url = "https://******.jp/**/upload.php" # ★ クラウドアップロードURL
token = "your_secret_token" # ★
#認証の情報
user = "*****" # ★
pass = "*****" # ★
# -----------------------
BASE_DIR = SAVE_DIR

def get_next_serial(BASE_DIR ):
counter_file = os.path.join(BASE_DIR , "counter.txt")

# 現在の番号を読み込む
if os.path.exists(counter_file):
with open(counter_file, "r") as f:
try:
count = int(f.read().strip())
except:
count = 0
else:
count = 0

# 次の番号を決定(0-199のリング)
next_count = (count + 1) % 200

# 更新して保存
with open(counter_file, "w") as f:
f.write(str(next_count))

return f"{count:03d}.jpg" # 000.jpg 形式

def upload_to_xserver(local_file_path, serial_name):
# ユーザー名とパスワードを結合してBase64エンコード
user_pass = f"{user}:{pass}"
auth_encoded = base64.b64encode(user_pass.encode('ascii')).decode('ascii')
# curlで「サーバー側の名前」を指定して送る # ★
cmd = [
'curl', '-s', '-X', 'POST',
#'--user', f'{basic_user}:{basic_pass}', # ここで認証を通す # ★
#'-H', f'Authorization: Basic {auth_encoded}', # ヘッダーで認証を通す # ★
'-F', f'image=@{local_file_path};filename={serial_name}',
'-F', f'token={token}',
url
]
subprocess.run(cmd)



def capture_with_auto_management():
ip = get_current_ip(TARGET_MAC)
if not ip:
print("Error: Camera not found.")
sys.exit(1)

# 1. 日付ごとのディレクトリ名を生成 (例: 2025-12-23)
today_str = datetime.now().strftime("%Y-%m-%d")
daily_dir = os.path.join(BASE_DIR, today_str)

# 2. ディレクトリがなければ作成
if not os.path.exists(daily_dir):
os.makedirs(daily_dir, exist_ok=True)

# 3. ファイル名の生成 (例: 20251223_183000.jpg)
filename = datetime.now().strftime("%Y%m%d_%H%M%S.jpg")
save_path = os.path.join(daily_dir, filename)

# --- ffmpeg実行部 ---
rtsp_url = f"rtsp://{RTSP_USER}:{RTSP_PASS}@{ip}/live"
cmd = [
'ffmpeg', '-rtsp_transport', 'tcp', '-i', rtsp_url,
'-ss', '00:00:01', '-vframes', '1', '-q:v', '2', '-y', save_path
]

try:
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True, timeout=20)
print(f"Saved: {filename} (via {ip})")
serial_name = get_next_serial(BASE_DIR )
upload_to_xserver(save_path, serial_name)
except Exception as e:
print(f"FFmpeg failed: {e}")


def get_current_ip(mac):
"""MACアドレスから現在のIPアドレスを特定する (Win/Linux共用)"""
target_mac_raw = mac.replace(":", "").replace("-", "").lower()

# --- 1. ARPテーブルの強制更新 (Linuxのみ) ---
if os.name != 'nt':
subprocess.run(["ping", "-c", "2", "-b", "192.168.*.255"], # ★
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

try:
# ARPテーブルを取得
res = subprocess.check_output(["arp", "-a"]).decode("cp932" if os.name == 'nt' else "utf-8")

for line in res.splitlines():
# 解析中の行からも記号をすべて消す
line_raw = line.replace(":", "").replace("-", "").lower()

# 純粋な英数字の並びでマッチング
if target_mac_raw in line_raw:
# 行からIPアドレス部分だけを抜き出す
match = re.search(r"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", line)
if match:
return match.group(1)
except Exception as e:
print(f"Network scan error: {e}")
return None

if __name__ == "__main__":
capture_with_auto_management()

NASの指定ディレクトリの下に日付ディレクトリを作成し、その下にファイルを蓄積していきます。
ファイル自動削除の実装はありません。
必要に応じて、WindowsのエクスプローラーやNAS管理画面から手動で削除してください。

 

■サンプル実装(クラウド側実装)

※ 本PHPコードは動作確認用の簡易実装です。
※ 実運用では、IP制限、HTTPS、拡張子チェック等の追加を推奨します。

<?php
//---★環境に合わせてアクセス制限等を追加してください
$token = "your_secret_token"; // 簡易認証用
if ($_POST['token'] !== $token) exit("Access Denied");

$save_dir = "/cam_images/";

if (!is_dir($save_dir)) mkdir($save_dir, 0755);

if (isset($_FILES['image'])) {
// クライアントが指定したファイル名(001.jpg等)で保存
$file_name = basename($_FILES['image']['name']);
move_uploaded_file($_FILES['image']['tmp_name'], $save_dir . $file_name);

// 常に最新を確認するための固定名コピーも同時に行う
copy($save_dir . $file_name, $save_dir . "latest.jpg");
echo "OK";
}

アップロードされたファイルをディレクトリに保存します。 アップロードする際に000~199の番号をシリアルでつけてアップロードしてくるので、それを上書き保存します。あふれることはないので削除は不要です。
 同時に、”latest.jpg”にコピーします。 latest.jpgに常に最新の画像が保存されます。

あとはcronに設定を追加するだけで、画像を蓄積し続けます。
cron設定についてはhsBox本家サイトの記事(hsBoxで作る“LAN監視システム・アラート”)を参考にしてください。

関連記事

温度測定、3か月以上の長期間ロギング環境の整備に向けて事前準備

先の「コンクリート劣化の原因調査」の検証のためのデータ採取の1つとして温度の情報を収集蓄積する。 4ポイント(壁3点と気温)を収集することにした。 4か所を収集蓄積し、リアルタイムでクラウド等に上げる仕組みの構築は比較的簡単そうではあるが、20万円程度かかる見込みとなった。そこで、リアルタイムでのアップロードはあきらめ、逐次データ吸い上げでアップロードする方式として、後述の構成で、6万円程度で環境整備を行うことにした。

測定方式と使用機器

 下の写真の通りTタイプ熱電対(100m分を用意)を使用し、ロギングにはT&D MCR‑4TC日本の T&D Corporation:4 チャンネル 熱電対データロガー)を利用することにした。


MCR-4TCの実物は次の通り

とりあえず、1ch分熱電対を作成して、1日分の外気温を測定してみました。10秒間隔で測定しています。PCから設定できるものもありますが、基本は本体で設定操作が必要です。特に、測定開始の操作は本体側の操作が必要でした。 PCソフトの画面構成的にはPC操作で測定開始できそうに見えますが、MCR-4TCでは使えない。

測定できそうな結果がえられたので、4ch分熱電対を作成しました。そして、下の写真のように氷水を使って0℃の測定精度チェックをしてみました。

下グラフは氷水を使ってのチェックしたときの結果です。コップ面に近い水は4℃程度までしか下がらない感じでした。中央の氷に囲まれた当たりがほぼ0℃に近い0.3℃くらいでした。

グラフの温度レンジが広すぎてあれですが、4chともにうまく測れています。測定点がここまで細かくとれると、この温度変化の動きでプラトー領域(※参考情報参照)を見ることで、凍結開始タイミングを確認できそうです。
MCR-4TCは1分間隔で4ch測定する場合、140日分ほどデータをロギングできるのでこの測定にはぴったりです。また、ロギングしながらデータを吸い上げることができるので、ほとんど切れ目なく測定し続けることができそうです。

参考情報

化学講座 第46回:凝固点降下
https://www.sidaiigakubu.com/examination-measure/chemistry/46/

冷却曲線と凝固点降下【高校化学】溶液の性質#6
https://www.youtube.com/watch?v=GKnf_UetCOg

10年越しの謎に挑む:なぜ壁は膨らんだのか?IT駆使で迫るコンクリート劣化の原因~この3年間の調査の締めくくりに向けて~

建築から約10年で徐々にコンクリート壁の表面にひび割れが入り膨らんできた。修復が必要だが、単純に表面を直しただけでは再発することが容易に想像できる。そこで、ダメージの根本原因の特定を目的として、原因についての仮説を立て妥当性の検討をした。残念ながら決め手となる証拠を得られず仮説の域を出ていない。そこで、明確に原因特定するためにITを駆使して温度やAEのデータを採取して検証することとした。

これまでの外観の変化、ストリートビュー&撮影記録より

2012年4月時点 (建築から3年後)↓ストリートビューより

2017年8月↓ストリートビューより

2018年4月↓ストリートビューより

2021年4月↓ストリートビューより

2024年11月↓ストリートビューより

2025年12月↓ 撮影

仮説と調査方法

壁面の中央からひび割れが入り始めて、左右上下に進行している状況と中央部を中心に膨らんでいることから凍結膨張が主要因と仮説を立てた。地震の影響も受けている可能性も考えられるが、地震であれば周辺部にも中央部と同様にひび割れがあってもおかしくはない。しかし、周辺部が起点のひび割れがないことから地震は主要因ではなく付加要因と推測した。
 凍結膨張(アイスレンズ)が発生する条件は、先人の研究結果(①凍結過程にある土中のアイスレンズ近傍の水分・熱移動、 ②土の凍上発生メカニズムについて、③土の凍上性評価手法に関する研究)などから、水分・温度・土粒子サイズの要因がそろうと発生することが知られている。本事例では水分と粒子サイズについては、過去の研究結果と合致している。3年前につぎの写真の通り床面に穿孔調査を行った。

土の粒子サイズは1mm以下を中心としている真砂土で、アイスレンズの影響を抑制できるほど大きいわけではない。また、一定期間穴に蓋をしていて、蓋を開けた直後の写真が次である。

蓋の内側には、多量の結露が発生していた。この結果から、多量の水分が存在していて、土は水分を透過するほど十分に大きいことが確認できた。これらより、水分と粒子サイズについては合致していると判断できる。

残るのは温度である。少なくとも外気温や一部の壁面は期間中に零下になったことが気象庁のデータおよび昨年計測した結果から確認できている。

推定される発生モデル
図1.推定される発生メカニズム


この発生モデルを確認するため、コンクリート壁内側の温度(複数個所)および外気温を測定する。また、内圧で破壊(コンクリート破砕音)を検知するAE(アコースティックエミッション)センサシステムを構築して破砕が発生するタイミングをとらえる方針です。 そして、外観の映像も記録していきます。

・撮影、動画化

上の通りカメラでの定点観測は運用開始済みです。
画像をアップロードする仕組みを構築しました。自動アップロードしている画像が見れる構築方法を記載したページはこちらです。→「hsBoxで、ATOM Cam 2の映像をキャプチャしてNASに蓄積、さらにクラウドにアップロードする https://mic.or.jp/info/2025/12/25/cam/」

・温度測定

4か所の温度をロギングする仕組みは用意できました。事前準備を行いました。→事前準備の結果はこちらです。 現在、仮設置を行った件の記事を準備中です。
その後、取得したデータ結果もアップロードする予定です。

・AE測定

準備中です。 部材発注済みです。 
ロギングしてクラウドに結果を自動アップする仕組みを構築する予定です。

まとめ

何からの結論が得られることを期待して進めていきます。それぞれのデータ採取に関するページは別途作成・公開予定です。

その他

みつけた抑制策
[参考資料] 凍害抑制に関する研究(JST)
https://shingi.jst.go.jp/pdf/2022/2022_kansai_004.pdf

2025年12月22日で太陽光発電 通知メールがなくなる件。 代替として自前で収集した情報をLINEに通知してみた

いよいよ「太陽光発電、 通知メールがなくなる」。さてどうしようか、2025/12/07時点で、一番下に添付したメールが朝9:00ころに届いている。これを、代替できるLINE通知する仕組みを作ってみました。 12/14に取得した結果は次の通り、ほぼ同じ結果で十分な結果と言えるでしょう。

自作したLINEでの表示例 と【フロンティアモニター】のレポート
下記の通り、2025年12月13日の発電量をお知らせいたします。

発電量:7.52kWh
下記の通り、2025年12月13日の電力量をお知らせいたします。

発電量:7.52kWh
売電量:0.28kWh
買電量:53.99kWh
今月の目標売電量(223kWh)に対して、28%達成しました。
今月の目標消費電力量(1,106kWh)に対して、641kWh消費しました。
下記の通り、2025年12月07日-2025年12月13日の電力量をお知らせいたします。

発電量:96.83kWh
売電量:31.50kWh
買電量:281.26kWh
今月の目標売電量(223kWh)に対して、28%達成しました。
今月の目標消費電力量(1,106kWh)に対して、641kWh消費しました。


実装方針

・従来の通知メールに含まれる発電量等の計測値データはすべて含める
・通知メールの種類はいくつかあるが、元データは1つなので、引数で送信メッセージの内容を切り替える
・CRONで起動指定する

この方針で、ここまでで作成した実装をベースに集計+メッセージ送信するスクリプトを作成します。まずは、iPython上で動作確認して、hsBox上に移植しました。
以下のスクリプトを /home/hsbox/pyd/power_report.py に配置し、後述の設定を行いました。

スクリプト実装(例 ★印の箇所は要更新)

# power_report.py
import pandas as pd
from datetime import datetime, timedelta
import os
import sys
import argparse
import requests

# ==================== 設定エリア ====================
NAS_PATH = r"/mnt/nas<★NASマウント+パス>" #★
IFTTT_WEBHOOK_URL0 = "https://maker.ifttt.com/trigger/{event}/with/key/{your_key}"
IFTTT_EVENT_NAME = "******" # IFTTTで作ったイベント名★
your_key="********" # ←ここを自分のものに変更★
IFTTT_WEBHOOK_URL = IFTTT_WEBHOOK_URL0.replace("{your_key}", your_key)
# ====================================================


def send_line_message(title: str, body: str, timestamp: str):
payload = {
"value1": title,
"value2": body,
"value3": timestamp
}
url = IFTTT_WEBHOOK_URL.replace("{event}", IFTTT_EVENT_NAME)
try:
response = requests.post(url, headers={"Content-Type": "application/json"}, json=payload, timeout=10)
if response.status_code == 200:
print("LINE通知成功")
else:
print(f"エラー: {response.status_code}")
except Exception as e:
print(f"LINE通知失敗: {e}")

def load_day_data(target_date: datetime) -> pd.DataFrame:
date_str = target_date.strftime("%Y%m%d")
file_path = fr"{NAS_PATH}/power_{date_str}.parquet"
if not os.path.exists(file_path):
raise FileNotFoundError(f"データが見つかりません: {file_path}")
return pd.read_parquet(file_path)

def calc_daily_summary(df: pd.DataFrame, date_label: str):
# 数値化
df["value1"] = pd.to_numeric(df["value1"], errors="coerce") # 発電 kW
df["value2"] = pd.to_numeric(df["value2"], errors="coerce") # 買電 kW
df["value3"] = pd.to_numeric(df["value3"], errors="coerce") # 売電 kW
df["value4"] = pd.to_numeric(df["value4"], errors="coerce") / 6 # 消費 kWh(既に1時間積算値)

# 10分間隔と仮定して正確にkWh計算
interval_min = 10
hours_per_record = interval_min / 60.0

total_gen_kwh = df["value1"].mean() * len(df) * hours_per_record
total_buy_kwh = df["value2"].mean() * len(df) * hours_per_record
total_sell_kwh = df["value3"].mean() * len(df) * hours_per_record
total_use_kwh = total_buy_kwh + total_gen_kwh - total_sell_kwh # 電力収支で算出(最も正確)

return {
"date": date_label,
"gen": round(total_gen_kwh, 2),
"buy": round(total_buy_kwh, 2),
"sell": round(total_sell_kwh, 2),
"use": round(total_use_kwh, 2)
}

def calc_week_summary(days=7, da=-8 ):
"""過去days日分の集計(今日を除く昨日まで)"""
base_day = datetime.now().date()
results = []
for i in range(1+8+da, days + 1+8+da):
target_date = base_day - timedelta(days=i)
try:
df = load_day_data(target_date)
date_label = target_date.strftime("%m/%d")
summary = calc_daily_summary(df, date_label)
results.append(summary)
except Exception as e:
print(f"{target_date} のデータ読み込み失敗: {e}")

if not results:
return None

total_gen = sum(r["gen"] for r in results)
total_buy = sum(r["buy"] for r in results)
total_sell = sum(r["sell"] for r in results)
total_use = sum(r["use"] for r in results)

lines = [f"【過去{days}日間実績】"]
for r in reversed(results): # 古い順→新しい順
lines.append(f"{r['date']}: 発電{r['gen']} kWh")
lines.append("")
lines.append(f"合計発電量: {total_gen:.1f} kWh")
lines.append(f"合計買電量: {total_buy:.1f} kWh")
lines.append(f"合計売電量: {total_sell:.1f} kWh")
lines.append(f"合計消費量: {total_use:.1f} kWh")

return "\n".join(lines)

def main():
parser = argparse.ArgumentParser(description="電力データ集計&LINE通知")
parser.add_argument("--da", type=int, default=0, help="日付加算。-1=昨日, 0=今日, 1=明日…")
parser.add_argument("--ptn", type=str, default="f", choices=["p", "f", "w"],
help="p=発電量のみ, f=全項目, w=週間集計")
args = parser.parse_args()

# --- 対象日の決定 ---
base_date = datetime.now()
if args.da != 0:
base_date += timedelta(days=args.da)

# 今日の場合、現在時刻までのデータのみ読み込む(ファイルは当日分全部ある前提)
target_date = base_date.date()
date_label = base_date.strftime("%Y/%m/%d")

if args.ptn == "w":
message = calc_week_summary(7,args.da)
if message:
send_line_message("太陽光発電1週間データ",message,"-")
message=f"{message}\n"
else:
send_line_message("太陽光発電","週間集計データが取得できませんでした","-")
message="週間集計データが取得できませんでした"
print(message)
return
else:
try:
df = load_day_data(base_date)
except Exception as e:
send_line_message("太陽光発電",f"⚠️ {date_label} のデータがありません\n{e}","-")
message = f"⚠️ {date_label} のデータがありません\n{e}"
print(message)
return

summary = calc_daily_summary(df, date_label)

# --- メッセージ作成 ---
if args.ptn == "p":
message = f"☀️ {base_date.date()} 発電量\n{summary['gen']} kWh"
else: # f
message = f"⚡️ {base_date.date()} 電力実績\n" \
f"発電量 :{summary['gen']} kWh\n" \
f"買電量 :{summary['buy']} kWh\n" \
f"売電量 :{summary['sell']} kWh\n" \
f"消費電力量:{summary['use']} kWh"

send_line_message("太陽光発電データ",message,"-OK-")
print(message)

import sys
if "ipykernel_launcher.py" in sys.argv[0]:
# ここに実行したい引数を書く(好きな組み合わせでOK)
sys.argv = ["power_report.py"] # ← ptnなし → f 扱い(今日分フル)
#sys.argv = ["power_report.py", "--da", "-1"] # 昨日分フル
#sys.argv = ["power_report.py", "--ptn", "p"] # 今日の発電量だけ
# sys.argv = ["power_report.py", "--ptn", "w"] # 週間集計

if __name__ == "__main__":
main()
使用方法・CRON設定方法(CRON起動設定 例)
30 19 * * * /usr/bin/python3 /home/hsbox/pyd/power_report.py --da 0 --ptn p
19:30に当日の発電量を通知

0 9 * * * /usr/bin/python3 /home/hsbox/pyd/power_report.py --da -1 --ptn f
AM9:00に前日の発電量・売電量・買電量・消費電力を通知

1 9 * * 7 /usr/bin/python3 /home/hsbox/pyd/power_report.py --da -8 --ptn w
日曜日 AM9:00に前日までの7日間の発電量・売電量・買電量・消費電力を通知

IFTTTの設定

IFTTTでの設定は、随時更新されるため参考程度で見てください。詳細はWebhooksやLINEの項目を確認してください。 ※これは、2025/12/10時点の情報です。

Webhooksの「Your key」の確認方法

1. IFTTT にログイン

https://ifttt.com
にアクセスし、ログインします。

2. Webhooks サービスページへ移動

以下の公式ページを開く
👉 https://ifttt.com/maker_webhooks

3. 右上の「Settings」をクリック

画面右上に Settingsという青いボタンがあります。

4. “Webhooks Settings” の欄を確認

開いたページに以下のような記載があります:

URL
https://maker.ifttt.com/use/**********


この key(*******の部分) が個人専用の Webhooks Key です。
このkeyをスクリプト(power_report.py)のyour_keyに設定してください
IFTTTの Applet 作成例(※画面は2025年12月現在のものです)

Appletの名称は自分にわかりやすいように任意に設定してください。

イベント(THEN)に「Receive a web request」を選択し、Event Nameを設定します。このEvent Nameをスクリプト(power_report.py)内のIFTTT_EVENT_NAMEに設定します。

THAT(実行内容)に LINEの「Send message to self」を選択し、自分のLINE accountを設定します。 Messageは、上のように設定すれば、設定完了です。

この設定は、自分あてのメッセージ送信なので、このスクリプトに限らず、他のメッセージ送信にも応用できます。

以下、2025/12/07に届いた通知メール
件名:【フロンティアモニター】 12月06日 電力量レポート


内容:
**** 様

日頃より【フロンティアモニター】ホームエネルギーモニタリングサービスをご利用いただき、誠にありがとうございます。

【システム終了のお知らせ】
2025年12月22日(月)をもって本計測装置のサービスを終了いたします。
なお、システムの都合により、一部サービス終了のタイミングについては前後する可能性がございますので、ご承知おきください。
詳しくはお客様ご利用サイトのお知らせ欄をご覧ください。

本メール発信は、メールシステムメンテナンスにより、1日遅延する場合があります。メンテナンスの日程は、お客様ログイン画面の「お知らせ」欄に随時記載いたします。
メンテナンス時はご不便をおかけしますが、何卒ご承知おきくださいますようお願いいたします。

下記の通り、2025年12月06日の電力量をお知らせいたします。

発電量:19.98kWh
売電量:9.56kWh
買電量:37.58kWh

今月の目標売電量(223kWh)に対して、14%達成しました。
今月の目標消費電力量(1,106kWh)に対して、293kWh消費しました。

省エネ目標が01月01日から変更されておりません。

発電・消費電力量は季節ごとにかわりますので、目標も毎月更新されることをおすすめします。

日没後に送られてくる当日分発電量
**** 様

日頃より【フロンティアモニター】ホームエネルギーモニタリングサービスをご利用いただき、誠にありがとうございます。

【システム終了のお知らせ】
2025年12月22日(月)をもって本計測装置のサービスを終了いたします。
なお、システムの都合により、一部サービス終了のタイミングについては前後する可能性がございますので、ご承知おきください。
詳しくはお客様ご利用サイトのお知らせ欄をご覧ください。

本メール発信は、メールシステムメンテナンスにより、1日遅延する場合があります。メンテナンスの日程は、お客様ログイン画面の「お知らせ」欄に随時記載いたします。
メンテナンス時はご不便をおかけしますが、何卒ご承知おきくださいますようお願いいたします。

下記の通り、2025年12月06日の発電量をお知らせいたします。

発電量:19.98kWh















今後ともフロンティアモニターをよろしくお願いいたします。
★なお、お心当たりのない方は、お手数ではございますが、下記メールアドレスまでご連絡頂きますようお願いいたします。
★このメールは送信専用メールアドレスから配信しています。このまま返信いただいてもお答えできませんのでご了承ください。
-----------------------------------------------
ソーラーフロンティア株式会社
【フロンティアモニター】お客様サービスセンター
電話:0570-053115(受付時間:9:00-17:00)※日曜、祝祭日、メーデー、年末年始を除く
メール:information@solar-frontier.com
-----------------------------------------------

上の内容のうち、太字部分に相当する情報を、LINEで通知するようにしてみました。
参考にしてみてください。

関連記事

リモートデスクトップでモヤっと。

Windows 11からWindows 11をリモートデスクトップ接続でモヤっとした画面表示になったままどうすることもできない事象が発生している。これに対する対処を検討する。

以前にも「リモートデスクトップのキーボード配置が変わった」問題があった。リモートデスクトップに関する問題は、数多くのバージョンの組み合わせで使われるので難易度が高い問題でもあるだろう。同じパターンで解決した人がいればコメントください。

いろいろ試して、これかという設定を見つけて対処してみたが今のところ効いていない。今時点で、まだ解決していないが、解決まで話が長くなりそうなのでいったん公開しておきます。

まずは、今の症状・現状分析から書いていこう。

1.問題の症状

このようなモヤっとした画面である。可能な操作は次の通り。
・ウィンドウの最小化、最大化、ピン止め、など
接続情報も見える

おや、Client detailsに想定外の「Windows 10」の文字が。。。。 なぜ? これが原因では? ということで、調べてみた。

接続先のWindowsは?

接続元は?

どっちもWindows 11なのに、なぜかリモートデスクトップはWindows 10 これは怪しい。

※ただ、Windows 10のリモートデスクトップに接続したときは、モヤッとならない。
また、その際の接続情報も上と同じ表示でWindows 10。 なので、接続情報がWindows 10であることが直接の原因ということはない。 組み合わせかもしれないが。。

「リモートデスクトップのWindows 11に接続して少し時間がたつとモヤっとなり、接続情報を見るとちゃんと接続しているが、なにも操作できなくなる。ウィンドウを閉じて再接続すると操作はできる。 ウィンドウを閉じて再接続しなくても、操作をできるようにする方法を解説してください。 原因を調べる方法があれば教えてください。」と今噂?のGemini3.0Proに聞いてみた。以下、背景が灰色の部分はGeminiの回答で、赤文字は私のコメントです。

リモートデスクトップ(RDP)接続中に「画面がモヤっとして(画質が低下して)操作不能になる」現象、非常にストレスが溜まりますよね。

この症状の典型的な原因は、RDPが使用している通信プロトコル(UDP)の不調や、描画キャッシュの不整合であることが多いです。「接続情報は繋がっている」のに操作できないのは、通信経路の一部(特に画面転送を行うUDP)だけが詰まっている状態と考えられます。

以下に、再接続せずに復帰を試みる方法(対処療法)と、そもそもこの現象が起きないようにする設定(根本治療)、および原因の調査方法を解説します。


1. 再接続せずに操作可能にする方法(対処療法)画面が固まった際、マウス操作は効かなくてもキーボードショートカットがサーバーに届けば、画面の再描画(リフレッシュ)が走り、操作可能になることがあります。

以下のショートカットを順番に試してみてください。

  • **Ctrl + Alt + End**:  
  • リモート先で Ctrl + Alt + Del を押したことになります。セキュリティ画面に切り替わることで画面が強制的に再描画され、フリーズが解けることがあります。
  • **Ctrl + Alt + Break** (または Fn + Break / Pause):
  • リモートデスクトップの「全画面表示」と「ウィンドウ表示」を切り替えます。ウィンドウサイズが変わることで画面情報がリセットされ、復帰することがあります。

※注意: これらで反応がない場合は、通信セッション自体が「ゾンビ状態(切断されているのに認識されていない)」になっているため、残念ながらウィンドウを閉じて再接続するしかありません。


2. 現象を二度と起こさないための設定(根本治療)「モヤっとなる」のは、回線速度に合わせて画質を落とそうとする機能が働いた直後に、通信が詰まっている可能性が高いです。これを防ぐには、「UDP通信を無効化してTCPのみにする」のが最も効果的です。

方法A:ホスト側(接続されるWindows 11)の設定変更これが最も確実です。グループポリシーエディタを使用します(Pro版以上)。

  1. Windowsキー + R を押し、gpedit.msc と入力してEnter。
  2. 左側のツリーで以下へ進みます。
    コンピューターの構成 > 管理用テンプレート > Windows コンポーネント > リモート デスクトップ サービス > リモート デスクトップ セッション ホスト > 接続
  3. 「RDP トランスポート プロトコルの選択」 をダブルクリックします。
  4. 「有効」を選択し、オプションで 「TCP のみを使用」 を選択してOKを押します。
  5. PCを再起動します。

Windows 11 Home版の場合は、レジストリ操作が必要です。

  1. regedit を起動。
  2. HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services へ移動。
  3. 右クリック > 新規 > DWORD(32ビット)値を作成。名前を fClientDisableUDP にする。
  4. 値を 1 に設定して再起動。

方法B:クライアント側(操作する手元のPC)の設定変更手元のPCの設定で緩和できる場合もあります。

  1. リモートデスクトップ接続アプリを起動し、「オプションの表示」を開く。
  2. 「エクスペリエンス」タブへ移動。
  3. 「ビットマップのキャッシュを保持する」のチェックを外す。
  • キャッシュファイルが壊れて画面がおかしくなるのを防ぎます。
  1. 「接続速度の自動検出」ではなく、「LAN(10Mbps以上)」などに固定してみる。

3. 原因を調べる方法なぜ切れるのか、ログを確認して特定する方法です。

イベントビューアーでログを確認するWindowsにはRDP関連の詳細なログが記録されています。

  1. 接続される側(Windows 11)または手元のPCで、スタートボタンを右クリック > 「イベント ビューアー」 を選択。
  2. 以下のパスを開きます。
    アプリケーションとサービス ログ > Microsoft > Windows > TerminalServices-LocalSessionManager > Operational
  • ここでは切断や再接続のタイミングがわかります。
  1. より詳細なエラー理由は以下を確認します。
    アプリケーションとサービス ログ > Microsoft > Windows > TerminalServices-ClientActiveXCore > Microsoft-Windows-TerminalServices-RDPClient/Operational

  • ここで「警告」「エラー」になっている項目のIDやメッセージ(例:ID 1026 ネットワーク接続が失われました 等)を確認します。

パケットロスを確認する接続中にコマンドプロンプトを開き、以下のコマンドを打ちっぱなしにしておきます。

ping -t [接続先IPアドレス]

画面が「モヤっと」して操作不能になった瞬間、pingも Request timed out になっていれば、PCの問題ではなくネットワーク機器(ルーターやWi-Fi)の瞬断が原因です。


まとめ:まず試していただきたいことまずは、「UDP通信の無効化(TCP固定)」を行ってみてください。

「モヤっとなる(画質低下)」現象は、UDP通信特有の症状であることが多いため、TCPに固定することで画質の変動はなくなり、通信の安定性が向上する可能性が非常に高いです。

レジストリやポリシーの設定変更について、より詳細な手順のサポートが必要ですか?


追加情報2

更新プログラムの適用

  • Windows Updateで最新の累積更新を適用(2025年3月以降の更新でRDP関連の不具合が修正済み)
  • 更新の影響範囲
  • 接続元PC(クライアント側)
  • RDPクライアント( や ActiveXコンポーネント)の不具合修正は 接続元側の更新 で効果が出ます。
  • 特に「マルチトランスポート(UDP/TCP併用)」関連の修正はクライアント側に依存するため、接続元を最新にすることが重要です。
  • 接続先PC(サーバー側)
  • RDPサービス()やグラフィック描画、セッション管理の修正は 接続先側の更新 で効果があります。
  • サーバー側が古いと、クライアントが最新でも描画が乱れたり切断が発生することがあります。
  • ✅ 実際の対策
  • 両方のPCを最新にするのがベスト
  • クライアント側だけ更新しても改善するケースはありますが、サーバー側が古いと再発しやすいです。

パッチ情報を確認

✅ 確認方法のステップ

  1. Windows Updateの更新履歴を確認
  • 手順
  1. 「設定」 → 「Windows Update」 → 「更新履歴」を開く
  2. インストール済み更新プログラムの一覧から KB5053656(2025年3月27日公開) または KB5053598(2025年3月定例更新) があるか確認

これらが表示されていれば、リモートデスクトップの「モヤ」問題は修正済みです。

  • 累積更新の世代違い
  • 3月の KB5053598 は既に古く、25H2 では 4月以降の累積更新 (例: KB5055523, KB5067036) が必要です。

  1. OSビルド番号を確認
  • 手順
  1. → 「winver」と入力
  2. 表示されたビルド番号を確認
  • 修正済みの目安:
  • KB5052093 適用後 → 26100.3323 以上
  • KB5053656 適用後 → さらに安定版(2025年3月末以降)
  1. コマンドラインで確認(管理者向け)
  • PowerShellで以下を実行:
  • 出力に KB5053656 や KB5053598 が含まれていれば適用済み。

📌 補足情報

  • 問題の原因は2025年1月~2月の更新(KB5050094, KB5051987)で発生した既知の不具合。
  • Microsoftは 2025年3月以降の累積更新(KB5053598, KB5053656, KB5055523など)で修正済み。
  • 企業環境でWSUSやWUfBを利用している場合は、3月以降の累積更新を承認していれば同じ効果が得られます。

👉 まとめると、「更新履歴」でKB番号を確認するか、「winver」でビルド番号が26100.3323以上になっているか」を見れば、パッチ適用済みかどうか判断できます。


仕切り直し

ここまでの結果、AIでは? AIでもそう簡単に解決できる問題ではないことが判明した。再度、論理的に考え直してみよう。
関連するパッチは、すべて適用できていることになっている。ただし、2か月間ほどPCを起動できていなかった期間に配信されたパッチは適用されず、その後配信された累積パッチで、問題の修正を含むパッチが適用されたことになる。しかし、それでも修正が反映されていないように見える。ここから考えられるパターンは、実装レベルの修正は反映されたが、設定での変更が最初にパッチが配布されたときにだけ配布され、その後配信されていないパターンである。 なんか、「リモートデスクトップのキーボード配置が変わった」件とすごく似ている感じがします。あのときは、レジストリ設定をいろいろ変更しました。

 それから、挙動から、グラフィック処理周りの設定が怪しそうです。接続情報で「接続品質が良好」なのに操作不能になるのは、通信ではなくグラフィックレンダリング層での問題である可能性が高いと推測されます。

関連する設定の確認と変更検討

# 1. グラフィック処理の最適化を無効化
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fEnableVirtualizedGraphics /t REG_DWORD /d 0 /f
※この設定がない


# 2. RemoteFXを完全無効化
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fEnableRemoteFXAdvancedRemoteApp /t REG_DWORD /d 0 /f
※この設定がない

# 3. ビットマップキャッシュの無効化(サーバー側)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v fDisableCam /t REG_DWORD /d 1 /f
※ 0 がセットされていた

# 4. グラフィック出力のハードウェアアクセラレーション無効化
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v fDisableVideoCompressionMode /t REG_DWORD /d 1 /f
※ この設定がない

# 5. セッション制限時間の延長(ミリ秒単位)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v MaxIdleTime /t REG_DWORD /d 0 /f
※ ★これは設定済み

reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v MaxConnectionTime /t REG_DWORD /d 0 /f
※ ★これは設定済み

# 再起動
Restart-Computer

管理者権限のターミナルで上の設定を実施、レジストリエディタで更新されていることを確認して、再起動した。 とりあえずこれで様子見だったが、 すぐに発生した。

# 1. 接続先PCのGPUドライバー情報確認
Get-WmiObject Win32_VideoController | Select-Object Name, DriverVersion, DriverDate

# 2. RDP使用時のGPU負荷監視
# タスクマネージャーのパフォーマンスタブでGPUエンジンを監視しながら接続

# 3. ドライバーの互換性テスト
# ディスプレイアダプターの設定で「リモートデスクトップ用にこのデバイスを使用する」のチェック確認


# 接続先PC(25H2)で以下を確認
winver
# ビルド番号が26200.xxxx台であることを再確認

# Windows Insider Program加入の有無確認
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\WindowsSelfHost\Applicability" -ErrorAction SilentlyContinue

# 25H2用の修正パッチ検索
Get-HotFix | Where-Object {$_.InstalledOn -gt (Get-Date).AddMonths(-2)} |
Format-Table HotFixID, Description, InstalledOn

d:
PS D:> Get-WmiObject Win32_VideoController | Select-Object Name, DriverVersion, DriverDate

Name DriverVersion DriverDate
—- ————- ———-
NVIDIA GeForce RTX 3080 32.0.15.6094 20240814000000.000000-000
Microsoft Remote Display Adapter 10.0.26100.7309 20060621000000.000000-000

PS D:> winver
PS D:> Get-ItemProperty “HKLM:\SOFTWARE\Microsoft\WindowsSelfHost\Applicability” -ErrorAction SilentlyContinue

WNSUriRegName : {85, 248, 12, 164…}
UseSettingsExperience : 0
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsSelfHost\Appli
cability
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsSelfHost
PSChildName : Applicability
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry

PS D:> Get-HotFix | Where-Object {$_.InstalledOn -gt (Get-Date).AddMonths(-2)} |

Format-Table HotFixID, Description, InstalledOn

HotFixID Description InstalledOn
——– ———– ———–
KB5067931 Update 2025/12/13 0:00:00
KB5054156 Update 2025/12/03 0:00:00
KB5072033 Security Update 2025/12/10 0:00:00
KB5071142 Update 2025/12/10 0:00:00

-. NVIDIA RTX 3080のドライバーが古い

DriverVersion: 32.0.15.6094 (2024年8月14日)
nvidia-smiの出力から

Driver Version: 560.94 (最新版)

実はドライバーは既に最新

次の対策手順

対策1: GPUハードウェアアクセラレーションの無効化(最優先)

接続先PCで実行:

# 1. RDP専用のGPU制御設定
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v AVCHardwareEncodePreferred /t REG_DWORD /d 0 /f

# 2. RemoteFX vGPUの完全無効化
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fEnableVirtualizedGraphics /t REG_DWORD /d 0 /f

# 3. ハードウェアアクセラレーション全体の無効化
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v fDisableVideoCompressionMode /t REG_DWORD /d 1 /f

# 4. ビットマップキャッシュのサーバー側無効化
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v fDisableCam /t REG_DWORD /d 1 /f

# 5. WDDM(Windows Display Driver Model)グラフィックスドライバーの制御
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v bEnumerateHWBeforeSW /t REG_DWORD /d 0 /f

# 再起動
Restart-Computer

ほぼ設定済みだが

# 1. GPU制御の無効化(最重要)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v AVCHardwareEncodePreferred /t REG_DWORD /d 0 /f

# 2. WDDM制御(ハードウェアGPU優先を無効化)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v bEnumerateHWBeforeSW /t REG_DWORD /d 0 /f

Write-Host "`n設定完了。再起動が必要です。" -ForegroundColor Yellow
Write-Host "再起動コマンド: Restart-Computer" -ForegroundColor Cyan

上の設定をしたがだめ、
 で、「接続品質は良好です」が気になります。そもそも何か間違えているのでは?という気になってきた。 右下の電源アイコンをクリックすると反応する。 「スリープ」させるとスリープした。

# Desktop Window Manager (DWM) のログを有効化
wevtutil sl Microsoft-Windows-Dwm-Core/Diagnostic /e:true /l:5

# グラフィックドライバーのログも有効化
wevtutil sl Microsoft-Windows-Display/Operational /e:true

# RDPのグラフィックチャネル詳細ログ
wevtutil sl Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Debug /e:true /l:5

Write-Host "詳細ログを有効化しました。モヤっと現象を再現してください。" -ForegroundColor Yellow
# Desktop Window Manager (DWM) のログを有効化
wevtutil sl Microsoft-Windows-Dwm-Core/Diagnostic /e:true /l:5

# グラフィックドライバーのログも有効化
wevtutil sl Microsoft-Windows-Display/Operational /e:true

# RDPのグラフィックチャネル詳細ログ
wevtutil sl Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Debug /e:true /l:5

Write-Host "詳細ログを有効化しました。モヤっと現象を再現してください。" -ForegroundColor Yellow
$logTime = (Get-Date).AddMinutes(-5)
$outputDir = "C:\RDP_Debug_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
New-Item -ItemType Directory -Path $outputDir -Force

# 1. DWM(デスクトップ描画)のエラー
Get-WinEvent -LogName "Microsoft-Windows-Dwm-Core/Diagnostic" -MaxEvents 100 |
Where-Object {$_.TimeCreated -gt $logTime} |
Format-List TimeCreated, Id, LevelDisplayName, Message |
Out-File "$outputDir\dwm_diagnostic.txt"

# 2. RDPコアのグラフィック処理エラー
Get-WinEvent -LogName "Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational" -MaxEvents 100 |
Where-Object {$_.TimeCreated -gt $logTime -and $_.Message -match "graphics|video|display|render"} |
Format-List TimeCreated, Id, LevelDisplayName, Message |
Out-File "$outputDir\rdp_graphics.txt"

# 3. ディスプレイドライバーのエラー
Get-WinEvent -LogName "System" -MaxEvents 200 |
Where-Object {$_.TimeCreated -gt $logTime -and $_.ProviderName -match "nvlddmkm|Display"} |
Format-List TimeCreated, Id, LevelDisplayName, Message |
Out-File "$outputDir\display_driver.txt"

# 4. 「理由=1」の前後詳細
Get-WinEvent -LogName "Microsoft-Windows-TerminalServices-RDPClient/Operational" -MaxEvents 50 |
Where-Object {$_.TimeCreated -gt $logTime} |
Format-List TimeCreated, Id, LevelDisplayName, Message |
Out-File "$outputDir\rdp_client_detail.txt"

Write-Host "ログを $outputDir に保存しました" -ForegroundColor Green

———————–
対策1: ネットワークアダプタの省電力を無効化

# 接続先PCで実行
Write-Host "=== ネットワークアダプタの省電力設定確認 ===" -ForegroundColor Cyan

# すべてのネットワークアダプタを取得
$adapters = Get-NetAdapter | Where-Object {$_.Status -eq "Up"}

foreach ($adapter in $adapters) {
Write-Host "`n[$($adapter.Name)]" -ForegroundColor Yellow

# デバイスマネージャーのプロパティを取得
$device = Get-PnpDevice | Where-Object {$_.FriendlyName -like "*$($adapter.InterfaceDescription)*"}

if ($device) {
# 省電力設定を確認
$powerMgmt = Get-CimInstance -ClassName MSPower_DeviceEnable -Namespace root/wmi |
Where-Object {$_.InstanceName -like "*$($device.InstanceId)*"}

if ($powerMgmt) {
Write-Host " 省電力有効: $($powerMgmt.Enable)"
}
}
}

# GUIで設定する場合の手順を表示
Write-Host "`n=== 手動設定の手順 ===" -ForegroundColor Green
Write-Host "1. デバイスマネージャーを開く"
Write-Host "2. ネットワークアダプターを展開"
Write-Host "3. 使用中のアダプターを右クリック → プロパティ"
Write-Host "4. 電源の管理タブ"
Write-Host "5. 以下のチェックを外す:"
Write-Host " □ 電力の節約のために、コンピューターでこのデバイスの電源をオフにできるようにする"

次を実施
1. デバイスマネージャーを開く
2. ネットワークアダプターを展開
3. 使用中のアダプターを右クリック → プロパティ
4. 電源の管理タブ
5. 以下のチェックを外す:
□ 電力の節約のために、コンピューターでこのデバイスの電源をオフにできるようにする

とりあえず、これで様子見ですが、すぐにモヤっとが再発しました。 他のログと混ざらないように、少し時間をおいて次の調査作業に入りましょう。

この状態でスリープさせることは確認できていますが、 何らかのキー操作で復活させることはできないか検討してみましょう。

モヤっとリモートデスクトップにポインチが当たっているときは、


Win + Tab (タスクビュー表示)
Ctrl + Shift + F10 (メニューバー表示)
Ctrl + Alt + Break (フルスクリーン ⇔ ウィンドウモード切り替え)
この辺は反応があり、右下の表示()が切り替わりますが、それ以上の反応はない

もちろん「モヤっとのリモートデスクトップ」にpointが当たっていないときはその他のウインドウは動く。まるで、サインインの前の状態のように…?

ソーラーフロンティア太陽光発電・発電量独自集積データ解析をiPythonで書いてみた

モニタリングを視覚化と、異常検知するアプローチを進めていきましょう。 まずは、自動化に向けて太陽光発電・発電量独自集積データ解析をiPythonで書いてみます。

先の記事までにデータ収集に成功し、ソーラーフロンティア太陽光発電のモニタリングサービスで収集した結果とデータ比較しほとんど一致していることを確認できています。ここからは、モニタリングを視覚化と、異常検知するアプローチを進めていきましょう。 まずは、自動化に向けて太陽光発電・発電量独自集積データ解析をiPythonで書いてみます。 → LINE通知はこちら

システム構成
fmget
ソーラフロンティアモニタ代替

ここからは、前にNASに保存した形式のデータを扱う前提で書いていきます。

元のデータは、10分毎の瞬間値データでした。1時間ごとに平均してkWhに変換すると、ソーラーフロンティアモニタリングサービスに蓄積されたデータとほとんど同じデータになります。※取得した瞬間値の取得タイミングが異なるので、雲がまばらにあるような瞬間値の変動が激しい天候の場合はずれが大きくなるでしょう。
 1日分の発電量を集計・グラフ化するipythonコードは次の通りです。

import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
from datetime import datetime

dt1 = "2025/12/02" #★参照したい日付 を指定
nas_path = r"<NASのパス名>" #★NASのパス 環境に合わせて指定


date_obj = datetime.strptime(dt1, "%Y/%m/%d")
date_with_slash = date_obj.strftime("%Y/%m/%d")
date_str = date_obj.strftime("%Y%m%d")

# --- ① parquet 読み込み(あなたのコード) ---
# ファイルパスを組み立て
file_path = fr"{nas_path}\power_{date_str}.parquet"
df = pd.read_parquet(file_path)
ttl=f"発電量推移 {date_with_slash}"

# --- ② Value1 を数値化(エラーを NaN に) ---
df["value1"] = pd.to_numeric(df["value1"], errors="coerce")

# --- ③ timestamp を datetime に変換 ---
df["timestamp"] = pd.to_datetime(df["timestamp"])

# --- ④ 時刻(Hour)を抽出 ---
df["hour"] = df["timestamp"].dt.hour

# --- ⑤ 1時間ごとの平均値を計算 ---
hourly_mean = df.groupby("hour")["value1"].mean()

# --- ⑥ 結果表示 ---
print(hourly_mean)
total_sum = df["value1"].sum()/6
print(total_sum)

# timestamp を x 軸として、そのままプロット
plt.figure(figsize=(14,4))
plt.plot(hourly_mean, linewidth=1)
plt.title(ttl)
plt.grid(True)
plt.tight_layout()
plt.show()

★印の箇所は、任意に変更してください。NASのパスは iPythonが動作しているマシン上から見た、データ保存のパスです。
\\192.168.1.50\share など

表示結果例

SolarPower

つぎは、月単位、年単位の集計値を出すコード書いてみましょう。それから、hsBoxで、スマートディスプレイやGoogleTVに表示させる仕組みに着手です。

関連記事

hsbox1.3で屋内のソーラーフロンティアホームサーバから直接発電量データ取得、データ検証編 まず2日分データで検証

hsbox でのソーラーフロンティアホームサーバーからのデータ収集の続きをしましょう。ホームサーバから直接取得する方法で、ホームエネルギーモニタリングサービス とほぼ一致するデータが取れたことを確認できました。


今回は、情報採取した2日分のデータと、「フロンティアモニター – ホームエネルギーモニタリングサービス -」のデータがどの程度一致しているか検証してみます。

取得データ比較結果

12/1と12/2の発電量の比較デーは以下の通りです。10分間隔で取得して1時間ごとに平均化しています。ほぼ同じ取得方法ですが、取得タイミングが微妙に違うので少しずれます。それでも、1日の発電量の一致度は、12/1は98.4%、 12/2は100.5%でした。十分満足できる結果でした。昨日公開した実装方法で発電量などのデータを取得できることを確認できました。

先のValue1が発電量のデータです。さらに2週間ほど並行してソーラーフロンティアに上がっているデータと一致しているか、詳細確認をしてみます。

検証環境

今回、データ取得に使用した環境は次の通りです。
フロンティアモニターホームサーバー
カーネルVer. 3.22
システムVer. 3.22
AD変換ボードVer. 2.00

hsBox
Version: 1.03.01.01, Build: 324

fmget
ソーラフロンティアモニタ代替

関連記事

https://www.frontier-monitor.com/persite/top

hsbox1.3で、ソーラーフロンティアホームサーバから発電量データ取得 遂に成功!? (fm_dataget.py)

hsbox でのソーラーフロンティアホームサーバーからのデータ収集の続きをしましょう。PROXY方式は諦めて、ホームサーバから直接取得する方法で再検討です。
結論から言うと、どうもうまくいっていそうです。最初に構成図です、前に描いた図と同じですが、ホームサーバから受け取るのではなく、ホームサーバに取りに行くイメージです。

検証環境

今回、データ取得に使用した環境は次の通りです。
フロンティアモニターホームサーバー
カーネルVer. 3.22
システムVer. 3.22
AD変換ボードVer. 2.00

hsBox
Version: 1.03.01.01, Build: 324

データ取得実装例(/home/hsbox/pyd/fm_dataget.py)

フロンティアモニターホームサーバーのバージョンによってデータ取得方法に違いがあります。参考にしてみてください

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import requests
import pandas as pd
import os
import json
import logging
from datetime import datetime
from pathlib import Path
import platform

# ===== 設定 =====
URL = "http://<★フロンティアモニターホームサーバーIP>/getEpData.cgi"
if platform.system() == "Windows":
NAS_DIR = Path(r"\\<★NAS IP>\share\PowerData")
else:
NAS_DIR = Path("/mnt/nas/PowerData") ★

NAS_DIR.mkdir(parents=True, exist_ok=True)

# ===== ログ設定 =====
today = datetime.now().strftime("%Y%m%d")
logfile = NAS_DIR / f"powerD_{today}.log"

logging.basicConfig(
filename=str(logfile),
level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
encoding='utf-8'
)

# ===== データ取得 =====
try:
response = requests.post(URL, data={"ep_units": "KW"}, timeout=5)
response.raise_for_status()
raw_data = response.text.strip()
except Exception as e:
logging.error(f"データ取得エラー: {e}")
print(f"データ取得エラー: {e}")
exit(1)

# ===== データ整形 =====
values = raw_data.split('|')

now = datetime.now()
data_dict = {
"timestamp": now,
"value1": values[0],
"value2": values[1],
"value3": values[2],
"value4": values[3],
"value5": values[4],
"value6": values[5],
"value7": values[6],
"value8": values[7] if len(values) > 7 else None,
"value9": values[8] if len(values) > 8 else None,
"value10": values[9] if len(values) > 9 else None,
"value11": values[10] if len(values) > 10 else None,
}

df = pd.DataFrame([data_dict]) # ← 1行 DataFrame

# ===== daily Parquet 追記 =====
daily_file = NAS_DIR / f"power_{today}.parquet"

try:
if daily_file.exists():
df_existing = pd.read_parquet(daily_file)
df = pd.concat([df_existing, df], ignore_index=True)

df.to_parquet(daily_file, index=False)
print(f"{daily_file} にデータを保存しました。")

# JSON ログ用に datetime を文字列化
log_dict = data_dict.copy()
log_dict["timestamp"] = log_dict["timestamp"].isoformat()
logging.info(f"データ保存: {json.dumps(log_dict, ensure_ascii=False)}")

except Exception as e:
logging.error(f"Parquet 保存エラー: {e}")
print(f"Parquet 保存エラー: {e}")

★印の箇所は、環境に合わせて、書き換えてください。
NAS設定はこちらのページを参考してください

cron設定

*/10 * * * *  /usr/bin/python3 /home/hsbox/pyd/fm_dataget.py

CRON設定で、10分おきに実行するように設定します。
CRON設定の方法は、hsbox本家サイトのページを参考にしてください。

このような感じでデータを取得できました


読み込み完了! → 143 行 × 12 列
timestamp value1 value2 value3 value4 value5 value6 value7 value8 value9 value10 value11
0 2025-12-01 00:00:03.338238 0.00 1.15 0.00 6.39 99.59 6.64 99.35 --/-- --:-- -.-- -.-- --/-- --:--
1 2025-12-01 00:10:03.199163 0.00 1.84 0.00 11.67 99.55 8.01 99.48 --/-- --:-- -.-- -.-- --/-- --:--
2 2025-12-01 00:20:03.231549 0.00 1.19 0.00 5.79 100.05 7.47 99.64 --/-- --:-- -.-- -.-- --/-- --:--
3 2025-12-01 00:30:02.432434 0.00 1.66 0.00 10.68 99.80 7.15 99.72 --/-- --:-- -.-- -.-- --/-- --:--
4 2025-12-01 00:40:03.512127 0.00 1.12 0.00 5.50 100.37 7.18 99.92 --/-- --:-- -.-- -.-- --/-- --:--
5 2025-12-01 00:50:02.524990 0.00 1.66 0.00 10.88 99.81 7.06 99.78 --/-- --:-- -.-- -.-- --/-- --:--
6 2025-12-01 01:00:03.315994 0.00 1.67 0.00 11.06 100.06 7.03 100.07 --/-- --:-- -.-- -.-- --/-- --:--
7 2025-12-01 01:10:02.494529 0.00 1.13 0.00 5.94 100.36 6.77 100.07 --/-- --:-- -.-- -.-- --/-- --:--
8 2025-12-01 01:20:03.026167 0.00 1.08 0.00 5.49 100.05 6.85 99.70 --/-- --:-- -.-- -.-- --/-- --:--
9 2025-12-01 01:30:03.163444 0.00 1.03 0.00 5.21 100.12 6.67 99.77 --/-- --:-- -.-- -.-- --/-- --:--
10 2025-12-01 01:40:02.385593 0.00 0.99 0.00 5.46 100.18 6.18 99.92 --/-- --:-- -.-- -.-- --/-- --:--
11 2025-12-01 01:50:03.190017 0.00 0.91 0.00 5.44 100.25 5.43 100.11 --/-- --:-- -.-- -.-- --/-- --:--

それぞれの項目のデータの意味は次のようになっているようです。

保存されたデータを確認

とりあえず一部のみです。

発電量のデータです。 多分取れているようです。2週間ほど並行してそらーフロンティアに上がっているデータと一致しているか、詳細確認をしてみます。

関連記事

本番、仕切り直し。(proxy設定 httpからhttpsに変換、 ポストデータ取得を検証)この方法は断念…   

「フロンティアモニターホームサーバー」のプロキシ設定を変更して、プロキシ経由でのデータ送信を検証してみます。hsBoxのIPとプロキシのポート番号8080を設定しました。すると、フロンティアモニター – ホームエネルギーモニタリングサービス – https://www.frontier-monitor.com/persite/top へのデータ反映が止まりました。当然過去分は見えますが、プロキシ設定変更後のデータが反映されません。 先のポストデータの取得のスクリプトでは、データが取れないどころか、「フロンティアモニターホームサーバー」から何か届いているのかさえも確認できません。スプリプトを改造してスタブ実装で200応答するように改造しましたが、コネクションまでは確認でき接続先サーバーを記録できることまではできましたが、TLS接続してくるのを疑似CAで応答できなさそうであることを確認しました。

solar
solar

PROXY方式についての結論

ユーザー名、パスワードを設定してもhttpsで接続し、httpで接続してくることはない。疑似的接続させることもほぼ不可能である。
 ということで、PROXY方式での情報採取はあきらめました。


再び、内部APIの調査、CGIでデータを採取

次回は、内部CGIでデータをとれるかを検証してみます。 どうもこっちが本命になりそう。


関連記事

さて本番だ、切り替えてみよう。(proxy設定 httpからhttpsに変換、 ポストデータ取得を検証)あと1歩に見えたが…

「フロンティアモニターホームサーバー」のプロキシ設定を変更して、プロキシ経由でのデータ送信を検証してみます。hsBoxのIPとプロキシのポート番号8080を設定しました。すると、フロンティアモニター – ホームエネルギーモニタリングサービス – https://www.frontier-monitor.com/persite/top へのデータ反映が止まりました。当然過去分は見えますが、プロキシ設定変更後のデータが反映されません。 先のポストデータの取得のスクリプトでは、データが取れないどころか、「フロンティアモニターホームサーバー」から何か届いているのかさえも確認できません。横から、テスト用のポストをするとデータは記録されるので、構築した環境は動いているようです。

今回の結果を先に書くと、www.frontier-monitor.comの仕様の古さのために、当初の第一階目のゴールにはたどり着けないということが判明した。そして、いきなり最終ゴールにむけた実装が必要ということがわかった。調査結果を以下に書く。ゴールだけを見たいという人はこの記事は読み飛ばしてもらって構わない。

再びデバック開始

よく見たら、ジャーナルにたくさん「フロンティアモニターホームサーバー」接続記録が出ていました。

journalctl -u fm-mitmproxy.service -f


11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:04.599][192.168.x.xx:57372] server connect www.frontier-monitor.com:443 (150.31.252.104:443)
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:05.235][192.168.x.xx:57372] Client TLS handshake failed. Client and mitmproxy cannot agree on a TLS version to use. You may need to adjust mitmproxy's tls_version_client_min option.
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:05.240][192.168.x.xx:57372] client disconnect
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:05.245][192.168.x.xx:57372] server disconnect www.frontier-monitor.com:443 (150.31.252.104:443)
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:11.362][192.168.x.xx:43760] client connect
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:11.469][192.168.x.xx:43760] server connect www.frontier-monitor.com:443 (150.31.252.104:443)
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:12.019][192.168.x.xx:43760] Client TLS handshake failed. Client and mitmproxy cannot agree on a TLS version to use. You may need to adjust mitmproxy's tls_version_client_min option.
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:12.023][192.168.x.xx:43760] client disconnect
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:12.028][192.168.x.xx:43760] server disconnect www.frontier-monitor.com:443 (150.31.252.104:443)
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:18.092][192.168.x.xx:40724] client connect
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:18.143][192.168.x.xx:40724] server connect www.frontier-monitor.com:443 (150.31.252.104:443)
11月 29 17:11:53 hsbox mitmdump[47809]: [17:10:18.670][192.168.x.xx:40724] Client TLS handshake failed. Client and mitmproxy cannot agree on a TLS version to use. You may need to adjust mitmproxy's tls_version_client_min option.
11月 29

「Client TLS handshake failed. Client and mitmproxy cannot agree on a TLS version to use. You may need to adjust」このログが大量に出ているが、これが問題だったようだ。 TLS1.0に下げるように要求されている。 hsBoxでも設定で下げれないことはないが、外部公開している入り口が怪しくなるので無理にTLS1.0にさげないことにした。

太陽光機器(192.168.*.**)  
      ↓ CONNECT www.frontier-monitor.com:443 HTTP/1.1    プロキシ宛
mitmproxy(192.168.*.*:8080) ←ここで TLS 開始(クライアント側 TLS)  
      ↓ TLS ハンドシェイク開始  
      × 失敗 → Client TLS handshake failed  
      (mitmproxy → 150.31.252.104:443 にはまだ接続すらしていない)


ということで、データのキャプチャにも失敗し、プロキシ経由でのサーバへのアップロードもできていない。 プロキシ設定してから、 www.frontier-monitor.comへのデータアップロードも止まったままである。
  この記事での成果は、「フロンティアモニターホームサーバー」の送信先がwww.frontier-monitor.comであると確認できたことだ。

一旦、切り戻しして、仕切り直しましょう。そして、最終型にむけて再検討します。


関連記事