Device Discovery Functions

Device discovery is a very protocol specific process, and the IDL Driver Instance (IDI) needs to break the complex process of device discovery into one or more functional steps that the IDL must do to complete one discovery session. This callback function steps along with the type (startstop, or step function) and are reported by the IDI at startup to the IDL via repeated calls to IdlDevDiscoveryCallbackSet().

The IDL knows the total number of callback step functions by counting the number of IdlDevDiscoveryCallbackSet calls with type DISCOVERY_STEP_CALLBACK between DISCOVERY_START_CALLBACK and DISCOVERY_STOP_CALLBACK.

Three timeout values can be defined in the .conf file: 

  • Discovery start callback timeout ms
  • Discovery step callback timeout ms
  • Discovery stop callback timeout ms

If they are not specified in the conf file, the IDL uses default values of 15sec, 30sec, 15sec respectively. The IDL will add these timeout values in discoveryData, which is sent to the IDI discovery callback functions as driverInstanceContext. IDIs such as the BACnet driver use these values when determining what timeout value to be sent to the IDL on every callback call. Other drivers can ignore these values. The IDL also sends a singly linked list of the interface files available in the /var/apollo/data folder for the particular protocol’s /res directory. The IDI is supposed to send the XIN of the device type of the discovered device when calling the IdlDeviceDiscovered() API.

When the IDL gets a discovery start message from the CMS, it stops periodic polling of the existing devices, creates a separate thread dedicated for device discovery, and then calls the first callback step that is registered as DISCOVERY_START_CALLBACK. Next it goes through all the list of discovery steps i.e. DISCOVERY_STEP_CALLBACK, and finally calls the callback that is registered as DISCOVERY_STOP_CALLBACK. On completion, it sends a response to the CMS regarding discovery complete, and the number of unprovisioned devices that were successfully discovered.

For each discovery step, the IDI must uses the done & mSecDelaymsTimeout output parameters in the DeviceDiscoveryCallbackFPtr to signal to the IDL whether the current step is completed (done = 1) or not, and the time interval that the IDL must wait before calling the next step. If after waiting for mSecDelaymsTimeout time, the done flag is still 0, then the IDL will again call the same discovery step. This will continue until the IDI sets the done flag to 1. Then the IDL will call the next discovery step in line.

While the IDI is performing its discovery steps, for each discovered device, the IDI must call the IdlDeviceDiscovered() API passing the XIN of the device interface and the device’s unid. It can know about the XIN from the singly linked list of interface file details that the IDL had passed when starting the discovery process. This API can be called by IDI any time between the DISCOVERY_START_CALLBACK callback and DISCOVERY_STOP_CALLBACK callback calls. When this API is called, the IDL verifies the uniqueness of the unid, increments its internal count of the discovered devices and then publishes a discovery event to the CMS with the device type and the unid. The CMS then sends a device create request back to the IDL with a unique device handle allocated to the discovered device. After completion of the last step, the IDL published a discovery completion message to the housekeeper with the final count of the discovered devices and then deleted the discovery thread. Monitoring is resumed after this.

Device Discovery Callback Function

IdlDevDiscoveryCallbackSet()  

IdlDevDiscoveryCallbackSet(idl, driverInstanceContext, DISCOVERY_START_CALLBACK, DiscoveryStart);

IdlDevDiscoveryCallbackSet(idl, driverInstanceContext, DISCOVERY_STEP_CALLBACK, DiscoveryStep1);

IdlDevDiscoveryCallbackSet(idl, driverInstanceContext, DISCOVERY_STEP_CALLBACK, DiscoveryStep2);

   … StepN-1

IdlDevDiscoveryCallbackSet(idl, driverInstanceContext, DISCOVERY_STEP_CALLBACK, DiscoveryStepN);

IdlDevDiscoveryCallbackSet(idl, driverInstanceContext, DISCOVERY_STOP_CALLBACK, DiscoveryStop);

Device Discovery Related Functions and Data Structures 

typedef struct _IdlXifInfo {
        char *xin;
        char *pid;
        ModbusMarkerInfo *firstMarker;            //singly linked list of ModbusMarkerInfo
        struct _IdlXifInfo *next;
} IdlXifInfo;

typedef struct _IdlDiscoveryData {
        IdlDiscoveryTimeouts timeouts;
        IdlXifInfo *firstXif; //singly linked list of IdlXifInfo
} IdlDiscoveryData;

typedef int (*DeviceDiscoveryCallbackFPtr) (void
        *driverInstanceContext, IdlDiscoveryData *data, int *done, unsigned int *msTimeout);

typedef struct _IdlDiscoveryCallback {
        void *context;
        DeviceDiscoveryCallbackFPtr cb;
        struct _IdlDiscoveryCallback *next;
} IdlDiscoveryCallback;

int IdlDevDiscoveryCallbackSet(Idl *idl, void *driverInstanceContext,
        DiscoveryCallbackType dcbFunctionType,
        DeviceDiscoveryCallbackFPtr dcbFunction);

int IdlDeviceDiscovered(char *unid, char *xin, char *frName);