sk heavy industries

mining monitor active

miningbitcoin-cashmonitoringautomationbash

Monitors a small fleet of open-source solo-mining boards (Bitaxe / NerdAxe-class) plus the mining pool, run every few hours by the on-device lil-sis agent. Part of the agents system.

 every ~5 hours  (lil-sis cron)
        │
        ▼
 miner-watchdog.sh
        └─ poll each miner's HTTP API; 0 hashrate / no response → restart
        │
        ▼
 full-mining-report.sh
        ├─ miner-status.sh → per-miner info snapshot (hashrate, temp) → JSON
        └─ pool-status.sh  → pool API: hashrate, workers, earnings, balance
                             + live BCH price → balance in USD
        │
        ▼
 lil-sis  →  chat summary: restarts · total hashrate · per-miner · BCH/USD

The hardware

A mix of open-source solo-mining boards, spanning a few ASIC generations:

Board ASICs Clock (stock → tuned) Core V Hashrate Power Efficiency
NerdQAxe++ (×2) BM1370 ×4 600 → 950 MHz 1150 → 1220 mV ~6.2 TH/s each ~100 W ~16 J/TH
Bitaxe-class BM1370 ×1 675 MHz 1150 mV ~1.4 TH/s ~22 W ~15 J/TH
8-chip board BM1368 ×8 600 MHz 1200 mV ~5.0 TH/s ~131 W ~26 J/TH

Combined that's ≈ 18.8 TH/s at ≈ 354 W.

Tuning for hashrate

The headline experiment is on the two NerdQAxe++ boards: clocked from a stock 600 MHz up to 950 MHz (+58%) with only a modest core-voltage bump (1150 → 1220 mV), nearly doubling per-board output to ~6.2 TH/s while holding ~16 J/TH efficiency and ~53 °C die temps under active cooling (~2,350 rpm fans). The single-chip Bitaxe-class board runs lean (~1.4 TH/s at 22 W, ~15 J/TH, the most efficient of the bunch), while the older 8-chip BM1368 board trades efficiency (~26 J/TH) for raw hashrate.

This is exactly what the per-miner snapshots are for: every reading captures frequency, core voltage, hashrate, power, and die temperature, so a setting can be pushed and then judged against the resulting hashrate/temp/efficiency over time, dialing the clocks in without cooking a board. And when a clock is pushed too far and a unit drops to 0, the watchdog catches it and restarts.

Watchdog

miner-watchdog.sh polls each miner's local HTTP API (/api/system/info). If a board is unreachable or reporting 0 hashrate, it issues a restart (POST /api/system/restart) and tallies how many it had to kick, so a hung miner recovers on its own instead of silently sitting dead until the next time someone looks.

for entry in "${MINERS[@]}"; do          # MINERS is a list of name:ip pairs
  name="${entry%%:*}"; ip="${entry##*:}"
  hashrate=$(curl -s --max-time 10 "http://$ip/api/system/info" \
    | python3 -c "import json,sys; print(json.load(sys.stdin).get('hashRate', 0))")
  if [ -z "$hashrate" ] || [ "$hashrate" = "0" ]; then
    echo "restarting $name ($ip): 0 H/s"
    curl -s -X POST "http://$ip/api/system/restart" >/dev/null
  else
    echo "ok $name: ${hashrate} GH/s"
  fi
done

Miner status

miner-status.sh fetches each miner's info and writes a timestamped JSON snapshot, pretty-printing per-miner stats (hashrate, temperature, and the rest of the device telemetry). Over time those snapshots are a lightweight time series of the fleet's health.

Pool status

pool-status.sh queries the mining pool's API for overall hashrate, per-worker stats (10-minute / 1-hour hashrate, reject rate, online status), earnings, and account balance. It then pulls a live BCH price from a public price feed to convert the balance to USD.

# pull the BCH balance from the pool, convert to USD with a live price
bch=$(curl -s "$POOL_API/account?coin=BCH" -H "X-API-KEY: $KEY" \
  | jq -r '.data.balance[] | select(.coin=="BCH").amount')
price=$(curl -s "$PRICE_API?ids=bitcoin-cash&vs_currencies=usd" \
  | jq -r '.["bitcoin-cash"].usd')
printf "BCH %.6f  =  \$%.2f\n" "$bch" "$(echo "$bch * $price" | bc -l)"

Putting it together

full-mining-report.sh runs the miner and pool status back to back; the cron runs the watchdog first, then the report. lil-sis summarizes the whole thing to chat every ~5 hours: any restarts, total hashrate, each miner's hashrate and temperature, and the pool balance in both BCH and USD.

Stack: Bash, curl + jq, miner and pool REST APIs, a price feed, cron via the OpenClaw gateway.