perkun.eu Services Portfolio Blog About Contact PL
← Blog

12/9/2024

Solar installation SMS alert system for under $15

TL;DR: Twilio SMS API + Python + Node-RED. Cost: $0.04/SMS. If the installation produces < 20% of the seasonal norm for 2 hours — SMS. Twilio Free Trial = $15 credit to start — enough for over a year of alerts at sensible usage levels.

A photovoltaic installation normally runs unattended. You find out about problems when the electricity bills return to pre-solar levels, or when you happen to check the app. An SMS alert system notifies you when something’s wrong — a cable came loose, the inverter is showing an error, a new tree’s shadow is blocking panels.

Twilio setup

Registering an account at twilio.com is free. The Free Trial gives you $15 credit — at $0.04/SMS that’s 375 messages, enough for over a year of normal use.

Buy a Twilio number (US: $1/month, or use the Free Trial number with limitations). Download from the dashboard: Account SID and Auth Token.

pip install twilio

Sending an SMS in Python:

from twilio.rest import Client

account_sid = "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
auth_token  = "your_auth_token"
client = Client(account_sid, auth_token)

def send_alert(message: str, to_number: str = "+48600123456"):
    client.messages.create(
        body=message,
        from_="+12025551234",  # your Twilio number
        to=to_number,
    )
    print(f"SMS sent: {message}")

Five lines of code. There’s no simpler SMS API.

Data from the installation

We assume solar installation data is already in InfluxDB (MQTT from the inverter or MPPT controller → Telegraf → InfluxDB v2). Flux query fetching the average production over the last 2 hours:

from(bucket: "solar")
  |> range(start: -2h)
  |> filter(fn: (r) => r._measurement == "mppt" and r._field == "panel_power_w")
  |> mean()
  |> yield(name: "avg_production_2h")

The result is average power in watts. For a 3 kWp installation in July at noon you’d expect ~2000–2500W. If it returns 300W at 12:00 on a sunny day — something is wrong.

Alert logic in Node-RED

The Node-RED flow consists of five nodes:

1. Inject (every hour): Trigger that runs the flow every 60 minutes throughout the day.

2. InfluxDB In: Executes the Flux query for the last 2 hours, returns average power as msg.payload.

3. Function node — alert logic:

const avgPower = msg.payload[0]?._value ?? 0;
const month = new Date().getMonth() + 1; // 1-12

// Seasonal norms for a 3 kWp installation [W]
const norms = {
    1: 150, 2: 250, 3: 450, 4: 700, 5: 900, 6: 1000,
    7: 950, 8: 850, 9: 600, 10: 350, 11: 180, 12: 120
};

const threshold = norms[month] * 0.20; // 20% of norm = alert threshold
const hour = new Date().getHours();

// Alert only during daylight hours (9:00–17:00)
if (hour < 9 || hour > 17) {
    return null; // don't send alerts at night
}

if (avgPower < threshold) {
    msg.alertMessage = `SOLAR ALERT: production ${Math.round(avgPower)}W < threshold ${Math.round(threshold)}W (norm ${norms[month]}W). Check the installation.`;
    return msg;
}

return null; // all good

4. HTTP Request to Twilio API (or call Python script):

Twilio endpoint via HTTP POST with Basic Auth (Account SID + Auth Token). Body: Body=...&From=...&To=... (form-urlencoded).

5. InfluxDB Out: Write the alert to InfluxDB with tag type=sms_alert for history and dashboard display.

Anti-spam

Without throttling, the system could send 8 alerts per day (8 hours × 1/h). Over a week of problems — 56 SMS, cost $2.24. Unacceptable.

Solution: Node-RED Context Storage to remember when the last alert was sent:

const lastAlert = context.get('lastAlertTimestamp') ?? 0;
const now = Date.now();
const cooldownMs = 6 * 60 * 60 * 1000; // 6 hour cooldown

if (now - lastAlert < cooldownMs) {
    return null; // too soon for the next alert
}

// If we're sending an alert — save the timestamp
context.set('lastAlertTimestamp', now);
return msg;

Maximum 2 alerts per day (6h cooldown × 2 = 12h coverage during the day). Alternatively, save lastAlertTimestamp to InfluxDB instead of Node-RED context — it’ll survive a Node-RED restart.

Seasonal norms

Norms for a 3 kWp installation on a 35° south-facing roof, central Poland location (52°N). Empirical values averaged from PVGIS data:

MonthDaily norm [kWh]Peak hourly norm [W]
January1.2150
February2.0250
March3.6450
April5.6700
May7.2900
June8.01000
July7.6950
August6.8850
September4.8600
October2.8350
November1.5180
December1.0120

Scaling to your installation size: multiply values by your_peak_kWp / 3. For a 6 kWp installation — multiply by 2.

Summary

An SMS alert system for a solar installation is an afternoon project: Twilio (5 minutes setup), Node-RED flow with logic (2 hours), calibrating seasonal norms (1 hour). Operating cost: $0.04 per SMS × maximum 2 per day × 365 days = $29.20 per year — and that assumes a year-long problem. Under normal conditions, a few alerts per year costs $1–2. Peace of mind for the price of a cup of coffee a month.