
|
//-----------------------------------------------------------------------------
// 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..4] OF 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..4] OF 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..512] OF SINT; // Receive buffer for TCP/IP data
txbuf : ARRAY[0..512] OF 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..100] OF SINT;
END_VAR;
strToMemory(dst:=ADDR(txbuf), str:=str, len:=strLen(str:=str));
DebugFmt(message:="sockSend=\1", v1:=sockSend(id:=id, data:=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:=id, str:="Welcome to the RTCU Telnet Server.$N$N");
SendData(id:=id, str:="Available commands:$N");
SendData(id:=id, str:=" <input> : Show status of digital inputs$N");
SendData(id:=id, str:=" <on n> : Set digital output n to ON$N");
SendData(id:=id, str:=" <off n> : Set digital output n to OFF$N");
SendData(id:=id, str:=" <help>/<?> : Show available commands$N");
SendData(id:=id, str:="$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:=id, data:=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:=PartialCommand, str2:=str);
// If there is a Carriage return in the string...
i:=strFind(str1:=PartialCommand, str2:="$R");
IF i>0 THEN
// We now have a complete command assembled in PartialCommand
Command:=strLeft(str:=PartialCommand, length:=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)=0 THEN
SendData(id:=id, str:="$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 >= 1 AND extract.v1 <= 8 THEN
DOut[extract.v1] := ON;
str:=strFormat(format:="Setting output \1 to ON", v1:=extract.v1);
DebugMsg(message:=str);
SendData(id:=id, str:=strConcat(str1:=str, str2:="$N"));
END_IF;
// Check if it is a "OFF" command
extract(format:="OFF \1", str:=Command);
IF extract.match AND extract.v1 >= 1 AND extract.v1 <= 8 THEN
Dout[extract.v1] := OFF;
str:=strFormat(format:="Setting output \1 to OFF", v1:=extract.v1);
DebugMsg(message:=str);
SendData(id:=id, str:=strConcat(str1:=str, str2:="$N"));
END_IF;
// Check if it is a "INPUT" command
IF strCompare(str1:="INPUT", str2:=Command)=0 THEN
FOR i:=1 TO 4 DO
str:=strFormat(format:="$NInput \1 is \2", v1:=i, v2:=INT(Din[i]));
SendData(id:=id, str:=str);
END_FOR;
END_IF;
// Check if it is a "HELP"/"?" command
IF strCompare(str1:="HELP", str2:=Command)=0 OR
strCompare(str1:="?", str2:=Command)=0 THEN
SendData(id:=id, str:="Available commands:$N");
SendData(id:=id, str:=" <input> : Show status of digital inputs$N");
SendData(id:=id, str:=" <on n> : Set digital output n to ON$N");
SendData(id:=id, str:=" <off n> : Set digital output n to OFF$N");
SendData(id:=id, str:=" <help>/<?> : Show available commands$N");
END_IF;
// Send a new prompt
SendData(id:=id, str:="$NEnter command> ");
END_IF;
END_IF;
END_IF;
Sleep(delay:=50);
// Update the LED
LED:=NOT LED;
END;
END_PROGRAM;
|
|