Telnet server
NMarkRoberts
Posts: 455
I was frustrated with trying to use the unreliable G3 browser control for remote admin / testing / config so I decided to build a command line server.
This code is a "telnet server" in the form of an include. It won't compile as is because it uses my code infrastructure, you'll have to modify it to yours.
It just listens for an incoming IP connection on a given port and replies to or acts upon text received. Note that you need to use a telnet client in which you can specify the port.
I'm not sure how robust this is yet, comments welcome.
This may be old hat to some but I was pleased with how easy it was to do!
This code is a "telnet server" in the form of an include. It won't compile as is because it uses my code infrastructure, you'll have to modify it to yours.
It just listens for an incoming IP connection on a given port and replies to or acts upon text received. Note that you need to use a telnet client in which you can specify the port.
I'm not sure how robust this is yet, comments welcome.
(*** iTelnetServer.axi ***) (******************************************************************************) define_device (******************************************************************************) dTelnetServer = 0:3:0 (******************************************************************************) define_variable (******************************************************************************) volatile char sTelnetServerBuffer[1000] = '' volatile integer bTelnetServerOpen = False volatile integer bTelnetServerOnline = False volatile integer nTelnetServerPort = 8001 (******************************************************************************) define_function TelnetSend ( char sArgString[] ) (******************************************************************************) { send_string dTelnetServer,"sArgString,cCR,cLF" } (* TelnetSendMessage *) (******************************************************************************) define_function integer TelnetServerOpen( dev dArgDevice , integer nArgPort ) (******************************************************************************) { stack_var integer nMyResult stack_var integer bMyServerOpen nMyResult = type_cast(ip_server_open(dTelnetServer.Port,nArgPort,ip_tcp) * -1) switch (nMyResult) { case 0: { Debug('OpenTelnetServer successful') bMyServerOpen = True } case 1: { Error('OpenTelnetServer invalid server port') bMyServerOpen = False } case 2: { Error('OpenTelnetServer invalid value for Protocol') bMyServerOpen = False } case 3: { Error('OpenTelnetServer unable to open communication port') bMyServerOpen = False } default: { ErrorNumber('OpenTelnetServer unknown result',nMyResult) bMyServerOpen = False } } return bMyServerOpen; } (* TelnetServerOpen *) (******************************************************************************) (* Handle string on incoming telnet session *) define_function HandleTelnetServerBuffer() (******************************************************************************) { stack_var char sMyString[1000] stack_var char sMyTerminator[10] stack_var char sMyTokens[100][100] stack_var integer nMyTokenCount DebugHex('HandleTelnetServerBuffer',sTelnetServerBuffer) sMyTerminator = "cLF" while (find_string(sTelnetServerBuffer,sMyTerminator,1)) { DebugHex('Terminator',sTelnetServerBuffer) sMyString = remove_string(sTelnetServerBuffer,sMyTerminator,1) sMyString = TruncateString(sMyString) (* Ditch trailing whitespace, CR, LF *) while (length_string(sMyString) > 0) { nMyTokenCount++ sMyTokens[nMyTokenCount] = RemoveString(sMyString,' ') } sMyTokens[1] = upper_string(sMyTokens[1]) DebugHex('Token',sMyTokens[1]) (* First token is the keyword *) switch (sMyTokens[1]) { case 'HELLO': { TelnetSend('How the heck are you?') } case 'REBOOT': { TelnetSend('Rebooting') RebootController() } default: { DebugHex('Unknown keyword',sMyTokens[1]) TelnetSend("'Unknown keyword [',sMyTokens[1],']'") } } } } (* HandleTelnetServerBuffer *) (******************************************************************************) define_event (******************************************************************************) data_event[dTelnetServer] { onerror: { ErrorNumber('dTelnetServer onerror',type_cast(data.number)) } online: { Debug('dTelnetServer online') bTelnetServerOnline = True } offline: { Debug('dTelnetServer offline') bTelnetServerOnline = False } string: { DebugHex('dTelnetServer string',data.text) sTelnetServerBuffer = "sTelnetServerBuffer,data.text" HandleTelnetServerBuffer() } } (******************************************************************************) define_program (******************************************************************************) if (bModuleReady) { wait nOneMinuteTenths { if (not bTelnetServerOpen) { bTelnetServerOpen = TelnetServerOpen(dTelnetServer,nTelnetServerPort) } } } (*** End of iTelnetServer.axi ***)
This may be old hat to some but I was pleased with how easy it was to do!
0
Comments
Now you just telnet into the NI master, turn on messages with ?msg on?, and SEND_COMMANDs or SEND_STRINGs to your virtual CLI.
And make sure you say ?hello? to the NI master.
So far I have experimentally implemented push, pulse, release, and also get and set for a bunch of regular variables and config variables that I already have in a diagnostics structure which allows me to refer to them by their name in a string.
I should note that I have more or less given up using NS2 debug cos it's unreliable when you have multiple modules.
i described then what i was doing with my application for all installations.
basically, every device is described in a text file database.
i've prepared a masssive arrary of commands for my command line interface.
also, the system runs scripts similiar to DOS batch files. all script commands are compatible with the command line interface.
my scripts also store their own local status variables and can use them for compares when the script runs. all devices report to a 'central' variable stack, so the scripts can also get the status of just about every device.
i've made the commands and variables to be fast indexed/lookup.
my objective is to do all processing thru scripts. this is close to being achieved after nearly three years of working on the one application.
the benefits include installing a known and thoroughly tested application, that hopefully only needs to be altered in it's text database and script files, ensuring a robust installation.
another benefit is to be able to quickly and quietly change functionality, even remotely over the net, without rebooting a system or recompiling and uploading.
a feature of this system is it contains a full web interface to all devices in the installation. command lines can be executed thru the web interface. lights and audio etc can be controlled (and automatically labelled from the database) from a mobile phone with web access.
i'm fairly happy now with the end product and willing to brag about it . if anyone wants to see the web interface i'll setup a demo link.
here is some sample text from one of my script files. the DO statement begins the command. DO can be replaced by IF x=y to create a conditional command line.
do toggle lights bed 2
do delayscript bed2button3:5
if light~bed 2 = 0 goto killEnsuite
do on lights bed 2 ensuite
do goto endScript
:killEnsuite
do off lights bed 2 ensuite
:endScript
note the GOTO commands. there is also a GOSUB command to call repeated functions within the script.
i haven't provided source code samples. the project has become quite massive. it takes a couple of minutes for the controller to fully reboot and reload the application and it's data. a bit longer than usual, but many benefits once the reboot is done. (the compiled source file is over 2MBs).
i guess some wont agree with me on the taking this path. but i didn't want to rewrite a new application for every customer, so i have tried to create one application that does all.
so now, i write all my functions to be command line ready. then when a script wants access to something, it's already there.
more raving then help here i know, but i hope it gives you some food for thought.
i've setup a link to a demo system webpage if you care to take a look.
try http://zentra.com.au:888