2023-08-11 16:50:41 +02:00

518 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Authentication;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;
using Mqtt.Client.AspNetCore.Services;
using MyCore.Interfaces.DTO;
using MyCore.Interfaces.Models;
using MyCore.Service.Controllers.Helpers;
using MyCore.Service.Services;
using MyCore.Services;
using MyCore.Services.Devices;
using MyCore.Services.MyControlPanel;
namespace MyCore.Controllers
{
[Authorize] // TODO Add ROLES (Roles = "Admin")
[Route("api/device")]
[ApiController]
public class DeviceController : ControllerBase
{
private DeviceDatabaseService _DeviceDatabaseService;
private ProviderDatabaseService _ProviderDatabaseService;
private GroupDatabaseService _GroupDatabaseService;
private RoomDatabaseService _RoomDatabaseService;
private HomeDatabaseService _HomeDatabaseService;
private AutomationService _automationService;
private readonly IMqttClientService _mqttClientService;
//private readonly IMqttOnlineClientService _mqttOnlineClientService;
public DeviceController(DeviceDatabaseService DeviceDatabaseService, ProviderDatabaseService ProviderDatabaseService, GroupDatabaseService GroupDatabaseService, RoomDatabaseService RoomDatabaseService, HomeDatabaseService HomeDatabaseService, AutomationService AutomationService, MqttClientServiceProvider provider)//, MqttClientOnlineServiceProvider onlineProvider)
{
this._DeviceDatabaseService = DeviceDatabaseService;
this._ProviderDatabaseService = ProviderDatabaseService;
this._GroupDatabaseService = GroupDatabaseService;
this._RoomDatabaseService = RoomDatabaseService;
this._HomeDatabaseService = HomeDatabaseService;
this._automationService = AutomationService;
this._mqttClientService = provider.MqttClientService;
//this._mqttOnlineClientService = onlineProvider.MqttOnlineClientService;
}
/// <summary>
/// Get all devices summary
/// </summary>
/// <param name="homeId">Home Id</param>
[ProducesResponseType(typeof(List<DeviceSummaryDTO>), 200)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("{homeId}")]
public ObjectResult GetAll(string homeId)
{
try
{
List<Device> Devices = _DeviceDatabaseService.GetAll(homeId);
List<DeviceSummaryDTO> devicesSummaryDTO = Devices.Select(d => d.ToSummaryDTO()).ToList();
foreach (var device in devicesSummaryDTO)
{
device.ProviderName = _ProviderDatabaseService.GetById(device.ProviderId).Name;
}
return new OkObjectResult(devicesSummaryDTO);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Get a specific device info
/// </summary>
/// <param name="deviceId">id of device</param>
[ProducesResponseType(typeof(DeviceDetailDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("detail/{deviceId}")]
public ObjectResult GetDetail(string deviceId)
{
try
{
if (deviceId == null)
throw new ArgumentNullException("Incorrect parameters");
Device device = _DeviceDatabaseService.GetById(deviceId);
if (device == null)
throw new KeyNotFoundException("Device does not exist");
return new OkObjectResult(device.ToDTO());
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) { };
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Get list of devices from a type
/// </summary>
/// <param name="homeId">Home Id</param>
/// <param name="type">device type</param>
[ProducesResponseType(typeof(List<DeviceDetailDTO>), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("{homeId}/type/{type}")]
public ObjectResult GetDevicesByType(string homeId, DeviceType type)
{
try
{
if (homeId == null)
throw new ArgumentNullException("Incorrect parameters");
List<Device> devices = _DeviceDatabaseService.GetByType(homeId, type);
return new OkObjectResult(devices.Select(d => d.ToDTO()));
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Create a device
/// </summary>
/// <param name="deviceDetailDTO">Device to create</param>
[ProducesResponseType(typeof(DeviceDetailDTO), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 409)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost]
public ObjectResult Create([FromBody] DeviceDetailDTO deviceDetailDTO)
{
try
{
if (deviceDetailDTO == null)
throw new ArgumentNullException("Incorrect parameters");
DeviceDetailDTO deviceCreated = DeviceService.CreateOrUpdate(this._DeviceDatabaseService, this._ProviderDatabaseService, this._RoomDatabaseService, deviceDetailDTO.HomeId, deviceDetailDTO, true);
return new OkObjectResult(deviceCreated);
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) { };
}
catch (DuplicateWaitObjectException ex)
{
return new ConflictObjectResult(ex.Message) { };
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Send action to device
/// </summary>
/// <param name="action">Action to sent</param>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost("action")]
public ObjectResult SendAction([FromBody] Interfaces.Models.Action action)
{
try
{
if (action == null)
throw new ArgumentNullException("Incorrect parameters");
if (action.DeviceId == null && action.GroupId == null)
throw new ArgumentNullException("Incorrect parameters");
Device device = null;
Group group = null;
string homeId;
if (action.DeviceId != null) {
device = _DeviceDatabaseService.GetById(action.DeviceId);
homeId= device?.HomeId;
}
else
{
group = _GroupDatabaseService.GetById(action.GroupId);
homeId= group?.HomeId;
}
if (device == null && group == null)
throw new KeyNotFoundException("Device or group does not exist");
AutomationService.HandleAction(homeId, action, _ProviderDatabaseService, _DeviceDatabaseService, _GroupDatabaseService);
return new ObjectResult("Action has been sent successfully") { StatusCode = 202 }; // To test with accepted result
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) { };
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) { };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Create devices from provider
/// </summary>
/// <param name="homeId">Home Id</param>
/// <param name="providerId">Id of Provider</param>
[ProducesResponseType(typeof(List<DeviceDetailDTO>), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 401)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 421)]
[ProducesResponseType(typeof(string), 500)]
[HttpPost("{homeId}/fromProvider/{providerId}")]
public async Task<ObjectResult> CreateDevicesFromProvider(string homeId, string providerId)
{
try
{
if (homeId == null)
throw new ArgumentNullException("Invalid paramaters");
if (!HomeService.IsExist(_HomeDatabaseService, homeId))
throw new KeyNotFoundException("Home not found");
Provider provider = ProviderService.GetProviderById(this._ProviderDatabaseService, homeId, providerId);
if (provider == null)
throw new KeyNotFoundException("Provider not found");
Dictionary<string, List<DeviceDetailDTO>> devices = await DeviceService.CreateFromProvider(this._DeviceDatabaseService, this._ProviderDatabaseService, this._RoomDatabaseService, homeId, provider);
return new OkObjectResult(devices);
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) {};
}
catch (AuthenticationException ex)
{
return new UnauthorizedObjectResult(ex.Message) {};
}
catch (HttpRequestException ex) // Not ok if not http request..
{
return new BadRequestObjectResult(ex.Message) { StatusCode = 421 };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Get all zigbee2Mqtt devices
/// </summary>
/// <param name="homeId">Home Id</param>
[ProducesResponseType(typeof(List<DeviceDetailDTO>), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("zigbee2Mqtt/{homeId}")]
public ObjectResult GetDevicesFromZigbee2Mqtt(string homeId)
{
try
{
if (homeId == null)
throw new ArgumentNullException("Invalid paramaters");
if (!HomeService.IsExist(_HomeDatabaseService, homeId))
throw new KeyNotFoundException("Home not found");
// GET ALL LOCAL DEVICES
var devices = MqttClientService.devices; // Be carefull, we only got the exact result after each connection
return new OkObjectResult(devices);
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) {};
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Get devices from provider
/// </summary>
/// <param name="homeId">Home Id</param>
/// <param name="providerId">Id of Provider</param>
[ProducesResponseType(typeof(List<DeviceDetailDTO>), 200)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpGet("{homeId}/fromProvider/{providerId}")]
public ObjectResult GetDevicesFromProvider(string homeId, string providerId)
{
try
{
if (homeId == null || providerId == null)
throw new ArgumentNullException("Invalid paramaters");
if (!_HomeDatabaseService.IsExist(homeId))
throw new KeyNotFoundException("Home does not exist");
if (!_ProviderDatabaseService.IsExist(providerId))
throw new KeyNotFoundException("Provider does not exist");
List<Device> devices = _DeviceDatabaseService.GetByProviderId(providerId);
return new OkObjectResult(devices.Select(d => d.ToDTO()));
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (KeyNotFoundException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Update a device
/// </summary>
/// <param name="deviceDetailDTO">Device to update</param>
[ProducesResponseType(typeof(DeviceDetailDTO), 200)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpPut("{deviceId}")]
public ObjectResult Update([FromBody] DeviceDetailDTO deviceDetailDTO)
{
try
{
if (!_DeviceDatabaseService.IsExist(deviceDetailDTO.Id))
throw new KeyNotFoundException("Device does not exist");
DeviceDetailDTO deviceUpdated = DeviceService.CreateOrUpdate(this._DeviceDatabaseService, this._ProviderDatabaseService, this._RoomDatabaseService, deviceDetailDTO.HomeId, deviceDetailDTO, false);
return new OkObjectResult(deviceUpdated);
}
catch (KeyNotFoundException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Delete a device
/// </summary>
/// <param name="deviceId">Id of device to delete</param>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpDelete("{deviceId}")]
public ObjectResult Delete(string deviceId)
{
try
{
if (deviceId == null)
throw new ArgumentNullException("Invalid paramaters");
if (!_DeviceDatabaseService.IsExist(deviceId))
throw new KeyNotFoundException("Device does not exist");
// TODO REMOVE DEVICE ID IN AUTOMATION and delete automation if none device ?
_DeviceDatabaseService.Remove(deviceId);
return new ObjectResult("Device has been deleted") { StatusCode = 202 };
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) {};
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Delete devices from provider
/// </summary>
/// <param name="homeId">Home Id</param>
/// <param name="providerId">Id of Provider</param>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpDelete("{homeId}/fromProvider/{providerId}")]
public ObjectResult DeleteDevicesFromProvider(string homeId, string providerId)
{
try
{
if (homeId == null || providerId == null)
throw new ArgumentNullException("Invalid paramaters");
if (!_HomeDatabaseService.IsExist(homeId))
throw new KeyNotFoundException("Home does not exist");
if (!_ProviderDatabaseService.IsExist(providerId))
throw new KeyNotFoundException("Provider does not exist");
// TODO REMOVE DEVICE ID IN AUTOMATION and delete automation if none device ?
_DeviceDatabaseService.RemoveForProvider(providerId);
return new ObjectResult("Provider devices has been successfully deleted") { StatusCode = 202 };
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) {};
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
/// <summary>
/// Delete all device for a specified home
/// </summary>
/// <param name="homeId">Id of home</param>
[ProducesResponseType(typeof(string), 202)]
[ProducesResponseType(typeof(string), 400)]
[ProducesResponseType(typeof(string), 404)]
[ProducesResponseType(typeof(string), 500)]
[HttpDelete("home/{homeId}")]
public ObjectResult DeleteAllForHome(string homeId)
{
try
{
if (homeId == null)
throw new ArgumentNullException("Invalid paramaters");
if (!_HomeDatabaseService.IsExist(homeId))
throw new KeyNotFoundException("Home does not exist");
// TODO REMOVE DEVICE ID IN AUTOMATION and delete automation if none device ?
_DeviceDatabaseService.RemoveForHome(homeId);
return new ObjectResult("Home devices has been successfully deleted") { StatusCode = 202 };
}
catch (ArgumentNullException ex)
{
return new BadRequestObjectResult(ex.Message) {};
}
catch (KeyNotFoundException ex)
{
return new NotFoundObjectResult(ex.Message) {};
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
}
}