From 97fc143865ff33801bd73f238acb37ec5b0cb65a Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Fri, 4 Aug 2023 18:36:03 +0200 Subject: [PATCH] Update code for send action + update for main info + categorized devices + add multiple main info fields to device --- .../Business/NotificationLogic.cs | 4 +- MyCore.Interfaces/DTO/Common/DeviceType.cs | 10 + .../DTO/MyControlPanel/DeviceDTO.cs | 94 ++++++ .../DTO/MyControlPanel/RoomDTO.cs | 6 + .../Models/MyControlPanel/Database/Device.cs | 182 +++++++++++- .../Models/MyControlPanel/SupportedDevice.cs | 23 ++ .../Zigbee2Mqtt/Zigbee2MqttOperations.cs | 17 ++ .../Zigbee/Zigbee2Mqtt/Zigbee2MqttRequest.cs | 31 +- .../Controllers/Devices/DeviceController.cs | 4 +- MyCore/Controllers/Helpers/DevicesHelper.cs | 16 +- MyCore/Controllers/RoomController.cs | 12 +- MyCore/Extensions/MqttClientService.cs | 32 +- MyCore/Services/AlarmService.cs | 20 +- MyCore/Services/AutomationService.cs | 10 +- MyCore/Services/Devices/ActionService.cs | 33 ++- MyCore/Services/Devices/DeviceService.cs | 274 +++++++++++++++--- MyCore/Services/RoomService.cs | 51 +++- MyCore/Startup.cs | 2 +- 18 files changed, 717 insertions(+), 104 deletions(-) create mode 100644 MyCore.Interfaces/Models/Providers/Zigbee/Zigbee2Mqtt/Zigbee2MqttOperations.cs diff --git a/MyCore.Framework/Business/NotificationLogic.cs b/MyCore.Framework/Business/NotificationLogic.cs index 21715d0..1df7b8b 100644 --- a/MyCore.Framework/Business/NotificationLogic.cs +++ b/MyCore.Framework/Business/NotificationLogic.cs @@ -20,8 +20,8 @@ namespace MyCore.Framework.Business Topic = home == null ? "main" : home.Id, Notification = new Notification() { - Title = notificationDTO.notificationTitle, - Body = home == null ? notificationDTO.notificationTitle : $"{home.Name}, {notificationDTO.notificationMessage}" + Title = home == null ? notificationDTO.notificationTitle : $"{home.Name} - {notificationDTO.notificationTitle}", + Body = notificationDTO.notificationMessage }, Data = new Dictionary() { diff --git a/MyCore.Interfaces/DTO/Common/DeviceType.cs b/MyCore.Interfaces/DTO/Common/DeviceType.cs index 01eb260..2e95fa9 100644 --- a/MyCore.Interfaces/DTO/Common/DeviceType.cs +++ b/MyCore.Interfaces/DTO/Common/DeviceType.cs @@ -30,4 +30,14 @@ namespace MyCore.Interfaces.DTO on, off } + + public enum RoomMainInfo + { + Temperature = 1, + Humidity, + Pressure, + Illuminance, + Motion, + Door + } } diff --git a/MyCore.Interfaces/DTO/MyControlPanel/DeviceDTO.cs b/MyCore.Interfaces/DTO/MyControlPanel/DeviceDTO.cs index 12499ed..8745c5f 100644 --- a/MyCore.Interfaces/DTO/MyControlPanel/DeviceDTO.cs +++ b/MyCore.Interfaces/DTO/MyControlPanel/DeviceDTO.cs @@ -31,6 +31,8 @@ namespace MyCore.Interfaces.DTO public DateTime LastStateDate { get; set; } + public DateTime LastMessageDate { get; set; } + public bool Battery { get; set; } public int BatteryStatus { get; set; } @@ -50,6 +52,8 @@ namespace MyCore.Interfaces.DTO public DateTime UpdatedDate { get; set; } + public string LastMessage { get; set; } // TODO UNIFORMISATION ? + public string LastState { get; set; } // TODO UNIFORMISATION ? public string IpAddress { get; set; } @@ -63,5 +67,95 @@ namespace MyCore.Interfaces.DTO public string Properties { get; set; } // Dictionary public List SupportedOperations { get; set; } + + public bool IsContact { get; set; } + + public bool Contact { get; set; } + + public bool IsIlluminance { get; set; } + + public int? Illuminance { get; set; } + + public bool IsBrightness { get; set; } + + public int Brightness { get; set; } + + public bool IsState { get; set; } + + public bool State { get; set; } + + public bool IsColorTemp { get; set; } + + public int ColorTemp { get; set; } + + public bool IsColorXY { get; set; } + + public int ColorX { get; set; } + + public int ColorY { get; set; } + + public bool IsOccupation { get; set; } + + public bool Occupation { get; set; } + + public bool IsAlarm { get; set; } + + public bool Alarm { get; set; } + + public bool IsWaterLeak { get; set; } + + public bool WaterLeak { get; set; } + + public bool IsSmoke { get; set; } + + public bool Smoke { get; set; } + + public bool IsVibration { get; set; } + + public bool Vibration { get; set; } + + public bool IsAction { get; set; } + + public string Action { get; set; } + + public bool IsTemperature { get; set; } + + public decimal? Temperature { get; set; } + + public bool IsHumidity { get; set; } + + public decimal? Humidity { get; set; } + + public bool IsPressure { get; set; } // Example : 1005.7hPa + + public decimal? Pressure { get; set; } // Example : 1005.7hPa + + public bool IsAirQuality { get; set; } + + public string AirQuality { get; set; } + + public bool IsFanSpeed { get; set; } + + public int FanSpeed { get; set; } + + public bool IsFanMode { get; set; } + + public string FanMode { get; set; } + + public bool IsConsumption { get; set; } // Example: 256.88kWh + + public decimal Consumption { get; set; } // Example: 256.88kWh + + public bool IsCurrentPower { get; set; } // Example: 0.0384A + + public decimal CurrentPower { get; set; } // Example: 0.0384A + + public bool IsVoltage { get; set; } // Example: 230V + + public decimal Voltage { get; set; } // Example: 230V + + public bool IsLinkQuality { get; set; } // Example: 84 LQI + + public int LinkQuality { get; set; } // Example: 84 LQI } } diff --git a/MyCore.Interfaces/DTO/MyControlPanel/RoomDTO.cs b/MyCore.Interfaces/DTO/MyControlPanel/RoomDTO.cs index d7986f3..5f23be2 100644 --- a/MyCore.Interfaces/DTO/MyControlPanel/RoomDTO.cs +++ b/MyCore.Interfaces/DTO/MyControlPanel/RoomDTO.cs @@ -35,12 +35,18 @@ namespace MyCore.Interfaces.DTO public bool IsHumidity { get; set; } public string Humidity { get; set; } + public bool IsPressure { get; set; } + public string Pressure { get; set; } + public bool IsMotion { get; set; } public bool? Motion { get; set; } public bool IsDoor { get; set; } public bool? Door { get; set; } + public bool IsIlluminance { get; set; } + public string Illuminance { get; set; } + public List EnvironmentalDevices { get; set; } // for temp and humidity public List SecurityDevices { get; set; } // for motion diff --git a/MyCore.Interfaces/Models/MyControlPanel/Database/Device.cs b/MyCore.Interfaces/Models/MyControlPanel/Database/Device.cs index fa65db1..3294a4d 100644 --- a/MyCore.Interfaces/Models/MyControlPanel/Database/Device.cs +++ b/MyCore.Interfaces/Models/MyControlPanel/Database/Device.cs @@ -65,11 +65,17 @@ namespace MyCore.Interfaces.Models public DateTime UpdatedDate { get; set; } [BsonElement("LastState")] - public string LastState { get; set; } // TODO UNIFORMISATION ? + public string LastState { get; set; } [BsonElement("LastStateDate")] public DateTime LastStateDate { get; set; } + [BsonElement("LastMessage")] + public string LastMessage { get; set; } + + [BsonElement("LastMessageDate")] + public DateTime LastMessageDate { get; set; } + [BsonElement("IpAddress")] public string IpAddress { get; set; } @@ -99,6 +105,142 @@ namespace MyCore.Interfaces.Models [BsonElement("SupportedOperations")] public List SupportedOperations { get; set; } + [BsonElement("IsContact")] + public bool IsContact { get; set; } + + [BsonElement("Contact")] + public bool Contact { get; set; } + + [BsonElement("IsIlluminance")] + public bool IsIlluminance { get; set; } + + [BsonElement("Illuminance")] + public int Illuminance { get; set; } + + [BsonElement("IsBrightness")] + public bool IsBrightness { get; set; } + + [BsonElement("Brightness")] + public int Brightness { get; set; } + + [BsonElement("IsState")] + public bool IsState { get; set; } + + [BsonElement("State")] + public bool State { get; set; } + + [BsonElement("IsColorTemp")] + public bool IsColorTemp { get; set; } + + [BsonElement("ColorTemp")] + public int ColorTemp { get; set; } + + [BsonElement("IsColorXY")] + public bool IsColorXY { get; set; } + + [BsonElement("ColorX")] + public int ColorX { get; set; } + + [BsonElement("ColorY")] + public int ColorY { get; set; } + + [BsonElement("IsOccupation")] // Motion + public bool IsOccupation { get; set; } + + [BsonElement("Occupation")] + public bool Occupation { get; set; } + + [BsonElement("IsAlarm")] + public bool IsAlarm { get; set; } + + [BsonElement("Alarm")] + public bool Alarm { get; set; } + + [BsonElement("IsWaterLeak")] + public bool IsWaterLeak { get; set; } + + [BsonElement("WaterLeak")] + public bool WaterLeak { get; set; } + + [BsonElement("IsSmoke")] + public bool IsSmoke { get; set; } + + [BsonElement("Smoke")] + public bool Smoke { get; set; } + + [BsonElement("IsVibration")] + public bool IsVibration { get; set; } + + [BsonElement("Vibration")] + public bool Vibration { get; set; } + + [BsonElement("IsAction")] + public bool IsAction { get; set; } + + [BsonElement("Action")] + public string Action { get; set; } + + [BsonElement("IsTemperature")] + public bool IsTemperature { get; set; } + + [BsonElement("Temperature")] + public decimal Temperature { get; set; } + + [BsonElement("IsHumidity")] + public bool IsHumidity { get; set; } + + [BsonElement("Humidity")] + public decimal Humidity { get; set; } + + [BsonElement("IsPressure")] + public bool IsPressure { get; set; } // Example : 1005.7hPa + + [BsonElement("Pressure")] + public decimal Pressure { get; set; } // Example : 1005.7hPa + + [BsonElement("IsAirQuality")] + public bool IsAirQuality { get; set; } + + [BsonElement("AirQuality")] + public string AirQuality { get; set; } + + [BsonElement("IsFanSpeed")] + public bool IsFanSpeed { get; set; } + + [BsonElement("FanSpeed")] + public int FanSpeed { get; set; } + + [BsonElement("IsFanMode")] + public bool IsFanMode { get; set; } + + [BsonElement("FanMode")] + public string FanMode { get; set; } + + [BsonElement("IsConsumption")] + public bool IsConsumption { get; set; } // Example: 256.88kWh + + [BsonElement("Consumption")] + public decimal Consumption { get; set; } // Example: 256.88kWh + + [BsonElement("IsCurrentPower")] + public bool IsCurrentPower { get; set; } // Example: 0.0384A + + [BsonElement("CurrentPower")] + public decimal CurrentPower { get; set; } // Example: 0.0384A + + [BsonElement("IsVoltage")] + public bool IsVoltage { get; set; } // Example: 230V + + [BsonElement("Voltage")] + public decimal Voltage { get; set; } // Example: 230V + + [BsonElement("IsLinkQuality")] + public bool IsLinkQuality { get; set; } // Example: 84 LQI + + [BsonElement("LinkQuality")] + public int LinkQuality { get; set; } // Example: 84 LQI + + public DeviceSummaryDTO ToSummaryDTO() { return new DeviceSummaryDTO() @@ -108,10 +250,10 @@ namespace MyCore.Interfaces.Models Name = Name, Model = Model, Type = Type, - Status = Status, ConnectionStatus = ConnectionStatus, ProviderId = ProviderId, RoomId = RoomId, // Include room id + LastMessageDate = LastMessageDate, LastStateDate = LastStateDate, Battery = Battery, BatteryStatus = BatteryStatus @@ -127,7 +269,6 @@ namespace MyCore.Interfaces.Models Name = Name, Model = Model, Type = Type, - Status = Status, Port = Port, FirmwareVersion = FirmwareVersion, ConnectionStatus = ConnectionStatus, @@ -137,6 +278,8 @@ namespace MyCore.Interfaces.Models UpdatedDate = UpdatedDate, LastState = LastState, LastStateDate = LastStateDate, + LastMessage = LastMessage, + LastMessageDate = LastMessageDate, IpAddress = IpAddress, ServiceIdentification = ServiceIdentification, ProviderId = ProviderId, @@ -144,7 +287,38 @@ namespace MyCore.Interfaces.Models Properties = Properties, SupportedOperations = SupportedOperations, Battery = Battery, - BatteryStatus = BatteryStatus + BatteryStatus = BatteryStatus, + IsContact = IsContact, + Contact = Contact, + IsIlluminance = IsIlluminance, + Illuminance = Illuminance, + IsBrightness = IsBrightness, + Brightness = Brightness, + IsState = IsState, + State = State, + IsColorTemp = IsColorTemp, + ColorTemp = ColorTemp, + IsColorXY = IsColorXY, + ColorX = ColorX, + ColorY = ColorY, + IsOccupation = IsOccupation, + Occupation = Occupation, + IsAlarm = IsAlarm, + Alarm = Alarm, + IsTemperature = IsTemperature, + Temperature = Temperature, + IsHumidity = IsHumidity, + Humidity = Humidity, + IsPressure = IsPressure, + Pressure = Pressure, + IsConsumption = IsConsumption, + Consumption = Consumption, + IsCurrentPower = IsCurrentPower, + CurrentPower = CurrentPower, + IsVoltage = IsVoltage, + Voltage = Voltage, + IsLinkQuality = IsLinkQuality, + LinkQuality = LinkQuality, }; } } diff --git a/MyCore.Interfaces/Models/MyControlPanel/SupportedDevice.cs b/MyCore.Interfaces/Models/MyControlPanel/SupportedDevice.cs index dbad617..0bb76c6 100644 --- a/MyCore.Interfaces/Models/MyControlPanel/SupportedDevice.cs +++ b/MyCore.Interfaces/Models/MyControlPanel/SupportedDevice.cs @@ -12,5 +12,28 @@ namespace MyCore.Interfaces.Models.MyControlPanel public string Description { get; set; } public DeviceType DeviceType { get; set; } public List DeviceActions { get; set; } // TODO <= + + public bool IsContact { get; set; } + public bool IsIlluminance { get; set; } + public bool IsBrightness { get; set; } + public bool IsState { get; set; } + public bool IsColorTemp { get; set; } + public bool IsColorXY { get; set; } + public bool IsOccupation { get; set; } + public bool IsAction { get; set; } + public bool IsAirQuality { get; set; } + public bool IsFanSpeed { get; set; } + public bool IsFanMode { get; set; } + public bool IsAlarm { get; set; } + public bool IsSmoke { get; set; } + public bool IsWaterLeak { get; set; } + public bool IsVibration { get; set; } + public bool IsTemperature { get; set; } + public bool IsHumidity { get; set; } + public bool IsPressure { get; set; } // Example : 1005.7hPa + public bool IsConsumption { get; set; } // Example: 256.88kWh + public bool IsCurrentPower { get; set; } // Example: 0.0384A + public bool IsVoltage { get; set; } // Example: 230V + public bool IsLinkQuality { get; set; } // Example: 84 LQI } } diff --git a/MyCore.Interfaces/Models/Providers/Zigbee/Zigbee2Mqtt/Zigbee2MqttOperations.cs b/MyCore.Interfaces/Models/Providers/Zigbee/Zigbee2Mqtt/Zigbee2MqttOperations.cs new file mode 100644 index 0000000..15e0946 --- /dev/null +++ b/MyCore.Interfaces/Models/Providers/Zigbee/Zigbee2Mqtt/Zigbee2MqttOperations.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MyCore.Interfaces.Models +{ + public class Zigbee2MqttOperations + { + public string access { get; set; } + public string description { get; set; } + public string name { get; set; } + public string property { get; set; } + public string type { get; set; } + public string unit { get; set; } + public List values { get; set; } + } +} diff --git a/MyCore.Interfaces/Models/Providers/Zigbee/Zigbee2Mqtt/Zigbee2MqttRequest.cs b/MyCore.Interfaces/Models/Providers/Zigbee/Zigbee2Mqtt/Zigbee2MqttRequest.cs index e639fb2..4101c51 100644 --- a/MyCore.Interfaces/Models/Providers/Zigbee/Zigbee2Mqtt/Zigbee2MqttRequest.cs +++ b/MyCore.Interfaces/Models/Providers/Zigbee/Zigbee2Mqtt/Zigbee2MqttRequest.cs @@ -7,8 +7,33 @@ namespace MyCore.Interfaces.Models public class Zigbee2MqttRequest { public string state { get; set; } - public int brightness { get; set; } // 0 -> 255 GU10 - - // TODO + public int? brightness { get; set; } // 0 -> 255 GU10 + public int? linkquality { get; set; } + public int? battery { get; set; } + public int? illuminance { get; set; } + public int? illuminance_lux { get; set; } + public bool? occupancy { get; set; } + public decimal? temperature { get; set; } + public decimal? humidity { get; set; } + public bool? humidity_alarm { get; set; } + public bool? alarm { get; set; } + public int? voltage { get; set; } + public bool? contact { get; set; } + public decimal? consumption { get; set; } + public decimal? current { get; set; } + public int? melody { get; set; } + public string power_type { get; set; } + public string volume { get; set; } + public bool? vibration { get; set; } + public bool? water_leak { get; set; } + public int? strength { get; set; } + public int? angle { get; set; } + public int? angle_x { get; set; } + public int? angle_x_absolute { get; set; } + public int? angle_y { get; set; } + public int? angle_y_absolute { get; set; } + public int? angle_z { get; set; } + public int? side { get; set; } + public string action { get; set; } } } diff --git a/MyCore/Controllers/Devices/DeviceController.cs b/MyCore/Controllers/Devices/DeviceController.cs index df92054..c780b5d 100644 --- a/MyCore/Controllers/Devices/DeviceController.cs +++ b/MyCore/Controllers/Devices/DeviceController.cs @@ -197,7 +197,7 @@ namespace MyCore.Controllers if (action == null) throw new ArgumentNullException("Incorrect parameters"); - if (action.DeviceId == null || action.GroupId == null) + if (action.DeviceId == null && action.GroupId == null) throw new ArgumentNullException("Incorrect parameters"); Device device = null; @@ -214,7 +214,7 @@ namespace MyCore.Controllers homeId= group?.HomeId; } - if (device == null || group == null) + if (device == null && group == null) throw new KeyNotFoundException("Device or group does not exist"); AutomationService.HandleAction(homeId, action, _ProviderDatabaseService, _DeviceDatabaseService, _GroupDatabaseService); diff --git a/MyCore/Controllers/Helpers/DevicesHelper.cs b/MyCore/Controllers/Helpers/DevicesHelper.cs index 6cbd5c9..5777b03 100644 --- a/MyCore/Controllers/Helpers/DevicesHelper.cs +++ b/MyCore/Controllers/Helpers/DevicesHelper.cs @@ -17,10 +17,12 @@ namespace MyCore.Service.Controllers.Helpers public static List GetDeviceExposes(Device device) { List exposes = new List(); - // Get Exposes for the zigbee device - foreach (var supportedOperation in device.SupportedOperations) - { - exposes.Add(JsonConvert.DeserializeObject(supportedOperation)); + if (device.SupportedOperations != null) { + // Get Exposes for the zigbee device + foreach (var supportedOperation in device.SupportedOperations) + { + exposes.Add(JsonConvert.DeserializeObject(supportedOperation)); + } } return exposes; } @@ -131,6 +133,8 @@ namespace MyCore.Service.Controllers.Helpers // Update Last state actionDeviceToTest.LastState = JsonConvert.SerializeObject(states); actionDeviceToTest.LastStateDate = DateTime.Now; + actionDeviceToTest.LastMessage = JsonConvert.SerializeObject(states); + actionDeviceToTest.LastMessageDate = DateTime.Now; deviceDatabaseService.Update(actionDeviceToTest); } else @@ -218,8 +222,8 @@ namespace MyCore.Service.Controllers.Helpers } // Update Last state - actionDeviceToTest.LastState = JsonConvert.SerializeObject(statuses); - actionDeviceToTest.LastStateDate = DateTime.Now; + actionDeviceToTest.LastMessage = JsonConvert.SerializeObject(statuses); + actionDeviceToTest.LastMessageDate = DateTime.Now; _DeviceDatabaseService.Update(actionDeviceToTest); } else diff --git a/MyCore/Controllers/RoomController.cs b/MyCore/Controllers/RoomController.cs index 5af141e..79e61d6 100644 --- a/MyCore/Controllers/RoomController.cs +++ b/MyCore/Controllers/RoomController.cs @@ -78,13 +78,17 @@ namespace MyCore.Service.Controllers foreach (var room in rooms) { RoomMainDetailDTO roomMainDetailDTO = room.ToMainDetailsDTO(_DeviceDatabaseService.GetByRoom(room.Id).Select(d => d.ToDTO()).ToList()); - roomMainDetailDTO.Temperature = (string) RoomService.GetValueFromJson(roomMainDetailDTO.EnvironmentalDevices, DeviceType.Environment, "temperature", false); // Todo take the one selected by user as default if more than one + roomMainDetailDTO.Temperature = (string) RoomService.GetValueFromDeviceType(roomMainDetailDTO.EnvironmentalDevices, RoomMainInfo.Temperature); // Todo take the one selected by user as default if more than one roomMainDetailDTO.IsTemperature = roomMainDetailDTO.Temperature != null; - roomMainDetailDTO.Humidity = (string) RoomService.GetValueFromJson(roomMainDetailDTO.EnvironmentalDevices, DeviceType.Environment, "humidity", false); // Todo take the one selected by user as default if more than one + roomMainDetailDTO.Humidity = (string) RoomService.GetValueFromDeviceType(roomMainDetailDTO.EnvironmentalDevices, RoomMainInfo.Humidity); // Todo take the one selected by user as default if more than one roomMainDetailDTO.IsHumidity = roomMainDetailDTO.Humidity != null; - roomMainDetailDTO.Motion = (bool?) RoomService.GetValueFromJson(roomMainDetailDTO.SecurityDevices, DeviceType.Motion, "motion", true); + roomMainDetailDTO.Pressure = (string)RoomService.GetValueFromDeviceType(roomMainDetailDTO.EnvironmentalDevices, RoomMainInfo.Pressure); // Todo take the one selected by user as default if more than one + roomMainDetailDTO.IsPressure = roomMainDetailDTO.Pressure != null; + roomMainDetailDTO.Illuminance = (string)RoomService.GetValueFromDeviceType(roomMainDetailDTO.EnvironmentalDevices, RoomMainInfo.Illuminance); // Todo take the one selected by user as default if more than one + roomMainDetailDTO.IsIlluminance = roomMainDetailDTO.Illuminance != null; + roomMainDetailDTO.Motion = (bool?) RoomService.GetValueFromDeviceType(roomMainDetailDTO.SecurityDevices, RoomMainInfo.Motion); roomMainDetailDTO.IsMotion = roomMainDetailDTO.SecurityDevices.Any(sd => sd.Type == DeviceType.Motion) ? roomMainDetailDTO.Motion != null : false; - roomMainDetailDTO.Door = (bool?) RoomService.GetValueFromJson(roomMainDetailDTO.SecurityDevices, DeviceType.Door, "contact", true); // Todo handle more than just by string + roomMainDetailDTO.Door = (bool?) RoomService.GetValueFromDeviceType(roomMainDetailDTO.SecurityDevices, RoomMainInfo.Door); roomMainDetailDTO.IsDoor = roomMainDetailDTO.SecurityDevices.Any(sd => sd.Type == DeviceType.Door) ? roomMainDetailDTO.Door != null : false; roomMainDetailDTOs.Add(roomMainDetailDTO); } diff --git a/MyCore/Extensions/MqttClientService.cs b/MyCore/Extensions/MqttClientService.cs index 01dba27..052f687 100644 --- a/MyCore/Extensions/MqttClientService.cs +++ b/MyCore/Extensions/MqttClientService.cs @@ -3,6 +3,7 @@ using MQTTnet.Client; using MQTTnet.Client.Connecting; using MQTTnet.Client.Disconnecting; using MQTTnet.Client.Options; +using MyCore.Framework.Business; using MyCore.Interfaces.DTO; using MyCore.Interfaces.Models; using MyCore.Interfaces.Models.Providers.Zigbee.Zigbee2Mqtt; @@ -27,7 +28,7 @@ namespace Mqtt.Client.AspNetCore.Services public static List devices = new List(); public static List devicesNew = new List(); public static List groups = new List(); - public static string homeId; + public static Home _home; private DeviceDatabaseService _deviceDatabaseService; private GroupDatabaseService _groupDatabaseService; private ProviderDatabaseService _providerDatabaseService; @@ -37,11 +38,12 @@ namespace Mqtt.Client.AspNetCore.Services private HomeDatabaseService _homeDatabaseService; private AlarmDatabaseService _alarmDatabaseService; private EventDatabaseService _eventDatabaseService; + private readonly FirebaseClient _firebaseClient; public static string lastTopic; public static long lastTimeTopic; - public MqttClientService(IMqttClientOptions options, HomeDatabaseService homeDatabaseService, DeviceDatabaseService deviceDatabaseService, GroupDatabaseService groupDatabaseService, ProviderDatabaseService providerDatabaseService, RoomDatabaseService roomDatabaseService, ActionService actionService, AutomationDatabaseService automationDatabaseService, AlarmDatabaseService alarmDatabaseService, EventDatabaseService eventDatabaseService) + public MqttClientService(IMqttClientOptions options, HomeDatabaseService homeDatabaseService, DeviceDatabaseService deviceDatabaseService, GroupDatabaseService groupDatabaseService, ProviderDatabaseService providerDatabaseService, RoomDatabaseService roomDatabaseService, ActionService actionService, AutomationDatabaseService automationDatabaseService, AlarmDatabaseService alarmDatabaseService, EventDatabaseService eventDatabaseService, FirebaseClient firebaseClient) { this._homeDatabaseService = homeDatabaseService; this._deviceDatabaseService = deviceDatabaseService; @@ -52,12 +54,14 @@ namespace Mqtt.Client.AspNetCore.Services this._alarmDatabaseService = alarmDatabaseService; this._eventDatabaseService = eventDatabaseService; this._actionService = actionService; + this._firebaseClient = firebaseClient; + Home home = this._homeDatabaseService.GetAll().ToList().Where(h => h.IsDefault).FirstOrDefault(); if (home != null) - homeId = home.Id; + _home = home; - System.Console.WriteLine($"Home Id in MQTT client service : {homeId}"); + System.Console.WriteLine($"Home Id in MQTT client service : {_home?.Id}"); var server = "localhost"; var clientId = "ApiService"; @@ -117,9 +121,9 @@ namespace Mqtt.Client.AspNetCore.Services // Less than one second between two messages from a same device if (!(lastTopic == topic && test <= 500) || configMessage) { - if (_actionService != null && homeId != null) + if (_actionService != null && _home.Id != null) { - ActionService.HandleActionFromMQTTAsync(topic, payload, _deviceDatabaseService, _groupDatabaseService, _providerDatabaseService, _roomDatabaseService, _automationDatabaseService, _alarmDatabaseService, _eventDatabaseService, homeId); + ActionService.HandleActionFromMQTTAsync(topic, payload, _deviceDatabaseService, _groupDatabaseService, _providerDatabaseService, _roomDatabaseService, _automationDatabaseService, _alarmDatabaseService, _eventDatabaseService, _home); } } else @@ -128,7 +132,7 @@ namespace Mqtt.Client.AspNetCore.Services System.Console.WriteLine($"Drop message - spam from {topic}"); } - UpdateZigbee2MqttConfigOrStateAsync(topic, payload, homeId, _deviceDatabaseService, _groupDatabaseService, _providerDatabaseService, _roomDatabaseService); + UpdateZigbee2MqttConfigOrStateAsync(topic, payload, _home?.Id, _deviceDatabaseService, _groupDatabaseService, _providerDatabaseService, _roomDatabaseService); switch (topic) { @@ -172,7 +176,7 @@ namespace Mqtt.Client.AspNetCore.Services lastTopic = topic; } - return new Task(null); + return Task.CompletedTask; } public async Task HandleConnectedAsync(MqttClientConnectedEventArgs eventArgs) @@ -328,12 +332,16 @@ namespace Mqtt.Client.AspNetCore.Services state.Value = "on"; status.Add(state); - var buildRequest = new Dictionary(); - buildRequest.Add(state.Name, state.Value); + var buildRequest = new Dictionary + { + { state.Name, state.Value } + }; // Update device state ! - zigbeeDevice.LastState = JsonConvert.SerializeObject(buildRequest); - zigbeeDevice.LastStateDate = DateTime.Now; + zigbeeDevice.LastMessage = JsonConvert.SerializeObject(buildRequest); + zigbeeDevice.LastMessageDate = DateTime.Now; + zigbeeDevice.IsState = true; + zigbeeDevice.State = true; _DeviceDatabaseService.Update(zigbeeDevice); // Check if all group has the same state // Not needed as we test the first device of a group diff --git a/MyCore/Services/AlarmService.cs b/MyCore/Services/AlarmService.cs index a3b2082..a322833 100644 --- a/MyCore/Services/AlarmService.cs +++ b/MyCore/Services/AlarmService.cs @@ -1,4 +1,5 @@ using Mqtt.Client.AspNetCore.Services; +using MyCore.Framework.Business; using MyCore.Interfaces.DTO; using MyCore.Interfaces.Models; using MyCore.Service.Controllers.Helpers; @@ -140,7 +141,7 @@ namespace MyCore.Service.Services #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) + internal static async Task HandleMessageAsync(AlarmMode alarmMode, Device deviceTrigger, string message, DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, GroupDatabaseService _GroupDatabaseService, EventDatabaseService _EventDatabaseService, Home home) { bool isAction = false; switch (alarmMode.Type) @@ -173,7 +174,6 @@ namespace MyCore.Service.Services validTrigger = false; } - if (validTrigger && alarmTrigger.StateValue.ToLower() == triggerStateValueCheck.ToString().ToLower()) { // Correct trigger ! @@ -192,7 +192,7 @@ namespace MyCore.Service.Services { case ActionType.DEVICE: var deviceAction = _DeviceDatabaseService.GetById(action.DeviceId); - var providerActionTest = _ProviderDatabaseService.GetById(homeId, action.ProviderId); + var providerActionTest = _ProviderDatabaseService.GetById(home.Id, action.ProviderId); DeviceNameForAction = deviceAction.Name; actionDeviceToTest = deviceAction; @@ -225,7 +225,7 @@ namespace MyCore.Service.Services break; } - var providerAction = _ProviderDatabaseService.GetById(homeId, action.ProviderId); + var providerAction = _ProviderDatabaseService.GetById(home.Id, action.ProviderId); // Check if device exist if (actionDeviceToTest != null && providerAction != null) @@ -330,12 +330,18 @@ namespace MyCore.Service.Services 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); + EventDetailDTO eventDetailDTO = new EventDetailDTO() { Type = EventType.AlarmTriggered, HomeId = home.Id, 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, home.Id, eventDetailDTO, true); // Send notification if exist if (alarmMode.Notification) - System.Console.WriteLine($"TODO send notification"); + { + System.Console.WriteLine($"Send notification"); + NotificationDTO notificationDTO = new NotificationDTO(); + notificationDTO.notificationTitle = "Alarme déclenchée"; + notificationDTO.notificationMessage = $"Le capteur {deviceTrigger.Name} a fait déclencher l'alarme à {DateTime.Now.ToShortTimeString()}"; + await NotificationLogic.PushFCMNotification(notificationDTO, home); + } } #endregion } diff --git a/MyCore/Services/AutomationService.cs b/MyCore/Services/AutomationService.cs index c826951..4faf078 100644 --- a/MyCore/Services/AutomationService.cs +++ b/MyCore/Services/AutomationService.cs @@ -8,8 +8,6 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using static Mqtt.Client.AspNetCore.Services.MqttClientMerossService; namespace MyCore.Service.Services { @@ -55,7 +53,7 @@ namespace MyCore.Service.Services return _AutomationDatabaseService.Update(automation.Id, automation).ToDTO(); } - public static void HandleAutomation(List automations, Device deviceTrigger, string message, DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, GroupDatabaseService _GroupDatabaseService, EventDatabaseService _EventDatabaseService, string homeId) + public static void HandleAutomation(List automations, Device deviceTrigger, string message, DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, GroupDatabaseService _GroupDatabaseService, EventDatabaseService _EventDatabaseService, Home home) { foreach (var automation in automations) { @@ -100,12 +98,12 @@ namespace MyCore.Service.Services System.Console.WriteLine("Conditions respected !"); // Create an event - EventDetailDTO eventDetailDTO = new EventDetailDTO() { Type = EventType.AutomationTriggered, HomeId = homeId, 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, homeId, eventDetailDTO, true); + 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(homeId, action, _ProviderDatabaseService, _DeviceDatabaseService, _GroupDatabaseService) ; + HandleAction(home.Id, action, _ProviderDatabaseService, _DeviceDatabaseService, _GroupDatabaseService) ; } } else diff --git a/MyCore/Services/Devices/ActionService.cs b/MyCore/Services/Devices/ActionService.cs index 810547b..f500ce3 100644 --- a/MyCore/Services/Devices/ActionService.cs +++ b/MyCore/Services/Devices/ActionService.cs @@ -1,18 +1,13 @@ -using Mqtt.Client.AspNetCore.Services; -using MyCore.Interfaces.DTO; +using MyCore.Interfaces.DTO; using MyCore.Interfaces.Models; -using MyCore.Interfaces.Models.Providers.Zigbee.Zigbee2Mqtt; using MyCore.Service; -using MyCore.Service.Controllers.Helpers; using MyCore.Service.Services; -using MyCore.Services.MyControlPanel; using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; -using System.Reflection; using System.Threading.Tasks; -using static Mqtt.Client.AspNetCore.Services.MqttClientMerossService; namespace MyCore.Services.Devices { @@ -22,7 +17,7 @@ namespace MyCore.Services.Devices private static Device deviceTrigger; private static string providerFromTopic; private static string deviceServiceName; - public static async Task HandleActionFromMQTTAsync(string topic, string message, DeviceDatabaseService _DeviceDatabaseService, GroupDatabaseService _GroupDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, AutomationDatabaseService _AutomationDatabaseService, AlarmDatabaseService _AlarmDatabaseService, EventDatabaseService _EventDatabaseService, string homeId) + public static async Task HandleActionFromMQTTAsync(string topic, string message, DeviceDatabaseService _DeviceDatabaseService, GroupDatabaseService _GroupDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, AutomationDatabaseService _AutomationDatabaseService, AlarmDatabaseService _AlarmDatabaseService, EventDatabaseService _EventDatabaseService, Home home) { System.Console.WriteLine($"Received message {message}"); @@ -57,27 +52,37 @@ namespace MyCore.Services.Devices { #region Automations var automations = _AutomationDatabaseService.GetActiveByProvider(currentProvider.Id); - AutomationService.HandleAutomation(automations, deviceTrigger, message, _DeviceDatabaseService, _ProviderDatabaseService, _GroupDatabaseService, _EventDatabaseService, homeId); + AutomationService.HandleAutomation(automations, deviceTrigger, message, _DeviceDatabaseService, _ProviderDatabaseService, _GroupDatabaseService, _EventDatabaseService, home); #endregion #region Alarm - AlarmMode alarmMode = _AlarmDatabaseService.GetCurrentActivatedAlarm(homeId); + AlarmMode alarmMode = _AlarmDatabaseService.GetCurrentActivatedAlarm(home.Id); if (alarmMode != null) if (alarmMode.DevicesIds.Contains(deviceTrigger.Id)) - AlarmService.HandleMessage(alarmMode, deviceTrigger, message, _DeviceDatabaseService, _ProviderDatabaseService, _GroupDatabaseService, _EventDatabaseService, homeId); + AlarmService.HandleMessageAsync(alarmMode, deviceTrigger, message, _DeviceDatabaseService, _ProviderDatabaseService, _GroupDatabaseService, _EventDatabaseService, home); #endregion + // We'll try to get last info and update our objects + if (topicSplit.Length == 2) + { + // try the parsing ! + var zigbeeParsedMessage = JsonConvert.DeserializeObject(message); + deviceTrigger = DeviceService.UpdateDeviceFromZigbeeEvent(deviceTrigger, zigbeeParsedMessage); + } + // Update last state of devices + deviceTrigger.LastMessageDate = DateTime.Now; + deviceTrigger.LastMessage = message; deviceTrigger.LastStateDate = DateTime.Now; deviceTrigger.LastState = message; _DeviceDatabaseService.Update(deviceTrigger); - EventDetailDTO eventDetailDTO = new EventDetailDTO() { Type = EventType.DeviceState, HomeId = homeId, RoomId = deviceTrigger.RoomId, DeviceState = new DeviceState() { DeviceId = deviceTrigger.Id, DeviceName = deviceTrigger.Name, DeviceType = deviceTrigger.Type, Message = message } }; - EventService.CreateOrUpdate(_EventDatabaseService, homeId, eventDetailDTO, true); + EventDetailDTO eventDetailDTO = new EventDetailDTO() { Type = EventType.DeviceState, HomeId = home.Id, RoomId = deviceTrigger.RoomId, DeviceState = new DeviceState() { DeviceId = deviceTrigger.Id, DeviceName = deviceTrigger.Name, DeviceType = deviceTrigger.Type, Message = message } }; + EventService.CreateOrUpdate(_EventDatabaseService, home.Id, eventDetailDTO, true); } else { - // do nothing is a set + } } catch (Exception ex) diff --git a/MyCore/Services/Devices/DeviceService.cs b/MyCore/Services/Devices/DeviceService.cs index ed69713..0071589 100644 --- a/MyCore/Services/Devices/DeviceService.cs +++ b/MyCore/Services/Devices/DeviceService.cs @@ -7,6 +7,7 @@ using MyCore.Services.MyControlPanel; using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Net.Http; using System.Security.Authentication; @@ -17,31 +18,38 @@ namespace MyCore.Services.Devices public class DeviceService { static List supportedDevices = new List() { - new SupportedDevice { Manufacturer = "Aqara", Model = "RTCGQ11LM", Description = "Aqara human body movement and illuminance sensor", DeviceType = DeviceType.Motion }, - new SupportedDevice { Manufacturer = "Aqara", Model = "DJT11LM", Description = "Aqara vibration sensor", DeviceType = DeviceType.Environment }, - new SupportedDevice { Manufacturer = "Aqara", Model = "SJCGQ11LM", Description = "Aqara water leak sensor", DeviceType = DeviceType.Environment }, - new SupportedDevice { Manufacturer = "Aqara", Model = "WSDCGQ11LM", Description = "Aqara temperature, humidity and pressure sensor", DeviceType = DeviceType.Environment }, + new SupportedDevice { Manufacturer = "Aqara", Model = "RTCGQ11LM", Description = "Aqara human body movement and illuminance sensor", DeviceType = DeviceType.Motion, IsIlluminance = true, IsOccupation = true, IsLinkQuality = true}, + new SupportedDevice { Manufacturer = "Aqara", Model = "DJT11LM", Description = "Aqara vibration sensor", DeviceType = DeviceType.Environment, IsVibration = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Aqara", Model = "SJCGQ11LM", Description = "Aqara water leak sensor", DeviceType = DeviceType.Environment, IsWaterLeak = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Aqara", Model = "WSDCGQ11LM", Description = "Aqara temperature, humidity and pressure sensor", DeviceType = DeviceType.Environment, IsTemperature = true, IsHumidity = true, IsPressure = true, IsLinkQuality = true }, - new SupportedDevice { Manufacturer = "Xiaomi", Model = "WXKG01LM", Description = "MiJia wireless switch", DeviceType = DeviceType.Switch }, - new SupportedDevice { Manufacturer = "Xiaomi", Model = "MFKZQ01LM", Description = "Mi/Aqara smart home cube", DeviceType = DeviceType.Switch }, - new SupportedDevice { Manufacturer = "Xiaomi", Model = "MCCGQ01LM", Description = "MiJia door & window contact sensor", DeviceType = DeviceType.Door }, - new SupportedDevice { Manufacturer = "Xiaomi", Model = "JTYJ-GD-01LM/BW", Description = "MiJia Honeywell smoke detector", DeviceType = DeviceType.Environment }, - new SupportedDevice { Manufacturer = "Xiaomi", Model = "ZNCZ04LM", Description = "Mi power plug ZigBee EU", DeviceType = DeviceType.Plug }, + new SupportedDevice { Manufacturer = "Xiaomi", Model = "WXKG01LM", Description = "MiJia wireless switch", DeviceType = DeviceType.Switch, IsAction = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Xiaomi", Model = "MFKZQ01LM", Description = "Mi/Aqara smart home cube", DeviceType = DeviceType.Switch, IsAction = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Xiaomi", Model = "MCCGQ01LM", Description = "MiJia door & window contact sensor", DeviceType = DeviceType.Door, IsContact = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Xiaomi", Model = "JTYJ-GD-01LM/BW", Description = "MiJia Honeywell smoke detector", DeviceType = DeviceType.Environment, IsSmoke = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Xiaomi", Model = "ZNCZ04LM", Description = "Mi power plug ZigBee EU", DeviceType = DeviceType.Plug, IsCurrentPower = true, IsConsumption = true, IsTemperature = true, IsVoltage = true, IsLinkQuality = true }, - new SupportedDevice { Manufacturer = "Ikea", Model = "E1744", Description = "SYMFONISK Sound Controller", DeviceType = DeviceType.Switch }, - new SupportedDevice { Manufacturer = "Ikea", Model = "LED1836G9", Description = "TRADFRI LED bulb E26/E27 806 lumen, dimmable, warm white", DeviceType = DeviceType.Light }, - new SupportedDevice { Manufacturer = "Ikea", Model = "LED1842G3", Description = "TRADFRI LED bulb E27 WW clear 250 lumen, dimmable", DeviceType = DeviceType.Light }, - new SupportedDevice { Manufacturer = "Ikea", Model = "LED1837R5", Description = "TRADFRI LED bulb GU10 400 lumen, dimmable", DeviceType = DeviceType.Light }, - new SupportedDevice { Manufacturer = "Ikea", Model = "E1743", Description = "TRADFRI ON/OFF switch", DeviceType = DeviceType.Switch }, - new SupportedDevice { Manufacturer = "Ikea", Model = "E1524/E1810", Description = "TRADFRI remote control", DeviceType = DeviceType.Switch }, + new SupportedDevice { Manufacturer = "Ikea", Model = "E1744", Description = "SYMFONISK Sound Controller", DeviceType = DeviceType.Switch, IsAction = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "LED1836G9", Description = "TRADFRI LED bulb E26/E27 806 lumen, dimmable, warm white", DeviceType = DeviceType.Light, IsState = true, IsBrightness = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "LED1842G3", Description = "TRADFRI LED bulb E27 WW clear 250 lumen, dimmable", DeviceType = DeviceType.Light, IsState = true, IsBrightness = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "LED1837R5", Description = "TRADFRI LED bulb GU10 400 lumen, dimmable", DeviceType = DeviceType.Light, IsState = true, IsBrightness = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "E1743", Description = "TRADFRI ON/OFF switch", DeviceType = DeviceType.Switch, IsAction = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "E1524/E1810", Description = "TRADFRI remote control", DeviceType = DeviceType.Switch, IsAction = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "LED1924G9", Description = "TRADFRI bulb E26/E27 CWS 800/806 lumen, dimmable, color, opal white", DeviceType = DeviceType.Light, IsState = true, IsBrightness = true, IsColorTemp = true, IsColorXY = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "E2007", Description = "STARKVIND air purifier", DeviceType = DeviceType.Environment, IsAirQuality = true, IsFanMode = true, IsFanSpeed = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "ICPSHC24-10EU-IL-1", Description = "TRADFRI driver for wireless control (10 watt)", DeviceType = DeviceType.Light, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "ICPSHC24-30EU-IL-1", Description = "TRADFRI driver for wireless control (30 watt)", DeviceType = DeviceType.Light, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "E1812", Description = "TRADFRI shortcut button", DeviceType = DeviceType.Switch, IsAction = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "Ikea", Model = "E1603/E1702/E1708", Description = "TRADFRI control outlet", DeviceType = DeviceType.Switch, IsState = true, IsLinkQuality = true }, // TODO update to plug - new SupportedDevice { Manufacturer = "SONOFF", Model = "BASICZBR3", Description = "Zigbee smart switch", DeviceType = DeviceType.Switch }, + new SupportedDevice { Manufacturer = "SONOFF", Model = "BASICZBR3", Description = "Zigbee smart switch", DeviceType = DeviceType.Plug, IsState = true, IsLinkQuality = true }, - new SupportedDevice { Manufacturer = "Philips", Model = "8718696743133", Description = "Hue tap", DeviceType = DeviceType.Switch }, + new SupportedDevice { Manufacturer = "Philips", Model = "8718696743133", Description = "Hue tap", DeviceType = DeviceType.Switch, IsAction = true, IsLinkQuality = true }, - new SupportedDevice { Manufacturer = "Neo", Model = "NAS-AB02B0", Description = "Temperature & humidity sensor and alarm", DeviceType = DeviceType.Sound }, + new SupportedDevice { Manufacturer = "Neo", Model = "NAS-AB02B0", Description = "Temperature & humidity sensor and alarm", DeviceType = DeviceType.Sound, IsHumidity = true, IsTemperature = true, IsAlarm = true, IsLinkQuality = true }, - new SupportedDevice { Manufacturer = "TuYa", Model = "TS0201", Description = "Temperature & humidity sensor with display", DeviceType = DeviceType.Environment }, + new SupportedDevice { Manufacturer = "TuYa", Model = "TS0201", Description = "Temperature & humidity sensor with display", DeviceType = DeviceType.Environment, IsHumidity = true, IsTemperature = true, IsLinkQuality = true }, + new SupportedDevice { Manufacturer = "TuYa", Model = "LCZ030", Description = "Temperature & humidity & illuminance sensor with display", DeviceType = DeviceType.Environment, IsHumidity = true, IsTemperature = true, IsIlluminance = true, IsLinkQuality = true }, }; public static DeviceDetailDTO CreateOrUpdate(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, string homeId, DeviceDetailDTO deviceDetailDTO, bool create, bool isZigbee = false) @@ -70,7 +78,9 @@ namespace MyCore.Services.Devices }*/ device.HomeId = homeId; - device.Name = deviceDetailDTO.Name; + if (create) { + device.Name = deviceDetailDTO.Name; + } device.Description = deviceDetailDTO.Description; device.ManufacturerName = deviceDetailDTO.ManufacturerName; @@ -89,7 +99,6 @@ namespace MyCore.Services.Devices device.Type = deviceDetailDTO.Type; device.FirmwareVersion = deviceDetailDTO.FirmwareVersion; device.HardwareVersion = deviceDetailDTO.HardwareVersion; - device.Status = deviceDetailDTO.Status; if (create) device.ConnectionStatus = ConnectionStatus.Unknown; else @@ -101,9 +110,8 @@ namespace MyCore.Services.Devices } else { device.UpdatedDate = DateTime.Now; - device.LastState = deviceDetailDTO.LastState; - device.LastStateDate = deviceDetailDTO.LastStateDate; - device.Status = deviceDetailDTO.Status; + device.LastMessage = deviceDetailDTO.LastMessage; + device.LastMessageDate = deviceDetailDTO.LastMessageDate; } device.MeansOfCommunications = deviceDetailDTO.MeansOfCommunications; @@ -117,6 +125,15 @@ namespace MyCore.Services.Devices // Todo structure SupportedOperations device.SupportedOperations = deviceDetailDTO.SupportedOperations; + if (deviceDetailDTO.SupportedOperations != null) + { + foreach (var supportedOperation in deviceDetailDTO.SupportedOperations) + { + var supportedOperationDeserialized = JsonConvert.DeserializeObject(supportedOperation); + device = UpdateDeviceCapabilities(device, supportedOperationDeserialized); + } + } + if (create) return _DeviceDatabaseService.Create(device).ToDTO(); else @@ -256,8 +273,10 @@ namespace MyCore.Services.Devices deviceDetailDTO.Battery = zigbee2MqttDevice.powerSource == null ? false : zigbee2MqttDevice.powerSource.Contains("Battery"); deviceDetailDTO.ManufacturerName = zigbee2MqttDevice.vendor == null ? provider.Type.ToString() : zigbee2MqttDevice.vendor.ToLower(); - deviceDetailDTO.MeansOfCommunications = new List(); - deviceDetailDTO.MeansOfCommunications.Add(MeansOfCommunication.Zigbee); + deviceDetailDTO.MeansOfCommunications = new List + { + MeansOfCommunication.Zigbee + }; deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.UpdatedDate = DateTime.Now; @@ -328,8 +347,10 @@ namespace MyCore.Services.Devices deviceDetailDTO.Battery = zigbee2MqttDevice.power_source == null ? false : zigbee2MqttDevice.power_source.Contains("Battery"); deviceDetailDTO.ManufacturerName = zigbee2MqttDevice.definition?.vendor == null ? provider.Type.ToString() : zigbee2MqttDevice.definition?.vendor.ToLower(); - deviceDetailDTO.MeansOfCommunications = new List(); - deviceDetailDTO.MeansOfCommunications.Add(MeansOfCommunication.Zigbee); + deviceDetailDTO.MeansOfCommunications = new List + { + MeansOfCommunication.Zigbee + }; deviceDetailDTO.GroupIds = existingDevice != null ? existingDevice.GroupIds : null; deviceDetailDTO.Properties = existingDevice != null ? existingDevice.Properties : null; @@ -430,9 +451,11 @@ namespace MyCore.Services.Devices deviceDetailDTO.Type = DeviceType.Gateway; break; } - - deviceDetailDTO.MeansOfCommunications = new List(); - deviceDetailDTO.MeansOfCommunications.Add(MeansOfCommunication.Wifi); // To check + + deviceDetailDTO.MeansOfCommunications = new List + { + MeansOfCommunication.Wifi // To check + }; deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.UpdatedDate = DateTime.Now; @@ -487,8 +510,10 @@ namespace MyCore.Services.Devices } // deviceDetailDTO.SupportedOperations = supportedOperationsDTO; TODO - deviceDetailDTO.MeansOfCommunications = new List(); - deviceDetailDTO.MeansOfCommunications.Add(MeansOfCommunication.Wifi); // TO CHECK + deviceDetailDTO.MeansOfCommunications = new List + { + MeansOfCommunication.Wifi // TO CHECK + }; deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.UpdatedDate = DateTime.Now; createdMerossDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, deviceDetailDTO, true)); @@ -533,8 +558,10 @@ namespace MyCore.Services.Devices supportedOperationsDTO.Add(supportedOperation.ToString()); } deviceDetailDTO.SupportedOperations = supportedOperationsDTO; - deviceDetailDTO.MeansOfCommunications = new List(); - deviceDetailDTO.MeansOfCommunications.Add(MeansOfCommunication.Wifi); + deviceDetailDTO.MeansOfCommunications = new List + { + MeansOfCommunication.Wifi + }; deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.UpdatedDate = DateTime.Now; createdYeelightDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, deviceDetailDTO, true)); @@ -542,5 +569,182 @@ namespace MyCore.Services.Devices return new Dictionary>() { { "createdDevices", createdYeelightDevices } }; // TODO Check if exist not supported devices } + + public static Device UpdateDeviceFromZigbeeEvent(Device device, Zigbee2MqttRequest zigbee2MqttRequest) + { + if (zigbee2MqttRequest.state != null) + { + try + { + switch (zigbee2MqttRequest.state.ToLower()) { + case "on": + device.State = true; + break; + case "off": + default: + device.State = false; + break; + } + } + catch (Exception e) + { + Debug.Print($"State parsing issue : {zigbee2MqttRequest.state} - {e.Message}"); + device.State = false; + } + } + + if (zigbee2MqttRequest.brightness != null) + { + device.Brightness = zigbee2MqttRequest.brightness.Value; + } + + if (zigbee2MqttRequest.linkquality != null) + { + device.LinkQuality = zigbee2MqttRequest.linkquality.Value; + } + + if (zigbee2MqttRequest.battery != null) + { + device.BatteryStatus = zigbee2MqttRequest.battery.Value; + } + + if (zigbee2MqttRequest.illuminance_lux != null) + { + device.Illuminance = zigbee2MqttRequest.illuminance_lux.Value; + } + + if (zigbee2MqttRequest.occupancy != null) + { + device.Occupation = zigbee2MqttRequest.occupancy.Value; + } + + if (zigbee2MqttRequest.temperature != null) + { + device.Temperature = zigbee2MqttRequest.temperature.Value; + } + + if (zigbee2MqttRequest.humidity != null) + { + device.Humidity = zigbee2MqttRequest.humidity.Value; + } + + if (zigbee2MqttRequest.alarm != null) + { + device.Alarm = zigbee2MqttRequest.alarm.Value; + } + + if (zigbee2MqttRequest.voltage != null) + { + device.Voltage = zigbee2MqttRequest.voltage.Value; + } + + if (zigbee2MqttRequest.contact != null) + { + device.Contact = zigbee2MqttRequest.contact.Value; + } + + if (zigbee2MqttRequest.consumption != null) + { + device.Consumption = zigbee2MqttRequest.consumption.Value; + } + + if (zigbee2MqttRequest.current != null) + { + device.CurrentPower = zigbee2MqttRequest.current.Value; + } + + if (zigbee2MqttRequest.vibration != null) + { + device.Vibration = zigbee2MqttRequest.vibration.Value; + } + + if (zigbee2MqttRequest.water_leak != null) + { + device.WaterLeak = zigbee2MqttRequest.water_leak.Value; + } + + /*if (zigbee2MqttRequest.angle != null) + { + device.Angle = zigbee2MqttRequest.angle.Value; + }*/ + + if (zigbee2MqttRequest.action != null) + { + device.Action = zigbee2MqttRequest.action; + } + + return device; + } + + public static Device UpdateDeviceCapabilities(Device device, Zigbee2MqttOperations zigbee2MqttOperations) + { + if (zigbee2MqttOperations.property != null) + { + switch (zigbee2MqttOperations.property.ToLower()) + { + case "power_on_behavior": + device.IsState = true; + break; + case "linkquality": + device.IsLinkQuality = true; + break; + case "air_quality": + device.IsAirQuality = true; + break; + case "temperature": + device.IsTemperature = true; + break; + case "humidity": + device.IsHumidity = true; + break; + case "battery": + device.Battery = true; + break; + case "pressure": + device.IsPressure = true; + break; + case "illuminance_lux": + device.IsIlluminance = true; + break; + case "effect": + device.IsBrightness = true; + break; + case "voltage": + device.IsVoltage = true; + break; + case "contact": + device.IsContact = true; + break; + case "smoke": + device.IsSmoke = true; + break; + case "action": + device.IsAction = true; + break; + case "vibration": + device.IsVibration = true; + break; + case "water_leak": + device.IsWaterLeak = true; + break; + case "state": + device.IsState = true; + break; + case "power": + device.IsCurrentPower = true; + break; + case "energy": + device.IsConsumption = true; + break; + case "occupancy": + device.IsOccupation = true; + break; + case "illuminance": + device.IsIlluminance = true; + break; + } + } + return device; + } } } diff --git a/MyCore/Services/RoomService.cs b/MyCore/Services/RoomService.cs index 93b3441..d8f3d0e 100644 --- a/MyCore/Services/RoomService.cs +++ b/MyCore/Services/RoomService.cs @@ -56,12 +56,50 @@ namespace MyCore.Service return room.ToDTO(devices.Select(d => d.ToDTO()).ToList()); } - public static dynamic GetValueFromJson(List devicesDetail, DeviceType deviceType, string field, bool ifAny) + public static dynamic GetValueFromDeviceType(List devicesDetail, RoomMainInfo roomMainInfo) { - var isAny = false; foreach (var device in devicesDetail) { - if (device.LastState != null) + switch (roomMainInfo) + { + case RoomMainInfo.Temperature: + if (device.IsTemperature && device.Temperature != null && device.Temperature != 0) + { + return device.Temperature.ToString(); + } + break; + case RoomMainInfo.Humidity: + if (device.IsHumidity && device.Humidity != null && device.Humidity != 0) + { + return device.Humidity.ToString(); + } + break; + case RoomMainInfo.Door: + if (device.IsContact) + { + return device.Contact; + } + break; + case RoomMainInfo.Motion: + if (device.IsOccupation) + { + return device.Occupation; + } + break; + case RoomMainInfo.Illuminance: + if (device.IsIlluminance && device.Illuminance != null && device.Illuminance != 0) + { + return device.Illuminance.ToString(); + } + break; + case RoomMainInfo.Pressure: + if (device.IsPressure && device.Pressure != null && device.Pressure != 0) + { + return device.Pressure.ToString(); + } + break; + } + /*if (device.LastState != null) { var lastState = JsonConvert.DeserializeObject(device.LastState); if (lastState[field] != null && deviceType == device.Type) @@ -75,12 +113,9 @@ namespace MyCore.Service return lastState[field]; } } - } + }*/ } - if (ifAny) - return isAny; - else - return null; + return null; } } } diff --git a/MyCore/Startup.cs b/MyCore/Startup.cs index 7aaa4dc..95adc75 100644 --- a/MyCore/Startup.cs +++ b/MyCore/Startup.cs @@ -170,7 +170,7 @@ namespace MyCore services.AddMqttClientHostedService(); // Todo client files (a lot are useless) - services.AddScoped(c => { + services.AddSingleton(c => { var projectId = Configuration["GCP:project_id"]; var gcpCreds = File.ReadAllText("googleConfig.json"); var firebaseCreds = File.ReadAllText("googleConfig.json");