HomePort
Tutorial 01: Template

Table of Contents

Introduction

In this tutorial, we will briefly cover the required elements of the main program, an adapter, and an application. See the other examples for more in depth guidance on how to implement this required functions.

The full files can be found in the example/template folder, and can be compiled with make template.

Main Program

The includes part of the main program (template_main.c) will need to include hpd_daemon_api.h for all hpd daemon related functions, and include the header files of all the modules (adapters and applications) that it starts:

The main program should allocate memory for hpd, add each module (with a unique id), start hpd, and finally clean up to avoid memory leaks. You will most likely only have to change the add modules part of this template to provide a main program for your project.

int main(int argc, char *argv[])
{
hpd_t *hpd;
// Allocate hpd memory
if ((rc = hpd_alloc(&hpd))) goto error_return;
// Add modules
if ((rc = hpd_module(hpd, "template_adapter", &template_adapter_def))) goto error_free;
if ((rc = hpd_module(hpd, "template_application", &template_app_def))) goto error_free;
// Start hpd
if ((rc = hpd_start(hpd, argc, argv))) goto error_free;
// Clean up
if ((rc = hpd_free(hpd))) goto error_return;
return rc;
error_free:
hpd_free(hpd);
error_return:
return rc;
}

Demo Adapter

A module consists of two files; a header file and a source file. The header file of a module should only need to contain a single struct, which is the module definition of said module:

#ifndef HOMEPORT_TEMPLATE_ADAPTER_H
#define HOMEPORT_TEMPLATE_ADAPTER_H
#include <hpd/hpd_types.h>
#endif //HOMEPORT_TEMPLATE_ADAPTER_H

The source file should include hpd_adapter_api.h, which contains all the required functions to create an adapter.

To instantiate this struct, the source file needs to implement five functions:

static hpd_error_t template_adapter_on_create(void **data, const hpd_module_t *context);
static hpd_error_t template_adapter_on_start(void *data, hpd_t *hpd);
static hpd_error_t template_adapter_on_stop(void *data, hpd_t *hpd);
static hpd_error_t template_adapter_on_parse_opt(void *data, const char *name, const char *arg);

This can be expected to be called in the sequence:

sequence

The the struct defining our module become:

on_create() generally have two tasks. First, it should allocate the memory we need for our module, and store this within the given data pointer. Secondly, it should add the supported command-line arguments to hpd. See the other examples for more in-depth guidance on the contents of these functions.

static hpd_error_t template_adapter_on_create(void **data, const hpd_module_t *context)
{
return HPD_E_SUCCESS;
}

on_destroy() should clean up the memory allocated by on_create() (and in other places of our module), to avoid any memory leaks.

{
return HPD_E_SUCCESS;
}

on_start() is where you would most likely open a connection to an underlying network, and add the required objects (adapters, devices, services, and parameters) to hpd. Note as many of these probably depends on asynchronous responses from the network, it is perfectly fine to add/remove objects during the entire runtime (that is between calls to on_start() and on_stop()).

{
return HPD_E_SUCCESS;
}

on_stop() should stop everything that was started during runtime.

static hpd_error_t template_adapter_on_stop(void *data, hpd_t *hpd)
{
return HPD_E_SUCCESS;
}

Finally, on_parse_opt() will be called for each command-line argument given to your module. Note, this should return HPD_E_ARGUMENT if it does not understand the given argument:

static hpd_error_t template_adapter_on_parse_opt(void *data, const char *name, const char *arg)
{
}

Application Template

The application template is almost identical with just one exception; the source file includes hpd_application_api.h instead of hpd_adapter_api.h. First the header file (template_application.h):

#ifndef HOMEPORT_TEMPLATE_APPLICATION_H
#define HOMEPORT_TEMPLATE_APPLICATION_H
#include <hpd/hpd_types.h>
#endif //HOMEPORT_TEMPLATE_APPLICATION_H

Then the source file (template_application.c):

static hpd_error_t template_app_on_create(void **data, const hpd_module_t *context);
static hpd_error_t template_app_on_start(void *data, hpd_t *hpd);
static hpd_error_t template_app_on_stop(void *data, hpd_t *hpd);
static hpd_error_t template_app_on_parse_opt(void *data, const char *name, const char *arg);
};
static hpd_error_t template_app_on_create(void **data, const hpd_module_t *context)
{
return HPD_E_SUCCESS;
}
{
return HPD_E_SUCCESS;
}
static hpd_error_t template_app_on_start(void *data, hpd_t *hpd)
{
return HPD_E_SUCCESS;
}
static hpd_error_t template_app_on_stop(void *data, hpd_t *hpd)
{
return HPD_E_SUCCESS;
}
static hpd_error_t template_app_on_parse_opt(void *data, const char *name, const char *arg)
{
}