gps 测试

This commit is contained in:
yanghongwei 2024-08-04 22:18:34 +08:00
parent bb33e69cd8
commit 82cf538330
11 changed files with 386 additions and 9 deletions

View File

@ -9,6 +9,12 @@
缓存管理
</summary>
</member>
<member name="M:langguanApi.Common.CacheManager.#ctor(langguanApi.Common.Redis.RedisHelper)">
<summary>
构造函数
</summary>
<param name="redisHelper"></param>
</member>
<member name="M:langguanApi.Common.CacheManager.GetConvertVale``1(System.String,System.Func{System.Threading.Tasks.Task{``0}},System.Int32)">
<summary>
缓存数据
@ -19,11 +25,53 @@
<param name="seconds">缓存时间秒0=int.max </param>
<returns></returns>
</member>
<member name="T:langguanApi.Common.Gps.ProtocolParser">
<summary>
gps 协议解析器
</summary>
</member>
<member name="M:langguanApi.Common.Gps.ProtocolParser.ParseHeader(System.Byte[],System.Int32@)">
<summary>
解析消息头
</summary>
<param name="data"></param>
<param name="offset"></param>
<returns></returns>
</member>
<member name="M:langguanApi.Common.Gps.ProtocolParser.ParsePosition(System.Byte[])">
<summary>
解析位置信息
</summary>
<param name="data"></param>
<returns></returns>
</member>
<member name="M:langguanApi.Common.Gps.ProtocolParser.ParseTerminalRegisterMessage(System.Byte[],System.Int32@)">
<summary>
解析终端注册消息
</summary>
<param name="data"></param>
<param name="offset"></param>
<returns></returns>
</member>
<member name="M:langguanApi.Common.Gps.ProtocolParser.ParseLocationReportMessage(System.Byte[],System.Int32@)">
<summary>
解析位置上报消息
</summary>
<param name="data"></param>
<param name="offset"></param>
<returns></returns>
</member>
<member name="T:langguanApi.Common.Proxy.HttpProxy">
<summary>
http
</summary>
</member>
<member name="M:langguanApi.Common.Proxy.HttpProxy.#ctor(System.Net.Http.IHttpClientFactory)">
<summary>
构造函数
</summary>
<param name="httpClientFactory"></param>
</member>
<member name="M:langguanApi.Common.Proxy.HttpProxy.Get``1(System.Collections.Generic.Dictionary{System.String,System.String},System.String)">
<summary>
获取数据
@ -47,6 +95,11 @@
sub
</summary>
</member>
<member name="M:langguanApi.Common.Redis.RedisHelper.#ctor">
<summary>
构造函数
</summary>
</member>
<member name="F:langguanApi.Common.Redis.RedisKeylist.Weather">
<summary>
缓存天气信息

View File

@ -12,6 +12,10 @@ namespace langguanApi.Common
public class CacheManager
{
private readonly IDatabase _redisDatabase;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="redisHelper"></param>
public CacheManager(RedisHelper redisHelper)
{
_redisDatabase = redisHelper._database;

View File

@ -0,0 +1,31 @@
namespace langguanApi.Common.Gps
{
public class MessageHeader
{
public ushort MessageId { get; set; }
public ushort MessageBodyProperty { get; set; }
public string TerminalId { get; set; }
public ushort MessageSerialNumber { get; set; }
}
public class TerminalRegisterMessage
{
public ushort ProvinceId { get; set; }
public ushort CityId { get; set; }
public byte[] ManufacturerId { get; set; }
public byte[] TerminalType { get; set; }
public byte[] TerminalId { get; set; }
public byte LicensePlateColor { get; set; }
public string LicensePlate { get; set; }
}
public class LocationReportMessage
{
public uint AlarmFlag { get; set; }
public uint Status { get; set; }
public uint Latitude { get; set; }
public uint Longitude { get; set; }
public ushort Altitude { get; set; }
public ushort Speed { get; set; }
public ushort Direction { get; set; }
public DateTime Time { get; set; }
}
}

View File

@ -0,0 +1,110 @@
using System.Text;
namespace langguanApi.Common.Gps
{
/// <summary>
/// gps 协议解析器
/// </summary>
public class ProtocolParser
{
/// <summary>
/// 解析消息头
/// </summary>
/// <param name="data"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static MessageHeader ParseHeader(byte[] data, ref int offset)
{
var header = new MessageHeader
{
MessageId = BitConverter.ToUInt16(data, offset),
MessageBodyProperty = BitConverter.ToUInt16(data, offset + 2),
TerminalId = Encoding.ASCII.GetString(data, offset + 4, 6),
MessageSerialNumber = BitConverter.ToUInt16(data, offset + 10)
};
offset += 12;
return header;
}
public struct Position
{
public double Latitude;
public double Longitude;
public double Altitude;
}
/// <summary>
/// 解析位置信息
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static Position ParsePosition(byte[] data)
{
// 根据协议中的位置信息的偏移量和长度进行解析
int positionOffset = 21; // 位置信息在数据中的偏移量
int latitudeOffset = positionOffset + 0;
int longitudeOffset = positionOffset + 8;
int altitudeOffset = positionOffset + 16;
double latitude = BitConverter.ToDouble(data, latitudeOffset);
double longitude = BitConverter.ToDouble(data, longitudeOffset);
double altitude = BitConverter.ToDouble(data, altitudeOffset);
return new Position
{
Latitude = latitude,
Longitude = longitude,
Altitude = altitude
};
}
/// <summary>
/// 解析终端注册消息
/// </summary>
/// <param name="data"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static TerminalRegisterMessage ParseTerminalRegisterMessage(byte[] data, ref int offset)
{
var message = new TerminalRegisterMessage
{
ProvinceId = BitConverter.ToUInt16(data, offset),
CityId = BitConverter.ToUInt16(data, offset + 2),
ManufacturerId = data.Skip(offset + 4).Take(5).ToArray(),
TerminalType = data.Skip(offset + 9).Take(8).ToArray(),
TerminalId = data.Skip(offset + 17).Take(7).ToArray(),
LicensePlateColor = data[offset + 24],
LicensePlate = Encoding.ASCII.GetString(data, offset + 25, data.Length - offset - 25)
};
offset += 25 + message.LicensePlate.Length;
return message;
}
/// <summary>
/// 解析位置上报消息
/// </summary>
/// <param name="data"></param>
/// <param name="offset"></param>
/// <returns></returns>
public static LocationReportMessage ParseLocationReportMessage(byte[] data, ref int offset)
{
var message = new LocationReportMessage
{
AlarmFlag = BitConverter.ToUInt32(data, offset),
Status = BitConverter.ToUInt32(data, offset + 4),
Latitude = BitConverter.ToUInt32(data, offset + 8),
Longitude = BitConverter.ToUInt32(data, offset + 12),
Altitude = BitConverter.ToUInt16(data, offset + 16),
Speed = BitConverter.ToUInt16(data, offset + 18),
Direction = BitConverter.ToUInt16(data, offset + 20),
Time = DateTime.ParseExact(
Encoding.ASCII.GetString(data, offset + 22, 6),
"yyMMddHHmmss",
null
)
};
offset += 28;
return message;
}
}
}

View File

@ -10,6 +10,10 @@ namespace langguanApi.Common.Proxy
public class HttpProxy
{
private readonly IHttpClientFactory _httpClientFactory;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="httpClientFactory"></param>
public HttpProxy(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;

View File

@ -9,6 +9,9 @@ namespace langguanApi.Common.Redis
/// sub
/// </summary>
public ISubscriber _subscriber;
/// <summary>
/// 构造函数
/// </summary>
public RedisHelper()
{
// var con = RedisOptions.Default.GetConnect();

View File

@ -1,9 +1,17 @@
using langguanApi.Model;
using JT808.Protocol.MessageBody;
using JT808.Protocol;
using langguanApi.Model;
using langguanApi.Service;
using langguanApi.Service.HJ212;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Org.BouncyCastle.Utilities;
using System.Text;
using JT808.Protocol.Extensions;
using static langguanApi.Service.WeatherService;
using langguanApi.Common.Gps;
using NPOI.SS.Formula.Functions;
using static langguanApi.Common.Gps.ProtocolParser;
namespace langguanApi.Controllers
{
@ -35,11 +43,128 @@ namespace langguanApi.Controllers
/// <returns></returns>
public async Task<IActionResult> test(int num = 1, string key = "")
{
// 示例数据(需替换为实际接收到的协议数据)
string hexData = "787811010868120321167279808D3202001AB12F0D0A";
byte[] protocolData = HexStringToByteArray(hexData);
// 进行转义还原
byte[] restoredData = RestoreEscape(protocolData);
// 验证校验码
if (!VerifyChecksum(restoredData))
{
Console.WriteLine("Checksum verification failed.");
}
Position? position = ParsePosition(restoredData);
if (position.HasValue)
{
Console.WriteLine($"Latitude: {position.Value.Latitude}");
Console.WriteLine($"Longitude: {position.Value.Longitude}");
Console.WriteLine($"Altitude: {position.Value.Altitude}");
}
else
{
Console.WriteLine("Failed to parse position.");
}
// Console.WriteLine("经度:" + lon + " 纬度:" + lat);
// string rawText = "数据报:##0250QN=20240424224800000;ST=22;CN=2011;PW=123456;MN=LGYC022024690001;Flag=5;CP=&&DataTime=20240424224800;a34001-Rtd=356.2";
//NetPackage netPackage = NetPackage.Parse(rawText, null);
//((NetServer)Server).RaiseReceivedData(this, netPackage, rawText);
return Ok();
}
public static Position? ParsePosition(byte[] data)
{
// 根据协议中的位置信息的偏移量和长度进行解析
int positionOffset = 21; // 位置信息在数据中的偏移量
int latitudeOffset = positionOffset + 0;
int longitudeOffset = positionOffset + 4;
int altitudeOffset = positionOffset + 8;
// 检查数组长度是否足够长
if (data.Length < altitudeOffset + 2)
{
Console.WriteLine("Data array is not long enough to contain position information.");
return null;
}
// 解析纬度(单位:百万分之一度)
int rawLatitude = BitConverter.ToInt32(data, latitudeOffset);
double latitude = rawLatitude / 1000000.0;
// 解析经度(单位:百万分之一度)
int rawLongitude = BitConverter.ToInt32(data, longitudeOffset);
double longitude = rawLongitude / 1000000.0;
// 解析高度(单位:米)
int rawAltitude = BitConverter.ToInt16(data, altitudeOffset);
double altitude = rawAltitude;
return new Position
{
Latitude = latitude,
Longitude = longitude,
Altitude = altitude
};
}
private static bool VerifyChecksum(byte[] data)
{
// 校验码在数据包的倒数第二个字节
byte receivedChecksum = data[data.Length - 2];
byte calculatedChecksum = 0;
// 校验范围是从第一个字节到倒数第三个字节
for (int i = 0; i < data.Length - 2; i++)
{
calculatedChecksum ^= data[i];
}
return receivedChecksum == calculatedChecksum;
}
private static byte[] RestoreEscape(byte[] data)
{
List<byte> result = new List<byte>();
for (int i = 0; i < data.Length; i++)
{
if (data[i] == 0x7D)
{
if (i + 1 < data.Length)
{
if (data[i + 1] == 0x02)
{
result.Add(0x7E);
i++;
}
else if (data[i + 1] == 0x01)
{
result.Add(0x7D);
i++;
}
}
}
else
{
result.Add(data[i]);
}
}
return result.ToArray();
}
private static byte[] HexStringToByteArray(string hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
public struct Position
{
public double Latitude;
public double Longitude;
public double Altitude;
}
}
}

View File

@ -12,10 +12,12 @@ namespace langguanApi.Extensions
{
// services.AddSingleton<MQTTService>();
services.AddTransient<HJ212SocketServer>();
services.AddSingleton<Gps808SocketServer>(); // 808协议
services.AddTransient<PingService>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
_ = serviceProvider.GetService<HJ212SocketServer>().Start();
_ = serviceProvider.GetService<Gps808SocketServer>().Start();
serviceProvider.GetService<PingService>().CreatTask();
}
}

View File

@ -416,6 +416,8 @@
a34040,
a99010,
a99049,
LA,
a99054
//a99051,
#endregion

View File

@ -1,6 +1,13 @@
using IceCoffee.FastSocket.Tcp;
using JT808.Protocol;
using JT808.Protocol.Extensions;
using JT808.Protocol.MessageBody;
using langguanApi.Common.Gps;
using langguanApi.Model;
using Npoi.Mapper;
using NPOI.SS.Formula.Functions;
using System.Text;
using static langguanApi.Common.Gps.ProtocolParser;
namespace langguanApi.Service.HJ212
{
@ -31,11 +38,12 @@ namespace langguanApi.Service.HJ212
/// </summary>
protected override void OnReceived()
{
if (ReadBuffer.IndexOf(35) != 0L)// '#'
{
return;
// throw new Exception("异常TCP连接 IP: " + RemoteIPEndPoint);
}
//if (ReadBuffer.IndexOf(35) != 0L)// '#'
//{
// return;
// // throw new Exception("异常TCP连接 IP: " + RemoteIPEndPoint);
//}
string rawText = null;
while (ReadBuffer.CanReadLine)
@ -43,6 +51,41 @@ namespace langguanApi.Service.HJ212
try
{
byte[] data = ReadBuffer.ReadLine();
Console.WriteLine($"原始数据:{data}----------");
Console.WriteLine($"原始数据HexString:{data.ToHexString()}--------------------");
Console.WriteLine($"原始数据ASCII:{Encoding.ASCII.GetString(data)}-");
Position position = ParsePosition(data);
Console.WriteLine($"Latitude: {position.Latitude}");
Console.WriteLine($"Longitude: {position.Longitude}");
Console.WriteLine($"Altitude: {position.Altitude}");
int offset = 0;
// 解析消息头
var header = ProtocolParser.ParseHeader(data, ref offset);
Console.WriteLine($"Message ID: {header.MessageId}, Terminal ID: {header.TerminalId}");
// 解析终端注册消息
var registerMessage = ProtocolParser.ParseTerminalRegisterMessage(data, ref offset);
Console.WriteLine($"Province ID: {registerMessage.ProvinceId}, City ID: {registerMessage.CityId}");
Console.WriteLine($"License Plate: {registerMessage.LicensePlate}");
offset = 0;
// 解析位置信息汇报消息
var locationReportMessage = ProtocolParser.ParseLocationReportMessage(data, ref offset);
Console.WriteLine($"Latitude: {locationReportMessage.Latitude}, Longitude: {locationReportMessage.Longitude}");
Console.WriteLine($"Speed: {locationReportMessage.Speed}, Time: {locationReportMessage.Time}");
var jT808Package = new JT808Serializer().Deserialize(data);
//4.数据包体
JT808_0x0200 jT808_0x0200 = (JT808_0x0200)jT808Package.Bodies;
var lon = jT808_0x0200.Lat;
var lat = jT808_0x0200.Lng;
Console.WriteLine("经度:" + lon + " 纬度:" + lat);
rawText = Encoding.UTF8.GetString(data);
NetPackage netPackage = NetPackage.Parse(rawText, GetUnpackCache);
((NetServer)Server).RaiseReceivedData(this, netPackage, rawText);

View File

@ -35,7 +35,7 @@ namespace langguanApi.Service
/// <summary>
/// 服务端口号
/// </summary>
private int port => 5001;
private int port => 5003;
// 编码
// private string code;
/// <summary>