|
//-----------------------------------------------------------------------------
// Remote IO.vpl, created 2003-01-04 14:35
//
// This application will monitor upto 16 digital inputs. If any of these changes
// state, the application will send an SMS message to a predefined number containing
// information about which inputs has changed state. When the application receives
// such an SMS message, it will update its own outputs accordingly. The number
// which will receive the status changes, can be set with the "phone=xxx" SMS
// command (see below). All SMS messages can be sent in lower and/or uppercase
//
// Format of SMS messages:
//
// Snn=x;Smm=y;Skk=z
// Where nn,mm and kk is the input number (1..16) and x,y and z is the NEW state
// for the input (0/1).
//
// phone=xxxxxxxx
// Where xxxxxxxx is the number all status changes should be sent to, if blank
// no change of states are reported. The phonenumber will be saved at
// persistent memory location 1
//-----------------------------------------------------------------------------
INCLUDE rtcu.inc
// Input variables that can be configured via the configuration dialog (These are global)
VAR_INPUT
DIn : ARRAY[1..16] OF BOOL; | Digital inputs
END_VAR;
// Output variables that can be configured via the configuration dialog (These are global)
VAR_OUTPUT
DOut : ARRAY[1..16] OF BOOL; | Digital outputs
cellularOK : BOOL; | TRUE if connected to Cellular basestation (Blinks during startup)
END_VAR;
PROGRAM Remote_IO;
VAR
command : STRING;
position : INT;
extract : strGetValues;
str : STRING; // Temporary string
statestr : STRING; // Temporary string
index : SINT; // Temporary SINT
DIn_old : ARRAY[1..16] OF BOOL; // Keeps a copy of the old state of the inputs
sms : gsmIncomingSMS; // Receives incoming SMS messages
pdu : gsmIncomingPDU;
pdubuf : ARRAY[1..140] OF SINT;
cellular_linsec : DINT;
END_VAR;
// Switch power on to Cellular module
gsmPower(power:=TRUE);
// Wait for successful connect to the Cellular network
WHILE NOT gsmConnected() DO
Sleep(delay:=500);
DebugMsg(message:="Waiting for connect to Cellular network...");
cellularOK:=NOT cellularOK; // The LED will blink during this
UPDATEOUT;
END_WHILE;
cellular_linsec:=clockNow() + (24*60*60);
pdu(message:=ADDR(PDUbuf));
BEGIN
// Update function blocks
sms();
pdu();
IF pdu.status>0 THEN
DebugFmt(message:="PDU received. \1",v1:=pdu.length);
DebugFmt(message:=pdu.phonenumber);
END_IF;
//---------------------------------------------------------------------------
// Check all inputs for state change
//---------------------------------------------------------------------------
str:="";
FOR index:=1 TO 16 DO
// If the input has changed state since last time
IF Din[index] <> Din_old[index] THEN
// Build the "Snn=x;" string
statestr:=strFormat(format:="S\1=\2;", v1:=index, v2:=SINT(Din[index]));
// Add it to the command string we will send
str:=strConcat(str1:=str, str2:=statestr);
// Remember the new state
Din_Old[index]:=Din[index];
END_IF;
END_FOR;
// If any state changes, go send them
IF strLen(str:=str)>0 THEN
statestr:=LoadString(index:=1);
// ...but only if phonenumber is defined
IF strLen(str:=statestr)=0 THEN
DebugMsg(message:="Phonenumber is empty, sending NO state change");
ELSE
DebugMsg(message:="Sending new state change:");
DebugMsg(message:=str);
gsmSendSMS(phonenumber:=statestr, message:=str);
END_IF;
END_IF;
//---------------------------------------------------------------------------
// See if any incoming SMS messages
//---------------------------------------------------------------------------
IF sms.status > 0 THEN
position:=1;
// Loop through the received message, and decode it
WHILE TRUE DO
// Find next ";" delimited command
command:=strToken(str:=sms.message, delimiter:=";",index:=position);
position:=position+1;
DebugMsg(message:=command);
// If empty, no more commands...
IF strLen(str:=command)=0 THEN
DebugMsg(message:="No more commands...");
EXIT;
END_IF;
//---------------------------------------------------------------------------
// See if it is a "Snn=x" command...
// if we find a "S" at first position, and a "=" at position 3 or 4
//---------------------------------------------------------------------------
IF strFind(str1:=command, str2:="S")=1 AND
(strFind(str1:=command, str2:="=")=3 OR strFind(str1:=command, str2:="=")=4) THEN
extract(str:=command, format:="S\1=\2");
IF extract.match THEN
// extract.v1 contains input number, extract.v2 contains the new state
IF extract.v1 >= 1 AND extract.v1 <= 16 THEN
// Reflect the new state on the outputs
DOut[extract.v1]:=BOOL(extract.v2);
END_IF;
END_IF;
//---------------------------------------------------------------------------
// See if it's a "phone=xxxxx" command
// If so, we save the new number, and sends back a confirmation to the sender
//---------------------------------------------------------------------------
ELSIF strFind(str1:=command, str2:="phone=")>0 THEN
// Save the parameters
SaveString(index:=1, str:=strMid(str:=command, start:=7));
str:=strConcat(str1:="New receiver set, number=", str2:=LoadString(index:=1));
gsmSendSMS(phonenumber:=sms.phonenumber, message:=str);
END_IF;
END_WHILE;
END_IF;
IF clockNow() > cellular_linsec THEN
DebugMsg(message:="Cellular Module turned OFF");
gsmPower(power:=OFF);
DebugMsg(message:="Cellular Module turned ON");
gsmPower(power:=ON);
cellular_linsec:=clockNow() + (24*60*60);
// Wait for successful connect to the Cellular network
WHILE NOT gsmConnected() DO
Sleep(delay:=500);
DebugMsg(message:="Waiting for connect to Cellular network...");
END_WHILE;
DebugMsg(message:="Now connected to Cellular network");
END_IF;
cellularOK:=gsmConnected();
END;
END_PROGRAM;
|