Examples - 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(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 GSM 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 := gprsOpen();
  IF rc = 0 THEN
    DebugMsg(message := "GPRS initialized");
  ELSE
    DebugFmt(message := "GPRS error (gprsOpen=\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 sent");
          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;