MC Clean code + action on yeelight (from zigbee)

This commit is contained in:
Thomas Fransolet 2021-03-24 17:40:41 +01:00
parent a4f3748649
commit c694f4a9aa
2 changed files with 337 additions and 212 deletions

View File

@ -89,44 +89,7 @@ namespace MyCore.Services.Devices
// Correct trigger !
System.Console.WriteLine($"Correct trigger for automation {automation.Name}");
var isConditionsRespected = automation.Conditions.Count <= 0 ? new List<bool>() { true } : new List<bool>(new bool[automation.Conditions.Count]);
var i = 0;
foreach (var condition in automation.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++;
}
var isConditionsRespected = CheckConditions(automation.Conditions);
if (!isConditionsRespected.Any(cr => !cr))
{
@ -176,18 +139,90 @@ namespace MyCore.Services.Devices
switch (providerAction.Type)
{
case "zigbee2mqtt":
var request = "";
var buildRequest = new Dictionary<string, object>();
try
{
ActionOnZigbee2Mqtt(actionDeviceToTest, action, DeviceNameForAction);
} catch (Exception ex) {
System.Console.WriteLine($"ActionOnZigbee2Mqtt result in error: {ex}");
}
break;
case "meross":
try
{
ActionOnMeross(_DeviceDatabaseService, actionDeviceToTest, action, DeviceNameForAction);
}
catch (Exception ex)
{
System.Console.WriteLine($"ActionOnMeross result in error: {ex}");
}
break;
case "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");
}
}
}
}
}
// Update last state of devices
deviceTrigger.LastStateDate = DateTime.Now;
deviceTrigger.LastState = message;
_DeviceDatabaseService.Update(deviceTrigger);
}
else
{
// do nothing is a set
}
}
catch (Exception ex)
{
System.Console.WriteLine($"Exeption from automation logic - {ex}");
}
}
else
{
System.Console.WriteLine($"Current device Trigger not found - {deviceTrigger}");
}
}
else {
System.Console.WriteLine($"Current provider not found - {providerFromTopic}");
}
}
System.Console.WriteLine($"zigbee2mqtt type !");
var actionDeviceExpose = GetDeviceExposes(actionDeviceToTest);
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($"yellight type !");
// Get device last state
var dic = new Dictionary<string, object>();
var dic = new List<State>();
if (actionDeviceToTest.LastState != null)
{
dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(actionDeviceToTest.LastState);
dic = JsonConvert.DeserializeObject<List<State>>(actionDeviceToTest.LastState);
}
try
@ -196,82 +231,69 @@ namespace MyCore.Services.Devices
switch (actionDeviceToTest.Type)
{
case DeviceType.Light:
case DeviceType.Switch:
var actionDeviceExposeForFeatures = actionDeviceExpose.Where(e => e.type == ((DeviceType)actionDeviceToTest.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))
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())
/*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;
}
}
// TODO clean this
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}");
}
// Update Last state
actionDeviceToTest.LastState = JsonConvert.SerializeObject(states);
actionDeviceToTest.LastStateDate = DateTime.Now;
deviceDatabaseService.Update(actionDeviceToTest);
}
else
{
// Add to request
buildRequest.Add(state.Name, state.Value);
throw new Exception($"Action device light in yeelight does not have correct expose");
}
}
else
{
throw new Exception($"Action device light|switch does not have expose of type {state.Name}");
}
}
}
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 !");
}
}
else
{
System.Console.WriteLine($"Yeelight - Lamp offline! - {actionDeviceToTest.Name}");
}
}
break;
case "meross":
try
private static void ActionOnMeross(DeviceDatabaseService _DeviceDatabaseService, Device actionDeviceToTest, Interfaces.Models.Action action, string deviceNameForAction)
{
var merossDevice = _DeviceDatabaseService.GetById(actionDeviceToTest.Id);
@ -344,67 +366,147 @@ namespace MyCore.Services.Devices
{
throw new Exception("Meross: Request action invalid");
}
// TODO UPDATE STATE
}
}
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))
{
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}");
}
}
// TODO clean this
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($"Meross error: {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}");
}
}
}
else
throw new Exception("Action device does not have expose of type light|switch");
break;
case "yeelight":
if (YeelightService.devices.Count <= 0)
default:
foreach (var state in action.States)
{
await YeelightService.GetDevices();
}
var labLamp = YeelightService.devices.Where(d => d.Hostname == actionDeviceToTest.IpAddress).FirstOrDefault();
if (labLamp != null)
System.Console.WriteLine($"Check Action ! {state.Name} {state.Value}");
if (!actionDeviceExpose.Any(ade => ade.name == state.Name))
{
// Check action type..
Task.Run(async () => { await YeelightService.Toggle(labLamp); });
throw new Exception($"Action device does not have expose of type {state.Name}");
}
}
break;
}
}
else
{
System.Console.WriteLine($"Device or group found in action incorrect");
}
}
}
else
{
System.Console.WriteLine($"One or more condition aren't respected");
}
}
}
}
}
// Update last state of devices
deviceTrigger.LastStateDate = DateTime.Now;
deviceTrigger.LastState = message;
_DeviceDatabaseService.Update(deviceTrigger);
}
else
{
// do nothing is a set
}
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($"Exeption from automation logic - {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
{
System.Console.WriteLine($"Current device Trigger not found - {deviceTrigger}");
// start and stop times are in different days
if (now >= start || now <= end)
{
isConditionsRespected[i] = true;
}
}
else {
System.Console.WriteLine($"Current provider not found - {providerFromTopic}");
break;
}
i++;
}
return isConditionsRespected;
}
private static List<Expose> GetDeviceExposes(Device device)

View File

@ -21,5 +21,28 @@ namespace MyCore.Services
await device.Connect();
return await device.Toggle();
}
public static async Task<bool> TurnOff(Device device)
{
await device.Connect();
return await device.TurnOff();
}
public static async Task<bool> TurnOn(Device device, int? brightness)
{
await device.Connect();
if (brightness != null)
{
if (brightness >= 0 && brightness <= 255)
{
await device.TurnOn();
return await device.SetBrightness((int)brightness);
}
else return await device.TurnOn();
}
else {
return await device.TurnOn();
}
}
}
}