
|
//-----------------------------------------------------------------------------
// thread example.vpl, created 2004-10-15 10:23
//
// Simple program to demonstrate the use of threads, mutexes and I-Button.
// The program creates 3 threads, 1 to read the GPS position and store it
// in persistent memory, 1 to read an I-Button and control I-Button LED and 1 to
// Parse incoming SMS messages.
// By using an I-Button or sending a SMS the program will monitor the 4 inputs
// and send a SMS when one of them is activated. The monitoring must restart
// before another alarm is send.
// A tracking function is also included, to be activated by a SMS.
//
// The following SMS commands are supported:
// OWI#,nnnnnnnnnnnn: Register an I-Button ID for validation. #=Index(1..5), nnnnn=I-Button ID
// AON: Activate alarm monitoring
// AOFF: Deactivate alarm monitoring
// TON: Start tracking
// TOFF: Stop tracking
// POS: Get position
// PHONEnnnnnnnn: Tracking and Alarm response phone number
//-----------------------------------------------------------------------------
INCLUDE rtcu.inc
INCLUDE thread.inc
VAR_INPUT
in : ARRAY[1..4] OF BOOL;
END_VAR;
VAR_OUTPUT
led : BOOL;
END_VAR;
VAR
AlarmState : BOOL := FALSE;
TrackState : BOOL := FALSE;
mxStateAl : MUTEX;
mxStateTr : MUTEX;
NextGps : DINT;
END_VAR;
//----------------------------------------------------------------------------
// SetAlarm
// Set the state of the AlarmState flag.
//----------------------------------------------------------------------------
FUNCTION SetAlarm
VAR_INPUT
state : BOOL;
END_VAR;
mxLock(mx:=mxStateAl);
AlarmState := state;
mxUnlock(mx:=mxStateAl);
END_FUNCTION
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// TestAlarm
// Test the state of the AlarmState flag.
//----------------------------------------------------------------------------
FUNCTION TestAlarm : BOOL
mxLock(mx:=mxStateAl);
TestAlarm := AlarmState;
mxUnlock(mx:=mxStateAl);
END_FUNCTION
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// SetTracking
// Set the state of the TrackState flag.
//----------------------------------------------------------------------------
FUNCTION SetTracking
VAR_INPUT
state : BOOL;
END_VAR;
mxLock(mx:=mxStateTr);
TrackState := state;
mxUnlock(mx:=mxStateTr);
END_FUNCTION
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// TestTracking
// Test the state of the TrackState flag.
//----------------------------------------------------------------------------
FUNCTION TestTracking : BOOL
mxLock(mx:=mxStateTr);
TestTracking := TrackState;
mxUnlock(mx:=mxStateTr);
END_FUNCTION
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// SetId
// Register or Unregister an I-Button ID
//----------------------------------------------------------------------------
FUNCTION SetId
VAR_INPUT
index : INT;
ID : STRING;
END_VAR;
VAR
oldIDs : STRING;
newIDs : STRING;
i : INT;
END_VAR;
// Verify index
IF index > 0 AND index < 6 THEN
// Read Registered IDs
oldIDs := LoadStringF(index:=3);
// Insert IDs before new
IF index > 1 THEN
FOR i := 1 TO index - 1 BY 1 DO
newIDs := strConcat(str1:=newIDs,str2:=strToken(str:=oldIDs,delimiter:=",",index:=i));
newIDs := strConcat(str1:=newIDs,str2:=",");
END_FOR;
END_IF;
// Insert new ID
newIDs := strConcat(str1:=newIDs,str2:=ID);
newIDs := strConcat(str1:=newIDs,str2:=",");
// Insert IDs after new
IF index < 5 THEN
FOR i := index + 1 to 5 BY 1 DO
newIDs := strConcat(str1:=newIDs,str2:=strToken(str:=oldIDs,delimiter:=",",index:=i));
newIDs := strConcat(str1:=newIDs,str2:=",");
END_FOR;
END_IF;
// Save Registered IDs
SaveStringF(index:=3,str:=newIDs);
END_IF;
END_FUNCTION
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// SendPos
// Sends the last position
//----------------------------------------------------------------------------
FUNCTION SendPos
VAR_INPUT
phone : STRING;
END_VAR;
VAR
message : STRING;
END_VAR;
// Retrieve last valid position from FRAM
message := LoadStringF(index:=1);
// Send position
gsmSendSMS(phonenumber:=phone,message:=message);
END_FUNCTION
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// OWIBUTTON
// Thread that reads and validates I-Button IDs, for alarm activation/
// deactivation.
//----------------------------------------------------------------------------
THREAD_BLOCK OWIBUTTON
VAR
strID : STRING;
Valid : BOOL;
Count : INT := 0;
Blink : INT := 0;
END_VAR;
// Init
OWiButtonEnableLED(enable:=TRUE);
OWiButtonSetLED(state:=OFF);
// Do forever
WHILE TRUE DO
// Read I-Button ID
strID := OWiButtonGetID();
// Is there an I-Button present?
IF strLen(str:=strID) > 0 THEN
// Reset timer
Count := 20;
Blink := 10;
// Repetition?
IF NOT Valid THEN
// Lookup ID
IF strFind(str1:=LoadStringF(index:=3),str2:=strID) > 0 THEN
// Change alarm state
SetAlarm( state := NOT TestAlarm() );
END_IF;
// I-Button has been read
OWiButtonSetLED(state:=ON);
Valid := TRUE;
END_IF;
ELSE
Valid := FALSE;
// Delay for I-Button removed from reader
IF Count > 0 THEN
// Delay
Count := Count - 1;
Sleep(delay:=100);
// Is alarm survailance activated?
ELSIF TestAlarm() THEN
// Led := ON for 100 ms.
IF Blink = 0 THEN
// Reset timer
Blink := 10;
// Turn LED on
OWiButtonSetLED(state:=ON);
ELSIF Blink = 9 THEN
// Turn LED off
OWiButtonSetLED(state:=OFF);
END_IF;
// Delay
Blink := Blink - 1;
Sleep(delay:=100);
ELSE
OWiButtonSetLED(state:=OFF);
Sleep(delay:=100);
END_IF;
END_IF;
END_WHILE;
END_THREAD_BLOCK;
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// GPS
// Thread that reads valid GPS positions and save them in FRAM
//----------------------------------------------------------------------------
THREAD_BLOCK GPS
VAR
gpspos : gpsFix;
str : STRING;
END_VAR;
// Init
gpsPower(power:=ON);
// Do forever
WHILE TRUE DO
// Get GPS position
gpspos();
// Valid Position?
IF gpspos.mode > 1 THEN
// String
str := strFormat(format:="Time: \1.\2.\3, ",v1:=gpspos.day,v2:=gpspos.month,v3:=gpspos.year);
str := strConcat(str1:=str,str2:=strFormat(format:="\1:\2:\3 ",v1:=gpspos.hour,v2:=gpspos.minute,v3:=gpspos.second));
IF gpspos.latsouth THEN
str := strConcat(str1:=str,str2:=strFormat(format:="Lat: S\1*\2.\3 ",v1:=gpspos.latdeg,v2:=gpspos.latmin,v3:=gpspos.latdecmin));
ELSE
str := strConcat(str1:=str,str2:=strFormat(format:="Lat: N\1*\2.\3 ",v1:=gpspos.latdeg,v2:=gpspos.latmin,v3:=gpspos.latdecmin));
END_IF;
IF gpspos.lonwest THEN
str := strConcat(str1:=str,str2:=strFormat(format:="Long: W\1*\2.\3 ",v1:=gpspos.londeg,v2:=gpspos.lonmin,v3:=gpspos.londecmin));
ELSE
str := strConcat(str1:=str,str2:=strFormat(format:="Long: E\1*\2.\3 ",v1:=gpspos.londeg,v2:=gpspos.lonmin,v3:=gpspos.londecmin));
END_IF;
SaveStringF(index:=1,str:=str);
END_IF;
Sleep(delay:=1000);
END_WHILE;
END_THREAD_BLOCK;
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// SMS
// Thread that reads incoming SMS messages and executes commands
//----------------------------------------------------------------------------
THREAD_BLOCK SMS
VAR
incoming : gsmIncomingSMS;
END_VAR;
// Init
gsmPower(power:=ON);
DebugMsg(message:="Ready to receive SMS");
// Do forever
WHILE TRUE DO
incoming();
// GSM connection status
led := gsmConnected();
// Check for incoming SMS
IF incoming.status > 0 THEN
DebugMsg(message:=strConcat(str1:="SMS recieved => ", str2:=strConcat(str1:=incoming.phonenumber,str2:=strConcat(str1:=",",str2:=incoming.message))));
// Set I-Button ID
IF strCompare(str1:="OWI",str2:=strLeft(str:=incoming.message,length:=3)) = 0 THEN
// Insert new ID
SetId( index := strToInt(str:=strMid(str:=incoming.message,start:=4,length:=1)), ID := strMid(str:=incoming.message,start:=6) );
gsmSendSMS(phonenumber:=incoming.phonenumber,message:=strConcat(str1:=strMid(str:=incoming.message,start:=4,length:=1),str2:=strMid(str:=incoming.message,start:=6)));
// Activate Alarm
ELSIF strCompare(str1:="AON",str2:=incoming.message) = 0 THEN
// Change alarm state
SetAlarm(state:=ON);
gsmSendSMS(phonenumber:=incoming.phonenumber,message:="Alarm=ON");
// Deactivate Alarm
ELSIF strCompare(str1:="AOFF",str2:=incoming.message) = 0 THEN
// Change alarm state
SetAlarm(state:=OFF);
gsmSendSMS(phonenumber:=incoming.phonenumber,message:="Alarm=OFF");
// Activate Tracking
ELSIF strCompare(str1:="TON",str2:=incoming.message) = 0 THEN
// Syncronize tracking timer
NextGps := clockNow();
// Change tracking state
SetTracking(state:=ON);
gsmSendSMS(phonenumber:=incoming.phonenumber,message:="Tracking=ON");
// Deactivate Tracking
ELSIF strCompare(str1:="TOFF",str2:=incoming.message) = 0 THEN
// Change tracking state
SetTracking(state:=OFF);
gsmSendSMS(phonenumber:=incoming.phonenumber,message:="Tracking=OFF");
// Retrieve Position
ELSIF strCompare(str1:="POS",str2:=incoming.message) = 0 THEN
// Send last position
SendPos(phone:=incoming.phonenumber);
// Set reply phone number
ELSIF strCompare(str1:="PHONE",str2:=strLeft(str:=incoming.message,length:=5)) = 0 THEN
SaveStringF(index:=4,str:=strMid(str:=incoming.message,start:=6));
gsmSendSMS(phonenumber:=incoming.phonenumber,message:=strConcat(str1:="Phone=",str2:=strMid(str:=incoming.message,start:=6)));
END_IF;
END_IF;
Sleep(delay:=2000);
END_WHILE;
END_THREAD_BLOCK;
//----------------------------------------------------------------------------
PROGRAM thread_example;
VAR
thIbutton : OWIBUTTON;
thGps : GPS;
thSms : SMS;
Valid : BOOL;
END_VAR;
// Init MUTEX
DebugMsg(message:="Initializing Mutex");
mxStateAl := mxInit();
mxStateTr := mxInit();
IF mxStatus(mx:=mxStateAl) = 1 THEN DebugMsg(message:="mxStateAl failed to init!"); END_IF;
IF mxStatus(mx:=mxStateTr) = 1 THEN DebugMsg(message:="mxStateTr failed to init!"); END_IF;
// Init THREAD
DebugMsg(message:="Starting Threads");
thIbutton();
thGps();
thSms();
IF NOT thIbutton._running THEN DebugMsg(message:="thIbutton failed to start!"); END_IF;
IF NOT thGps._running THEN DebugMsg(message:="thGps failed to start!"); END_IF;
IF NOT thSms._running THEN DebugMsg(message:="thSms failed to start!"); END_IF;
BEGIN
// Are we monitoring Alarm inputs?
IF TestAlarm() THEN
// Test alarm inputs
IF (in[1] OR in[2] OR in[3] OR in[4]) AND NOT Valid THEN
gsmSendSMS(phonenumber:=LoadStringF(index:=4),message:="ALARM!");
Valid := TRUE;
END_IF;
ELSE
Valid := FALSE;
END_IF;
// Are we tracking unit?
IF TestTracking() THEN
// Time for next position?
IF clockNow() >= NextGps THEN
// Send last position
SendPos(phone:=LoadStringF(index:=4));
// Time for next position
NextGps := clockNow() + 60; // 1 Min.
END_IF;
END_IF;
END;
END_PROGRAM;
|
|