/* * Copyright (c) 2022 Actions Semi Co., Inc. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief gps service interface */ #include #include #include #include #include #include #include #include #include #include #include #include #define CONFIG_GPS_DEV_NAME "gps" #define CONFIG_SENSORSRV_STACKSIZE 2048 #define CONFIG_GPSSVR_PRIORITY 6 static gps_res_cb_t gps_res_cb = {NULL}; extern gps_res_t gps_res; void gps_event_report_nmea(uint8_t *gps_nmea_data) { struct app_msg msg = {0}; msg.type = MSG_SENSOR_EVENT; msg.cmd = MSG_GPS_NMEA_DATA; msg.ptr = gps_nmea_data; send_async_msg(GPS_SERVICE_NAME, &msg); } static void gps_notify_callback(struct device *dev, struct gps_value *val) { gps_event_report_nmea(val->gps_nmea_data); } static void _gps_service_init(void) { const struct device *gps_dev = device_get_binding("gps"); if (!gps_dev) { SYS_LOG_ERR("cannot found key dev gps\n"); } memset(&gps_res, 0, sizeof(gps_res)); gps_dev_register_notify(gps_dev, gps_notify_callback); SYS_LOG_INF("_gps_service_init\n"); } static void gps_enable(void) { const struct device *gps_dev = device_get_binding(CONFIG_GPS_DEV_NAME); if (!gps_dev) { SYS_LOG_ERR("cannot found key dev gps\n"); } gps_dev_enable(gps_dev); SYS_LOG_INF("gps_dev_enable\n"); } static void gps_disable(void) { const struct device *gps_dev = device_get_binding(CONFIG_GPS_DEV_NAME); if (!gps_dev) { SYS_LOG_ERR("cannot found key dev gps\n"); } gps_dev_disable(gps_dev); SYS_LOG_INF("gps_dev_disable\n"); } static void gps_minmea_parse(const char *sentence) { uint8_t parse_state = false; SYS_LOG_INF("gps sentence: %s\n", sentence); switch (minmea_sentence_id(sentence, false)) { #ifdef CONFIG_GPS_PARSE_RMC_ENABLE case MINMEA_SENTENCE_RMC: { struct minmea_sentence_rmc frame; if (minmea_parse_rmc(&frame, sentence)) { parse_state = true; memcpy(&gps_res.rmc_data, &frame, sizeof(frame)); SYS_LOG_INF("$xxRMC sentence parse ok\n"); } else { SYS_LOG_INF("$xxRMC sentence is not parsed\n"); } } break; #endif #ifdef CONFIG_GPS_PARSE_GGA_ENABLE case MINMEA_SENTENCE_GGA: { struct minmea_sentence_gga frame; if (minmea_parse_gga(&frame, sentence)) { parse_state = true; memcpy(&gps_res.gga_data, &frame, sizeof(frame)); // printk( "$xxGGA: hours: %d\n", frame.time.hours); // printk( "$xxGGA: minutes: %d\n", frame.time.minutes); // printk( "$xxGGA: seconds: %d\n", frame.time.seconds); // printk( "$xxGGA: microseconds: %d\n", frame.time.microseconds); // printk( "$xxGGA: latitude: %f\n", minmea_tofloat(&frame.latitude)); // printk( "$xxGGA: longitude: %f\n", minmea_tofloat(&frame.longitude)); // printk( "$xxGGA: hdop: %f\n", minmea_tofloat(&frame.hdop)); // printk( "$xxGGA: altitude: %f\n", minmea_tofloat(&frame.altitude)); // printk( "$xxGGA: height: %f\n", minmea_tofloat(&frame.height)); // printk( "$xxGGA: dgps_age: %f\n", minmea_tofloat(&frame.dgps_age)); SYS_LOG_INF("$xxGGA sentence parse ok\n"); } else { SYS_LOG_INF("$xxGGA sentence is not parsed\n"); } } break; #endif #ifdef CONFIG_GPS_PARSE_GST_ENABLE case MINMEA_SENTENCE_GST: { struct minmea_sentence_gst frame; if (minmea_parse_gst(&frame, sentence)) { parse_state = true; memcpy(&gps_res.gst_data, &frame, sizeof(frame)); SYS_LOG_INF("$xxGST sentence parse ok\n"); } else { SYS_LOG_INF("$xxGST sentence is not parsed\n"); } } break; #endif #ifdef CONFIG_GPS_PARSE_GSV_ENABLE case MINMEA_SENTENCE_GSV: { struct minmea_sentence_gsv frame; if (minmea_parse_gsv(&frame, sentence)) { parse_state = true; memcpy(&gps_res.gsv_data, &frame, sizeof(frame)); SYS_LOG_INF("$xxGSV sentence parse ok\n"); } else { SYS_LOG_INF("$xxGSV sentence is not parsed\n"); } } break; #endif #ifdef CONFIG_GPS_PARSE_VTG_ENABLE case MINMEA_SENTENCE_VTG: { struct minmea_sentence_vtg frame; if (minmea_parse_vtg(&frame, sentence)) { parse_state = true; memcpy(&gps_res.vtg_data, &frame, sizeof(frame)); SYS_LOG_INF("$xxVTG sentence parse ok"); } else { SYS_LOG_INF("$xxVTG sentence is not parsed\n"); } } break; #endif #ifdef CONFIG_GPS_PARSE_ZDA_ENABLE case MINMEA_SENTENCE_ZDA: { struct minmea_sentence_zda frame; if (minmea_parse_zda(&frame, sentence)) { parse_state = true; emcpy(&gps_res.zda_data, &frame, sizeof(frame)); SYS_LOG_INF("$xxZDA sentence parse ok\n"); } else { SYS_LOG_INF("$xxZDA sentence is not parsed\n"); } } break; #endif case MINMEA_INVALID: { SYS_LOG_INF("$xxxxx sentence is not valid\n"); } break; default: { SYS_LOG_INF("$xxxxx sentence is not parsed\n"); } break; } if ((parse_state == true) && (gps_res_cb != NULL)) { gps_res_cb(0, &gps_res); } } static void _gps_service_proc(struct app_msg *msg) { switch (msg->cmd) { case MSG_GPS_ENABLE: gps_enable(); break; case MSG_GPS_DISABLE: gps_disable(); break; case MSG_GPS_NMEA_DATA: gps_minmea_parse(msg->ptr); break; case MSG_GPS_ADD_CB: gps_res_cb = (gps_res_cb_t)msg->ptr; break; case MSG_GPS_REMOVE_CB: gps_res_cb = NULL; break; default: break; } } static void _gps_service_main_loop(void *parama1, void *parama2, void *parama3) { struct app_msg msg = {0}; bool terminaltion = false; bool suspended = false; int timeout; int result = 0; printk("gps_service enter\n"); while (!terminaltion) { timeout = suspended ? OS_FOREVER : thread_timer_next_timeout(); if (receive_msg(&msg, timeout)) { // SYS_LOG_INF("gps_service msg:%d, cmd:%d\n", msg.type, msg.cmd); switch (msg.type) { case MSG_INIT_APP: _gps_service_init(); break; // case MSG_EXIT_APP: // _sensor_service_exit(); // terminaltion = true; // break; case MSG_SENSOR_EVENT: _gps_service_proc(&msg); break; // case MSG_SUSPEND_APP: // SYS_LOG_INF("SUSPEND_APP"); // sensor_sleep_suspend(); // suspended = true; // break; // case MSG_RESUME_APP: // SYS_LOG_INF("RESUME_APP"); // sensor_sleep_resume(); // suspended = false; // break; default: break; } if (msg.callback) { msg.callback(&msg, result, NULL); } } thread_timer_handle_expired(); } } char __aligned(ARCH_STACK_PTR_ALIGN) gpssrv_stack_area[CONFIG_SENSORSRV_STACKSIZE]; SERVICE_DEFINE(gps_service, gpssrv_stack_area, sizeof(gpssrv_stack_area), CONFIG_GPSSVR_PRIORITY, BACKGROUND_APP, NULL, NULL, NULL, _gps_service_main_loop);