The Attribute daemon is the central nervous system for the device. It communicates changes in device attributes between multiple client daemons on the device though a customized IPC layer. Clients use an event-based API to:
This page contains the following sections:
Afero device attributes have the following properties:
You can create your own attributes; instructions for doing this are in Defining Your Own Attributes. We use a Potenco as an example.
Several Afero attributes that are used to control and debug the device are available. To be visible, they must be defined in the device Profile. However, some are private between hubby and the daemons so developers do not have access to them.
The following is a list of Afero attributes that are used or owned by device daemons. Note that the flags in the table are Attribute daemon flags.
ID | Name | Type | Owner | attrd Flags | Description |
---|---|---|---|---|---|
51600 | REPORT_RSSI_CHANGES | INT8 | ATTRD | WRITE NOTIFY |
Tells the Wi-Fi Station daemon and the WAN daemon to report signal strength changes periodically. |
51611 | HUBBY_STATE | INT8 | HUBBY | NOTIFY | State of hubby: 0 - Unknown 1 - Connected to the Afero Cloud 2 - Unable to connect to the Afero Cloud |
51612 | OTA_UPGRADE_PATH | UTF8S[128] | HUBBY | NOTIFY | The attribute ID for transferring the OTA update image path to the OTA Manager. The value is a null-terminated string containing the path of the OTA images. The header is stored in the file with a name using a “.hdr” extension. The OTA update binary is stored in the file with a name using a “.img” extension. |
51613 | DEBUG_LEVEL | INT8 | ATTRD | WRITE | The debug level (0-3) of the Attribute daemon.
Debug levels are: 0 - All debug messages off 1 - LOG_DEBUG1; shows all attribute traffic for attrd 2 - LOG_DEBUG2; shows all IPC traffic 3 - LOG_DEBUG3; verbose |
51614 | DEBUG_LEVEL | INT8 | WIFISTAD | WRITE | The debug level (0-3) of the Wi-Fi Station daemon. See 51613 above for level definitions. |
51615 | DEBUG_LEVEL | INT8 | WAND | WRITE | The debug level (0-3) of the WAN daemon. See 51613 above for level definitions. |
51616 | DEBUG_LEVEL | INT8 | CONNMGR | WRITE | The debug level (0-3) of the Connection Manager daemon. See 51613 above for level definitions. |
51617 | DEBUG_LEVEL | INT8 | EDGED | WRITE | The debug level (0-3) of the Edge Device daemon. See 51613 above for level definitions. |
51618 | OTA_UPGRADE_PATH_PREFIX | OTAMGR | The path prefix for the OTA update files (see 51612 OTA_UPGRADE_PATH). If this is not specified, hubby defaults to a prefix of “/tmp/”. | ||
51619 | PROFILE UPDATED | INT8 | OTAMGR | WRITE | The attribute in which hubby will inform the rest of the world that a new profile has just been downloaded successfully and is ready to use. |
65001 | UTC_OFFSET_DATA | BYTES[8] | HUBBY | WRITE NOTIFY |
Contains the current UTC offset in minutes, the next timestamp to change the UTC offset, and the new UTC offset to apply at the previous timestamp, in that order (2-bytes signed short, 4-bytes int, 2-bytes signed short). |
65004 | CONFIGURED_SSID | UTF8S[33] | WIFISTAD | NOTIFY | The SSID the device is currently configured to use. |
65005 | WIFI_RSSI | INT8 | WIFISTAD | NOTIFY | The Wi-Fi Receive Signal Strength Indicator. |
65006 | WIFI_STEADY_STATE | INT8 | WIFISTAD | NOTIFY | Used to communicate the Wi-Fi state to the apps outside the Wi-Fi setup. Wi-Fi steady state possibilities: 0 = Not Connected 1 = Pending 2 = Connected 3 = Unknown Failure, 4 = Association Failed 5 = Handshake Failed 6 = Echo Failed 7 = SSID Not Found |
65007 | WIFI_SETUP_STATE | INT8 | WIFISTAD | NOTIFY | Wi-Fi setup state: 0 = Not Connected 1 = Pending 2 = Connected 3 = Unknown Failure 4 = Association Failed 5 = Handshake Failed 6 = Echo Failed 7 = SSID Not Found Used during the W-Fi setup process to let the apps know what state the W-Fi connection is in. |
65008 | NETWORK_TYPE | INT8 | CONNMGR | NOTIFY | -1 - NONE 0 - Ethernet 1 - WLAN 2 - WAN |
65019 | REBOOT_REASON | UTF8S[100] | ATTRD | NOTIFY | Reason the device rebooted the last time. |
65022 | NET_CAPABILITIES | INT8 | CONNMGR | NOTIFY | Bitfield indicating which network interfaces this hardware contains: bit 0 - Wi-Fi 1 bit 1 - WAN 1 bit 2 - Ethernet 1 |
65024 | WIFI_ITF_STATE | INT8 | CONNMGR | Network interface state: 0 - Not Available/Broken 1 - Disabled 2 - Pending 3 - Up |
|
65025 | WIFI_IPADDR | BYTES[4] | CONNMGR | Local IPv4 address of the network interface in network byte order (Big Endian). | |
65026 | WIFI_UPTIME | INT32 | CONNMGR | Uptime in seconds. | |
65027 | WIFI_DL_DATA_USAGE | INT32 | CONNMGR | Downlink data usage in bytes. | |
65028 | WIFI_UL_DATA_USAGE | INT32 | CONNMGR | Uplink data usage in bytes. | |
65029 | WIFI_MAC_ADDR | UINT8[6] | CONNMGR | MAC address of Wi-Fi interface. | |
65030 | WIFI_KEY_MGMT | INT8 | WIFISTAD | Key management for the interface. Supported at this time: 0 - None 1 - WPA PSK 2 - WPA-EAP 3 - IEEE 802.1X |
|
65031 | WIFI_GROUP_CIPHER | INT8 | WIFISTAD | Group (multicast and broadcast) cipher. Supported at this time: 0 - None 1 - WEP 40 bit 2 - WEP 104 bit 3 - TKIP 4 - AES CCMP |
|
65032 | WIFI_PAIRWISE_CIPHER | INT8 | WIFISTAD | Pairwise (unicast) cipher. Supported at this time: 0 - None 1 - WEP 40 bit 2 - WEP 104 bit 3 - TKIP 4 - AES CCMP |
|
65034 | WAN_RSRP | INT16 | WAND | NOTIFY | Reference Signal Receive Power. This attribute should be reported when Report RSSI Changes attribute (51600) is nonzero. |
65035 | WAN_BARS | INT8 | WAND | NOTIFY | Signal strength in bars. This attribute should be reported when Report RSSI Changes attribute (51600) is nonzero. |
65037 | WAN_ITF_STATE | INT8 | WAND | Network interface state: 0 - Not Available/Broken 1 - Disabled 2 - Pending 3 - Up |
|
65038 | WAN_IPADDR | BYTES[4] | CONNMGR | Local IPv4 address of the network interface in network byte order (Big Endian). | |
65039 | WAN_UPTIME | INT32 | CONNMGR | Uptime in seconds. | |
65040 | WAN_DL_DATA_USAGE | INT32 | CONNMGR | Downlink data usage in kilobytes. | |
65041 | WAN_UL_DATA_USAGE | INT32 | CONNMGR | Uplink data usage in kilobytes. | |
65042 | WAN_IMEISV | UTF8S[32] | WAND | Modem International Mobile Equipment Identifier with Software Version. | |
65043 | WAN_IMSI | UTF8S[32] | WAND | SIM International Mobile Subscriber Identity. | |
65044 | WAN_ICCID | UTF8S[32] | WAND | SIM Integrated Circuit Card Identity. | |
65045 | WAN_RAT | INT8 | WAND | Current Radio Access Technology: 0 - Unknown 1 - GSM 2 - EGPRS (EDGE) 3 - CDMA 1x 4 - UMTS (WCDMA) 5 - EvDO 6 - LTE |
|
65046 | WAN_REG_STATE | INT8 | WAND | Registration state. Tentatively: 0 - Not registered 1 - Registered with a network 2 - Searching 3 - Registration denied by the visible network 4 - Registration state is unknown |
|
65047 | WAN_PS_STATE | INT8 | WAND | Packet-switched domain attach state of the mobile: 0 - Detached 1 - Attached 2 - Unknown |
|
65048 | WAN_MCC | UTF8S[8] | WAND | Mobile Country Code (MCC) of operator. | |
65049 | WAN_MNC | UTF8S[8] | WAND | Mobile Network Code (MNC) of operator. | |
65050 | WAN_LAC | INT32 | WAND | Location Area Code (LAC) or cell ID (28 bits). | |
65051 | WAN_CELL_ID | INT16 | WAND | LTE physical cell ID (0 to 503). | |
65052 | WAN_ROAMING_STATE | INT8 | WAND | Roaming status: 0 - Home 1 - Roaming 2 - Unknown |
|
65053 | WAN_PLMN | UTF8S[32] | WAND | Short name of Public Land Mobile Network (PLMN) on which the modem is camped. | |
65054 | WAN_APN | UTF8S[100] | WAND | Access Point Name (APN) providing IP connectivity. | |
65055 | WAN_SIM_STATUS | INT8 | WAND | Indicates the state of the card. Valid values: 0 - Absent 1 - Present 2 - Error 3 - Unknown |
|
65056 | WAN_DL_BIT_RATE | INT32 | WAND | Downlink bit rate in bits per second. | |
65057 | WAN_UL_BIT_RATE | INT32 | WAND | Uplink bit rate in bits per second. | |
65059 | ETH_ITF_STATE | INT8 | CONNMGR | Network interface state: 0 - Not Available/Broken 1 - Disabled 2 - Pending 3 - Up |
|
65060 | ETH_IPADDDR | BYTES[4] | CONNMGR | Local IPv4 address of the network interface. | |
65061 | ETH_UPTIME | INT32 | CONNMGR | Uptime in seconds. | |
65062 | ETH_DL_DATA_USAGE | INT32 | CONNMGR | Downlink data usage in kilobytes. | |
65063 | ETH_UL_DATA_USAGE | INT32 | CONNMGR | Uplink data usage in kilobytes. | |
65064 | ETH_MAC_ADDRESS | BYTES[6] | CONNMGR | MAC address of Wi-Fi interface. | |
65065 | SYSTEM_TIME | INT32 | CONNMGR | UTC system time in seconds since on the Unix Epoch (Jan 1, 1970). |
If the Notify flag is set for an attribute, then the Attribute daemon (attrd) will tell the other daemons when a value changes (hubby being one of them). If the attribute is in the Profile then hubby will send the value to the Afero Cloud; otherwise, it’s dropped. So for hubby to communicate the values to the Afero Cloud, both the Notify flag has to be set and the attribute must be in the Profile.
Afero attributes that are integers are always communicated in Little Endian byte order. Therefore daemons that provide values for Afero attributes must convert the values to Little Endian byte format. The Attribute Client library provides functions to perform these conversions. See the Handling Endian Issues section below.
An “attribute client” is a daemon that talks to the Attribute daemon through the Attribute Client API. The Wi-Fi Station daemon, the WAN daemon, the Connection Manager, and hubby are all attribute clients. Probably the best way to understand the Attribute Client API is to look at any of the daemons in the af conn repository.
The Attribute Client API is based on libevent, and the callbacks are called in the context of the event loop.
Here’s an example of a skeleton you can use if the client does not own any attributes and doesn’t want to receive notifications. Indeed this client does nothing except open the attribute library and wait. It will be the basis for the more complex examples below:
#include <stdint.h> #include <stdlib.h> #include <event.h> #include <event2/thread.h> #include <unistd.h> #include "af_attr_client.h" #include "af_log.h" static struct event_base *sEventBase = NULL; uint32_t g_debugLevel = 3; static void on_open(int status, void *context) { if (status != AF_ATTR_STATUS_OK) { /* do something to notify the user of an error */ return; } } static void on_close(int status, void *context) { if (status != AF_ATTR_STATUS_OK) { /* do something to notify the user of an error */ } } int main(int argc, char *argv[]) { openlog("myclient", LOG_PID, LOG_USER); sEventBase = event_base_new(); if (sEventBase == NULL) { /* Notify user */ return AF_ATTR_STATUS_NO_SPACE; /* you can use your own error codes */ } int status = af_attr_open( sEventBase, /* event base */ "IPC.MYCLIENT", /* owner name */ 0, NULL, /* numRanges, ranges */ NULL, /* notifyCB */ NULL, /* ownerSetCB */ NULL, /* ownerGetCB */ on_close, /* closeCB */ on_open, /* openCB */ NULL); /* context */ if (status != AF_ATTR_STATUS_OK) { /* Notify user */ event_base_free(sEventBase); return status; } event_base_dispatch(sEventBase); af_attr_close(); event_base_free(sEventBase); closelog(); return 0; }
This code defines callbacks for handling open failures and unexpected closes. Then it opens the library. If opening the library is successful, the code starts the event loop. The event loop exits when there are no pending events. In this case, the loop waits forever for attribute events to occur, but because the app owns no attributes, has not registered for notifications, and has not performed a get
or a set
, no events occur and the loop just hangs.
Note that the main
function also opens the system log. This makes sure that the error and debug messages logged by the client library can be attributed to your application.
Under development. Will describe what is needed to build and run this code.
We can modify the code to perform a set
operation after the library is opened; for example, if this is a command-line utility.
First we write a callback function that tells us whether the set
operation was successful. Note some ways it could fail:
set
operation.static void on_set_finished(int status, uint32_t attributeId, void *context) { if (status != AF_ATTR_STATUS_OK) { /* notify user of error condition */ } /* you wouldn't do the following if you're writing a daemon */ event_base_loopbreak(&sEventBase); }
When the set
operation finishes, the on_set_finished
function is called with the status of the operation.
Now we need to initiate the set
operation at a reasonable time. For our example, we use the on_open
function. Replace the skeleton’s on_open function
with this:
static void on_open(int status, void *context) { if (status != AF_ATTR_STATUS_OK) { /* do something to notify the user of an error */ return; } int8_t level = 2; status = af_attr_set(AF_ATTR_ATTRD_DEBUG_LEVEL, &level, sizeof(level), on_set_finished, NULL); if (status != AF_ATTR_STATUS_OK) { event_base_loopbreak(&sEventBase); } }
The af_attr_set call
sets the Attribute daemon debug level.
If you’re writing a daemon, you’d probably call the af_attr_set
function based on a different event than opening the Attribute Client library. Also you would not exit the event loop when the set
fails and when it finishes.
If the daemon owns the attribute, the set
code would be exactly the same; however, in this case you would be writing a daemon and the caveats in the last paragraph would definitely apply.
Let’s modify the original skeleton to perform a get
operation. First we need a callback that tells us the value of the attribute:
static void on_get_response(uint8_t status, uint32_t attributeId, uint8_t *value, int length, void *context) { if (status != AF_ATTR_STATUS_OK) { /* notify the user of the get failure) } else { /* the value parameter points to the value of the attribute. The length parameter contains the length of the value */ printf ("the value of attribute %d is %d\n", attributeId, *(int8_t *)value); } event_base_loopbreak(sEventBase); }
When the get
operation finishes, the on_get_response
function is called with the status of the get
operation and the value of the attribute if the operation were successful.
Again, we’ll use the on_open
function to initiate the get
operation:
static void on_open(int status, void *context) { if (status != AF_ATTR_STATUS_OK) { /* do something to notify the user of an error */ return; } int8_t level = 2; status = af_attr_get(AF_ATTR_ATTRD_DEBUG_LEVEL, on_get_response, NULL); if (status != AF_ATTR_STATUS_OK) { event_base_loopbreak(&sEventBase); } }
The af_attr_get
call initiates a get
operation on the Attribute daemon’s debug level.
As with Setting attributes, if you’re writing a daemon, you would probably call the af_attr_get
function based on a different event than opening the Attribute Client library. Also, you would not exit the event loop when the get
fails and when it finishes.
Let's modify the original skeleton to receive notifications. First we need a function to handle the notification:
static void on_notify(uint32_t attributeId, uint8_t *value, int length, void *context) { /* attribute with specified ID has been set to the specified value, and it has the specified length */ printf ("the value of attribute %d is %d\n", attributeId, *(int8_t *)value); }
In the main loop, we add a range of attributes to listen for, and we add the range, number of ranges, and the callback to the open
function. In our case we’ll listen to the attribute that tells the WAN and Wi-Fi Station daemons to periodically report their RSSI values. The complete main
function is below:
int main(int argc, char *argv[]) { openlog("myclient", LOG_PID, LOG_USER); sEventBase = event_base_new(); if (sEventBase == NULL) { /* Notify user */ return AF_ATTR_STATUS_NO_SPACE; /* you can use your own error codes */ } af_attr_range_t r[] = { { AF_ATTR_ATTRD_REPORT_RSSI_CHANGES, AF_ATTR_ATTRD_REPORT_RSSI_CHANGES } }; int status = af_attr_open( sEventBase, /* event base */ "IPC.MYCLIENT", /* owner name */ sizeof(r)/sizeof(r[0]), /* numRanges */ r, /* ranges */ on_notify, /* notifyCB */ NULL, /* ownerSetCB */ NULL, /* ownerGetCB */ on_close, /* closeCB */ on_open, /* openCB */ NULL); /* context */ if (status != AF_ATTR_STATUS_OK) { /* Notify user */ event_base_free(sEventBase); return status; } event_base_dispatch(sEventBase); af_attr_close(); event_base_free(sEventBase); closelog(); return 0; }
This app will loop forever, printing out a message every time the REPORT_RSSI_CHANGES attribute gets set. If you want to exit the first time the attribute gets set, you can put an event_base_loopbreak
call in the on_notify
function. To test it you can set the attribute using the Attribute Client:
attrc set ATTRD_REPORT_RSSI_CHANGES 01
The Attribute Client is described in greater detail in the Attribute Client API Reference section.
An application that owns attributes needs to specify an ownerGet
callback. Also, if any of the attributes it owns is writable, it must specify an ownerSet
callback too. The Attribute daemon defines two attributes for the ATTRTEST client that can be used to demonstrate how to handle ownerSets
and ownerGets
. This code is a modified version of the code in the attr_test.c
function in the Attribute daemon repository.
The first attribute is flagged Writable and Notify and called AF_ATTR_ATTRTEST_SCRATCHWO. We’ll implement an owner set
function for it:
static int on_owner_set(uint32_t attributeId, uint8_t *value, int length, void *context) { /* at this point the new value of the attribute is stored in the value parameter */ /* and the length is stored in the length parameter. You can do something in */ /* in response to the set operation */ printf ("attribute %d was set. The first byte of the value is 0x%02x and the length is %d\n", attributeId, value[0], length); return AF_ATTR_STATUS_OK; }
We will also implement a read-only attribute called SCRATCH_RO. First we write an owner get
function for it:
static void on_get_request(uint32_t attributeId, uint16_t getId, void *context) { if (attributeId == AF_ATTR_ATTRTEST_SCRATCHRO) { char reply[] = "This is the value."; af_attr_send_get_response(AF_ATTR_STATUS_OK, getId, (uint8_t *)reply, sizeof(reply)); } else { af_attr_send_get_response(AF_ATTR_STATUS_ATTR_ID_NOT_FOUND, getId, NULL, 0); } }
Sometimes additional operations are needed to get the attribute value. If this operation takes a long time or needs the event loop to provide the value, you can delay the call to af_attr_send_get_response
to later. It does not have to be called in the on_get_request
callback.
There are two additional things we need to do:
open
call to ATTRTEST.ownerSet
and ownerGet
callbacks in the open
call.The full main
function is shown below:
int main(int argc, char *argv[]) { openlog("myclient", LOG_PID, LOG_USER); sEventBase = event_base_new(); if (sEventBase == NULL) { /* Notify user */ return AF_ATTR_STATUS_NO_SPACE; /* you can use your own error codes */ } int status = af_attr_open( sEventBase, /* event base */ "IPC.MYCLIENT", /* owner name */ 0, NULL, /* numRanges, ranges */ on_notify, /* notifyCB */ on_set_request, /* ownerSetCB */ on_get_request, /* ownerGetCB */ on_close, /* closeCB */ on_open, /* openCB */ NULL); /* context */ if (status != AF_ATTR_STATUS_OK) { /* Notify user */ event_base_free(sEventBase); return status; } event_base_dispatch(sEventBase); af_attr_close(); event_base_free(sEventBase); closelog(); return 0; }
You can use the Attribute Client to set
and get
these values:
attrc set ATTRTEST_SCRATCHWO "A" attrc get ATTRTEST_SCRATCHRO s
The Attribute Client is described in greater detail in the Attribute Client API Reference section.
If you want to add attributes that are supported by the attribute system you’ll need to modify the af_attr_def.h
file. The attributes are defined in the _ATTRIBUTES macro. The format for a single attribute is:
_ATTRDEF(<attributeID>, <short_name>, 0, <get_timeout>, <short_owner_name>, <flags>),
For example, the ATTRD_DEBUG_LEVEL is defined like this:
_ATTRDEF(51613, DEBUG_LEVEL, 0, 5, ATTRD, AF_ATTR_FLAG_WRITABLE), \
The attribute name is composed of the short owner name, an underscore delimiter, followed by the attribute short name. If you use this attribute name in your code you need to prefix the name with “AF_ATTR_”, for example, AF_ATTR_ATTRD_DEBUG_LEVEL.
To add an attribute to an existing daemon you just create a new entry in the _ATTRIBUTES macro.
If you want to create a new daemon, you add the name to the _OWNERS macro:
#define _OWNERS \ _OWNERDEF(UNKNOWN), \ _OWNERDEF(ATTRD), \ _OWNERDEF(ATTRTEST), \ _OWNERDEF(FSD), \ _OWNERDEF(WAN), \ _OWNERDEF(CONNMGR), \ _OWNERDEF(WIFISTAD), \ _OWNERDEF(HUBBY), \ _OWNERDEF(EDGED), \ _OWNERDEF(OTAMGR), \ _OWNERDEF(MYCLIENT), \
Then you can add an attribute to the _ATTRIBUTES macro. In this example we provide a debug level attribute.
_ATTRDEF(1102, DEBUG_LEVEL, 0, 5, MYCLIENT, AF_ATTR_FLAG_WRITABLE), \
Whenever you modify the attribute definitions you need to recompile the Attribute daemon and all code that depends on it to ensure everything works properly.
Afero attributes are all in Little Endian byte order. You should write your code to support both Little Endian and Big Endian architectures in case you decide to migrate your code to a different architecture. The Attribute Client library provides the following functions to help convert integers between host byte order and Little Endian.
Function | Description |
---|---|
af_attr_store_uint16 |
Stores a 16-bit unsigned integer in host byte order to an attribute value buffer in Little Endian byte order. |
af_attr_store_int16 |
Stores a 16-bit signed integer in host byte order to an attribute value buffer in Little Endian byte order. |
af_attr_store_uint32 |
Stores a 32-bit unsigned integer in host byte order to an attribute value buffer in Little Endian byte order. |
af_attr_store_int32 |
Stores a 32-bit signed integer in host byte order to an attribute value buffer in Little Endian byte order. |
af_attr_get_uint16 |
Retrieves a 16-bit unsigned integer from an attribute value buffer in Little Endian byte order and return its value in host byte order. |
af_attr_get_int16 |
Retrieves a 16-bit signed integer from an attribute value buffer in Little Endian byte order and return its value in host byte order. |
af_attr_get_uint32 |
Retrieves a 32-bit unsigned integer from an attribute value buffer in Little Endian byte order and return its value in host byte order. |
af_attr_get_int32 |
Retrieves a 32-bit signed integer from an attribute value buffer in Little Endian byte order and return its value in host byte order. |
The Attribute Client API Reference, directly below, has more information about these functions.
typedef struct { uint32_t first; uint32_t last; } af_attr_range_t;
Specifies a range of attributes. The range includes the specified endpoints.
typedef void (*af_attr_notify_callback_t) (uint32_t attributeId, uint8_t *value, int length, void *context);
Informs the client that the attribute with the specified ID has been set to the specified value with the specified length.
typedef int (*af_attr_set_request_callback_t) (uint32_t attributeId, uint8_t *value, int length, void *context);
Informs the client that another client has attempted to set the specified attribute that it owns. The owner returns the status of the set
operation. For example, the set
could fail because the client is busy modifying the same attribute.
typedef void (*af_attr_get_request_callback_t) (uint32_t attributeId, uint16_t getId, void *context);
Informs the client that someone has requested an attribute that it owns. The owner is responsible for calling the af_attr_send_get_response
function. This call can be made in this callback. Alternatively the af_attr_send_get_response
function can be called later if the operations required to get
the attribute value would block the event loop.
typedef void (*af_attr_status_callback_t) (int status, void *context);
Informs the client of the success or failure of an open or close operation. If an open operation failed, the status parameter indicates why the open failed. If the library closed unexpectedly, the status parameter indicates why the library closed. This callback is not called if you close the library using the af_attr_close
function.
typedef void (*af_attr_set_response_callback_t)(int status, uint32_t attributeId, void *setContext);
Used in conjunction with the af_attr_set
function. This function is called when a client Sets an attribute to indicate whether the set
operation was successful or not. If not, the status parameter contains the failure reason.
typedef void (*af_attr_get_response_callback_t)(uint8_t status, uint32_t attributeId, uint8_t *value, int length, void *context);
Used in conjunction with the af_attr_get
function. This function is called when the value the client is Getting is available. If the get
failed, the status parameter contains the reason.
Prototype
int af_attr_open (struct event_base *base, char *clientName, uint16_t numListenRanges, af_attr_range_t *listenRanges, af_attr_notify_callback_t notifyCb, af_attr_set_request_callback_t ownerSetCb, af_attr_get_request_callback_t getReqCb, af_attr_status_callback_t closeCb, af_attr_status_callback_t openCb, void *context);
Parameters
base |
Event base for the daemon’s event loop. You need to set up the event loop using event_base_new() before calling this function. |
clientName |
Name of the client. All Attribute Client names must start with the “IPC.” prefix. The name must match the name in the af_attr_def.h include file. |
numListenRanges |
Number of ranges in listenRanges list. |
listenRanges |
Array of ranges of attribute IDs for which the client wants attribute change notifications. |
notifyCb |
Callback that is called when an attribute in one of the listenRanges has changed. Set to NULL if you don’t need to receive notifications. |
ownerSetCb |
Callback that is called when another client changes an attribute this client owns. Set to NULL if the daemon doesn’t own any attributes that can be set. |
getReqCb |
Callback that is called when another client has requested the value of an attribute this client owns. |
closeCb |
Attribute Client library has closed unexpectedly. |
openCb |
Attribute Client library either opened successfully or failed to open. |
context |
Reference context for all of the callbacks. |
Description
Opens a connection to the Attribute daemon.
Return Value
Returns an error code on failure. If the return value is AF_ATTR_STATUS_OK, you need to wait for the open
callback to complete before you can know the final status of the open
operation.
Prototype
int af_attr_set (uint32_t attributeId, uint8_t *value, int length, af_attr_set_response_callback_t setCB, void *setContext);
Parameters
attributeId |
ID of the attribute to set. |
value |
Pointer to a byte array containing the value of the attribute. |
length |
Length of the value byte array. |
setCB |
Callback that is called to indicate if the set was successful or not. |
setContext |
Reference context for the set callback. |
Description
Sets the attribute with the specified ID to the specified value. All attributes are byte arrays with a length. This means that the attribute value is not necessarily a null-terminated string.
If the client is the owner of the attribute and the notify bit is set in the attribute flags, the change is propagated to the Attribute daemon and any interested listeners.
If the client is not the owner of the attribute, the setting is propagated to the Attribute daemon and then to the owner. If the owner allows the change and the Notify bit is set in the attribute’s flags, the change is propagated to the interested listeners too.
Return Value
Returns an error code on failure. If the return value is AF_ATTR_STATUS_OK, you need to wait for the callback to complete before you can know the final status of the set
operation.
Prototype
int af_attr_get (uint32_t attributeId, af_attr_get_response_callback_t cb, void *context);
Parameters
attributeId |
ID of the attribute to get . |
cb |
Callback that is called to return the value of the attribute. |
context |
Reference context for the get callback. |
Description
Gets the attribute with the specified ID. This is an asynchronous call, and the result is returned using the specified callback function. This function requests the attribute value from the Attribute daemon, who forwards the request to the client that owns the attribute. The owner returns the value of the attribute to the Attribute daemon, who returns it to the requesting client via the callback.
Return Value
Returns an error code on failure. If the return value is AF_ATTR_STATUS_OK, you need to wait for the callback to complete before you can know the final status of the get
operation.
Prototype
int af_attr_send_get_response (int status, uint16_t getId, uint8_t *value, int length);
Parameters
status |
Status value you can set if you can’t return the specified attribute. |
getId |
The getId that was passed in from the af_get_request_callback_t used by the Attribute Client library to match this response to the original request. |
value |
Byte buffer containing the attribute value to be returned. |
length |
Length of the request to be returned. |
Description
Sends a response to a get
request received from the af_attr_get_request_callback_t
in the af_attr_open function. This function sends the response to the Attribute daemon, who forwards it to the requesting client.
Return Value
Returns an error code on failure or AF_STATUS_OK if the response was successfully sent to the Attribute daemon.
Prototype
void af_attr_close (void);
Description
Closes the Attribute Client library. Calling this function will not call the close
callback function specified in the af_attr_open function
.
Prototype
void af_attr_store_uint16(uint8_t *dst, uint16_t value);
Description
Stores the specified 16-bit unsigned integer value into the specified destination attribute value buffer in Little Endian byte order. This is a convenience function that works on both Big Endian and Little Endian architectures. If the dst
parameter is NULL, this function has no effect.
Prototype
uint16_t af_attr_get_uint16(uint8_t *src);
Description
Returns the 16-bit unsigned integer value from the specified source attribute value buffer in Little Endian byte order. This is a convenience function that works on both Big Endian and Little Endian architectures. If the src
parameter is NULL, this function returns 0.
Prototype
void af_attr_store_int16(uint8_t *dst, int16_t value);
Description
Stores the specified 16-bit signed integer value into the specified destination attribute value buffer in Little Endian byte order. This is a convenience function that works on both Big Endian and Little Endian architectures. If the dst
parameter is NULL, this function has no effect.
int16_t af_attr_get_int16(uint8_t *src);
Description
Returns the 16-bit signed integer value from the specified source attribute value buffer in Little Endian byte order. This is a convenience function that works on both Big Endian and Little Endian architectures. If the src
parameter is NULL, this function returns 0.
Prototype
void af_attr_store_uint32(uint8_t *dst, uint32_t value);
Description
Stores the specified 32-bit unsigned integer value into the specified destination attribute value buffer in Little Endian byte order. This is a convenience function that works on both Big Endian and Little Endian architectures. If the dst
parameter is NULL, this function has no effect.
Prototype
uint32_t af_attr_get_uint32(uint8_t *src);
Description
Returns the 32-bit unsigned integer value from the specified source attribute value buffer in Little Endian byte order. This is a convenience function that works on both Big Endian and Little Endian architectures. If the src
parameter is NULL, this function returns 0.
Prototype
void af_attr_store_int32(uint8_t *dst, int32_t value);
Description
Stores the specified 32-bit signed integer value into the specified destination attribute value buffer in Little Endian byte order. This is a convenience function that works on both Big Endian and Little Endian architectures. If the dst
parameter is NULL, this function has no effect.
Prototype
int32_t af_attr_get_int32(uint8_t *src);
Description
Returns the 32-bit signed integer value from the specified source attribute value buffer in Little Endian byte order. This is a convenience function that works on both Big Endian and Little Endian architectures. If the src
parameter is NULL, this function returns 0.