mirror of
https://bitbucket.org/myhomie/mycorerepository.git
synced 2025-12-06 09:41:19 +00:00
345 lines
18 KiB
C#
345 lines
18 KiB
C#
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> devicesIdsTriggers = alarmModeCreateOrUpdateDetailDTO.Triggers.Select(t => t.DeviceId).ToList();
|
|
alarmMode.DevicesIds = devicesIdsTriggers;
|
|
|
|
List<string> devicesIdsActions = alarmModeCreateOrUpdateDetailDTO.Actions.Select(t => t.DeviceId).ToList();
|
|
alarmMode.DevicesIds.AddRange(devicesIdsActions);
|
|
|
|
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 alarmMode.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, Actions = new List<Interfaces.Models.Action>(), Triggers = new List<Trigger>(), DevicesIds = new List<string>() };
|
|
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, Triggers = new List<Trigger>(), DevicesIds = new List<string>() };
|
|
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(), Triggers = new List<Trigger>(), DevicesIds = new List<string>() };
|
|
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(), Triggers = new List<Trigger>(), DevicesIds = new List<string>() };
|
|
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, Triggers = new List<Trigger>(), DevicesIds = new List<string>() };
|
|
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, EventDatabaseService _EventDatabaseService, 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}");
|
|
isAction = true;
|
|
|
|
#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 - save event
|
|
if (isAction)
|
|
{
|
|
// Create an event
|
|
EventDetailDTO eventDetailDTO = new EventDetailDTO() { Type = EventType.AlarmTriggered, HomeId = homeId, RoomId = deviceTrigger.RoomId, AlarmTriggered = new AlarmTriggered() { AlarmModeId = alarmMode.Id, AlarmModeName = alarmMode.Name }, DeviceState = new DeviceState() { DeviceId = deviceTrigger.Id, DeviceName = deviceTrigger.Name, DeviceType = deviceTrigger.Type, Message = message } };
|
|
EventService.CreateOrUpdate(_EventDatabaseService, homeId, eventDetailDTO, true);
|
|
|
|
// Send notification if exist
|
|
if (alarmMode.Notification)
|
|
System.Console.WriteLine($"TODO send notification");
|
|
}
|
|
#endregion
|
|
}
|
|
#endregion
|
|
}
|
|
}
|