You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建接收原始NMEA消息的API并将GPS数据存入SQL表

解决方案:ASP.NET Web API接收NMEA格式GPS数据并存入SQL表

1. 修改API控制器,接收原始NMEA文本

原控制器绑定JSON模型的方式无法处理纯文本格式的NMEA数据,需要改为直接读取请求的原始内容。调整后的代码如下:

public class GPSStatusController : ApiController
{
    public async Task<HttpResponseMessage> Post()
    {
        // 读取请求中的原始NMEA文本
        string nmeaData = await Request.Content.ReadAsStringAsync();
        
        if (string.IsNullOrWhiteSpace(nmeaData))
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "NMEA数据不能为空");
        }

        using (LocationEntities entities = new LocationEntities())
        {
            var gpsRecord = new GPSStatu(); 
            // 设备ID建议从请求头(如Device-ID)或NMEA数据中提取,这里替换为实际逻辑
            gpsRecord.ID = Request.Headers.GetValues("Device-ID").FirstOrDefault() ?? "未知设备";
            gpsRecord.GPSData = nmeaData; // 若需存原始NMEA字符串,直接赋值即可
            
            // 注意:原代码中BatteryStatus应为对应GPSStatu的DbSet名称,需根据实际项目调整
            entities.GPSStatu.Add(gpsRecord);
            entities.SaveChanges();
        }

        return Request.CreateResponse(HttpStatusCode.OK, "数据已成功保存");
    }
}

2. 配置API支持text/plain请求格式

默认ASP.NET Web API不支持解析text/plain类型的请求,需要添加自定义格式化器。在WebApiConfig.cs中添加以下配置:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // 添加text/plain格式支持
        config.Formatters.Add(new PlainTextFormatter());
        
        // 原有路由配置保持不变
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

// 自定义文本格式化器
public class PlainTextFormatter : MediaTypeFormatter
{
    public PlainTextFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
    }

    public override bool CanReadType(Type type) => type == typeof(string);
    public override bool CanWriteType(Type type) => type == typeof(string);

    public override async Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
    {
        using (var reader = new StreamReader(readStream))
        {
            return await reader.ReadToEndAsync();
        }
    }

    public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
    {
        if (value is string text)
        {
            using (var writer = new StreamWriter(writeStream))
            {
                await writer.WriteAsync(text);
            }
        }
    }
}

3. 可选:解析NMEA为结构化数据存储

如果需要将NMEA解析为经纬度、时间等结构化数据存入数据库,可添加解析逻辑示例:

// 解析NMEA语句为结构化数据
private GPSStatu ParseNmeaToStructuredData(string nmeaData)
{
    var gpsData = new GPSStatu();
    var lines = nmeaData.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
    
    foreach (var line in lines)
    {
        if (!line.StartsWith("$")) continue;
        
        var parts = line.Split('*');
        var fields = parts[0].Split(',');
        
        switch (fields[0])
        {
            case "$GPGLL":
                // 解析纬度、经度、时间
                gpsData.Latitude = ConvertNmeaCoordinate(fields[1], fields[2]);
                gpsData.Longitude = ConvertNmeaCoordinate(fields[3], fields[4]);
                gpsData.Timestamp = ParseNmeaUtcTime(fields[5]);
                break;
            case "$GPGSA":
                // 解析定位类型、卫星数量
                gpsData.FixType = fields[1];
                gpsData.SatelliteCount = int.TryParse(fields[2], out var count) ? count : 0;
                break;
        }
    }
    return gpsData;
}

// 将NMEA坐标转换为十进制格式
private double ConvertNmeaCoordinate(string coordStr, string direction)
{
    if (string.IsNullOrWhiteSpace(coordStr)) return 0;
    
    var degreeIndex = coordStr.IndexOf('.') - 2;
    var degrees = double.Parse(coordStr.Substring(0, degreeIndex));
    var minutes = double.Parse(coordStr.Substring(degreeIndex));
    var decimalDeg = degrees + minutes / 60;
    
    // 根据方向调整正负(南/S、西/W为负)
    return (direction == "S" || direction == "W") ? -decimalDeg : decimalDeg;
}

// 解析NMEA UTC时间为DateTime
private DateTime ParseNmeaUtcTime(string timeStr)
{
    if (string.IsNullOrWhiteSpace(timeStr)) return DateTime.UtcNow;
    
    var hours = int.Parse(timeStr.Substring(0, 2));
    var minutes = int.Parse(timeStr.Substring(2, 2));
    var seconds = double.Parse(timeStr.Substring(4));
    
    var utcDate = DateTime.UtcNow.Date;
    return new DateTime(utcDate.Year, utcDate.Month, utcDate.Day, hours, minutes, (int)seconds, DateTimeKind.Utc);
}

修改控制器Post方法使用该解析逻辑:

public async Task<HttpResponseMessage> Post()
{
    string nmeaData = await Request.Content.ReadAsStringAsync();
    
    if (string.IsNullOrWhiteSpace(nmeaData))
    {
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "NMEA数据不能为空");
    }

    var parsedData = ParseNmeaToStructuredData(nmeaData);
    parsedData.ID = Request.Headers.GetValues("Device-ID").FirstOrDefault() ?? "未知设备";

    using (LocationEntities entities = new LocationEntities())
    {
        entities.GPSStatu.Add(parsedData);
        entities.SaveChanges();
    }

    return Request.CreateResponse(HttpStatusCode.OK, "数据已解析并保存");
}

4. 测试方法

用Postman或curl发起请求:

  • 请求方法:POST
  • URL:http://你的API地址/api/GPSStatus
  • 请求头:Content-Type: text/plain
  • 请求体:粘贴提供的NMEA数据示例

内容的提问来源于stack exchange,提问作者Sudhe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 10:25:21