Main Page | Features | Central Services | csv-Files | Types | Transfer | Access | API-C | API-.NET | API-Java | Examples | Downloads
page generated on 22.12.2024 - 04:45
The buffered Server for Visual Basic .NET programs

VB Programmers:

A "do-nothing" server

  • create a new VB project called myServer (or myVbServer if you already have a c project named this).
  • In the Solution explorer under the myServer Class, right mouse click to get an options menu and choose 'Add Reference'
  • In the Add Reference dialog, browse to the tine .NET dll. This is called tine.dll and is found in L:\System32 (as long as you have L: substituted or mapped correctlyh).
  • VB will make a Form1 Class for you (unless you have renamed it to something else). Open the code for Form1.vb.
  • Add 'Imports time' at the top of this file.
  • We will read the same server database as the other examples, so we won't need to do any property or device registration via API.
  • Add empty sub routines called sinini(), sinexi(), and sinbkg(). We'll fill in the background task shortly.
  • Add a sub routine called sineqm() with the following prototype:
    Public Function sineqm(ByVal dev As String, ByVal prp As String, ByVal dout As TDataType, ByVal din As TDataType, ByVal acc As UShort, ByVal eqm As TEquipmentModule) As Int32
    End Function
    VB might complain that it doesn't return a value, so add a 'return 0' for the moment
  • At the top of the Class declaration, add a field variable 'myeqm' as a TEequipmentModule
    Public Class Form1
    Dim myeqm As TEquipmentModule
    '...
  • In the Form1_Load() routine (assuming your top form is still called 'Form1') you should attach to the underlying database and start the server. The following three lines of code will accomplish this
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    TKernel.InitializeServer()
    myeqm = New TEquipmentModule("", "SINEQM", 0, AddressOf sineqm, AddressOf sinini, AddressOf sinbkg, 500, AddressOf sinexi)
    TKernel.StartServices()
    End Sub
  • You can now run the server and find it in the Instant Client. Of course, none of the registered properties 'do anything'. They all return 'success' (that's the return 0 you added to sineqm()) and no data.

Check the Log file (please !)

Before rushing to the Instant Client, have a look at the server's log file. This will be called 'fec.log' and should be located in c:\tine\log (if that's where FECLOG is pointing to!), or directly in the working area, if there's no FECLOG environment.

Near the end of the log file you should see a message saying that your equipment module was "registered with equipment name server". If you see this then everything went reasonably well so far.

15.12.13 13:38:15.549 CET[*unknown*] Attach Server to local equipment module SINEQM
15.12.13 13:38:15.549 CET[*unknown*] timer thread starting
15.12.13 13:38:15.551 CET[*unknown*] TineStopCycler has been called
15.12.13 13:38:15.552 CET[*unknown*] terminating local cycle
15.12.13 13:38:15.572 CET[*unknown*] timer thread ending
15.12.13 13:38:15.572 CET[*unknown*] flushing client and contract lists
15.12.13 13:38:15.573 CET[*unknown*] contract table flushed
15.12.13 13:38:15.575 CET[*unknown*] shutting down server ports
15.12.13 13:38:15.575 CET[*unknown*] SystemReset called (level 0)
15.12.13 13:38:15.575 CET[*unknown*] all equipment module memory returned to heap
15.12.13 13:38:15.594 CET[*unknown*] timer thread exited normally prior to wait
15.12.13 13:38:15.595 CET[*unknown*] closing timer thread handle
15.12.13 13:38:15.595 CET[*unknown*] closing system mutex set
15.12.13 13:38:15.596 CET[*unknown*] SystemReset called (level 0)
15.12.13 13:38:15.596 CET[*unknown*] all equipment module memory returned to heap
15.12.13 13:38:15.598 CET[*unknown*] Stock property mutex set initialized
15.12.13 13:38:15.598 CET[*unknown*] system mutexes initialized
15.12.13 13:38:15.599 CET[*unknown*] WIN32 host is little endian
15.12.13 13:38:15.601 CET[*unknown*] VERSION : 4.03.0012
15.12.13 13:38:15.601 CET[*unknown*] OS : WIN32
15.12.13 13:38:15.601 CET[*unknown*] Work Area: 65536
15.12.13 13:38:15.602 CET[*unknown*] Temp Size: 65536
15.12.13 13:38:15.604 CET[*unknown*] FEC: is running multi-threaded
15.12.13 13:38:15.604 CET[*unknown*] FEC HOME : [C:\Users\duval\AppData\Local\tine\servers\]
15.12.13 13:38:15.605 CET[*unknown*] Contract Table: reserved space for 1000 entries
15.12.13 13:38:15.605 CET[*unknown*] Client Table: reserved space for 100 entries
15.12.13 13:38:15.607 CET[*unknown*] alias table (FEC) : no such file
15.12.13 13:38:15.607 CET[*unknown*] exports file exports.csv (FEC): no such file
15.12.13 13:38:15.608 CET[*unknown*] scanning fecid.csv for FEC name
15.12.13 13:38:15.609 CET[*unknown*] C:\Users\duval\AppData\Local\tine\servers\fecid.csv : success
15.12.13 13:38:15.611 CET[*unknown*] unable to register as fec name is unknown!
15.12.13 13:38:15.611 CET[*unknown*] FEC: user access : NONE has DENIED access
15.12.13 13:38:15.611 CET[*unknown*] delaying system initialization
15.12.13 13:38:15.612 CET[*unknown*] RegisterExport : server (export) name -> (null), eqm (local) name -> SINEQM, num devices -> 1
15.12.13 13:38:15.614 CET[*unknown*] looking for exports for local name SINEQM
15.12.13 13:38:15.618 CET[*unknown*] get registered exports from file (24 entries)
15.12.13 13:38:15.619 CET[*unknown*] file SINEQM\devices.csv found
15.12.13 13:38:15.621 CET[*unknown*] device file for SINEQM : found
15.12.13 13:38:15.647 CET[*unknown*] exports file exports.csv (SINEQM): found
15.12.13 13:38:15.648 CET[*unknown*] scanning fecid.csv for FEC name
15.12.13 13:38:15.650 CET[*unknown*] export entry WinSineServer found!
15.12.13 13:38:15.653 CET[SINEGEN.7] accepting SINEGEN.7 as FEC name
15.12.13 13:38:15.654 CET[SINEGEN.7] SINEQM task registration: ---- ---- ----

Browsing your server

Now try to find your server in the Instant Client under the context name you assigned. You will more than likely need to click on the "Reload Names" menu item under options (if the context itself is new) or at a minimum open up and close again the context combo box (this will force a reload of the names under the given context).

You should see your device server and be able to browse the properties and devices you entered in the setup wizard.

You should be able to read a lot of '0' values (not very interesting).

A "do-something" server

  • Let's add some more field variables to the class:
    Public Class Form1
    Dim myeqm As TEquipmentModule
    Private Const PRP_SINE = 1
    Private Const PRP_AMPLITUDE = 2
    Private Const PRP_FREQUENCY = 3
    Private Const NUM_DEVICES = 10
    Private Const NUM_VALUES = 1024
    Dim sinbuf(NUM_DEVICES - 1, NUM_VALUES - 1) As Single
  • Now add some 'meat' to the equipment module handler. We'll handle a request to the a sine curve:
    Public Function sineqm(ByVal dev As String, ByVal prp As String, ByVal dout As TDataType, ByVal din As TDataType, ByVal acc As UShort, ByVal eqm As TEquipmentModule) As Int32
    Dim devnr As Integer
    Dim prpid As Integer
    Dim cc As Integer
    devnr = eqm.GetDeviceNumber(dev, prp)
    prpid = eqm.GetPropertyId(prp)
    Select Case prpid
    Case PRP_SINE
    cc = Errors.illegal_read_write
    If ((acc And Access.CA_WRITE) = 0) Then
    cc = dout.PutData(sinbuf, devnr, NUM_VALUES, 0)
    End If
    Return cc
    End Select
    Return Errors.illegal_property
    End Function
  • But, as is, the 'sine buffer' (variable sinbuf) is unitialized, so the property will still return all zeros. But if this property is called the handler returns a '0' (success). Otherwise we've added a 'return Errors.illegal_property' (Perhaps Errors.non_implemented would be a better idea, as we do plan to implement the other registered properties.
  • Let's make the sinbuf update itself in the background task (simulating hardware i/o). So add some update code to the sinbkg module we created before:
    Public Sub sinbkg()
    Dim k As Integer
    For k = 0 To NUM_DEVICES - 1
    For i = 0 To NUM_VALUES - 1
    sinbuf(k, i) = (Rnd()) * 5 + (Math.Sin(2 * i * 6.2832 / (NUM_VALUES / 8)) * 50)
    Next
    Next
    End Sub
  • Your current VB code should look something like:
    Imports tine
    Public Class Form1
    Dim myeqm As TEquipmentModule
    Private Const PRP_SINE = 1
    Private Const PRP_AMPLITUDE = 2
    Private Const PRP_FREQUENCY = 3
    Private Const NUM_DEVICES = 10
    Private Const NUM_VALUES = 1024
    Dim sinbuf(NUM_DEVICES - 1, NUM_VALUES - 1) As Single
    Public Function sineqm(ByVal dev As String, ByVal prp As String, ByVal dout As TDataType, ByVal din As TDataType, ByVal acc As UShort, ByVal eqm As TEquipmentModule) As Int32
    Dim devnr As Integer
    Dim prpid As Integer
    Dim cc As Integer
    devnr = eqm.GetDeviceNumber(dev, prp)
    prpid = eqm.GetPropertyId(prp)
    Select prpid
    Case PRP_SINE
    cc = Errors.illegal_read_write
    If ((acc And Access.CA_WRITE) = 0) Then
    cc = dout.PutData(sinbuf, devnr, NUM_VALUES, 0)
    End If
    Return cc
    End Select
    Return Errors.illegal_property
    End Function
    Public Sub sinini()
    End Sub
    Public Sub sinexi()
    End Sub
    Public Sub sinbkg()
    Dim k As Integer
    For k = 0 To NUM_DEVICES - 1
    For i = 0 To NUM_VALUES - 1
    sinbuf(k, i) = (Rnd()) * 5 + (Math.Sin(2 * i * 6.2832 / (NUM_VALUES / 8)) * 50)
    Next
    Next
    End Sub
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    TKernel.InitializeServer()
    myeqm = New TEquipmentModule("", "SINEQM", 0, AddressOf sineqm, AddressOf sinini, AddressOf sinbkg, 500, AddressOf sinexi)
    TKernel.StartServices()
    End Sub
    End Class

This basically shows how to service the property 'Sine'. You should now be able to figure out how to add the missing properties from our configuration database.

Channel versus Spectrum Arrays

Copy this new exports.csv into your FEC_HOME database area and restart your server.

Now when you browse for it with the instant client, you should notice that when you click on property "Sine" the display type automatically changes to "PolyLine", i.e. a SPECTRUM data type automatically gets displayed as a trace.

Note
you should open up and close the Device Server Combo Box on the instant client, before you re-browse for your server. The reason is that the instant client will cache the property information for a server and not know about the array type changes you just made unless you force it to re-acquire this information.

Click on the "Amplitude" property. The display type automatically changes to "Histogram", i.e. CHANNEL array data generally refer to an array where each element refers to value of the property for a particular channel. And this is best displayed as a histogram.

If you make the instant client read the Amplitude, you will also see that the x-axis label also includes the device names and the element positions.

Note
When a property returns a spectrum array (also known as a waveform or trace), it usually has x-axis units as well as y-axis units. (Voltage versus time for instance). The Wizard currently doesn't have room for x-axis units, but you can add it by hand by editing the export.csv file yourself. You need to find the description of the property in question (for instance "Sine" in our case). And instead of "[-100:100 V]Sine Curve", you would expand it to read for instance "[-100:100 V][-100:900 usec]Sine Curve". A client program reading this information would then know how to position the min and max settings for the horizontal axis as well as what the x-axis units are. HOWEVER: only make these kinds of changes when you're finished using the server wizard, otherwise you'll have to copy-and-paste them back in.

Before leaving the server wizard, let's have a look at local history files (followd by alarm files). Use the wizard to call up your database again and select the Amplitude property. Now check the "Keep History" check box, followed by clicking the "Edit" button and then the "Done" Button. You can also edit the history panel if you wish. The default settings should be good enough for our demonstation purposes.

Local histories

You should have generated a "history.csv" file, which you can now copy to your FEC_HOME area as well. Now restart your server and have a look at the log file. It should now tell you that it is keeping a history of "Amplitude". If you re-browse your server in the Instant Client, you should see a "history" check box appear, which will let you trivially check the history of the selected device. A better way to see what is going on, is to add by hand ".HIST" to the property name in the combo box (make sure the history check box is NOT checked), and then hit the read button. Without any further input the local history server will ask for history data starting from "now" minus the depth in seconds given by the data size in the request. You can also have some fun by repeating the call with a format type of "FLTINT" which will return an array of data-timestamp pairs.

If you want to hava sneek preview of the local history viewer, you can call it up and under "Options" choose "Data Sources" and then choose the "Local History Chooser". You can then navigate via the Context combo box to the "WORKSHOP" context and find your server. It should display everything you are keeping a local history of. Choose one of your properties and devices and the click on "Add Selection".

Local Alarm Server

Now let's have a look at the local alarm system. A tine server can automatically set threshold alarms for you if you provide an alarm watch file. Let's see how this works. Start the wizard again, select "Amplitude" and check the "Alarm Watch" check box. You should change some of the settings in the alarm watch panel, namely the "Value too high" Threshold, you can set to 90, with a warning at 80 and the "Value too low" threshold to 10, with a warning at 20. Click the "Edit" button and then the "Done" button.

A tine server can also set 'invalid data' alarms for you if you like. In the alarm watch panel, instead of providing threshold settings, you could provide a 'normal' value (which a property should have) along with a 'mask'. This category of alarms generally applies to 'status' data (typically integer values) where a mask is applied to the data read and the result is compared against a 'normal' setting. If the data read doesn't match an 'invalid data' alarm is set. Other categories of alarms require the use of the tine local alarm server API.

You should now have generated an "almwatch.csv" file. Have a look at this file (if you like) and copy it into your FEC_HOME area and restart your server.

You can check the alarms on your server via the instant client, by including the "Stock Properties" in the property list. The relevant properties are "NALARMS" (number of alarms as a 5-parameter snapshot - when the first number > 0 then you have local alarms) and "ALARMS", which will return the current local alarm list (you might want to ask for fewer then the default 512 alarms).

Another simple way to view the alarms is to start the Remote Fec Control panel, find your server and click on the Alarms tab.

Commands (changing settings)

In the handler section for 'Amplitude' trap with an 'If' whether the access contains the 'CA_WRITE' bit and if so, look at the input data from the 'din' parameter and decide to accept or reject it. If accepted then assign it to the new amplitude and continue on.

TODO: finish this!


Impressum   |   Imprint   |   Datenschutzerklaerung   |   Data Privacy Policy   |   Declaration of Accessibility   |   Erklaerung zur Barrierefreiheit
Generated for TINE API by  doxygen 1.5.8