Ich beschäftige mich auch gerade mit dem Thema. Der Thread hier und auch die anderen Vorschläge im Forum haben mir sehr geholfen. Vielen Dank!
Hier ist meine Lösung, die auch den Absender überprüft. Die Steuerbefehle werden in eckigen Klammern übergeben. Der Befehl beispielsweise schaltet das erste Relais. Die Steuerungsbefehle können nach dem Schema beliebig erweitert werden.
Es hat jedoch einen Schönheitsfehler: Wenn ein Angreifer die korrekte Absendernummer weiß, kann er diese den Steuerbefehlen in der SMS voranstellen. In diesem Fall müsste er aber genau wissen welche Befehle angenommen werden und es würde eine Bestätigungs-SMS an die hinterlegte Handynummer gehen. Für meinen Einsatzzweck ist das etwas womit ich leben kann. Falls jemand jedoch seine Haustür damit absichern möchte, dann sollte er sich darüber im Klaren sein. Über Verbesserungsvorschläge würde ich mich freuen.
Viel Spaß damit.
Nachtrag: Ich benutze ein Siemens TC 35. Bei anderen GSM Modulen kann ggf. die Baud-Rate hochgesetzt werden. Wenn Ihr den Code übernehmt, dann denkt daran die Baud-Rate im Serial-Monitor auf 4800 einzustellen.
Edit 2015-05-03: Ich habe den Code nochmal verfeinert und einen Bug behoben. Nun ist es eine bessere Vorlage.
Edit 2015-05-24: Code nochmals geändert und einen Bug behoben.
#include <SoftwareSerial.h>
SoftwareSerial gsm(2,3);
const int PowerLED = 4; // Power-LED red
const int InfoLED = 5; // Info-LED red
const int resetGSM = 8; // Reset PIN GSM
const int relay01 = 6; // Relais #01
const int relay02 = 7; // Relais #02
const String phoneNo = "491711234567"; // Phone number to send messages to and
// which is allowed to operate the system
void setup() {
Serial.begin(4800); // set the serial for debugging
gsm.begin(4800); // set the GSM serial
Serial.println("Initializing system...");
// Set up the LED pin to be an output:
pinMode(PowerLED, OUTPUT);
pinMode(InfoLED, OUTPUT);
pinMode(resetGSM, OUTPUT);
pinMode(relay01, OUTPUT);
pinMode(relay02, OUTPUT);
digitalWrite(PowerLED, HIGH);
digitalWrite(relay01, HIGH);
digitalWrite(relay02, HIGH);
// Waking up the Siemens TC35 (same as pressing the reset button on the device)
delay(3000);
digitalWrite(resetGSM, HIGH);
digitalWrite(resetGSM, LOW);
delay(100);
digitalWrite(resetGSM, HIGH);
delay(3000);
gsm.println("AT+CMGF=1"); // putting GSM device into text mode
delay(100);
while( gsm.available() ) gsm.read();
delay(3000);
deleteAllSMS();
int SMSCounter = 0; // variable to store amount of SMS
Serial.println("Ready.");
Serial.println("");
Serial.println("System started. Waiting for SMS...");
digitalWrite(InfoLED, HIGH);
}
void loop() {
digitalWrite(InfoLED, HIGH);
char c;
boolean newSMS = false;
boolean authSucc = false;
boolean cmdSucc = false;
boolean ack = false;
String auth = "";
String command = "";
String report = "";
delay(1000);
gsm.println("AT+CMGL=\"REC UNREAD\"");
int count = 5; // Number of 100ms intervals before
// assuming there is no more data
while(count-- != 0) { // Loop until count = 0
delay(100); // Delay 100ms
while ( gsm.available() ){ // If there is data read it
c = char( gsm.read() );
//Serial.print(c); // Uncomment for debugging
auth = auth + String( c ); // putting gsm.read() into auth
if ( auth.endsWith( "+CMGL:" ) ) newSMS = true; // trigger for new SMS
if ( auth.endsWith( phoneNo ) ) authSucc = true; // checking auth against phoneNo
if ( authSucc && auth.endsWith( "<" ) ) cmdSucc = true; // begin parsing the command on a "<"
if ( authSucc && cmdSucc ) command = command + String( c ); // putting gsm.read() into command
if ( auth.endsWith( ">" ) ) cmdSucc = false; // end parsing the command on a ">"
// at this point we have checked that the sender
// has the defined phone number (however this is tricky since a hacker may
// put the phone number in the SMS message text - so it is not 100% secure
// I had not time for final testing yet - use with caution)
// and we have the command that shall be executed in the variable 'command'
count = 5;
}
}
if ( newSMS ) {
digitalWrite(InfoLED, LOW);
SMSCounter++;
report = "Command '" + command + "' received.";
Serial.println("SMS received! SMS Count is: " + String( SMSCounter ));
if ( authSucc ) Serial.println( "Auth success. Command is: " + command );
else {
Serial.println("No valid authentication. Reporting possible break-in attempt.");
report = "Attention! Unknown sender tried to send a message to this device. Possible break-in attempt.";
command = "<Alert>";
}
// Code for command <Relay01>
if ( command.equals( "<Relay01>" ) ) {
Serial.println("Engaging Relay01.");
digitalWrite(relay01, LOW);
delay(1000);
digitalWrite(relay01, HIGH);
report = report + " Relay01 engaged.";
ack = true;
}
// Code for command <Relay02>
if ( command.equals( "<Relay02>" ) ) {
Serial.println("Engaging Relay02.");
digitalWrite(relay02, LOW);
delay(1000);
digitalWrite(relay02, HIGH);
report = report + " Relay02 engaged.";
ack = true;
}
// Code for command <Status>
if ( command.equals( "<Status>" ) ) {
Serial.println("Reporting status to " + phoneNo );
report = report + " Status is up and running."; // you may want to add some other stuff here like temperature or else
ack = true;
}
// Code for command <Info>
if ( command.equals( "<Info>" ) ) {
Serial.println("Sending command info to " + phoneNo );
report = report + " You can use: <Relay01>, <Relay02>, <Status> and <Info> as command.";
ack = true;
}
// Code for command <Alert>
if ( command.equals( "<Alert>" ) ) {
Serial.println("Sending possible break-in alert to " + phoneNo );
ack = true;
}
if ( !ack ) {
Serial.println("Command not recognized. Aborting.");
report = report + " Command not recognized. Aborting. Send <Info> for a list of commands.";
}
sendSMS( report , phoneNo ); // be careful if there is a prepaid SIM card in the device since it will produce costs
delay(1000);
SMSCounter++;
if ( SMSCounter > 12 ) { deleteAllSMS(); SMSCounter = 0; } // Adapt to the storage capacity of the SIM card. Notice that messages will be sent, too.
delay(1000);
}
}
void sendSMS(String message , String receiverNo ) {
gsm.print("AT+CMGF=1\r");
delay(100);
gsm.println("AT+CMGS=\"+" + receiverNo + "\"");
delay(100);
gsm.print( message );
delay(100);
gsm.println((char)26);
}
void callNumber() {
gsm.println("AT"); // Wake-up GSM module
gsm.println("ATD<+"+ phoneNo + ">;"); // Call phoneNo (for i.e. emergencies)
delay(10000); // Wait some seconds to establish the call
gsm.println("AT+CHUP"); // Hang up (to be more precise: AT+CHUP closes all connections)
}
void deleteAllSMS()
{
digitalWrite(InfoLED, LOW);
Serial.println("Clearing SMS storage...");
char c;
delay(300);
for ( int i=1 ; i<=20 ; i++ )
{
gsm.println("AT+CMGD=" + String( i )); // delete all SMS
int count = 5; // Number of 100ms intervals before
// assuming there is no more data
while(count-- != 0) { // Loop until count = 0
delay(100); // Delay 150ms
while (gsm.available() > 0){ // If there is data, read it and reset
c = (char)gsm.read(); // the counter, otherwise go try again
//Serial.print(c);
count = 5;
}
}
}
Serial.println("SMS storage cleared.");
digitalWrite(InfoLED, HIGH);
}