rama creada apartir de master en j
This commit is contained in:
@@ -9,6 +9,10 @@ using MongoDB.Bson;
|
||||
|
||||
namespace adas_core.Application.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Provides the concrete implementation of the <see cref="IDeviceService"/> contract,
|
||||
/// handling device-related service operations defined by the interface.
|
||||
/// </summary>
|
||||
public class DeviceService : IDeviceService
|
||||
{
|
||||
private readonly IDeviceRepository _deviceRepository;
|
||||
@@ -34,213 +38,263 @@ public class DeviceService : IDeviceService
|
||||
_alarmService = alarmService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="DeviceDto"/> into a <see cref="Device"/> entity by mapping its properties. Applies a fallback to an empty list when <c>PointOfCareIds</c> is null, and to a new <see cref="DeviceSettings"/> instance when <c>Settings</c> is null.
|
||||
/// </summary>
|
||||
/// <param name="dto">The data transfer object containing the device information to convert.</param>
|
||||
/// <returns>A new <see cref="Device"/> entity populated with the values from the supplied DTO.</returns>
|
||||
public Device ToEntity(DeviceDto dto)
|
||||
{
|
||||
return new Device()
|
||||
{
|
||||
DeviceType = dto.DeviceType,
|
||||
MacAddr = dto.MacAddr,
|
||||
SerialNumber = dto.SerialNumber,
|
||||
Name = dto.Name,
|
||||
Battery = dto.Battery,
|
||||
Color = dto.Color,
|
||||
Connected = dto.Connected,
|
||||
Ready = dto.Ready,
|
||||
Uuid = dto.Uuid,
|
||||
Key = dto.Key,
|
||||
CreatedAt = dto.CreatedAt,
|
||||
UpdatedAt = dto.UpdatedAt,
|
||||
PointOfCareIds = dto.PointOfCareIds ?? new List<ObjectId>(),
|
||||
Settings = dto.Settings ?? new DeviceSettings()
|
||||
};
|
||||
}
|
||||
return new Device()
|
||||
{
|
||||
DeviceType = dto.DeviceType,
|
||||
MacAddr = dto.MacAddr,
|
||||
SerialNumber = dto.SerialNumber,
|
||||
Name = dto.Name,
|
||||
Battery = dto.Battery,
|
||||
Color = dto.Color,
|
||||
Connected = dto.Connected,
|
||||
Ready = dto.Ready,
|
||||
Uuid = dto.Uuid,
|
||||
Key = dto.Key,
|
||||
CreatedAt = dto.CreatedAt,
|
||||
UpdatedAt = dto.UpdatedAt,
|
||||
PointOfCareIds = dto.PointOfCareIds ?? new List<ObjectId>(),
|
||||
Settings = dto.Settings ?? new DeviceSettings()
|
||||
};
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a new device entity from the provided DTO, sets the creation and update timestamps to the current UTC time, and persists it via the device repository.
|
||||
/// </summary>
|
||||
/// <param name="deviceDto">The data transfer object containing the device information to be mapped and stored.</param>
|
||||
/// <returns>The created <see cref="Device"/> entity after successful insertion, or <see langword="null"/> if the device could not be created.</returns>
|
||||
public async Task<Device?> Create(DeviceDto deviceDto)
|
||||
{
|
||||
var device = ToEntity(deviceDto);
|
||||
device.CreatedAt = DateTime.UtcNow;
|
||||
device.UpdatedAt = DateTime.UtcNow;
|
||||
await _deviceRepository.InsertOneAsync(device);
|
||||
return device;
|
||||
}
|
||||
{
|
||||
var device = ToEntity(deviceDto);
|
||||
device.CreatedAt = DateTime.UtcNow;
|
||||
device.UpdatedAt = DateTime.UtcNow;
|
||||
await _deviceRepository.InsertOneAsync(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an object identified by the specified <paramref name="objectId"/> by delegating to the device repository.
|
||||
/// Returns <c>true</c> when the repository's delete operation yields a non-null result, and <c>false</c> when the result is <c>null</c> (e.g., the object was not found or could not be deleted).
|
||||
/// </summary>
|
||||
/// <param name="objectId">The unique identifier of the object to delete.</param>
|
||||
/// <returns>A task that resolves to <c>true</c> if the object was deleted; otherwise, <c>false</c>.</returns>
|
||||
public async Task<bool> Delete(ObjectId objectId)
|
||||
{
|
||||
return await _deviceRepository.DeleteAsync(objectId) != null;
|
||||
}
|
||||
{
|
||||
return await _deviceRepository.DeleteAsync(objectId) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing device by mapping the provided DTO to a device entity, setting the update timestamp, and persisting the changes through the repository.
|
||||
/// </summary>
|
||||
/// <param name="deviceDto">The data transfer object containing the updated device information.</param>
|
||||
/// <returns>The updated <see cref="Device"/> entity, or <c>null</c> if no device is returned.</returns>
|
||||
public async Task<Device?> Update(DeviceDto deviceDto)
|
||||
{
|
||||
var device = ToEntity(deviceDto);
|
||||
device.UpdatedAt = DateTime.UtcNow;
|
||||
await _deviceRepository.UpdateOneAsync(device.Id, device);
|
||||
return device;
|
||||
}
|
||||
{
|
||||
var device = ToEntity(deviceDto);
|
||||
device.UpdatedAt = DateTime.UtcNow;
|
||||
await _deviceRepository.UpdateOneAsync(device.Id, device);
|
||||
return device;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes an incoming device event by locating an existing device or creating a new one, then handling device-type-specific logic. Looks up the device using the MAC address, serial number, UUID, or key in that order, falling back to creating a new record when no match is found. When the device is a button, additional button management logic is invoked.
|
||||
/// </summary>
|
||||
/// <param name="deviceDto">The data transfer object containing the device information from the event, used for lookup and creation.</param>
|
||||
/// <returns>The existing or newly created <see cref="Device"/> associated with the event.</returns>
|
||||
public async Task<Device?> ReceiveEvent(DeviceDto deviceDto)
|
||||
{
|
||||
Device? deviceExist = null;
|
||||
if (!string.IsNullOrEmpty(deviceDto.MacAddr))
|
||||
{
|
||||
deviceExist = await _deviceRepository.FindByMacAddr(deviceDto.MacAddr);
|
||||
Device? deviceExist = null;
|
||||
if (!string.IsNullOrEmpty(deviceDto.MacAddr))
|
||||
{
|
||||
deviceExist = await _deviceRepository.FindByMacAddr(deviceDto.MacAddr);
|
||||
}
|
||||
|
||||
if (deviceExist == null && deviceDto.SerialNumber != null)
|
||||
{
|
||||
deviceExist = await _deviceRepository.FindBySerialNumber(deviceDto.SerialNumber);
|
||||
}
|
||||
|
||||
if (deviceExist == null && deviceDto.Uuid != null)
|
||||
{
|
||||
deviceExist = await _deviceRepository.FindByUuid(deviceDto.Uuid);
|
||||
}
|
||||
|
||||
if (deviceExist == null && deviceDto.Key != null)
|
||||
{
|
||||
deviceExist = await _deviceRepository.FindByKey(deviceDto.Key);
|
||||
}
|
||||
|
||||
if (deviceExist == null)
|
||||
{
|
||||
deviceExist = ToEntity(deviceDto);
|
||||
deviceExist.CreatedAt = DateTime.UtcNow;
|
||||
deviceExist.UpdatedAt = DateTime.UtcNow;
|
||||
await _deviceRepository.InsertOneAsync(deviceExist);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _deviceRepository.UpdateDeviceStats(deviceExist.Id, deviceDto);
|
||||
}
|
||||
|
||||
switch (deviceDto.DeviceType)
|
||||
{
|
||||
case DeviceType.Unknown:
|
||||
break;
|
||||
case DeviceType.Button:
|
||||
await ManageDeviceButton(deviceExist, deviceDto);
|
||||
break;
|
||||
}
|
||||
|
||||
return deviceExist;
|
||||
}
|
||||
|
||||
if (deviceExist == null && deviceDto.SerialNumber != null)
|
||||
{
|
||||
deviceExist = await _deviceRepository.FindBySerialNumber(deviceDto.SerialNumber);
|
||||
}
|
||||
|
||||
if (deviceExist == null && deviceDto.Uuid != null)
|
||||
{
|
||||
deviceExist = await _deviceRepository.FindByUuid(deviceDto.Uuid);
|
||||
}
|
||||
|
||||
if (deviceExist == null && deviceDto.Key != null)
|
||||
{
|
||||
deviceExist = await _deviceRepository.FindByKey(deviceDto.Key);
|
||||
}
|
||||
|
||||
if (deviceExist == null)
|
||||
{
|
||||
deviceExist = ToEntity(deviceDto);
|
||||
deviceExist.CreatedAt = DateTime.UtcNow;
|
||||
deviceExist.UpdatedAt = DateTime.UtcNow;
|
||||
await _deviceRepository.InsertOneAsync(deviceExist);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _deviceRepository.UpdateDeviceStats(deviceExist.Id, deviceDto);
|
||||
}
|
||||
|
||||
switch (deviceDto.DeviceType)
|
||||
{
|
||||
case DeviceType.Unknown:
|
||||
break;
|
||||
case DeviceType.Button:
|
||||
await ManageDeviceButton(deviceExist, deviceDto);
|
||||
break;
|
||||
}
|
||||
|
||||
return deviceExist;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles device button actions by dispatching the configured action type (sending an observation or alarm) when both the device's configured action and the received click event are present.
|
||||
/// </summary>
|
||||
/// <param name="deviceExist">The existing device whose configured action settings determine which action to execute.</param>
|
||||
/// <param name="deviceDto">The incoming device event payload providing the click type that triggers the action.</param>
|
||||
private async Task ManageDeviceButton(Device deviceExist, DeviceDto deviceDto)
|
||||
{
|
||||
if (deviceExist.Settings?.Action?.Type != null && deviceDto.Event?.ClickType != null)
|
||||
{
|
||||
switch (deviceExist.Settings.Action.Type)
|
||||
if (deviceExist.Settings?.Action?.Type != null && deviceDto.Event?.ClickType != null)
|
||||
{
|
||||
case DeviceActionType.SendObs:
|
||||
await SendObservationOnAction(deviceExist.Settings.Action, deviceDto.Event.ClickType.Value, deviceExist.PointOfCareIds);
|
||||
break;
|
||||
case DeviceActionType.SendAlarm:
|
||||
await SendAlarmOnAction(deviceExist.Settings.Action, deviceDto.Event.ClickType.Value, deviceExist.PointOfCareIds);
|
||||
break;
|
||||
switch (deviceExist.Settings.Action.Type)
|
||||
{
|
||||
case DeviceActionType.SendObs:
|
||||
await SendObservationOnAction(deviceExist.Settings.Action, deviceDto.Event.ClickType.Value, deviceExist.PointOfCareIds);
|
||||
break;
|
||||
case DeviceActionType.SendAlarm:
|
||||
await SendAlarmOnAction(deviceExist.Settings.Action, deviceDto.Event.ClickType.Value, deviceExist.PointOfCareIds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a patient observation alarm based on a device action and the type of click event that triggered it.
|
||||
/// The alarm value is selected from the device action's configuration according to the click type
|
||||
/// (SingleClick, DoubleClick, or Hold) and is dispatched for each point of care that has an associated patient.
|
||||
/// The method exits early when the configuration observation cannot be found or when the action has no value defined for the current click type.
|
||||
/// </summary>
|
||||
/// <param name="settingsAction">The device action containing the configuration observation and the per-click-type alarm values to use.</param>
|
||||
/// <param name="eventClickType">The click event that triggered the action, which determines which value from the device action is sent.</param>
|
||||
/// <param name="deviceExistPointOfCareIds">The list of point of care identifiers whose patients should receive the alarm.</param>
|
||||
private async Task SendAlarmOnAction(
|
||||
DeviceAction settingsAction,
|
||||
ClickType eventClickType,
|
||||
List<ObjectId> deviceExistPointOfCareIds)
|
||||
{
|
||||
var configObs = await _configObservationService.GetConfigById(settingsAction.ConfigObservationId);
|
||||
if(configObs == null) return;
|
||||
var obsData = new ObservationData
|
||||
DeviceAction settingsAction,
|
||||
ClickType eventClickType,
|
||||
List<ObjectId> deviceExistPointOfCareIds)
|
||||
{
|
||||
Code = configObs.Code,
|
||||
CodingSystem = configObs.CodingSystem,
|
||||
Time = DateTime.UtcNow,
|
||||
Text = configObs.Name,
|
||||
};
|
||||
var obs = new PatientObservationAlarm
|
||||
{
|
||||
InactivationState = new InactivationState{ Visual = AlarmEnum.AudioVideoState.Enabled, Audio = AlarmEnum.AudioVideoState.Enabled},
|
||||
MessageTime = DateTime.UtcNow,
|
||||
Persist = true,
|
||||
Code = obsData.Code,
|
||||
CodingSystem = obsData.CodingSystem,
|
||||
Name = configObs.Name,
|
||||
Time = DateTime.UtcNow
|
||||
};
|
||||
foreach (var pocId in deviceExistPointOfCareIds)
|
||||
{
|
||||
var data = await _pointOfCareService.GetInfo(pocId, null, true);
|
||||
if (data != null && data.Patient?.Id != null)
|
||||
var configObs = await _configObservationService.GetConfigById(settingsAction.ConfigObservationId);
|
||||
if(configObs == null) return;
|
||||
var obsData = new ObservationData
|
||||
{
|
||||
obs.PatientId = data.Patient.Id;
|
||||
obs.Patient = data.Patient;
|
||||
switch (eventClickType)
|
||||
Code = configObs.Code,
|
||||
CodingSystem = configObs.CodingSystem,
|
||||
Time = DateTime.UtcNow,
|
||||
Text = configObs.Name,
|
||||
};
|
||||
var obs = new PatientObservationAlarm
|
||||
{
|
||||
InactivationState = new InactivationState{ Visual = AlarmEnum.AudioVideoState.Enabled, Audio = AlarmEnum.AudioVideoState.Enabled},
|
||||
MessageTime = DateTime.UtcNow,
|
||||
Persist = true,
|
||||
Code = obsData.Code,
|
||||
CodingSystem = obsData.CodingSystem,
|
||||
Name = configObs.Name,
|
||||
Time = DateTime.UtcNow
|
||||
};
|
||||
foreach (var pocId in deviceExistPointOfCareIds)
|
||||
{
|
||||
var data = await _pointOfCareService.GetInfo(pocId, null, true);
|
||||
if (data != null && data.Patient?.Id != null)
|
||||
{
|
||||
case ClickType.SingleClick:
|
||||
if(settingsAction.ValueOnSingleClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnSingleClick;
|
||||
break;
|
||||
case ClickType.DoubleClick:
|
||||
if(settingsAction.ValueOnDoubleClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnDoubleClick;
|
||||
break;
|
||||
case ClickType.Hold:
|
||||
if(settingsAction.ValueOnHoldClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnHoldClick;
|
||||
break;
|
||||
obs.PatientId = data.Patient.Id;
|
||||
obs.Patient = data.Patient;
|
||||
switch (eventClickType)
|
||||
{
|
||||
case ClickType.SingleClick:
|
||||
if(settingsAction.ValueOnSingleClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnSingleClick;
|
||||
break;
|
||||
case ClickType.DoubleClick:
|
||||
if(settingsAction.ValueOnDoubleClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnDoubleClick;
|
||||
break;
|
||||
case ClickType.Hold:
|
||||
if(settingsAction.ValueOnHoldClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnHoldClick;
|
||||
break;
|
||||
}
|
||||
// Process Obs on service
|
||||
await _alarmService.ProcessAlarmObservations(new List<PatientObservationAlarm>{obs},new List<PatientObservation>(){new (){Name = configObs.Name, Value = obs.Value, Code = obsData.Code, CodingSystem = obsData.CodingSystem}}, data.Patient, DateTime.UtcNow, obsData);
|
||||
}
|
||||
// Process Obs on service
|
||||
await _alarmService.ProcessAlarmObservations(new List<PatientObservationAlarm>{obs},new List<PatientObservation>(){new (){Name = configObs.Name, Value = obs.Value, Code = obsData.Code, CodingSystem = obsData.CodingSystem}}, data.Patient, DateTime.UtcNow, obsData);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a patient observation derived from the configuration linked to a device action, applying the value
|
||||
/// associated with the specified click type (single, double, or hold) for each point of care patient found.
|
||||
/// The method short-circuits when the configuration observation is missing or when no value is defined for
|
||||
/// the given click type.
|
||||
/// </summary>
|
||||
/// <param name="settingsAction">The device action whose associated configuration observation and per-click values drive the observation payload.</param>
|
||||
/// <param name="eventClickType">The type of click event that triggered the action; selects which value (single, double, or hold) is assigned to the observation.</param>
|
||||
/// <param name="deviceExistPointOfCareIds">The list of point of care identifiers whose resolved patients will receive the generated observation.</param>
|
||||
/// <returns>A task that represents the asynchronous send operation; no meaningful business result is returned.</returns>
|
||||
private async Task SendObservationOnAction(
|
||||
DeviceAction settingsAction,
|
||||
ClickType eventClickType,
|
||||
List<ObjectId> deviceExistPointOfCareIds)
|
||||
{
|
||||
var configObs = await _configObservationService.GetConfigById(settingsAction.ConfigObservationId);
|
||||
if(configObs == null) return;
|
||||
var obsData = new ObservationData
|
||||
DeviceAction settingsAction,
|
||||
ClickType eventClickType,
|
||||
List<ObjectId> deviceExistPointOfCareIds)
|
||||
{
|
||||
Code = configObs.Code,
|
||||
CodingSystem = configObs.CodingSystem,
|
||||
Time = DateTime.UtcNow,
|
||||
Text = configObs.Name,
|
||||
};
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
MessageTime = DateTime.UtcNow,
|
||||
Persist = true,
|
||||
Code = obsData.Code,
|
||||
CodingSystem = obsData.CodingSystem,
|
||||
Name = configObs.Name,
|
||||
Time = DateTime.UtcNow
|
||||
};
|
||||
foreach (var pocId in deviceExistPointOfCareIds)
|
||||
{
|
||||
var data = await _pointOfCareService.GetInfo(pocId, null, true);
|
||||
if (data != null && data.Patient?.Id != null)
|
||||
var configObs = await _configObservationService.GetConfigById(settingsAction.ConfigObservationId);
|
||||
if(configObs == null) return;
|
||||
var obsData = new ObservationData
|
||||
{
|
||||
obs.PatientId = data.Patient.Id;
|
||||
obs.Patient = data.Patient;
|
||||
switch (eventClickType)
|
||||
Code = configObs.Code,
|
||||
CodingSystem = configObs.CodingSystem,
|
||||
Time = DateTime.UtcNow,
|
||||
Text = configObs.Name,
|
||||
};
|
||||
var obs = new PatientObservation
|
||||
{
|
||||
MessageTime = DateTime.UtcNow,
|
||||
Persist = true,
|
||||
Code = obsData.Code,
|
||||
CodingSystem = obsData.CodingSystem,
|
||||
Name = configObs.Name,
|
||||
Time = DateTime.UtcNow
|
||||
};
|
||||
foreach (var pocId in deviceExistPointOfCareIds)
|
||||
{
|
||||
var data = await _pointOfCareService.GetInfo(pocId, null, true);
|
||||
if (data != null && data.Patient?.Id != null)
|
||||
{
|
||||
case ClickType.SingleClick:
|
||||
if(settingsAction.ValueOnSingleClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnSingleClick;
|
||||
break;
|
||||
case ClickType.DoubleClick:
|
||||
if(settingsAction.ValueOnDoubleClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnDoubleClick;
|
||||
break;
|
||||
case ClickType.Hold:
|
||||
if(settingsAction.ValueOnHoldClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnHoldClick;
|
||||
break;
|
||||
obs.PatientId = data.Patient.Id;
|
||||
obs.Patient = data.Patient;
|
||||
switch (eventClickType)
|
||||
{
|
||||
case ClickType.SingleClick:
|
||||
if(settingsAction.ValueOnSingleClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnSingleClick;
|
||||
break;
|
||||
case ClickType.DoubleClick:
|
||||
if(settingsAction.ValueOnDoubleClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnDoubleClick;
|
||||
break;
|
||||
case ClickType.Hold:
|
||||
if(settingsAction.ValueOnHoldClick == null) return;
|
||||
obs.Value = settingsAction.ValueOnHoldClick;
|
||||
break;
|
||||
}
|
||||
// Process Obs on service
|
||||
_observationService.ProcessObservations(new List<PatientObservation>{obs}, data.Patient, DateTime.UtcNow, obsData);
|
||||
}
|
||||
// Process Obs on service
|
||||
_observationService.ProcessObservations(new List<PatientObservation>{obs}, data.Patient, DateTime.UtcNow, obsData);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user