Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions services/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_subdirectory(crypto)
add_subdirectory(gps)
add_subdirectory(security)
add_subdirectory(os)
add_subdirectory(linux)
Expand Down
10 changes: 10 additions & 0 deletions services/gps/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_library(eos_gps STATIC
src/gps_nmea.c
)

target_compile_definitions(eos_gps PUBLIC EOS_ENABLE_GPS=1)

target_include_directories(eos_gps PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/include
)
48 changes: 48 additions & 0 deletions services/gps/include/eos/gps_nmea.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2026 EoS Project
// ISO/IEC 25000 | ISO/IEC/IEEE 15288:2023

/**
* @file gps_nmea.h
* @brief EoS GPS Service — NMEA 0183 sentence parsing
*
* Provides parsing of standard NMEA GPRMC sentences into a structured
* position/velocity fix usable by higher-level location services.
*/

#ifndef EOS_GPS_NMEA_H
#define EOS_GPS_NMEA_H

#include <stdbool.h>
#include <eos/eos_config.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
double latitude;
double longitude;
float altitude;
float speed_knots;
int satellites;
bool fix_valid;
} eos_gps_data_t;

/**
* Parse a standard NMEA $GPRMC sentence.
*
* @param nmea NUL-terminated NMEA sentence, e.g.
* "$GPRMC,092750.000,A,3746.4949,N,12225.1644,W,0.00,0.00,270526,,,A*7B"
* @param data Output struct populated on success.
* @return 0 on success (data->fix_valid indicates whether the fix is valid),
* -1 on invalid arguments or sentence type, -2 if the sentence has
* too few fields to parse.
*/
int eos_gps_parse_gprmc(const char *nmea, eos_gps_data_t *data);

#ifdef __cplusplus
}
#endif

#endif /* EOS_GPS_NMEA_H */
15 changes: 7 additions & 8 deletions services/gps/src/gps_nmea.c
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2026 EoS Project
// ISO/IEC 25000 | ISO/IEC/IEEE 15288:2023

#include <eos/gps_nmea.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef struct {
double latitude;
double longitude;
float altitude;
float speed_knots;
int satellites;
bool fix_valid;
} eos_gps_data_t;
#if EOS_ENABLE_GPS

/* Parse standard NMEA $GPRMC sentence */
int eos_gps_parse_gprmc(const char *nmea, eos_gps_data_t *data) {
Expand Down Expand Up @@ -62,3 +59,5 @@ int eos_gps_parse_gprmc(const char *nmea, eos_gps_data_t *data) {
data->fix_valid = true;
return 0;
}

#endif /* EOS_ENABLE_GPS */
10 changes: 9 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ add_executable(test_service test_service.c)
target_link_libraries(test_service PRIVATE eos_service)
add_test(NAME test_service COMMAND test_service)

# --- test_gps: GPS NMEA sentence parsing ---
add_executable(test_gps test_gps.c)
target_link_libraries(test_gps PRIVATE eos_gps)
if(UNIX AND NOT APPLE)
target_link_libraries(test_gps PRIVATE m)
endif()
add_test(NAME test_gps COMMAND test_gps)

# --- test_debug: GDB stub + core dump ---
add_executable(test_debug test_debug.c)
target_include_directories(test_debug PRIVATE
Expand Down Expand Up @@ -173,4 +181,4 @@ add_test(NAME test_devicetree COMMAND test_devicetree)

# --- Fuzz targets ---
# Opt-in (-DEOS_ENABLE_FUZZING=ON, Clang only); the subdirectory guards itself.
add_subdirectory(fuzz)
add_subdirectory(fuzz)
59 changes: 59 additions & 0 deletions tests/test_gps.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2026 EoS Project
// ISO/IEC 25000 | ISO/IEC/IEEE 15288:2023

#include <stdio.h>
#include <math.h>
#include <assert.h>
#include "eos/gps_nmea.h"

static void test_gprmc_valid_fix(void) {
const char *nmea =
"$GPRMC,092750.000,A,3746.4949,N,12225.1644,W,0.00,0.00,270526,,,A*7B";
eos_gps_data_t data;

assert(eos_gps_parse_gprmc(nmea, &data) == 0);
assert(data.fix_valid);
assert(fabs(data.latitude - 37.7749) < 0.01);
assert(fabs(data.longitude - (-122.4194)) < 0.01);
printf("[PASS] gps gprmc valid fix\n");
}

static void test_gprmc_void_fix(void) {
const char *nmea =
"$GPRMC,092750.000,V,3746.4949,N,12225.1644,W,0.00,0.00,270526,,,A*7B";
eos_gps_data_t data;

assert(eos_gps_parse_gprmc(nmea, &data) == 0);
assert(!data.fix_valid);
printf("[PASS] gps gprmc void fix\n");
}

static void test_gprmc_rejects_wrong_sentence(void) {
eos_gps_data_t data;
assert(eos_gps_parse_gprmc("$GPGGA,092750.000,3746.4949,N", &data) == -1);
printf("[PASS] gps gprmc rejects non-GPRMC sentence\n");
}

static void test_gprmc_rejects_null_args(void) {
eos_gps_data_t data;
assert(eos_gps_parse_gprmc(NULL, &data) == -1);
assert(eos_gps_parse_gprmc("$GPRMC,...", NULL) == -1);
printf("[PASS] gps gprmc rejects null args\n");
}

static void test_gprmc_rejects_short_sentence(void) {
eos_gps_data_t data;
assert(eos_gps_parse_gprmc("$GPRMC,092750.000,A", &data) == -2);
printf("[PASS] gps gprmc rejects short sentence\n");
}

int main(void) {
test_gprmc_valid_fix();
test_gprmc_void_fix();
test_gprmc_rejects_wrong_sentence();
test_gprmc_rejects_null_args();
test_gprmc_rejects_short_sentence();
printf("All GPS NMEA tests passed.\n");
return 0;
}