DALI User Manual: C Client
Diamond Systems provides a simple cross platform C client API which can be
used to communicate with the DALI server over the Internet. This software
hides details of SOAP and network communication and allows the user to write
software just as if they were using a driver to communicate with an I/O board
on the local system.
DALI Win32 developers can use a higher level API with Windows specific
features instead. See the Windows Client section of this manual for
more information
Example Program
Here is an example program for taking an AD sample from a remote system using
DALI.
#include <stdio.h>
#include "dalic.h"
int main(int argc, char *argv[])
{
DALIENV dali;
DALIADSETTINGS adsettings;
int channel = 0;
int value;
DALIInit(&dali);
dali.service = "http://myhost.example.com:8444/dali/soap/demo";
adsettings.range = 5;
adsettings.gain = 1;
adsettings.polarity = DALI_BIPOLAR;
if ( DALIADSample(&dali, channel, &adsettings, &value) )
printf("Error: %s\n", dali.last_error);
else
printf("Sample: %d\n", value);
DALIFree(&dali);
}
Compiling the Example Program
Copy the above program to a file dalidemo.c
. Edit the
dali.service
initialization to point to the IP address where the
DALI server is running. Edit the string demo
at the end of the
URL to the name of a board you have configured for your DALI server. See the
Board Configuration section of the manual for more information.
Instructions for Linux
gcc -o dalidemo dalidemo.c -I/usr/local/dali/include
-L/usr/local/dali/lib/linux/ -ldaliclient -pthread
- type
./dalidemo
to run.
Instructions for QNX
gcc -o dalidemo dalidemo.c -I/opt/dali/include
-L/opt/dali/lib/linux/ -ldaliclient -pthread
- type
./dalidemo
to run.
Instructions for Windows
- Open Microsoft Visual C++.
- Select File->New.. and create a new Windows Console Application [empty] named
dalidemo
.
- Add
dalidemo.c
to the 'Source Files' project listing.
- Press Alt+F7 for the Project Settings dialog and go to the C/C++ tab.
- Select
Code Generation
from the Category dropdown and select Debug Multithreaded DLL
from the run-time library dropdown.
- Go to the Link tab.
- Add
dalic.lib
and ws2_32.lib
to the 'Object/library modules:' edit field.
- Press the OK button.
- Press F7 to build the program. A warning will appear because you are building a debug version of
dalidemo
, but dalic.lib
uses the release version of msvcrt. This can be ignored.
- Press Ctrl+F5 to run the program in debug mode with pause enabled.
The dalidemo
program will connect to the DALI server and board
specified in the dali.service
string and request an AD sample.
OpenSSL Support
The C/C++ Client includes support for encrypted network communication
using OpenSSL. To use this you will have to have OpenSSL installed on
your client systems. This software is available from OpenSSL.org. If
you will be using OpenSSL in your DALI application you need to link with
the SSL enabled client library. This is called "dalic-ssl.a" on Linux
and QNX, and "dalic-ssl.lib" on Windows.
Once you've linked with the SSL enabled library you just have to
change your dali.service parameters to use the "https" protocol instead
of "http".
A Note on SOAP Service URLs
Several data structures are used to specify a service URL. This is a
SOAP endpoint which specifies a DALI server on the network and a service
on that server. It has the following format:
PROTOCOL://HOSTNAME:PORT/dali/soap/BOARDNAME
PROTOCOL is "http" for plain text or "https" for SSL encrypted
communications. SSL puts a much larger resource strain on the server so it
should only be used for requests which contain sensitive information.
HOSTNAME is the valid DNS hostname or IP address of the DALI server. Use
"127.0.0.1" to request a connection to the same machine the client software
is running on.
PORT is the TCP/IP port the DALI server is listening on. By default this
is 8444.
/dali/soap/ is text which should not be modified. It indicates to the
DALI server that this is a request for its services.
BOARDNAME is the unique name of a board on the DALI server. See the
Board Configuration section of this manual for more information.
DALI Client Data Structures
The DALI Client uses two data structures in the requests sent to the
DALI server, plus a number of other data structures for presenting the
data returned by the server.
DALIENV
A "handle" to an instance of the DALI client.
Multithreaded programs should either use separate DALIENV handles for each
thread or set the thread_safe
member of this struct to
1
for serialized DALI client access.
char *service
The service URL for the DALI server to connect to. See the note on
SOAP Service URLs above for more information.
char *userid
The DALI username to associate with this request, or NULL.
char *password
The DALI password to associate with this request, or NULL.
int thread_safe
Set to
1
if multiple threads will share the same DALIENV
handle and internal sychronization is required.
char last_error[128]
Last NULL terminated error string generated by client.
void *mutex
Internal use only. Do not modify. Platform specific mutex handle.
void *soap
Internal use only. Do not modify. Pointer to gSOAP
struct soap
.
void *alarm_soap
Internal use only. Do not modify. Pointer to gSOAP
struct soap
.
DALIADSETTINGS
Configures AD settings for the AD operations associated with this request.
The DALI server is able to switch the DAQ board between AD modes for
each request.
int range
Set to
5
or
10
. Represents 5 volt and 10 volt
modes.
int gain
Set to
1
,
2
,
4
, or
8
.
DAQ multiplies analog input voltage by this factor.
int polarity
Set to
0
(
DALI_BIPOLAR
) or
1
(
DALI_UNIPOLAR
). Sets analog input voltage polarity.
DALIBOARD
Represents a board which is being serviced by the DALI server. Returned
by the DALIGetBoardInfo()
function which is documented later
in this section.
char board[128]
The board name as specified by the board configuration file. Passed
at the end of the
dali.service
string to select this board.
See the above note on SOAP Service URLs for information on BOARDNAME.
enum daliboardtype boardtype
The product identifier of the DAQ board. One of:
DALI_BOARD_UNKNOWN, DALI_DMM, DALI_DMM32, DALI_DMMAT, DALI_DMM16AT,
DALI_PROM, DALI_TEST
int base_address
The base I/O address of the board.
DALICHANNEL
Represents a channel which is being serviced by the DALI server. Returned
by the DALIGetChannelInfo()
function which is documented later
in this section.
int channel
The AD, DA, or DIO channel. In the case of DIO this is sometimes called a
port, with DIO port A translating to DALI channel 0.
enum dalichtype type
The type of the channel. One of:
DALI_CH_UNKNOWN, DALI_CH_AD,
DALI_CH_DA, DALI_CH_DIOIN, DALI_CH_DIOOUT
enum dalisecurity security
The security level for the channel. One of:
DALI_CH_DISABLED,
DALI_PUBLIC, DALI_MUST_LOGIN
DALIALARMSETTINGS
Configures a DALI alarm. See the section on Alarm functions later in this
manual for more information.
char *actiontype
What the server should do when the alarm is triggered. One of:
DALI_ACTION_SOAP DALI_ACTION_EMAIL DALI_ACTION_LOG
char *actiontarget
If the actiontype is EMAIL the actiontarget holds the e-mail address to be
notified. If the actiontype is SOAP the SOAP Service URL to contact. Should
be NULL for actiontype LOG.
char *message
A text message explaining the alarm condition which will be delivered with the
alarm to the recipient. Can be NULL.
int period
How often in seconds the server should check the alarm condition
int duration
How long the server should monitor the alarm condition before discontinuing the
alarm. Set to 0 for permanent alarms.
int postalarmpause
Period in seconds to delay watching the the alarm after a previous alarm is
activated. Avoids too many alarms being generated in a short period.
DALIALARMNOTICE
Information about an alarm which is delivered to a SOAP service recipient
when actiontype is set to SOAP. See the section on Alarm functions later in
this manual for more information.
char *id
The alarm id string which uniquely identifies this alarm.
char *service
The SOAP Service URL of the DALI server which generated this alarm. Useful for
connecting back to the DALI server to unregister the alarm if it is no longer
needed.
char *message
A text message explaining the alarm condition which was set by the client
which registered the alarm.
int value
The value read from the board which triggered the alarm.
int status
A status code associated with the alarm. If non-zero an error has occured and
the alarm has been canceled by the server. Disregard the value parameter in
this struct if the status indicates an error.
long timestamp
A Unix epoch timestamp taken by the server when the alarm was generated. This
is the number of seconds which have passed since midnight January 1st, 1970.
It may be in the timezone of the server and is subject to inaccuracies of the
system clock and time on the server.
Initialization and Deinitialization Functions
int DALIInit(DALIENV *dali)
Initializes the DALI client.
Returns Non-zero on error.
DALIENV *dali
Pointer to a DALIENV struct. Clears any values set in this struct.
void DALIFree(DALIENV *dali)
Releases any resources claimed by the DALI server.
Returns: This function has no return value.
DALIENV *dali
Pointer to a DALIENV struct.
A/D Functions
int DALIADSample(DALIENV *dali, int channel, DALIADSETTINGS *adsettings,
int *value)
Takes a single AD sample with the given AD settings and
returns the result.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel to do the AD sample on.
DALIADSETTINGS *adsettings
The AD settings to use with this AD conversion.
int *value
Pointer to an integer which will hold the new AD value if the call succeeds.
int DALIADScan(DALIENV *dali, int low_channel, int high_channel, DALIADSETTINGS *adsettings,
int *values)
Takes a single AD scan with the given AD settings and returns
the result.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int low_channel
The low channel of the AD scan.
int high_channel
The high channel of the AD scan.
DALIADSETTINGS *adsettings
The AD settings to use with this AD conversion.
int *values
Pointer to an array of integers large enough to hold all the sample values if
the call succeeds. Should be size (
high_channel - low_channel +
1
).
int DALIADSampleMulti(DALIENV *dali, int channel, int count, float hz, DALIADSETTINGS *adsettings,
int *values)
Takes multiple AD samples at the given rate on the DALI server and returns
all the sample values together when count
samples have been
generated. The DALI server will attempt to generate the samples at the
frequency specified by hz
but will be limited by available
processor time and requests from other DALI clients.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel of the AD sample.
int count
The number of samples to take before returning.
float hz
The frequency in seconds at which samples should be taken.
DALIADSETTINGS *adsettings
The AD settings to use with this AD conversion.
int *values
Pointer to an array of integers large enough to hold all the sample values if
the call succeeds. Should be size (
count
).
int DALIADScanMulti(DALIENV *dali, int low_channel, int high_channel, int count, float hz, DALIADSETTINGS *adsettings,
int *values)
Takes multiple AD scans at the given rate on the DALI server and returns
all the sample values together when count
samples have been
generated. The DALI server will attempt to generate the scans at the
frequency specified by hz
but will be limited by available
processor time and requests from other DALI clients.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int low_channel
The low channel of the AD scan.
int high_channel
The high channel of the AD scan.
int count
The number of samples to take before returning. Must be a multiple of
(
high_channel - low_channel + 1
)
float hz
The frequency in seconds at which samples should be taken.
DALIADSETTINGS *adsettings
The AD settings to use with this AD conversion.
int *values
Pointer to an array of integers large enough to hold all the sample
values if the call succeeds. Should be size (
count
).
D/A Functions
int DALIDAConvert(DALIENV *dali, int channel, int value)
Does a DA conversion of the value on the channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel of the DA conversion.
int value
The value to convert. Must be in the range
0 - 4095
.
int DALIDAConvertScan(DALIENV *dali, int low_channel, int high_value, int value)
Does simultaneous DA conversions on several channels.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int low_channel
The low channel of the DA conversion.
int high_channel
The high channel of the DA conversion.
int *values
An array of values to convert. The array must be size
(
high_channel - low_channel + 1
). Values must be in the range
0 - 4095
.
int DALIDAReadback(DALIENV *dali, int channel, int *value)
Reads back the last DA value converted on a specified channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel to read back.
int *values
Pointer to an integer which will hold the last DA value converted.
int DALIDAReadbackScan(DALIENV *dali, int low_channel, int high_channel, int *values)
Reads back the last DA value converted on several channels.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int low_channel
The low_channel to read back.
int high_channel
The high_channel to read back.
int *values
Pointer to an integer which will hold an array of the last values
converted on these channels. Must be size (
high_channel - low_channel + 1
).
Digital I/O Functions
int DALIDIOOutputByte(DALIENV *dali, int channel, int value)
Output a digital byte on that channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel to write to. A digital channel is a port of 8 bits.
int value
The digital value to write. In the range of
0 - 255
.
int DALIDIOOutputBit(DALIENV *dali, int channel, int bit, int value)
Output a digital bit on that channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel to write to. A digital channel is a port of 8 bits.
int bit
The bit to write to. A bit in the range
0 - 7
.
int value
The digital value to write. In the range of
0 - 1
.
int DALIDIOInputByte(DALIENV *dali, int channel, int *value)
Read a digital byte from that channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel to read from. A digital channel is a port of 8 bits.
int *value
Pointer to an integer which will hold the digital value.
int DALIDIOInputBit(DALIENV *dali, int channel, int bit, int *value)
Read the value of a specific bit on a digital channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel to read from. A digital channel is a port of 8 bits.
int bit
The bit to read. A bit in the range
0 - 7
.
int *value
The digital value of the bit.
int DALIDIOReadbackByte(DALIENV *dali, int channel, int *value)
Read back the last digital value output on that channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel to read back. A digital channel is a port of 8 bits.
int *value
Pointer to an integer which will hold the digital value read back.
int DALIDIOReadbackBit(DALIENV *dali, int channel, int bit, int *value)
Read back the last value set on a bit on a digital channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel to read back. A digital channel is a port of 8 bits.
int bit
The bit to read back. A bit in the range
0 - 7
.
int *value
The last set digital value of the bit.
Configuration Query Functions
int DALIGetBoardInfo(DALIENV *dali, DALIBOARD **boards, int *board_count)
Get a list of the DAQ boards being serviced by DALI.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
DALIBOARD **boards
Pointer to a pointer to a DALIBOARD struct. When function returns this
will point to a list of DALIBOARD structs. See the data structures section
earlier in this manual for more information on DALIBOARD. This memory must
be freed by the user with the
free()
call or it will become a
memory leak.
int *board_count
Pointer to an integer which will be set to the number of boards returned
in the above DALIBOARD array.
int DALIGetChannelInfo(DALIENV *dali, DALIBOARD **boards, int *board_count)
Get a list of the I/O channels of all types supported by a DAQ board being serviced by DALI.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
DALICHANNEL **channels
Pointer to a pointer to a DALICHANNEL struct. When function returns this
will point to a list of DALICHANNEL structs. See the data structures section
earlier in this manual for more information on DALICHANNEL. This memory must
be freed by the user with the
free()
call or it will become a
memory leak.
int *channel_count
Pointer to an integer which will be set to the number of channels
returned in the above DALICHANNEL array.
Misc Utility Functions
int DALIPing(DALIENV *dali)
A simple function for checking to make sure the DALI server is alive and responding to requests.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
Alarm Functions
DALI alarms let the client specify a condition and request asynchronous
notification when this condition becomes true. For example, the client can
request that the server contact it when an analog value exceeds a specified
range.
This is implemented with a kind of SOAP callback, in which the server
temporarily becomes a SOAP client and connects back to the DALI application
which is waiting to receive this connection. This is only possible if
direct TCP/IP connections from the server to the client are possible. For
example, network firewalls or NAT security will prevent this feature from
working.
The DALIALARM struct specifies the parameters of the alarm. This struct
is documented earlier in data structures section of this manual. The
notify_url
specifies a SOAP service URL which the DALI server
will contact when the alarm becomes true. In the case of DALI this URL should
always be in the form of http://yourhost:8444/dali/soap/
.
More information on the internals of DALI alarm is available in the
server section of this manual.
int DALIAlarmADOutOfRange(DALIENV *dali, int channel, int low_value,
int_high_value, DALIADSETTINGS *adsettings, DALIALARMSETTINGS *alarm, char
*alarm_id, int alarmid_bufsize)
Register an alarm which will notify the client when an AD value on a channel falls out of a specified tolerance.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The AD channel to monitor.
int low_value
The low end of the acceptable range of values for this AD channel.
int high_value
The high end of the acceptable range of values for this AD channel.
DALIADSETTINGS *adsettings
AD settings used for generating the AD values.
DALIALARMSETTINGS *alarm
Pointer to the alarm configuration struct.
char *alarm_id
Pointer to an buffer which will be set to the unique alarm ID for this
alarm. Client must save this ID for later to recognize the alarm notification.
int alarmid_bufsize
Size of the alarm ID buffer
int DALIAlarmDAOnChange(DALIENV *dali, int channel, DALIALARMSETTINGS
*alarm, char *alarm_id, int alarmid_bufsize)
Register an alarm which will notify the client when a new DA value is converted on a DA channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The DA channel to monitor.
DALIALARMSETTINGS *alarm
Pointer to the alarm configuration sturct.
char *alarm_id
Pointer to a buffer which will be set to the unique alarm ID for this
alarm. Client must save this ID for later to recognize the alarm notification.
int alarmid_bufsize
Size of the alarm ID buffer
int DALIAlarmDIOInOnChange(DALIENV *dali, int channel, DALIALARMSETTINGS
*alarm, char *alarm_id, int alarmid_bufsize)
Register an alarm which will notify the client when a new digital I/O input
value is converted on a DIO channel.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel (digital port) monitor.
DALIALARMSETTINGS *alarm
Pointer to the alarm configuration struct.
char *alarm_id
Pointer to a buffer which will be set to the unique alarm ID for this
alarm. Client must save this ID for later to recognize the alarm
notification.
int alarmid_bufsize
Size fo the alarm ID buffer
int DALIAlarmDIOOutOnChange(DALIENV *dali, int channel, DALIALARMSETTINGS
*alarm, char *alarm_id, int alarmid_bufsize)
Register an alarm which will notify the client when the value of a digital
I/O output changes.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int channel
The channel (digital port) monitor.
DALIALARMSETTINGS *alarm
Pointer to the alarm configuration sturct.
char *alarm_id
Pointer to a buffer which will be set to the unique alarm ID for this
alarm. Client must save this ID for later to recognize the alarm
notification.
int alarmid_bufsize
Size fo the alarm ID buffer
int DALIAInitAlarmListener(DALIENV *dali, int port)
Must be called before DALIWaitForAlarm() to prepare networking on the
client to receive connections with alarm notices.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int port
The TCP/IP port to listen on. Must match the port used in the SOAP alarm
service URL provided to the server.
int DALIWaitForAlarm(DALIENV *dali, DALIALARMNOTICE *alarm_notice)
Function will block waiting for an alarm from the DALI server. The user
must call this function to wait after registering one or more alarms.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
DALIALARMNOTICE *alarm_notice
Pointer to a struct which contains information about the alarm
int DALIAFreeAlarmListener(DALIENV *dali, int port)
Call when no more alarm functions will be used by the program. Frees
network resources.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
int DALIUnregisterAlarm(DALIENV *dali, char *alarm_id)
Function will unregister an alarm with the DALI server. The server will
no longer monitor the condition associated with that alarm ID.
Returns: Non-zero on error
DALIENV *dali
Pointer to a DALIENV struct.
char *alarm_id
The alarm ID to be unregistered
int DALIAlarmIsAlive(DALIENV *dali, char *alarm_id)
Function will return an error if the specified alarm id does not match
a known alarm on the server. Useful for checking to see if an alarm
is still running.
DALIENV *dali
Pointer to a DALIENV struct.
char *alarm_id
The alarm ID to be checked