Adding remote power cycle / reboot capabilities to an isolated home assistant system without people with an SMS gateway
I have some RPI’s that are remote, and it takes days to get humans to the location.
In the last 5 years I had to reboot the whole stack 3 times, so here’s the automation setup to reboot it all remotely with an SMS (asuming the home assistant is up 🙂
Add https://github.com/PavelVe/home-assistant-addons to your addon’s (or whatever)

Have MQTT set up on your HA




optional: add an sms gateway user / pwd



Install & configure the SMS addon, throw in your newly created credentials

start up the gateway

it should show up

Activating the Orange simcard
Activating an Orange Mobicarte SIM via AT Commands on a SIM800C
Context
I had a SIM800C GSM modem connected to a Home Assistant instance via a CH340 USB-to-serial adapter (/dev/ttyUSB0). The SMS Gammu Gateway addon was failing to send SMS with Gammu Error Code 27, which translates to +CMS ERROR: 69 ("Requested
facility not subscribed") at the AT command level.
Before debugging, I stopped the SMS gateway addon to free the serial port:
ha addons stop 06c5e726_sms_gammu_gateway
Serial port setup
All commands use the same setup — configure the serial port and open a file descriptor:
stty -F /dev/ttyUSB0 9600 cs8 -cstopb -parenb -echo raw
exec 3<>/dev/ttyUSB0
Calling 225 to activate the SIM
Orange France requires you to call 225 to activate a Mobicarte and receive your phone number via SMS.
# Dial 225 as a voice call (the semicolon makes it a voice call)
echo -ne "ATD225;\r" >&3
Response:
OK
After ~30 seconds the call ends:
NO CARRIER
Hang up cleanly:
echo -ne "ATH\r" >&3
Reading the received SMS
First, switch to text mode and set SMS storage to SIM card:
echo -ne "AT+CMGF=1\r" >&3 # Text mode
echo -ne "AT+CSCS=\"GSM\"\r" >&3 # GSM charset
echo -ne "AT+CPMS=\"SM\",\"SM\",\"SM\"\r" >&3 # Use SIM storage
Then list all messages:
echo -ne "AT+CMGL=\"ALL\"\r" >&3
Response (4-part concatenated SMS from Orange):
Orange : Votre numéro mobicarte est le +33XXXXXXXXX. Conditions de l'offre sur https://r.orange.fr/r/Srcmobi . Vous pouvez recharger votre compte dans les boutiques orange, boutique.orange.fr ou travel.orange.com
Bonus: Checking prepaid balance via USSD
echo -ne "AT+CUSD=1,\"#123#\"\r" >&3
Response:
Accueil
Crédit rechargé: épuisé
Validité de la ligne: 24/08
"épuisé" = exhausted — the SIM had zero credit, which was the root cause of the SMS send failures.
Summary
┌────────────────────────┬────────────────────────────────────┐
│ AT Command │ Purpose │
├────────────────────────┼────────────────────────────────────┤
│ ATD225; │ Voice call to 225 (SIM activation) │
├────────────────────────┼────────────────────────────────────┤
│ ATH │ Hang up │
├────────────────────────┼────────────────────────────────────┤
│ AT+CMGF=1 │ Switch to SMS text mode │
├────────────────────────┼────────────────────────────────────┤
│ AT+CPMS="SM","SM","SM" │ Set storage to SIM card │
├────────────────────────┼────────────────────────────────────┤
│ AT+CMGL="ALL" │ List all SMS messages │
├────────────────────────┼────────────────────────────────────┤
│ AT+CMGR=N │ Read message N │
├────────────────────────┼────────────────────────────────────┤
│ AT+CUSD=1,"#123#" │ USSD balance check │
└────────────────────────┴────────────────────────────────────┘
adding the shell command.
I have NUT running so claude came up with this NC command to reboot the UPS
(I initally had a simple docker exec, but docker isn’t a recognised command)
shell_command: powercyle_ups: docker exec addon_a0d7b954_nut upscmd -u nut -p beepboop APC shutdown.reboot
shell_command: powercycle_ups: 'printf "USERNAME nut\nPASSWORD beepboop\nINSTCMD APC shutdown.reboot\nLOGOUT\n" | nc -w 3 a0d7b954-nut 3493'
for the automation part, I have an allow list of phone numbers who can text reboot
alias: "[SMS] Reboot Cabinet"
description: Power cycle server cabinet via UPS when SMS reboot command is received
triggers:
- entity_id: sensor.sms_gateway_last_sms_received
trigger: state
conditions:
- condition: and
conditions:
- condition: template
value_template: "{{ trigger.to_state.state | lower | trim == \"reboot\" }}"
- condition: template
value_template: >-
{{ state_attr("sensor.sms_gateway_last_sms_received", "Number") in
["+3200000000", "+3200000001", "+3200000002"] }}
actions:
- action: shell_command.powercycle_ups
data: {}
mode: single