Home Contact us


Telnet server



//-----------------------------------------------------------------------------
// Telnet.vpl, created 2003-03-04 20:05
//
// This is a VERY simple telnet server. It has only a few commands, but still
// shows how to establish a TCP/IP connection. The demo requires that the
// RTCU unit has a GLOBAL accessible IP address on the internet ! When a Telnet
// client connects to the RTCU, a welcome message is shown, together with a
// prompt, where the telnet client then can enter commands. The following commnds
// are available: input, on n, off n, quit and help. Input will show the state
// of 4 digital inputs, on/off n will switch digital output n to either on or off
// state, quit will close the connection, and help will show a list of available
// commands.
//-----------------------------------------------------------------------------
INCLUDE rtcu.inc
INCLUDE tcpip.inc

// Input variables that can be configured via the configuration dialog (These are global)
VAR_INPUT
   Din ARRAY[1..4OF BOOL| Digital inputs (can be read with "input" command)
END_VAR;

// Output variables that can be configured via the configuration dialog (These are global)
VAR_OUTPUT
   LED bool| LED that shows the program scan
   Dout ARRAY[1..4OF BOOL| Digital outputs (can be set with the "on"/"off" commands)
END_VAR;

// These are the global variables of the program
VAR
   sockrcv    sockReceive;    // Receives data on a TCP/IP socket
   soccon     sockConnection// Manages a TCP/IP connection
   id         SINT          // TCP/IP connection id
   rxbuf      ARRAY[0..512OF SINT// Receive buffer for TCP/IP data
   txbuf      ARRAY[0..512OF SINT// Transmit buffer for TCP/IP data
   i          INT           // Temporary variable
   str        STRING        // Temporary variable
   extract    strGetValues;   // Matching of commandstrings
   PartialCommand STRING;     // Characters on TCP/IP socket gets assembled in this
   Command    STRING;         // Final command received (after CR)
   listenport SINT:=23;       // Which port to listen on (port 23=standard Telnet port)
END_VAR;


//---------------------------------------------------------------------------
// Send a STRING on a TCP/IP connection
//---------------------------------------------------------------------------
FUNCTION SendData;
VAR_INPUT
   id SINT;
   str STRING;
END_VAR
VAR
   txbuf ARRAY[0..100OF SINT;
END_VAR;
   strToMemory(dst:=ADDR(txbuf), str:=strlen:=strLen(str:=str));
   DebugFmt(message:="sockSend=\1", v1:=sockSend(id:=iddata:=ADDR(txbuf), size:=strLen(str:=str)));
END_FUNCTION;


//---------------------------------------------------------------------------
// Start at TCP/IP socket listen on a specified port
// (and update the sockConnection() and sockReceive() functionblocks)
//---------------------------------------------------------------------------
FUNCTION StartListen;
   // Start listener on port
   id:=sockListen(port:=listenport);
   DebugFmt(message:="socListen()=\1",v1:=id);
   // Update id for sockConnection() and sockReceive()
   soccon(id:=id);
   sockrcv(id:=id,data:=ADDR(rxbuf),MaxSize:=SIZEOF(rxbuf));
END_FUNCTION;


//---------------------------------------------------------------------------
// Main program
//---------------------------------------------------------------------------
PROGRAM Telnet;
// Switch on power to the GSM module
gsmPower(power:=TRUE);
// Open the GPRS connection (connects the RTCU unit to the Internet)
DebugFmt(message:="gprsOpen()=\1",v1:=gprsOpen());
// Wait for connection to the Internet
// (This is actually not needed, as the sockListen() can be called before
// the connection is established)
WHILE NOT gprsConnected() DO
   DebugMsg(message:="Waiting for GPRS connection");
   Sleep(delay:=3000);
END_WHILE;
// Show our assigned IP address (this is the one the telnet client should connect to)
DebugMsg(message:=strConcat(str1:="My IP Address=",str2:=sockIPToName(ip:=sockGetLocalIP())));
// Start listening for TCP/IP connects on the Telnet port (port 23)
StartListen();
BEGIN
   soccon(); // Update status for sockConnection() functionblock
   sockrcv(); // Update status for sockReceive() functionblock
   // Connection status changed (someone connected or disconnected)
   IF soccon.changed THEN
      // Someone just connected to us...
      IF soccon.Connected THEN
         DebugMsg(message:=strConcat(str1:=sockIPToName(ip:=soccon.remoteip), str2:=" has connected"));
         SendData(id:=idstr:="Welcome to the RTCU Telnet Server.$N$N");
         SendData(id:=idstr:="Available commands:$N");
         SendData(id:=idstr:=" <input> : Show status of digital inputs$N");
         SendData(id:=idstr:=" <on n> : Set digital output n to ON$N");
         SendData(id:=idstr:=" <off n> : Set digital output n to OFF$N");
         SendData(id:=idstr:=" <help>/<?> : Show available commands$N");
         SendData(id:=idstr:="$NEnter command> ");
      // Someone disconnected
      ELSE
         DebugMsg(message:=strConcat(str1:=sockIPToName(ip:=soccon.remoteip), str2:=" is disconnecting !"));
         // Disconnect socket
         sockDisconnect(id:=id);
         // and start listening again
         StartListen();
      END_IF;
   END_IF;


   // We have received some data...
   IF sockrcv.ready THEN
      DebugFmt(message:="socket data received len=\1",v1:=sockrcv.size);
      // Echo the received data
      DebugFmt(message:="sockSend=\1", v1:=sockSend(id:=iddata:=addr(rxbuf), size:=sockrcv.size));
      // Convert the received data to a string
      str:=strFromMemory(src:=ADDR(rxbuf), len:=sockrcv.size);
      DebugMsg(message:=str);
      // concatenate the received data to command string
      PartialCommand:=strConcat(str1:=PartialCommandstr2:=str);
      // If there is a Carriage return in the string...
      i:=strFind(str1:=PartialCommandstr2:="$R");
      IF i>THEN
         // We now have a complete command assembled in PartialCommand
         Command:=strLeft(str:=PartialCommandlength:=i-1);
         DebugMsg(message:=strConcat(str1:="Command=", str2:=Command));
         PartialCommand:="";
         // Check if it is a "QUIT" command (No prompt sent if it's quit)
         IF strCompare(str1:="QUIT", str2:=Command)=THEN
            SendData(id:=idstr:="$NGoodbye.$N");
            // Disconnect socket
            // (Note: this will NOT activate a soccon.changed, as it is "ourself" who has disconnected !)
            sockDisconnect(id:=id);
            // and start listening again
            StartListen();
            // Check for other commands
         ELSE
            // Check if it is a "ON" command
            extract(format:="ON \1", str:=Command);
            IF extract.match AND extract.v1 >= AND extract.v1 <= THEN
               DOut[extract.v1] := ON;
               str:=strFormat(format:="Setting output \1 to ON", v1:=extract.v1);
               DebugMsg(message:=str);
               SendData(id:=idstr:=strConcat(str1:=strstr2:="$N"));
            END_IF;
            
            
// Check if it is a "OFF" command
            extract(format:="OFF \1", str:=Command);
            IF extract.match AND extract.v1 >= AND extract.v1 <= THEN
               Dout[extract.v1] := OFF;
               str:=strFormat(format:="Setting output \1 to OFF", v1:=extract.v1);
               DebugMsg(message:=str);
               SendData(id:=idstr:=strConcat(str1:=strstr2:="$N"));
            END_IF;
            
            
// Check if it is a "INPUT" command
            IF strCompare(str1:="INPUT", str2:=Command)=THEN
               FOR i:=TO DO
                  str:=strFormat(format:="$NInput \1 is \2", v1:=iv2:=INT(Din[i]));
                  SendData(id:=idstr:=str);
               END_FOR;
            END_IF;
            
            
// Check if it is a "HELP"/"?" command
            IF strCompare(str1:="HELP", str2:=Command)=OR
               strCompare(str1:="?", str2:=Command)=THEN
               SendData(id:=idstr:="Available commands:$N");
               SendData(id:=idstr:=" <input> : Show status of digital inputs$N");
               SendData(id:=idstr:=" <on n> : Set digital output n to ON$N");
               SendData(id:=idstr:=" <off n> : Set digital output n to OFF$N");
               SendData(id:=idstr:=" <help>/<?> : Show available commands$N");
            END_IF;
         
            
// Send a new prompt
            SendData(id:=idstr:="$NEnter command> ");
         END_IF;
      END_IF;
   END_IF;

   Sleep
(delay:=50);
   // Update the LED
   LED:=NOT LED;

END
;
END_PROGRAM;