mirror of
https://bitbucket.org/myhomie/mycorerepository.git
synced 2025-12-06 09:41:19 +00:00
Add alarm type, controller service, update automation, alarm service + update group logic
This commit is contained in:
parent
479ef5784d
commit
6da8b6bb33
@ -1,7 +1,9 @@
|
|||||||
using System;
|
using MyCore.Interfaces.Models;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using static MyCore.Interfaces.Models.AlarmMode;
|
||||||
|
|
||||||
namespace MyCore.Interfaces.DTO
|
namespace MyCore.Interfaces.DTO
|
||||||
{
|
{
|
||||||
@ -13,9 +15,27 @@ namespace MyCore.Interfaces.DTO
|
|||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public string HomeId { get; set; }
|
public string HomeId { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
public AlarmType Type { get; set; }
|
||||||
|
public bool Activated { get; set; }
|
||||||
public bool IsDefault { get; set; }
|
public bool IsDefault { get; set; }
|
||||||
|
public bool Notification { get; set; }
|
||||||
public DateTime CreatedDate { get; set; }
|
public DateTime CreatedDate { get; set; }
|
||||||
public DateTime UpdatedDate { get; set; }
|
public DateTime UpdatedDate { get; set; }
|
||||||
public List<string> DevicesIds { get; set; } // Check if ok
|
}
|
||||||
|
|
||||||
|
public class AlarmModeDetailDTO : AlarmModeDTO
|
||||||
|
{
|
||||||
|
public List<Trigger> Triggers { get; set; }
|
||||||
|
public List<DeviceDetailDTO> Devices { get; set; }
|
||||||
|
public ProgrammedMode ProgrammedMode { get; set; }
|
||||||
|
public GeolocalizedMode GeolocalizedMode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AlarmModeCreateOrUpdateDetailDTO : AlarmModeDTO
|
||||||
|
{
|
||||||
|
public List<Trigger> Triggers { get; set; }
|
||||||
|
public List<MyCore.Interfaces.Models.Action> Actions { get; set; }
|
||||||
|
public ProgrammedMode ProgrammedMode { get; set; }
|
||||||
|
public GeolocalizedMode GeolocalizedMode { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,12 +23,4 @@ namespace MyCore.Interfaces.DTO
|
|||||||
public List<MyCore.Interfaces.Models.Action> Actions { get; set; }
|
public List<MyCore.Interfaces.Models.Action> Actions { get; set; }
|
||||||
public List<string> DevicesIds { get; set; }
|
public List<string> DevicesIds { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AutomationCreateOrUpdateDetailDTO : AutomationDTO
|
|
||||||
{
|
|
||||||
public List<Trigger> Triggers { get; set; }
|
|
||||||
public List<Condition> Conditions { get; set; }
|
|
||||||
public List<MyCore.Interfaces.Models.Action> Actions { get; set; }
|
|
||||||
public List<string> DeviceIds { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,19 +25,52 @@ namespace MyCore.Interfaces.Models
|
|||||||
[BsonRequired]
|
[BsonRequired]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("Activated")]
|
||||||
|
[BsonRequired]
|
||||||
|
public bool Activated { get; set; }
|
||||||
|
|
||||||
[BsonElement("IsDefault")]
|
[BsonElement("IsDefault")]
|
||||||
[BsonRequired]
|
[BsonRequired]
|
||||||
public bool IsDefault { get; set; }
|
public bool IsDefault { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("Notification")]
|
||||||
|
[BsonRequired]
|
||||||
|
public bool Notification { get; set; }
|
||||||
|
|
||||||
[BsonElement("CreatedDate")]
|
[BsonElement("CreatedDate")]
|
||||||
public DateTime CreatedDate { get; set; }
|
public DateTime CreatedDate { get; set; }
|
||||||
|
|
||||||
[BsonElement("UpdatedDate")]
|
[BsonElement("UpdatedDate")]
|
||||||
public DateTime UpdatedDate { get; set; }
|
public DateTime UpdatedDate { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("Type")]
|
||||||
|
public AlarmType Type { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("ProgrammedModes")]
|
||||||
|
public ProgrammedMode ProgrammedMode { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("GeolocalizedMode")]
|
||||||
|
public GeolocalizedMode GeolocalizedMode { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("Triggers")]
|
||||||
|
public List<Trigger> Triggers { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("Actions")]
|
||||||
|
public List<Action> Actions { get; set; }
|
||||||
|
|
||||||
[BsonElement("DevicesIds")]
|
[BsonElement("DevicesIds")]
|
||||||
public List<string> DevicesIds { get; set; }
|
public List<string> DevicesIds { get; set; }
|
||||||
|
|
||||||
|
public enum AlarmType
|
||||||
|
{
|
||||||
|
Home,
|
||||||
|
Absent,
|
||||||
|
Geolocalized,
|
||||||
|
Programmed,
|
||||||
|
Desarmed,
|
||||||
|
Custom
|
||||||
|
}
|
||||||
|
|
||||||
public AlarmModeDTO ToDTO()
|
public AlarmModeDTO ToDTO()
|
||||||
{
|
{
|
||||||
return new AlarmModeDTO()
|
return new AlarmModeDTO()
|
||||||
@ -45,11 +78,58 @@ namespace MyCore.Interfaces.Models
|
|||||||
Id = Id,
|
Id = Id,
|
||||||
HomeId = HomeId,
|
HomeId = HomeId,
|
||||||
Name = Name,
|
Name = Name,
|
||||||
|
Type = Type,
|
||||||
|
Activated = Activated,
|
||||||
|
IsDefault = IsDefault,
|
||||||
|
Notification = Notification,
|
||||||
|
CreatedDate = CreatedDate,
|
||||||
|
UpdatedDate = UpdatedDate,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlarmModeDetailDTO ToDetailDTO(List<DeviceDetailDTO> devicesDetail)
|
||||||
|
{
|
||||||
|
return new AlarmModeDetailDTO()
|
||||||
|
{
|
||||||
|
Id = Id,
|
||||||
|
HomeId = HomeId,
|
||||||
|
Name = Name,
|
||||||
|
Type = Type,
|
||||||
|
Activated = Activated,
|
||||||
IsDefault = IsDefault,
|
IsDefault = IsDefault,
|
||||||
CreatedDate = CreatedDate,
|
CreatedDate = CreatedDate,
|
||||||
UpdatedDate = UpdatedDate,
|
UpdatedDate = UpdatedDate,
|
||||||
DevicesIds = DevicesIds,
|
Triggers = Triggers,
|
||||||
|
Devices = devicesDetail,
|
||||||
|
ProgrammedMode = ProgrammedMode,
|
||||||
|
GeolocalizedMode = GeolocalizedMode
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ProgrammedMode
|
||||||
|
{
|
||||||
|
public List<TimePeriodAlarm> Monday { get; set; }
|
||||||
|
public List<TimePeriodAlarm> Tuesday { get; set; }
|
||||||
|
public List<TimePeriodAlarm> Wednesday { get; set; }
|
||||||
|
public List<TimePeriodAlarm> Thursday { get; set; }
|
||||||
|
public List<TimePeriodAlarm> Friday { get; set; }
|
||||||
|
public List<TimePeriodAlarm> Saturday { get; set; }
|
||||||
|
public List<TimePeriodAlarm> Sunday { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TimePeriodAlarm
|
||||||
|
{
|
||||||
|
public string Start { get; set; }
|
||||||
|
public string End { get; set; }
|
||||||
|
public AlarmMode AlarmMode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GeolocalizedMode
|
||||||
|
{
|
||||||
|
public string Latitude { get; set; }
|
||||||
|
public string Longitude { get; set; }
|
||||||
|
public AlarmMode HomeMode { get; set; }
|
||||||
|
public AlarmMode AbsentMode { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ using MongoDB.Bson;
|
|||||||
using Mqtt.Client.AspNetCore.Services;
|
using Mqtt.Client.AspNetCore.Services;
|
||||||
using MyCore.Interfaces.DTO;
|
using MyCore.Interfaces.DTO;
|
||||||
using MyCore.Interfaces.Models;
|
using MyCore.Interfaces.Models;
|
||||||
|
using MyCore.Service.Services;
|
||||||
using MyCore.Services;
|
using MyCore.Services;
|
||||||
using MyCore.Services.Devices;
|
using MyCore.Services.Devices;
|
||||||
using MyCore.Services.MyControlPanel;
|
using MyCore.Services.MyControlPanel;
|
||||||
@ -25,16 +26,323 @@ namespace MyCore.Service.Controllers
|
|||||||
private UserDatabaseService _UserDatabaseService;
|
private UserDatabaseService _UserDatabaseService;
|
||||||
private RoomDatabaseService _RoomDatabaseService;
|
private RoomDatabaseService _RoomDatabaseService;
|
||||||
private DeviceDatabaseService _DeviceDatabaseService;
|
private DeviceDatabaseService _DeviceDatabaseService;
|
||||||
|
private AlarmDatabaseService _AlarmDatabaseService;
|
||||||
|
private HomeDatabaseService _HomeDatabaseService;
|
||||||
private readonly IMqttClientService _mqttClientService;
|
private readonly IMqttClientService _mqttClientService;
|
||||||
//private readonly IMqttOnlineClientService _mqttOnlineClientService;
|
//private readonly IMqttOnlineClientService _mqttOnlineClientService;
|
||||||
|
|
||||||
public AlarmController(UserDatabaseService userDatabaseService, RoomDatabaseService roomDatabaseService, DeviceDatabaseService deviceDatabaseService, MqttClientServiceProvider provider)//, MqttClientOnlineServiceProvider onlineProvider)
|
public AlarmController(UserDatabaseService userDatabaseService, RoomDatabaseService roomDatabaseService, DeviceDatabaseService deviceDatabaseService, AlarmDatabaseService alarmDatabaseService, HomeDatabaseService homeDatabaseService, MqttClientServiceProvider provider)//, MqttClientOnlineServiceProvider onlineProvider)
|
||||||
{
|
{
|
||||||
this._UserDatabaseService = userDatabaseService;
|
this._UserDatabaseService = userDatabaseService;
|
||||||
this._RoomDatabaseService = roomDatabaseService;
|
this._RoomDatabaseService = roomDatabaseService;
|
||||||
this._DeviceDatabaseService = deviceDatabaseService;
|
this._DeviceDatabaseService = deviceDatabaseService;
|
||||||
|
this._AlarmDatabaseService = alarmDatabaseService;
|
||||||
|
this._HomeDatabaseService = homeDatabaseService;
|
||||||
this._mqttClientService = provider.MqttClientService;
|
this._mqttClientService = provider.MqttClientService;
|
||||||
//this._mqttOnlineClientService = onlineProvider.MqttOnlineClientService;
|
//this._mqttOnlineClientService = onlineProvider.MqttOnlineClientService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all alarm modes for the specified home
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="homeId">Home Id</param>
|
||||||
|
[ProducesResponseType(typeof(List<AlarmModeDTO>), 200)]
|
||||||
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
|
[HttpGet("{homeId}")]
|
||||||
|
public ObjectResult GetAll(string homeId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<AlarmMode> alarmModes = _AlarmDatabaseService.GetAll(homeId);
|
||||||
|
|
||||||
|
List<AlarmModeDTO> alarmModesDTO = alarmModes.Select(a => a.ToDTO()).ToList();
|
||||||
|
|
||||||
|
return new OkObjectResult(alarmModesDTO);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get detail info of a specified alarm mode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alarmModeId">alarm id</param>
|
||||||
|
[ProducesResponseType(typeof(AlarmModeDetailDTO), 200)]
|
||||||
|
[ProducesResponseType(typeof(string), 400)]
|
||||||
|
[ProducesResponseType(typeof(string), 404)]
|
||||||
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
|
[HttpGet("detail/{alarmId}")]
|
||||||
|
public ObjectResult GetDetail(string alarmModeId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (alarmModeId == null)
|
||||||
|
throw new ArgumentNullException("Incorrect parameters");
|
||||||
|
|
||||||
|
AlarmMode alarmMode = _AlarmDatabaseService.GetById(alarmModeId);
|
||||||
|
if (alarmMode == null)
|
||||||
|
throw new KeyNotFoundException("Alarm does not exist");
|
||||||
|
|
||||||
|
List<Device> devices = new List<Device>();
|
||||||
|
foreach (var deviceId in alarmMode.DevicesIds) {
|
||||||
|
Device device = _DeviceDatabaseService.GetById(deviceId);
|
||||||
|
if (device != null)
|
||||||
|
{
|
||||||
|
devices.Add(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OkObjectResult(alarmMode.ToDetailDTO(devices.Select(d => d.ToDTO()).ToList()));
|
||||||
|
|
||||||
|
}
|
||||||
|
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 an alarm mode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alarmModeCreateOrUpdateDetailDTO">Alarm mode to create</param>
|
||||||
|
[ProducesResponseType(typeof(AlarmModeDetailDTO), 200)]
|
||||||
|
[ProducesResponseType(typeof(string), 400)]
|
||||||
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
|
[HttpPost]
|
||||||
|
public ObjectResult Create([FromBody] AlarmModeCreateOrUpdateDetailDTO alarmModeCreateOrUpdateDetailDTO)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (alarmModeCreateOrUpdateDetailDTO == null)
|
||||||
|
throw new ArgumentNullException("Incorrect parameters");
|
||||||
|
|
||||||
|
AlarmModeDetailDTO alarmModeCreated = AlarmService.CreateOrUpdate(this._AlarmDatabaseService, this._DeviceDatabaseService, alarmModeCreateOrUpdateDetailDTO.HomeId, alarmModeCreateOrUpdateDetailDTO, true);
|
||||||
|
|
||||||
|
return new OkObjectResult(alarmModeCreated);
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException ex)
|
||||||
|
{
|
||||||
|
return new BadRequestObjectResult(ex.Message) { };
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create default alarm modes
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="homeId">Home Id</param>
|
||||||
|
[ProducesResponseType(typeof(bool), 202)]
|
||||||
|
[ProducesResponseType(typeof(string), 400)]
|
||||||
|
[ProducesResponseType(typeof(string), 404)]
|
||||||
|
[ProducesResponseType(typeof(string), 409)]
|
||||||
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
|
[HttpPost("defaults/{homeId}")]
|
||||||
|
public ObjectResult CreateDefaultAlarms (string homeId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (homeId == null)
|
||||||
|
throw new ArgumentNullException("Incorrect parameters");
|
||||||
|
|
||||||
|
Home home = _HomeDatabaseService.GetById(homeId);
|
||||||
|
if (home == null)
|
||||||
|
throw new KeyNotFoundException("Home does not exist");
|
||||||
|
|
||||||
|
List<AlarmMode> alarmModes = _AlarmDatabaseService.GetAll(homeId);
|
||||||
|
if (alarmModes.Where(a => a.IsDefault).Count() == 5)
|
||||||
|
throw new SystemException("Default modes already existing");
|
||||||
|
|
||||||
|
return new ObjectResult(AlarmService.CreateDefaultAlarmModes(_HomeDatabaseService, _AlarmDatabaseService, home)) { StatusCode = 202 };
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException ex)
|
||||||
|
{
|
||||||
|
return new BadRequestObjectResult(ex.Message) { };
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException ex)
|
||||||
|
{
|
||||||
|
return new NotFoundObjectResult(ex.Message) { };
|
||||||
|
}
|
||||||
|
catch (SystemException ex)
|
||||||
|
{
|
||||||
|
return new ObjectResult(ex.Message) { StatusCode = 409 };
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Activate current alarm mode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alarmModeId">Alarm mode to activate</param>
|
||||||
|
[ProducesResponseType(typeof(string), 202)]
|
||||||
|
[ProducesResponseType(typeof(string), 400)]
|
||||||
|
[ProducesResponseType(typeof(string), 404)]
|
||||||
|
[ProducesResponseType(typeof(string), 409)]
|
||||||
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
|
[HttpPost("activate/{alarmModeId}")]
|
||||||
|
public ObjectResult Activate(string alarmModeId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (alarmModeId == null)
|
||||||
|
throw new ArgumentNullException("Incorrect parameters");
|
||||||
|
|
||||||
|
AlarmMode alarmMode = _AlarmDatabaseService.GetById(alarmModeId);
|
||||||
|
if (alarmMode == null)
|
||||||
|
throw new KeyNotFoundException("Alarm mode does not exist");
|
||||||
|
|
||||||
|
if (alarmMode.Activated)
|
||||||
|
throw new AccessViolationException("This alarm mode is already activated");
|
||||||
|
|
||||||
|
bool successfull = AlarmService.Activate(_AlarmDatabaseService, alarmMode, _HomeDatabaseService);
|
||||||
|
|
||||||
|
return new OkObjectResult($"Alarm mode {alarmMode.Name} has been successfully activated") { StatusCode = 202 };
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException ex)
|
||||||
|
{
|
||||||
|
return new BadRequestObjectResult(ex.Message) { };
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException ex)
|
||||||
|
{
|
||||||
|
return new NotFoundObjectResult(ex.Message) { };
|
||||||
|
}
|
||||||
|
catch (AccessViolationException ex)
|
||||||
|
{
|
||||||
|
return new ObjectResult(ex.Message) { StatusCode = 409 };
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update an alarm mode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alarmModeCreateOrUpdateDetailDTO">alarm mode to update</param>
|
||||||
|
[ProducesResponseType(typeof(AlarmModeDetailDTO), 200)]
|
||||||
|
[ProducesResponseType(typeof(string), 404)]
|
||||||
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
|
[HttpPut]
|
||||||
|
public ObjectResult Update([FromBody] AlarmModeCreateOrUpdateDetailDTO alarmModeCreateOrUpdateDetailDTO)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_AlarmDatabaseService.IsExist(alarmModeCreateOrUpdateDetailDTO.Id))
|
||||||
|
throw new KeyNotFoundException("This alarm mode does not exist");
|
||||||
|
|
||||||
|
AlarmModeDetailDTO alarmModeUpdated = AlarmService.CreateOrUpdate(this._AlarmDatabaseService, this._DeviceDatabaseService, alarmModeCreateOrUpdateDetailDTO.HomeId, alarmModeCreateOrUpdateDetailDTO, false);
|
||||||
|
|
||||||
|
return new OkObjectResult(alarmModeUpdated);
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException ex)
|
||||||
|
{
|
||||||
|
return new NotFoundObjectResult(ex.Message) { };
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete an alarm mode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alarmModeId">Id of alarm mode to delete</param>
|
||||||
|
[ProducesResponseType(typeof(string), 202)]
|
||||||
|
[ProducesResponseType(typeof(string), 400)]
|
||||||
|
[ProducesResponseType(typeof(string), 404)]
|
||||||
|
[ProducesResponseType(typeof(string), 405)]
|
||||||
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
|
[HttpDelete("{alarmModeId}")]
|
||||||
|
public ObjectResult Delete(string alarmModeId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (alarmModeId == null)
|
||||||
|
throw new ArgumentNullException("Incorrect parameters");
|
||||||
|
|
||||||
|
if (!_AlarmDatabaseService.IsExist(alarmModeId))
|
||||||
|
throw new KeyNotFoundException("This alarm mode does not exist");
|
||||||
|
|
||||||
|
AlarmMode alarmMode = _AlarmDatabaseService.GetById(alarmModeId);
|
||||||
|
|
||||||
|
if (alarmMode.IsDefault)
|
||||||
|
throw new NotSupportedException("This alarm mode cannot be deleted");
|
||||||
|
|
||||||
|
// Delete alarm
|
||||||
|
_AlarmDatabaseService.Remove(alarmModeId);
|
||||||
|
|
||||||
|
return new OkObjectResult("Alarm mode has been successfully deleted") { StatusCode = 202 };
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException ex)
|
||||||
|
{
|
||||||
|
return new BadRequestObjectResult(ex.Message) { };
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException ex)
|
||||||
|
{
|
||||||
|
return new NotFoundObjectResult(ex.Message) { };
|
||||||
|
}
|
||||||
|
catch (NotSupportedException ex)
|
||||||
|
{
|
||||||
|
return new ObjectResult(ex.Message) { StatusCode = 405 };
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new ObjectResult(ex.Message) { StatusCode = 500 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete all alarm mode for a specified home
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="homeId">Home Id</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("Incorrect parameters");
|
||||||
|
|
||||||
|
if (!_HomeDatabaseService.IsExist(homeId))
|
||||||
|
throw new KeyNotFoundException("Home does not exist");
|
||||||
|
|
||||||
|
_AlarmDatabaseService.RemoveForHome(homeId);
|
||||||
|
|
||||||
|
return new OkObjectResult("All alarm mode associated to specified home has been removed") { 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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,19 +100,19 @@ namespace MyCore.Service.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create an automation
|
/// Create an automation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="automationCreateOrUpdateDetail">Automation to create</param>
|
/// <param name="automationDetailDTO">Automation to create</param>
|
||||||
[ProducesResponseType(typeof(AutomationDTO), 200)]
|
[ProducesResponseType(typeof(AutomationDTO), 200)]
|
||||||
[ProducesResponseType(typeof(string), 400)]
|
[ProducesResponseType(typeof(string), 400)]
|
||||||
[ProducesResponseType(typeof(string), 500)]
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public ObjectResult Create([FromBody] AutomationCreateOrUpdateDetailDTO automationCreateOrUpdateDetail)
|
public ObjectResult Create([FromBody] AutomationDetailDTO automationDetailDTO)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (automationCreateOrUpdateDetail == null)
|
if (automationDetailDTO == null)
|
||||||
throw new ArgumentNullException("Incorrect parameters");
|
throw new ArgumentNullException("Incorrect parameters");
|
||||||
|
|
||||||
AutomationDTO automationCreated = AutomationService.CreateOrUpdate(this._AutomationDatabaseService, automationCreateOrUpdateDetail.HomeId, automationCreateOrUpdateDetail, true);
|
AutomationDTO automationCreated = AutomationService.CreateOrUpdate(this._AutomationDatabaseService, automationDetailDTO.HomeId, automationDetailDTO, true);
|
||||||
|
|
||||||
return new OkObjectResult(automationCreated);
|
return new OkObjectResult(automationCreated);
|
||||||
}
|
}
|
||||||
@ -130,23 +130,23 @@ namespace MyCore.Service.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update an automation
|
/// Update an automation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="automationCreateOrUpdateDetail">automation to update</param>
|
/// <param name="automationDetailDTO">automation to update</param>
|
||||||
[ProducesResponseType(typeof(AutomationCreateOrUpdateDetailDTO), 200)]
|
[ProducesResponseType(typeof(AutomationDetailDTO), 200)]
|
||||||
[ProducesResponseType(typeof(string), 400)]
|
[ProducesResponseType(typeof(string), 400)]
|
||||||
[ProducesResponseType(typeof(string), 404)]
|
[ProducesResponseType(typeof(string), 404)]
|
||||||
[ProducesResponseType(typeof(string), 500)]
|
[ProducesResponseType(typeof(string), 500)]
|
||||||
[HttpPut]
|
[HttpPut]
|
||||||
public ObjectResult Update([FromBody] AutomationCreateOrUpdateDetailDTO automationCreateOrUpdateDetail)
|
public ObjectResult Update([FromBody] AutomationDetailDTO automationDetailDTO)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (automationCreateOrUpdateDetail == null)
|
if (automationDetailDTO == null)
|
||||||
throw new ArgumentNullException("Incorrect parameters");
|
throw new ArgumentNullException("Incorrect parameters");
|
||||||
|
|
||||||
if (!_AutomationDatabaseService.IsExist(automationCreateOrUpdateDetail.Id))
|
if (!_AutomationDatabaseService.IsExist(automationDetailDTO.Id))
|
||||||
throw new KeyNotFoundException("Automation does not exist");
|
throw new KeyNotFoundException("Automation does not exist");
|
||||||
|
|
||||||
AutomationDTO automationUpdated = AutomationService.CreateOrUpdate(this._AutomationDatabaseService, automationCreateOrUpdateDetail.HomeId, automationCreateOrUpdateDetail, false);
|
AutomationDTO automationUpdated = AutomationService.CreateOrUpdate(this._AutomationDatabaseService, automationDetailDTO.HomeId, automationDetailDTO, false);
|
||||||
|
|
||||||
return new OkObjectResult(automationUpdated);
|
return new OkObjectResult(automationUpdated);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,7 +91,7 @@ namespace MyCore.Service.Controllers
|
|||||||
if (group == null)
|
if (group == null)
|
||||||
throw new KeyNotFoundException("Group not found");
|
throw new KeyNotFoundException("Group not found");
|
||||||
|
|
||||||
List<Device> devices = _DeviceDatabaseService.GetByLocation(group.HomeId, groupId);
|
List<Device> devices = _DeviceDatabaseService.GetByRoom(group.HomeId, groupId);
|
||||||
|
|
||||||
return new OkObjectResult(group.ToDTO(devices.Select(d => d.ToDTO()).ToList()));
|
return new OkObjectResult(group.ToDTO(devices.Select(d => d.ToDTO()).ToList()));
|
||||||
|
|
||||||
@ -360,7 +360,7 @@ namespace MyCore.Service.Controllers
|
|||||||
|
|
||||||
Group group = _GroupDatabaseService.GetById(groupId);
|
Group group = _GroupDatabaseService.GetById(groupId);
|
||||||
// Delete group from all devices
|
// Delete group from all devices
|
||||||
List<Device> devices = _DeviceDatabaseService.GetByLocation(group.HomeId, groupId);
|
List<Device> devices = _DeviceDatabaseService.GetByRoom(group.HomeId, groupId);
|
||||||
foreach (var device in devices)
|
foreach (var device in devices)
|
||||||
{
|
{
|
||||||
device.GroupIds = device.GroupIds.Where(g => g != groupId).ToList();
|
device.GroupIds = device.GroupIds.Where(g => g != groupId).ToList();
|
||||||
|
|||||||
386
MyCore/Controllers/Helpers/DevicesHelper.cs
Normal file
386
MyCore/Controllers/Helpers/DevicesHelper.cs
Normal file
@ -0,0 +1,386 @@
|
|||||||
|
using MyCore.Interfaces.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using MyCore.Interfaces.DTO;
|
||||||
|
using static Mqtt.Client.AspNetCore.Services.MqttClientMerossService;
|
||||||
|
using Mqtt.Client.AspNetCore.Services;
|
||||||
|
using MyCore.Services;
|
||||||
|
|
||||||
|
namespace MyCore.Service.Controllers.Helpers
|
||||||
|
{
|
||||||
|
public class DevicesHelper
|
||||||
|
{
|
||||||
|
#region Common methods
|
||||||
|
public static List<Expose> GetDeviceExposes(Device device)
|
||||||
|
{
|
||||||
|
List<Expose> exposes = new List<Expose>();
|
||||||
|
// Get Exposes for the zigbee device
|
||||||
|
foreach (var supportedOperation in device.SupportedOperations)
|
||||||
|
{
|
||||||
|
exposes.Add(JsonConvert.DeserializeObject<Expose>(supportedOperation));
|
||||||
|
}
|
||||||
|
return exposes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static System.Type GetStateType(Expose expose)
|
||||||
|
{
|
||||||
|
switch (expose.type)
|
||||||
|
{
|
||||||
|
// e.g.: occupancy
|
||||||
|
case "binary":
|
||||||
|
if (expose.value_toggle == null)
|
||||||
|
{
|
||||||
|
// value are boolean
|
||||||
|
return true.GetType();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// value are string
|
||||||
|
return "".GetType();
|
||||||
|
}
|
||||||
|
case "numeric":
|
||||||
|
return new long().GetType();
|
||||||
|
case "enum":
|
||||||
|
return expose.values.GetType();
|
||||||
|
break;
|
||||||
|
/*case "text":
|
||||||
|
break;
|
||||||
|
case "light":
|
||||||
|
break;
|
||||||
|
case "composite":
|
||||||
|
break;
|
||||||
|
case "switch":
|
||||||
|
break;*/
|
||||||
|
/*case "fan":
|
||||||
|
break;
|
||||||
|
case "cover":
|
||||||
|
break;
|
||||||
|
case "lock":
|
||||||
|
break;
|
||||||
|
case "climate":
|
||||||
|
break;*/
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region ACTIONS !
|
||||||
|
public async static void ActionOnYeelight(DeviceDatabaseService deviceDatabaseService, Device actionDeviceToTest, Interfaces.Models.Action action)
|
||||||
|
{
|
||||||
|
if (YeelightService.devices.Count <= 0)
|
||||||
|
{
|
||||||
|
await YeelightService.GetDevices();
|
||||||
|
}
|
||||||
|
var lamp = YeelightService.devices.Where(d => d.Hostname == actionDeviceToTest.IpAddress).FirstOrDefault();
|
||||||
|
if (lamp != null)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"Yeelight type !");
|
||||||
|
|
||||||
|
// Get device last state
|
||||||
|
var dic = new List<AutomationState>();
|
||||||
|
if (actionDeviceToTest.LastState != null)
|
||||||
|
{
|
||||||
|
dic = JsonConvert.DeserializeObject<List<AutomationState>>(actionDeviceToTest.LastState);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (actionDeviceToTest.Type)
|
||||||
|
{
|
||||||
|
case DeviceType.Light:
|
||||||
|
var states = action.States.Where(s => s.Name == "state" || s.Name == "brightness").ToList();
|
||||||
|
|
||||||
|
if (states.Count >= 0)
|
||||||
|
{
|
||||||
|
if (dic.Count > 0)
|
||||||
|
{
|
||||||
|
/*if (dic["state"].ToString().ToLower() == state.Value.ToLower() && action.States.Count <= 1) // workaround if brightness not the same
|
||||||
|
{
|
||||||
|
throw new Exception($"Action device is already at the good state : {state.Name} {state.Value}");
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var state in states)
|
||||||
|
{
|
||||||
|
switch (state.Name)
|
||||||
|
{
|
||||||
|
case "state":
|
||||||
|
switch (state.Value.ToLower())
|
||||||
|
{
|
||||||
|
case "on":
|
||||||
|
Task.Run(async () => { await YeelightService.TurnOn(lamp, null); });
|
||||||
|
break;
|
||||||
|
case "off":
|
||||||
|
Task.Run(async () => { await YeelightService.TurnOff(lamp); });
|
||||||
|
break;
|
||||||
|
case "toggle":
|
||||||
|
Task.Run(async () => { await YeelightService.Toggle(lamp); });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "brightness":
|
||||||
|
var brightness = int.Parse(state.Value);
|
||||||
|
Task.Run(async () => { await YeelightService.TurnOn(lamp, brightness); });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Last state
|
||||||
|
actionDeviceToTest.LastState = JsonConvert.SerializeObject(states);
|
||||||
|
actionDeviceToTest.LastStateDate = DateTime.Now;
|
||||||
|
deviceDatabaseService.Update(actionDeviceToTest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"Action device light in yeelight does not have correct expose");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"Not a valid action !");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"Yeelight - Lamp offline! - {actionDeviceToTest.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ActionOnMeross(DeviceDatabaseService _DeviceDatabaseService, Device actionDeviceToTest, Interfaces.Models.Action action, string deviceNameForAction)
|
||||||
|
{
|
||||||
|
var merossDevice = _DeviceDatabaseService.GetById(actionDeviceToTest.Id);
|
||||||
|
|
||||||
|
if (merossDevice != null)
|
||||||
|
{
|
||||||
|
//As multisocket channel 0 is all the sockets, skip 0
|
||||||
|
|
||||||
|
// two state = first state = ON/OFF, second var = switch channels number (LIST) // TODO better check
|
||||||
|
if (action.States.Count >= 2 && action.States.Any(s => s.Name.ToLower() == "state" && (s.Value.ToLower() == "on" || s.Value.ToLower() == "off" || s.Value.ToLower() == "toggle")))
|
||||||
|
{
|
||||||
|
var state = action.States.Where(s => s.Name.ToLower() == "state").FirstOrDefault();
|
||||||
|
var channels = action.States.Where(s => s.Name.ToLower() == "channels").FirstOrDefault();
|
||||||
|
var plugIds = JsonConvert.DeserializeObject<List<int>>(channels.Value);
|
||||||
|
|
||||||
|
List<ToggleStatus> lastStatePlug = new List<ToggleStatus>(); // Off by default
|
||||||
|
// => TODO GET ALL POSSIBILITIES FROM DEVICE (number of channels)
|
||||||
|
|
||||||
|
if (actionDeviceToTest.LastState != null) // Get last state of device
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lastStatePlug = JsonConvert.DeserializeObject<List<ToggleStatus>>(actionDeviceToTest.LastState);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"Meross error: Last state ! - {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// By default set to OFF
|
||||||
|
foreach (var plug in plugIds)
|
||||||
|
{
|
||||||
|
lastStatePlug.Add(ToggleStatus.OFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ToggleStatus> statuses = new List<ToggleStatus>();
|
||||||
|
var p = 0;
|
||||||
|
foreach (var plugId in plugIds)
|
||||||
|
{
|
||||||
|
ToggleStatus status = new ToggleStatus();
|
||||||
|
// check if device, check if multiprise
|
||||||
|
switch (merossDevice.Type)
|
||||||
|
{
|
||||||
|
case DeviceType.Multiplug:
|
||||||
|
case DeviceType.Plug:
|
||||||
|
if (state.Value.ToLower() == "toggle")
|
||||||
|
{
|
||||||
|
status = lastStatePlug[p] == ToggleStatus.OFF ? ToggleStatus.ON : ToggleStatus.OFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = state.Value.ToLower() == "on" ? ToggleStatus.ON : ToggleStatus.OFF;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Send request
|
||||||
|
MqttClientMerossService.ExecuteCommand(actionDeviceToTest.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", status, plugId);
|
||||||
|
statuses.Add(status);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Last state
|
||||||
|
actionDeviceToTest.LastState = JsonConvert.SerializeObject(statuses);
|
||||||
|
actionDeviceToTest.LastStateDate = DateTime.Now;
|
||||||
|
_DeviceDatabaseService.Update(actionDeviceToTest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Meross: Request action invalid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ActionOnZigbee2Mqtt(Device device, Interfaces.Models.Action action, string deviceNameForAction)
|
||||||
|
{
|
||||||
|
var request = "";
|
||||||
|
var buildRequest = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
System.Console.WriteLine($"zigbee2mqtt type !");
|
||||||
|
|
||||||
|
var actionDeviceExpose = DevicesHelper.GetDeviceExposes(device);
|
||||||
|
|
||||||
|
// Get device last state
|
||||||
|
var dic = new Dictionary<string, object>();
|
||||||
|
if (device.LastState != null)
|
||||||
|
{
|
||||||
|
dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(device.LastState);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (device.Type)
|
||||||
|
{
|
||||||
|
case DeviceType.Light:
|
||||||
|
case DeviceType.Switch:
|
||||||
|
var actionDeviceExposeForFeatures = actionDeviceExpose.Where(e => e.type == ((DeviceType)device.Type).ToString().ToLower()).FirstOrDefault();
|
||||||
|
if (actionDeviceExposeForFeatures != null)
|
||||||
|
{
|
||||||
|
foreach (var state in action.States)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"Check Action in light|switch ! {state.Name} {state.Value}");
|
||||||
|
if (actionDeviceExposeForFeatures.features.Any(ade => ade.name == state.Name))
|
||||||
|
{
|
||||||
|
// Comment this for test (ensure the request will be sent)
|
||||||
|
/*if (dic.Count > 0)
|
||||||
|
{
|
||||||
|
//if (device.Type == DeviceType.Light) {}
|
||||||
|
var test = dic["state"].ToString().ToLower();
|
||||||
|
var test0 = state.Value.ToLower();
|
||||||
|
if (dic["state"].ToString().ToLower() == state.Value.ToLower() && action.States.Count <= 1) // workaround if brightness not the same => For switch or light without brightness
|
||||||
|
{
|
||||||
|
throw new Exception($"Action device is already at the good state : {state.Name} {state.Value}");
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (state.Name == "brightness")
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int brightness = int.Parse(state.Value);
|
||||||
|
// Add to request
|
||||||
|
buildRequest.Add(state.Name, brightness);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"zigbee - Parse to int error {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Add to request
|
||||||
|
buildRequest.Add(state.Name, state.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"Action device light|switch does not have expose of type {state.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any action ask for state update, check if device is already at the asked state
|
||||||
|
if (action.States.Any(s => s.Name == "state") && !action.IsForce)
|
||||||
|
{
|
||||||
|
bool sendRequest = true;
|
||||||
|
|
||||||
|
// If action doesn't ask for brightness just test if device is already at the asked state
|
||||||
|
if (action.States.Any(s => s.Name == "brightness"))
|
||||||
|
{
|
||||||
|
// Check state and brightness
|
||||||
|
// if we got state value (current value)
|
||||||
|
if (dic.Any(d => d.Key == "state"))
|
||||||
|
{
|
||||||
|
var currentValue = dic["state"].ToString().ToLower();
|
||||||
|
var askedValue = action.States.FirstOrDefault(s => s.Name == "state").Value.ToLower();
|
||||||
|
if (currentValue == askedValue)
|
||||||
|
{
|
||||||
|
// Check brightness difference
|
||||||
|
if (dic.Any(d => d.Key == "brightness"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var currentValueBrightness = int.Parse(dic["brightness"].ToString().ToLower());
|
||||||
|
var askedValueBrightness = int.Parse(action.States.FirstOrDefault(s => s.Name == "brightness").Value.ToLower());
|
||||||
|
if (Math.Abs(currentValueBrightness - askedValueBrightness) <= 5) // brightness diff is lower than 5 => don't change brightness
|
||||||
|
sendRequest = false;
|
||||||
|
else
|
||||||
|
sendRequest = true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
sendRequest = false;
|
||||||
|
System.Console.WriteLine($"int parse error in brightness check", ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check only state value
|
||||||
|
// if we got state value (current value)
|
||||||
|
if (dic.Any(d => d.Key == "state"))
|
||||||
|
{
|
||||||
|
var currentValue = dic["state"].ToString().ToLower();
|
||||||
|
var askedValue = action.States.FirstOrDefault(s => s.Name == "state").Value.ToLower();
|
||||||
|
if (currentValue == askedValue)
|
||||||
|
sendRequest = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sendRequest)
|
||||||
|
throw new Exception($"Action device is already at the good state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new Exception("Action device does not have expose of type light|switch");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
foreach (var state in action.States)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"Check Action ! {state.Name} {state.Value}");
|
||||||
|
if (!actionDeviceExpose.Any(ade => ade.name == state.Name))
|
||||||
|
{
|
||||||
|
throw new Exception($"Action device does not have expose of type {state.Name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
request = JsonConvert.SerializeObject(buildRequest);
|
||||||
|
|
||||||
|
// SEND REQUEST
|
||||||
|
//var requestToSend = $"Send request ! zigbee2mqtt/{deviceNameForAction}/set/{request}";
|
||||||
|
System.Console.WriteLine($"Send request ! zigbee2mqtt/{deviceNameForAction}/set/{request}");
|
||||||
|
|
||||||
|
MqttClientService.PublishMessage("zigbee2mqtt/" + deviceNameForAction + "/set", request);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"Not a valid action !");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ using MongoDB.Bson;
|
|||||||
using Mqtt.Client.AspNetCore.Services;
|
using Mqtt.Client.AspNetCore.Services;
|
||||||
using MyCore.Interfaces.DTO;
|
using MyCore.Interfaces.DTO;
|
||||||
using MyCore.Interfaces.Models;
|
using MyCore.Interfaces.Models;
|
||||||
|
using MyCore.Service.Services;
|
||||||
using MyCore.Services;
|
using MyCore.Services;
|
||||||
using MyCore.Services.Devices;
|
using MyCore.Services.Devices;
|
||||||
using MyCore.Services.MyControlPanel;
|
using MyCore.Services.MyControlPanel;
|
||||||
@ -153,6 +154,10 @@ namespace MyCore.Service.Controllers
|
|||||||
|
|
||||||
Home homeCreated = HomeService.CreateOrUpdate(this._HomeDatabaseService, this._AlarmDatabaseService, createOrUpdateHomeDTO, true);
|
Home homeCreated = HomeService.CreateOrUpdate(this._HomeDatabaseService, this._AlarmDatabaseService, createOrUpdateHomeDTO, true);
|
||||||
|
|
||||||
|
if (homeCreated.IsAlarm)
|
||||||
|
// Create default alarm modes
|
||||||
|
AlarmService.CreateDefaultAlarmModes(_HomeDatabaseService, _AlarmDatabaseService, homeCreated); // Create and by default select desarmed mode
|
||||||
|
|
||||||
foreach (var userId in createOrUpdateHomeDTO.UsersIds)
|
foreach (var userId in createOrUpdateHomeDTO.UsersIds)
|
||||||
{
|
{
|
||||||
UserInfo user = _UserDatabaseService.GetById(userId);
|
UserInfo user = _UserDatabaseService.GetById(userId);
|
||||||
@ -228,7 +233,7 @@ namespace MyCore.Service.Controllers
|
|||||||
throw new KeyNotFoundException("Home does not exist");
|
throw new KeyNotFoundException("Home does not exist");
|
||||||
|
|
||||||
Home home = _HomeDatabaseService.GetById(homeId);
|
Home home = _HomeDatabaseService.GetById(homeId);
|
||||||
// Check if something needs to be done.. (delete all devices related to home, all automations, all groups, etc)
|
// Check if something needs to be done.. (delete all devices related to home, all automations, all groups, all alarm modes, etc)
|
||||||
// Delete home
|
// Delete home
|
||||||
_HomeDatabaseService.Remove(homeId);
|
_HomeDatabaseService.Remove(homeId);
|
||||||
|
|
||||||
|
|||||||
@ -79,7 +79,7 @@ namespace MyCore.Service.Controllers
|
|||||||
Room room = _RoomDatabaseService.GetById(roomId);
|
Room room = _RoomDatabaseService.GetById(roomId);
|
||||||
if (room == null)
|
if (room == null)
|
||||||
throw new KeyNotFoundException("Room does not exist");
|
throw new KeyNotFoundException("Room does not exist");
|
||||||
List<Device> devices = _DeviceDatabaseService.GetByLocation(room.HomeId, roomId);
|
List<Device> devices = _DeviceDatabaseService.GetByRoom(room.HomeId, roomId);
|
||||||
|
|
||||||
return new OkObjectResult(room.ToDTO(devices.Select(d => d.ToDTO()).ToList()));
|
return new OkObjectResult(room.ToDTO(devices.Select(d => d.ToDTO()).ToList()));
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ namespace MyCore.Service.Controllers
|
|||||||
|
|
||||||
Room room = _RoomDatabaseService.GetById(roomId);
|
Room room = _RoomDatabaseService.GetById(roomId);
|
||||||
// Delete location from all devices
|
// Delete location from all devices
|
||||||
List<Device> devices = _DeviceDatabaseService.GetByLocation(room.HomeId, roomId);
|
List<Device> devices = _DeviceDatabaseService.GetByRoom(room.HomeId, roomId);
|
||||||
foreach (var device in devices)
|
foreach (var device in devices)
|
||||||
{
|
{
|
||||||
device.RoomId = null;
|
device.RoomId = null;
|
||||||
|
|||||||
@ -35,11 +35,12 @@ namespace Mqtt.Client.AspNetCore.Services
|
|||||||
private AutomationDatabaseService _automationDatabaseService;
|
private AutomationDatabaseService _automationDatabaseService;
|
||||||
private ActionService _actionService;
|
private ActionService _actionService;
|
||||||
private HomeDatabaseService _homeDatabaseService;
|
private HomeDatabaseService _homeDatabaseService;
|
||||||
|
private AlarmDatabaseService _alarmDatabaseService;
|
||||||
|
|
||||||
public static string lastTopic;
|
public static string lastTopic;
|
||||||
public static long lastTimeTopic;
|
public static long lastTimeTopic;
|
||||||
|
|
||||||
public MqttClientService(IMqttClientOptions options, HomeDatabaseService homeDatabaseService, DeviceDatabaseService deviceDatabaseService, GroupDatabaseService groupDatabaseService, ProviderDatabaseService providerDatabaseService, RoomDatabaseService roomDatabaseService, ActionService actionService, AutomationDatabaseService automationDatabaseService)
|
public MqttClientService(IMqttClientOptions options, HomeDatabaseService homeDatabaseService, DeviceDatabaseService deviceDatabaseService, GroupDatabaseService groupDatabaseService, ProviderDatabaseService providerDatabaseService, RoomDatabaseService roomDatabaseService, ActionService actionService, AutomationDatabaseService automationDatabaseService, AlarmDatabaseService alarmDatabaseService)
|
||||||
{
|
{
|
||||||
this._homeDatabaseService = homeDatabaseService;
|
this._homeDatabaseService = homeDatabaseService;
|
||||||
this._deviceDatabaseService = deviceDatabaseService;
|
this._deviceDatabaseService = deviceDatabaseService;
|
||||||
@ -47,6 +48,7 @@ namespace Mqtt.Client.AspNetCore.Services
|
|||||||
this._providerDatabaseService = providerDatabaseService;
|
this._providerDatabaseService = providerDatabaseService;
|
||||||
this._roomDatabaseService = roomDatabaseService;
|
this._roomDatabaseService = roomDatabaseService;
|
||||||
this._automationDatabaseService = automationDatabaseService;
|
this._automationDatabaseService = automationDatabaseService;
|
||||||
|
this._alarmDatabaseService = alarmDatabaseService;
|
||||||
this._actionService = actionService;
|
this._actionService = actionService;
|
||||||
|
|
||||||
Home home = this._homeDatabaseService.GetAll().ToList().Where(h => h.IsDefault).FirstOrDefault();
|
Home home = this._homeDatabaseService.GetAll().ToList().Where(h => h.IsDefault).FirstOrDefault();
|
||||||
@ -115,7 +117,7 @@ namespace Mqtt.Client.AspNetCore.Services
|
|||||||
{
|
{
|
||||||
if (_actionService != null && homeId != null)
|
if (_actionService != null && homeId != null)
|
||||||
{
|
{
|
||||||
ActionService.HandleActionFromMQTTAsync(topic, payload, _deviceDatabaseService, _groupDatabaseService, _providerDatabaseService, _roomDatabaseService, _automationDatabaseService, homeId);
|
ActionService.HandleActionFromMQTTAsync(topic, payload, _deviceDatabaseService, _groupDatabaseService, _providerDatabaseService, _roomDatabaseService, _automationDatabaseService, _alarmDatabaseService, homeId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -298,9 +300,7 @@ namespace Mqtt.Client.AspNetCore.Services
|
|||||||
if (zigbee2mqttProvider != null)
|
if (zigbee2mqttProvider != null)
|
||||||
{
|
{
|
||||||
var groups = _GroupDatabaseService.GetByType(homeId, "zigbee2mqtt");
|
var groups = _GroupDatabaseService.GetByType(homeId, "zigbee2mqtt");
|
||||||
// Compare the groups from MyCore and the group we received, if something diff in one group => Hard refresh (delete, new)
|
|
||||||
|
|
||||||
// TODO : Test with new devices !! => Id always change BUUUUUUG !!
|
|
||||||
GroupService.CompareGroupsFromZigbee2Mqtt(homeId, groups, groupsConvert, _DeviceDatabaseService, _GroupDatabaseService);
|
GroupService.CompareGroupsFromZigbee2Mqtt(homeId, groups, groupsConvert, _DeviceDatabaseService, _GroupDatabaseService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,6 +74,7 @@ namespace MyCore.Service.Extensions
|
|||||||
services.AddSingleton<ProviderDatabaseService>();
|
services.AddSingleton<ProviderDatabaseService>();
|
||||||
services.AddSingleton<RoomDatabaseService>();
|
services.AddSingleton<RoomDatabaseService>();
|
||||||
services.AddSingleton<AutomationDatabaseService>();
|
services.AddSingleton<AutomationDatabaseService>();
|
||||||
|
services.AddSingleton<AlarmDatabaseService>();
|
||||||
services.AddSingleton<ActionService>();
|
services.AddSingleton<ActionService>();
|
||||||
services.AddSingleton<MqttClientService>();
|
services.AddSingleton<MqttClientService>();
|
||||||
services.AddSingleton<IHostedService>(serviceProvider =>
|
services.AddSingleton<IHostedService>(serviceProvider =>
|
||||||
|
|||||||
332
MyCore/Services/AlarmService.cs
Normal file
332
MyCore/Services/AlarmService.cs
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
using Mqtt.Client.AspNetCore.Services;
|
||||||
|
using MyCore.Interfaces.DTO;
|
||||||
|
using MyCore.Interfaces.Models;
|
||||||
|
using MyCore.Service.Controllers.Helpers;
|
||||||
|
using MyCore.Services;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static MyCore.Interfaces.Models.AlarmMode;
|
||||||
|
|
||||||
|
namespace MyCore.Service.Services
|
||||||
|
{
|
||||||
|
public class AlarmService
|
||||||
|
{
|
||||||
|
#region DB - classic methods
|
||||||
|
public static AlarmModeDetailDTO CreateOrUpdate(AlarmDatabaseService _AlarmDatabaseService, DeviceDatabaseService _DeviceDatabaseService, string homeId, AlarmModeCreateOrUpdateDetailDTO alarmModeCreateOrUpdateDetailDTO, bool create)
|
||||||
|
{
|
||||||
|
AlarmMode alarmMode;
|
||||||
|
if (create)
|
||||||
|
{
|
||||||
|
alarmMode = new AlarmMode();
|
||||||
|
alarmMode.CreatedDate = DateTime.Now;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alarmMode = _AlarmDatabaseService.GetById(alarmModeCreateOrUpdateDetailDTO.Id);
|
||||||
|
|
||||||
|
alarmMode.HomeId = homeId;
|
||||||
|
alarmMode.Name = alarmModeCreateOrUpdateDetailDTO.Name;
|
||||||
|
alarmMode.UpdatedDate = DateTime.Now;
|
||||||
|
alarmMode.Type = alarmModeCreateOrUpdateDetailDTO.Type;
|
||||||
|
alarmMode.Notification = alarmModeCreateOrUpdateDetailDTO.Notification;
|
||||||
|
|
||||||
|
switch (alarmMode.Type)
|
||||||
|
{
|
||||||
|
case AlarmType.Home:
|
||||||
|
case AlarmType.Absent:
|
||||||
|
case AlarmType.Custom:
|
||||||
|
alarmMode.Triggers = alarmModeCreateOrUpdateDetailDTO.Triggers;
|
||||||
|
alarmMode.Actions = alarmModeCreateOrUpdateDetailDTO.Actions;
|
||||||
|
break;
|
||||||
|
case AlarmType.Geolocalized:
|
||||||
|
// 1. Select GPS coord and zone
|
||||||
|
// 2. Which mode when absent
|
||||||
|
// 3. Which mode when present
|
||||||
|
alarmMode.GeolocalizedMode = alarmModeCreateOrUpdateDetailDTO.GeolocalizedMode;
|
||||||
|
break;
|
||||||
|
case AlarmType.Programmed:
|
||||||
|
// Define periods when specific mode are activated (existing ones)
|
||||||
|
alarmMode.ProgrammedMode = alarmModeCreateOrUpdateDetailDTO.ProgrammedMode;
|
||||||
|
break;
|
||||||
|
case AlarmType.Desarmed:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> devicesIds = alarmModeCreateOrUpdateDetailDTO.Triggers.Select(t => t.DeviceId).ToList();
|
||||||
|
alarmMode.DevicesIds = devicesIds;
|
||||||
|
if (create)
|
||||||
|
alarmMode = _AlarmDatabaseService.Create(alarmMode);
|
||||||
|
else
|
||||||
|
alarmMode = _AlarmDatabaseService.Update(alarmMode);
|
||||||
|
|
||||||
|
// List devices for DTO (only)
|
||||||
|
List<Device> devices = new List<Device>();
|
||||||
|
foreach (var deviceId in devicesIds)
|
||||||
|
{
|
||||||
|
Device device = _DeviceDatabaseService.GetById(deviceId);
|
||||||
|
if (device != null)
|
||||||
|
{
|
||||||
|
devices.Add(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return alarmMode.ToDetailDTO(devices.Select(d => d.ToDTO()).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Activate(AlarmDatabaseService _AlarmDatabaseService, AlarmMode alarmModeToActivate, HomeDatabaseService _HomeDatabaseService)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// Desactivate current mode
|
||||||
|
AlarmMode alarmMode = _AlarmDatabaseService.GetCurrentActivatedAlarm(alarmModeToActivate.HomeId);
|
||||||
|
alarmMode.Activated = false;
|
||||||
|
|
||||||
|
alarmMode = _AlarmDatabaseService.Update(alarmMode);
|
||||||
|
|
||||||
|
// Activate the new one
|
||||||
|
alarmModeToActivate.Activated = true;
|
||||||
|
alarmModeToActivate = _AlarmDatabaseService.Update(alarmModeToActivate);
|
||||||
|
|
||||||
|
// Update home
|
||||||
|
return HomeService.UpdateAlarmMode(_HomeDatabaseService, alarmModeToActivate); // Change active mode for home
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Todo add log
|
||||||
|
System.Console.WriteLine($"An error has occurred during activating alarm {alarmModeToActivate.Name} : {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CreateDefaultAlarmModes(HomeDatabaseService _HomeDatabaseService, AlarmDatabaseService _AlarmDatabaseService, Home home)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Home mode
|
||||||
|
AlarmMode homeMode = new AlarmMode() { HomeId = home.Id, Name = AlarmType.Home.ToString(), Type = AlarmType.Home, Activated = false, IsDefault = true, Notification = true, CreatedDate = DateTime.Now, UpdatedDate = DateTime.Now };
|
||||||
|
homeMode = _AlarmDatabaseService.Create(homeMode);
|
||||||
|
|
||||||
|
// Absent mode
|
||||||
|
AlarmMode absentMode = new AlarmMode() { HomeId = home.Id, Name = AlarmType.Absent.ToString(), Type = AlarmType.Absent, Activated = false, IsDefault = true, Notification = true, CreatedDate = DateTime.Now, UpdatedDate = DateTime.Now };
|
||||||
|
absentMode = _AlarmDatabaseService.Create(absentMode);
|
||||||
|
|
||||||
|
// Geolocalized
|
||||||
|
AlarmMode geolocalizedMode = new AlarmMode() { HomeId = home.Id, Name = AlarmType.Geolocalized.ToString(), Type = AlarmType.Geolocalized, Activated = false, IsDefault = true, Notification = true, CreatedDate = DateTime.Now, UpdatedDate = DateTime.Now, GeolocalizedMode = new GeolocalizedMode() };
|
||||||
|
geolocalizedMode = _AlarmDatabaseService.Create(geolocalizedMode);
|
||||||
|
|
||||||
|
// Programmed mode
|
||||||
|
AlarmMode programmedMode = new AlarmMode() { HomeId = home.Id, Name = AlarmType.Programmed.ToString(), Type = AlarmType.Programmed, Activated = false, IsDefault = true, Notification = true, CreatedDate = DateTime.Now, UpdatedDate = DateTime.Now, ProgrammedMode = new ProgrammedMode() };
|
||||||
|
programmedMode = _AlarmDatabaseService.Create(programmedMode);
|
||||||
|
|
||||||
|
// Desarmed mode
|
||||||
|
AlarmMode desarmedMode = new AlarmMode() { HomeId = home.Id, Name = AlarmType.Desarmed.ToString(), Type = AlarmType.Desarmed, Activated = true, IsDefault = true, Notification = true, CreatedDate = DateTime.Now, UpdatedDate = DateTime.Now };
|
||||||
|
desarmedMode = _AlarmDatabaseService.Create(desarmedMode);
|
||||||
|
|
||||||
|
return HomeService.UpdateAlarmMode(_HomeDatabaseService, desarmedMode); // Activate desarmed mode by default
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Todo add log
|
||||||
|
System.Console.WriteLine($"An error has occurred during creating default alarm modes for home {home.Name} : {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Handle message event
|
||||||
|
internal static void HandleMessage(AlarmMode alarmMode, Device deviceTrigger, string message, DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, GroupDatabaseService _GroupDatabaseService, string homeId)
|
||||||
|
{
|
||||||
|
bool isAction = false;
|
||||||
|
switch (alarmMode.Type)
|
||||||
|
{
|
||||||
|
case AlarmType.Home:
|
||||||
|
case AlarmType.Absent:
|
||||||
|
case AlarmType.Custom:
|
||||||
|
// Check if trigger status correct
|
||||||
|
var alarmTriggers = alarmMode.Triggers.Where(t => t.DeviceId == deviceTrigger.Id).ToList();
|
||||||
|
|
||||||
|
#region Check trigger
|
||||||
|
foreach (var alarmTrigger in alarmTriggers)
|
||||||
|
{
|
||||||
|
List<Expose> exposes = DevicesHelper.GetDeviceExposes(deviceTrigger);
|
||||||
|
|
||||||
|
var triggerStateValueCheck = (object)null;
|
||||||
|
|
||||||
|
// Try to get automationTrigger.StateName of zigbee device
|
||||||
|
var expose = exposes.Where(e => e.name == alarmTrigger.StateName).FirstOrDefault();
|
||||||
|
bool validTrigger = expose != null; // No expose found.. => the device has not the correct state => not correct automation
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Try to get specific field from message
|
||||||
|
var dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(message);
|
||||||
|
triggerStateValueCheck = dic[alarmTrigger.StateName]; // if action slide => get slide
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
validTrigger = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (validTrigger && alarmTrigger.StateValue.ToLower() == triggerStateValueCheck.ToString().ToLower())
|
||||||
|
{
|
||||||
|
// Correct trigger !
|
||||||
|
System.Console.WriteLine($"Correct trigger for alarm {alarmMode.Name}");
|
||||||
|
|
||||||
|
#region Actions !
|
||||||
|
foreach (var action in alarmMode.Actions)
|
||||||
|
{
|
||||||
|
|
||||||
|
var DeviceNameForAction = "";
|
||||||
|
Device actionDeviceToTest = new Device();
|
||||||
|
|
||||||
|
// Retrieve action type
|
||||||
|
switch (action.Type)
|
||||||
|
{
|
||||||
|
case ActionType.DEVICE:
|
||||||
|
var deviceAction = _DeviceDatabaseService.GetById(action.DeviceId);
|
||||||
|
var providerActionTest = _ProviderDatabaseService.GetById(homeId, action.ProviderId);
|
||||||
|
|
||||||
|
DeviceNameForAction = deviceAction.Name;
|
||||||
|
actionDeviceToTest = deviceAction;
|
||||||
|
System.Console.WriteLine($"We get a device action ! Name={deviceAction.Name} Type={deviceAction.Type}");
|
||||||
|
System.Console.WriteLine($"Check action provider type ! Type={providerActionTest.Type} Name={providerActionTest.Name}");
|
||||||
|
break;
|
||||||
|
case ActionType.GROUP:
|
||||||
|
var groupAction = _GroupDatabaseService.GetById(action.GroupId);
|
||||||
|
DeviceNameForAction = groupAction.Name;
|
||||||
|
|
||||||
|
System.Console.WriteLine($"We get a group action ! Name={groupAction.Name} Type={groupAction.Type}");
|
||||||
|
System.Console.WriteLine($"Check action zigbeeGroupAction type ! Type={groupAction.Type}");
|
||||||
|
|
||||||
|
// Check state of first device of a group
|
||||||
|
actionDeviceToTest = _DeviceDatabaseService.GetByGroup(groupAction.Id).FirstOrDefault(); // TODO : Send error if no device found !
|
||||||
|
break;
|
||||||
|
case ActionType.MQTT:
|
||||||
|
// take raw request and send it !
|
||||||
|
RawRequestMQTT rawRequestMQTT = JsonConvert.DeserializeObject<RawRequestMQTT>(action.RawRequest);
|
||||||
|
|
||||||
|
if (rawRequestMQTT != null)
|
||||||
|
{
|
||||||
|
// SEND REQUEST
|
||||||
|
System.Console.WriteLine($"Send raw request mqtt! topic:{rawRequestMQTT.topic} - message: {rawRequestMQTT.message}");
|
||||||
|
MqttClientService.PublishMessage(rawRequestMQTT.topic, rawRequestMQTT.message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ActionType.HTTP: // Correct way ?
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var providerAction = _ProviderDatabaseService.GetById(homeId, action.ProviderId);
|
||||||
|
|
||||||
|
// Check if device exist
|
||||||
|
if (actionDeviceToTest != null && providerAction != null)
|
||||||
|
{
|
||||||
|
switch (providerAction.Type)
|
||||||
|
{
|
||||||
|
case ProviderType.zigbee2mqtt:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DevicesHelper.ActionOnZigbee2Mqtt(actionDeviceToTest, action, DeviceNameForAction);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"ActionOnZigbee2Mqtt result in error: {ex}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ProviderType.meross:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DevicesHelper.ActionOnMeross(_DeviceDatabaseService, actionDeviceToTest, action, DeviceNameForAction);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"ActionOnMeross result in error: {ex}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ProviderType.yeelight:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DevicesHelper.ActionOnYeelight(_DeviceDatabaseService, actionDeviceToTest, action);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"ActionOnYeelight result in error: {ex}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"Device or group found in action incorrect");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
break;
|
||||||
|
case AlarmType.Geolocalized:
|
||||||
|
// Todo check geolocalisation..
|
||||||
|
break;
|
||||||
|
case AlarmType.Programmed:
|
||||||
|
try {
|
||||||
|
List<TimePeriodAlarm> CurrentDayLogic = new List<TimePeriodAlarm>();
|
||||||
|
switch (DateTime.Now.DayOfWeek)
|
||||||
|
{
|
||||||
|
case DayOfWeek.Monday:
|
||||||
|
CurrentDayLogic = alarmMode.ProgrammedMode.Monday;
|
||||||
|
break;
|
||||||
|
case DayOfWeek.Tuesday:
|
||||||
|
CurrentDayLogic = alarmMode.ProgrammedMode.Tuesday;
|
||||||
|
break;
|
||||||
|
case DayOfWeek.Wednesday:
|
||||||
|
CurrentDayLogic = alarmMode.ProgrammedMode.Wednesday;
|
||||||
|
break;
|
||||||
|
case DayOfWeek.Thursday:
|
||||||
|
CurrentDayLogic = alarmMode.ProgrammedMode.Thursday;
|
||||||
|
break;
|
||||||
|
case DayOfWeek.Friday:
|
||||||
|
CurrentDayLogic = alarmMode.ProgrammedMode.Friday;
|
||||||
|
break;
|
||||||
|
case DayOfWeek.Saturday:
|
||||||
|
CurrentDayLogic = alarmMode.ProgrammedMode.Saturday;
|
||||||
|
break;
|
||||||
|
case DayOfWeek.Sunday:
|
||||||
|
CurrentDayLogic = alarmMode.ProgrammedMode.Sunday;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Error in days");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo retrieve current time period depending the current time.
|
||||||
|
|
||||||
|
//=> TODO
|
||||||
|
isAction = false;
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Todo log
|
||||||
|
System.Console.WriteLine($"Error in alarm programmed mode {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case AlarmType.Desarmed:
|
||||||
|
isAction = false;
|
||||||
|
// Do nothing, alarm is disarmed :)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Send notification - check if error
|
||||||
|
// Send notification if exist
|
||||||
|
if (alarmMode.Notification && isAction)
|
||||||
|
System.Console.WriteLine($"TODO send notification");
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,34 +1,38 @@
|
|||||||
using MyCore.Interfaces.DTO;
|
using Mqtt.Client.AspNetCore.Services;
|
||||||
|
using MyCore.Interfaces.DTO;
|
||||||
using MyCore.Interfaces.Models;
|
using MyCore.Interfaces.Models;
|
||||||
|
using MyCore.Service.Controllers.Helpers;
|
||||||
using MyCore.Services;
|
using MyCore.Services;
|
||||||
using MyCore.Services.MyControlPanel;
|
using MyCore.Services.MyControlPanel;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using static Mqtt.Client.AspNetCore.Services.MqttClientMerossService;
|
||||||
|
|
||||||
namespace MyCore.Service.Services
|
namespace MyCore.Service.Services
|
||||||
{
|
{
|
||||||
public class AutomationService
|
public class AutomationService
|
||||||
{
|
{
|
||||||
public static AutomationDTO CreateOrUpdate(AutomationDatabaseService _AutomationDatabaseService, string homeId, AutomationCreateOrUpdateDetailDTO automationCreateOrUpdateDetailDTO, bool create)
|
public static AutomationDTO CreateOrUpdate(AutomationDatabaseService _AutomationDatabaseService, string homeId, AutomationDetailDTO automationDetailDTO, bool create)
|
||||||
{
|
{
|
||||||
Automation automation;
|
Automation automation;
|
||||||
if (create)
|
if (create)
|
||||||
automation = new Automation();
|
automation = new Automation();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
automation = _AutomationDatabaseService.GetById(automationCreateOrUpdateDetailDTO.Id);
|
automation = _AutomationDatabaseService.GetById(automationDetailDTO.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
automation.HomeId = homeId;
|
automation.HomeId = homeId;
|
||||||
automation.Name = automationCreateOrUpdateDetailDTO.Name;
|
automation.Name = automationDetailDTO.Name;
|
||||||
automation.Active = automationCreateOrUpdateDetailDTO.Active;
|
automation.Active = automationDetailDTO.Active;
|
||||||
automation.CreatedDate = create ? DateTime.Now : automation.CreatedDate;
|
automation.CreatedDate = create ? DateTime.Now : automation.CreatedDate;
|
||||||
automation.UpdatedDate = DateTime.Now;
|
automation.UpdatedDate = DateTime.Now;
|
||||||
automation.Triggers = automationCreateOrUpdateDetailDTO.Triggers;
|
automation.Triggers = automationDetailDTO.Triggers;
|
||||||
automation.Conditions = automationCreateOrUpdateDetailDTO.Conditions;
|
automation.Conditions = automationDetailDTO.Conditions;
|
||||||
automation.Actions = automationCreateOrUpdateDetailDTO.Actions;
|
automation.Actions = automationDetailDTO.Actions;
|
||||||
var allDeviceIds = new List<string>();
|
var allDeviceIds = new List<string>();
|
||||||
allDeviceIds.AddRange(automation.Triggers.Select(t => t.DeviceId)); // Only take the deviceIds from triggers
|
allDeviceIds.AddRange(automation.Triggers.Select(t => t.DeviceId)); // Only take the deviceIds from triggers
|
||||||
/*allDeviceIds.AddRange(automation.Conditions.Select(t => t.DeviceId));
|
/*allDeviceIds.AddRange(automation.Conditions.Select(t => t.DeviceId));
|
||||||
@ -50,5 +54,195 @@ namespace MyCore.Service.Services
|
|||||||
else
|
else
|
||||||
return _AutomationDatabaseService.Update(automation.Id, automation).ToDTO();
|
return _AutomationDatabaseService.Update(automation.Id, automation).ToDTO();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void HandleAutomation(List<Automation> automations, Device deviceTrigger, string message, DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, GroupDatabaseService _GroupDatabaseService, string homeId)
|
||||||
|
{
|
||||||
|
foreach (var automation in automations)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// todo check if not null and if more than one element
|
||||||
|
if (deviceTrigger != null && automation.Triggers.Any(t => t.DeviceId == deviceTrigger.Id))
|
||||||
|
{
|
||||||
|
var automationTriggers = automation.Triggers.Where(t => t.DeviceId == deviceTrigger.Id).ToList();
|
||||||
|
|
||||||
|
// Test for each automation trigger found
|
||||||
|
foreach (var automationTrigger in automationTriggers)
|
||||||
|
{
|
||||||
|
List<Expose> exposes = DevicesHelper.GetDeviceExposes(deviceTrigger);
|
||||||
|
|
||||||
|
var triggerStateValueCheck = (object)null;
|
||||||
|
|
||||||
|
// Try to get automationTrigger.StateName of zigbee device
|
||||||
|
var expose = exposes.Where(e => e.name == automationTrigger.StateName).FirstOrDefault();
|
||||||
|
bool validTrigger = expose != null; // No expose found.. => the device has not the correct state => not correct automation
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Try to get specific field from message
|
||||||
|
var dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(message);
|
||||||
|
triggerStateValueCheck = dic[automationTrigger.StateName]; // if action slide => get slide
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
validTrigger = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (validTrigger && automationTrigger.StateValue.ToLower() == triggerStateValueCheck.ToString().ToLower())
|
||||||
|
{
|
||||||
|
// Correct trigger !
|
||||||
|
System.Console.WriteLine($"Correct trigger for automation {automation.Name}");
|
||||||
|
|
||||||
|
var isConditionsRespected = CheckConditions(automation.Conditions);
|
||||||
|
|
||||||
|
if (!isConditionsRespected.Any(cr => !cr))
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("Conditions respected !");
|
||||||
|
foreach (var action in automation.Actions)
|
||||||
|
{
|
||||||
|
|
||||||
|
var DeviceNameForAction = "";
|
||||||
|
Device actionDeviceToTest = new Device();
|
||||||
|
|
||||||
|
// Retrieve action type
|
||||||
|
switch (action.Type)
|
||||||
|
{
|
||||||
|
case ActionType.DEVICE:
|
||||||
|
var deviceAction = _DeviceDatabaseService.GetById(action.DeviceId);
|
||||||
|
var providerActionTest = _ProviderDatabaseService.GetById(homeId, action.ProviderId);
|
||||||
|
|
||||||
|
DeviceNameForAction = deviceAction.Name;
|
||||||
|
actionDeviceToTest = deviceAction;
|
||||||
|
System.Console.WriteLine($"We get a device action ! Name={deviceAction.Name} Type={deviceAction.Type}");
|
||||||
|
System.Console.WriteLine($"Check action provider type ! Type={providerActionTest.Type} Name={providerActionTest.Name}");
|
||||||
|
break;
|
||||||
|
case ActionType.GROUP:
|
||||||
|
var groupAction = _GroupDatabaseService.GetById(action.GroupId);
|
||||||
|
DeviceNameForAction = groupAction.Name;
|
||||||
|
|
||||||
|
System.Console.WriteLine($"We get a group action ! Name={groupAction.Name} Type={groupAction.Type}");
|
||||||
|
System.Console.WriteLine($"Check action zigbeeGroupAction type ! Type={groupAction.Type}");
|
||||||
|
|
||||||
|
// Check state of first device of a group
|
||||||
|
actionDeviceToTest = _DeviceDatabaseService.GetByGroup(groupAction.Id).FirstOrDefault(); // TODO : Send error if no device found !
|
||||||
|
break;
|
||||||
|
case ActionType.MQTT:
|
||||||
|
// take raw request and send it !
|
||||||
|
RawRequestMQTT rawRequestMQTT = JsonConvert.DeserializeObject<RawRequestMQTT>(action.RawRequest);
|
||||||
|
|
||||||
|
if (rawRequestMQTT != null)
|
||||||
|
{
|
||||||
|
// SEND REQUEST
|
||||||
|
System.Console.WriteLine($"Send raw request mqtt! topic:{rawRequestMQTT.topic} - message: {rawRequestMQTT.message}");
|
||||||
|
MqttClientService.PublishMessage(rawRequestMQTT.topic, rawRequestMQTT.message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ActionType.HTTP: // Correct way ?
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var providerAction = _ProviderDatabaseService.GetById(homeId, action.ProviderId);
|
||||||
|
|
||||||
|
// Check if device exist
|
||||||
|
if (actionDeviceToTest != null && providerAction != null)
|
||||||
|
{
|
||||||
|
switch (providerAction.Type)
|
||||||
|
{
|
||||||
|
case ProviderType.zigbee2mqtt:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DevicesHelper.ActionOnZigbee2Mqtt(actionDeviceToTest, action, DeviceNameForAction);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"ActionOnZigbee2Mqtt result in error: {ex}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ProviderType.meross:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DevicesHelper.ActionOnMeross(_DeviceDatabaseService, actionDeviceToTest, action, DeviceNameForAction);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"ActionOnMeross result in error: {ex}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ProviderType.yeelight:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DevicesHelper.ActionOnYeelight(_DeviceDatabaseService, actionDeviceToTest, action);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"ActionOnYeelight result in error: {ex}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"Device or group found in action incorrect");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"One or more condition aren't respected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) { System.Console.WriteLine($"Exeption in one of automation logic - {ex}"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<bool> CheckConditions(List<Condition> conditions)
|
||||||
|
{
|
||||||
|
var isConditionsRespected = conditions.Count <= 0 ? new List<bool>() { true } : new List<bool>(new bool[conditions.Count]);
|
||||||
|
var i = 0;
|
||||||
|
foreach (var condition in conditions)
|
||||||
|
{
|
||||||
|
switch (condition.Type)
|
||||||
|
{
|
||||||
|
case ConditionType.STATE:
|
||||||
|
break;
|
||||||
|
case ConditionType.TIME:
|
||||||
|
TimeSpan now = DateTime.Now.TimeOfDay;
|
||||||
|
|
||||||
|
var test = JsonConvert.SerializeObject(now);
|
||||||
|
|
||||||
|
TimeSpan start = JsonConvert.DeserializeObject<TimeSpan>(condition.StartTime);
|
||||||
|
TimeSpan end = JsonConvert.DeserializeObject<TimeSpan>(condition.EndTime);
|
||||||
|
|
||||||
|
// => Test if ok with night !
|
||||||
|
|
||||||
|
if (start <= end)
|
||||||
|
{
|
||||||
|
// start and stop times are in the same day
|
||||||
|
if (now >= start && now <= end)
|
||||||
|
{
|
||||||
|
isConditionsRespected[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// start and stop times are in different days
|
||||||
|
if (now >= start || now <= end)
|
||||||
|
{
|
||||||
|
isConditionsRespected[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isConditionsRespected;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using MyCore.Interfaces.DTO;
|
using MyCore.Interfaces.DTO;
|
||||||
using MyCore.Interfaces.Models;
|
using MyCore.Interfaces.Models;
|
||||||
using MyCore.Interfaces.Models.Providers.Zigbee.Zigbee2Mqtt;
|
using MyCore.Interfaces.Models.Providers.Zigbee.Zigbee2Mqtt;
|
||||||
|
using MyCore.Service.Controllers.Helpers;
|
||||||
using MyCore.Service.Services;
|
using MyCore.Service.Services;
|
||||||
using MyCore.Services.MyControlPanel;
|
using MyCore.Services.MyControlPanel;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@ -20,7 +21,7 @@ namespace MyCore.Services.Devices
|
|||||||
private static Device deviceTrigger;
|
private static Device deviceTrigger;
|
||||||
private static string providerFromTopic;
|
private static string providerFromTopic;
|
||||||
private static string deviceServiceName;
|
private static string deviceServiceName;
|
||||||
public static async Task HandleActionFromMQTTAsync(string topic, string message, DeviceDatabaseService _DeviceDatabaseService, GroupDatabaseService _GroupDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, AutomationDatabaseService _AutomationDatabaseService, string homeId)
|
public static async Task HandleActionFromMQTTAsync(string topic, string message, DeviceDatabaseService _DeviceDatabaseService, GroupDatabaseService _GroupDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, AutomationDatabaseService _AutomationDatabaseService, AlarmDatabaseService _AlarmDatabaseService, string homeId)
|
||||||
{
|
{
|
||||||
System.Console.WriteLine($"Received message {message}");
|
System.Console.WriteLine($"Received message {message}");
|
||||||
|
|
||||||
@ -44,7 +45,6 @@ namespace MyCore.Services.Devices
|
|||||||
|
|
||||||
if (currentProvider != null)
|
if (currentProvider != null)
|
||||||
{
|
{
|
||||||
var automations = _AutomationDatabaseService.GetActiveByProvider(currentProvider.Id);
|
|
||||||
|
|
||||||
deviceTrigger = _DeviceDatabaseService.GetByName(deviceServiceName).FirstOrDefault();
|
deviceTrigger = _DeviceDatabaseService.GetByName(deviceServiceName).FirstOrDefault();
|
||||||
|
|
||||||
@ -55,145 +55,17 @@ namespace MyCore.Services.Devices
|
|||||||
// if is not a set => check automation
|
// if is not a set => check automation
|
||||||
if (topicSplit.Length <= 2)
|
if (topicSplit.Length <= 2)
|
||||||
{
|
{
|
||||||
foreach (var automation in automations)
|
#region Automations
|
||||||
{
|
var automations = _AutomationDatabaseService.GetActiveByProvider(currentProvider.Id);
|
||||||
try {
|
AutomationService.HandleAutomation(automations, deviceTrigger, message, _DeviceDatabaseService, _ProviderDatabaseService, _GroupDatabaseService, homeId);
|
||||||
// todo check if not null and if more than one element
|
#endregion
|
||||||
if (deviceTrigger != null && automation.Triggers.Any(t => t.DeviceId == deviceTrigger.Id))
|
|
||||||
{
|
|
||||||
var automationTriggers = automation.Triggers.Where(t => t.DeviceId == deviceTrigger.Id).ToList();
|
|
||||||
|
|
||||||
// Test for each automation trigger found
|
#region Alarm
|
||||||
foreach (var automationTrigger in automationTriggers)
|
AlarmMode alarmMode = _AlarmDatabaseService.GetCurrentActivatedAlarm(homeId);
|
||||||
{
|
if (alarmMode.DevicesIds.Contains(deviceTrigger.Id))
|
||||||
List<Expose> exposes = GetDeviceExposes(deviceTrigger);
|
AlarmService.HandleMessage(alarmMode, deviceTrigger, message, _DeviceDatabaseService, _ProviderDatabaseService, _GroupDatabaseService, homeId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
var triggerStateValueCheck = (object)null;
|
|
||||||
|
|
||||||
// Try to get automationTrigger.StateName of zigbee device
|
|
||||||
var expose = exposes.Where(e => e.name == automationTrigger.StateName).FirstOrDefault();
|
|
||||||
bool validTrigger = expose != null; // No expose found.. => the device has not the correct state => not correct automation
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Try to get specific field from message
|
|
||||||
var dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(message);
|
|
||||||
triggerStateValueCheck = dic[automationTrigger.StateName]; // if action slide => get slide
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
validTrigger = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (validTrigger && automationTrigger.StateValue.ToLower() == triggerStateValueCheck.ToString().ToLower())
|
|
||||||
{
|
|
||||||
// Correct trigger !
|
|
||||||
System.Console.WriteLine($"Correct trigger for automation {automation.Name}");
|
|
||||||
|
|
||||||
var isConditionsRespected = CheckConditions(automation.Conditions);
|
|
||||||
|
|
||||||
if (!isConditionsRespected.Any(cr => !cr))
|
|
||||||
{
|
|
||||||
System.Console.WriteLine("Conditions respected !");
|
|
||||||
foreach (var action in automation.Actions)
|
|
||||||
{
|
|
||||||
|
|
||||||
var DeviceNameForAction = "";
|
|
||||||
Device actionDeviceToTest = new Device();
|
|
||||||
|
|
||||||
// Retrieve action type
|
|
||||||
switch (action.Type)
|
|
||||||
{
|
|
||||||
case ActionType.DEVICE:
|
|
||||||
var deviceAction = _DeviceDatabaseService.GetById(action.DeviceId);
|
|
||||||
var providerActionTest = _ProviderDatabaseService.GetById(homeId, action.ProviderId);
|
|
||||||
|
|
||||||
DeviceNameForAction = deviceAction.Name;
|
|
||||||
actionDeviceToTest = deviceAction;
|
|
||||||
System.Console.WriteLine($"We get a device action ! Name={deviceAction.Name} Type={deviceAction.Type}");
|
|
||||||
System.Console.WriteLine($"Check action provider type ! Type={providerActionTest.Type} Name={providerActionTest.Name}");
|
|
||||||
break;
|
|
||||||
case ActionType.GROUP:
|
|
||||||
var groupAction = _GroupDatabaseService.GetById(action.GroupId);
|
|
||||||
DeviceNameForAction = groupAction.Name;
|
|
||||||
|
|
||||||
System.Console.WriteLine($"We get a group action ! Name={groupAction.Name} Type={groupAction.Type}");
|
|
||||||
System.Console.WriteLine($"Check action zigbeeGroupAction type ! Type={groupAction.Type}");
|
|
||||||
|
|
||||||
// Check state of first device of a group
|
|
||||||
actionDeviceToTest = _DeviceDatabaseService.GetByGroup(groupAction.Id).FirstOrDefault(); // TODO : Send error if no device found !
|
|
||||||
break;
|
|
||||||
case ActionType.MQTT:
|
|
||||||
// take raw request and send it !
|
|
||||||
RawRequestMQTT rawRequestMQTT = JsonConvert.DeserializeObject<RawRequestMQTT>(action.RawRequest);
|
|
||||||
|
|
||||||
if (rawRequestMQTT != null)
|
|
||||||
{
|
|
||||||
// SEND REQUEST
|
|
||||||
System.Console.WriteLine($"Send raw request mqtt! topic:{rawRequestMQTT.topic} - message: {rawRequestMQTT.message}");
|
|
||||||
MqttClientService.PublishMessage(rawRequestMQTT.topic, rawRequestMQTT.message);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ActionType.HTTP: // Correct way ?
|
|
||||||
// TODO
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var providerAction = _ProviderDatabaseService.GetById(homeId, action.ProviderId);
|
|
||||||
|
|
||||||
// Check if device exist
|
|
||||||
if (actionDeviceToTest != null && providerAction != null)
|
|
||||||
{
|
|
||||||
switch (providerAction.Type)
|
|
||||||
{
|
|
||||||
case ProviderType.zigbee2mqtt:
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ActionOnZigbee2Mqtt(actionDeviceToTest, action, DeviceNameForAction);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"ActionOnZigbee2Mqtt result in error: {ex}");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ProviderType.meross:
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ActionOnMeross(_DeviceDatabaseService, actionDeviceToTest, action, DeviceNameForAction);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"ActionOnMeross result in error: {ex}");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ProviderType.yeelight:
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ActionOnYeelight(_DeviceDatabaseService, actionDeviceToTest, action);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"ActionOnYeelight result in error: {ex}");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"Device or group found in action incorrect");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"One or more condition aren't respected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception ex) { System.Console.WriteLine($"Exeption in one of automation logic - {ex}"); }
|
|
||||||
}
|
|
||||||
// Update last state of devices
|
// Update last state of devices
|
||||||
deviceTrigger.LastStateDate = DateTime.Now;
|
deviceTrigger.LastStateDate = DateTime.Now;
|
||||||
deviceTrigger.LastState = message;
|
deviceTrigger.LastState = message;
|
||||||
@ -218,416 +90,5 @@ namespace MyCore.Services.Devices
|
|||||||
System.Console.WriteLine($"Current provider not found - {providerFromTopic}");
|
System.Console.WriteLine($"Current provider not found - {providerFromTopic}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async static void ActionOnYeelight(DeviceDatabaseService deviceDatabaseService, Device actionDeviceToTest, Interfaces.Models.Action action)
|
|
||||||
{
|
|
||||||
if (YeelightService.devices.Count <= 0)
|
|
||||||
{
|
|
||||||
await YeelightService.GetDevices();
|
|
||||||
}
|
|
||||||
var lamp = YeelightService.devices.Where(d => d.Hostname == actionDeviceToTest.IpAddress).FirstOrDefault();
|
|
||||||
if (lamp != null)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"Yeelight type !");
|
|
||||||
|
|
||||||
// Get device last state
|
|
||||||
var dic = new List<AutomationState>();
|
|
||||||
if (actionDeviceToTest.LastState != null)
|
|
||||||
{
|
|
||||||
dic = JsonConvert.DeserializeObject<List<AutomationState>>(actionDeviceToTest.LastState);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (actionDeviceToTest.Type)
|
|
||||||
{
|
|
||||||
case DeviceType.Light:
|
|
||||||
var states = action.States.Where(s => s.Name == "state" || s.Name == "brightness").ToList();
|
|
||||||
|
|
||||||
if (states.Count >= 0)
|
|
||||||
{
|
|
||||||
if (dic.Count > 0)
|
|
||||||
{
|
|
||||||
/*if (dic["state"].ToString().ToLower() == state.Value.ToLower() && action.States.Count <= 1) // workaround if brightness not the same
|
|
||||||
{
|
|
||||||
throw new Exception($"Action device is already at the good state : {state.Name} {state.Value}");
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var state in states)
|
|
||||||
{
|
|
||||||
switch (state.Name)
|
|
||||||
{
|
|
||||||
case "state":
|
|
||||||
switch (state.Value.ToLower())
|
|
||||||
{
|
|
||||||
case "on":
|
|
||||||
Task.Run(async () => { await YeelightService.TurnOn(lamp, null); });
|
|
||||||
break;
|
|
||||||
case "off":
|
|
||||||
Task.Run(async () => { await YeelightService.TurnOff(lamp); });
|
|
||||||
break;
|
|
||||||
case "toggle":
|
|
||||||
Task.Run(async () => { await YeelightService.Toggle(lamp); });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "brightness":
|
|
||||||
var brightness = int.Parse(state.Value);
|
|
||||||
Task.Run(async () => { await YeelightService.TurnOn(lamp, brightness); });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Last state
|
|
||||||
actionDeviceToTest.LastState = JsonConvert.SerializeObject(states);
|
|
||||||
actionDeviceToTest.LastStateDate = DateTime.Now;
|
|
||||||
deviceDatabaseService.Update(actionDeviceToTest);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception($"Action device light in yeelight does not have correct expose");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"Not a valid action !");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"Yeelight - Lamp offline! - {actionDeviceToTest.Name}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ActionOnMeross(DeviceDatabaseService _DeviceDatabaseService, Device actionDeviceToTest, Interfaces.Models.Action action, string deviceNameForAction)
|
|
||||||
{
|
|
||||||
var merossDevice = _DeviceDatabaseService.GetById(actionDeviceToTest.Id);
|
|
||||||
|
|
||||||
if (merossDevice != null)
|
|
||||||
{
|
|
||||||
//As multisocket channel 0 is all the sockets, skip 0
|
|
||||||
|
|
||||||
// two state = first state = ON/OFF, second var = switch channels number (LIST) // TODO better check
|
|
||||||
if (action.States.Count >= 2 && action.States.Any(s => s.Name.ToLower() == "state" && (s.Value.ToLower() == "on" || s.Value.ToLower() == "off" || s.Value.ToLower() == "toggle")))
|
|
||||||
{
|
|
||||||
var state = action.States.Where(s => s.Name.ToLower() == "state").FirstOrDefault();
|
|
||||||
var channels = action.States.Where(s => s.Name.ToLower() == "channels").FirstOrDefault();
|
|
||||||
var plugIds = JsonConvert.DeserializeObject<List<int>>(channels.Value);
|
|
||||||
|
|
||||||
List<ToggleStatus> lastStatePlug = new List<ToggleStatus>(); // Off by default
|
|
||||||
// => TODO GET ALL POSSIBILITIES FROM DEVICE (number of channels)
|
|
||||||
|
|
||||||
if (actionDeviceToTest.LastState != null) // Get last state of device
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
lastStatePlug = JsonConvert.DeserializeObject<List<ToggleStatus>>(actionDeviceToTest.LastState);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"Meross error: Last state ! - {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// By default set to OFF
|
|
||||||
foreach (var plug in plugIds)
|
|
||||||
{
|
|
||||||
lastStatePlug.Add(ToggleStatus.OFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ToggleStatus> statuses = new List<ToggleStatus>();
|
|
||||||
var p = 0;
|
|
||||||
foreach (var plugId in plugIds)
|
|
||||||
{
|
|
||||||
ToggleStatus status = new ToggleStatus();
|
|
||||||
// check if device, check if multiprise
|
|
||||||
switch (merossDevice.Type)
|
|
||||||
{
|
|
||||||
case DeviceType.Multiplug:
|
|
||||||
case DeviceType.Plug:
|
|
||||||
if (state.Value.ToLower() == "toggle")
|
|
||||||
{
|
|
||||||
status = lastStatePlug[p] == ToggleStatus.OFF ? ToggleStatus.ON : ToggleStatus.OFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
status = state.Value.ToLower() == "on" ? ToggleStatus.ON : ToggleStatus.OFF;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Send request
|
|
||||||
MqttClientMerossService.ExecuteCommand(actionDeviceToTest.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", status, plugId);
|
|
||||||
statuses.Add(status);
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Last state
|
|
||||||
actionDeviceToTest.LastState = JsonConvert.SerializeObject(statuses);
|
|
||||||
actionDeviceToTest.LastStateDate = DateTime.Now;
|
|
||||||
_DeviceDatabaseService.Update(actionDeviceToTest);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Meross: Request action invalid");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ActionOnZigbee2Mqtt(Device device, Interfaces.Models.Action action, string deviceNameForAction)
|
|
||||||
{
|
|
||||||
var request = "";
|
|
||||||
var buildRequest = new Dictionary<string, object>();
|
|
||||||
|
|
||||||
System.Console.WriteLine($"zigbee2mqtt type !");
|
|
||||||
|
|
||||||
var actionDeviceExpose = GetDeviceExposes(device);
|
|
||||||
|
|
||||||
// Get device last state
|
|
||||||
var dic = new Dictionary<string, object>();
|
|
||||||
if (device.LastState != null)
|
|
||||||
{
|
|
||||||
dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(device.LastState);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (device.Type)
|
|
||||||
{
|
|
||||||
case DeviceType.Light:
|
|
||||||
case DeviceType.Switch:
|
|
||||||
var actionDeviceExposeForFeatures = actionDeviceExpose.Where(e => e.type == ((DeviceType)device.Type).ToString().ToLower()).FirstOrDefault();
|
|
||||||
if (actionDeviceExposeForFeatures != null)
|
|
||||||
{
|
|
||||||
foreach (var state in action.States)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"Check Action in light|switch ! {state.Name} {state.Value}");
|
|
||||||
if (actionDeviceExposeForFeatures.features.Any(ade => ade.name == state.Name))
|
|
||||||
{
|
|
||||||
// Comment this for test (ensure the request will be sent)
|
|
||||||
/*if (dic.Count > 0)
|
|
||||||
{
|
|
||||||
//if (device.Type == DeviceType.Light) {}
|
|
||||||
var test = dic["state"].ToString().ToLower();
|
|
||||||
var test0 = state.Value.ToLower();
|
|
||||||
if (dic["state"].ToString().ToLower() == state.Value.ToLower() && action.States.Count <= 1) // workaround if brightness not the same => For switch or light without brightness
|
|
||||||
{
|
|
||||||
throw new Exception($"Action device is already at the good state : {state.Name} {state.Value}");
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (state.Name == "brightness")
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int brightness = int.Parse(state.Value);
|
|
||||||
// Add to request
|
|
||||||
buildRequest.Add(state.Name, brightness);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"zigbee - Parse to int error {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Add to request
|
|
||||||
buildRequest.Add(state.Name, state.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception($"Action device light|switch does not have expose of type {state.Name}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If any action ask for state update, check if device is already at the asked state
|
|
||||||
if (action.States.Any(s => s.Name == "state") && !action.IsForce)
|
|
||||||
{
|
|
||||||
bool sendRequest = true;
|
|
||||||
|
|
||||||
// If action doesn't ask for brightness just test if device is already at the asked state
|
|
||||||
if (action.States.Any(s => s.Name == "brightness"))
|
|
||||||
{
|
|
||||||
// Check state and brightness
|
|
||||||
// if we got state value (current value)
|
|
||||||
if (dic.Any(d => d.Key == "state"))
|
|
||||||
{
|
|
||||||
var currentValue = dic["state"].ToString().ToLower();
|
|
||||||
var askedValue = action.States.FirstOrDefault(s => s.Name == "state").Value.ToLower();
|
|
||||||
if (currentValue == askedValue)
|
|
||||||
{
|
|
||||||
// Check brightness difference
|
|
||||||
if (dic.Any(d => d.Key == "brightness"))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var currentValueBrightness = int.Parse(dic["brightness"].ToString().ToLower());
|
|
||||||
var askedValueBrightness = int.Parse(action.States.FirstOrDefault(s => s.Name == "brightness").Value.ToLower());
|
|
||||||
if (Math.Abs(currentValueBrightness - askedValueBrightness) <= 5) // brightness diff is lower than 5 => don't change brightness
|
|
||||||
sendRequest = false;
|
|
||||||
else
|
|
||||||
sendRequest = true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
sendRequest = false;
|
|
||||||
System.Console.WriteLine($"int parse error in brightness check", ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check only state value
|
|
||||||
// if we got state value (current value)
|
|
||||||
if (dic.Any(d => d.Key == "state"))
|
|
||||||
{
|
|
||||||
var currentValue = dic["state"].ToString().ToLower();
|
|
||||||
var askedValue = action.States.FirstOrDefault(s => s.Name == "state").Value.ToLower();
|
|
||||||
if (currentValue == askedValue)
|
|
||||||
sendRequest = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sendRequest)
|
|
||||||
throw new Exception($"Action device is already at the good state");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw new Exception("Action device does not have expose of type light|switch");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
foreach (var state in action.States)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"Check Action ! {state.Name} {state.Value}");
|
|
||||||
if (!actionDeviceExpose.Any(ade => ade.name == state.Name))
|
|
||||||
{
|
|
||||||
throw new Exception($"Action device does not have expose of type {state.Name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
request = JsonConvert.SerializeObject(buildRequest);
|
|
||||||
|
|
||||||
// SEND REQUEST
|
|
||||||
//var requestToSend = $"Send request ! zigbee2mqtt/{deviceNameForAction}/set/{request}";
|
|
||||||
System.Console.WriteLine($"Send request ! zigbee2mqtt/{deviceNameForAction}/set/{request}");
|
|
||||||
|
|
||||||
MqttClientService.PublishMessage("zigbee2mqtt/" + deviceNameForAction + "/set", request);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Console.WriteLine($"Not a valid action !");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<bool> CheckConditions(List<Condition> conditions)
|
|
||||||
{
|
|
||||||
var isConditionsRespected = conditions.Count <= 0 ? new List<bool>() { true } : new List<bool>(new bool[conditions.Count]);
|
|
||||||
var i = 0;
|
|
||||||
foreach (var condition in conditions)
|
|
||||||
{
|
|
||||||
switch (condition.Type)
|
|
||||||
{
|
|
||||||
case ConditionType.STATE:
|
|
||||||
break;
|
|
||||||
case ConditionType.TIME:
|
|
||||||
TimeSpan now = DateTime.Now.TimeOfDay;
|
|
||||||
|
|
||||||
var test = JsonConvert.SerializeObject(now);
|
|
||||||
|
|
||||||
TimeSpan start = JsonConvert.DeserializeObject<TimeSpan>(condition.StartTime);
|
|
||||||
TimeSpan end = JsonConvert.DeserializeObject<TimeSpan>(condition.EndTime);
|
|
||||||
|
|
||||||
// => Test if ok with night !
|
|
||||||
|
|
||||||
if (start <= end)
|
|
||||||
{
|
|
||||||
// start and stop times are in the same day
|
|
||||||
if (now >= start && now <= end)
|
|
||||||
{
|
|
||||||
isConditionsRespected[i] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// start and stop times are in different days
|
|
||||||
if (now >= start || now <= end)
|
|
||||||
{
|
|
||||||
isConditionsRespected[i] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isConditionsRespected;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Expose> GetDeviceExposes(Device device)
|
|
||||||
{
|
|
||||||
List<Expose> exposes = new List<Expose>();
|
|
||||||
// Get Exposes for the zigbee device
|
|
||||||
foreach (var supportedOperation in device.SupportedOperations)
|
|
||||||
{
|
|
||||||
exposes.Add(JsonConvert.DeserializeObject<Expose>(supportedOperation));
|
|
||||||
}
|
|
||||||
return exposes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static System.Type GetStateType(Expose expose)
|
|
||||||
{
|
|
||||||
switch (expose.type)
|
|
||||||
{
|
|
||||||
// e.g.: occupancy
|
|
||||||
case "binary":
|
|
||||||
if (expose.value_toggle == null)
|
|
||||||
{
|
|
||||||
// value are boolean
|
|
||||||
return true.GetType();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// value are string
|
|
||||||
return "".GetType();
|
|
||||||
}
|
|
||||||
case "numeric":
|
|
||||||
return new long().GetType();
|
|
||||||
case "enum":
|
|
||||||
return expose.values.GetType();
|
|
||||||
break;
|
|
||||||
/*case "text":
|
|
||||||
break;
|
|
||||||
case "light":
|
|
||||||
break;
|
|
||||||
case "composite":
|
|
||||||
break;
|
|
||||||
case "switch":
|
|
||||||
break;*/
|
|
||||||
/*case "fan":
|
|
||||||
break;
|
|
||||||
case "cover":
|
|
||||||
break;
|
|
||||||
case "lock":
|
|
||||||
break;
|
|
||||||
case "climate":
|
|
||||||
break;*/
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,24 +140,45 @@ namespace MyCore.Service.Services
|
|||||||
} else {
|
} else {
|
||||||
if (!Enumerable.SequenceEqual(zigbee2MqttGroup.members.Select(m => m.ieee_address).OrderBy(t => t), existingGroupWithThisId.members.Select(m => m.ieee_address).OrderBy(t => t)))
|
if (!Enumerable.SequenceEqual(zigbee2MqttGroup.members.Select(m => m.ieee_address).OrderBy(t => t), existingGroupWithThisId.members.Select(m => m.ieee_address).OrderBy(t => t)))
|
||||||
{
|
{
|
||||||
// different ? Update
|
// TO TEEEEST !!
|
||||||
|
|
||||||
|
/*
|
||||||
// As user not change everytime.. => Hard refresh.
|
// As user not change everytime.. => Hard refresh.
|
||||||
var groupToDelete = groups.Where(eg => eg.ServiceIdentification == existingGroupWithThisId.id).FirstOrDefault();
|
var groupToUpdate = groups.Where(eg => eg.ServiceIdentification == existingGroupWithThisId.id).FirstOrDefault();
|
||||||
|
|
||||||
// Delete in device first
|
// Update in device first
|
||||||
var devicesInGroup = _DeviceDatabaseService.GetByGroup(groupToDelete.Id);
|
var devicesInGroup = _DeviceDatabaseService.GetByGroup(groupToUpdate.Id);
|
||||||
|
|
||||||
foreach (var device in devicesInGroup)
|
// Devices to add to the group
|
||||||
|
List<string> devicesToAdd = zigbee2MqttGroup.members.Select(m => m.ieee_address).Where(ia => !existingGroupWithThisId.members.Select(m => m.ieee_address).ToList().Contains(ia)).ToList();
|
||||||
|
|
||||||
|
foreach (var deviceId in devicesToAdd)
|
||||||
{
|
{
|
||||||
device.GroupIds = device.GroupIds.Where(g => g != groupToDelete.Id).ToList();
|
Device device = _DeviceDatabaseService.GetById(deviceId);
|
||||||
|
device.GroupIds.Add(groupToUpdate.Id);
|
||||||
_DeviceDatabaseService.Update(device);
|
_DeviceDatabaseService.Update(device);
|
||||||
}
|
}
|
||||||
// Delete group
|
|
||||||
_GroupDatabaseService.Remove(groupToDelete.Id);
|
|
||||||
|
|
||||||
// Create new group
|
// Devices to add to the group
|
||||||
CreateFromZigbeeAsync(_GroupDatabaseService, _DeviceDatabaseService, homeId, new List<Zigbee2MqttGroup>() { zigbee2MqttGroup });
|
List<string> devicesToRemove = existingGroupWithThisId.members.Select(m => m.ieee_address).Where(ia => !zigbee2MqttGroup.members.Select(m => m.ieee_address).ToList().Contains(ia)).ToList();
|
||||||
|
|
||||||
|
foreach (var deviceId in devicesToRemove)
|
||||||
|
{
|
||||||
|
Device device = _DeviceDatabaseService.GetById(deviceId);
|
||||||
|
device.GroupIds = device.GroupIds.Where(g => g != groupToUpdate.Id).ToList();
|
||||||
|
_DeviceDatabaseService.Update(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update group
|
||||||
|
groupToUpdate.DevicesIds = new List<string>(); // Remove all for update
|
||||||
|
foreach (var deviceId in zigbee2MqttGroup.members.Select(m => m.ieee_address).ToList())
|
||||||
|
{
|
||||||
|
Device device = _DeviceDatabaseService.GetById(deviceId);
|
||||||
|
groupToUpdate.DevicesIds.Add(device.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
_GroupDatabaseService.Update(groupToUpdate);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else do nothing
|
// else do nothing
|
||||||
|
|||||||
@ -45,6 +45,11 @@ namespace MyCore.Services
|
|||||||
return alarmIn;
|
return alarmIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AlarmMode GetCurrentActivatedAlarm(string homeId)
|
||||||
|
{
|
||||||
|
return _Alarms.Find<AlarmMode>(alarm => alarm.Activated && alarm.HomeId == homeId).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
public void Remove(string id)
|
public void Remove(string id)
|
||||||
{
|
{
|
||||||
_Alarms.DeleteOne(alarm => alarm.Id == id);
|
_Alarms.DeleteOne(alarm => alarm.Id == id);
|
||||||
|
|||||||
@ -44,7 +44,7 @@ namespace MyCore.Services
|
|||||||
return _Devices.Find<Device>(h => h.HomeId == homeId).ToList();
|
return _Devices.Find<Device>(h => h.HomeId == homeId).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Device> GetByLocation(string homeId, string roomId)
|
public List<Device> GetByRoom(string homeId, string roomId)
|
||||||
{
|
{
|
||||||
return _Devices.Find<Device>(d => d.HomeId == homeId && d.RoomId == roomId).ToList();
|
return _Devices.Find<Device>(d => d.HomeId == homeId && d.RoomId == roomId).ToList();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,9 +39,9 @@ namespace MyCore.Services
|
|||||||
return home;
|
return home;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Home Update(string id, Home homeIn)
|
public Home Update(Home homeIn)
|
||||||
{
|
{
|
||||||
_Homes.ReplaceOne(home => home.Id == id, homeIn);
|
_Homes.ReplaceOne(home => home.Id == homeIn.Id, homeIn);
|
||||||
return homeIn;
|
return homeIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,26 @@ namespace MyCore.Services
|
|||||||
if (create)
|
if (create)
|
||||||
return _HomeDatabaseService.Create(home);
|
return _HomeDatabaseService.Create(home);
|
||||||
else
|
else
|
||||||
return _HomeDatabaseService.Update(home.Id, home);
|
return _HomeDatabaseService.Update(home);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool UpdateAlarmMode(HomeDatabaseService _HomeDatabaseService, AlarmMode alarmMode)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Home home = _HomeDatabaseService.GetById(alarmMode.HomeId);
|
||||||
|
home.CurrentAlarmMode = alarmMode;
|
||||||
|
|
||||||
|
_HomeDatabaseService.Update(home);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Todo add log
|
||||||
|
System.Console.WriteLine($"An error has occurred during updating default alarm modes named {alarmMode.Name} : {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user