update at 2026-03-17 10:37:27
This commit is contained in:
64
scripts/capture-kindle-screen.sh
Normal file
64
scripts/capture-kindle-screen.sh
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
ROOT_DIR=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
|
||||
HOST_TARGET=${1:-kindle}
|
||||
OUTPUT_BASENAME=${2:-current-screen}
|
||||
OUTPUT_DIR=${3:-"$ROOT_DIR/tmp"}
|
||||
RUNTIME_ENV_PATH=/mnt/us/dashboard/local/state/theme-runtime.env
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
raw_path="$OUTPUT_DIR/${OUTPUT_BASENAME}-raw.png"
|
||||
physical_path="$OUTPUT_DIR/${OUTPUT_BASENAME}-physical.png"
|
||||
tmp_download_path="$OUTPUT_DIR/${OUTPUT_BASENAME}-download.tmp"
|
||||
|
||||
read_remote_value() {
|
||||
key=$1
|
||||
ssh "$HOST_TARGET" "awk -F= '/^export ${key}=/{gsub(\"\\047\", \"\", \$2); print \$2; exit}' \"$RUNTIME_ENV_PATH\" 2>/dev/null || true"
|
||||
}
|
||||
|
||||
orientation=$(read_remote_value ORIENTATION)
|
||||
device_placement=$(read_remote_value THEME_DEVICE_PLACEMENT)
|
||||
|
||||
ssh "$HOST_TARGET" '
|
||||
set -eu
|
||||
capture_path="/tmp/kindle-dashboard-capture-$$.png"
|
||||
fbgrab "$capture_path" >/dev/null 2>&1
|
||||
cat "$capture_path"
|
||||
rm -f "$capture_path"
|
||||
' >"$tmp_download_path"
|
||||
|
||||
python3 - "$tmp_download_path" "$raw_path" <<'PY'
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
download_path = Path(sys.argv[1])
|
||||
raw_path = Path(sys.argv[2])
|
||||
data = download_path.read_bytes()
|
||||
magic = b"\x89PNG\r\n\x1a\n"
|
||||
index = data.find(magic)
|
||||
if index == -1:
|
||||
raise SystemExit("抓屏结果里没有找到 PNG 头")
|
||||
|
||||
raw_path.write_bytes(data[index:])
|
||||
download_path.unlink(missing_ok=True)
|
||||
PY
|
||||
|
||||
case "$orientation:$device_placement" in
|
||||
landscape:logo_right)
|
||||
cp "$raw_path" "$physical_path"
|
||||
# 原始 fbgrab 输出始终是纵向 framebuffer。
|
||||
# Logo 在右侧时,日常评审应优先看 physical 图;
|
||||
# 它等于把 raw 图按设备实际摆放方向逆时针旋转 90 度。
|
||||
sips -r 270 "$physical_path" >/dev/null
|
||||
;;
|
||||
*)
|
||||
cp "$raw_path" "$physical_path"
|
||||
;;
|
||||
esac
|
||||
|
||||
printf 'raw=%s\n' "$raw_path"
|
||||
printf 'physical=%s\n' "$physical_path"
|
||||
printf 'orientation=%s\n' "${orientation:-unknown}"
|
||||
printf 'devicePlacement=%s\n' "${device_placement:-unknown}"
|
||||
@@ -2,9 +2,68 @@
|
||||
set -eu
|
||||
|
||||
ROOT_DIR="$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)"
|
||||
KINDLE_TARGET=${1:-kindle}
|
||||
KINDLE_TARGET="kindle"
|
||||
THEME_FILTER=""
|
||||
ORIENTATION_FILTER=""
|
||||
CLOCK_REGION_JSON="$ROOT_DIR/calendar/dist/clock-region.json"
|
||||
|
||||
print_usage() {
|
||||
cat <<'EOF'
|
||||
用法:
|
||||
sh scripts/sync-layered-clock-to-kindle.sh [host] [选项]
|
||||
|
||||
选项:
|
||||
--theme <theme-id> 只同步指定主题
|
||||
--orientation <value> 只同步指定方向;必须和 --theme 一起使用
|
||||
-h, --help 查看帮助
|
||||
|
||||
示例:
|
||||
sh scripts/sync-layered-clock-to-kindle.sh kindle
|
||||
sh scripts/sync-layered-clock-to-kindle.sh kindle --theme simple
|
||||
sh scripts/sync-layered-clock-to-kindle.sh kindle --theme simple --orientation portrait
|
||||
EOF
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--theme)
|
||||
shift
|
||||
THEME_FILTER=${1:?"missing theme id"}
|
||||
;;
|
||||
--orientation)
|
||||
shift
|
||||
ORIENTATION_FILTER=${1:?"missing orientation"}
|
||||
;;
|
||||
-h|--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
KINDLE_TARGET=$1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -n "$ORIENTATION_FILTER" ] && [ -z "$THEME_FILTER" ]; then
|
||||
echo "--orientation 必须和 --theme 一起使用。" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$ROOT_DIR/calendar"
|
||||
if [ -n "$THEME_FILTER" ]; then
|
||||
if [ -n "$ORIENTATION_FILTER" ]; then
|
||||
npm run export:themes -- --theme "$THEME_FILTER" --orientation "$ORIENTATION_FILTER" >/dev/null
|
||||
CLOCK_REGION_JSON="$ROOT_DIR/calendar/dist/themes/$THEME_FILTER/$ORIENTATION_FILTER/kindlebg.clock-region.json"
|
||||
else
|
||||
npm run export:themes -- --theme "$THEME_FILTER" >/dev/null
|
||||
CLOCK_REGION_JSON=""
|
||||
fi
|
||||
else
|
||||
npm run export:themes >/dev/null
|
||||
fi
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
clock_region_value() {
|
||||
key=$1
|
||||
python3 - "$CLOCK_REGION_JSON" "$key" <<'PY'
|
||||
@@ -25,46 +84,105 @@ print(data[key])
|
||||
PY
|
||||
}
|
||||
|
||||
clock_x=$(clock_region_value x)
|
||||
clock_y=$(clock_region_value y)
|
||||
clock_width=$(clock_region_value width)
|
||||
clock_height=$(clock_region_value height)
|
||||
sync_dashboard_runtime() {
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/dash/src/start.sh" \
|
||||
"$ROOT_DIR/dash/src/dash.sh" \
|
||||
"$ROOT_DIR/dash/src/switch-theme.sh" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/
|
||||
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/dash/src/dash.sh" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/dash/src/local/env.sh" \
|
||||
"$ROOT_DIR/dash/src/local/fetch-dashboard.sh" \
|
||||
"$ROOT_DIR/dash/src/local/clock-index.sh" \
|
||||
"$ROOT_DIR/dash/src/local/render-clock.lua" \
|
||||
"$ROOT_DIR/dash/src/local/render-clock.sh" \
|
||||
"$ROOT_DIR/dash/src/local/theme-menu-service.sh" \
|
||||
"$ROOT_DIR/dash/src/local/theme-json.lua" \
|
||||
"$ROOT_DIR/dash/src/local/theme-sync.sh" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/local/
|
||||
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/dash/src/local/fetch-dashboard.sh" \
|
||||
"$ROOT_DIR/dash/src/local/clock-index.sh" \
|
||||
"$ROOT_DIR/dash/src/local/render-clock.lua" \
|
||||
"$ROOT_DIR/dash/src/local/render-clock.sh" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/local/
|
||||
ssh "$KINDLE_TARGET" "chmod +x /mnt/us/dashboard/start.sh /mnt/us/dashboard/dash.sh /mnt/us/dashboard/switch-theme.sh /mnt/us/dashboard/local/fetch-dashboard.sh /mnt/us/dashboard/local/clock-index.sh /mnt/us/dashboard/local/render-clock.sh /mnt/us/dashboard/local/theme-menu-service.sh /mnt/us/dashboard/local/theme-sync.sh"
|
||||
ssh "$KINDLE_TARGET" "mkdir -p /mnt/us/dashboard/local/state"
|
||||
ssh "$KINDLE_TARGET" "date '+%s' >/mnt/us/dashboard/local/state/background-updated-at"
|
||||
}
|
||||
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/calendar/dist/kindlebg.png" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/
|
||||
sync_theme_bundle() {
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/calendar/dist/themes.json" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/
|
||||
|
||||
ssh "$KINDLE_TARGET" "chmod +x /mnt/us/dashboard/dash.sh /mnt/us/dashboard/local/fetch-dashboard.sh /mnt/us/dashboard/local/clock-index.sh /mnt/us/dashboard/local/render-clock.sh"
|
||||
if [ -z "$THEME_FILTER" ]; then
|
||||
if [ -f "$ROOT_DIR/calendar/dist/kindlebg.png" ]; then
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/calendar/dist/kindlebg.png" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/
|
||||
fi
|
||||
|
||||
ssh "$KINDLE_TARGET" "mkdir -p /mnt/us/dashboard/local/state"
|
||||
ssh "$KINDLE_TARGET" "date '+%s' >/mnt/us/dashboard/local/state/background-updated-at"
|
||||
ssh "$KINDLE_TARGET" "tmp=\$(mktemp) && awk \
|
||||
-v x='$clock_x' \
|
||||
-v y='$clock_y' \
|
||||
-v w='$clock_width' \
|
||||
-v h='$clock_height' \
|
||||
'BEGIN { seen_x=0; seen_y=0; seen_w=0; seen_h=0 } \
|
||||
/^export CLOCK_REGION_X=/ { print \"export CLOCK_REGION_X=\" x; seen_x=1; next } \
|
||||
/^export CLOCK_REGION_Y=/ { print \"export CLOCK_REGION_Y=\" y; seen_y=1; next } \
|
||||
/^export CLOCK_REGION_WIDTH=/ { print \"export CLOCK_REGION_WIDTH=\" w; seen_w=1; next } \
|
||||
/^export CLOCK_REGION_HEIGHT=/ { print \"export CLOCK_REGION_HEIGHT=\" h; seen_h=1; next } \
|
||||
{ print } \
|
||||
END { \
|
||||
if (!seen_x) print \"export CLOCK_REGION_X=\" x; \
|
||||
if (!seen_y) print \"export CLOCK_REGION_Y=\" y; \
|
||||
if (!seen_w) print \"export CLOCK_REGION_WIDTH=\" w; \
|
||||
if (!seen_h) print \"export CLOCK_REGION_HEIGHT=\" h; \
|
||||
}' /mnt/us/dashboard/local/env.sh >\"\$tmp\" && cat \"\$tmp\" >/mnt/us/dashboard/local/env.sh && rm -f \"\$tmp\""
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/calendar/dist/themes/" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/themes/
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Layered clock runtime synced to $KINDLE_TARGET"
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/calendar/dist/themes/$THEME_FILTER.json" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/themes/
|
||||
|
||||
if [ -n "$ORIENTATION_FILTER" ]; then
|
||||
ssh "$KINDLE_TARGET" "mkdir -p /mnt/us/dashboard/themes/$THEME_FILTER/$ORIENTATION_FILTER"
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/calendar/dist/themes/$THEME_FILTER/$ORIENTATION_FILTER/" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/themes/$THEME_FILTER/$ORIENTATION_FILTER/
|
||||
return
|
||||
fi
|
||||
|
||||
ssh "$KINDLE_TARGET" "mkdir -p /mnt/us/dashboard/themes/$THEME_FILTER"
|
||||
rsync -av --no-o --no-g \
|
||||
"$ROOT_DIR/calendar/dist/themes/$THEME_FILTER/" \
|
||||
"$KINDLE_TARGET":/mnt/us/dashboard/themes/$THEME_FILTER/
|
||||
}
|
||||
|
||||
update_default_clock_region_env() {
|
||||
if [ -z "$CLOCK_REGION_JSON" ] || [ ! -f "$CLOCK_REGION_JSON" ]; then
|
||||
echo "Skipped CLOCK_REGION_* env update: no single background region selected"
|
||||
return
|
||||
fi
|
||||
|
||||
clock_x=$(clock_region_value x)
|
||||
clock_y=$(clock_region_value y)
|
||||
clock_width=$(clock_region_value width)
|
||||
clock_height=$(clock_region_value height)
|
||||
|
||||
ssh "$KINDLE_TARGET" "tmp=\$(mktemp) && awk \
|
||||
-v x='$clock_x' \
|
||||
-v y='$clock_y' \
|
||||
-v w='$clock_width' \
|
||||
-v h='$clock_height' \
|
||||
'BEGIN { seen_x=0; seen_y=0; seen_w=0; seen_h=0 } \
|
||||
/^export CLOCK_REGION_X=/ { print \"export CLOCK_REGION_X=\" x; seen_x=1; next } \
|
||||
/^export CLOCK_REGION_Y=/ { print \"export CLOCK_REGION_Y=\" y; seen_y=1; next } \
|
||||
/^export CLOCK_REGION_WIDTH=/ { print \"export CLOCK_REGION_WIDTH=\" w; seen_w=1; next } \
|
||||
/^export CLOCK_REGION_HEIGHT=/ { print \"export CLOCK_REGION_HEIGHT=\" h; seen_h=1; next } \
|
||||
{ print } \
|
||||
END { \
|
||||
if (!seen_x) print \"export CLOCK_REGION_X=\" x; \
|
||||
if (!seen_y) print \"export CLOCK_REGION_Y=\" y; \
|
||||
if (!seen_w) print \"export CLOCK_REGION_WIDTH=\" w; \
|
||||
if (!seen_h) print \"export CLOCK_REGION_HEIGHT=\" h; \
|
||||
}' /mnt/us/dashboard/local/env.sh >\"\$tmp\" && cat \"\$tmp\" >/mnt/us/dashboard/local/env.sh && rm -f \"\$tmp\""
|
||||
}
|
||||
|
||||
sync_dashboard_runtime
|
||||
sync_theme_bundle
|
||||
update_default_clock_region_env
|
||||
|
||||
if [ -n "$THEME_FILTER" ]; then
|
||||
if [ -n "$ORIENTATION_FILTER" ]; then
|
||||
echo "Layered clock runtime synced to $KINDLE_TARGET (theme=$THEME_FILTER orientation=$ORIENTATION_FILTER)"
|
||||
else
|
||||
echo "Layered clock runtime synced to $KINDLE_TARGET (theme=$THEME_FILTER)"
|
||||
fi
|
||||
else
|
||||
echo "Layered clock runtime synced to $KINDLE_TARGET"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user