Navigation Example

Top  Previous  Next

//-----------------------------------------------------------------------------
// 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(:= 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;