|
//-----------------------------------------------------------------------------
// example.vpl, created 2009-10-21 12:00
//
// This application program demonstrates use of the new navigation system
//
// Commands:
//
// stopset <ID> <latitude> <longitude> <text>
// -ID : ID of destination
// -latitude : The latitude of the destination position.
// This must be in semicircles format.
// -longitude : The longitude of the destination position.
// This must be in semicircles format.
// -text : The text to describe the destination
//
// stopset 1 582902091 27369314 Eiffel Tower
// stopset 2 582920384 27860319 Louvre
// stopset 3 666381800 117509175 Holmboes Allé 14, Logic IO Aps
//
// stopdel <ID>
// -ID : ID of destination
//
// etaset <delay>
// -delay : The delay between ETA events in seconds.
//
// userreq
//
// userset <Status ID> <Driver ID>
// -status ID : The new status of user, if not exists then shown as 'not set'
// -Driver ID : The new user ID.
//
// userdef <Status ID> <text>
// -status ID : The user status to define
// -text : The text describing the status.
//
// message <ID> <type> <text>
// -ID : The ID of the message
// -type : 1 = Normal, 2 = popup
// -text : The text of the message
//
// clear
//
// uitext <text>
// -text : The text of the UI text, empty deletes
//
// quicktxt <ID> <text>
// -ID : The ID of the quick text
// -text : The text of the quick message, empty deletes
//
//-----------------------------------------------------------------------------
INCLUDE rtcu.inc
VAR
navMsgAck : navMessageReplyReceive;
navMsg : navMessageReceive;
navMsgStatus : navMessageStatusReceive;
navETA : navETAReceive;
navStop : navStopReceive;
navUserID : navUserIDReceive;
navUserStatus : navUserStatusReceive;
clock : clockLinsecToTime;
commands : ARRAY[1..10] OF STRING :=
"stopset",
"stopdel",
"etaset",
"userreq",
"userset",
"message",
"userdef",
"clear",
"uitext",
"quicktxt";
// phone number to receive notification on navigation events
dst : STRING := "9999";
END_VAR;
//-----------------------------------------------------------------------------
// FUNCTION : command_parser
// extract command and parameters from input message
// INPUT :
// message : message to pass for command
// OUTPUT :
// cmd : number identifying the command
// param[] : parameters extracted from message
// no_param : max number of entries in param
//-----------------------------------------------------------------------------
FUNCTION_BLOCK command_parser;
VAR_INPUT
message : STRING;
END_VAR;
VAR_OUTPUT
cmd : INT;
param : ARRAY[1..5] OF STRING;
no_param: SINT := 5; // max number of entries in param
END_VAR;
VAR
temp : STRING;
i : INT;
END_VAR;
// Clear outputs
FOR i := 1 TO no_param DO
param[i] := "";
END_FOR;
cmd := 0;
// Extract command word
temp := strToken(str := message, delimiter := " ", index := 1);
// Determine command
FOR i := 1 TO 10 DO
IF strCompare(str1 := temp, str2 := commands[i]) = 0 THEN
cmd := i;
EXIT;
END_IF;
END_FOR;
// not a valid command string
IF cmd = 0 THEN
RETURN;
END_IF;
DebugFmt(message := "SMS received (command ): '\1' (" + commands[cmd] + ")", v1 := cmd);
// Unpack parameters
CASE cmd OF
//stopset <ID> <latitude> <longitude> <text>
1: temp := strRemoveSpaces(str := message);
temp := strMid(str := temp, start := strLen(str := commands[cmd]) + 1);
temp := strRemoveSpaces(str := temp);
param[1] := strToken(str := temp, delimiter := " ", index := 1);
temp := strMid(str := temp, start := strLen(str := param[1]) + 1);
temp := strRemoveSpaces(str := temp);
param[2] := strToken(str := temp, delimiter := " ", index := 1);
temp := strMid(str := temp, start := strLen(str := param[2]) + 1);
temp := strRemoveSpaces(str := temp);
param[3] := strToken(str := temp, delimiter := " ", index := 1);
temp := strMid(str := temp, start := strLen(str := param[3]) + 1);
param[4] := strRemoveSpaces(str := temp);
// stopdel <ID>
2: param[1] := strToken(str := message, delimiter := " ", index := 2);
// etaset
3: param[1] := strToken(str := message, delimiter := " ", index := 2);
// userset <user status id> <text>
5: temp := strRemoveSpaces(str := message);
temp := strMid(str := temp, start := strLen(str := commands[cmd]) + 1);
temp := strRemoveSpaces(str := temp);
param[1] := strToken(str := temp, delimiter := " ", index := 1);
temp := strMid(str := temp, start := strLen(str := param[1]) + 1);
param[2] := strRemoveSpaces(str := temp);
// message <ID> <type> <text>
6: temp := strRemoveSpaces(str := message);
temp := strMid(str := temp, start := strLen(str := commands[cmd]) + 1);
FOR i := 1 TO 2 DO
temp := strRemoveSpaces(str := temp);
param[i] := strToken(str := temp, delimiter := " ", index := 1);
temp := strMid(str := temp, start := strLen(str := param[i]) + 1);
END_FOR;
param[3] := strRemoveSpaces(str := temp);
//userdef <status id> <text>
7: temp := strRemoveSpaces(str := message);
temp := strMid(str := temp, start := strLen(str := commands[cmd]) + 1);
temp := strRemoveSpaces(str := temp);
param[1] := strToken(str := temp, delimiter := " ", index := 1);
temp := strMid(str := temp, start := strLen(str := param[1]) + 1);
param[2] := strRemoveSpaces(str := temp);
// uitext <text>
9: temp := strRemoveSpaces(str := message);
temp := strMid(str := temp, start := strLen(str := commands[cmd]) + 1);
param[1] := strRemoveSpaces(str := temp);
// quicktxt <ID> <text>
10:temp := strRemoveSpaces(str := message);
temp := strMid(str := temp, start := strLen(str := commands[cmd]) + 1);
temp := strRemoveSpaces(str := temp);
param[1] := strToken(str := temp, delimiter := " ", index := 1);
temp := strMid(str := temp, start := strLen(str := param[1]) + 1);
param[2] := strRemoveSpaces(str := temp);
END_CASE;
FOR i := 1 TO no_param DO
DebugFmt(message := "SMS received (argument \1): '" + param[i] + "'", v1 := i);
END_FOR;
END_FUNCTION_BLOCK;
//-----------------------------------------------------------------------------
// FUNCTION : TimeString
// extract command and parameters from input message
// INPUT :
// linsec : time in Linux seconds
// RETURN :
// time : a string with the time expressed in ASCII
//-----------------------------------------------------------------------------
FUNCTION TimeString : STRING;
VAR_INPUT
linsec : DINT;
END_VAR;
clock(linsec := linsec);
TimeString := strFormat(format := "\1.\2.\3, ", v1 := clock.day, v2 := clock.month, v3 := clock.year);
TimeString := TimeString + strFormat(format := "\1:\2:\3", v1 := clock.hour, v2 := clock.minute, v3 := clock.second);
END_FUNCTION;
//-----------------------------------------------------------------------------
// THREAD : navMonitor
// monitor events from the navigation device
//-----------------------------------------------------------------------------
THREAD_BLOCK navMonitor;
VAR
event : INT := 0;
reply : STRING;
END_VAR;
WHILE event <> -1 DO
event := navWaitEvent(timeout := -1);
CASE event OF
1: // A reply for a text message is received
navMsgAck();
DebugMsg(message := "MON: message reply received");
DebugFmt(message := "MON: -ID=\1", v1 := navMsgAck.ID);
DebugMsg(message := "MON: -time=" + TimeString(linsec := navMsgAck.time));
DebugFmt(message := "MON: -reply=\1", v1 := navMsgAck.reply);
// Reply to server: reply <ID> <timestamp> <reply>
reply := strFormat(format := "reply \1 \4 \2", v1 := navMsgAck.ID, v2 := navMsgAck.reply, v4 := navMsgAck.time);
gsmSendSMS(phonenumber := dst, message := reply);
2: // A text message is received
navMsg();
DebugMsg(message := "MON: message received");
DebugFmt(message := "MON: -time=" + TimeString(linsec := navMsg.time));
DebugMsg(message := "MON: -text=" + navMsg.message);
// Reply to server: message <text>
gsmSendSMS(phonenumber := dst, message := "message " + navMsg.message);
3: // The status for a text message is received
navMsgStatus();
DebugMsg(message := "MON: message status received");
DebugFmt(message := "MON: -ID=\1", v1 := navMsgStatus.ID);
CASE navMsgStatus.status OF
1: DebugMsg(message := "MON: -status=Unread");
2: DebugMsg(message := "MON: -status=Read");
3: DebugMsg(message := "MON: -status=Deleted/Not found");
END_CASE;
4: // An ETA update is received
navETA();
DebugMsg(message := "MON: ETA received");
DebugFmt(message := "MON: -stop=\1", v1 := navETA.id);
DebugFmt(message := "MON: -time=" + TimeString(linsec := navETA.time));
DebugFmt(message := "MON: -distance=\4", v4 := navETA.distance);
DebugFmt(message := "MON: -latitude=\4", v4 := navETA.latitude);
DebugFmt(message := "MON: -longitude=\4", v4 := navETA.longitude);
// Reply to server: ETA <stop> <time> <distance>
reply := strFormat(format := "ETA \1 \4 ", v1 := navETA.id, v4 := navETA.time);
gsmSendSMS(phonenumber := dst, message := reply + dintToStr(v := navETA.distance));
5: // The status of a destination is received
navStop();
DebugMsg(message := "MON: stop status received");
DebugFmt(message := "MON: -ID=\1", v1 := navStop.ID);
DebugFmt(message := "MON: -index=\1", v1 := navStop.index);
CASE navStop.status OF
1: DebugMsg(message := "MON: -status=Active");
2: DebugMsg(message := "MON: -status=Done");
3: DebugMsg(message := "MON: -status=Inactive - Unread");
4: DebugMsg(message := "MON: -status=Inactive - Read");
5: DebugMsg(message := "MON: -status=Deleted/Not found");
END_CASE;
// Reply to server: ETA <stop> <time> <distance>
reply := strFormat(format := "stop \1 \2 \3", v1 := navStop.ID, v2 := navStop.index, v3 := navStop.status);
gsmSendSMS(phonenumber := dst, message := reply);
6: // An user ID is received
navUserID();
DebugMsg(message := "MON: user ID received");
DebugFmt(message := "MON: -time=" + TimeString(linsec := navUserID.time));
DebugMsg(message := "MON: -user=" + navUserID.user);
// Reply to server: user <ID>
gsmSendSMS(phonenumber := dst, message := "user " + navUserID.user);
7: // The status of an user is received
navUserStatus();
DebugMsg(message := "MON: user status received");
DebugFmt(message := "MON: -time=" + TimeString(linsec := navUserStatus.time));
DebugFmt(message := "MON: -status=\1", v1 := navUserStatus.status);
// Reply to server: status <status>
reply := strFormat(format := "status \1", v1 := navUserStatus.status);
gsmSendSMS(phonenumber := dst, message := reply);
129: // A request to refresh the Quick messages
DebugMsg(message := "MON: refresh of quick messages received, sending defaults");
navMessageQuickDefine(id := 1, text := "I have arrived at the destination");
navMessageQuickDefine(id := 2, text := "There are no persons to receive the packages at destination");
navMessageQuickDefine(id := 3, text := "Armed robbery in progress, send help");
navMessageQuickDefine(id := 4, text := "Packages delivered");
navMessageQuickDefine(id := 5, text := "Finish with my route.");
130: // A request to refresh the message replies.
DebugMsg(message := "MON: refresh of message replies received, sending defaults");
navMessageReplyDefine(id := 1, text := "Accept");
navMessageReplyDefine(id := 2, text := "Reject");
navMessageReplyDefine(id := 3, text := "Yes");
navMessageReplyDefine(id := 4, text := "No");
131: // A request to refresh the user status list.
DebugMsg(message := "MON: refresh of drivers status, sending defaults");
navUserStatusDefine(id := 1, text := "Awaiting new destination");
navUserStatusDefine(id := 2, text := "On the way to a destination");
navUserStatusDefine(id := 3, text := "On the way to the office");
navUserStatusDefine(id := 4, text := "At destination delivering packages");
132: // Connection to navigation device established
DebugMsg(message := "MON: navigation device present");
DebugFmt(message := "MON: -serial=" + navDeviceSerial());
133: // Connection to navigation device lost
DebugMsg(message := "MON: navigation device not present");
ELSE
DebugFmt(message := "MON: unhandled event form device '\1'", v1 := event);
END_CASE;
END_WHILE;
END_THREAD_BLOCK;
//-----------------------------------------------------------------------------
// PROGRAM : example
// main application handling initialization, startup of navigation monitor
// thread. Also handles incoming Cellular connections.
//-----------------------------------------------------------------------------
PROGRAM example;
VAR
PDU : gsmIncomingPDU;
SMS : gsmIncomingSMS;
pdu_rx : ARRAY[1..140] OF SINT;
navMon : navMonitor;
rc : INT;
cmd : command_parser;
id : INT; // Message identifier
END_VAR;
// Initializing
rc := navOpen();
IF rc = 0 THEN
DebugMsg(message := "navigation open");
ELSE
DebugFmt(message := "navigation error (navOpen=\1)", v1 := rc);
END_IF;
navMon();
gsmPower(power := ON);
rc := netOpen(iface:=_NET_IFACE_CELLULAR);
IF rc = 0 THEN
DebugMsg(message := "Cellular network initialized");
ELSE
DebugFmt(message := "Cellular network error (netOpen=\1)", v1 := rc);
END_IF;
PDU.message := ADDR(pdu_rx);
DebugMsg(message := "Initialization finish, ready for communication.");
BEGIN
// Flush PDU messages
PDU();
// Receive SMS commands
SMS();
IF SMS.status > 0 THEN
// Parse command
cmd(message := SMS.message);
CASE cmd.cmd OF
1: // Set destination
rc := navStopSet(ID := strToInt(str := cmd.param[1]),
latitude := strToDint(str := cmd.param[2]),
longitude := strToDint(str := cmd.param[3]),
text := cmd.param[4]);
IF rc = 0 THEN
DebugMsg(message := "Destination set");
ELSE
DebugFmt(message := "Destination error (navStopSet=\1)", v1 := rc);
END_IF;
2: // Delete destination
rc := navStopDelete(ID := strToInt(str := cmd.param[1]));
IF rc = 0 THEN
DebugMsg(message := "Destination removed");
ELSE
DebugFmt(message := "Destination error (navStopDelete=\1)", v1 := rc);
END_IF;
3: // Set ETA delay
rc := navETAAutoSet(freq := strToInt(str := cmd.param[1]));
IF rc = 0 THEN
DebugMsg(message := "ETA delay set");
ELSE
DebugFmt(message := "ETA error (navETAAutoSet=\1)", v1 := rc);
END_IF;
4: // Request user info
navUserIDRequest();
navUserStatusRequest();
5: // Set user info
rc := navUserIDSet(user := cmd.param[2]);
IF rc = 0 THEN
rc := navUserStatusSet(id := strToInt(str := cmd.param[1]));
IF rc = 0 THEN
DebugMsg(message := "User info set");
ELSE
DebugFmt(message := "User info error (navUserStatusSet=\1)", v1 := rc);
END_IF;
ELSE
DebugFmt(message := "User info error (navUserIDSet=\1)", v1 := rc);
END_IF;
6: // Send message
rc := navMessageSend(ID := strToInt(str := cmd.param[1]),
text := cmd.param[3],
type := strToSint(str := cmd.param[2]) - 1);
IF rc = 0 THEN
DebugMsg(message := "Message send");
ELSE
DebugFmt(message := "Message error (navMessageSend=\1)", v1 := rc);
END_IF;
7: // Define user status
rc := navUserStatusDefine(id := strToInt(str := cmd.param[1]), text := cmd.param[2]);
IF rc = 0 THEN
DebugMsg(message := "User status defined");
ELSE
DebugFmt(message := "User status error (navUserStatusDefine=\1)", v1 := rc);
END_IF;
8: // Clear data in Garmin
navDeleteData(type := 0);
navDeleteData(type := 1);
navDeleteData(type := 2);
navDeleteData(type := 3);
navDeleteData(type := 4);
navDeleteData(type := 6);
9: // set UI text
// Customize the text of the user interface in the navigation device
rc := navSetUIText(id := 0, text := cmd.param[1]);
IF rc = 0 THEN
DebugMsg(message := "The user interface is set");
ELSE
DebugFmt(message := "User interface text error (navSetUIText=\1)", v1 := rc);
END_IF;
10: // set quick message
id := strToInt(str := cmd.param[1]);
IF strLen(str := cmd.param[2]) > 0 THEN
// Define a quick message
rc := navMessageQuickDefine(id := id, text := cmd.param[2]);
IF rc = 0 THEN
DebugFmt(message := "The quick message \1 has been set/updated.", v1 := id);
ELSE
DebugFmt(message := "Updating/Setting quick message \1 failed (navMessageQuickDefine=\2)", v1 := id, v2 := rc);
END_IF;
ELSE
// Delete a quick message
rc := navMessageQuickDelete(id := id);
IF rc = 0 THEN
DebugFmt(message := "The quick message \1 has been deleted.", v1 := id);
ELSE
DebugFmt(message := "Deletion of quick message \1 failed (navMessageQuickDelete=\2)", v1 := id, v2 := rc);
END_IF;
END_IF;
ELSE
// Unknown command
DebugMsg(message := "Unknown command=" + SMS.message);
END_CASE;
END_IF;
END;
END_PROGRAM;
|