CarTrackingRuleEngine/RuleEngine/Services/DeviceService.cs

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());
}
}
}
}