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; } /// /// Get all devices summary /// /// Home Id [ProducesResponseType(typeof(List), 200)] [ProducesResponseType(typeof(string), 500)] [HttpGet("{homeId}")] public ObjectResult GetAll(string homeId) { try { List Devices = _DeviceDatabaseService.GetAll(homeId); List 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 }; } } /// /// Get a specific device info /// /// id of device [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 }; } } /// /// Get list of devices from a type /// /// Home Id /// device type [ProducesResponseType(typeof(List), 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 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 }; } } /// /// Create a device /// /// Device to create [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 }; } } /// /// Send action to device /// /// Action to sent [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 }; } } /// /// Create devices from provider /// /// Home Id /// Id of Provider [ProducesResponseType(typeof(List), 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 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> 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 }; } } /// /// Get all zigbee2Mqtt devices /// /// Home Id [ProducesResponseType(typeof(List), 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 }; } } /// /// Get devices from provider /// /// Home Id /// Id of Provider [ProducesResponseType(typeof(List), 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 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 }; } } /// /// Update a device /// /// Device to update [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 }; } } /// /// Delete a device /// /// Id of device to delete [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 }; } } /// /// Delete devices from provider /// /// Home Id /// Id of Provider [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 }; } } /// /// Delete all device for a specified home /// /// Id of home [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 }; } } } }