New functionality
With the ACU6 application project set up and an application running, it’s time to add new functionality. Specifically, we’ll focus on enhancing the application to indicate GNSS location status using an LED - lighting it up when a GNSS position is fixed and turning it off if the position is lost.
Add Location Service to led-example
To interact with the location service (A_SERVICE_ID_LOCATION), similar to how the application communicates with A_SERVICE_ID_SYSTEM for LED control, a session must be opened with the location service.
Modify Event Handler
Begin by modifying event_handler.c. In the event_loop_start function, add a second a_ipc_send call to address A_SERVICE_ID_LOCATION:
res = a_ipc_send(ipc_handle, A_SERVICE_ID_LOCATION, msg);
if (res != A_IPC_RET_OK) {
printf("Send Open session to location service failed %d\n", res);
return -3;
}
Since the application is now communicating with two services, use the from parameter in a_ipc_recv to identify the service that responded:
running = ipc_handler(msg, from);
Create functions for sending A_IPC_MSG_LOCATION_REQUEST_REQ to start the location service and A_IPC_MSG_LOCATION_SUBSCRIBE_REQ to subscribe to location updates:
A_IPC_RESULT ipc_location_request(void)
{
static char *user = "led-example";
A_IPC_MSG_ON_STACK(msg, 256);
A_IPC_RESULT res = a_ipc_init_location_request_req(msg, 15);
if (res != A_IPC_RET_OK) {
printf("Could not init A_IPC_MSG_LOCATION_REQUEST_REQ message %d\n", res);
return -1;
}
msg->location_request_req.user.value = user;
msg->location_request_req.user.length = strlen(user);
return a_ipc_send(ipc_handle, A_SERVICE_ID_LOCATION, msg);
}
A_IPC_RESULT ipc_location_subscribe(void)
{
A_IPC_MSG_ON_STACK(msg, 256);
A_IPC_RESULT res = a_ipc_init_location_subscribe_req(msg);
if (res != A_IPC_RET_OK) {
printf("Could not init A_IPC_MSG_LOCATION_SUBSCRIBE_REQ message %d\n", res);
return -1;
}
return a_ipc_send(ipc_handle, A_SERVICE_ID_LOCATION, msg);
}
Updating event_handler.h
Finally, update event_handler.h to reflect the new function prototypes:
typedef bool (*ipc_response_cbk)(a_ipc_msg* message, int from);
A_IPC_RESULT ipc_location_request(void);
A_IPC_RESULT ipc_location_subscribe(void);
These updates will enable the event handler to manage interactions with both the LED and location services, using an LED to indicate the GNSS location status.
Modify LED Example
Changes are made to led_example.c to use the red LED for blinking every second and the green LED to indicate GNSS location fix status. Update the ipc_handler function to handle different messages:
static struct timespec last_location_update_time;
static bool ipc_handler(a_ipc_msg *msg, int from)
{
bool keep_going = true;
A_IPC_RESULT res;
switch (msg->info.type) {
case A_IPC_MSG_IPC_OPEN_SESSION_RSP:
if (msg->ipc_open_session_rsp.result != A_IPC_ENUM_IPC_OPEN_SESSION_RESULT_OK) {
printf("Error Opening Session: %d", msg->ipc_open_session_rsp.result);
keep_going = false;
} else {
if (from == A_SERVICE_ID_SYSTEM) {
int ret = timer_arm(1, 1);
if (ret < 0) {
printf("Couldn't arm timer");
keep_going = false;
}
}
if (from == A_SERVICE_ID_LOCATION) {
res = ipc_location_request();
if (res != A_IPC_RET_OK) {
printf("Couldn't send message\n");
keep_going = false;
}
}
}
break;
case A_IPC_MSG_LED_SET_RSP:
if (msg->led_set_rsp.result != A_IPC_ENUM_LED_RESULT_OK) {
printf("Error lighting LED: %d", msg->led_set_rsp.result);
keep_going = false;
}
break;
case A_IPC_MSG_LOCATION_REQUEST_RSP:
res = ipc_location_subscribe();
if (res != A_IPC_RET_OK) {
printf("Couldn't send message\n");
keep_going = false;
}
break;
case A_IPC_MSG_LOCATION_SUBSCRIBE_RSP:
printf("Subscribed to location updates\n");
break;
case A_IPC_MSG_LOCATION_PUBLISH_IND:
clock_gettime(CLOCK_MONOTONIC, &last_location_update_time);
printf("Longitude: %d, Latitude: %d, Altitude: %d\n",
msg->location_publish_ind.longitude,
msg->location_publish_ind.latitude,
msg->location_publish_ind.altitude);
res = ipc_set_led(leds[1], LED_ON);
if (res != A_IPC_RET_OK) {
printf("Couldn't send message\n");
keep_going = false;
}
break;
default:
printf("Unrecognized response recieved");
keep_going = false;
break;
}
return keep_going;
}
This updated ipc_handler function will now manage both the blinking of the red LED and the status indication of the green LED based on the GNSS location fix.
Modify Timeout Handler
The timeout_handler function will be updated to handle the blinking of the red LED and to monitor the status of the location updates. The green LED will indicate the receipt of new location updates, and it will be turned off if no updates are received for a specific duration.
static bool timeout_handler(void)
{
static uint8_t state = LED_ON;
struct timespec current_time;
struct timespec diff_time;
bool keep_going = true;
A_IPC_RESULT res = ipc_set_led(leds[0], state);
if (res != A_IPC_RET_OK) {
printf("Couldn't send message");
keep_going = false;
}
clock_gettime(CLOCK_MONOTONIC, ¤t_time);
diff_time.tv_sec = current_time.tv_sec - last_location_update_time.tv_sec;
diff_time.tv_nsec = current_time.tv_nsec - last_location_update_time.tv_nsec;
if (diff_time.tv_nsec < 0) {
diff_time.tv_sec++;
diff_time.tv_nsec += 1000000000;
}
if (diff_time.tv_sec > 5) {
res = ipc_set_led(leds[1], LED_OFF);
if (res != A_IPC_RET_OK) {
printf("Couldn't send message\n");
keep_going = false;
}
}
state = (state == LED_ON) ? LED_OFF : LED_ON;
ticks += 1;
if ((ticks > max_ticks) && (max_ticks != 0)) {
keep_going = false;
}
return keep_going;
}
This function now alternates the red LED between on and off states, representing the system’s active status. It also checks the time elapsed since the last location update. If more than 5 seconds pass without a new update, the green LED is turned off, indicating the loss of a recent location fix.
Rebuilding the Application for the last time
make buildroot-led-example-dirclean: Clean the build directory to ensure a fresh start.
make: Compile the application with the new changes.
make flash: Flash the compiled program onto the target device.
ssh root@198.18.1.3: Connect to the device via SSH for direct interaction.
led-example: Run the program.
Observing Application Behavior
Observe the LEDs on the device. The red LED should blink, indicating active operation. When a location fix is obtained, the green LED should light up. The position is also printed in the terminal. N ote that acquiring a location fix indoors might be challenging. Using an external antenna, ideally positioned outdoors or near a window, is recommended in such cases.
Future Considerations
For applications capable of reading NMEA sentences, a simpler approach might suffice. Sending an A_IPC_MSG_LOCATION_REQUEST_REQ followed by reading raw NMEA sentences via TCP/IP from 198.18.1.2 port 1001 could be a more straightforward method for handling location data.