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

Instructions for QNX

Instructions for Windows

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