2. Overview of Functionality
Amazon Sidewalk provides an Application Programming Interface API (the “Sid API”) that allows Amazon Sidewalk device creators to onboard their devices to Amazon Sidewalk, and to manage an encrypted data pipe over BLE and sub-GHz radio interfaces.
A developer’s application interacts with the Amazon Sidewalk stack through the Sid API. The Sid API supports the following operations for Amazon Sidewalk links:
- Initialize and de-initialize links.
- Start and stop links.
- Send and receive messages.
- Set and get configuration through IOCTLs.
2.1 Supported Links
Amazon Sidewalk supports three radio link types that can be used by devices to transport messages between the application running on the Endpoint device and the application services interacting with AWS IoT Core for Amazon Sidewalk, and one wired link type that is used only for factory registration (section 2.3.4). These links are enumerated in the following code, and described below.
/**
* Describes the link types supported by the Sidewalk stack.
*
* Note: Previously SID_LINK_TYPE_BLE used here now maps to SID_LINK_TYPE_1.
* The change is done to abstract link names from physical link types since
* more combinations are expected to be added in the future.
*/
enum SID_LINK_TYPE {
/** Bluetooth Low Energy link */
SID_LINK_TYPE_1 = 1 << 0,
/** 900 MHz link for FSK */
SID_LINK_TYPE_2 = 1 << 1,
/** 900 MHz link for LoRa */
SID_LINK_TYPE_3 = 1 << 2,
/** Wired (serial/UART) link, used only for factory registration */
SID_LINK_TYPE_8 = 1 << 7,
/** Any Link Type */
SID_LINK_TYPE_ANY = INT_MAX,
};
enum SID_LINK_TYPE_idx {
/** Bluetooth Low Energy link */
SID_LINK_TYPE_1_IDX = 0,
/** 900 MHz link for FSK */
SID_LINK_TYPE_2_IDX = 1,
/** 900 MHz link for LoRa */
SID_LINK_TYPE_3_IDX = 2,
/** sid max supported links */
SID_LINK_TYPE_MAX_IDX,
};
SID_LINK_TYPE_8 is not a radio link. It is brought up by the serial registration API (section 3.30), not by sid_init or sid_start, and it is not a valid link_mask member. It is required in the diagnostics firmware, the image the factory flashes to provision the Endpoint and register it over wire, or in any other image that performs factory registration; the production firmware does not otherwise need to include it.
2.1.1 BLE link
Amazon Sidewalk over BLE is called SID_LINK_TYPE_1. Amazon Sidewalk over BLE uses the Bluetooth Specification v4.2+ standard to transport messages through Amazon Sidewalk enabled Amazon/Ring Gateways.
The Amazon Sidewalk stack configures the BLE advertisement payload according to the use case to allow an Amazon Sidewalk BLE Gateway to detect the Endpoint and establish a connection. The beacons are periodically advertised by the Endpoint. The beacon advertisements switch between fast (160ms) and slow (1s) periodicity.
After detecting a beacon from the Endpoint the Gateway establishes connection only when the Amazon Sidewalk cloud instructs the Gateway to connect. (Note that the Amazon Sidewalk Cloud provides network management services for Amazon Sidewalk. The operation and control of these services is not visible to the developer.) The Gateway uses the standard BLE connection establishment procedure.
If, and only if, one of the following three conditions occurs, a BLE Gateway connects to the Endpoint:
-
The Endpoint requests time synchronization by updating the advertisement payload.
- The advertisement payload in the beacon is correctly received by the Gateway
- The advertisement payload contains information that informs the Gateway that the Endpoint is requesting time synchronization.
-
The Endpoint requests a connection by updating the advertisement payload.
- If the Endpoint has data to send to the AWS IoT Core for Amazon Sidewalk, or Amazon Sidewalk cloud services, it updates the request to the Gateway that it has data to send.
- The Gateway propagates this request to Amazon Sidewalk cloud services.
- The Amazon Sidewalk cloud service requests the Gateway to establish an encrypted connection with the Endpoint.
-
Amazon Sidewalk cloud services or the application on AWS IoT Core for Amazon Sidewalk has data to send to the Endpoint.
- The cloud service instructs a Gateway in range of the Endpoint to establish connection with the Endpoint to send downlink data. (An Endpoint is in range of a Gateway if the Gateway can listen to the beacons advertised by the Endpoint and periodically forward to the Amazon Sidewalk Cloud.)
For more details see the Amazon Sidewalk Specification.
2.1.2 FSK Link
Amazon Sidewalk over FSK is called SID_LINK_TYPE_2. Amazon Sidewalk over FSK uses a 2-GFSK modulation scheme in sub-GHz spectrum.
If the Gateway is using FSK, it periodically transmits a beacon. The beacon is discovered by FSK capable Endpoints to detect the presence of Amazon Sidewalk sub-GHz capable Gateways. The beacon also allows Endpoints that are using FSK to communicate with the Gateway to synchronize and schedule uplink and downlink messages.
For more details see the Amazon Sidewalk Specification.
2.1.3 LoRa Link
Amazon Sidewalk over LoRa is called SID_LINK_TYPE_3. Amazon Sidewalk over LoRa uses CSS in sub-GHz spectrum. Amazon Sidewalk over LoRa is an asynchronous radio protocol and so does not use beacons. The Amazon Sidewalk stack operates the LoRa link at one of two data rates: a default data rate and, where the regulatory region permits it, a higher data rate. See section 2.11.2.
For more details see the Amazon Sidewalk Specification.
2.2 Supported Link modes
Amazon Sidewalk supports two link modes SID_LINK_MODE_CLOUD, and SID_LINK_MODE_MOBILE.
SID_LINK_MODE_CLOUDis used forSID_LINK_TYPE_1,SID_LINK_TYPE_2, andSID_LINK_TYPE_3.SID_LINK_MODE_MOBILEis only used for link typeSID_LINK_TYPE_1, (BLE).
If a communication channel is established between an Endpoint and the Amazon Sidewalk cloud/AWS IoT Core for Amazon Sidewalk through a Gateway, the link mode for each link is set to SID_LINK_MODE_CLOUD.
If a communication channel is established between an Endpoint and the Sidewalk Mobile SDK, the link mode for the SID_LINK_TYPE_1 link is set to SID_LINK_MODE_MOBILE.
A session establishment procedure is used to establish the encrypted link between an Endpoint and the Amazon Sidewalk Mobile SDK.
For more details see the Amazon Sidewalk Specification.
/**
* Describes the link modes supported on each link type.
*
* Link mode determines the destination of the messages
* that sid api user can send on a link.
*/
enum sid_link_mode {
/** Messages can be sent to cloud only, when a link type
* notifies support of this mode */
SID_LINK_MODE_CLOUD = 1 << 0,
/** Messages can be sent to mobile only, when a link type
* notifies support of this mode */
SID_LINK_MODE_MOBILE = 1 << 1,
/** Invalid mode */
SID_LINK_MODE_INVALID = INT_MAX,
};
2.3 Registration and Deregistration
An Endpoint that is provisioned with Amazon Sidewalk certificates can use Registration to authenticate itself as an Amazon Sidewalk Endpoint. Registration involves transfer of messages between the Endpoint and the Amazon Sidewalk cloud services. During Registration, messages are transferred through Gateways or through the Amazon Sidewalk Mobile SDK. Registration establishes the authenticity of the Endpoint to the Amazon Sidewalk cloud and also establishes the authenticity of the Amazon Sidewalk cloud to the Endpoint. Successful registration is required before the Endpoint can access services offered by Amazon Sidewalk.
The Endpoint requires security credentials to encrypt communications with Amazon Sidewalk Cloud services, and with AWS IoT Core for Amazon Sidewalk. During the registration process the security credentials are stored in the Endpoint’s non-volatile storage.
Messages exchanged between the Endpoint and the AWS IoT application are encrypted with two keys: the Application server key and the Network server key.
The Application server key is derived during registration with AWS IoT Core for Amazon Sidewalk. The Network server key is derived during registration between the Endpoint and the Amazon Sidewalk cloud service.
User payloads are secured using two levels of encryption:
- The Application server key is used with the AES-CTR encryption scheme, to encrypt the User’s payload.
- The Network server key is used with the AES-GCM and AES-CTR encryption scheme, as a second layer of encryption on the payload.
Internal messages between the Amazon Sidewalk stack and cloud services are only encrypted with the Network server key. For more details on security refer to the Amazon Sidewalk white paper.
Over the air, Endpoint registration is only supported on SID_LINK_TYPE_2 (FSK) and SID_LINK_TYPE_1 (BLE). Endpoints cannot register with Amazon Sidewalk using SID_LINK_TYPE_3 (LoRa). Please note that only consent-enabled Amazon Sidewalk Gateways can be used to register Endpoints. There is no explicit API call to the Amazon Sidewalk stack to start the process of registration over SID_LINK_TYPE_2 or SID_LINK_TYPE_1. An Endpoint can also be registered at the factory over a wired link, SID_LINK_TYPE_8, through an explicit API, see section 2.3.4.
The Amazon Sidewalk stack automatically detects the registration status and triggers the registration procedure with the Amazon Sidewalk cloud services if the following conditions are met:
- The Amazon Sidewalk stack is initialized.
- The link is started.
- The Endpoint is not already registered.
The APIs to initialize and start the links are described below.
The Amazon Sidewalk stack exposes an API to de-register through the factory reset API, see section 2.3.5.
Registration uses one of four procedures described below.
2.3.1 Registration using Amazon Sidewalk Mobile SDK
The Amazon Sidewalk Mobile SDK allows a developer to integrate endpoint registration and de-registration controls into the developer’s own mobile application. (The Amazon Sidewalk Mobile SDK also supports a connection to an Endpoint to directly transmit and receive packets.)
The Endpoint uses SID_LINK_TYPE_1 (BLE) to register, and the Amazon Sidewalk Mobile SDK uses the phone’s BLE to communicate with the Endpoint.
During registration the Endpoint communicates with a mobile app that uses the Amazon Sidewalk Mobile SDK. The Amazon Sidewalk Mobile SDK handles the interaction between the Amazon Sidewalk cloud and the edge device, exchanging keys and registering the edge device, so that the edge device can then connect to the Amazon Sidewalk via Amazon Sidewalk gateways.
- The Endpoint’s beacons communicate its pre-registered state to the Gateway.
- The Amazon Sidewalk Mobile SDK connects to the Endpoint.
- The Amazon Sidewalk Mobile SDK triggers the registration sequence.
- The registration sequence completes.
For more details see the Amazon Sidewalk Mobile SDK Developer Guide.
2.3.2 Registration using FFS or FFN over BLE
Registration using FFS/FFN (Frustration Free Setup/Frustration Free Networking) over BLE requires SID_LINK_TYPE_1 (BLE).
The Endpoint uses SID_LINK_TYPE_1 to register. During registration the Endpoint communicates with an Amazon Sidewalk enabled BLE Gateway. Registration proceeds as follows:
- The Endpoint’s beacons communicate its pre-registered state to the Gateway.
- The Gateway is instructed by Amazon Sidewalk cloud services to connect to the Endpoint.
- The Gateway triggers the registration sequence.
- The registration sequence completes.
2.3.3 Registration using FFS or FFN over FSK
Registration using FFS/FFN over FSK requires SID_LINK_TYPE_2 (FSK)
The Endpoint uses SID_LINK_TYPE_2 to register. During registration the Endpoint communicates an Amazon Sidewalk enabled FSK Gateway. Registration proceeds as follows:
- The Endpoint scans for Amazon Sidewalk FSK beacons.
- The Endpoint synchronizes to a beacon from a Gateway that has Amazon Sidewalk consent enabled.
- The Endpoint triggers the registration sequence.
- The registration sequence completes.
Please note that in case of FSK, it is the Endpoint that starts the registration sequence while in the case of BLE, the registration is started by the Amazon Sidewalk cloud services through an Amazon Sidewalk BLE Gateway
2.3.4 Factory registration over a wired link
An Endpoint can be registered at the factory, before it has any radio contact, over a serial connection to a manufacturing host that runs the Amazon Sidewalk manufacturing tool. The exchange runs over SID_LINK_TYPE_8. The Endpoint authenticates the Amazon Sidewalk cloud and the cloud authenticates the Endpoint exactly as in the procedures above, and the security credentials are stored in the Endpoint’s non-volatile storage. For the manufacturing flow see the Amazon Sidewalk Registration over Wire Application Note.
The developer’s application does not use sid_init or sid_start for this. It initializes the serial transport, calls sid_serial_registration_init with the transport and a completion callback, calls sid_serial_registration_start when the host requests registration, and calls sid_serial_registration_process from its main loop until the callback reports completion, see sections 3.30 to 3.33. Registration proceeds as follows:
- The host sends the registration request over the serial link.
- The Endpoint and the Amazon Sidewalk cloud exchange the registration messages through the host.
- The registration sequence completes and the completion callback is called.
An Endpoint registered this way is factory-registered. On a build with SID_SDK_INTERNAL_CONFIG_IS_FACTORY_REGISTERED (section 2.15) the Amazon Sidewalk stack requests field activation itself once a link is started; sid_get_status reports SID_STATUS_NOT_REGISTERED until the Amazon Sidewalk cloud completes it, and on_status_changed reports SID_STATUS_REGISTERED when it does. On the lite build variants (section 2.15) the credentials are restored from the manufacturing page when the Amazon Sidewalk stack is initialized and the Endpoint reports SID_STATUS_REGISTERED immediately.
2.3.5 De-Registration
The Endpoint can be de-registered from Amazon Sidewalk. The de-registration process involves deletion of security keys and configuration parameters from the Endpoint’s non-volatile storage. De-registration of an Endpoint uses one of three procedures described below.
- Endpoint application initiated: the Sid API exposes the factory reset API. Calling this API de-registers the Endpoint from Amazon Sidewalk. The on factory reset callback notifies the developer’s application of the status of de-registration by the Amazon Sidewalk stack. Note that calling this API changes the device’s registered state to ready for registration. If the Amazon Sidewalk stack is not stopped or de-initialized, the Endpoint can start the process of registration immediately through FFS/FFN through an Amazon Sidewalk Gateway or through a mobile app that has Amazon Sidewalk Mobile SDK support.
- AWS IoT application service initiated: The AWS IoT application can de-register the device by issuing a factory reset command to the Amazon Sidewalk stack running on the Endpoint. The on factory reset callback notifies the developer’s Endpoint application that the Endpoint is de-registered from Amazon Sidewalk.
-
Initiated via Sidewalk Mobile SDK: The Amazon Sidewalk Mobile SDK exposes an API for the core application to trigger Amazon Sidewalk Endpoint de-registration.
- When the Amazon Sidewalk Mobile SDK triggers a request to de-register the Endpoint, The Amazon Sidewalk cloud sends a Factory Reset command which shall be routed via an Amazon Sidewalk Gateway OR the Amazon Sidewalk Mobile SDK. The routing choice for a factory reset command is based on the range of the Endpoint to the mobile.
- When the Endpoint is in range of the Amazon Sidewalk Mobile SDK, the de-registration process is simplified because the Amazon Sidewalk Mobile SDK has already established a direct communication path to the Endpoint to de-register. Using the Amazon Sidewalk Mobile SDK to inject a factory reset command is also useful if the developer’s application triggers the deregistration procedure when the Endpoint is not in range of an Amazon Sidewalk gateway.
On the lite build variants (section 2.15) the factory reset does not delete the factory credentials. The Amazon Sidewalk stack clears its non-volatile storage, restores the factory-provisioned credentials from the manufacturing page, re-applies the live network key and time-sync counter, and returns the Endpoint to the factory-registered state; the Endpoint then field-activates again on its next contact with the Amazon Sidewalk network. The on factory reset callback is called in both cases.
/**
* Describes the Registration status of the Sidewalk stack.
*/
enum sid_registration_status {
/** Used to indicate Sidewalk stack is registered with
* Sidewalk cloud services */
SID_STATUS_REGISTERED = 0,
/** Used to indicate Sidewalk stack is not registered
* with Sidewalk cloud services */
SID_STATUS_NOT_REGISTERED = 1,
};
2.4 Time Synchronization
The Amazon Sidewalk stack uses GPS time as a common frame of reference between Endpoints and the Amazon Sidewalk cloud service. The GPS time is used for encryption, and for derivation of the keys used to encrypt messages exchanged between Endpoints and Amazon Sidewalk services. A device has to be in the registered state to request time from the Amazon Sidewalk cloud service. After device registration is complete, or after the device resets in the registered state, the Amazon Sidewalk stack requests GPS time from the Amazon Sidewalk service. The time sync request process is described below:
-
Time sync on
SID_LINK_TYPE_1(BLE)- The Endpoint updates the advertisement payload on the beacon requesting time.
- Any BLE Gateway in range of the Endpoint forwards the request to the cloud service.
- The cloud service authenticates the Endpoint using its beacon payload.
- If authentication succeeds, the cloud service instructs the BLE Gateway through which the beacon was received to connect to the Endpoint and provide the time.
- The BLE Gateway connects to the Endpoint.
- The Amazon Sidewalk cloud service provides the time through the BLE Gateway. (The Endpoint does not need to send a time sync request message.)
-
Time sync on
SID_LINK_TYPE_2(FSK)- The Endpoint synchronizes to the beacon.
- The Endpoint sends a time sync request message to the Amazon Sidewalk service through the FSK enabled Gateway.
- The Amazon Sidewalk cloud authenticates the request.
- If authentication succeeds, the cloud service sends a time sync response message to the Endpoint. This message contains the GPS time.
- The EP authenticates the time sync response message.
- If authentication succeeds, the Endpoint accepts the GPS time from the message.
-
Time sync on
SID_LINK_TYPE_3(LoRa)- The time sync request message is sent by the Endpoint to the Amazon Sidewalk service through the LoRa enabled Amazon Sidewalk Gateway. The time sync request is sent soon after reset. The Amazon Sidewalk cloud authenticates the request and provides time to the Endpoint in the time sync response message. The Endpoint authenticates the time sync response message before accepting the time from the message.
To compensate for clock drift, the Endpoint periodically requests updated GPS time from the Amazon Sidewalk service. The periodicity is dependent on the device tolerance to clock drift and is the same for all of the device’s links. For more details on time sync request periodicity of the Endpoint see the Amazon Sidewalk Specification.
When the Amazon Sidewalk stack is in time synced state, the developer’s application can get the GPS time by querying the stack. The Amazon Sidewalk stack does not provide UTC or local time.
/**
* Describes the Time synchronization status of the Sidewalk
* stack with the cloud services.
* Sidewalk security relies on the synchronization of time
* between the cloud services and the end device.
*
* @note Sidewalk stack can have time synchronization with
* cloud service only when the device is registered
*
*/
enum sid_time_sync_status {
/** Used to indicate Sidewalk stack is registered with
* Sidewalk cloud services */
SID_STATUS_TIME_SYNCED = 0,
/** Used to indicate Sidewalk stack is not time synchronized
* with cloud services */
SID_STATUS_NO_TIME = 1,
};
/**
* Option to get current time.
*
* @attention GPS time is the time in milliseconds since 6/1/1980.
* GPS time is not adjusted by leap seconds.
* UTC time is the number of milliseconds since 1/1/1970.
* Local time is the adjusted time taking timezone into consideration.
*/
enum sid_time_format {
/** Option to get current gps time */
SID_GET_GPS_TIME = 0,
};
2.5 Stack States
The Amazon Sidewalk stack state of an Endpoint can be queried through a Sid API. The Amazon Sidewalk stack state is ready only when the Endpoint is registered, time is synced and at least one of the links is connected. The developer’s application can only send and receive messages when the Amazon Sidewalk stack is in ready state. For the Amazon Sidewalk stack states see table 2.1. A factory-registered Endpoint that has not yet been field-activated (section 2.3.4) reports SID_STATUS_NOT_REGISTERED and SID_STATE_NOT_READY; the Sid API does not distinguish it from an unregistered Endpoint.
Table 2.1: Amazon Sidewalk stack states.
| State | Type | Value | | ————————— | ——- | ———————————————————————————————————————- | | Sidewalk registration state | Boolean | Endpoint’s registration status<br>0 = registered<br>1 = not registered | | Sidewalk time sync state | Boolean | Endpoint’s time sync status<br>0 = Endpoint has time sync<br>1 = Endpoint does not have time sync | | Sidewalk link status | Boolean | Amazon Sidewalk link connection status (per link type)<br>0 = Endpoint is connected<br>1 = Endpoint is not connected |
/**
* Describes the state of the Sidewalk stack.
*/
enum sid_state {
/** Used when the Sidewalk stack is ready to
* send and receive messages */
SID_STATE_READY = 0,
/** Used when the Sidewalk stack is unable to send or receive
* messages, such as when the device is not registered
* or link gets disconnected or time is not synced */
SID_STATE_NOT_READY = 1,
/** Used when the Sidewalk stack encountered an error.
* Use sid_get_error() for a diagnostic
* error code */
SID_STATE_ERROR = 2,
/** Used when the Sidewalk stack is ready to send and receive
* messages only with secure channel establishment completed
* but device is not registered and time is not synced */
SID_STATE_SECURE_CHANNEL_READY = 3,
};
2.6 Stack Status
The Amazon Sidewalk stack status contains: registration state, time synchronization state, link connection states for each link, and link modes supported for each link.
For registration and time synchronization states see section 2.5.
The link_status mask holds the connection status of all the links supported by Amazon Sidewalk. The following code defines the link_status mask values. Note that concurrent FSK and LoRa is not supported.
// All links are in disconnected state
link_status_mask = 0;
// Only BLE link is connected
link_status_mask = 1; // ((link_status_mask & SID_LINK_TYPE_1) != 0)
// Only FSK link is connected
link_status_mask = 2; // ((link_status_mask & SID_LINK_TYPE_2) != 0)
// Only LoRa link is connected
link_status_mask = 4; // ((link_status_mask & SID_LINK_TYPE_3) != 0)
// BLE and FSK link is connected
link_status_mask = 3; // ((link_status_mask & SID_LINK_TYPE_1) != 0
// and (link_status_mask & SID_LINK_TYPE_2) != 0)
// BLE and LoRa link is connected
link_status_mask = 5; // ((link_status_mask & SID_LINK_TYPE_1) != 0
// and (link_status_mask & SID_LINK_TYPE_3) != 0)
The supported link modes is an array giving the connection mode for each link. Entries in the supported link modes array are accessed using the link type index.
/**
* Describes the link connection status with the gateway device
*
*/
struct sid_status_detail {
/**
* Used to indicate which link is up, if the bit corresponding to a link
* is set it is up otherwise it is down.
* For example to check if SID_LINK_TYPE_1 is up,
* !!(link_status_mask & SID_LINK_TYPE_1) needs to be true
*
* supported link modes indicate the modes supported by each link.
* A link type may support more than one mode simultaneously
*
* @see #sid_link_type_idx
*
*/
enum sid_registration_status registration_status;
enum sid_time_sync_status time_sync_status;
uint32_t link_status_mask;
uint32_t supported_link_modes[SID_LINK_TYPE_MAX_IDX];
};
The Amazon Sidewalk stack provides no Sid API call and no callback dedicated to reporting the data rate at which it operates the LoRa link, or whether a Gateway Session Key is in use. Get Device Profile reports the RX window interval in effect, and section 2.9 states which intervals are accepted at each data rate. See section 2.11.1 and section 2.11.2.
2.7 Link States
The connection establishment and maintenance of the established connection is different for each of the link types supported by Amazon Sidewalk, and is described below.
2.7.1 BLE Link States
When the Endpoint has messages to send to AWS IoT Core for Amazon Sidewalk, the Endpoint updates its beacon’s advertisement payload to request a connection. If there is an Amazon Sidewalk BLE Gateway in range, the gateway establishes a connection. For details of connection establishment see section 2.1.1
The Endpoint’s Amazon Sidewalk stack maintains the connection with the Amazon Sidewalk BLE Gateway only when there is uplink or downlink traffic. If the Endpoint does not transmit uplink traffic to the gateway, or receive downlink traffic from the Gateway for a period of 30 seconds, the Endpoint’s stack terminates the connection with the Amazon Sidewalk BLE Gateway and the developer’s application is notified. To re-connect, the developer’s application again requests the Amazon Sidewalk stack to updates its beacon’s advertisement payload to request a connection.
The developer’s application can prevent the Amazon Sidewalk stack from terminating the connection by sending at least one uplink message to AWS IoT Core for Amazon Sidewalk every 30 seconds, or if at least one downlink message is received by the Endpoint every 30 seconds the connection is maintained by the Amazon Sidewalk stack.
When the Endpoint on a BLE link does not have time synchronization, the Amazon Sidewalk stack updates the beacon’s payload requesting time sync. This is handled automatically by the Amazon Sidewalk stack. When the Endpoint does not have time synchronization, the developer’s application is notified of the time acquisition status and the developer’s application cannot send or receive messages until GPS time is acquired.
2.7.2 FSK Link States
The connection establishment procedure for an Amazon Sidewalk FSK Gateway starts with the Endpoint synchronizing with an FSK Gateway’s beacon that has consent enabled. When the beacon is synchronized, the Amazon Sidewalk stack starts the time acquistion process if the End point does not have GPS time. When the Endpoint has acquired GPS time, the developer is notified of the successful time acquisition status. After the Endpoint successfully acquires time, the Amazon Sidewalk stack starts the join procedure with Amazon Sidewalk cloud. See the Amazon Sidewalk Specification for more details on Join procedure.
If the Endpoint has not successfully acquired time or completed the Join procedure, the developer’s application cannot send or receive messages. When the Endpoint has completed the Join procedure successfully, the developer’s application is notified of the successful link connection status and the developer’s application can send and receive messages. When the Endpoint misses 3 consecutive beacons from the already synchronized Amazon Sidewalk FSK gateway, the developer’s applcation is notified of link disconnected status. The Amazon Sidewalk stack starts the gateway discovery procedure to discover Amazon Sidewalk FSK gateways after disconnection.
Note that time synchronization process is started by the Amazon Sidewalk stack only when the Endpoint does not have GPS time. The synchronization with a Amazon Sidewalk FSK gateway’s beacon will not always trigger time acquisition process. However, every time the Endpoint transistions from gateway discovering state to a successful gateway discovered state, Join procedure is triggered.
The configuration of the device profile settings configuration determines the following:
- The parameters that are sent in the join request.
- The downlink schedules of the Endpoint.
See the Amazon Sidewalk Sub-GHz Device Profiles Application Note for more details.
2.7.3 LoRa Link States
The LoRa link does not establish a connection with an Amazon Sidewalk LoRa Gateway (the link between the Endpoint and the Gateway is asynchronous and connectionless). After the link is initialized and started, the Amazon Sidewalk stack starts the time acquistion process if the End point does not have GPS time. When the Endpoint has acquired GPS time, the developer is notified of the successful time acquisition status. After the Endpoint successfully acquires time, the Amazon Sidewalk stack starts the join procedure with Amazon Sidewalk cloud. See the Amazon Sidewalk Specification for more details on Join procedure.
If the Endpoint has not successfully acquired time or completed the Join procedure, the developer’s application cannot send or receive messages. When the Endpoint has completed the Join procedure successfully, the developer’s application is notified of the successful link connection status and the developer’s application can send and receive messages. The configuration of the device profile settings configuration determines the following:
- The parameters that are sent in the join request.
- The downlink schedules of the Endpoint.
- In some cases, the requirements on the Endpoint to send periodic uplinks.
See the Amazon Sidewalk Sub-GHz Device Profiles Application Note for more details.
An accepted change to the device profile on a started, network synchronized LoRa link takes the link out of network synchronization. SID_LINK_TYPE_3 therefore leaves and later re-enters link_status_mask, and the developer’s application is notified through the on status changed callback. That notification is indistinguishable from any other LoRa outage, so the developer’s application cannot use it to establish the cause.
A change of the data rate at which the Amazon Sidewalk stack operates the LoRa link has the same effect. Establishing a key moves the link to the higher data rate, so the Join occurs only where the Amazon Sidewalk stack has to make that change; if the developer’s application already requested that rate, nothing in the Amazon Sidewalk stack status changes. Where the Amazon Sidewalk stack ceases to use a key and the developer’s application has not requested the higher data rate, it returns the link to the default data rate: SID_LINK_TYPE_3 leaves and later re-enters link_status_mask, and in some cases the link restarts and re-enters time acquisition before re-joining. Otherwise the link stays at the higher data rate: the Endpoint does not repeat the Join procedure, nothing in the Amazon Sidewalk stack status changes, and an RX window interval shorter than the default, if one was in effect, remains in effect until the link moves away from the higher data rate. On the FSK link, establishing a Gateway Session Key makes the Endpoint repeat the Join procedure without taking the link out of network synchronization, so a successful repeat changes nothing in the Amazon Sidewalk stack status; a repeat that does not succeed is reported like any other FSK outage. The developer’s application shall not use the on status changed callback to detect a key change on either link. See section 2.11.1 and section 2.11.2.
2.7.4 Route Selection For Downlinks
The last uplink message affects how Amazon Sidewalk processes downlink messages. Cloud services send any pending downlink packets using the link on which the Endpoint last sent an uplink packet.
For BLE, if there is no active link, downlink packets for an Endpoint are sent to the BLE Gateway that last received a beacon from that Endpoint.
For FSK, downlink packets for an Endpoint are sent to the FSK Gateway that last received an uplink message from that Endpoint.
For LoRa, downlink packets for an Endpoint are sent to the LoRa Gateway that last received an uplink message from that Endpoint.
How soon the Endpoint can receive a pending LoRa downlink depends on when it next opens an RX window, which the device profile and the configured RX window interval together determine, once the link has completed the Join procedure. For how that interval is configured, see section 2.9.
If BLE beacons and uplinks from FSK or LoRa reach the cloud simultaneously, BLE is the preferred link for the downlink transmission.
2.8 Amazon Sidewalk Messages
The Amazon Sidewalk stack provides APIs to send messages to AWS IoT and notifies the developer’s application of messages received from AWS IoT Core for Amazon Sidewalk.
Each Amazon Sidewalk message is associated with metadata that uniquely identifies the message. The metadata in a message also notifies the Amazon Sidewalk stack of the attributes that are to be applied to each message.
Amazon Sidewalk messages are agnostic to the link on which the messages are being sent. The only varying factor is the MTU of the link. The message types and attributes of messages are the same irrespective of the link the message is being sent on.
For the MTU of the links supported by Amazon Sidewalk see table 2.2.
Table 2.2: MTU of Amazon Sidewalk links.
| Link Type | MTU (Bytes) | | —————— | ———– | | BLE (link type 1) | 255 | | FSK (link type 2) | 200 | | LoRa (link type 3) | 19 |
The message consists of msg and msg_desc data structures. The msg data structure has size and a pointer to the payload of the message. The msg_desc data structure has message attributes which are described in detail below:
union sid_msg_desc_attributes {
/** Attributes that are applied only when message is
* transmitted, see #sid_put_msg */
struct sid_msg_desc_tx_attributes tx_attr;
/** Attributes reported per message when the message is
* reported to the developer's application, see #on_msg_received */
struct sid_msg_desc_rx_attributes rx_attr;
};
struct sid_msg_desc {
/** The link type on which this message is to be sent
* or was received from */
uint32_t link_type;
/** The message type */
enum sid_msg_type type;
/** The link mode on which message is sent or received */
enum sid_link_mode link_mode;
/** The id associated with a message, generated by the
* Sidewalk stack
* The maximum value the id can take is 0x3FFF after
* which the id resets % to
*/
uint16_t id;
/** Attributes applied to the message */
union sid_msg_desc_attributes msg_desc_attr;
};
/**
* Describes a message payload.
*/
struct sid_msg {
void *data;
size_t size;
};
2.8.1 Amazon Sidewalk Message Types
Sid API supports four types of messages. The same message types are available to the application on AWS IoT Core for Amazon Sidewalk. When messages are exchanged between the Endpoint and AWS IoT Core for Amazon Sidewalk, the message type is also notified.
The four message types are as follows:
GETto retrieve some data from destination. This message type elicits a mandatory response from the receiver.SETrequests to write some data on destined devices. These requests can be used to update feature configuration or trigger an operation on device.RESPtype messages are sent in response toGET,SETorNOTIFY.RESPmessages are an empty acknowledgement, and shall not contain any payload data. TheRESPmessages are sent in response only when there is an explicit request from the message senderNOTIFYmessages are sent by a device or application.NOTIFYmessages do not correspond to any preceding requests.
When the API to send a message is called, the Amazon Sidewalk stack generates a unique ID. This unique ID is the message ID. The developer’s application is expected to store this message ID to compare with the corresponding message ID returned in a send status event or in an acknowledgement from the AWS IoT Core for Amazon Sidewalk. The stack generates a unique message ID for all message types except RESP. For message type RESP, the stack expects the message ID to be provided by the developer’s application.
There is no restriction on the use of a message type in a different manner than what is documented above except for message type RESP. For example the message type GET can be used to trigger an operation on a device or NOTIFY can be used by the developer’s application to get some data from destination.
/**
* The Sidewalk stack message types.
* The messages from cloud services to the End device are designated as
* "Downlink Messages"
* The messages from End device to Cloud services are designated as
* "Uplink Messages"
*/
enum sid_msg_type {
/** #SID_MSG_TYPE_GET is used by the sender to retrieve information from
* the receiver, the sender
* expects a mandatory response from the receiver. On reception of
* SID_MSG_TYPE_GET, the receiver is expected to send a message with type
* #SID_MSG_TYPE_RESPONSE with the same message id it received from the
* message type #SID_MSG_TYPE_GET.
* This is to ensure the sender can map message type #SID_MSG_TYPE_GET
* with the received #SID_MSG_TYPE_RESPONSE.
* Both uplink and downlink messages use this message type.
* @see sid_put_msg().
* @see on_msg_received in #sid_event_callbacks.
*/
SID_MSG_TYPE_GET = 0,
/** #SID_MSG_TYPE_SET indicates that the sender is expecting the receiver
* to take an action on receiving the message and the sender does not
* expect a response.
* #SID_MSG_TYPE_SET type is used typically by Cloud services to trigger
* an action to be preformed by the End device.
* Typical users for this message type are downlink messages.
*/
SID_MSG_TYPE_SET = 1,
/** #SID_MSG_TYPE_NOTIFY is used to notify cloud services of any periodic
* events or events triggered/originated from the device. Cloud services
* do not typically use #SID_MSG_TYPE_NOTIFY as the nature of messages
* from cloud services to the devices are explicit commands instead of
* notifications.
* Typical users for this message type are uplink messages.
*/
SID_MSG_TYPE_NOTIFY = 2,
/** #SID_MSG_TYPE_RESPONSE is sent as a response to the message of type
* #SID_MSG_TYPE_GET.
* The sender of #SID_MSG_TYPE_RESPONSE is required to the copy the
* message id received in the message of type #SID_MSG_TYPE_GET.
* Both uplink and downlink messages use this message type.
* @see sid_put_msg().
* @see on_msg_received in #sid_event_callbacks.
*/
SID_MSG_TYPE_RESPONSE = 3,
};
2.8.2 Amazon Sidewalk Message Sequence Numbers
Every message sent by the Endpoint or received by the Endpoint has a unique sequence number associated with it. When Amazon Sidewalk stack successfully accepts message for transmission, an unique sequence number is assigned to the messsage. The sequence number can be used to track messages exchanged between the Endpoint and AWS IoT core for Amazon Sidewalk. Amazon Sidewalk stack does not guarantee the order of messages sent and received by the Endpoint.
2.8.3 Amazon Sidewalk Message Attributes
When sending a message, the message attributes can be used to modify each message’s behavior. When receiving a message, the Amazon Sidewalk stack uses the received message attributes to notify the developer’s application of the attributes AWS IoT Core for Amazon Sidewalk has configured for the message.
2.8.3.1 Amazon Sidewalk Message Transmit Attributes
The Amazon Sidewalk stack notifies the status of the message sent over the air by configured link and also the status of message received by the AWS IoT Core for Amazon Sidewalk based on the transmit attributes configured on every message. The status of the message whether received by AWS IoT Core for Amazon Sidewalk is reported to the developer’s application only when Transport Ack is requested by the developer’s application.
For each message, the Amazon Sidewalk stack performs retries based on the Number of Retries configuration.
The developer’s application can configure the following attributes of the message that is to be sent by the Amazon Sidewalk stack:
- Request Acknowledgment from AWS IoT: When this configuration is set to true, the Amazon Sidewalk stack requests AWS Io Core for Amazon Sidewalk to send an Acknowledgment when AWS IoT Core for Amazon Sidewalk receives the message. Note that the acknowledgment is sent by AWS IoT Core for Amazon Sidewalk, and not by the developer’s AWS IoT application. This is configured with Transport Ack set to
TRUE. Acknowledgements are sent using messages with message typeRESPand zero size payload. - Number of Retries This requires Transport Ack set to
TRUE. When set toTRUE, AWS IoT Core for Amazon Sidewalk sends an Acknowledgment back to the Amazon Sidewalk stack. If the Acknowledgment is not received, the Amazon Sidewalk stack retries the message the number of times configured in Number of Retries. If there is no Acknowledgement received after Number of Retries transmissions, then the Amazon Sidewalk stack sends a failure to send status report to the developer’s application. - Time to Live: The time in milliseconds that the Amazon Sidewalk stack holds the message in its queue before reporting to the developer’s application the failure to receive the acknowledgment from AWS IoT.
Please note that the retry periodicity is derived from Number of Retries and Time to Live configuration.
Retry periodicity = Time to Live / Number of Retries
/** Attributes applied to the message descriptor on tx */
struct sid_msg_desc_tx_attributes {
/** Whether this message requests an ack from the AWS IOT service */
bool request_ack;
/** Number of retries the Sidewalk stack needs to preform in case the
* ack is not received. Setting not applicable if request_ack is set
* to false
*/
uint8_t num_retries;
/** Total time the Sidewalk stack holds the message in its queue in case
* the ack is not received. Setting not applicable if request_ack is set
* to false
*/
uint16_t ttl_in_seconds;
}
2.8.3.2 Amazon Sidewalk Message Receive Attributes
Each message received by the Amazon Sidewalk stack is notified to the developer’s application using the on msg received callback registered by the developer’s application. The following are the received message attributes reported on every Amazon Sidewalk message:
- Acknowledgement: The received message is an acknowledgement from the AWS IoT Core for Amazon Sidewalk that it has received the message sent by the Endpoint.
- Duplicate: The received message is a duplicate. The Amazon Sidewalk stack keeps track of the last 10 messages received from AWS IoT Core for Amazon Sidewalk and either reports or filters duplicates. The choice to report or filter can be configured, see section 2.9. A duplicate is a message that has the same message ID and payload size as a message that has already been reported to the developer’s application.
- Acknowledgement Request: The AWS IoT application can request acknowledgment from the device when sending messages to the device. The Amazon Sidewalk stack reports the status that AWS IoT Core for Amazon Sidewalk requested in an acknowledgement for a message. The Amazon Sidewalk stack responds to AWS IoT Core for Amazon Sidewalk immediately with an Acknowledgment and then reports the message to the developer’s application with the acknowledgment request set to
TRUE. When the developer’s application receives the message with acknowledgment set toTRUE, the Amazon Sidewalk stack had already queued the Acknowledgment to AWS IoT Core for Amazon Sidewalk. - rssi: the received signal strength at which the message is received by the link’s radio.
- snr: the signal to noise ratio reported by the radio on this message.
/** Attributes with which the message is received */
struct sid_msg_desc_rx_attributes {
/** Whether the message received is an acknowledgement. Acknowledgements
* have the same message id as that of message sent but with zero payload
* size. See #sid_msg_desc_tx_attributes
*/
bool is_msg_ack;
/** Whether the message received is a duplicate. If a message arrives at
* the Sidewalk stack with message id and payload size equal to an
* already reported message, this message is marked as a duplicate
* See #SID_OPTION_SET_MSG_POLICY_FILTER_DUPLICATES
*/
bool is_msg_duplicate;
/** Whether the message received has requested an acknowledgement to be
* sent, Acknowledgements have the same message id as that of the
* received message. The Sidewalk stack immediately queues an
* acknowledgement to the sender before propagating this message to the
* developer's application */
bool ack_requested;
/** rssi of the received message */
int16_t rssi;
/** snr of the received message */
int16_t snr;
}
see section 2.3.5.
2.9 Stack IOCTLs
The Sid API allows the developer’s application to modify certain aspects of the Amazon Sidewalk stack’s behavior through IOCTLs. The following IOCTLs are available for the developer’s application to configure:
-
Set Device Profile: This IOCTL is valid only for FSK and LoRa and does not apply for BLE. The default profile setting for FSK is Profile 1 and for LoRa it is Profile B. For FSK (Link Type 2), additional parameters can be configured:
beacon_interval_unit: Specifies the beacon interval unit for FSK communication. Valid values areSID_LINK2_BEACON_INTERVAL_UNIT_1,SID_LINK2_BEACON_INTERVAL_UNIT_2, andSID_LINK2_BEACON_INTERVAL_UNIT_3.l2_rx_duration_sec: Defines the Layer 2 receive duration in seconds for FSK links. Valid range is 0 to 65535 seconds.
For LoRa (Link Type 3), the following profiles are supported:
SID_LINK3_PROFILE_A(0x80): Asynchronous profile with configurable RX windows. Therx_window_countcan be set from 0 toSID_RX_WINDOW_CNT_PROFILE_A_MAX(60). No periodic network sync.SID_LINK3_PROFILE_B(0x81): Default LoRa profile with infinite RX windows. Therx_window_countshall beSID_RX_WINDOW_CNT_INFINITE; any other value is rejected. Supports periodic network sync with configurable interval (1-240 mins, default 5 mins).SID_LINK3_PROFILE_C(0x82): Continuous RX mode profile. The device stays in continuous receive mode with no RX window interval: the Amazon Sidewalk stack replacesrx_window_countwithSID_RX_WINDOW_CONTINUOUS(0xFF) andunicast_window_interval.async_rx_interval_mswithSID_LINK3_RX_WINDOW_SEPARATION_CONTINUOUS(0), rather than validating the values supplied for them. This profile provides lowest latency for downlink messages but highest power consumption. The Amazon Sidewalk stack arms the keep-alive for this profile as it does forSID_LINK3_PROFILE_B, with a default keep-alive interval of 24 hours for this profile; see section 2.9.8 and section 2.9.10.SID_LINK3_PROFILE_D(0x83): Reserved. Set Device Profile does not accept this profile ID.
For the LoRa device profile parameters that can be configured, their accepted values, the preconditions of each operation and the error conditions, see section 2.9.11. For more details on FSK and LoRa device profiles, see Amazon Sidewalk Sub-GHz Device Profiles Application Note.
- Get Device Profile: Get the device’s current operating profile. The developer’s application shall set
unicast_params.device_profile_idto a profile ID of the link being queried before the call; see section 2.9.11. See Amazon Sidewalk Sub-GHz Device Profiles Application Note. - Set filter duplicates: The Amazon Sidewalk stack can filter or report duplicate messages. This setting allows the developer’s application to modify the stack behavior to filter or to report the duplicate messages. When set to 1, the Amazon Sidewalk stack filters the duplicates and does not report duplicate messages to the developer’s application. The default setting is 0, to filter duplicates. When set to 1, the Amazon Sidewalk stack reports the duplicates using the on msg received callback with the
is_msg_duplicateset to 1 in the metadata of the message. - Get filter duplicates: Get the current setting of filter duplicates.
- Set link connection policy: Set the link connection policy. See section 2.9.1.
- Get link connection policy: Get the current setting of link connection policy. See section 2.9.1.
- Set auto link connection policy parameters: Set auto link connection policy parameters. See section 2.9.1.2.
- Get auto link connection policy parameters: Get the current setting of auto link connection policy parameters. See section 2.9.1.2.
- Set multi-link connection policy: Set multi-link connection policy. See section 2.9.1.3.
- Get multi-link connection policy: Get the current setting of multi-link connection policy. See section 2.9.1.3.
- Get statistics: Get statistics report from Amazon Sidewalk stack. See section 2.9.2.
- Clear statistics: Clear statistics collected by Amazon Sidewalk stack. See section 2.9.2.
- Get Sidewalk ID: Get the Sidewalk ID for the device. Since Sidewalk ID is given to the device post regsitration. This option will only work post regsitration. See section 2.9.7.
- Get/Set delayed ack time: Get/Set the time of delayed ack. See section 2.9.3.
- Get/Set gateway discovery and selection policy: Option to get/set the gateway discovery and selection policy. This IOCTL is valid only for FSK. See section 2.9.4.
- BLE user configuration: Get/set the current BLE configuration. See section 2.9.5.
- Get/Set downlink route validity and keep-alive interval: Option to get/set the current downlink route validity time and, together with it, the keep-alive / network-sync interval for Sub-GHz links. See section 2.9.8.
- Sub-GHz user control: Option to send user control commands to Sub-GHz links (FSK/LoRa). See section 2.9.9.
- LoRa transmit power control configuration: Option to set transmit power control configuration for LoRa (Link Type 3).
The currently available IOCTL options are listed below.
/**
* The set of options to be used with sid_option API.
*/
enum sid_option {
/** Reserved option for future use */
SID_OPTION_RESERVED = 0,
/** Option to configure the device profile.
* Value is of type struct sid_device_profile */
SID_OPTION_900MHZ_SET_DEVICE_PROFILE = 1,
/** Option to get the device profile configuration.
* Value is of type struct sid_device_profile */
SID_OPTION_900MHZ_GET_DEVICE_PROFILE = 2,
/** Option to set the message policy to filter duplicates,
* value is 0 or 1, when set to 0, the default setting,
* duplicates are filtered and are not propagated using
* #on_msg_received, when set to 1, duplicates are detected
* and are propagated using #on_msg_receive,
* see #sid_msg_desc_rx_attributes
*/
SID_OPTION_SET_MSG_POLICY_FILTER_DUPLICATES = 3,
/** Option to get the configured policy of filtering duplicates,
* 0 - Filter duplicates, 1 - Allow duplicates */
SID_OPTION_GET_MSG_POLICY_FILTER_DUPLICATES = 4,
/** Option to set the link connection policy setting */
SID_OPTION_SET_LINK_CONNECTION_POLICY = 5,
/** Option to get the current link connection policy setting */
SID_OPTION_GET_LINK_CONNECTION_POLICY = 6,
/** Option to allow the stack to attempt connection of the link
* when the message is sent using sid_put_msg. This option is valid
* only when the message is sent not using #SID_MSG_LINK_TYPE_ANY
* #SID_MSG_LINK_TYPE_ANY enables multi-link policy and connection policy
* is determined by the configured multi-link policy. see
* #sid_link_auto_connect_params
*/
SID_OPTION_SET_LINK_POLICY_AUTO_CONNECT_PARAMS = 7,
/** Option to get the configured auto connect params for a
* particular link type. see #sid_link_auto_connect_params.
* The link_type needs to filled when getting the auto connect params */
SID_OPTION_GET_LINK_POLICY_AUTO_CONNECT_PARAMS = 8,
/** Option to configure mlm link policy settings for the device */
SID_OPTION_SET_LINK_POLICY_MULTI_LINK_POLICY = 9,
/** Option to configure mlm link policy settings for the device */
SID_OPTION_GET_LINK_POLICY_MULTI_LINK_POLICY = 10,
/** Get msg statistics for the device */
SID_OPTION_GET_STATISTICS = 11,
/** Clear msg statistics for the device */
SID_OPTION_CLEAR_STATISTICS = 12,
/** Get the Sidewalk ID for the device. Since Sidewalk ID is given to the
* device post regsitration. This option will only work post regsitration
*/
SID_OPTION_GET_SIDEWALK_ID = 13,
/** Option to get/set the time of delayed ack */
SID_OPTION_DELAYED_ACK_CONFIG = 14,
/** Option to get/set the gateway discovery policy for FSK.
* Value is of type struct sid_link_type_2_gw_discovery_policy_config */
SID_OPTION_LINK_TYPE_2_GW_DISCOVERY_POLICY = 15,
/** Option to get/set ble config */
SID_OPTION_BLE_USER_CONFIG = 16,
/** Option to get/set BLE use for D2D only */
SID_OPTION_USE_BLE_FOR_D2D_ONLY = 17,
/** Option to get/set ble connection policy */
SID_OPTION_BLE_CONNECTION_POLICY = 18,
/** Option to get/set DL route validity settings for the device */
SID_OPTION_DL_ROUTE_VALIDITY = 19,
/** Option to set user control for sub-ghz */
SID_OPTION_SUB_GHZ_USER_CONTROL = 20,
/** Option to set transmit power control config for LoRa */
SID_OPTION_LINK_TYPE_3_TRANSMIT_POWER_CONTROL_CONFIG = 21,
/** Delimiter to enum sid_option */
SID_OPTION_LAST,
};
The device profile IDs for FSK (Link Type 2) and LoRa (Link Type 3) are defined as follows:
/**
* Describes the profile type of the device
*/
enum sid_device_profile_id {
/** Device Profile ID for Synchronous Network (FSK) */
SID_LINK2_PROFILE_1 = 0x01,
SID_LINK2_PROFILE_2 = 0x02,
SID_LINK2_PROFILE_LAST,
/** Device Profile ID for Asynchronous Network (LoRa) */
SID_LINK3_PROFILE_A = 0x80, // Configurable RX windows, no periodic sync
SID_LINK3_PROFILE_B = 0x81, // Default, infinite RX windows, periodic sync
SID_LINK3_PROFILE_C = 0x82, // Continuous RX mode, no periodic sync
SID_LINK3_PROFILE_D = 0x83, // Reserved
SID_LINK3_PROFILE_LAST,
};
2.9.1 Amazon Sidewalk stack Connection Policy
The connection policy adopted by the Amazon Sidewalk stack to establish and maintain connection with Amazon Sidewalk Gateways can be configured by the developer.
/**
* Describes the connection policy setting
*/
enum sid_link_connection_policy {
/** Default setting. Sidewalk stack does not apply any
* connection policy. */
SID_LINK_CONNECTION_POLICY_NONE = 0,
/** Auto connection policy, Sidewalk stack applies auto connection policy
* based on the parameters
* configured through auto connection policy parameters. */
SID_LINK_CONNECTION_POLICY_AUTO_CONNECT,
/** Multi-link connection policy, Sidewalk stack applies multi-link
* connection policy based on the policy
* configured through multi-link connection policy. */
SID_LINK_CONNECTION_POLICY_MULTI_LINK_MANAGER,
/** Delimiter to enum sid_link_connection_policy */
SID_LINK_CONNECTION_POLICY_LAST
};
// IOCTL to set link connection policy
// Set link connection policy to SID_LINK_CONNECTION_POLICY_AUTO_CONNECT
enum sid_link_connection_policy set_policy =
SID_LINK_CONNECTION_POLICY_AUTO_CONNECT;
sid_error_t ret = sid_option(handle, SID_OPTION_SET_LINK_CONNECTION_POLICY,
&set_policy, sizeof(set_policy));
// IOCTL to get link connection policy
// Get configured link connection policy
enum sid_link_connection_policy get_policy;
sid_error_t ret = sid_option(handle, SID_OPTION_GET_LINK_CONNECTION_POLICY,
&get_policy, sizeof(get_policy));
2.9.1.1 SID_LINK_CONNECTION_POLICY_NONE
The Amazon Sidewalk stack does not play a role in the connection establishment and its maintenance with the Amazon Sidewalk Network. The developer is expected to handle the connection establishment and its maintenance in this configuration. The default connection policy the Amazon Sidewalk stack is configured with is SID_LINK_CONNECTION_POLICY_NONE
2.9.1.2 SID_LINK_CONNECTION_POLICY_AUTO_CONNECT
The developer provides the parameters of the connection establishment and maintenance under this configuration of connection policy. For details on auto connection policy and its parameters, Please see Amazon Sidewalk Multi-link Application Note
/**
* Describes link auto connect parameters
*/
struct sid_link_auto_connect_params {
/** Sid link type */
enum sid_link_type link_type;
/** Auto connect policy if set enable is equal to 0 */
bool enable;
/** Priority of the link type when more than one link is specified
* using #sid_put_msg
* 0 is highest priority, 2 is lowest priority */
uint8_t priority;
/** Maximum period upto which the stack attempts to form a connection */
uint16_t connection_attempt_timeout_seconds;
};
// IOCTL to set auto connect parameters
// Set auto connection params for SID_LINK_TYPE_1 with priority 1 and
// connection_attempt_timeout_seconds to 30
struct sid_link_auto_connect_params params_link_1 = {
.link_type = SID_LINK_TYPE_1,
.enable = true,
.priority = 0,
.connection_attempt_timeout_seconds = 30
};
sid_error_t ret = sid_option(handle,
SID_OPTION_SET_LINK_POLICY_AUTO_CONNECT_PARAMS,
¶ms_link_1, sizeof(params_link_1));
// IOCTL to get auto connect parameters
// Get auto connection parameters configured for SID_LINK_TYPE_1
struct sid_link_auto_connect_params get_params_link_1 = {
.link_type = SID_LINK_TYPE_1,
};
ret = sid_option(handle, SID_OPTION_GET_LINK_POLICY_AUTO_CONNECT_PARAMS,
&get_params_link_1, sizeof(get_params_link_1));
2.9.1.3 SID_LINK_CONNECTION_POLICY_MULTI_LINK_MANAGER
The multi-link connection policy determines the message uplink attributes and link connection attributes and does not expect the developer to configure these parameters while sending the message. For details on multi-link connection policy, Please see Amazon Sidewalk Multi-link Application Note.
/** multi-link policy modes */
enum sid_link_multi_link_policy {
/** Default policy, Default Setting, All links are enabled */
SID_LINK_MULTI_LINK_POLICY_DEFAULT = 0,
/** Policy optimized for better power consumption */
SID_LINK_MULTI_LINK_POLICY_POWER_SAVE = 1,
/** Policy optimized for performance, better throughput */
SID_LINK_MULTI_LINK_POLICY_PERFORMANCE = 2,
/** Policy optimized for latency, faster uplinks */
SID_LINK_MULTI_LINK_POLICY_LATENCY = 3,
/** Policy optimized for reliability, messages have a longer Time to live
* and more retries */
SID_LINK_MULTI_LINK_POLICY_RELIABILITY = 4,
/** Delimiter to enum sid_link_power_policy_type */
SID_LINK_MULTI_LINK_POLICY_LAST
};
// IOCTL to set multi-link policy
// Set multi-link policy to SID_LINK_MULTI_LINK_POLICY_PERFORMANCE
enum sid_link_multi_link_policy policy =
SID_LINK_MULTI_LINK_POLICY_PERFORMANCE;
sid_error_t ret = sid_option(handle,
SID_OPTION_SET_LINK_POLICY_MULTI_LINK_POLICY,
&policy, sizeof(policy));
// IOCTL to get multi-link policy
// Get current configured multi-link policy
enum sid_link_multi_link_policy get_policy;
sid_error_t ret = sid_option(handle,
SID_OPTION_GET_LINK_POLICY_MULTI_LINK_POLICY,
&get_policy, sizeof(get_policy));
2.9.2 Amazon Sidewalk stack statistics
The Amazon Sidewalk stack records the statistics from the time the user initializes and starts the Amazon Sidewalk stack to the time the Amazon Sidewalk stack is stopped and deinitialized. The Amazon Sidewalk stack does not store the statistics in non-volatile memory. The following are the statistics that are collected by the Amazon Sidewalk stack.
- Number of Messages sent: The number of messages sent successfully by the Amazon Sidewalk stack when the developer’s application calls
sid_put_msgAPI to send a message. See 3.8. - Number of Acknowledgements sent: The number of Acknowledgements sent by the Amazon Sidewalk stack when AWS IoT core for Amazon Sidewalk requests Acknowledgement to be sent for a downlink.
- Number of Messages failed to send: The number of messages failed to be sent by the Amazon Sidewalk stack when the developer’s application calls
sid_put_msgAPI to send a message. See 3.8. - Number of Retries: The number of retransmissions attempted by Amazon Sidewalk stack whent the developer’s application calls
sid_put_msgAPI to send a message with retries. See 3.8. - Number of Duplicates: The number of duplicates received by Amazon Sidewalk stack from AWS IoT core for Amazon Sidewalk. Irrespective of the configuration setting of the filter duplicates, the duplicates statistic is incremented whenever the Amazon Sidewalk stack receives a duplicate.
- Number of Messages received: The number of messages received by the Amazon Sidewalk stack from AWS IoT core for Amazon Sidewalk and notified to the developer using the
on_msg_receivedcallback. See section 2.10. - Number of Acknowledgements received: The number of acknowledgements received by the Amazon Sidewalk stack from AWS IoT core for Amazon Sidewalk and notified to the developer using the
on_msg_receivedcallback. See section 2.10.
/** The cumulative statistics of all links configured on the device */
struct sid_msg_statistics {
/** number of messages sent successfully. */
uint32_t tx;
/** number of acknowledments sent to AWS-IOT core. */
uint32_t acks_sent;
/** number of messages failed transmissions. */
uint32_t tx_fail;
/** number of message retries. */
uint32_t retries;
/** number of duplicates received. */
uint32_t duplicates;
/** number of messages received. */
uint32_t rx;
/** number of acknowledments received from AWS-IOT core. */
uint32_t acks_recv;
};
/** The metrics collected by the Sidewalk stack */
struct sid_statistics {
struct sid_msg_statistics msg_stats;
};
// Get statistics
struct sid_statistics stats = {0};
sid_error_t ret = sid_option(handle, SID_OPTION_GET_STATISTICS,
&stats, sizeof(stats));
// Clear statistics
ret = sid_option(handle, SID_OPTION_CLEAR_STATISTICS, NULL, 0);
2.9.3 Amazon Sidewalk stack Delayed Ack
The Amazon Sidewalk stack allows the developer to enable delayed ack and configure the delay. The default setting when the developer does not enable delayed ack is immediate ack.
/**
* Structure used to configure the delayed ack
*/
struct sid_delayed_ack_config {
/** time for the delayed ack in milliseconds. Range: 0-20000 msecs */
uint32_t delayed_ack;
/** indicates whether to get or set the delayed ack time.
* false: Get, true: Set */
bool is_set;
};
// IOCTL to set the time for delayed ack
// Set delayed ack parameters with time 10000 msecs and is_set = true
struct sid_delayed_ack_config delayed_ack_config = {
.delayed_ack = 10000,
.is_set = true
};
sid_error_t ret = sid_option(*cli_cfg.app_cxt->sidewalk_handle,
SID_OPTION_DELAYED_ACK_CONFIG,
&delayed_ack_config, sizeof(delayed_ack_config));
// IOCTL to get the time for delayed ack
struct sid_delayed_ack_config delayed_ack_config = {0};
sid_error_t ret = sid_option(*cli_cfg.app_cxt->sidewalk_handle,
SID_OPTION_DELAYED_ACK_CONFIG,
&delayed_ack_config, sizeof(delayed_ack_config));
2.9.4 Amazon Sidewalk Gateway Discovery and Selection Policy
The Gateway Discovery and Selection policy defines a gateway selection strategy during the FSK discovery process. There are several predefined policies optimized for different applications, as well as a user custom policy that allows the user to configure most of the parameters. For details on Discovery and selection policies, Please see Amazon Sidewalk Gateway Discovery and Selection Application Note.
/**
* Describes the gateway discovery policy modes for FSK
*/
enum sid_link_type_2_gw_discovery_policy {
/** Default policy applied. The GW discovery behavior
* is same as 1.16 SDK release which is to connect to
* the first beacon which has opt-in flag set to true
*/
SID_LINK_TYPE_2_GW_DISCOVERY_POLICY_DEFAULT = 0,
/** Policy optimized for latency to establish a connection,
* and therefore choose the first-one that is available.
*/
SID_LINK_TYPE_2_GW_DISCOVERY_POLICY_OPTIMIZED_FOR_FAST_CONNECTION = 1,
/** Policy optimized for highest reliability to establish a connection,
* the gateway with the best RSSI and healthy connection is selected.
*/
SID_LINK_TYPE_2_GW_DISCOVERY_POLICY_OPTIMIZED_FOR_RELIABLE_CONNECTION = 2,
/** Policy optimized for minimum power consumption. */
SID_LINK_TYPE_2_GW_DISCOVERY_POLICY_OPTIMIZED_FOR_POWER_SAVE = 3,
/** Policy for implementing a custom user scenario */
SID_LINK_TYPE_2_GW_DISCOVERY_POLICY_CUSTOM = 4,
/** Delimiter to enum sid_link_type_2_gw_discovery_policy */
SID_LINK_TYPE_2_GW_DISCOVERY_POLICY_LAST,
};
/** Describes parameters for gateway discovery backoff intervals */
struct sid_link_type_2_gw_discovery_backoff_params {
/** Number of elements in the backoff table */
uint8_t retry_arr_size;
/** Retry threshold for transition to the next intervals.
* A value of 255 means infinite number of retries */
uint8_t retry_threshold[SID_LINK_TYPE_2_GWD_BACKOFF_ARRAY_MAX_SIZE];
/** Scan duration in seconds */
uint16_t retry_scan_duration_s[SID_LINK_TYPE_2_GWD_BACKOFF_ARRAY_MAX_SIZE];
/** Sleep time in seconds between scanning */
uint16_t retry_sleep_time_s[SID_LINK_TYPE_2_GWD_BACKOFF_ARRAY_MAX_SIZE];
};
/**
* Describes parameters for the custom gateway discovery policy
*/
struct sid_link_type_2_gw_discovery_custom_policy_params {
/** Gateway discovery scanning timeout in seconds */
uint16_t scan_timeout_secs;
/** Continue to scan even after scan_timeout_secs has expired */
bool continue_scanning_after_fail;
/** Gateway discovery backoff parameters.
* Set this parameter to NULL to use default values.
*/
struct sid_link_type_2_gw_discovery_backoff_params *backoff_params;
/** Minimum RSSI level at which connection is allowed.
* Zero means the parameter is not used
*/
int8_t min_rssi_to_connect;
/** RSSI level at which EP initiates disconnection from the connected gateway.
* Should be less than min_rssi_to_connect
*/
int8_t threshold_rssi_to_disconnect;
/** Number of beacons to calculate the average RSSI level
* for threshold_rssi_to_disconnect. Zero means the parameter is not used
*/
int8_t threshold_rssi_msg_num;
/** The maximum number of consecutive beacons that can be missed
* before the EP notifies disconnection.
*/
uint8_t max_beacon_miss;
/** The maximum number of beacons the EP can skip listening */
uint8_t max_beacon_skip;
/** Use gateway load to calculate gw score */
bool use_gateway_load_for_selection;
/** Gateway load at which EP initiates disconnection from the connected gateway.
* The range is [0,3]. Zero means the parameter is not used
*/
uint8_t gateway_load_to_disconnect;
/** Use gateway connection health to calculate gw score */
bool use_gateway_connection_health_for_selection;
/** Use gateway transmit power rank to calculate gw score */
bool use_gateway_tx_power_rank_for_selection;
};
/**
* The structure used to configure the gateway discovery policy
*/
struct sid_link_type_2_gw_discovery_policy_config {
/** Gateway discovery policy */
enum sid_link_type_2_gw_discovery_policy policy;
/** Parameters for the custom gateway discovery policy */
struct sid_link_type_2_gw_discovery_custom_policy_params *policy_params;
/** True: Set policy config, False: Get policy config */
bool is_set;
};
/**
* Describes the LINK2 GW Discovery events.
* These events are notified to the developer through network control events
*/
enum sid_link_type_2_gw_discovery_event {
/** Event indicating gateway under the selected discovered policy is not found */
SID_LINK_TYPE_2_GW_DISCOVERY_EVENT_DISC_FAILED = 0,
/** Event indicating the gateway is selected and beacon sync is done */
SID_LINK_TYPE_2_GW_DISCOVERY_EVENT_BEACON_SYNC = 1,
/** Event indicating the beacon sync was lost with the selected gateway */
SID_LINK_TYPE_2_GW_DISCOVERY_EVENT_BEACON_SYNC_LOST = 2,
};
// Examples of IOCTL to set/get gateway discovery and selection policy
// Set gateway discovery and selection policy to
// SID_LINK_TYPE_2_GW_DISCOVERY_POLICY_OPTIMIZED_FOR_FAST_CONNECTION
struct sid_link_type_2_gw_discovery_policy_config policy = {
.is_set = true,
.policy = SID_LINK_TYPE_2_GW_DISCOVERY_POLICY_OPTIMIZED_FOR_FAST_CONNECTION,
};
sid_error_t ret = sid_option(handle,
SID_OPTION_LINK_TYPE_2_GW_DISCOVERY_POLICY,
&policy, sizeof(policy));
// Get current gateway discovery and selection policy
struct sid_link_type_2_gw_discovery_policy_config policy = {
.is_set = false,
};
sid_error_t ret = sid_option(handle,
SID_OPTION_LINK_TYPE_2_GW_DISCOVERY_POLICY,
&policy, sizeof(policy));
2.9.5 Amazon Sidewalk BLE User Configuration
The BLE configuration for establishing and maintaining connections with Amazon Sidewalk Gateways is highly flexible and can be customized by developers to suit a variety of use cases.
The following parameter constraints apply:
Advertising Parameters:
fast_interval: In units of 0.625 ms, range: [32, 8192] (20ms to 5.12s)fast_timeout: In units of 10 ms, range: [0, 65535], 0 means indefiniteslow_interval: In units of 0.625 ms, range: [1600, 8192] (1s to 5.12s)slow_timeout: In units of 10 ms, range: [0, 65535], 0 means indefinite
Connection Parameters:
min_conn_interval: In units of 1.25 ms, range: [12, 3200] (15ms to 4s)max_conn_interval: In units of 1.25 ms, range: [12, 3200] (15ms to 4s), must be >=min_conn_intervalslave_latency: Range: [0, 499]conn_sup_timeout: In units of 10 ms, range: [10, 3200] (100ms to 32s), must satisfy:conn_sup_timeout * 10 > 2 * max_conn_interval * 1.25 * (slave_latency + 1)
Inactivity Timeout:
inactivity_timeout: In seconds, range: [1, 3600] (1 second to 1 hour)
/**
* Describes the BLE configuration type
*/
enum sid_ble_user_config_type {
/** BLE advertising configuration */
SID_BLE_USER_CFG_ADV,
/** BLE connection parameter configuration */
SID_BLE_USER_CFG_CONN,
/** BLE advertising and connection parameter configuration */
SID_BLE_USER_CFG_ADV_AND_CONN,
/** BLE inactivity timeout configuration */
SID_BLE_USER_CFG_INACTIVITY_TIMEOUT,
};
/**
* BLE configuration struct
*/
typedef struct sid_ble_user_config {
/** BLE advertising configuration */
sid_ble_cfg_adv_param_t adv_param;
/** BLE connection parameter configuration */
sid_ble_cfg_conn_param_t conn_param;
/** BLE configuration command, set config = true, get config = false */
bool is_set;
/** BLE configuration type */
enum sid_ble_user_config_type cfg_type;
/** BLE inactivity timeout in seconds, range: [1, 3600] */
uint32_t inactivity_timeout;
} sid_ble_user_config_t;
// IOCTL to get the current BLE configuration
sid_ble_user_config_t get_config = {
.is_set = false,
.cfg_type = SID_BLE_USER_CFG_ADV_AND_CONN
};
sid_error_t ret = sid_option(handle, SID_OPTION_BLE_USER_CONFIG,
&get_config, sizeof(get_config));
// IOCTL to set the BLE configuration
// Example of BLE configuration
sid_ble_user_config_t set_config = {
.is_set = true,
.cfg_type = SID_BLE_USER_CFG_ADV_AND_CONN,
.adv_param = {
.type = AMA_SERVICE,
.fast_enabled = true,
.slow_enabled = true,
/** In units of 0.625 ms, range: [32, 8192] */
.fast_interval = 160,
/** In units of 10 ms, range: [0, 65535], 0 means indefinite */
.fast_timeout = 1000,
/** In units of 0.625 ms, range: [1600, 8192] */
.slow_interval = 1600,
/** In units of 10 ms, range: [0, 65535], 0 means indefinite */
.slow_timeout = 0,
},
.conn_param = {
/** In units of 1.25 ms, range: [12, 3200] */
.min_conn_interval = 16,
/** In units of 1.25 ms, range: [12, 3200] */
.max_conn_interval = 80,
/** Range: [0, 499] */
.slave_latency = 0,
/** In units of 10 ms, range: [10, 3200] */
.conn_sup_timeout = 400,
},
.inactivity_timeout = 30, // 30 seconds
};
sid_error_t ret = sid_option(handle, SID_OPTION_BLE_USER_CONFIG,
&set_config, sizeof(set_config));
2.9.5.1 Platform Notes: Nordic NCS
Nordic Semiconductor has not yet support for runtime BLE configuration in their nRF Connect SDK (NCS) platform. As a result, the following limitations apply when using SID_OPTION_BLE_USER_CONFIG on Nordic NCS-based devices:
- Runtime advertisement parameter updates are not supported. The NCS BLE stack does not support modifying advertisement parameters at runtime. Advertisement parameters must be configured at compile time through Kconfig or devicetree overlays.
- Runtime connection parameter updates are not supported. The NCS BLE stack does not support modifying connection parameters at runtime. Connection parameters must be configured at compile time.
- Inactivity timeout configuration remains functional. The
SID_BLE_USER_CFG_INACTIVITY_TIMEOUTconfiguration type is handled at the Sidewalk stack level and is not affected by this platform limitation. - Backward compatibility with legacy Nordic devices. Devices using the older nRF5 SDK (e.g., nRF52832, nRF52840 with the native SoftDevice-based BLE stack) continue to support full runtime BLE configuration through
SID_OPTION_BLE_USER_CONFIG. Applications targeting both NCS and legacy nRF5 SDK platforms should account for this difference in behavior.
Developers migrating from the nRF5 SDK to NCS should review their BLE configuration strategy and move runtime parameter adjustments to compile-time configuration where applicable.
2.9.6 BLE Device-to-Device (D2D) Only Mode
The Amazon Sidewalk stack allows the developer to configure BLE to operate in device-to-device (D2D) only mode. When enabled, BLE will only be used for direct device-to-device communication rather than cloud connectivity through gateways.
/**
* Structure to configure BLE D2D only mode
*/
typedef struct sid_ble_d2d_config {
/** True: Set configuration, False: Get configuration */
bool is_set;
/** True: Use BLE for D2D only, False: Normal operation */
bool set_d2d_only;
} sid_ble_d2d_config_t;
// Get current D2D configuration
sid_ble_d2d_config_t get_d2d_config = {
.is_set = false
};
sid_error_t ret = sid_option(handle, SID_OPTION_USE_BLE_FOR_D2D_ONLY,
&get_d2d_config, sizeof(get_d2d_config));
// Set BLE to D2D only mode
sid_ble_d2d_config_t set_d2d_config = {
.is_set = true,
.set_d2d_only = true // Enable D2D only mode
};
ret = sid_option(handle, SID_OPTION_USE_BLE_FOR_D2D_ONLY,
&set_d2d_config, sizeof(set_d2d_config));
2.9.7 Amazon Sidewalk ID
The Sidewalk ID returned by this option is the Endpoint’s Sidewalk ID. It does not change with the key the Endpoint uses on a sub-GHz link.
/**
* Structure to hold Sidewalk ID
*/
struct sid_id {
#define MAX_SIDEWALK_ID_LEN 7
/** Array that holds the Sidewalk ID */
uint8_t id[MAX_SIDEWALK_ID_LEN];
/* Len of the Sidewalk ID */
size_t len;
};
// Get Sidewalk ID
struct sid_id id;
sid_error_t ret = sid_option(handle, SID_OPTION_GET_SIDEWALK_ID,
&id, sizeof(id));
2.9.8 Amazon Sidewalk Downlink Route Validity and Keep-Alive Interval
The Amazon Sidewalk stack allows the developer to configure the downlink route validity (DLRV) time for Sub-GHz links on the Amazon Sidewalk cloud, and, in the same structure, the keep-alive / network-sync interval (nwsync_time). The default DLRV setting is 15 minutes for LoRa and 1080 minutes for FSK when the developer does not configure it. The nwsync_time interval, when left at 0, is derived from the DLRV and the active link profile: on FSK it is the DLRV minus 5 minutes, on LoRa Profile B it is the network-sync interval (default 5 minutes), and on LoRa Profile C it is 24 hours. When set explicitly, its valid range depends on the enabled sub-GHz links (see the list below): LoRa Profile B accepts 1–240 minutes, while FSK and LoRa Profile C accept up to MAX_FSK_KA_INTERVAL_MINS (1440 minutes), which is why nwsync_time is a uint16_t — that range exceeds 255.
SID_OPTION_DL_ROUTE_VALIDITY validates only the upper bound of nwsync_time (SID_ERROR_INVALID_ARGS if it exceeds the per-link maximum below), not a lower bound. An explicitly set value below 2 minutes (e.g. 1) is therefore accepted, stored and reported back as-is by a get, but the keep-alive never runs more often than once every 2 minutes: the stack applies a 2-minute floor to the interval it uses, whether that interval was set explicitly or derived.
When LoRa is in sid_config.link_mask, sid_init() takes the initial interval from sid_sub_ghz_links_config.link3_b_nwsync_time if it is within 1–240 minutes, and otherwise uses the 5-minute default (DEF_LINK3_PROFILE_B_NW_SYNC_TIME_MINS). On LoRa Profile B the interval is therefore unset only if the application explicitly sets nwsync_time back to 0 (SID_NWSYNC_TIME_NOT_SET) through SID_OPTION_DL_ROUTE_VALIDITY; a subsequent get then reports 2 minutes until the application sets a non-zero value again. FSK and LoRa Profile C do not use link3_b_nwsync_time: they use their derived default (DLRV minus 5 minutes, and 24 hours) until the application sets nwsync_time through SID_OPTION_DL_ROUTE_VALIDITY.
The accepted upper bound for nwsync_time depends on which sub-GHz links are enabled in sid_config.link_mask, because the two links share this single interval value (FSK and LoRa never transmit the keep-alive concurrently — they time-division the sub-GHz radio):
- FSK only: up to
MAX_FSK_KA_INTERVAL_MINS(1440 minutes). - LoRa only, Profile C: up to 1440 minutes (24 hours, matching Profile C’s default).
- LoRa only, any other profile (in practice, Profile B): up to
MAX_LINK3_PROFILE_B_NW_SYNC_TIME_MINS(240 minutes). - Both FSK and LoRa enabled (
link_maskcontains bothSID_LINK_TYPE_2andSID_LINK_TYPE_3): the stricter 240-minute bound applies, so the single shared value stays valid for the LoRa Profile B time-slices too.
In the single-link build variants (section 2.15) only one sub-GHz link exists, so only that link’s bound applies and the mixed-mode row does not.
The keep-alive on a Sub-GHz link is armed automatically once the link is synchronized — on FSK, and on LoRa in Profile B or Profile C (LoRa Profile A has no keep-alive); there is no separate call to turn it on. The stack skips a keep-alive when an uplink that requested an acknowledgement was reported sent through on_msg_sent less than one interval earlier, and sends the next keep-alive one interval after that uplink; a skipped keep-alive produces no SID_CONTROL_EVENT_KA_ACK_STATUS event. Each keep-alive requests an acknowledgement, and the stack tracks consecutive misses. The acknowledgement result of each keep-alive is reported to the developer’s application through the on_control_event_notify callback with the SID_CONTROL_EVENT_KA_ACK_STATUS event (section 2.10). A change to the DLRV, whether negotiated by the Amazon Sidewalk cloud during join or set locally by the application, is reported through the same callback with the SID_CONTROL_EVENT_DL_ROUTE_VALIDITY_CONFIG_UPDATE event, whose event_data points to a uint16_t holding the updated DLRV time in minutes.
The miss threshold is 3 consecutive missed keep-alives. Each keep-alive is sent with one retry and a 60-second time-to-live. On each unacknowledged keep-alive the stack reports ack_received=false, then increments the miss counter. Below the threshold, the stack does not wait a full interval before retrying: it cancels the pre-armed full-interval timer and reschedules the next attempt at a shorter capped retry interval, so all attempts complete before the downlink route expires. On reaching the threshold, the stack tears the link down — clearing the link from link_status_mask, stopping the KA timer, resetting the miss counter, forcing a rejoin, and firing on_status_changed (link down). This is the same notification the application would see for any other outage, so it cannot be used on its own to attribute the cause to KA.
The keep-alive can never be acknowledged when the link profile is uplink-only, because no receive window is opened after an uplink; see the Amazon Sidewalk Sub-GHz Device Profiles Application Note.
sid_option() (section 3.11) with SID_OPTION_DL_ROUTE_VALIDITY and a struct sid_dlrv_config (below) configures the DLRV and nwsync_time. The keep-alive payload is part of the static sub-GHz configuration (sid_sub_ghz_links_config.ka_payload, section 2.9.10), and the keep-alive acknowledgement is reported through SID_CONTROL_EVENT_KA_ACK_STATUS (end of this section and section 2.10). SID_OPTION_DL_ROUTE_VALIDITY returns generic sid_error_t codes; there are no keep-alive-specific error codes:
| Return code | Condition |
|---|---|
SID_ERROR_INVALID_ARGS | handle is NULL/uninitialized, len is not sizeof(struct sid_dlrv_config), or a value in data is out of range (DLRV time, or nwsync_time above its upper bound). |
SID_ERROR_NOSUPPORT | The build enables neither FSK nor LoRa (SID_SDK_CONFIG_ENABLE_LINK_TYPE_2 and _3 both 0), so the option is not available. A link that is not in sid_config.link_mask does not cause SID_ERROR_NOSUPPORT: the values are applied only to the enabled links. |
SID_ERROR_NONE | Success. |
Public constants referenced in this section (declared in sid_900_cfg.h unless noted):
| Constant | Value | Meaning |
|---|---|---|
MIN_DL_ROUTE_VALIDITY_TIME_MINS | 1 | Minimum DLRV time. |
DEF_DL_ROUTE_VALIDITY_TIME_MINS | 15 | Default DLRV time (LoRa). |
DEF_DL_ROUTE_VALIDITY_TIME_MINS_FSK | 1080 | Default DLRV time (FSK). |
MAX_DL_ROUTE_VALIDITY_TIME_MINS | 1440 | Maximum DLRV time. |
MIN_LINK3_PROFILE_B_NW_SYNC_TIME_MINS | 1 | Minimum LoRa Profile B network-sync (KA) interval. |
DEF_LINK3_PROFILE_B_NW_SYNC_TIME_MINS | 5 | Default LoRa Profile B network-sync interval. |
MAX_LINK3_PROFILE_B_NW_SYNC_TIME_MINS | 240 | Maximum LoRa Profile B network-sync interval. |
SID_NWSYNC_TIME_NOT_SET | 0 | Sentinel meaning “not set — use link default” for nwsync_time. |
MAX_FSK_KA_INTERVAL_MINS | 1440 | Maximum FSK-only KA interval. |
/**
* The structure used to configure the DL route validity
*/
struct sid_dlrv_config {
/** time for the DL route validity in mins. Range: 1 ~ 1440 mins */
uint16_t time;
/** KA / NW-sync interval in mins. LoRa Pb: 1~240. FSK: up to MAX_FSK_KA_INTERVAL_MINS.
* 0 = not set (use link default). uint16_t to hold FSK values > 255. */
uint16_t nwsync_time;
/** indicates whether to get or set the dlrv time. false: Get, true: Set */
bool is_set;
};
// handle: the struct sid_handle * returned by sid_init()
// Set the downlink route validity time to 30 mins and the keep-alive interval to 5 mins
struct sid_dlrv_config dlrv_set = {
.time = 30,
.nwsync_time = 5,
.is_set = true
};
sid_error_t ret = sid_option(handle, SID_OPTION_DL_ROUTE_VALIDITY, &dlrv_set, sizeof(dlrv_set));
// Get the current downlink route validity time and keep-alive interval
struct sid_dlrv_config dlrv_get = {0};
ret = sid_option(handle, SID_OPTION_DL_ROUTE_VALIDITY, &dlrv_get, sizeof(dlrv_get));
On a successful set, the new DLRV / nwsync_time values are applied to the active sub-GHz link.
The keep-alive acknowledgement status is reported through the following structure, delivered as the event_data of the SID_CONTROL_EVENT_KA_ACK_STATUS control event:
/**
* Reports whether a link keep-alive received an application-layer ACK.
* event_data of SID_CONTROL_EVENT_KA_ACK_STATUS points to this structure.
*/
struct sid_ka_ack_status {
/** The link type on which the keep-alive was sent */
enum sid_link_type link_type;
/** true if the app-layer ACK was received, false on timeout */
bool ack_received;
};
The struct is stack-allocated by the Amazon Sidewalk stack for the duration of the callback only — the developer’s application shall not retain the event_data pointer beyond the callback’s return.
// Observe keep-alive acknowledgement in the control-event callback
void on_control_event_notify(const struct sid_control_event_data *evt, void *ctx)
{
if (evt->event_type == SID_CONTROL_EVENT_KA_ACK_STATUS) {
const struct sid_ka_ack_status *s = evt->event_data;
// s->link_type, s->ack_received
} else if (evt->event_type == SID_CONTROL_EVENT_DL_ROUTE_VALIDITY_CONFIG_UPDATE) {
uint16_t dlrv_mins = *(uint16_t *)evt->event_data;
}
}
2.9.9 Amazon Sidewalk Sub-GHz User Control
This option is included in this guide because it affects RX-window availability — and therefore whether a link KA can be acknowledged (section 2.9.8) — but it does not configure the KA. It does not touch the KA payload, interval, or acknowledgement state, and does not change the persistent link profile.
The Amazon Sidewalk stack allows the developer to send user control commands to Sub-GHz links (FSK and LoRa). This option provides a mechanism for advanced users to send custom control commands to the Sub-GHz radio layers.
/**
* Describes the SUB-GHZ user control commands.
*/
enum sid_sub_ghz_ctl_cmd {
/** Reserved command - not for application use */
SID_SUB_GHZ_CTL_CMD_RESERVED,
/** Request to terminate ongoing RX operation */
SID_SUB_GHZ_CTL_CMD_RX_TERMINATE_REQUEST,
/** Maximum command value */
SID_SUB_GHZ_CTL_CMD_MAX,
};
/**
* Structure used for Sub-GHz user control commands
*/
struct sid_sub_ghz_user_control {
/** Sub-GHz control command type */
enum sid_sub_ghz_ctl_cmd sub_ghz_ctl_cmd;
};
// Example: Send RX terminate request to Sub-GHz link
struct sid_sub_ghz_user_control user_cmd = {
.sub_ghz_ctl_cmd = SID_SUB_GHZ_CTL_CMD_RX_TERMINATE_REQUEST
};
sid_error_t ret = sid_option(handle,
SID_OPTION_SUB_GHZ_USER_CONTROL,
&user_cmd, sizeof(user_cmd));
2.9.10 Amazon Sidewalk Keep-Alive Payload
The developer’s application can set the payload carried by the periodic keep-alive uplink on the FSK link, and on the LoRa link in Profile B or Profile C. The payload is part of the static sub-GHz configuration: the ka_payload member of struct sid_sub_ghz_links_config, passed to sid_init() through sid_config.sub_ghz_link_config. When ka_payload.data is NULL or ka_payload.len is 0, the keep-alive carries the default payload, a single byte 0x00. Applications that do not set ka_payload keep this default behavior and need no change.
The buffer is owned by the developer’s application and is not copied. The Amazon Sidewalk stack reads it each time it sends a keep-alive, so the buffer shall remain valid until sid_deinit() is called. The application may change the buffer contents, ka_payload.data or ka_payload.len at any time after sid_init(); the next keep-alive uses the new values, and no API call is needed.
The length shall not exceed SID_KA_PAYLOAD_MAX_SIZE (19) bytes. SID_KA_PAYLOAD_MAX_SIZE (19) is the largest keep-alive payload that fits on both sub-GHz links; it equals the LoRa link MTU. sid_init() returns SID_ERROR_INVALID_ARGS if ka_payload.len exceeds SID_KA_PAYLOAD_MAX_SIZE.
/** Maximum keep-alive payload size in bytes */
#define SID_KA_PAYLOAD_MAX_SIZE 19
/**
* Keep-alive payload on FSK and LoRa Profile B / Profile C links.
* Part of struct sid_sub_ghz_links_config.
*/
struct sid_ka_payload_config {
/** Pointer to application-owned static buffer. NULL to use the default payload. */
const uint8_t *data;
/** Length of the payload in bytes (0 ~ SID_KA_PAYLOAD_MAX_SIZE). 0 to use the default payload. */
uint8_t len;
};
struct sid_sub_ghz_links_config {
/* ... existing members ... */
struct sid_ka_payload_config ka_payload; /* trailing member */
};
// Set the keep-alive payload at initialization
static uint8_t ka_buf[4] = { 0x01, 0x02, 0x03, 0x04 }; // app-owned, static
static struct sid_sub_ghz_links_config sub_ghz_cfg = {
/* ... other members ... */
.ka_payload = { .data = ka_buf, .len = sizeof(ka_buf) },
};
struct sid_config config = { /* ... */ .sub_ghz_link_config = &sub_ghz_cfg };
struct sid_handle *handle = NULL;
sid_error_t ret = sid_init(&config, &handle);
// Change the payload later: edit the buffer or the config; the next keep-alive uses it
ka_buf[0] = 0x05;
sub_ghz_cfg.ka_payload.len = 2;
// Return to the default payload
sub_ghz_cfg.ka_payload.len = 0;
2.9.11 LoRa Device Profile Parameters
Set Device Profile and Get Device Profile, described in section 2.9, exchange a struct sid_device_profile. Its unicast parameters are:
struct sid_device_profile_unicast_params {
/** Used to indicate profile type of the device */
enum sid_device_profile_id device_profile_id;
/** Used to indicate the number of RX windows opened by the device */
enum sid_rx_window_count rx_window_count;
/** Used to indicate the beacon interval in units (10080ms per unit) */
uint8_t beacon_interval_unit;
/** Used to indicate the frequency of RX windows opened by the device (in ms) */
union sid_unicast_window_interval {
/** Used to indicate the frequency of RX windows opened by the device (in ms) in synchronous mode */
enum sid_link2_rx_window_separation_ms sync_rx_interval_ms;
/** Used to indicate the frequency of RX windows opened by the device (in ms) in asynchronous mode */
enum sid_link3_rx_window_separation_ms async_rx_interval_ms;
} unicast_window_interval;
/** Used to indicate the TX/RX wake up configuration of the device */
enum sid_unicast_wakeup_type wakeup_type;
/** Used to indicate the RX windows open duration of the device (in sec) in synchronous mode */
uint32_t l2_rx_duration_sec;
/** Used to indicate the frequency of RX windows opened by the device (in ms) in MDR mode */
enum sid_link3_rx_window_separation_ms l3_mdr_rx_window_interval_ms;
};
In the member name and the comment above, MDR abbreviates the higher data rate; see section 2.11.2. unicast_window_interval is a union: the developer’s application sets sync_rx_interval_ms for FSK or async_rx_interval_ms for LoRa, never both. l3_mdr_rx_window_interval_ms is not part of that union, so it and async_rx_interval_ms can hold different values at the same time.
Note that SID_RX_WINDOW_CNT_INFINITE and SID_RX_WINDOW_CNT_ZERO are both the value 0; which meaning applies is determined by the profile ID.
For LoRa, the following parameters can be configured:
wakeup_type: shall beSID_TX_AND_RX_WAKEUP(3). Every other value ofenum sid_unicast_wakeup_type, includingSID_NO_WAKEUP(0), is rejected, so leaving this member zero-initialized is not accepted.unicast_window_interval.async_rx_interval_ms: the interval at which the Endpoint opens RX windows. UnderSID_LINK3_PROFILE_AandSID_LINK3_PROFILE_B, the only value accepted at the default data rate isSID_LINK3_RX_WINDOW_SEPARATION_3(5000 ms), or 0, which the Amazon Sidewalk stack replaces with it;SID_LINK3_RX_WINDOW_SEPARATION_5(500 ms) andSID_LINK3_RX_WINDOW_SEPARATION_2(1000 ms) are accepted only at the higher data rate. UnderSID_LINK3_PROFILE_Cthe value supplied in this member is not used: Set Device Profile replaces it withSID_LINK3_RX_WINDOW_SEPARATION_CONTINUOUS(0), and once the Join procedure has completed the Endpoint receives continuously. When the Amazon Sidewalk stack brings the link up at the higher data rate, or moves it to the higher data rate before the Join procedure has completed, it sets the receive cadence itself under every profile, including this one, until that Join completes; see section 2.11.2. Because a shorter interval is rejected underSID_LINK3_PROFILE_AandSID_LINK3_PROFILE_Bwhile the link operates at the default data rate, set this member toSID_LINK3_RX_WINDOW_SEPARATION_3or 0 and express any shorter-interval preference throughl3_mdr_rx_window_interval_ms, described below.l3_mdr_rx_window_interval_ms: the RX window interval the developer’s application prefers while the Amazon Sidewalk stack operates the LoRa link at the higher data rate; see section 2.11.2. The accepted values are 0,SID_LINK3_RX_WINDOW_SEPARATION_5(500 ms),SID_LINK3_RX_WINDOW_SEPARATION_2(1000 ms) andSID_LINK3_RX_WINDOW_SEPARATION_3(5000 ms); any other value, includingSID_LINK3_RX_WINDOW_SEPARATION_4(10000 ms), is rejected under every LoRa profile. A value of 0 means no preference is pending: it leaves the interval in effect unchanged and does not request a continuous RX window, even though 0 is also the value ofSID_LINK3_RX_WINDOW_SEPARATION_CONTINUOUS. If the link is already at the higher data rate, Set Device Profile applies the preference toasync_rx_interval_mswithin the same call; otherwise the preference is retained and applied the next time the link moves to the higher data rate, or at the next start-up if the link starts at that rate. When the link moves away from the higher data rate, the interval in effect returns toSID_LINK3_RX_WINDOW_SEPARATION_3and the preference is retained. The preference has no effect underSID_LINK3_PROFILE_C, although it is still stored and returned by Get Device Profile. A shorter interval makes the Endpoint open receive windows more often while it is receiving, which raises its receive power consumption over that period; choose the longest interval that meets the product’s downlink latency requirement. UnderSID_LINK3_PROFILE_Athe Endpoint opens receive windows only for a bounded period after each uplink: where that period is derived fromrx_window_countand the interval, a shorter interval shortens the downlink opportunity rather than adding receive windows, and where the Endpoint instead receives for a fixed duration, a shorter interval adds receive windows within that duration. UnderSID_LINK3_PROFILE_Bthe downlink opportunity does not depend on the interval.
Set Device Profile reads and writes the structure the developer’s application passes: as described above, it can replace rx_window_count and unicast_window_interval.async_rx_interval_ms. The developer’s application shall not reuse the structure across calls without re-initializing it, and shall call Get Device Profile for the values in effect.
Set Device Profile returns SID_ERROR_INVALID_ARGS if the Sidewalk handle is NULL, if the Amazon Sidewalk stack is not initialized, if len is not sizeof(struct sid_device_profile), or if unicast_params.device_profile_id is not a profile ID of a link in link_mask. It returns SID_ERROR_INVALID_STATE if the Endpoint is not registered, if the LoRa link has not been initialized, or if the LoRa link has been started but has not completed network synchronization. It returns SID_ERROR_INCOMPATIBLE_PARAMS if any of the three LoRa parameters above is outside its accepted set, or if the profile ID is SID_LINK3_PROFILE_D; the return code does not identify which parameter was rejected.
When link_mask contains both FSK and LoRa, the Amazon Sidewalk stack initializes the LoRa link only when it alternates onto that link, so apply the LoRa device profile after the Amazon Sidewalk stack reports SID_LINK_TYPE_3 in link_status_mask; see section 2.6. When link_mask contains LoRa without FSK, sid_init initializes the link, so only the other two conditions above apply: the Endpoint shall be registered, and after sid_start the call is accepted only once the Amazon Sidewalk stack reports SID_LINK_TYPE_3 in link_status_mask.
An accepted change to the device profile on a started, network synchronized LoRa link causes the Endpoint to repeat the Join procedure; for what the developer’s application observes, see section 2.7.3. Until the Join completes, Get Device Profile returns the previous profile, and a Join that does not complete leaves the profile unchanged. Once the Join completes, the profile, including l3_mdr_rx_window_interval_ms, persists across a device reset and is restored at the next start-up.
2.10 Stack Notifications
The Sid API notifies the developer’s application through a set of callbacks. The developer is required to register these calllbacks with the Sid API when initializing the Amazon Sidewalk stack. The following events are notified by the Amazon Sidewalk stack:
- on event: the stack does not create tasks for processing its internal events. The stack processes its internal events in the context supplied by the developer’s application. In order to process its pending internal events, the stack notifies the developer’s application through the on event callback. On getting the on event callback, the developer’s application is required to call the
sid_processAPI to cause the stack to process the pending events. The on event callback can be called in ISR context, and the arguments in the callback indicate whether the on event callback is being called in an ISR context or not. - on msg received: The stack uses this callback to notify the developer’s application that a message has arrived. The on msg received callback is always called in the context in which
sid_processis called. -
on msg sent: When the stack sends the message over the desired link, the stack notifies the developer’s application that it has sent the message successfully using the on msg sent callback. Note that the on msg sent callback does not indicate the message has been received by the AWS IoT application. The on msg sent callback only indicates that the message has been sent over the link successfully and no over the air transmission errors have occurred. The notification trigger for the on msg sent callback to the developer’s application by the stack is different for each link type that is used to send the message:
- BLE: on a BLE link, when the BLE Endpoint receives an acknowledgement from a BLE Gateway, the on msg sent callback is called.
- FSK: on an FSK link, when the FSK Endpoint receives a link layer acknowledgement from an FSK Gateway, the on msg sent callback is called.
- LoRa: on a LoRa link the developer’s application shall not treat the on msg sent callback as evidence that a Gateway received the message. Link layer acknowledgement and link layer retransmission are used only while a Gateway Session Key is active on the link, see section 2.11.1; otherwise the callback is called as soon as the message is transferred over the air by the low level LoRa radio driver. The Amazon Sidewalk stack does not report a LoRa transmission failure at the time it occurs; a message that is not delivered within its Time to Live period is reported through the on send error callback with
SID_ERROR_TIMEOUT.
-
on send error: The on send error message is sent if the stack cannot send the message for any of the following reasons.
- Link is not connected: If the link on which the message is being sent is disconnected, the on send error callback is called.
- AWS IoT Core for Amazon Sidewalk has not sent Acknowledgement: If the message requires a Transport Ack from AWS IoT Core for Amazon Sidewalk and the Transport Ack was not received in the configured Time to live period, the on send error callback is called.
Note that on msg sent and on send error are not mutually exclusive. There could be instances where the message could be sent over the air to the Gateway, but the message might not make it to the destination of AWS IoT Core for Amazon Sidewalk. In this scenario, on send error and on msg sent are called with the same message ID. This indicates that even though the message was able to be sent over the air to the Gateway, the message did not reach AWS IoT Core for Amazon Sidewalk within the Time to live period configured for that message.
-
on status changed: The on status changed callback is called when the Amazon Sidewalk stack state changes. The Amazon Sidewalk state is comprised of the following as explained in the previous sections.
- Connection status of the link
- Time sync status
- Registration status
When any of these items change status, the on status changed callback is called.
- on factory reset This callback is called when the AWS IoT application has de-registered the device or the developer’s application has called
sid_set_factory_reset. The Amazon Sidewalk stack removes all the non-volatile data stored during registration, and then uses the on factory reset callback to notify the developer’s application that the Endpoint is de-registered from the Amazon Sidewalk. On the lite build variants the Endpoint returns to the factory-registered state instead, see section 2.3.5. - on control event This callback is called when the Sidewalk stack notifies the developer application on control events. The control events that the Sidewalk stack notifies are when the developer’s application exceeds the traffic threshold limits
/**
* The set of callbacks a developer's application can register through
* sid_init().
*/
struct sid_event_callbacks {
/** Object used to store user data */
void *context;
/**
* Callback to invoke when any Sidewalk event occurs.
*
* The Sidewalk stack invokes this callback when there is at least one
* event to process, including internal events. Upon receiving this
* callback the sid api user is required to schedule
* a call to sid_process() within the application's
* main loop or running context.
*
* @warning sid_process() MUST NOT be called from within the
* #on_event callback to avoid re-entrancy and recursion problems.
*
* @see sid_process
*
* @param[in] in_isr true if invoked from within an ISR context,
* false otherwise.
* @param[in] context The context pointer given in
* sid_event_callbacks.context
*/
void (*on_event)(bool in_isr, void *context);
/**
* Callback to invoke when a message from Sidewalk is received.
*
* @warning sid_put_msg() MUST NOT be called from within the
* #on_msg_received callback to avoid re-entrancy and recursion problems.
*
* @param[in] msg_desc A pointer to the received message descriptor, which
* is never NULL.
* @param[in] msg A pointer to the received message payload, which is
* never NULL.
* @param[in] context The context pointer given in
* sid_event_callbacks.context
*/
void (*on_msg_received)(const struct sid_msg_desc *msg_desc,
const struct sid_msg *msg, void *context);
/**
* Callback to invoke when a message was successfully delivered to
* Sidewalk.
*
* @param[in] msg_desc A pointer to the sent message descriptor,
* which is never NULL.
* @param[in] context The context pointer given in
* sid_event_callbacks.context
*/
void (*on_msg_sent)(const struct sid_msg_desc *msg_desc, void *context);
/**
* Callback to invoke when a queued message failed to be delivered to
* Sidewalk.
*
* A developer's application can use this notification to schedule
* retrying sending a message, or invoke other error handling.
*
* @see sid_put_msg
*
* @warning sid_put_msg() MUST NOT be called from within the
* #on_send_error callback to avoid re-entrancy and recursion problems.
*
* @param[in] error The error code associated with the failure
* @param[in] msg_desc A pointer to the unsent message descriptor,
* which is never NULL.
* @param[in] context The context pointer given in
* sid_event_callbacks.context
*/
void (*on_send_error)(sid_error_t error,
const struct sid_msg_desc *msg_desc,
void *context);
/**
* Callback to invoke when the Sidewalk stack status changes.
*
* Once sid_start() is called, a #SID_STATE_READY status indicates
* the stack is ready to accept messages sid_put_msg().
*
* When receiving #SID_STATE_ERROR, sid api user can
* call sid_get_error() from within the #on_status_changed callback
* context to obtain more detail about the error condition.
* Receiving this status means the Sidewalk stack encountered a fatal
* condition and won't be able to proceed. Hence, this notification is
* mostly for diagnostic purposes.
*
* @param[in] status The current status, valid until the next invocation
* of this callback.
* @param[in] context The context pointer given in
* sid_event_callbacks.context
*/
void (*on_status_changed)(const struct sid_status *status, void *context);
/**
* Callback to invoke when the Sidewalk stack
* receives a Sidewalk factory reset from the cloud service.
*
* When the factory reset is triggered from cloud service
* or #sid_set_factory_reset api call, the Sidewalk stack clears
* its configuration from the non volatile storage
* and resets its state accordingly.
* This callback is then called by the Sidewalk stack
* to notify the sid api user of Sidewalk network factory reset
*
* The device needs to successfully complete device registration with the
* cloud services for the Sidewalk stack to send and receive messages
*
* @param[in] context The context pointer given in
* sid_event_callbacks.context
*/
void (*on_factory_reset)(void *context);
/**
* Callback to invoke when the Sidewalk library notifies network control
* event.
*
* Sidewalk stack notifies certain control events to the user
*/
void (*on_control_event_notify)(const struct sid_control_event_data *data,
void *context);
};
The following control events, delivered through the on_control_event_notify callback registered during sid_init(), are related to the keep-alive feature and extend the sid_control_event_type enumeration:
/** Event indicating change in DL route validity configuration.
* event_data points to a uint16_t holding the DLRV time in minutes. */
SID_CONTROL_EVENT_DL_ROUTE_VALIDITY_CONFIG_UPDATE = 3,
/** Event indicating a KA ACK was received or timed out on a Sub-GHz link.
* event_data points to struct sid_ka_ack_status. */
SID_CONTROL_EVENT_KA_ACK_STATUS = 6,
SID_CONTROL_EVENT_KA_ACK_STATUS is delivered only if the developer’s application has registered an on_control_event_notify callback; it is an observability hook and does not affect the keep-alive acknowledgement tracking or link teardown behavior. See section 2.9.8 for the associated struct sid_ka_ack_status.
2.11 Stack Configuration
The Amazon Sidewalk stack requires configuration to be passed during initialization. Configuration includes the following items:
- link_mask: The Amazon Sidewalk stack can be initialized to operate as one link or a combination of more than one link. The
link_maskis a bit mask that allows the developer’s application to specify a single link or a combination of more than one link. The following code shows the link combinations that are currently supported and the value thelink_masktakes for these combinations. FSK and LoRa links are mutually exclusive, and the Amazon Sidewalk stack cannot support these links simultaneously. If only one of them is inlink_mask, the developer’s application has to de-initialize and re-initialize the Amazon Sidewalk stack to switch to the other. If both are inlink_mask, the Amazon Sidewalk stack alternates between them until one connects.SID_LINK_TYPE_8is not alink_maskvalue, see section 2.1.
// BLE only
uint32_t link_mask = SID_LINK_TYPE_1; // link_mask = 1;
// FSK only
uint32_t link_mask = SID_LINK_TYPE_2; // link_mask = 2;
// LoRa only
uint32_t link_mask = SID_LINK_TYPE_3; // link_mask = 4;
// BLE and LoRa
uint32_t link_mask = SID_LINK_TYPE_1
| SID_LINK_TYPE_3; // link_mask = 5;
// BLE and FSK
uint32_t link_mask = SID_LINK_TYPE_1
| SID_LINK_TYPE_2; // link_mask = 3;
// FSK and LoRa
uint32_t link_mask = SID_LINK_TYPE_2
| SID_LINK_TYPE_3; // link_mask = 6;
// BLE and FSK and LoRa
uint32_t link_mask = SID_LINK_TYPE_1
| SID_LINK_TYPE_2
| SID_LINK_TYPE_3; // link_mask = 7;
- callbacks: a pointer to the callback structure documented above.
- link_config: static configuration for the BLE link. A
struct sid_ble_link_configpointer is required irrespective of thelink_mask. - sub_ghz_link_config: static configuration for the FSK and LoRa links, including the LoRa data rate requested by the developer’s application. This member is optional. See section 2.11.2.
- dev_ch: the characteristics of the end device: its type, its power source, and the qualification ID assigned at qualification.
- log_config: diagnostic logging configuration. Contains the pointer to the buffer in which logs are stored, the size of that buffer, and the log level. The allocated buffer shall be at least 1KB.
- time_sync_config: time synchronization configuration, an array of sync intervals in hours. The intervals shall be strictly increasing and each shall be between 2 and 720 hours. If the member is not provided, or the values do not meet those conditions, the default intervals are used. See section 2.4.
- gsk_config: Gateway Session Key configuration. See section 2.11.1. If it is not provided, default values are used.
The Amazon Sidewalk stack does not copy the structures referenced by callbacks, link_config, sub_ghz_link_config, and time_sync_config. The developer’s application shall keep those structures, and anything they point to, in static storage for as long as the Amazon Sidewalk stack is initialized (this includes the keep-alive payload buffer referenced by sub_ghz_link_config->ka_payload; see section 2.9.10). log_config and gsk_config are read once during sid_init and are not retained, but the log buffer that log_config points to shall remain valid for as long as the Amazon Sidewalk stack is initialized.
2.11.1 Gateway Session Key Configuration
A Gateway Session Key (GSK) is a key that the Amazon Sidewalk stack may establish for a sub-GHz link. Using a GSK does not change how user payloads are encrypted; see section 2.3.
Gateway Session Keys apply only to the sub-GHz links; the BLE link never uses one. On the LoRa link a key and the higher data rate go together: the Amazon Sidewalk stack moves the link to the higher data rate itself in order to establish a key, whichever data rate the developer’s application requested. See section 2.11.2.
There is no Sid API call to start or stop establishment. Amazon Sidewalk determines whether this procedure runs for a given device and link, and may also limit how long a key is used and how many messages are sent under it; the values in struct sid_gsk_config affect only when the Amazon Sidewalk stack attempts establishment and when it stops using a key.
Gateway Session Key support is a build-time option in the Amazon Sidewalk stack, and is enabled by default. Where it is not built in, gsk_config has no effect and no Gateway Session Key is established.
A field left at zero selects that field’s default. Any other value outside the permitted range is adjusted to the nearest permitted value rather than rejected. sid_init therefore never fails because of gsk_config.
#define SID_GSK_IDLE_TIMEOUT_MIN_SEC 10
#define SID_GSK_IDLE_TIMEOUT_MAX_SEC 600
#define SID_GSK_IDLE_TIMEOUT_DEFAULT_SEC 240
#define SID_GSK_APP_ACK_MISS_MIN 3
#define SID_GSK_APP_ACK_MISS_MAX 10
#define SID_GSK_APP_ACK_MISS_DEFAULT 6
#define SID_GSK_RETRY_INTERVAL_MIN_SEC 43200 /* 12 h */
#define SID_GSK_RETRY_INTERVAL_MAX_SEC 129600 /* 36 h */
#define SID_GSK_RETRY_INTERVAL_DEFAULT_SEC 86400 /* 24 h */
struct sid_gsk_config {
uint32_t idle_timeout_sec;
uint32_t app_ack_miss_threshold;
uint32_t retry_interval_sec;
};
idle_timeout_sec: the combined transmit and receive idle period on the sub-GHz link that shall elapse before the Amazon Sidewalk stack begins establishment of its own accord. Traffic that uses a key and traffic that uses the legacy credentials both reset it, so on a product that transmits on a sub-GHz link more often thanidle_timeout_secestablishment does not start on this basis. The idle period is not on its own sufficient: establishment also requires the Endpoint to be registered, the per-link enablement to be present, a capable sub-GHz link to have completed the Join procedure, no key to be held already, and, on the LoRa link, a regulatory region in which the higher data rate is permitted. Nor is it always awaited: after the Amazon Sidewalk stack stops using a key because of a failure over the air, such as a time synchronization or Join failure under the key, it may begin establishment immediately.app_ack_miss_threshold: the number of consecutive unacknowledged uplink messages sent under the key on the sub-GHz link, after which the Amazon Sidewalk stack stops using the key. Only messages that were transmitted and that requested an acknowledgment are counted; see section 2.8.3.1. The count is reset when the Endpoint next receives a message under that key. Such a message timing out is reported through the on send error callback withSID_ERROR_TIMEOUT, but the developer’s application shall not assume those reports account for every message counted towards this field. On reaching the threshold the Amazon Sidewalk stack discards the stored keys rather than suspending the key in use, and does not attempt establishment again untilretry_interval_sechas elapsed.retry_interval_sec: the period between attempts to establish a GSK, after an unsuccessful attempt or after the Amazon Sidewalk stack has stopped using a GSK. The idle period inidle_timeout_secapplies to a scheduled attempt as well. Within a single attempt the Amazon Sidewalk stack retries its request a bounded number of times with an escalating delay; neither the number of retries nor that delay is configurable, and the minimum of twelve hours does not follow a single lost message.
Establishing a Gateway Session Key, or ceasing to use one, can make the Endpoint repeat the Join procedure. Whether it does, and what the developer’s application observes, depends on the sub-GHz link and, on the LoRa link, on the data rate the developer’s application requested; see section 2.7.3. The developer’s application shall not use the on status changed callback to detect a key change.
Establishment and key maintenance generate sub-GHz uplinks that the developer’s application did not request, and these count against its energy and duty cycle budget. Raising idle_timeout_sec or retry_interval_sec makes them less frequent. app_ack_miss_threshold also affects them, for a product whose messages request acknowledgment: the Amazon Sidewalk stack makes a further establishment attempt after each time it stops using a key, so a threshold that is reached often produces more of this traffic.
The Amazon Sidewalk stack may also stop using a key for reasons the developer’s application does not configure, including a limit that Amazon Sidewalk places on the key’s age or on the number of messages sent under it, a failure to confirm the key over the air, or a time synchronization failure while the key is in use. A key survives a device reset and is resumed at the next start-up; a factory reset clears it.
The value returned by sid_get_mtu does not change while a Gateway Session Key is in use; see section 3.10. On the LoRa link two things the developer’s application can observe do change with a key: link layer acknowledgement and link layer retransmission are used only while a key is active on that link, see section 2.10; and where establishing the key moves the link to the higher data rate, any retained RX window interval preference is applied at that point, subject to the profile conditions in section 2.9.
2.11.2 LoRa Data Rate
The Amazon Sidewalk stack operates the LoRa link at one of two data rates: a default data rate and a higher data rate. The developer’s application requests one through the link3_data_rate member of the sub-GHz link configuration passed to sid_init. There is no IOCTL counterpart; for what the Amazon Sidewalk stack reports about the data rate, see section 2.6.
The higher data rate shortens the time each message occupies the air, at the cost of a reduced link budget in both directions: the Endpoint and the Gateway each need a stronger signal from the other to stay reachable. Request it for a product that sends or receives frequently and that operates within reliable range of a Gateway; leave the default data rate for a product that needs the greatest range.
The data rate is requested using the following enumeration.
enum sid_link3_data_rate {
/** Low data rate */
SID_LINK3_DATA_RATE_LDR = 0,
/** Medium data rate */
SID_LINK3_DATA_RATE_MDR = 1,
};
SID_LINK3_DATA_RATE_LDR is the default data rate and SID_LINK3_DATA_RATE_MDR is the higher data rate; this guide uses those two descriptions throughout.
sid_init does not validate this member. A zero-initialized sub-GHz link configuration, no sub-GHz link configuration at all, and any value other than SID_LINK3_DATA_RATE_MDR all select the default data rate.
The higher data rate additionally requires a regulatory region that permits it, established before the LoRa link is initialized. A request the region does not permit is refused the same way a mis-set member is: the link runs at the default data rate, with no return code and no callback to indicate it.
The developer’s application’s request is read once, during sid_init; modifying the sub-GHz link configuration afterwards does not change the data rate. The regulatory region condition is re-evaluated whenever the Amazon Sidewalk stack initializes the LoRa link, and again whenever it moves the link to the higher data rate. The developer’s application shall therefore establish the regulatory region before it calls sid_init. A region established afterwards takes effect only if and when the Amazon Sidewalk stack next performs one of those steps, which is not guaranteed to happen and is not reported to the developer’s application; until it does, the link operates at the default data rate. To make a region established after sid_init take effect, de-initialize and initialize the Amazon Sidewalk stack.
Where the regulatory region permits the higher data rate, the Amazon Sidewalk stack operates the LoRa link at it when the developer’s application has requested it, and also whenever a Gateway Session Key is being established or is in use on the link, including a key that is resumed at start-up after a device reset. While a key is being established the data rate changes first and the key becomes active afterwards. See section 2.11.1.
Requesting the higher data rate does not require Gateway Session Key support to be built in, and does not by itself enable link layer acknowledgement or link layer retransmission; see section 2.10. Where the Amazon Sidewalk stack brings the link up at the higher data rate, or moves it to the higher data rate before the Join procedure has completed, it sets the receive cadence itself until that Join completes, and the developer’s application shall not rely on the configured RX window interval being in effect during that period. For the RX window interval and the higher-data-rate interval preference, see section 2.9.
The developer’s application shall be functionally correct at the default data rate in every region it ships to: a request for the higher data rate can be refused, and the Amazon Sidewalk stack does not report that it was.
2.12 Sidewalk Handle
The Sidewalk handle is a pointer to an internal structure that is returned to the developer’s application as part of the Amazon Sidewalk stack initialization. The developer’s application is required to pass this handle when making Sid API calls. The Sidewalk handle is set to NULL when the Amazon Sidewalk stack is de-initialized.
2.13 Sidewalk Bulk Data Transfer
Sidewalk Bulk Data Transfer allows developers to transfer files to a device over BLE link only. These files could be firmware files for OTA upgrades. The developer’s application interacts with the Amazon Sidewalk bulk data transfer functionality through the Amazon Sidewalk Bulk Data Transfer API (SBDT API). Broadly the following operations are supported:
- Initialize and de-initialize SBDT API
- Accept and reject incoming transfers
- Cancel ongoing transfers
- Verify the received file at the end of the transfer
2.13.1 Flow
Internally the file that is transferred is divided into fragments, the size of the fragments is configured by the developer when the transfer is setup. This fragment is further divided into chunks of size limited by the link on which the transfer is being done. The maximum size of the chunks for SID_LINK_TYPE_1 (Bluetooth low power energy) is 216 bytes.
The device receives each of the chunks that makes up the fragment, the fragment is then verified if the verification fails the block is retransmitted, if not it sends an acknowledgement indicating that the fragment was successfully received. Then, the device receives the next fragment. The procedure continues until the whole file is transferred. Once the whole file is transferred, the application has the opportunity to validate the file. The file validation can be achieved by validating the CRC of the file, or by validating the signature.
2.13.2 File Id
Each transfer to the device is identified by a unique 4 byte id, called as the file_id.
2.13.3 Identifying an incoming transfer
An incoming transfer can be identified via file_descriptor field that developer provides when the transfer is created. The file_descriptor format is developer-defined, and is restricted to size not exceeding 40 bytes.
2.13.4 Memory Usage
The SBDT feature requires buffers to be allocated to handle the file transfer. The amount of memory needed is 2 times the chosen file transfer fragment size + context_memory (memory needed to hold the state). This memory is requested from the developer from the on_transfer_request callback. Some part of the memory is used for storing the transfer context, 1 fragment is used to store the received encrypted data and 1 fragment is used to hold the decrypted data. This memory is owned by SBDT until on_release_scratch is called.
2.13.5 Flash Storage
To allow for seamless functioning of the file transfer on reboots or planned device shutdown’s, the SBDT stack stores information that it receives at file transfer request to kv_store at the various stages of the transfer.
2.13.6 Requesting a transfer
When a transfer is started, the application has the option to reject or accept a transfer. An application can choose to reject transfers based on multiple reasons. The currently available options are listed below.
enum sid_bulk_data_transfer_reject_reason {
/** No reject reason */
SID_BULK_DATA_TRANSFER_REJECT_REASON_NONE = 0x0,
/** Rejected for generic reasons */
SID_BULK_DATA_TRANSFER_REJECT_REASON_GENERIC = 0x1,
/** Rejected because file is too big */
SID_BULK_DATA_TRANSFER_REJECT_REASON_FILE_TOO_BIG = 0x3,
/** Rejected because device has not space */
SID_BULK_DATA_TRANSFER_REJECT_REASON_NO_SPACE = 0x4,
/** Rejected bacause low battery to complete transfer */
SID_BULK_DATA_TRANSFER_REJECT_REASON_LOW_BATTERY = 0x5,
/** Rejected because file verification failed */
SID_BULK_DATA_TRANSFER_REJECT_REASON_FILE_VERIFICATION_FAILED = 0x9,
/** Rejected because file already exist */
SID_BULK_DATA_TRANSFER_REJECT_REASON_FILE_ALREADY_EXISTS = 0xB,
/** Rejected because fragment size is not supported */
SID_BULK_DATA_TRANSFER_REJECT_REASON_INVALID_FRAGMENT_SIZE = 0xE,
};
The developer is provided with multiple information points such as fragment_size, file_size, file_descriptor (Identifying an incoming transfer) that can help them determining the reason for rejection.
2.13.7 Receiving data
Once each fragment is received, the developer’s application is given fragment via on_data_received callback. The additional information that is provided includes file_id, file_offset, and the link that fragment the data is received on. Once the data is received, the developer’s application can then write the data to flash and release the buffer so that the next buffer can be received.
2.13.8 SBDT Callbacks
The SBDT API notifies the developer’s application through a set of callbacks. The developer is required to register these callbacks with SBDT API when initializing the SBDT feature. The following events are notified by SBDT:
- on transfer request: SBDT uses this callback to notify the developer’s application that it received a request to start a file transfer. The callback contains various information about the incoming transfer such as the size of the file, fragment size used for the transfer, the link over which the transfer is going to happen, file descriptor if provided when the transfer was created. This API allows developer’s application to reject the incoming transfer with a reject reason in Sidewalk Bulk Data Transfer Status Codes.
- on data received: SBDT uses this callback to notify the developer’s application that it received a fragment. The developer’s application now owns the buffer that contains fragment data and can only be released via
sid_bulk_data_transfer_release_bufferAPI call. - on finalize request: Once all the fragments are transferred, the SBDT triggers this callback to notify the developer that the file has been transferred. The developer’s application can indicate to SBDT if the recieved file is as expected via the
sid_bulk_data_transfer_finalizeAPI call. - on cancel request: SBDT uses this callback to notify the developer’s application that it received a cancel request from AWS cloud. This API is also called when the developer’s application calls
sid_bulk_data_transfer_cancelto cancel an ongoing transfer. - on error: SBDT uses this callback to notify the developer that it has encountered an unrecoverable error.
- on release scratch: This callback is called by the SBDT to release memory it acquired from the developer’s application in on transfer request. This callback is called after on finalize request, on cancel request, on error and
sid_bulk_data_transfer_deinit.
struct sid_bulk_data_transfer_event_callbacks {
/** User context data */
void *context;
/**
* Callback that is invoked when a transfer request is recieved
*
* The Sidewalk stack invokes this callback to let the user know about
* an Incoming transfer request. The user can then choose to accept or
* reject said transfer request
*
* @param[in] transfer_request A pointer to the data transfer request,
* which is never NULL
* @param[out] transfer_response A pointer to the data transfer response,
* which is never NULL
* @param[in] context The context pointer given in
* sid_bulk_data_transfer_event_callbacks.context
*
*/
void (*on_transfer_request)
(const struct sid_bulk_data_transfer_request *const transfer_request,
struct sid_bulk_data_transfer_response *const transfer_response,
void *context);
/**
* Callback that is invoked when data has been received
*
* @param[in] desc A pointer to the bulk transfer data,
* which is never NULL
* @param[in] buffer A pointer to the buffer that contains the received
* data, which is never NULL
* @param[in] context The context pointer given in
* sid_bulk_data_transfer_event_callbacks.context
*/
void (*on_data_received)
(const struct sid_bulk_data_transfer_desc *const desc,
const struct sid_bulk_data_transfer_buffer *const buffer,
void *context);
/**
* Callback that is invoked when data transfer is done
*
* @param[in] file_id Identifier of the file being transferred
* @param[in] context The context pointer given in
* sid_bulk_data_transfer_event_callbacks.context
*/
void (*on_finalize_request)(uint32_t file_id, void *context);
/**
* Callback that is invoked when data transfer is cancelled from cloud
*
* @param[in] file_id Identifier of the file being transferred
* @param[in] context The context pointer given in
* sid_bulk_data_transfer_event_callbacks.context
*/
void (*on_cancel_request)(uint32_t file_id, void *context);
/**
* Callback that is invoked when an error is encountered during data
* transfer
*
* The Sidewalk stack will invoke this API to let the user know an error
* was encountered during file transfer. Internally Sidewalk stack
* cleans up it's state and goes to the same state as when
* sid_bulk_data_transfer_start() is called.
*
* @param[in] file_id Identifier of the file being transferred
* @param[in] context The context pointer given in
* sid_bulk_data_transfer_event_callbacks.context
*/
void (*on_error)(uint32_t file_id, void *context);
/**
* Callback that is invoked when Sidewalk stack wants to release scratch
* buffer
*
* The Sidewalk stack will invoke this API to let the user cleanup the
* scratch buffer that was allocated to during on_transfer_request call
*
* @param[in] file_id Identifier of the file being released
* @param[in] context The context pointer given in
* sid_bulk_data_transfer_event_callbacks.context
*/
void (*on_release_scratch)(uint32_t file_id, void *context);
};
2.14 Amazon Sidewalk Location Library
The Amazon Sidewalk Location Library enables Sidewalk customers to use a range of cloud-based location solvers. Available in SDK >=1.19, this library provides an API that automatically selects the most power and time efficient location mechanism based on available hardware and network conditions. Developers will also have finer grain control to configure and override the mechanism used to determine location as required.
2.14.1 Supported Location Methods
The location library supports four location resolution methods:
- Sidewalk Network Location over BLE - Leverages existing BLE connections to trigger cloud-side location resolution
- Sidewalk Network Location over LoRa - Sends a location trigger over an active LoRa connection for cloud-side location resolution
- WiFi Scan - Scans for nearby WiFi access points and sends MAC addresses to the cloud for location resolution
- GNSS Scan - Uses Global Navigation Satellite System to collect satellite vehicle data for coordinate resolution
Methods 1 and 2 are network-level triggers that rely on the cloud to resolve location from the device’s network context, requiring no device-side scanning. Methods 3 and 4 perform device-side scans and can be sent over either BLE or LoRa link types.
FSK with WiFi/GNSS scanning enabled is not currently supported.
WiFi and GNSS scanning leverage the Semtech LoRa Basics Modem middleware to manage and conduct scans on the device.
These four methods correspond directly to the four effort levels defined in Section 2.14.2, ordered from lowest to highest power consumption.
2.14.2 Location Levels
Location levels are ordered by lowest effort first (power consumption and time) and are defined by the available hardware on the device. The library automatically steps down through levels at configurable timeouts.
2.14.2.1 Level 1: Connected to Sidewalk via BLE
- Power Consumption: No additional power draw
- Description: If the device can be located via BLE over the Sidewalk network, the device notifies the cloud to resolve the location with no further effort. If the device is not connected via BLE or location cannot be resolved, the next level is attempted.
2.14.2.2 Level 2: LoRa Location Trigger
- Power Consumption: Low power consumption
- Description: Sends a location trigger over LoRa (Link Type 3) to the cloud for location resolution. Requires the LoRa link to be network synced. This level is used when the device is not connected via BLE but has an active LoRa connection.
2.14.2.3 Level 3: Send WiFi Scan
- Power Consumption: Low power consumption
- Description: Conduct and send a WiFi scan. Minimum of 1 AP must be found in scan or next level will be attempted. If the cloud receives a low confidence score or no resolution is found, the device application must be notified to increment and try the next level.
2.14.2.4 Level 4: Send GNSS Scan
- Power Consumption: Higher power consumption than WiFi scanning
- Description: Conduct and send a GNSS scan. Minimum 4 Satellite Vehicles must be found for scan to be valid.
2.14.3 Architecture
The library provides a single interface for application developers to consume APIs for uplinking location data. WiFi and GNSS have corresponding Platform Abstraction Layers (PALs) that are required when these features are enabled.
2.14.4 Getting Started
2.14.4.1 Compilation Configuration
To enable the location library in your project, the following CMake variable definitions must be set:
set(SID_SDK_CONFIG_ENABLE_LOCATION 1)
set(SID_SDK_CONFIG_ENABLE_WIFI 1)
set(SID_SDK_CONFIG_ENABLE_GNSS 1)
add_compile_definitions(SID_SDK_CONFIG_ENABLE_LOCATION=1)
add_compile_definitions(SID_SDK_CONFIG_ENABLE_WIFI=1)
add_compile_definitions(SID_SDK_CONFIG_ENABLE_GNSS=1)
SID_SDK_CONFIG_ENABLE_LOCATION enables the location library as part of the build. SID_SDK_CONFIG_ENABLE_WIFI and SID_SDK_CONFIG_ENABLE_GNSS are features that can be enabled if available hardware supports WiFi and GNSS scanning.
Additional configurations may be required depending on the build system of the target.
2.14.4.2 Managed Effort Mode
The manage_effort configuration field controls whether the location library automatically selects and adjusts the effort level used for location operations.
When manage_effort is true:
- The application can pass
SID_LOCATION_EFFORT_DEFAULTas the mode insid_location_run(). The library will use its internally tracked effort level. - The library starts at
SID_LOCATION_EFFORT_L1and automatically escalates to higher effort levels if the current level is not supported or returns insufficient results. - After a successful scan at a higher effort level (L3 or L4), the library starts a stepdown timer. When the timer expires, the effort level is reduced back toward L1 based on the configured stepdowns timeouts.
- The maximum effort level the library can escalate to is bounded by
max_effort. - The application can override the maximum allowed effort at runtime using
sid_location_set_max_mode(), for example to limit power consumption during low-battery conditions.
When manage_effort is false:
- The application must specify an explicit effort level (L1, L2, L3, or L4) in every call to
sid_location_run(). PassingSID_LOCATION_EFFORT_DEFAULTwill return an error. - No automatic escalation or stepdown occurs. The library uses exactly the effort level requested.
- This mode gives the application full control over which location method is used for each operation.
L2 (LoRa location trigger) can be used explicitly by passing SID_LOCATION_EFFORT_L2 to sid_location_run(). During managed effort escalation, L2 is currently skipped and the library transitions directly between L1 and L3.
2.14.4.3 Fragmentation Timeout Configuration
If configuring the fragmentation timeout, the timeout_ms parameter should be considered carefully. The timeout will be calculated automatically if set to 0 and follows the following formula that mirrors the cloud algorithm to wait/reassemble fragments:
timeout = (total_size / MTU) × link_type_duration × 2
Where:
total_size / MTUdetermines the number of fragments requiredlink_type_durationis the maximum time the specified link type can take to uplink one fragment- The factor of 2 provides additional margin for retries to reach the cloud.
Current supported link type durations:
- LoRa: Up to 5 seconds per fragment
- BLE: BLE does not utilize fragmentation for location as the MTU is large enough. These configurations will not apply
2.14.5 Location Resolve via sid_put_msg
In addition to the explicit location APIs (sid_location_run()), the location library supports requesting location resolution as part of a user message sent via sid_put_msg(). This is done by setting the resolve_location field in the message descriptor’s TX attributes.
When resolve_location is set to true, the Sidewalk stack includes a location resolve request with the user’s message. The gateway uses this to resolve the device’s location based on its own known position. This works on both BLE and LoRa links.
Prerequisites:
SID_SDK_CONFIG_ENABLE_LOCATIONmust be enabled at compile timesid_location_init()must have been called successfully- The Sidewalk stack must be in
SID_STATE_READYstate
2.14.6 WiFi and GNSS Location Example (LR1110)
The following example shows how to enable GNSS and WiFi with the location library for use with the LR1110 shield.
// Platform parameters setup
platform_parameters_t platform_parameters = {
.mfg_store_region = sid_mfg_config_get(),
.platform_init_parameters.radio_cfg =
(radio_lr11xx_device_config_t *)get_radio_cfg(),
.platform_init_parameters.gnss_wifi_cfg =
(lr11xx_gnss_wifi_config_t *)get_location_cfg(),
};
// Location library usage
void location_callback(const struct sid_location_result *const result,
void *context)
{
// Handle location operation results
}
static struct sid_location_config cfg = {
.sid_location_type_mask = SID_LOCATION_METHOD_ALL,
.manage_effort = true,
.max_effort = SID_LOCATION_EFFORT_L4,
.callbacks = {
.on_update = location_callback,
.context = NULL,
},
.stepdowns = {
.l2_to_l1 = 0,
.l3_to_l2 = 0,
.l4_to_l3 = 0,
},
.fragmentation = {
.timeout_ms = 0,
.max_retries = 1,
},
.auto_link_pause_resume = true,
};
sid_error_t res = sid_location_init(*app_context->sidewalk_handle, &cfg);
// WiFi scan and send
struct sid_location_run_config config = {
.type = SID_LOCATION_SCAN_AND_SEND,
.mode = SID_LOCATION_EFFORT_L3
};
res = sid_location_run(*app_context->sidewalk_handle, &config, 0);
// GNSS scan and send
config.mode = SID_LOCATION_EFFORT_L4;
res = sid_location_run(*app_context->sidewalk_handle, &config, 0);
2.14.7 BLE-Only Location Example
static struct sid_location_config cfg = {
.sid_location_type_mask = SID_LOCATION_METHOD_BLE_GATEWAY,
.manage_effort = true,
.max_effort = SID_LOCATION_EFFORT_L1,
.callbacks = {
.on_update = location_callback,
.context = NULL,
},
.stepdowns = {0},
.fragmentation = {0},
.auto_link_pause_resume = false,
};
sid_error_t res = sid_location_init(*app_context->sidewalk_handle, &cfg);
struct sid_location_run_config config = {
.type = SID_LOCATION_SCAN_AND_SEND,
.mode = SID_LOCATION_EFFORT_DEFAULT
};
res = sid_location_run(*app_context->sidewalk_handle, &config, 0);
2.14.8 LoRa Location Example
static struct sid_location_config cfg = {
.sid_location_type_mask = SID_LOCATION_METHOD_BLE_GATEWAY,
.manage_effort = false,
.max_effort = SID_LOCATION_EFFORT_L2,
.callbacks = {
.on_update = location_callback,
.context = NULL,
},
.stepdowns = {0},
.fragmentation = {0},
.auto_link_pause_resume = false,
};
sid_error_t res = sid_location_init(*app_context->sidewalk_handle, &cfg);
struct sid_location_run_config config = {
.type = SID_LOCATION_SEND_ONLY,
.mode = SID_LOCATION_EFFORT_L2
};
res = sid_location_run(*app_context->sidewalk_handle, &config, 0);
2.14.9 Platform Abstraction Layers
If the device supports WiFi and GNSS scanning (levels 3 and 4), the WiFi and GNSS Platform Abstraction Layers (PALs) must be implemented and linked. Reference implementations are provided that utilize the Semtech LoRa Basics Modem middleware APIs.
2.14.10 Best Practices
- Use
sid_location_set_max_mode()to limit power consumption during low-power modes - Configure appropriate stepdown timeouts based on your application requirements
- Always check return values from location API functions
- Handle different status codes in your callback function appropriately
- Allow the library to manage effort levels automatically when possible
- Consider using scan-only operations when immediate uplink is not required
2.15 Build configuration for factory-registered Endpoints and lite variants
The Amazon Sidewalk stack can be built in a full variant, which supports every link type and registration over the air, or in one of three lite variants, each restricted to a single link type. The lite variants have no over-the-air registration path: an Endpoint running a lite variant is registered at the factory over a wired link (section 2.3.4). The following build settings apply:
SID_SDK_CONFIG_BUILD_BLE_ONLY,SID_SDK_CONFIG_BUILD_FSK_ONLY,SID_SDK_CONFIG_BUILD_LORA_ONLY: CMake options that select a lite variant. They are mutually exclusive; when none is set the full variant is built.SID_SDK_INTERNAL_CONFIG_IS_FACTORY_REGISTERED: when set to 1, the Amazon Sidewalk stack accepts a factory-registered Endpoint and performs field activation for it. The default is 0. The reference applications set it for every lite variant and, for the full variant, through theirBUILD_FACTORY_REGISTEREDbuild option.SID_SDK_CONFIG_SECURITY_LEVEL:SID_SDK_CONFIG_SECURITY_LEVEL_HIGH(0, the default) orSID_SDK_CONFIG_SECURITY_LEVEL_LOW(1). This setting only selects the security level the Endpoint reports in its capabilities to the Amazon Sidewalk cloud; the behavior of the stack (restoring the credentials from the manufacturing page, keeping them across a factory reset) follows from the variant. Build the lite variants withSID_SDK_CONFIG_SECURITY_LEVEL_LOWand the full variant withSID_SDK_CONFIG_SECURITY_LEVEL_HIGH, and register the Endpoint with the same security level in the manufacturing tool.
sid_init behaves differently in the two variants:
- In the full variant,
link_maskset toSID_LINK_TYPE_3(LoRa) only is accepted for a factory-registered Endpoint whenSID_SDK_INTERNAL_CONFIG_IS_FACTORY_REGISTEREDis set, see section 3.3. - In the lite variants,
sid_initreturnsSID_ERROR_NOSUPPORTwhen the Endpoint is neither registered nor factory-registered, because the build has no way to register it over the air.
2.16 Device Region (Internationalization)
Amazon Sidewalk device firmware operates in a specific regulatory zone, and the frequency plan and regulatory parameters the radio layer uses at bring-up are selected according to that zone, called the region. The Device Information API (sid_device_information.h) exposes the region to the Amazon Sidewalk stack for system integrators adopting Sidewalk internationalization (i18n).
The Amazon Sidewalk stack does not store the region itself. The developer’s application owns it end to end: it persists the region in non-volatile storage, reports it to the Amazon Sidewalk stack through a callback, and accepts cloud/app-driven updates through a callback. The Amazon Sidewalk stack reaches the application’s storage only through the callbacks registered in struct sid_device_info_callbacks.
An unregisterable region does not block sid_start() outright: it confines the call to SID_LINK_TYPE_1 (BLE) and fails a request for sub-GHz links alone with SID_ERROR_INVALID_STATE. An application adopting this API shall provision a valid region before registration is required on a sub-GHz link, or the sub-GHz link will not start. See section 2.16.4 for the exact mechanics, and section 3.36.
2.16.1 Data Types
The region is represented by the following enumeration:
enum sid_device_region {
SID_DEVICE_REGION_UNSET = 0, /* reserved / unset */
SID_DEVICE_REGION_NORTH_AMERICA = 1, /* North America (US/CA/MX) */
SID_DEVICE_REGION_EUROPE = 2, /* Europe, incl. UK */
SID_DEVICE_REGION_JAPAN = 3, /* Japan (defined, not enabled) */
SID_DEVICE_REGION_AUSTRALIA_NZ = 4, /* Australia / New Zealand (defined, not enabled) */
SID_DEVICE_REGION_NOT_SUPPORT = 0xFF,
};
The region travels in struct sid_device_dyn_info (a tagged union) when type is SID_DEVICE_INFO_TYPE_REGION:
struct sid_device_dyn_info {
enum sid_device_info_type type; /* = SID_DEVICE_INFO_TYPE_REGION */
union {
/* ... */
enum sid_device_region region;
};
};
The region itself is exchanged through two application-supplied callbacks, registered in struct sid_device_info_callbacks and passed to sid_device_information_init (section 3.34):
get_info()— the Amazon Sidewalk stack calls this withtype == SID_DEVICE_INFO_TYPE_REGIONto read the current region, for example to answer aGET_DEVICE_INFORMATIONrequest.set_info()— the Amazon Sidewalk stack calls this withtype == SID_DEVICE_INFO_TYPE_REGIONto apply a region change, for example from aDEVICE_CONFIGURATIONwrite.
2.16.2 Supported Regions and Build Flags
A region is registerable only if it is North America or Europe, and the firmware was built for it. The build-time flags gate configurability, reported through is_device_region_configurable().
Table 2.3: Supported regions and the build flags that enable them.
| Region | Registerable | Enabled by build flag(s) | | ————- | —————- | ——————————————— | | North America | Yes | REGION_LITE or REGION_US915 | | Europe | Yes | REGION_LITE or REGION_EU868 | | Australia/NZ | No | defined but not enabled — blocks registration | | Japan | No | defined but not enabled — blocks registration | | Unset (0) | No | n/a — blocks registration |
A set_info request for a region the firmware was not built for is rejected with NO_SUPPORT_ERROR, and the device keeps its previous region.
2.16.3 Integrating the Device Region API
1. Implement the callbacks. Handle SID_DEVICE_INFO_TYPE_REGION in both get_info and set_info. The region value shall be persisted to non-volatile storage — the example below keeps it in an app context for brevity, but a production integration shall survive reboot and factory state.
static bool on_device_get_info(struct sid_device_dyn_info *info, void *context)
{
struct app_context *app = context;
if (info->type == SID_DEVICE_INFO_TYPE_REGION) {
info->region = app->region_set
? (enum sid_device_region)app->region
: SID_DEVICE_REGION_UNSET;
return true;
}
/* ... handle ENV / BATTERY_LEVEL / OTA_BLOCK_SIZE as applicable ... */
return false;
}
static bool on_device_set_info(const struct sid_device_dyn_info *info, void *context)
{
struct app_context *app = context;
if (info->type == SID_DEVICE_INFO_TYPE_REGION) {
app->region = (uint8_t)info->region;
app->region_set = true;
/* MUST persist to NVM here so the region survives reboot/factory state. */
return true; /* return false to signal a storage failure */
}
/* ... handle ENV as applicable ... */
return false;
}
2. Register the module. Call sid_device_information_init (section 3.34) after sid_init returns a handle. The configuration passed is not copied and shall remain valid for the lifetime of the application.
static struct sid_device_info_callbacks device_info_callbacks = {
.context = &g_app_context,
.get_info = on_device_get_info,
.set_info = on_device_set_info,
};
static const struct sid_device_info_config device_info_cfg = {
.info = &device_static_info, /* serial, MAC, fw version, device kind */
.callbacks = &device_info_callbacks,
};
/* After sid_init() returns a handle. The config must stay valid for the app lifetime. */
sid_error_t ret = sid_device_information_init(&device_info_cfg, sidewalk_handle);
3. Provision a region. Provision a valid, build-enabled region before the device attempts to register on a sub-GHz link. There are two paths:
- Local provisioning (recommended at manufacturing/setup): the application sets the region through its own storage path, so
get_inforeturns a valid value on first boot. - Remote configuration: the cloud/app sends a
DEVICE_CONFIGURATIONwrite with the region tag; the module routes it toset_info.
If get_info returns SID_DEVICE_REGION_UNSET, the module falls back to a compile-time default only after the device is already registered — it does not fall back before registration. An unset region on a fresh device therefore leaves the device confined to BLE until a valid region is provisioned; see section 2.16.4.
4. Configure the radio region. The region the Endpoint reports through get_info and set_info, and the region its sub-GHz radio operates on, set by platform_init_parameters.region and iso_country in sid_platform_init (3.1), are separate values, and the Amazon Sidewalk stack does not connect them. Derive both from the same stored value:
- At every boot, pass the stored region to
sid_platform_init(), rather than a fixed compile-time value. - A region written through
set_inforeaches the radio at the next platform initialization, normally after the next reboot, becausesid_platform_init()runs once per boot. - If no region is stored, pass a region the build includes; the reported region remains
SID_DEVICE_REGION_UNSET, which confinessid_start()to BLE until a region is provisioned (section 2.16.4). - On factory reset, clear the stored region.
If the two values differ, the Endpoint reports one region while its radio operates on the parameters of another.
2.16.4 The Registration Gate
sid_start() (section 3.5) calls sid_device_information_is_region_registerable() (section 3.36) before starting the requested links:
- When the region is North America, Europe, or Australia/NZ,
is_region_registerable()returns true andsid_start()proceeds with thelink_maskthe developer’s application requested, unchanged. -
When the region is
UNSETor unsupported (e.g. Japan),is_region_registerable()returns false, andsid_start()maskslink_maskdown toSID_LINK_TYPE_1(BLE) before proceeding:- If that leaves no link to start — because the developer’s application requested only FSK, only LoRa, or FSK and LoRa together, with no BLE —
sid_start()returnsSID_ERROR_INVALID_STATEand no link starts. - If
SID_LINK_TYPE_1was among the requested links,sid_start()proceeds on BLE alone; the sub-GHz links the application requested do not start, and this is not separately reported.
- If that leaves no link to start — because the developer’s application requested only FSK, only LoRa, or FSK and LoRa together, with no BLE —
An application adopting this API shall provision a valid region before registration is required on a sub-GHz link, or the sub-GHz link will not start.
2.16.5 Backward Compatibility
An application that does not implement region reporting (legacy firmware without i18n support, or firmware that never calls sid_device_information_init) is unaffected:
sid_device_information_is_region_registerable()returns true (the gate is open), sosid_start()does not masklink_mask.- The
GET_DEVICE_INFORMATIONresponse omits the region tag; the app/cloud uses that absence to detect a legacy device.
The requirements in this section apply only to integrators adopting the region API.
2.16.6 Example Usage
/* Static device information reported alongside the dynamic region. */
static struct sid_device_info device_static_info = {
.serial_number = dsn_buf,
.serial_number_size = sizeof(dsn_buf),
.mac_address = mac_buf,
.mac_address_size = 6,
.product_fw_version = fw_ver_buf,
.product_fw_version_size = sizeof(fw_ver_buf),
};
static struct sid_device_info_callbacks device_info_callbacks = {
.context = &g_app_context,
.get_info = on_device_get_info, /* returns persisted region */
.set_info = on_device_set_info, /* persists region to NVM */
};
static const struct sid_device_info_config device_info_cfg = {
.info = &device_static_info,
.callbacks = &device_info_callbacks,
};
void app_setup(struct sid_handle *sidewalk_handle)
{
/* 1. Register the module after sid_init(). */
sid_device_information_init(&device_info_cfg, sidewalk_handle);
/* 2. Ensure a valid region is provisioned before sid_start().
* (Either set it here from NVM, or rely on a prior DEVICE_CONFIGURATION write.) */
/* 3. sid_start() invokes the region gate internally; a valid region lets
* the requested links proceed, an unset/unsupported one confines
* sid_start() to SID_LINK_TYPE_1 (BLE). */
}
2.16.7 Integration Checklist
- Firmware built with the flag(s) that enable the target region(s).
get_inforeturns the persisted region forSID_DEVICE_INFO_TYPE_REGION.set_infopersists the region to NVM forSID_DEVICE_INFO_TYPE_REGION.- Callbacks registered via
sid_device_information_init()aftersid_init(). - A valid (NA/EU/ANZ) region provisioned before the application needs a sub-GHz link to start.
- Verified registration succeeds on the sub-GHz links the product uses; confirmed an unset or Japan region is understood to confine
sid_start()to BLE. - The region passed to
sid_platform_init()at boot is derived from the same stored value thatget_inforeports. - The stored region is cleared on factory reset.