404 lines
18 KiB
C#
404 lines
18 KiB
C#
using System.Globalization;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using RuleEngine.Common;
|
|
using RuleEngine.Constants;
|
|
using RuleEngine.Database;
|
|
using RuleEngine.DTOs;
|
|
using RuleEngine.Interfaces;
|
|
using RuleEngine.Models;
|
|
using RuleEngine.Requests;
|
|
|
|
namespace RuleEngine.Services
|
|
{
|
|
public class DeviceService : IDeviceService
|
|
{
|
|
private readonly DatabaseContext _dbContext;
|
|
private readonly IConfiguration _config;
|
|
private readonly static string logFolderPath = LogConstants.LOG_FILE_PATH;
|
|
private readonly static string exceptionFolder = LogConstants.LOG_EXCEPTION_FILE_PATH;
|
|
private static readonly Dictionary<string, LimitedSizeQueue<DateTime>> dictCarHistory = [];
|
|
|
|
public DeviceService(DatabaseContext dbContext, IConfiguration config)
|
|
{
|
|
_dbContext = dbContext;
|
|
_config = config;
|
|
}
|
|
public async Task<bool> UpdatePVT(DeviceMessage deviceMessage)
|
|
{
|
|
DeviceLogRequest? deviceLogRequest = null;
|
|
try
|
|
{
|
|
var enableLogFile = _config.GetValue<bool>("EnableLogFile");
|
|
if (enableLogFile)
|
|
{
|
|
string Imei = "";
|
|
try
|
|
{
|
|
Imei = deviceMessage.Imei ?? string.Empty;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Log the exception
|
|
Console.WriteLine(ex.Message);
|
|
}
|
|
}
|
|
|
|
deviceLogRequest = CreatePVTRequest(deviceMessage);
|
|
if (deviceLogRequest == null)
|
|
{
|
|
return false;
|
|
}
|
|
if (deviceLogRequest.Code == "ERROR")
|
|
{
|
|
return false;
|
|
}
|
|
if (deviceLogRequest.GpsLat == 0 && deviceLogRequest.GpsLon == 0)
|
|
{
|
|
var online = _dbContext.Onlines.Where(x => (x.CarId ?? 0) == deviceLogRequest.CarID).FirstOrDefault();
|
|
if (online == null)
|
|
{
|
|
await UpdateOnlineProcedure(deviceLogRequest, deviceLogRequest.Imei);
|
|
}
|
|
else
|
|
{
|
|
if ((deviceLogRequest.GpsLat == 0) &&
|
|
(deviceLogRequest.GpsLon == 0))
|
|
{
|
|
deviceLogRequest.GpsLat = online.GpsLat;
|
|
deviceLogRequest.GpsLon = online.GpsLon;
|
|
}
|
|
//if ( (deviceLogRequest.NetworkLat == 0) &&
|
|
// (deviceLogRequest.NetworkLon == 0))
|
|
//{
|
|
// deviceLogRequest.NetworkLat = online.NetworkLat;
|
|
// deviceLogRequest.NetworkLon = online.NetworkLon;
|
|
//}
|
|
await UpdateOnlineProcedure(deviceLogRequest, deviceLogRequest.Imei);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
await UpdateOnlineProcedure(deviceLogRequest, deviceLogRequest.Imei);
|
|
}
|
|
|
|
await InsertHistoryProcedure(deviceLogRequest, deviceLogRequest.Imei);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Log the exception
|
|
if (Directory.Exists(logFolderPath))
|
|
StaticResources.Log2File(logFolderPath + "PVTException.txt", ex.ToString());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private DeviceLogRequest? CreatePVTRequest(DeviceMessage deviceMessage, bool bReupPVT = false)
|
|
{
|
|
DeviceLogRequest? requestLog = null;
|
|
var strServerTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
|
|
string Imei = deviceMessage?.Imei ?? string.Empty;
|
|
string strReceivedTime = deviceMessage?.ReceivedTime ?? string.Empty;
|
|
DateTime receivedTime = DateTime.UtcNow;
|
|
|
|
try
|
|
{
|
|
receivedTime = DateTime.ParseExact(strReceivedTime, "yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture);
|
|
if (!string.IsNullOrEmpty(strReceivedTime))
|
|
{
|
|
receivedTime = Convert.ToDateTime(strReceivedTime);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
StaticResources.Log2File(logFolderPath + "PVTException.txt", ex.ToString());
|
|
}
|
|
|
|
if ((bReupPVT == true) && (Imei != null) && (Imei != ""))
|
|
{
|
|
if (!dictCarHistory.TryGetValue(Imei, out LimitedSizeQueue<DateTime>? queue))
|
|
{
|
|
queue = new LimitedSizeQueue<DateTime>(QueueConstant.QUEUESIZE);
|
|
dictCarHistory.Add(Imei, queue);
|
|
}
|
|
|
|
if (queue != null && !queue.Contains(receivedTime))
|
|
{
|
|
queue.Enqueue(receivedTime);
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
double longtitude = deviceMessage?.Longitude ?? 0;
|
|
double latitude = deviceMessage?.Latitude ?? 0;
|
|
int gpsSpeed = deviceMessage?.GpsSpeed ?? 0;
|
|
bool isSos = deviceMessage?.IsSOS ?? false;
|
|
bool isStrongBoxOpen = deviceMessage?.IsStrongBoxOpen ?? false; //co mo ket: dong/mo
|
|
bool isEngineOn = deviceMessage?.IsEngineOn ?? false; //co dong co bat/tat
|
|
bool isStopping = deviceMessage?.IsStopping ?? false; //co dung do dung/do
|
|
bool isGPSLost = deviceMessage?.IsGPSLost ?? true; //co GPS mat/co
|
|
int totalImageCam1 = deviceMessage?.TotalImgCam1 ?? 0;
|
|
int totalImageCam2 = deviceMessage?.TotalImgCam2 ?? 0;
|
|
string strRFID = deviceMessage?.StrRFID ?? string.Empty;
|
|
string strOBD = deviceMessage?.StrOBD ?? string.Empty;
|
|
string strLac = deviceMessage?.LacID ?? string.Empty;
|
|
string version = deviceMessage?.Version ?? string.Empty;
|
|
var gpsInfor = deviceMessage?.GpsInfor;
|
|
bool isJamming = deviceMessage?.IsJamming ?? false;
|
|
bool isSpoofing = deviceMessage?.IsSpoofing ?? false;
|
|
bool cam1OK = deviceMessage?.Cam1OK ?? false;
|
|
bool cam2OK = deviceMessage?.Cam2OK ?? false;
|
|
bool camDetach = deviceMessage?.CamDetach ?? false;
|
|
double cell_lat = 0;
|
|
double cell_lon = 0;
|
|
try
|
|
{
|
|
if (gpsInfor != null)
|
|
{
|
|
int cellid = gpsInfor.Cellid != null ? Convert.ToInt32(gpsInfor.Cellid) : 0;
|
|
int lacid = gpsInfor.Lacid != null ? Convert.ToInt32(gpsInfor.Lacid) : 0;
|
|
int mcc = gpsInfor.Mcc != null ? Convert.ToInt32(gpsInfor.Mcc) : 0;
|
|
int mnc = gpsInfor.Mnc != null ? Convert.ToInt32(gpsInfor.Mnc) : 0;
|
|
string strCellType = gpsInfor.NetworkType != null ? gpsInfor.NetworkType.Trim() : string.Empty;
|
|
if ((cellid > 0) && (strCellType != null))
|
|
{
|
|
strCellType = strCellType.ToLower();
|
|
int? CellTypeGoogle = 0;
|
|
if (strCellType.Contains("cellsignalstrengthgsm"))
|
|
CellTypeGoogle = 3;
|
|
else if (strCellType.Contains("cellsignalstrengthcdma"))
|
|
CellTypeGoogle = 2;
|
|
else if (strCellType.Contains("cellsignalstrengthwcdma"))
|
|
CellTypeGoogle = 1;
|
|
else if (strCellType.Contains("cellsignalstrengthlte"))
|
|
CellTypeGoogle = 0;
|
|
var cellinfor = _dbContext.CellInfors.Where(x => (x.LacId == lacid) &&
|
|
(x.CellId == cellid) &&
|
|
(x.MCC == mcc) && (x.MNC == mnc)
|
|
&& (x.NetworkType == CellTypeGoogle)
|
|
).FirstOrDefault();
|
|
|
|
if (cellinfor == null)
|
|
{
|
|
if (CellTypeGoogle != null)
|
|
{
|
|
cellinfor = new CellInfor
|
|
{
|
|
CellId = cellid,
|
|
LacId = lacid,
|
|
MCC = mcc,
|
|
MNC = mnc,
|
|
NetworkType = CellTypeGoogle
|
|
};
|
|
_dbContext.CellInfors.Add(cellinfor);
|
|
_dbContext.SaveChanges();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cell_lat = cellinfor.NetworkLat ?? 0;
|
|
cell_lon = cellinfor.NetworkLon ?? 0;
|
|
if (cell_lat != 0 && cell_lon != 0 && latitude != 0 && longtitude != 0)
|
|
{
|
|
var dist = StaticResources.DistanceGpsCalculate(latitude, longtitude, cell_lat, cell_lon, 'K');
|
|
if (dist > DeviceConfig.SPOOFING_THRESH_DISTANCE)
|
|
{
|
|
isSpoofing = true;
|
|
var strLog = string.Format($"{strServerTime} {Imei} {cellinfor.Id} {cellinfor.NetworkLat} {cellinfor.NetworkLon} {latitude} {longtitude} {dist}");
|
|
if (Directory.Exists(logFolderPath))
|
|
StaticResources.Log2File(logFolderPath + "SpoofingDetection.txt", strLog);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (Directory.Exists(logFolderPath))
|
|
StaticResources.Log2File(logFolderPath + "CELLException.txt", ex.ToString());
|
|
}
|
|
return requestLog;
|
|
}
|
|
|
|
private async Task UpdateOnlineProcedure(DeviceLogRequest request, string imei)
|
|
{
|
|
try
|
|
{
|
|
DateTime currentTimeUTC = DateTime.UtcNow;
|
|
DateTime localTime = currentTimeUTC.AddHours(7);
|
|
|
|
if (request.ReceivedTime.Year <= (localTime.Year - 1)) //lost GPS
|
|
{
|
|
await UpdateLostGpsOnline(request.CarID, true, localTime);
|
|
return;
|
|
}
|
|
// loc ban tin tuong lai
|
|
TimeSpan diff02 = localTime.AddMinutes(5).Subtract(request.ReceivedTime);
|
|
if (diff02.TotalSeconds > 0) // TotalSeconds < 0 - ban tin gui lai, ko cap nhat bang truc tuyen
|
|
{
|
|
await UpdateOnlines(request, localTime);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
StaticResources.LogException2File(exceptionFolder, imei + "_ex_pvt", DateTime.UtcNow.ToString() + " InsertLst_TrucTuyen " + ex.ToString());
|
|
}
|
|
}
|
|
|
|
private async Task UpdateOnlines(DeviceLogRequest request, DateTime localTime)
|
|
{
|
|
var isSos = request.IsSos == true;
|
|
var isGpsLost = request.IsGPSLost == true;
|
|
var strongBoxOpen = request.IsStrongBoxOpen == true;
|
|
var engineOn = request.IsEngineOn == true;
|
|
|
|
var carId = request.CarID;
|
|
var deviceTime = request.ReceivedTime;
|
|
var resetStatusMinute = DeviceConfig.SECONDS_SET_CAR_STOP / 60;
|
|
|
|
var existingOnline = await _dbContext.Onlines
|
|
.FindAsync(carId);
|
|
|
|
if (existingOnline != null)
|
|
{
|
|
var diffSeconds = (deviceTime - existingOnline.DeviceTime)?.TotalSeconds ?? 0;
|
|
|
|
if (diffSeconds <= 0)
|
|
{
|
|
// Device sent an older or duplicate message; do nothing
|
|
return;
|
|
}
|
|
|
|
int carStatus = request.CarStatus ?? 0;
|
|
if (diffSeconds > resetStatusMinute)
|
|
{
|
|
carStatus = 2; // timeout -> set as disconnected
|
|
}
|
|
|
|
// Update record
|
|
existingOnline.GpsVelocity = request.GpsSpeed ?? 0;
|
|
existingOnline.IsSos = isSos;
|
|
existingOnline.IsGPSLost = isGpsLost;
|
|
existingOnline.StrongBoxOpen = strongBoxOpen;
|
|
existingOnline.EngineOn = engineOn;
|
|
existingOnline.CarStatus = carStatus;
|
|
existingOnline.Rfidstring = request.StrRFID;
|
|
existingOnline.CellId = request.CellID;
|
|
existingOnline.LacId = request.LacID ?? 0;
|
|
existingOnline.GpsLat = request.GpsLat ?? 0;
|
|
existingOnline.GpsLon = request.GpsLon ?? 0;
|
|
existingOnline.NetworkLat = request.NetworkLat ?? 0;
|
|
existingOnline.NetworkLon = request.NetworkLon ?? 0;
|
|
existingOnline.IsJamming = request.IsJamming == true;
|
|
existingOnline.IsSpoofing = request.IsSpoofing == true;
|
|
existingOnline.IsCam1OK = request.Cam1OK == true;
|
|
existingOnline.IsCam2OK = request.Cam2OK == true;
|
|
existingOnline.GpsInfor = request.GPSInfor ?? "";
|
|
existingOnline.ReceivedTime = localTime;
|
|
existingOnline.DeviceTime = deviceTime;
|
|
existingOnline.AppVersion = request.Version;
|
|
|
|
_dbContext.Onlines.Update(existingOnline);
|
|
}
|
|
else
|
|
{
|
|
// Insert new record
|
|
var newOnline = new Online
|
|
{
|
|
CarId = carId,
|
|
GpsVelocity = request.GpsSpeed ?? 0,
|
|
IsSos = isSos,
|
|
IsGPSLost = isGpsLost,
|
|
StrongBoxOpen = strongBoxOpen,
|
|
EngineOn = engineOn,
|
|
CarStatus = request.CarStatus ?? 0,
|
|
Rfidstring = request.StrRFID,
|
|
CellId = request.CellID,
|
|
LacId = request.LacID ?? 0,
|
|
GpsLat = request.GpsLat ?? 0,
|
|
GpsLon = request.GpsLon ?? 0,
|
|
NetworkLat = request.NetworkLat ?? 0,
|
|
NetworkLon = request.NetworkLon ?? 0,
|
|
IsJamming = request.IsJamming == true,
|
|
IsSpoofing = request.IsSpoofing == true,
|
|
IsCam1OK = request.Cam1OK == true,
|
|
IsCam2OK = request.Cam2OK == true,
|
|
GpsInfor = request.GPSInfor ?? "",
|
|
ReceivedTime = localTime,
|
|
DeviceTime = deviceTime,
|
|
AppVersion = request.Version
|
|
};
|
|
|
|
await _dbContext.Onlines.AddAsync(newOnline);
|
|
}
|
|
|
|
await _dbContext.SaveChangesAsync();
|
|
}
|
|
|
|
private async Task InsertHistoryProcedure(DeviceLogRequest request, string imei)
|
|
{
|
|
try
|
|
{
|
|
DateTime currentTimeUTC = DateTime.UtcNow;
|
|
DateTime localTime = currentTimeUTC.AddHours(7);
|
|
|
|
var history = new History
|
|
{
|
|
CarId = request.CarID,
|
|
UnitId = request.UnitID,
|
|
GpsVelocity = request.GpsSpeed ?? 0,
|
|
IsSos = request.IsSos == true,
|
|
IsGPSLost = request.IsGPSLost == true,
|
|
StrongBoxOpen = request.IsStrongBoxOpen == true,
|
|
EngineOn = request.IsEngineOn == true,
|
|
CarStatus = request.CarStatus ?? 0,
|
|
Rfidstring = request.StrRFID,
|
|
GpsLat = request.GpsLat ?? 0,
|
|
GpsLon = request.GpsLon ?? 0,
|
|
GpsInfor = request.GPSInfor ?? string.Empty,
|
|
IsJamming = request.IsJamming == true,
|
|
IsSpoofing = request.IsSpoofing == true,
|
|
Cam1OK = request.Cam1OK == true,
|
|
Cam2OK = request.Cam2OK == true,
|
|
CamDetach = request.CamDetach == true,
|
|
ReceivedTime = localTime,
|
|
DeviceTime = request.ReceivedTime,
|
|
DeviceDate = int.Parse(request.ReceivedTime.ToString("yyyyMMdd"))
|
|
};
|
|
|
|
await _dbContext.Histories.AddAsync(history);
|
|
await _dbContext.SaveChangesAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
StaticResources.LogException2File(exceptionFolder, imei + "_ex_pvt", DateTime.UtcNow.ToString() + " InsertHistoryProcedure " + ex.ToString());
|
|
}
|
|
}
|
|
|
|
public async Task UpdateLostGpsOnline(int carId, bool isGpsLost, DateTime receivedTime)
|
|
{
|
|
try
|
|
{
|
|
var online = await _dbContext.Onlines.FindAsync(carId);
|
|
|
|
if (online != null)
|
|
{
|
|
online.IsGPSLost = isGpsLost;
|
|
online.ReceivedTime = receivedTime;
|
|
|
|
await _dbContext.SaveChangesAsync();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
StaticResources.LogException2File(exceptionFolder, carId + "_ex_pvt", DateTime.UtcNow.ToString() + " UpdateLostGpsOnline " + ex.ToString());
|
|
}
|
|
}
|
|
|
|
}
|
|
} |