Introduction

TDVCentral2 is a development/utilisation platform for the ActiveXContainerX component. Any number of such controls may be inserted in the application, each exposing an ActiveX control via the TDVCmdProtocol text interface.

The IMTDVCmdProtocol component will expose all contained controls via the network, allowing remote connections to the controls; the RS232CmdProtocol does the same over serial lines.

An on-board scheduler can generate regular events.

An on-board “database” (CrossIndex) keeps variable names and values available.

An on-board Web Server can be configured in almost any way.

A system log will keep all important events kept as a reference.

Finally, a Python engine is part of the application, making scripts easily available via either the TDVCmdProtocol, or as autogenerated ActiveX event handlers.

All information is readily available from anywhere; all on-board or insertable components can communicate with each other (via Python scripts), these scripts have access to all parts of the application, and everything kan be made available over the network or serial cables.

The text protocol used is the Tordivel TDVCommandProtocol.

TDVCentral2 and ActiveXContainerX is a part of the TORDIVEL SOFTWARE SOLUTIONS.

TDVCentral2 is copyright of TORDIVEL AS 2002, 2003.

23 February 2003, Oslo, Norway.

Help Index

•	The Package

•	The ActiveXContainerX component

•	Commandline interface

•	Using the TDVCentral2 application

•	External interface

•	All about scripts  How to program the WebServer


The Package

TDVCentral2 is shipped with a number of components:

•	ReadMe.txt (read me file)

•	TDVCentral2.exe (program)

•	TDVCentral2.hlp (this help file)

•	ActiveXContainerX.ocx (the component)

•	ActiveXContainerX.hlp (help file)

•	Several additional ActiveX and COM components.

•	Python 2.2.1 runtime DLL


The ActiveXContainerX component

The ActiveXContainerX is a component which acts as a container for any ActiveX control.  The contained control’s Methods, Properties and Events are exposed through a textual interface to the housing application, where methods are called with named arguments, properties are exposed as Set and Get methods, and events are signalled through a single “Notify” event with the original event from the control and its parameters are sent as text. The text protocol used is the Tordivel TDVCommandProtocol.

For more information please refer to the ActiveXContainerX help file.


TDVCentral2 command line interface

Command line switches:

•	“-hide” hides the application window

•	Any other string is regarded as the name of an SPB file with configuration data that is attempted loaded on startup.

•	If no filename is given on the command line, the application tries to read a filename stored in a file “TDVCentral2.ini” in the current directory. This file is always created when the application exits, naming the last SPB file used.


Using the TDVCentral2 application

The application consists of a number of tabbed pages. When first started, there is only one main tab – Configure.  As ActiveX controls are inserted, each will appear on a page of its own (except hidden controls).

The Configure tab houses seven tabs – some of these have sub-tabs; here is the full tree:

•	General

•	Setup

o	Plugins

o	Scripts

o	Hidden pages

•	Scheduler

•	CrossIndex

•	Communication

o	TCP/IP

o	RS-232

•	Web server

•	System Log

•	About


General

Confirm close application: Tick to avoid closing the application inedvertently. If anything in the configuration has changed, you will always be prompted to save before the application exits.

Always save state when closing application: tick this to avoid the confirmation dialog to save data. Note: if you have not yet specified an .SPB file, you will be asked for a filename.

Send response to unknown/invalid commands: Tick to always send results via TDVCmdProtocol commands. If unticked, only responses to valid command (scripts, controls) are sent.

Application name: Set the main window caption here.

Configure name: Set the caption of the “configure” tab here.

Internal components available from TDVCmdProtocol: When ticked, the on-board components (Scheduler, Crossindex, Web Server, System Log) are available via the TDVCmdProtocol (either TCP/IP or RS-232).

Send response from internal components: If ticked, all internal components will generate command responses and send them back to the sender via either TCP/IP or RS-232.

Allow shutdown from TDVCmdProtocol: If ticked, the application can be closed via either TCP/IP or RS-232 (see external interface).

Separate size kept for configure mode: The application can remember two sets of screen positions, one for Configure (logged-in) mode, and one for normal mode.

Make application topmost: Set the main window as topmost.

Password protected login: If selected, the Configure page will be hidden at startup, and the script editor and Python log will never be visible. You will be asked to supply a password. A Logout/Login item will be made available on the system menu.

Load/Save SPB: The Structured Property Bag (SPB) file contains the complete configuration.


Plugins

TDVCentral2 is extended using standard ActiveX components. These are managed using the plugins page.

This is the configuration/test page. Use the “New page” button to insert new named pages, each containing an ActiveXContainerX control, that in turn can house any other ActiveX control registered with your system.

(The page can be created “hidden” – see Hidden pages.)

 When a page is inserted, a new main tab is created with a page for the control.

Highlight the new page name in the Page list and click New control to select an ActiveX control to be inserted. The page is immediately displayed with the new control inserted.

Any methods the control exposes are listed in the “Method info” list, with parameter names and types. The controls are identified by the name of the inserted page, with a period (‘.’) separating the control name from the command name, for example, “Calendar.AboutBox”. See the ActiveXContainerX help file for syntax information. Note: the Python script engine is accessible via the “pagename” Script. See the Scripts page for more information.

If you double-click a message in the Messages list, the text is copied to the Command edit field. By clicking Execute the command is sent to the named control, and the result is shown in the Result field:

Note that all string handling here is case insensitive: “Calendar.GetYear” and “calendar.getyear” are considered equal.

Available externally and Send command responses set the behaviour for each inserted control – see the General page for more information.

You can set the relative order of the pages with the arrow buttons. The other buttons should be self-explanatory.

Load SPB and Save SPB loads or saves the complete state of the application, with controls.

Note: the ActiveXContainerX “Notify” method and “Execute” event are not supported in this application.


Scripts

The scripts page manages all Python scripts defined.

There are several kinds of scripts involved on this page, listed under Source:

•	[Script] – these are general named functions you can define. See Script details

•	[Central] – these are the Start and Stop scripts, executed on startup and shutdown, respectively. Note that these scripts are not function definitions like all the other scripts, but rather lines that are executed directly.

•	[Scheduler] – each event exported from the built-in scheduler component can have a script associated with it. When you edit such a script, a skeleton with parameter information is generated for you. See “Editing Scripts” below for details, or Script details

•	[TCPIP] – same for the built-in networking component

•	[RS232] – same for the built-in serial component

•	[WebServer] – same for the built-in web server component

•	 (Pagenames) – similar, but for the configured ActiveX controls

The [All] source lists all defined scripts.

Each script also has a checkbox associated with it – you can temporarily (or permanently) disable a script by unticking it. The scripts themselves are retained until you delete them manually, even if the associated control page is deleted.

You can execute a script at any time by pressing Run. If the selected script needs parameters, you are prompted to supply them manually. See also Script details for more information.

Show python messages on error: For debugging purposes, the Python log can appear automatically if an error occurs in a script. The user must be logged in for this to have any effect.

Edit script on error: The Python script editor can appear automatically if an error occurs in a script, with the cursor positioned at the point of error. The user must be logged in for this to have any effect.

Scripts avail. from TDVCmd/Send responses to scripts set the behaviour for the general ([Script]) scripts – see the General page for more information.

Editing Scripts

Select a script in the “Scripts” box and press Edit, or double-click the script name. The script editor is shown with the current contents of the script.

Each script being edited is given a tabbed page on its own in the modeless editor. Pressing Cancel will abandon the current script; pressing Apply will register the script with the Python engine, but keep the editor open; Close will first apply, then close the editor tab. Run will first apply, the actually run the script. If the script needs parameters, you will be prompted to give them manually.

The … all buttons will of course handle all open scripts.

In case of syntax errors, you will not be allowed to close the editor, and both the Apply and Close buttons will inform you of the error, letting you re-edit it:

Note also in this example how the scripts are auto-generated:

•	The page Calendar has an event called KeyDown – the generated script is called Handle_Calendar_Keydown. This script is then executed when the event is signalled. See the “Script details” page (below) for more information on this.

•	The parameters are the ones from the event, with type information given as comments. In this case the first parameter is of type VT_PTR, which is a generic pointer that is unfortunately not handled by ActiveXContainerX. Parameter two is a two-byte integer, passed by value.

I have done my best to decode the Python error log, and find that in most cases, I pinpoint the error correctly. However, there must be cases I do not handle correctly, so please refer to the Python log if in doubt.

For more complete information on scripts, see Script details.


All the gory details regarding scripts

Event handlers

All events that are exported from the contained ActiveX controls, and most events from the built-in components, get a wrapper function defined in Python with the (Handle_) name defined in the Scripts page. Normally you will not call these scripts yourself (they are really event handlers), but you are of course free to do so. Parameters are typed, but everything is converted to strings before the function is called. Even so, things work mostly as expected – for example, you can do maths on numeric variables without converting anything.

The built-in components also raise events and have callable functions; these are slightly different and in some cases more powerful – see the description below.

ActiveX dispatch functions

Each exported function from an ActiveX control is also wrapped in a Python function. The real name of such a function is for example Calendar_SetYear, but for convenience, an alias name of Calendar.SetYear is also made. To access any of these from a Python script, simply follow this convention:

•	The page name is converted to a python class (case sensitive in Python)

•	The function name is unaltered (but also case sensitive in Python)

•	The function name is therefore Page.Function

•	All parameters are sent as a long string with Name=Value;…

For example:

Calendar.SetMonth(“Value=6”)

This Python call is transformed to a call to the Delphi callback Central.Execute. It should be of little importance here, but you can also call that method directly yourself. This function should be given a single parameter, specifying a TDVCmdProtocol string. To do the same as above, you may call:

Central.Execute(“Calendar.SetMonth;Value=6”)

The return value from such a call is a TDVCmdProtocol formatted string. The examples above would both result in this string returned to your Python function:

Calendar.SetMonthResponse;Value=6;Result=OK

This may be changed. For example, the following call:

Calendar.GetMonth()

returns this

Calendar.GetMonthResponse;Result=6

I believe the “Central.Execute” call should still return this value, while the abbreviated “Calendar.GetMonth” should return simply 6.

The functions defined are also available from TDVCmdProtocol (unless you select to hide them in the Plugins or Scripts pages), by using exactly the same syntax given in the Central.Execute example above.

General scripts

You can generate generic scripts from the Scripts page in TDVCentral2 by pressing New.

A new script skeleton is generated,

The script does nothing by default, but is syntactically legal. (The “import Central” line is probably not needed in all scripts – I’ll look into that...)

You can add parameters to this function, for example:

Remember that you have access to all the other generated scripts, including event handlers and control functions, and any global variables you may have defined, e.g., in the Start script (below). Upon Applying this script, it is also available to any other scripts you have.

Note: All scripts generated this way should just be “def” statements – that way, the model works very well. There is nothing stopping you from writing any Python code you want in these scripts, possibly apart from your own confusion. When the Apply or Close button is pressed, the contents of the editor is simply executed by the Python engine, notifying you of any syntax (or exec) errors. When you press the Run button, the script source is inspected, and if the “def” line has any parameters, you will be prompted to supply them before the function is actually executed.

All the scripts defined this way are also available from TDVCmdProtocol using the special “Page” name Script. For example, you may call the script defined above by sending this string to TDVCentral2:

Script.Double(100)

Note: This is the only place the TDVCmdProtocol commands are case sensitive. You may not call

Script.double(100)

although

script.Double(100)

iis quite OK.

Note also: The string sent here does not conform to the TDVCmdProtocol. You can not enter parameters following a semicolon.

Start/stop scripts

There is a script run at startup, as well as a script run just before shutdown. I like defining global variables and setting up system parameters in the startup script.  When the startup script is run, all control pages have been initiated, so all functions (like Calendar.SetMonth) are available.

Note: These scripts are special. They are NOT run when the editor’s Apply or Close buttons are pressed.

Script execute errors

During runtime, if a Python error occurs when a script is run, two things may happen depending on your settings.  First, the Python error log may pop up; second, an editor may pop up showing the point of error in your script(s). Again, I have done as much as I could to decode the Python messages, and if you follow the conventions with scripts, the correct script should show up in the editor with the error, even in a nested Python function call. No guarantees, though…

Built-in components

For the built-in components Scheduler, CrossIndex, IMTdvCommandProtocol (i.e. TCPIP), RS232CmdProtocol (RS232), WebServer and System log there are also special “Page” names defined, giving access to events and callable functions. In addition, you have complete access to the TDVCentral2 Structured Property Bag (SPB) configuration. A summary of all this is found here. See also the links below.

•	Scheduler

•	CrossIndex

•	IMTDVCmdProtocol

•	RS232TDVCmdProtocol

•	WebServer  How to program

•	System log

•	SPB access

•	General commands.

The general TDVCmdProtocol commands are:

GetVersion

Show;Value=Hide|Normal|Status

Shutdown

The first returns a version string; the second controls (or probes) the visibility of the application; the third will cause the application to exit (see general for details).


External Interface

There are several commands available via TDVCmdProtocol; see these pages for details:

These are all commands that are available via TDVCmdProtocol. Note that either of these may be turned off, and that responses may also be turned off.

General commands

Scheduler commands

Crossindex commands

TCP/IP commands

RS-232 commands

Web server commands

System log commands

SPB commands

Script commands

Dynamic component commands


General commands

Command: GetVersion

Response: GetVersionResponse;Version 2.0 update 6 build 25, 23 February 2003

Comments:

Command: Show;Value=Hide|Normal|Status

Response: ShowResponse;Status=Visible|Hidden

Comments:

Command: ShowPage;Name=<name>

Response: ShowPageResponse; Result=OK|Error

Comments:

Command: Shutdown

Response: ShutdownResponse;Result=OK|Error

Comments:


Scheduler commands

Command: Scheduler.IsEvent;Name=<name>

Response: Scheduler.IsEventResponse;Name=<name>;Result=True|False

Comments:

Command: Scheduler.SetEventActive;Name=<name>; Active=True|False

Response: Scheduler.SetEventActiveResponse;Name=<name>;Result=OK|Error

Comments:

Command: Scheduler.IsEventActive;Name=<name>

Response: Scheduler.IsEventActiveResponse;Name=<name>;Result=True|False|Error

Comments:

Command: Scheduler.ExecuteEvent;Name=<name>

Response: Scheduler.ExecuteEventResponse;Name=<name>;Result=OK|Error

Comments:


Crossindex commands

Command: TDVCentral.SetProperty;Name=<name>;Value=<value>

Response: TDVCentral.SetPropertyResponse;Name=<name>;Value=<value>;Result=OK|Error

Comments:

Command: TDVCentral.GetProperty;Name=<name>

Response: TDVCentral.GetPropertyResponse;Name=<name>;Result=<value>|Error

Comments:

Command: TDVCentral.DeleteProperty;Name=<name>

Response: TDVCentral.DeletePropertyResponse;Name=<name>;Result=OK|Error

Comments:

Command: TDVCentral.IsProperty;Name=<name>

Response: TDVCentral.IsPropertyResponse;Name=<name>;Result=True|False

Comments:


TCP/IP commands

Command: IMTDVCmdProtocol.Send;Command=<command>

Response: IMTDVCmdProtocol.SendResponse;Command=<command>;Result=OK|Error

Comments: Command may contain “destination=…”. An “OK” return value does not guarantee that the command was received by anyone, only that it was sent.

Command: IMTDVCmdProtocol.GetTimeout

Response: IMTDVCmdProtocol.GetTimeoutResponse;Result=<value>

Comments: Value in seconds

Command: IMTDVCmdProtocol.SetTimeout;Value=<value>

Response: IMTDVCmdProtocol.SetTimeoutResponse;Value=<value>;Result=OK|Error

Comments:

Command: IMTDVCmdProtocol.GetPortNo

Response: IMTDVCmdProtocol.GetPortNoResponse;Result=<value>

Comments: SetPortNo is not available

Command: IMTDVCmdProtocol.GetMode

Response: IMTDVCmdProtocol.GetModeResponse;Result=0|1|2

Comments: 0=normal; 1=simulation; 2=disabled

Command: IMTDVCmdProtocol.SetMode;Value=<value>

Response: IMTDVCmdProtocol.SetModeResponse;Value=<value>;Result=OK|Error

Comments: Caution: You can disable reception using this. If you set mode to anything else than 0, you will not get a response on TCP/IP, and you cannot send furher commands.

Command: IMTDVCmdProtocol.GetPortOpen

Response: IMTDVCmdProtocol.GetPortOpenResponse;Result=True|False

Comments:

Command: IMTDVCmdProtocol.GetPortParametres

Response: IMTDVCmdProtocol.GetPortParametresResponse;Result=<value>

Comments: Value is “remote machine:port”

Command: IMTDVCmdProtocol.SetPortParametres; Value=<value>

Response: IMTDVCmdProtocol.SetPortParametresResponse;Value=<value>;Result=OK|Error

Comments:


RS-232 commands

Command: RS232TDVCmdProtocol.Send;Command=<command>

Response: RS232TDVCmdProtocol.SendResponse;Command=<command>;Result=OK|Error

Comments:

Command: RS232TDVCmdProtocol.GetTimeout

Response: RS232TDVCmdProtocol.GetTimeoutResponse;Result=<value>

Comments:

Command: RS232TDVCmdProtocol.SetTimeout;Value=<value>

Response: RS232TDVCmdProtocol.SetTimeoutResponse;Value=<value>;Result=OK|Error

Comments: Value in seconds

Command: RS232TDVCmdProtocol.GetPortNo

Response: RS232TDVCmdProtocol.GetPortNoResponse;Result=<value>

Comments: SetPortNo is not available

Command: RS232TDVCmdProtocol.GetMode

Response: RS232TDVCmdProtocol.GetModeResponse;Result=0|1|2

Comments: 0=normal; 1=simulation; 2=disabled

Command: RS232TDVCmdProtocol.SetMode;Value=<value>

Response: RS232TDVCmdProtocol.SetModeResponse;Value=<value>;Result=OK|Error

Comments:

Command: RS232TDVCmdProtocol.GetPortOpen

Response: RS232TDVCmdProtocol.GetPortOpenResponse;Result=True|False

Comments:

Command: RS232TDVCmdProtocol.GetPortParametres

Response: RS232TDVCmdProtocol.GetPortParametres;Result=<value>

Comments: Value is “baud:bytelen:parity:stopbits”

Command: RS232TDVCmdProtocol.SetPortParametres; Value=<value>

Response: RS232TDVCmdProtocol.SetPortParametresResponse;Value=<value>;Result=OK|Error

Comments:


Web server commands

Command: WebServer.AsyncPostResponse;ID=<id>;ContentType=<type>;ExHeaderLines=<lines>;Body=<body>;Code=<code>

Response: WebServer.AsyncPostResponseResponse;ID=<id>;ContentType=<type>;ExHeaderLines=<lines>;Body=<body>;Code=<code>;Result=OK|Error

Comments: This is normally called from a script, not by external means.


System log commands

Command: SystemLog.Add; Level=<level>; Source=<source>; Text=<text>

Response: SystemLog.AddResponse;Level=<level>;Source=<source>;Text=<text>;Result=OK|Error

Comments: <level> is one of

-1: Error

0: Warning

1,2,3: normal log of the given level


SPB commands

Command: SPB.GetRoot

Response: SPB.GetRootResponse;Result=<path>

Comments: SPB access routed to this subsection

Command: SPB.SetRoot; Root=<path>

Response: SPB.SetRootResponse;Root=<path>;Result=OK|Error

Comments:

Command: SPB.GetDelimiter

Response: SPB.GetDelimiterResponse;Result=<delimiter>

Comments: Default delimiter is ‘.’ (period)

Command: SPB.IsSection; Section=<path>

Response: SPB.IsSectionResponse;Section=<path>;Result=True|False

Comments:

Command: SPB.SetSection; Section=<path>

Response: SPB.SetSectionResponse;Section=<path>;Result=True|False

Comments: Creates section if it does not already exist

Command: SPB.DeleteSection; Section=<path>

Response: SPB.DeleteSectionResponse;Section=<path>;Result=True|False

Comments: The section and any subsections/entries are deleted

Command: SPB.IsEntry; Path=<path>

Response: SPB.IsEntryResponse;Path=<path>;Result=True|False

Comments:

Command: SPB.GetEntry; Path=<path>

Response: SPB.GetEntryResponse;Path=<path>;Result=<value>

Comments: Returns an empty string if entry does not exist

Command: SPB.SetEntry; Path=<path>; Value=<value>

Response: SPB.SetEntryResponse;Path=<path>;Value=<value>;Result=OK|Error

Comments: Add or modify entry. If you specify a non-existing path, and intermediate sections are automatically created.

Command: SPB.DeleteEntry; Path=<path>

Response: SPB.DeleteEntryResponse;Path=<path>;Result=True|False

Comments:

Command: SPB.BrowseSections; Path=<path>

Response: SPB.BrowseSectionsResponse;Path=<path>;Result=<value>

Comments: Returns comma separated list

Command: SPB.BrowseEntries; Path=<path>

Response: SPB.BrowseEntriesResponse;Path=<path>;Result=<value>

Comments: Returns comma separated list

Command: SPB.SaveSPB

Response: SPB.SaveSPBResponse;Result=True|False

Comments: Fails if an SPB file name has not been set


Script commands

Command: Script. <name>(<parameters>)

Response: ScriptResponse;Script=<name>(<parameters>);Result=<value>

Comments: Generic Python scripts. Result is the return value from the Python script (‘None’ if no return value).


Dynamic component commands

Command: <Page>. <Command> [;<Name>=<Value>;…]

Response: <Page>.<Command>Response[;<Name>=<Value>;…];Result=<value>

Comments: <Page> is one of the dynamic ActiveX pages. The command result varies, but ‘Error’ means the command failed.


Hidden pages

The “Hidden pages” are no different from the main control pages, except that they do not show up in the top tabs of the application. Otherwise, any exported functions, properties and events are treated the same way as the none-hidden controls.

There is unfortunately no way to move pages between the main and the Hidden stores.


Scheduler

The Scheduler lives its own life in TDVCentral2 and stores its settings in the TDVCentral2 SPB file. It also generates events and TDVCmdProtocol commands, and may be accessed via commands sent to the special “page” Scheduler.

When a scheduled event is triggered from the Scheduler, the command string is sent directly to the TDVCentral2 Execute engine, so you may for example add an event that sends the command

Calendar.SetMonth(‘Value=8’)

These events (note the name confusion – these are component events!) are available via Python event handlers:

•	AddedEvent(EventName)

•	ChangeEvent(EventName)

•	DeletedEvent(EventName)

•	Error(Id,EventName,Description)

•	ScheduledEvent(EventName,Command)

These functions are available to control the Scheduler via the TDVCmdProtocol interface (details here):

•	Scheduler.IsEvent;Name=<name>

•	Scheduler.SetEventActive;Name=<name>;Active=True|False

•	Scheduler.IsEventActive;Name=<name>

•	Scheduler.ExecuteEvent;Name=<name>

To call these functions from a Python script, you use an abbreviated form,

Scheduler.IsEvent(<name>)

The return value is the TDVCmdProtocol Result field, possibly translated from True or OK to 1, or from False or Error to 0, otherwise unchanged. This translation means you can write

if Scheduler.IsEvent(‘Tick’):

Scheduler.ExecuteEvent(‘Tick’)


CrossIndex

This is a simple “database” storing name/value pairs. It is editable and stores its settings in the TDVCentral2 SPB file, and may also be accessed via TDVCmdProtocol commands sent to the special “page” TDVCentral.

(There are currently no component events from the CrossIndex database.)

These functions are available to control the CrossIndex via the TDVCmdProtocol interface (details here):

•	TDVCentral.SetProperty;Name=<name>;Value=<value>

•	TDVCentral.GetProperty;Name=<name>

•	TDVCentral.DeleteProperty;Name=<name>

•	TDVCentral.IsProperty;Name=<name>

To call these functions from a Python script, you use an abbreviated form,

TDVCentral.IsProperty(<name>)

The return value is the TDVCmdProtocol Result field, possibly translated from True or OK to 1, or from False or Error to 0, otherwise unchanged. This translation means you can write

if TDVCentral.IsProperty(‘Country’):

Country = TDVCentral.GetProperty(‘Country’)


TCP/IP (IMTDVCmdProtocol)

By configuring the IMTDVCmdProtocol component, remote control of TDVCentral2 or any of the contained components is activated. The syntax used is the TDVCmdProtocol, where an ActiveX method is identified by “<pagename>.<methodname>”. See elsewhere in this document for details.

The IMTDVCmdProtocol component stores its state in the TDVCentral2 SPB file.

These events are available via Python event handlers:

•	Command(Command)

•	PacketStart(Source)

•	PacketEnd(Source)

•	Value(Name,Value)

These functions are available to control the IMTDVCmdProtocol via the TDVCmdProtocol interface (details here):

•	IMTDVCmdProtocol.Send;Command=<command>

•	IMTDVCmdProtocol.GetTimeout

•	IMTDVCmdProtocol.SetTimeout;Value=<value>

•	IMTDVCmdProtocol.GetPortNo

•	IMTDVCmdProtocol.GetMode

•	IMTDVCmdProtocol.SetMode;Value=<value>

•	IMTDVCmdProtocol.GetPortOpen

•	IMTDVCmdProtocol.GetPortParametres

•	IMTDVCmdProtocol.SetPortParametres;Parametres=<value>

(Note that the GetSeparator, SetSeparator and SetPortNo calls are disabled.)

To call these functions from a Python script, you use an abbreviated form,

IMTDVCmdProtocol.Send(‘destination=localhost:7654:Analysis finished’)

The return value is the TDVCmdProtocol Result field, possibly translated from True or OK to 1, or from False or Error to 0, otherwise unchanged. This translation means you can write

if IMTDVCmdProtocol.GetPortOpen():

IMTDVCmdProtocol.Send(‘Analysis finished’)


RS-232 (RS232TDVCmdProtocol)

By configuring the RS232TDVCmdProtocol component, serial line control of TDVCentral2 or any of the contained components is activated. The syntax used is the TDVCmdProtocol, where an ActiveX method is identified by “<pagename>.<methodname>”. See elsewhere in this document for details.

The RS232TDVCmdProtocol component stores its state in the TDVCentral2 SPB file.

These events are available via Python event handlers:

•	Command(Command)

•	PacketStart()

•	PacketEnd()

•	Value(Name,Value)

These functions are available to control the RS232TDVCmdProtocol via the TDVCmdProtocol interface (details here):

•	RS232TDVCmdProtocol.Send;Command=<command>

•	RS232TDVCmdProtocol.GetTimeout

•	RS232TDVCmdProtocol.SetTimeout;Value=<value>

•	RS232TDVCmdProtocol.GetPortNo

•	RS232TDVCmdProtocol.GetMode

•	RS232TDVCmdProtocol.SetMode;Value=<value>

•	RS232TDVCmdProtocol.GetPortOpen

•	RS232TDVCmdProtocol.GetPortParametres

•	RS232TDVCmdProtocol.SetPortParametres

(Note that the GetSeparator, SetSeparator and SetPortNo calls are disabled.)

To call these functions from a Python script, you use an abbreviated form,

IMTDVCmdProtocol.Send(‘destination=localhost:7654:Analysis finished’)

The return value is the TDVCmdProtocol Result field, possibly translated from True or OK to 1, or from False or Error to 0, otherwise unchanged. This translation means you can write

if RS232TDVCmdProtocol.GetPortOpen():

RS232TDVCmdProtocol.Send(‘Analysis finished’)


WebServer

This is a web server component that can be pretty much fully customised by a set of Python scripts.

These events are available via Python event handlers:

•	GET(Requester,URL,Header,Body)

•	GETCompleted(Requester,URL,Code)

•	PUT(Requester,URL,Header,Body)

•	PUTCompleted(Requester,URL,Code)

•	DELETE(Requester,URL,Header,Body)

•	DELETECompleted(Requester,URL,Code)

•	HEAD(Requester,URL,Header,Body)

•	HEADCompleted(Requester,URL,Code)

•	POST(Id,Requester,URL,Header,Body)

These event handlers are very special indeed. All apart from the “--Completed” ones also return values to the web server, controlling the responses to requests. When you generate event handlers, you will be given comments to get you going. For Details, see How to program, here is just a summary of your options:

•	The GET handler can accept or deny the transaction, or compose the return value itself (either as text or as a file)

•	The PUT, DELETE and HEAD handlers can accept or deny the transaction

•	The POST handler must be implemented for any POST calls to be accepted. The script is responsible for handling this, either syncroneously or asyncroneously.

Only one function is available to the WebServer via the TDVCmdProtocol interface (details here):

•	WebServer.AsyncPostResponse;ID=<id>;ContentType=<type>;ExHeaderLines=<lines>;Body=<body>;Code=<code>

To call this function from a Python script, you use the abbreviated form,

WebServer.AsyncPostResponse(<id>,<type>,<exheaderlines>,<body>,<code>)

This is a belated reply to a POST event, needed if the POST handler specifies asyncroneous reply.

How to program


Programming the WebServer with Python handlers

GET requests

If you do not write an event handler for WebServer GET requests, the default behaviour is to return the contents of a file named in the URL field (unless, of course, you disable GET requests under the WebServer tab in TDVCentral2).

The autogenerated skeleton event handler looks like this:

import Central

def Handle_WebServer_GET(Requester,URL,Header,Body):

    #

    # Requester = VT_BSTR

    # URL = VT_BSTR

    # Header = VT_BSTR

    # Body = VT_BSTR

    #

    # Return 0 to deny, 1 to accept,

    # or return tuple (Code,ContentType,ExHeaderLines,Response,Type).

    # Type is 1 if Response is filename, 2 if Response is body.

    #

    # return 1

    # return (200,"text/plain","","Python says hello",2)

    #

    return 1

The parameters to the function are extracted from the incoming HTTP message, and gives information about the request. The further processing depends on your return value(s).

Returning an integer:

By returning 1 (as above) you tell the WebServer to accept the request for default handling; by returning 0 it will deny it (which means the requester will be given a return code of 403, “Forbidden”).

Returning a tuple:

The five items in the tuple are –

•	Code: integer. The most common values are 200 (OK), 400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found). Refer to RFC2068 for more codes.

•	ContentType: string. Common values are “text/plain”, “text/html”, “image/gif”, “image/jpeg”, but several more common codes exist.

•	ExHeaderLines: string. With this optional field you can add lines to the HTTP header. Each line must be of the format “<item>: <data>”, for example “Date: 2002-08-23”. If more than one line is specified, they must be separated by a CR/LF pair. You can code this using “\r” and “\n”, as in “Date: 2002-08-23\r\nTime: 08:00:00”. You do not need to put in the CR/LF pair at the end, that is done automatically if not present.

•	Response: string. In a HTTP reply this is really a series of 8-bit bytes. In TDVCentral2 you specify a text string. If Type (the last tuple item) is returned as 1, this string is used as a file name, and the contents of that file are sent as the response body. (This is an absolute filename, and is not related to the WebServer Root directory!). If Type is set to 2, the raw contents of the string (8 bits per character) are sent as the body.

•	Type: 1 or 2, see above.

Example – returning a file:

def Handle_WebServer_GET(Requester,URL,Header,Body):

    # (...)

    return (200, "text/html", "", "C:/web/information.htm", 1)

Example – returning text:

def Handle_WebServer_GET(Requester,URL,Header,Body):

    # (...)

    response = "For information refer to RFC2068."

    return (200, "text/plain", "", response, 2)

Example – using the requester’s IP address to decide:

def Handle_WebServer_GET(Requester,URL,Header,Body):

    # (...)

    if Requester.startswith("127.0.0.1"):

        print 'local access allowed from',Requester,':',URL

        return 1

    if URL.lower().endswith('.gif'):

        print 'gif access allowed from',Requester,':',URL

        return 1

    print 'remote access politely denied to', Requester

    header = '<html><title>Sorry</title><body>'

    body = '<H1>Access not granted</H1>'

    footer = '</body></html>'

    return (200,"text/html","",heaader+returnbody+footer,2)

PUT, DELETE and HEAD requests

For all of these requests, you simply return 0 to deny or 1 to accept. Not defining a handler results in the default action (accept) being taken.

POST requests

If the POST event handler is not implemented, POST requests are denied by the WebServer, returning the code 501 “Not Implemented”.

The autogenerated skeleton event handler looks like this:

import Central

def Handle_WebServer_POST(ID,Requester,URL,Header,Body):

    #

    # ID = VT_I4

    # Requester = VT_BSTR

    # URL = VT_BSTR

    # Header = VT_BSTR

    # Body = VT_BSTR

    #

    # Return 0 to deny, 1 for Async response, or return tuple

    # (Code,ContentType,ExHeaderLines,Response).

    # If you return nonzero for Async, you should call

    # WebServer.AsyncPostResponse later.

    #

    # return 1

    # return (200,"text/plain","","Postresponse")

    #

    return (200,"text/plain","","Postresponse")

The parameters are the same as for GET, except that a unique sequence ID (integer) is also given. This ID is important only for asynchroneous replies (below).

Again, you can return an integer or a tuple.

Returning an integer:

Simply return 1 to accept the request for asynchroneous handling (see below), or return 0 to deny it (which means 501 “Not Implemented” to the client).

Returning a tuple:

The five items in the tuple are (see also the description for GET above) –

•	Code: integer.

•	ContentType: string.

•	ExHeaderLines: string.

•	Response: string. For POST requests, the contents of this string (8 bits per character) are always sent as the body.

Example – returning a string:

def Handle_WebServer_POST(ID,Requester,URL,Header,Body):

    # ...

    return (200,"text/plain","","Postresponse")

Example – deferring the reply (asynchroneous handling):

def Handle_WebServer_POST(ID,Requester,URL,Header,Body):

    # (...)

    start_something(ID,Requester,URL,Header,Body)

    return 1

The function start_something is not defined here, but it must somehow manage to at a later stage (after the POST handler has returned, mind you!) result in a call to the Async handler in the WebServer, as shown below.

Asynchroneous POST response

When the POST response has been determined, the HTTP request can be satisfied by the following call in a Python script of your choice:

    WebServer.AsyncPostResponse(ID,Code,ContentType,ExHeaderLines,Body)

The ID must correspond to one received in a call to Handle_WebServer_POST earlier. What happens here is that the WebServer will map the ID to a request that was earlier given an asynchroneous handling, and send the values back to the requester. The parameters to the function are (with the exception of the ID) exactly the same as the items that would be returned as a tuple in a synchroneous response.

Of course, this call can also be made using TDVCmdProtocol. For example, an external program can make this call to satisfy the request:

WebServer.AsyncPostResponse;ID=<ID>;Code=<code>;ContentType=<contenttype>;ExHeaderLines=<exheaderlines>;Body=<body>


System log

This is basically an inaccessible component, with one minor exception.

Using TDVCmdProtocol, you can add a line to the log using this syntax (details here):

SystemLog.Add;Level=<level>;Source=<source>;Text=<text>

where <level> is one of

•	-1 – Error

•	0 – Warning

•	1,2,3 – normal log of the given level

To call these functions from a Python script, you use,

SystemLog.Add(<level>,<source>,<text>)

The return value is the TDVCmdProtocol Result field, translated to either 1 for success or 0 for failure.


SPB access

There is direct access to the Structured Property Bag database through the SPB interface, available both from TDVCmdProtocol and Python. The SPB contains several ‘predefined’ sections, e.g., ‘CentralFrame’ and ‘Eventlog’. Writing data to any of these sections will have no effect, since fresh copies of these sections are fetched from the components when the SPB is written to file.Otherwise, you are free to read or write anywhere in the SPB structure. If you stick to the default base (Root), you have an excellent structured database available under the ‘Database’ section In the SPB.

The available commands are (details here):

•	SPB.GetRoot

•	SPB.SetRoot;Root=<path>

•	SPB.GetDelimiter

•	SPB.IsSection;Section=<path>

•	SPB.SetSection;Section=<path>

•	SPB.DeleteSection;Section=<path>

•	SPB.IsEntry;Path=<path>

•	SPB.GetEntry;Path=<path>

•	SPB.SetEntry;Path=<path>;Value=<value>

•	SPB.DeleteEntry;Path=<path>

•	SPB.BrowseSections;Path=<path> (returns comma separated list)

•	SPB.BrowseEntries;Path=<path> (returns comma separated list)

•	SPB.SaveSPB (fails if an SPB file name has not been set)

From a Python script, you would use

SPB.SetRoot(‘Database’) (this is the default)

SPB.SetEntry(‘MySection.MinValue’,0) (assuming the delimiter is the default ‘.’)

SPB.SetEntry(‘MySection.MaxValue’,10)

Entries = SPB.BrowseEntries(‘MySection’).split(‘,’)

You can freely create entries/subsections in non-existing sections – any missing sections will automatically be made for you. If you delete a section, all values and subsections will be destroyed as well.


About

This page shows today’s details of your system…

The Licence info button reveals details about your TDVCentral licence (or any other TDV licences registered on your computer).


TORDIVEL SOFTWARE SOLUTIONS

TORDIVEL AS Software House is developing a portfolio of Windows NT/2000 software components and solutions with the following properties:

•	Simple and easy to use

•	Very high quality

•	Requirements from real use cases

•	Easy to deploy

•	"Simply working"

•	Network applications building blocks

Important keywords are: HTTP, TCP/IP, XML, and stateless servers.

These components and solutions are divided into two categories:

•	Professional Software Components

•	Freeware Components Library

We distribute the components and solutions to promote the skills of the experienced developers working at TORDIVEL and want to establish links to developers and companies all over the world.

If you have comments/suggestions your feedback is more than appreciated. Please contact us.

Storgata 20 N-0184 OSLO NORWAY
Telefax +47 2315 8701 Telephone +47 2315 8700
E-mail: office@tordivel.com Web: http://www.tordivel.com


Copyright Notice

(c) 2002,2003 TDVCentral2 is copyright of

Storgata 20 N-0184 OSLO NORWAY
Telefax +47 2315 8701 Telephone +47 2315 8700
E-mail: office@tordivel.com Web: http://www.tordivel.com