0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Switchbot PlugMini を使った WoL 代替

0
Posted at

What ?

  • TrueNAS の養育費(電気代)が地味にダメージ
    • TrueNAS のデータを参照するクローラは24時間365日動かしているが、Samba の情報をキャッシュして動作しているので、同期する時以外 TrueNAS が落ちていても問題ない
    • メインPCからも参照するが、参照する頻度は低い(仕事中とかは参照しないし)
  • Wake-on-LAN をしようと考えたが、どうも UEFI とかの設定をしても shutdown で LAN ポートも落ちてしまう
  • 電力把握のために Switchbot PlugMini を経由していた
    • 調べると API が公開されていた
  • 次のような運用を考えた
    • TrueNAS は、camcontrol を cron で動かして、HDD が一定時間アクセスされていないなら shutdown
    • UEFI の設定で "Restore AC Power Loss" を ON にする
    • その他の PC は、参照する際 PlugMini を Toggle して起動させる

Python コード(Windows)

  • クソ適当(動けばOK)
from sys import stderr
from subprocess import run
from time import sleep
import json
from time import time
from hashlib import sha256
import hmac
from base64 import b64encode
from uuid import uuid4
from typing import Dict

from requests import request

def eprint(msg: str) -> None:
    print(msg, file=stderr)

#
# switchbot
#

token: str  = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
secret: str = "yyyyyyyyyyyyyyyyyyyyyyyyyyyy"
devid: str  = "zzzzzzz"
ip: str     = "000.000.000.000"

def build_header() -> Dict[str, str]:
    global token, secret
    
    nonce: str = uuid4()
    stamp: int = int(round(time() * 1000))

    data: str = f"{token}{stamp}{nonce}"
    data_b: bytes = bytes(data, "utf-8")
    secret_b = bytes(secret, "utf-8")

    sign = b64encode(hmac.new(secret_b, msg=data_b, digestmod=sha256).digest())

    return {
        "Authorization": token,
        "Content-Type": "application/json",
        "charset": "utf8",
        "t": str(stamp),
        "sign": sign,
        "nonce": str(nonce),
    }

def power_on() -> None:
    global devid

    request(
        "POST",
        f"https://api.switch-bot.com/v1.1/devices/{devid}/commands",
        headers=build_header(),
        data=json.dumps({"commandType": "command", "command": "turnOn", "parameter": "default"}),
    )

def power_off() -> None:
    global devid

    request(
        "POST",
        f"https://api.switch-bot.com/v1.1/devices/{devid}/commands",
        headers=build_header(),
        data=json.dumps({"commandType": "command", "command": "turnOff", "parameter": "default"}),
    )


def is_alive() -> bool:
    result: str = run(f"ping {ip} -n 1 -w 10000", shell=True, text=True, capture_output=True).stdout
    return "100% の損失" not in result

def samba_on() -> None:
    # if NAS is powered off, boot
    if not is_alive():
        eprint("NAS is shutdowned. Re-power with PlugMini")

        power_off()
        power_on()
        eprint("NAS has been rebooted")

        eprint("waiting...")
        sleep(300)

    eprint("NAS has been (re)booted")

    while True:
        if is_alive():
            break
    
    eprint("NAS is powered ON now")

if __name__ == "__main__":
    samba_on()
    input("Press Any Key...")
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?