← Back to list

Bonus II — Device Monitoring

Hope so that the Bonus I part was a great read.

Darryl Mathias · 2026-06-03 12:46 · 0 claps · 4.4 min read
#termux #api #bash #android #logging-and-monitoring
Open on Medium ↗

Bonus II — Device Monitoring

Hope so that the Bonus I part was a great read.

Now, we’ll move forward to an important aspect of servers — monitoring.

This is the second bonus blog in the series:

  1. **Can a Phone Be a Server?**
  2. **Part 0: Android (The OS Is the Enemy)**
  3. **Part 1: Termux — Linux on Android (Done Right)**
  4. **Part 2: Installations, Builds & Debugging Hell**
  5. **Part 3: Networking & Cloudflare Tunnel**
  6. **Part 4: Persistence, Stability & Long-term Uptime**
  7. **Bonus I — Auto Deployment**
  8. **Bonus II — Device Monitoring — (this post)**

In Part 4 of the series, we had already discussed on persistence and it’s importance for production grade servers. In this blog, our key focus will be more on maintenance and monitoring, and as a byproduct enhanced persistence.

Why Monitoring Matters

In Part 4 of the series, we discussed persistence and why a server must be able to survive crashes, reboots, and unexpected interruptions.

However, persistence alone does not guarantee reliability.

A server can continue running while silently developing problems:

  • The battery may stop charging.
  • Device temperature may rise beyond safe operating limits.
  • Storage may become full.
  • Memory pressure may increase.

Unlike traditional cloud servers, an Android device was never designed to operate continuously as a production server. It lacks enterprise monitoring tools and dedicated management interfaces. As a result, detecting issues often requires manually checking the device.

For a server that is expected to run unattended for days or weeks, I found this approach to be impractical.

To solve this problem, I built a lightweight monitoring system capable of:

  • Reporting charging state changes.
  • Reporting higher temperature levels.
  • Retrieving live device statistics on demand.
  • Sending notifications whenever intervention is required.

The goal was not to build a complex observability platform, but rather a simple monitoring layer that would immediately alert me whenever the phone’s health became a concern.

System Architecture

The monitoring system consists of three major components:

  1. Monitoring scripts running on the Android device.
  2. A lightweight monitoring API exposed through Cloudflare Tunnel.
  3. An email notification service powered by Resend.

The following diagram illustrates the overall architecture:

System architecture of the monitoring layer

System architecture of the monitoring layer

Monitoring Battery State

One of the biggest risks of running a phone as a server is power loss. If charging stops unexpectedly, the device will eventually shut down and take every hosted service with it.

To prevent this, I created a small monitoring script that continuously watches the device’s charging state using Termux’s termux-battery-status command (GOATed Termux).

The script stores the previous charging state and compares it against the current one. Instead of sending notifications every 30 seconds, an alert is generated only when a state change occurs. I specifically chose this event-based architecture to avoid receiving a ton of e-mails.

if [[ "$STATE" != "$LAST_STATE" ]]; then

This simple check prevents notification spam while ensuring important events such as:

  • Charging → Discharging
  • Discharging → Charging
  • Charging → Full

are reported immediately.

When a change is detected, the script sends a request to the monitoring server, which in turn delivers an email notification through Resend.

Monitoring Device Temperature

Heat is one of the biggest enemies of Android. Continuous workloads, charging, and poor airflow can all contribute to higher temperatures.

To monitor this, I built a second script that periodically checks the device temperature.

TEMP=$(echo "$BATTERY" | jq -r '.temperature')

The value is compared against a predefined threshold. I personally found 45 to the best threshold beyond which the operation of a mobile isn’t safe.

temp.sh

#!/data/data/com.termux/files/usr/bin/bash

API_URL="https://portfolio-monitoring.darrylmathias.tech"
API_SECRET="secret"

THRESHOLD=45
ALERT_SENT=false

echo "Temperature monitor started..."

while true; do
    BATTERY=$(termux-battery-status)

    TEMP=$(echo "$BATTERY" | jq -r '.temperature')

    echo "Current temperature: ${TEMP}°C"

    TEMP_INT=${TEMP%.*}

    if (( TEMP_INT >= THRESHOLD )); then

        if [[ "$ALERT_SENT" == false ]]; then
            echo "Temperature threshold crossed!"

            curl -s \
                "$API_URL/temp-alert?token=$API_SECRET&temp=$TEMP" \
                >/dev/null

            ALERT_SENT=true
        fi

    else
        ALERT_SENT=false
    fi

    sleep 60
done

If the threshold is exceeded, an alert is triggered.

A small but important addition is the ALERT_SENT flag. Without it, the script would send an email every minute while the device remained hot.

Using this variable, the email is only sent when the device crosses the threshold, like 44 -> 47and not when 46 -> 48preventing spam.

On-Demand Device Statistics

Alerts are useful, but sometimes I simply want to inspect the current state of the server.

For this purpose, I created a /stats endpoint that executes a shell script and returns live device information.

You may yourself try it out at: https://portfolio-monitoring.darrylmathias.tech/stats

The script collects:

  • Battery percentage and health
  • Temperature
  • RAM usage
  • Storage usage
  • System uptime
  • Network information

and returns everything as structured JSON.

Rather than constantly collecting metrics and storing them in a database, statistics are generated only when requested. This keeps the implementation lightweight while still providing real-time visibility into the device.

stats.sh

#!/data/data/com.termux/files/usr/bin/bash

BATTERY=$(termux-battery-status)

PERCENT=$(echo "$BATTERY" | jq '.percentage')
STATUS=$(echo "$BATTERY" | jq -r '.status')
PLUGGED=$(echo "$BATTERY" | jq -r '.plugged')
TEMP=$(echo "$BATTERY" | jq '.temperature')
HEALTH=$(echo "$BATTERY" | jq -r '.health')
VOLTAGE=$(echo "$BATTERY" | jq '.voltage')
CURRENT=$(echo "$BATTERY" | jq '.current')

UPTIME=$(uptime -p)

RAM=$(free -h | awk '/Mem:/ {print $3 " / " $2}')

STORAGE=$(df -h /data | awk 'NR==2 {print $3 " / " $2}')

LOAD_AVG=$(cat /proc/loadavg | awk '{print $1}')

WIFI=$(termux-wifi-connectioninfo 2>/dev/null)

SSID=$(echo "$WIFI" | jq -r '.ssid // "N/A"')
IP=$(echo "$WIFI" | jq -r '.ip // "N/A"')
LINK_SPEED=$(echo "$WIFI" | jq -r '.link_speed_mbps // "N/A"')

cat <<EOF
{
  "battery": {
    "percentage": $PERCENT,
    "status": "$STATUS",
    "plugged": "$PLUGGED",
    "temperature": $TEMP,
    "health": "$HEALTH",
    "voltage_mv": $VOLTAGE,
    "current_ua": $CURRENT
  },
  "system": {
    "uptime": "$UPTIME",
    "ram_usage": "$RAM",
    "storage_usage": "$STORAGE",
    "cpu_load_avg": "$LOAD_AVG"
  },
  "network": {
    "ssid": "$SSID",
    "ip_address": "$IP",
    "link_speed_mbps": "$LINK_SPEED"
  },
  "timestamp": "$(date -Iseconds)"
}
EOF

Security Considerations

Since these endpoints are exposed to the internet, basic security measures are essential.

Every request must include a secret token:

if (req.query.token !== process.env.API_SECRET)

Invalid requests are immediately rejected with a403 forbiddenresponse.

I also added rate limiting to prevent abuse and accidental request floods. Combined with Cloudflare Tunnel, this ensures that the monitoring infrastructure remains reasonably secure while still being accessible remotely.

Results

Now that monitoring is in place, I no longer need to manually check the device throughout the day, and hence repetition is avoided :)

The server automatically reports charging interruptions and overheating events, while live system statistics are available on demand. Combined with the persistence mechanisms discussed in Part 4, this monitoring layer significantly improves the reliability of the Android server and makes long-term operation far more practical.

With this, the Android server gained something that most production systems rely on: visibility. Problems are no longer discovered after an outage occurs — the server proactively reports them before they become critical.


메타데이터
post_id
17348474a0fa
slug
bonus-ii-device-monitoring-17348474a0fa
url
https://medium.com/@mathiasndarryl7/bonus-ii-device-monitoring-17348474a0fa
canonical_url
https://medium.com/@mathiasndarryl7/bonus-ii-device-monitoring-17348474a0fa
author_url
https://medium.com/@mathiasndarryl7
status
ok
fetched_at
2026-07-14 20:51:12