mirror of
https://bitbucket.org/myhomie/mycorerepository.git
synced 2025-12-06 01:31:19 +00:00
MC Clean code + action on yeelight (from zigbee)
This commit is contained in:
parent
a4f3748649
commit
c694f4a9aa
@ -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,195 +139,32 @@ namespace MyCore.Services.Devices
|
||||
switch (providerAction.Type)
|
||||
{
|
||||
case "zigbee2mqtt":
|
||||
var request = "";
|
||||
var buildRequest = new Dictionary<string, object>();
|
||||
|
||||
System.Console.WriteLine($"zigbee2mqtt type !");
|
||||
|
||||
var actionDeviceExpose = GetDeviceExposes(actionDeviceToTest);
|
||||
|
||||
// Get device last state
|
||||
var dic = new Dictionary<string, object>();
|
||||
if (actionDeviceToTest.LastState != null)
|
||||
{
|
||||
dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(actionDeviceToTest.LastState);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
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))
|
||||
{
|
||||
if (dic.Count > 0)
|
||||
{
|
||||
if (dic["state"].ToString().ToLower() == state.Value.ToLower())
|
||||
{
|
||||
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($"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;
|
||||
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);
|
||||
|
||||
ActionOnZigbee2Mqtt(actionDeviceToTest, action, DeviceNameForAction);
|
||||
} catch (Exception ex) {
|
||||
System.Console.WriteLine($"ActionOnZigbee2Mqtt result in error: {ex}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Not a valid action !");
|
||||
}
|
||||
|
||||
break;
|
||||
case "meross":
|
||||
try
|
||||
{
|
||||
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");
|
||||
}
|
||||
// TODO UPDATE STATE
|
||||
}
|
||||
ActionOnMeross(_DeviceDatabaseService, actionDeviceToTest, action, DeviceNameForAction);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Meross error: {ex}");
|
||||
System.Console.WriteLine($"ActionOnMeross result in error: {ex}");
|
||||
}
|
||||
break;
|
||||
case "yeelight":
|
||||
|
||||
if (YeelightService.devices.Count <= 0)
|
||||
try
|
||||
{
|
||||
await YeelightService.GetDevices();
|
||||
ActionOnYeelight(_DeviceDatabaseService, actionDeviceToTest, action);
|
||||
}
|
||||
var labLamp = YeelightService.devices.Where(d => d.Hostname == actionDeviceToTest.IpAddress).FirstOrDefault();
|
||||
if (labLamp != null)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Check action type..
|
||||
Task.Run(async () => { await YeelightService.Toggle(labLamp); });
|
||||
System.Console.WriteLine($"ActionOnYeelight result in error: {ex}");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -407,6 +207,308 @@ namespace MyCore.Services.Devices
|
||||
}
|
||||
}
|
||||
|
||||
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 List<State>();
|
||||
if (actionDeviceToTest.LastState != null)
|
||||
{
|
||||
dic = JsonConvert.DeserializeObject<List<State>>(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))
|
||||
{
|
||||
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($"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;
|
||||
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>();
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user