mirror of
https://bitbucket.org/myhomie/mycorerepository.git
synced 2025-12-06 09:41:19 +00:00
255 lines
12 KiB
C#
255 lines
12 KiB
C#
using Mqtt.Client.AspNetCore.Services;
|
|
using MyCore.Interfaces.DTO;
|
|
using MyCore.Interfaces.Models;
|
|
using MyCore.Service.Controllers.Helpers;
|
|
using MyCore.Services;
|
|
using MyCore.Services.MyControlPanel;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace MyCore.Service.Services
|
|
{
|
|
public class AutomationService
|
|
{
|
|
public static AutomationDTO CreateOrUpdate(AutomationDatabaseService _AutomationDatabaseService, string homeId, AutomationDetailDTO automationDetailDTO, bool create)
|
|
{
|
|
Automation automation;
|
|
if (create)
|
|
automation = new Automation();
|
|
else
|
|
{
|
|
automation = _AutomationDatabaseService.GetById(automationDetailDTO.Id);
|
|
}
|
|
|
|
automation.HomeId = homeId;
|
|
automation.Name = automationDetailDTO.Name;
|
|
automation.Active = automationDetailDTO.Active;
|
|
automation.CreatedDate = create ? DateTime.Now : automation.CreatedDate;
|
|
automation.UpdatedDate = DateTime.Now;
|
|
automation.Triggers = automationDetailDTO.Triggers;
|
|
automation.Conditions = automationDetailDTO.Conditions;
|
|
automation.Actions = automationDetailDTO.Actions;
|
|
var allDeviceIds = new List<string>();
|
|
allDeviceIds.AddRange(automation.Triggers.Select(t => t.DeviceId)); // Only take the deviceIds from triggers
|
|
/*allDeviceIds.AddRange(automation.Conditions.Select(t => t.DeviceId));
|
|
|
|
foreach(var action in automation.Actions) {
|
|
if (action.DeviceId != null) {
|
|
allDeviceIds.Add(action.DeviceId);
|
|
}
|
|
if (action.GroupId != null)
|
|
{
|
|
|
|
}
|
|
}*/
|
|
|
|
automation.DevicesIds = allDeviceIds;
|
|
|
|
if (create)
|
|
return _AutomationDatabaseService.Create(automation).ToDTO();
|
|
else
|
|
return _AutomationDatabaseService.Update(automation.Id, automation).ToDTO();
|
|
}
|
|
|
|
public static void HandleAutomation(List<Automation> automations, Device deviceTrigger, string message, DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, GroupDatabaseService _GroupDatabaseService, EventDatabaseService _EventDatabaseService, Home home)
|
|
{
|
|
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 !");
|
|
|
|
// Create an event
|
|
EventDetailDTO eventDetailDTO = new EventDetailDTO() { Type = EventType.AutomationTriggered, HomeId = home.Id, RoomId = deviceTrigger.RoomId, AutomationTriggered = new AutomationTriggered() { AutomationId = automation.Id, AutomationName = automation.Name }, DeviceState = new DeviceState() { DeviceId = deviceTrigger.Id, DeviceName = deviceTrigger.Name, DeviceType = deviceTrigger.Type, Message = message } };
|
|
EventService.CreateOrUpdate(_EventDatabaseService, home.Id, eventDetailDTO, true);
|
|
|
|
foreach (var action in automation.Actions)
|
|
{
|
|
HandleAction(home.Id, action, _ProviderDatabaseService, _DeviceDatabaseService, _GroupDatabaseService) ;
|
|
}
|
|
}
|
|
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 void HandleAction(string homeId, Interfaces.Models.Action action, ProviderDatabaseService providerDatabaseService, DeviceDatabaseService deviceDatabaseService, GroupDatabaseService groupDatabaseService)
|
|
{
|
|
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(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(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");
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
}
|
|
}
|