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.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 LocationDatabaseService _LocationDatabaseService;
private UserDatabaseService _UserDatabaseService;
private readonly IMqttClientService _mqttClientService;
private readonly IMqttOnlineClientService _mqttOnlineClientService;
public DeviceController(DeviceDatabaseService DeviceDatabaseService, ProviderDatabaseService ProviderDatabaseService, LocationDatabaseService LocationDatabaseService, UserDatabaseService UserDatabaseService, MqttClientServiceProvider provider, MqttClientOnlineServiceProvider onlineProvider)
{
this._DeviceDatabaseService = DeviceDatabaseService;
this._ProviderDatabaseService = ProviderDatabaseService;
this._LocationDatabaseService = LocationDatabaseService;
this._UserDatabaseService = UserDatabaseService;
this._mqttClientService = provider.MqttClientService;
this._mqttOnlineClientService = onlineProvider.MqttOnlineClientService;
}
// GET: Devices
///
/// Get all devices summary
///
/// Id of user
[ProducesResponseType(typeof(List), 200)]
[HttpGet("{userId}")]
public ObjectResult GetAll(string userId)
{
try
{
List Devices = _DeviceDatabaseService.GetAll(userId);
List devicesSummaryDTO = Devices.Select(d => d.ToSummaryDTO()).ToList();
foreach (var device in devicesSummaryDTO)
{
device.ProviderName = _ProviderDatabaseService.GetById(userId, 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)]
[HttpGet("detail/{deviceId}")]
public ObjectResult GetDetail(string deviceId)
{
try
{
Device device = _DeviceDatabaseService.GetById(deviceId);
return new OkObjectResult(device.ToDTO());
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
///
/// Create a device
///
/// Device to create
[ProducesResponseType(typeof(DeviceDetailDTO), 200)]
[HttpPost]
public ObjectResult Create([FromBody] DeviceDetailDTO deviceDetailDTO)
{
try
{
if (deviceDetailDTO == null)
throw new KeyNotFoundException("Device is null");
DeviceDetailDTO deviceCreated = DeviceService.CreateOrUpdate(this._DeviceDatabaseService, this._ProviderDatabaseService, this._LocationDatabaseService, deviceDetailDTO.UserId, deviceDetailDTO, true);
return new OkObjectResult(deviceCreated);
}
catch (DuplicateWaitObjectException ex)
{
return new BadRequestObjectResult(ex.Message) { StatusCode = 400 };
}
catch (KeyNotFoundException ex)
{
return new BadRequestObjectResult(ex.Message) { StatusCode = 404 };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
///
/// Create devices from provider
///
/// User Id
/// Id of Provider
[ProducesResponseType(typeof(List), 200)]
[HttpPost("{userId}/fromProvider/{providerId}")]
public async Task CreateDevicesFromProvider(string userId, string providerId)
{
try
{
if (userId == null)
throw new InvalidOperationException("User not found");
if (!UserService.IsExist(_UserDatabaseService, userId))
throw new KeyNotFoundException("User not found");
Provider provider = ProviderService.GetProviderById(this._ProviderDatabaseService, userId, providerId);
if (provider == null)
throw new KeyNotFoundException("Provider id is null");
List devicesCreated = await DeviceService.CreateFromProvider(this._DeviceDatabaseService, this._ProviderDatabaseService, this._LocationDatabaseService, userId, provider);
return new OkObjectResult(devicesCreated);
}
catch (InvalidOperationException ex)
{
return new BadRequestObjectResult(ex.Message) { StatusCode = 400 };
}
catch (KeyNotFoundException ex)
{
return new BadRequestObjectResult(ex.Message) { StatusCode = 404 };
}
catch (AuthenticationException ex)
{
return new BadRequestObjectResult(ex.Message) { StatusCode = 401 };
}
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
///
/// User Id
[ProducesResponseType(typeof(List), 200)]
[HttpGet("zigbee2Mqtt/{userId}")]
public async Task GetDevicesFromZigbee2Mqtt(string userId)
{
try
{
if (userId == null)
throw new InvalidOperationException("User not found");
if (!UserService.IsExist(_UserDatabaseService, userId))
throw new KeyNotFoundException("User not found");
// GET ALL LOCAL DEVICES
var devices = MqttClientService.devices;
// Test mqtt
await MqttClientService.PublishMessage("test", "zdz").ContinueWith(res => {
if (res.Status == TaskStatus.RanToCompletion)
{
}
else
{
throw new Exception("Publish error");
}
});
// Test online mqtt
await MqttClientOnlineService.PublishMessage("test", "zdz").ContinueWith(res => {
if (res.Status == TaskStatus.RanToCompletion)
{
}
else
{
throw new Exception("Publish error");
}
});
return new OkObjectResult(devices);
}
catch (InvalidOperationException ex)
{
return new BadRequestObjectResult(ex.Message) { StatusCode = 400 };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
///
/// Create devices from provider
///
/// User Id
[ProducesResponseType(typeof(List), 200)]
[HttpPost("fromZigbee2Mqtt/{userId}")]
public async Task CreateDevicesFromZigbee2Mqtt(string userId)
{
try
{
if (userId == null)
throw new InvalidOperationException("User not found");
if (!UserService.IsExist(_UserDatabaseService, userId))
throw new KeyNotFoundException("User not found");
// Test mqtt
await MqttClientService.PublishMessage("test", "zdz").ContinueWith(res => {
if (res.Status == TaskStatus.RanToCompletion)
{
}
else {
throw new Exception("Publish error");
}
});
var test = MqttClientService.devices;
// Peut etre juste mettre un ok pour ajout zigbee vu qu'on fait le get device lors de la connexion.
List devicesCreated = await DeviceService.CreateFromZigbee(this._DeviceDatabaseService, this._ProviderDatabaseService, this._LocationDatabaseService, userId);
return new OkObjectResult(test);
}
catch (InvalidOperationException ex)
{
return new BadRequestObjectResult(ex.Message) { StatusCode = 400 };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
///
/// Update a device
///
/// Device to update
[ProducesResponseType(typeof(DeviceDetailDTO), 200)]
[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._LocationDatabaseService, deviceDetailDTO.UserId, deviceDetailDTO, false);
return new OkObjectResult(deviceUpdated);
}
catch (KeyNotFoundException ex)
{
return new BadRequestObjectResult(ex.Message) { StatusCode = 404 };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
///
/// Delete a device
///
/// Id of device to delete
[HttpDelete("{deviceId}")]
public ObjectResult Delete(string deviceId)
{
try
{
if (deviceId != null)
{
if (_DeviceDatabaseService.IsExist(deviceId))
{
_DeviceDatabaseService.Remove(deviceId);
}
}
return new OkObjectResult(201);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
///
/// Delete all device for a specified
///
/// Id of user
[HttpDelete("user/{userId}")]
public ObjectResult DeleteAllForUser(string userId)
{
try
{
if (userId != null)
{
if (_UserDatabaseService.IsExist(userId))
{
_DeviceDatabaseService.RemoveForUser(userId);
}
}
return new OkObjectResult(201);
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
}
}