4 TTGO sendet eine Alarm-SMS mit SIM800L
Im Kapitel 3 habe ich dargestellt, wie man mithilfe eines Terminals eine SMS über das SIM800L-Modul versenden kann. Nun möchte ich zeigen, wie eine Alarm-SMS von unserem TTGO verschickt werden kann, wenn z. B. eine Bewegung mit einem PIR-Bewegungsmelder registriert wird.
Im Folgenden soll der Alarm der Einfachheit halber durch Betätigen des Tasters Ta0 des TTGO ausgelöst werden. Es dürfte keine größeren Probleme bereiten, das Programm so abzuändern, dass der Alarm auch durch andere Sensoren ausgelöst werden kann.
Das Programm baut im Wesentlichen auf dem Programm des letzten Kapitels auf. Damit es auch ohne Entwicklungsumgebung eingesetzt werden kann, werden jetzt die wichtigsten Informationen für den Anwender auch auf dem Display angezeigt.
Außerdem wird berücksichtigt, dass die Verbindung zwischen dem SIM800L-Modul und dem GSM-Netz nicht unbedingt schon beim ersten Versuch zustande kommt oder auch nach einem Einloggen wieder abbrechen kann; mit diesem Problem war ich manchmal konfrontiert, weil in meinem Arbeitszimmer das benutzte GSM-Netz recht schwach ist. So kann es vorkommen, dass das vom SIM800L-Modul gesendete Signal nicht von dem benutzten Netz registriert wird oder umgekehrt die vom Funkmast abgestrahlten Antworten nicht oder nur teilweise von meinem Modul empfangen werden konnten. In solchen Fällen wird in der response-Funktion die globale Variable time-out-flag auf True gesetzt; dann wird erneut versucht, die Alarm-SMS zu senden. Wie viele Versuche maximal durchgeführt werden, wird in der Variable max_count festgelegt.
Wird der Alarm z. B. durch einen Bewegungs-/Näherungs-Sensor ausgelöst, muss beachtet werden, dass ggf. in rascher Folge Alarm-Signale beim TTGO ankommen. Damit nun keine riesige Flut von Nachrichten an das Handy gesendet wird, werden nach einem Alarm-Ereignis für eine gewisse Zeitspanne delay_after_alarm keine SMS gesendet.
Weitere Hinweise zur Funktionsweise des Programms finden Sie in den Kommentaren des folgenden Listings.
Code: Alles auswählen
###################################################################################
# Import und Instanziierungen #
###################################################################################
from time import sleep, ticks_ms, ticks_diff
from machine import UART, Pin, SPI
# UART und Taster instanziieren; SIM800L hat autobauding von 1200 bis 57600
uart1 = UART(1, baudrate = 56000, tx = 12, rx = 13)
taster0 = Pin(0, Pin.IN, Pin.PULL_UP)
import vga1_8x16 as font1
import vga1_bold_16x32 as font2
import st7789
# display instanziieren und konfigurieren...
spi = SPI(1, baudrate=20000000, polarity=1, sck=Pin(18), mosi=Pin(19))
display = st7789.ST7789(spi, 135, 240, reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=3)
display.init()
####################################################################################
# Funktionen u. globale Variable zur Kommunikation mit dem SIM800L-Modul #
####################################################################################
pin = b'xxxx'
phone_number = b'0177xxxxxxx'
timeout = 40000 # in ms
message = b'Alarm: Taster0 wurde betaetigt'
delay_after_alarm = 120 # in Sekunden (Ein erneuter Alarm kann erst nach
dieser Zeitspanne gesendet werden.)
time_out_flag = False
count = 0 # zählt Anzahl der Versuche (Wenn ein Time-Out auftritt,
wird ein erneuter Sende-Versuch gestartet; max. 3 Versuche)
max_count = 3
def send_command(uart, cmd): # cmd ist vom Typ Bytes, ohne \r
c = cmd + '\r' # c ist vom Typ Bytes
anzahl_der_gesendeten_zeichen = uart.write(c)
print(anzahl_der_gesendeten_zeichen, 'Zeichen gesendet:', c)
def read_response(uart, search_word, timeout):
global time_out_flag
received = b''
t0 = ticks_ms()
while not (search_word in received) or ('ERROR' in received):
c = uart.read(1) # nur 1 Byte lesen (oder keins)
if c != None:
# print(c)
received = received + c
# print('received:', received) # zum Testen
t1 = ticks_ms()
deltat = ticks_diff(t1, t0)
if deltat > timeout:
time_out_flag = True
break # Abbruch, wenn timeout ms überschritten
# print('Time-Out-Flag', time_out_flag) # zum Testen
print('Test', received)
return str(received, 'UTF-8')
####################################################################################
# Alarm senden #
####################################################################################
def one_alarm(message, uart):
global time_out_flag
# Attention...
cmd = b'AT'
send_command(uart, cmd)
response = read_response(uart1, b'OK\r\n', timeout)
print(response) # zum Testen
sleep(2)
'''
# SIM800L resetten, ggf. zum Auslassen auskommentieren
if not time_out_flag:
cmd = b'ATZ'
send_command(uart, cmd)
response = read_response(uart1, b'OK\r\n', timeout)
print(response)
sleep(2)
'''
# eingeloggt?
if not time_out_flag:
cmd = b'AT+CREG?'
send_command(uart, cmd)
response = read_response(uart1, b'OK\r\n', timeout)
print(response)
logged = '0,1'
if logged in response:
print('SIM bereits im Netz eingeloggt')
print()
else: # einloggen...
cmd = b'AT+CPIN="'+pin+b'"'
send_command(uart, cmd)
response = read_response(uart1, b'SMS Ready\r\n', timeout)
print(response)
sleep(2)
# Message Format: Textmode...
if not time_out_flag:
cmd = b'AT+CMGF=1'
send_command(uart, cmd)
response = read_response(uart1, b'OK\r\n', timeout)
print(response)
sleep(2)
# Text Mode: SMS-SUBMIT, Validity 1 day
if not time_out_flag:
cmd = b'AT+CSMP=17,167,0,0'
send_command(uart, cmd)
response = read_response(uart1, b'OK\r\n', timeout)
print(response)
sleep(2)
# Adressat (Handy-Nr.)
if not time_out_flag:
cmd = b'AT+CMGS="'+phone_number+b'"'
send_command(uart, cmd)
response = read_response(uart1, b'>', timeout)
print(response)
sleep(2)
# Nachricht
if not time_out_flag:
cmd = message + b'\x1A' # \x1A = Ctrl-Z
send_command(uart, cmd)
response = read_response(uart1, b'OK\r\n', timeout)
print(response)
sleep(2)
def alarm(message, uart):
global count
global max_count
global time_out_flag
while count < max_count:
print('count:', count) # zum Testen
one_alarm(message, uart)
if not time_out_flag: # wenn kein Time-Out vorliegt, Schleife abbrechen
print('Alarm-SMS wurde an', phone_number, 'gesendet!')
print()
display.text(font1, 'Alarm-SMS gesendet', 5, 90)
break
else:
display.text(font1, 'Alarm-SMS: Error', 5, 90)
display.text(font1, 'Neuer Versuch in '
+ str(delay_after_alarm) + 's ', 5, 110)
count =+ 1 # sonst count inkrementieren und neuen Versuch starten
time_out_flag = False
##################################################################################
# Hauptprogramm #
##################################################################################
display.fill(0)
print('SMS-Alarm-Programm bereit!')
print('Alarm wird mit Taster0 ausgelöst...')
display.text(font2, 'SMS-Alarm', 40, 5)
display.text(font1, 'Alarm -> Taster Ta0', 5, 50)
while True:
if (taster0.value() == 0): # wenn Taster Ta0 betätigt
print('Alarm!!!')
display.text(font1, 'Alarm ausgeloest...', 5, 70)
alarm(message , uart1)
print('Erneuter Alarm nach', str(delay_after_alarm), 's möglich...')
display.text(font1, 'Alarm moeglich in ', 5, 110)
for i in range(delay_after_alarm): # Countdown der Wartezeit
display.text(font1, str(delay_after_alarm-i) + ' s', 150, 110)
sleep(1)
print()
display.fill(0)
print('SMS-Alarm-Programm bereit!')
print('Alarm wird mit Taster0 ausgelöst...')
display.text(font2, 'SMS-Alarm', 40, 5)
display.text(font1, 'Alarm -> Taster Ta0', 5, 50)
.