MC add automation handler in action service + test with zigbee2mqtt devices

This commit is contained in:
Thomas Fransolet 2021-03-03 18:14:17 +01:00
parent 5425e7aeee
commit fd1e6994da
12 changed files with 152 additions and 33 deletions

View File

@ -22,4 +22,11 @@ namespace MyCore.Interfaces.DTO
Gateway, Gateway,
Unknown Unknown
} }
public enum DeviceAction // TO BE Continued
{
toggle = 1,
on,
off
}
} }

View File

@ -20,7 +20,7 @@ namespace MyCore.Interfaces.DTO
public List<Trigger> Triggers { get; set; } public List<Trigger> Triggers { get; set; }
public List<Condition> Conditions { get; set; } public List<Condition> Conditions { get; set; }
public List<MyCore.Interfaces.Models.Action> Actions { get; set; } public List<MyCore.Interfaces.Models.Action> Actions { get; set; }
public List<string> DeviceIds { get; set; } public List<string> DevicesIds { get; set; }
} }
public class AutomationCreateOrUpdateDetailDTO : AutomationDTO public class AutomationCreateOrUpdateDetailDTO : AutomationDTO

View File

@ -48,6 +48,8 @@ namespace MyCore.Interfaces.Models
Id = Id, Id = Id,
Name = Name, Name = Name,
UserId = UserId, UserId = UserId,
CreatedDate = CreatedDate,
UpdatedDate = UpdatedDate,
//Triggers = Triggers //Triggers = Triggers
//Conditions = Conditions //Conditions = Conditions
//Actions = Actions //Actions = Actions
@ -63,9 +65,10 @@ namespace MyCore.Interfaces.Models
UserId = UserId, UserId = UserId,
CreatedDate = CreatedDate, CreatedDate = CreatedDate,
UpdatedDate = UpdatedDate, UpdatedDate = UpdatedDate,
//Triggers = Triggers Triggers = Triggers,
//Conditions = Conditions Conditions = Conditions,
//Actions = Actions Actions = Actions,
DevicesIds = DevicesIds
}; };
} }
} }
@ -74,8 +77,8 @@ namespace MyCore.Interfaces.Models
{ {
public string ProviderId { get; set; } public string ProviderId { get; set; }
public string DeviceId { get; set; } public string DeviceId { get; set; }
public object StateName { get; set; } public string StateName { get; set; }
public object StateValue { get; set; } public string StateValue { get; set; }
public enum Type public enum Type
{ {
@ -88,8 +91,8 @@ namespace MyCore.Interfaces.Models
public class Condition public class Condition
{ {
public string DeviceId { get; set; } public string DeviceId { get; set; }
public object StateName { get; set; } public string StateName { get; set; }
public object StateValue { get; set; } public string StateValue { get; set; }
public enum Type public enum Type
{ {
@ -101,8 +104,8 @@ namespace MyCore.Interfaces.Models
public class Action public class Action
{ {
public string DeviceId { get; set; } public string DeviceId { get; set; }
public object StateName { get; set; } // example : state public string StateName { get; set; } // example : state
public object StateValue { get; set; } // example : ON public string StateValue { get; set; } // example : ON
public string ProviderId { get; set; } // TODO public string ProviderId { get; set; } // TODO
public string DeviceType { get; set; } // TODO public string DeviceType { get; set; } // TODO

View File

@ -11,5 +11,6 @@ namespace MyCore.Interfaces.Models.MyControlPanel
public string Model { get; set; } public string Model { get; set; }
public string Description { get; set; } public string Description { get; set; }
public DeviceType DeviceType { get; set; } public DeviceType DeviceType { get; set; }
public List<DeviceAction> DeviceActions { get; set; } // TODO <=
} }
} }

View File

@ -10,8 +10,8 @@ namespace MyCore.Interfaces.Models
{ {
public class AqaraCube : AqaraDevice public class AqaraCube : AqaraDevice
{ {
public double Angle { get; set; } public double angle { get; set; }
public int Side { get; set; } public int side { get; set; }
public string Action { get; set; } public string action { get; set; }
} }
} }

View File

@ -63,7 +63,7 @@ namespace MyCore.Service.Controllers
/// </summary> /// </summary>
/// <param name="automationId">automation id</param> /// <param name="automationId">automation id</param>
[ProducesResponseType(typeof(AutomationDetailDTO), 200)] [ProducesResponseType(typeof(AutomationDetailDTO), 200)]
[HttpGet("detail/{roomId}")] [HttpGet("detail/{automationId}")]
public ObjectResult GetDetail(string automationId) public ObjectResult GetDetail(string automationId)
{ {
try try

View File

@ -22,11 +22,16 @@ namespace MyCore.Service.Services
automation.UserId = userId; automation.UserId = userId;
automation.Name = automationCreateOrUpdateDetailDTO.Name; automation.Name = automationCreateOrUpdateDetailDTO.Name;
automation.CreatedDate = DateTime.Now; automation.CreatedDate = create ? DateTime.Now : automation.CreatedDate;
automation.UpdatedDate = DateTime.Now; automation.UpdatedDate = DateTime.Now;
automation.Triggers = automationCreateOrUpdateDetailDTO.Triggers; automation.Triggers = automationCreateOrUpdateDetailDTO.Triggers;
automation.Conditions = automationCreateOrUpdateDetailDTO.Conditions; automation.Conditions = automationCreateOrUpdateDetailDTO.Conditions;
automation.Actions = automationCreateOrUpdateDetailDTO.Actions; automation.Actions = automationCreateOrUpdateDetailDTO.Actions;
var allDeviceIds = new List<string>();
allDeviceIds.AddRange(automation.Triggers.Select(t => t.DeviceId));
allDeviceIds.AddRange(automation.Conditions.Select(t => t.DeviceId));
allDeviceIds.AddRange(automation.Actions.Select(t => t.DeviceId));
automation.DevicesIds = allDeviceIds;
if (create) if (create)
return _AutomationDatabaseService.Create(automation).ToDTO(); return _AutomationDatabaseService.Create(automation).ToDTO();

View File

@ -1,4 +1,5 @@
using Mqtt.Client.AspNetCore.Services; using Mqtt.Client.AspNetCore.Services;
using MyCore.Interfaces.DTO;
using MyCore.Interfaces.Models; using MyCore.Interfaces.Models;
using MyCore.Interfaces.Models.Providers.Zigbee.Aqara; using MyCore.Interfaces.Models.Providers.Zigbee.Aqara;
using MyCore.Services.MyControlPanel; using MyCore.Services.MyControlPanel;
@ -6,6 +7,7 @@ using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using static Mqtt.Client.AspNetCore.Services.MqttClientMerossService; using static Mqtt.Client.AspNetCore.Services.MqttClientMerossService;
@ -15,8 +17,12 @@ namespace MyCore.Services.Devices
{ {
public static bool isOpen = false; public static bool isOpen = false;
public static long lastActionTime; public static long lastActionTime;
private static dynamic deserializedReceivedMessage;
private static dynamic triggerStateValue;
private static dynamic triggerStateName;
private static dynamic triggerStateValueCheck;
// TODO it's here that action are thrown.. Call from Mqtt Or other service like controller if from RpiServices // TODO it's here that action are thrown.. Call from Mqtt Or other service like controller if from RpiServices
public async static Task HandleActionFromMQTTAsync(string topic, string message, DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, AutomationDatabaseService _AutomationDatabaseService, string userId) public static void HandleActionFromMQTTAsync(string topic, string message, DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, AutomationDatabaseService _AutomationDatabaseService, string userId)
{ {
// TODO Check if last action is not too close for each action // TODO Check if last action is not too close for each action
var actionTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(); var actionTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
@ -26,9 +32,99 @@ namespace MyCore.Services.Devices
switch (topicSplit[0]) { switch (topicSplit[0]) {
case "zigbee2mqtt": case "zigbee2mqtt":
var test0 = _ProviderDatabaseService.GetByType(topicSplit[0]).Id; var test0 = _ProviderDatabaseService.GetByType(topicSplit[0]).Id;
var anotherTest = _AutomationDatabaseService.GetByProvider(test0); var automations = _AutomationDatabaseService.GetByProvider(test0);
foreach (var automation in automations) {
// TODO filter incoming message, retrieve
var serviceName = topicSplit[1];
var zigbeeDevice = _DeviceDatabaseService.GetByName(serviceName).FirstOrDefault();
// todo check if not null and if more than one element
if (zigbeeDevice != null && automation.Triggers.Any(t => t.DeviceId == zigbeeDevice.Id)) {
var automationTrigger = automation.Triggers.Where(t => t.DeviceId == zigbeeDevice.Id).FirstOrDefault();
// Todo Deserialize by type
switch (zigbeeDevice.Model)
{
case "MFKZQ01LM":
deserializedReceivedMessage = JsonConvert.DeserializeObject<AqaraCube>(message);
break;
default:
break;
}
Type type = deserializedReceivedMessage.GetType();
PropertyInfo property = type.GetProperty(automationTrigger.StateName);
triggerStateValueCheck = property.GetValue(deserializedReceivedMessage);
triggerStateName = property.Name;
// Todo check state name and value for triggers..
if (automationTrigger.StateName == triggerStateName && automationTrigger.StateValue == triggerStateValueCheck) {
// Todo check condition
if (automation.Conditions.Count >= 0)
{
// => SEND REQUEST
foreach (var action in automation.Actions)
{
var stateName = action.StateName;
var stateValue = action.StateValue;
var zigbeeDeviceAction = _DeviceDatabaseService.GetById(action.DeviceId);
var providerAction = _ProviderDatabaseService.GetById(userId, zigbeeDeviceAction.ProviderId);
switch (providerAction.Type)
{
case "zigbee2mqtt":
Zigbee2MqttRequest zigbee2MqttRequest = new Zigbee2MqttRequest() { };
var actionRequest = "";
// Todo GET AND CHECK DEVICE ACTION POSSIBLE
// todo check state name (state, action.. )
if (zigbeeDeviceAction.Type == DeviceType.Light)
{
if (stateValue == DeviceAction.toggle.ToString())
{
// TO CHECK
switch (zigbeeDeviceAction.LastState)
{
case "ON":
actionRequest = "OFF";
zigbee2MqttRequest.brightness = 0;
break;
case "OFF":
case null:
default:
actionRequest = "ON";
zigbee2MqttRequest.brightness = 255;
break;
}
zigbeeDeviceAction.LastState = actionRequest;
zigbeeDeviceAction.LastStateDate = DateTime.Now;
}
}
Type type2 = zigbee2MqttRequest.GetType();
PropertyInfo property2 = type2.GetProperty(stateName);
property2.SetValue(zigbee2MqttRequest, actionRequest, null);
var request = JsonConvert.SerializeObject(zigbee2MqttRequest);
MqttClientService.PublishMessage("zigbee2mqtt/" + zigbeeDeviceAction.Name.Substring(0, zigbeeDeviceAction.Name.Length-1) + "/set", request);
// Save laststate
DeviceService.CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, zigbeeDeviceAction.UserId, zigbeeDeviceAction.ToDTO(), false);
break;
case "meross":
break;
}
//=> TODO SEND REQUEST
}
}
}
}
}
// switch case according to device type (topic !) // switch case according to device type (topic !)
if (topicSplit[1].Contains("MagicCube0")) if (topicSplit[1].Contains("MagicCube0"))
@ -44,16 +140,16 @@ namespace MyCore.Services.Devices
Task.Run(async () => { await YeelightService.Toggle(labLamp); }); Task.Run(async () => { await YeelightService.Toggle(labLamp); });
} }
}*/ }*/
if (test.Action == "shake") /* if (test.action == "shake")
{ {
// TODO Check state // TODO Check state
Zigbee2MqttRequest zigbee2MqttRequest = new Zigbee2MqttRequest() { state = "OFF", brightness = 0 }; Zigbee2MqttRequest zigbee2MqttRequest = new Zigbee2MqttRequest() { state = "OFF", brightness = 0 };
var request = JsonConvert.SerializeObject(zigbee2MqttRequest); var request = JsonConvert.SerializeObject(zigbee2MqttRequest);
MqttClientService.PublishMessage("zigbee2mqtt/LampeTable/set", request); MqttClientService.PublishMessage("zigbee2mqtt/GU10Bureau/set", request);
} }*/
if (test.Action == "tap") if (test.action == "tap")
{ {
var provider = providers.Where(p => p.Type == "meross").FirstOrDefault(); var provider = providers.Where(p => p.Type == "meross").FirstOrDefault();
var merossDevices = _DeviceDatabaseService.GetByProviderId(provider.Id); var merossDevices = _DeviceDatabaseService.GetByProviderId(provider.Id);
@ -76,15 +172,15 @@ namespace MyCore.Services.Devices
i++; i++;
}*/ }*/
MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 1); MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 1);
MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 2); /*MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 2);
MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 3); MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 3);*/
//MqttClientMerossService.ExecuteCommand(prise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 0); //MqttClientMerossService.ExecuteCommand(prise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.ON, 0);
} }
else else
{ {
MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 1); MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 1);
MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 2); /*MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 2);
MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 3); MqttClientMerossService.ExecuteCommand(multiprise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 3);*/
//MqttClientMerossService.ExecuteCommand(prise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 0); //MqttClientMerossService.ExecuteCommand(prise.ServiceIdentification, Method.SET, CommandMqtt.TOGGLEX, "", "", ToggleStatus.OFF, 0);
} }
} }
@ -110,10 +206,10 @@ namespace MyCore.Services.Devices
MqttClientService.PublishMessage("zigbee2mqtt/LampeWC/set", request); MqttClientService.PublishMessage("zigbee2mqtt/LampeWC/set", request);
} }
else { else {
Zigbee2MqttRequest zigbee2MqttRequest = new Zigbee2MqttRequest() { state = "OFF" }; /*Zigbee2MqttRequest zigbee2MqttRequest = new Zigbee2MqttRequest() { state = "OFF" };
var request = JsonConvert.SerializeObject(zigbee2MqttRequest); var request = JsonConvert.SerializeObject(zigbee2MqttRequest);
MqttClientService.PublishMessage("zigbee2mqtt/LampeWC/set", request); MqttClientService.PublishMessage("zigbee2mqtt/LampeWC/set", request);*/
} }
} }
if (topicSplit[1].Contains("Motion0")) if (topicSplit[1].Contains("Motion0"))
@ -128,10 +224,10 @@ namespace MyCore.Services.Devices
} }
else else
{ {
Zigbee2MqttRequest zigbee2MqttRequest = new Zigbee2MqttRequest() { state = "OFF", brightness = 0 }; /*Zigbee2MqttRequest zigbee2MqttRequest = new Zigbee2MqttRequest() { state = "OFF", brightness = 0 };
var request = JsonConvert.SerializeObject(zigbee2MqttRequest); var request = JsonConvert.SerializeObject(zigbee2MqttRequest);
MqttClientService.PublishMessage("zigbee2mqtt/GU10Bureau/set", request); MqttClientService.PublishMessage("zigbee2mqtt/GU10Bureau/set", request);*/
} }
} }
break; break;

View File

@ -79,6 +79,8 @@ namespace MyCore.Services.Devices
device.LocationId = deviceDetailDTO.LocationId; device.LocationId = deviceDetailDTO.LocationId;
device.CreatedDate = DateTime.Now; device.CreatedDate = DateTime.Now;
device.UpdatedDate = DateTime.Now; device.UpdatedDate = DateTime.Now;
device.LastState = deviceDetailDTO.LastState;
device.LastStateDate = deviceDetailDTO.LastStateDate;
device.MeansOfCommunications = deviceDetailDTO.MeansOfCommunications; device.MeansOfCommunications = deviceDetailDTO.MeansOfCommunications;
device.IpAddress = deviceDetailDTO.IpAddress; device.IpAddress = deviceDetailDTO.IpAddress;

View File

@ -144,12 +144,12 @@ namespace MyCore.Services
try try
{ {
var test = JsonConvert.DeserializeObject<AqaraCube>(payload); var test = JsonConvert.DeserializeObject<AqaraCube>(payload);
if (test.Action == "shake") if (test.action == "shake")
{ {
/*var labLamp = yeelightService.devices.Where(d => d.Hostname == "192.168.31.74").FirstOrDefault(); /*var labLamp = yeelightService.devices.Where(d => d.Hostname == "192.168.31.74").FirstOrDefault();
Task.Run(async () => { await yeelightService.Toggle(labLamp); });*/ Task.Run(async () => { await yeelightService.Toggle(labLamp); });*/
} }
if (test.Action == "slide") if (test.action == "slide")
{ {
if (lightStateIkeaBulb == LightState.Undefined || lightStateIkeaBulb == LightState.Off) if (lightStateIkeaBulb == LightState.Undefined || lightStateIkeaBulb == LightState.Off)
PublishMessage("zigbee2mqtt/0x14b457fffe7628fa/set", "{\"state\": \"ON\"}"); PublishMessage("zigbee2mqtt/0x14b457fffe7628fa/set", "{\"state\": \"ON\"}");

View File

@ -28,9 +28,9 @@ namespace MyCore.Services.MyControlPanel
return _Automations.Find<Automation>(a => a.Id == id).FirstOrDefault(); return _Automations.Find<Automation>(a => a.Id == id).FirstOrDefault();
} }
public Automation GetByProvider(string id) public List<Automation> GetByProvider(string id)
{ {
return _Automations.Find<Automation>(a => a.Triggers.Any(t => t.ProviderId == id)).FirstOrDefault(); return _Automations.Find<Automation>(a => a.Triggers.Any(t => t.ProviderId == id)).ToList();
} }
public bool IsExist(string id) public bool IsExist(string id)

View File

@ -33,6 +33,11 @@ namespace MyCore.Services.MyControlPanel
return _Devices.Find(d => d.ProviderId == providerId).ToList(); return _Devices.Find(d => d.ProviderId == providerId).ToList();
} }
public List<Device> GetByName(string name)
{
return _Devices.Find(d => d.Name == name).ToList();
}
public bool IsExist(string id) public bool IsExist(string id)
{ {
return _Devices.Find<Device>(d => d.Id == id).FirstOrDefault() != null ? true : false; return _Devices.Find<Device>(d => d.Id == id).FirstOrDefault() != null ? true : false;