using DevExpress.Data.Mask; using Microsoft.AspNetCore.Mvc; using Mqtt.Client.AspNetCore.Services; using MyCore.Interfaces.DTO; using MyCore.Interfaces.Models; using MyCore.Interfaces.Models.MyControlPanel; using MyCore.Service.Services.Devices.SupportedDevices; using MyCore.Services.MyControlPanel; using Newtonsoft.Json; using Swashbuckle.AspNetCore.Swagger; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Net.Http; using System.Security.Authentication; using System.Security.Claims; using System.Threading.Tasks; using System.Xml.Linq; 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, 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, 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, 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.Plug, IsState = true, IsLinkQuality = true }, 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, IsHumidity = true, IsTemperature = true, IsAlarm = true, IsLinkQuality = true }, 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) { Device device; if (isZigbee) { device = _DeviceDatabaseService.GetByServiceIdentification(deviceDetailDTO.ServiceIdentification); if (device == null) device = new Device(); } else { if (create) device = new Device(); else { device = _DeviceDatabaseService.GetById(deviceDetailDTO.Id); } } /*// What's the purpose here ? if (_DeviceDatabaseService.IsAlreadyHere(homeId, deviceDetailDTO.ServiceIdentification, deviceDetailDTO.Model) && create) { return null; }*/ device.HomeId = homeId; if (create) { device.Name = deviceDetailDTO.Name; } device.NameForAction = deviceDetailDTO.NameForAction; device.Description = deviceDetailDTO.Description; device.ManufacturerName = deviceDetailDTO.ManufacturerName; if (_ProviderDatabaseService.IsExist(deviceDetailDTO.ProviderId)) device.ProviderId = deviceDetailDTO.ProviderId; else throw new KeyNotFoundException("Provider does not exist"); if (device.RoomId == null || _RoomDatabaseService.IsExist(deviceDetailDTO.RoomId)) device.RoomId = deviceDetailDTO.RoomId; else throw new KeyNotFoundException("Location does not exist"); device.Port = deviceDetailDTO.Port; device.Model = deviceDetailDTO.Model; device.Type = deviceDetailDTO.Type; device.FirmwareVersion = deviceDetailDTO.FirmwareVersion; device.HardwareVersion = deviceDetailDTO.HardwareVersion; if (create) device.ConnectionStatus = ConnectionStatus.Unknown; else device.ConnectionStatus = deviceDetailDTO.ConnectionStatus; device.RoomId = deviceDetailDTO.RoomId; if (create) { device.CreatedDate = DateTime.Now; } else { device.UpdatedDate = DateTime.Now; device.LastMessage = deviceDetailDTO.LastMessage; device.LastMessageDate = deviceDetailDTO.LastMessageDate; } device.MeansOfCommunications = deviceDetailDTO.MeansOfCommunications; device.IpAddress = deviceDetailDTO.IpAddress; device.ServiceIdentification = deviceDetailDTO.ServiceIdentification; device.Battery = deviceDetailDTO.Battery; device.BatteryStatus = deviceDetailDTO.BatteryStatus; device.GroupIds = deviceDetailDTO.GroupIds; // Todo structure Properties device.Properties = deviceDetailDTO.Properties; // Todo structure SupportedOperations device.SupportedOperations = deviceDetailDTO.SupportedOperations; // If no zigbee, update data (Netatmo ..) if (!isZigbee) { device.LastStateDate = deviceDetailDTO.LastStateDate; device.LastState = deviceDetailDTO.LastState; device.IsContact = deviceDetailDTO.IsContact; device.Contact = deviceDetailDTO.Contact; device.IsIlluminance = deviceDetailDTO.IsIlluminance; device.Illuminance = deviceDetailDTO.Illuminance != null ? deviceDetailDTO.Illuminance.Value : 0; device.IsBrightness = deviceDetailDTO.IsBrightness; device.Brightness = deviceDetailDTO.Brightness; device.IsState = deviceDetailDTO.IsState; device.State = deviceDetailDTO.State; device.IsColorTemp = deviceDetailDTO.IsColorTemp; device.ColorTemp = deviceDetailDTO.ColorTemp; device.IsColorXY = deviceDetailDTO.IsColorXY; device.ColorX = deviceDetailDTO.ColorX; device.ColorY = deviceDetailDTO.ColorY; device.IsOccupation = deviceDetailDTO.IsOccupation; device.Occupation = deviceDetailDTO.Occupation; device.IsAlarm = deviceDetailDTO.IsAlarm; device.Alarm = deviceDetailDTO.Alarm; device.IsTemperature = deviceDetailDTO.IsTemperature; device.Temperature = deviceDetailDTO.Temperature != null ? deviceDetailDTO.Temperature.Value : 0; device.IsHumidity = deviceDetailDTO.IsHumidity; device.Humidity = deviceDetailDTO.Humidity != null ? deviceDetailDTO.Humidity.Value : 0; device.IsPressure = deviceDetailDTO.IsPressure; device.Pressure = deviceDetailDTO.Pressure != null ? deviceDetailDTO.Pressure.Value : 0; device.IsConsumption = deviceDetailDTO.IsConsumption; device.Consumption = deviceDetailDTO.Consumption; device.IsCurrentPower = deviceDetailDTO.IsCurrentPower; device.CurrentPower = deviceDetailDTO.CurrentPower; device.IsVoltage = deviceDetailDTO.IsVoltage; device.Voltage = deviceDetailDTO.Voltage; device.IsLinkQuality = deviceDetailDTO.IsLinkQuality; device.LinkQuality = deviceDetailDTO.LinkQuality; device.IsCO2 = deviceDetailDTO.IsCO2; device.CO2 = deviceDetailDTO.CO2; device.IsNoise = deviceDetailDTO.IsNoise; device.Noise = deviceDetailDTO.Noise; } 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 return _DeviceDatabaseService.Update(device).ToDTO(); } public async static Task>> CreateFromProvider(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, string homeId, Provider provider) { Dictionary> devices = new Dictionary>(); try { switch (provider.Type) { case ProviderType.arlo: List arloDevices = new ArloService(provider.Username, provider.Password).GetAllDevices(); devices = CreateArloDevices(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, arloDevices, provider); break; case ProviderType.meross: List merossDevices = MqttClientMerossService.GetMerossDevices(); // TO TEST IF IT WORKS devices = CreateMerossDevices(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, merossDevices, provider); break; case ProviderType.yeelight: List yeelightDevices = await YeelightService.GetDevices(); devices = CreateYeelightDevices(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, yeelightDevices, provider); break; case ProviderType.netatmo: NetatmoService netatmoService = new NetatmoService(provider.Username, provider.Password, provider.Value, provider.ValueRefresh, provider, _ProviderDatabaseService); List netatmoHomes = netatmoService.GetHomeData(); List netatmoCoachDevices = netatmoService.GetHomeCoachsData(); devices = CreateOrUpdateNetatmoDevices(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, netatmoHomes, netatmoCoachDevices, provider); break; case ProviderType.zigbee2mqtt: if (MqttClientService.devices.Count > 0) { // Simple list mode List zigbee2MqttDevices = MqttClientService.devices; devices = await CreateFromZigbeeAsync(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, zigbee2MqttDevices, provider); } if (MqttClientService.devicesNew.Count > 0) { // Complex list mode List zigbee2MqttDevices = MqttClientService.devicesNew; devices = await UpdateFromZigbeeAsync(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, zigbee2MqttDevices, provider); } break; } } catch (AuthenticationException ex) { throw new AuthenticationException("Bad username or password for service " + provider.Name + " ex: " + ex.Message); } catch (HttpRequestException ex) { throw new HttpRequestException("Error retrieving devices for " + provider.Name + " ex: " + ex.Message); } catch (Exception ex) { } return devices; } // Old way /*public static async Task>> CreateFromZigbeeAsync(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, LocationDatabaseService _LocationDatabaseService, string homeId, List zigbee2MqttDevices, Provider provider) { List createdZigbeeDevices = new List(); List notSupportedZigbeeDevices = new List(); List existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id); if (zigbee2MqttDevices.Count <= 0) { zigbee2MqttDevices = await MqttClientService.AskDevicesAsync(); } zigbee2MqttDevices = zigbee2MqttDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.ieeeAddr)).ToList(); foreach (var zigbee2MqttDevice in zigbee2MqttDevices) { DeviceDetailDTO deviceDetailDTO = new DeviceDetailDTO(); deviceDetailDTO.Name = zigbee2MqttDevice.friendly_name; deviceDetailDTO.Description = zigbee2MqttDevice.description; deviceDetailDTO.ServiceIdentification = zigbee2MqttDevice.ieeeAddr; deviceDetailDTO.ProviderId = provider.Id; deviceDetailDTO.ProviderName = provider.Name; deviceDetailDTO.Model = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.model; // Is the base to understand incoming messages ! deviceDetailDTO.FirmwareVersion = zigbee2MqttDevice.softwareBuildID; deviceDetailDTO.HardwareVersion = zigbee2MqttDevice.hardwareVersion.ToString(); deviceDetailDTO.Battery = zigbee2MqttDevice.powerSource == null ? false : zigbee2MqttDevice.powerSource.Contains("Battery"); deviceDetailDTO.ManufacturerName = zigbee2MqttDevice.vendor == null ? provider.Type : zigbee2MqttDevice.vendor.ToLower(); deviceDetailDTO.MeansOfCommunications = new List(); deviceDetailDTO.MeansOfCommunications.Add(MeansOfCommunication.Zigbee); deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.UpdatedDate = DateTime.Now; deviceDetailDTO.LastStateDate = new DateTime(zigbee2MqttDevice.lastSeen); deviceDetailDTO.Type = zigbee2MqttDevice.type == "Coordinator" ? DeviceType.Gateway : GetDeviceTypeFromZigbeeModel(zigbee2MqttDevice.model); if (deviceDetailDTO.Type != DeviceType.Unknown) { // Supoorted device ! createdZigbeeDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _LocationDatabaseService, homeId, deviceDetailDTO, true)); } else { // Not yet supported ! notSupportedZigbeeDevices.Add(deviceDetailDTO); } } return new Dictionary>() { { "createdDevices", createdZigbeeDevices }, { "notSupportedDevices", notSupportedZigbeeDevices } }; }*/ public static async Task>> CreateFromZigbeeAsync(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, string homeId, List zigbee2MqttDevices, Provider provider) { List createdZigbeeDevices = new List(); List notSupportedZigbeeDevices = new List(); List existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id); // Not necessarry if (zigbee2MqttDevices.Count <= 0) { //zigbee2MqttDevices = await MqttClientService.AskDevicesAsync(); } zigbee2MqttDevices = zigbee2MqttDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.ieeeAddr)).ToList(); foreach (var zigbee2MqttDevice in zigbee2MqttDevices) { DeviceDetailDTO deviceDetailDTO = new DeviceDetailDTO(); deviceDetailDTO.Name = zigbee2MqttDevice.friendly_name; deviceDetailDTO.NameForAction = zigbee2MqttDevice.friendly_name; deviceDetailDTO.ServiceIdentification = zigbee2MqttDevice.ieeeAddr; deviceDetailDTO.ProviderId = provider.Id; deviceDetailDTO.ProviderName = provider.Name; deviceDetailDTO.Description = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.description; deviceDetailDTO.Model = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.model; // Is the base to understand incoming messages ! //deviceDetailDTO.FirmwareVersion = zigbee2MqttDevice.software_build_id; 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 { MeansOfCommunication.Zigbee }; deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.UpdatedDate = DateTime.Now; if (zigbee2MqttDevice.type != "Coordinator") { // EXPOSES ! List supportedOperationsDTO = new List(); /*foreach (var supportedOperation in zigbee2MqttDevice.definition?.exposes) { supportedOperationsDTO.Add(JsonConvert.SerializeObject(supportedOperation)); } deviceDetailDTO.SupportedOperations = supportedOperationsDTO; deviceDetailDTO.Type = GetDeviceTypeFromZigbeeModel(zigbee2MqttDevice.definition.model);*/ } else { deviceDetailDTO.Type = DeviceType.Gateway; } if (true) //zigbee2MqttDevice.supported // TODO QUID { // Supported device ! createdZigbeeDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, deviceDetailDTO, true)); } else { // Not yet supported ! notSupportedZigbeeDevices.Add(deviceDetailDTO); } } return new Dictionary>() { { "createdDevices", createdZigbeeDevices }, { "notSupportedDevices", notSupportedZigbeeDevices } }; } public static async Task>> UpdateFromZigbeeAsync(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, string homeId, List zigbee2MqttDevices, Provider provider) { List updatedZigbeeDevices = new List(); List notSupportedZigbeeDevices = new List(); List existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id); // Not necessarry if (zigbee2MqttDevices.Count <= 0) { //zigbee2MqttDevices = await MqttClientService.AskDevicesAsync(); } //zigbee2MqttDevices = zigbee2MqttDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.ieee_address)).ToList(); foreach (var zigbee2MqttDevice in zigbee2MqttDevices) { var existingDevice = _DeviceDatabaseService.GetByServiceIdentification(zigbee2MqttDevice.ieee_address); DeviceDetailDTO deviceDetailDTO = new DeviceDetailDTO(); deviceDetailDTO.Name = zigbee2MqttDevice.friendly_name; deviceDetailDTO.ServiceIdentification = zigbee2MqttDevice.ieee_address; deviceDetailDTO.ProviderId = provider.Id; deviceDetailDTO.ProviderName = provider.Name; deviceDetailDTO.Description = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.definition?.description; deviceDetailDTO.Model = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.definition?.model; // Is the base to understand incoming messages ! deviceDetailDTO.FirmwareVersion = zigbee2MqttDevice.software_build_id; 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 { MeansOfCommunication.Zigbee }; deviceDetailDTO.GroupIds = existingDevice != null ? existingDevice.GroupIds : null; deviceDetailDTO.Properties = existingDevice != null ? existingDevice.Properties : null; deviceDetailDTO.RoomId = existingDevice != null ? existingDevice.RoomId : null; deviceDetailDTO.CreatedDate = existingDevice != null ? existingDevice.CreatedDate : DateTime.Now; deviceDetailDTO.UpdatedDate = DateTime.Now; if (zigbee2MqttDevice.type != "Coordinator") { // EXPOSES ! List supportedOperationsDTO = new List(); if(zigbee2MqttDevice.definition?.exposes != null) { foreach (var supportedOperation in zigbee2MqttDevice.definition?.exposes) { supportedOperationsDTO.Add(JsonConvert.SerializeObject(supportedOperation)); } deviceDetailDTO.SupportedOperations = supportedOperationsDTO; } deviceDetailDTO.Type = GetDeviceTypeFromZigbeeModel(zigbee2MqttDevice.definition?.model); } else { deviceDetailDTO.Type = DeviceType.Gateway; } if (zigbee2MqttDevice.supported || deviceDetailDTO.Type == DeviceType.Gateway) { // Supported device ! updatedZigbeeDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, deviceDetailDTO, false, true)); } else { // Not yet supported ! notSupportedZigbeeDevices.Add(deviceDetailDTO); } } return new Dictionary>() { { "updatedZigbeeDevices", updatedZigbeeDevices }, { "notSupportedDevices", notSupportedZigbeeDevices } }; } private static DeviceType GetDeviceTypeFromZigbeeModel(string zigbeeModel) { return supportedDevices.Any(sd => sd.Model == zigbeeModel) ? // It's supported ! supportedDevices.Where(sd => sd.Model == zigbeeModel).FirstOrDefault().DeviceType : // Not yet supported DeviceType.Unknown; } public static Dictionary> CreateArloDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, string homeId, List arloDevices, Provider provider) { List createdArloDevices = new List(); List existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id); arloDevices = arloDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.deviceId)).ToList(); foreach (var arlo in arloDevices) { DeviceDetailDTO deviceDetailDTO = new DeviceDetailDTO(); deviceDetailDTO.ManufacturerName = provider.Type.ToString(); deviceDetailDTO.Name = arlo.deviceName; deviceDetailDTO.Description = arlo.deviceName; // As description not exist, put name in description deviceDetailDTO.ServiceIdentification = arlo.deviceId; deviceDetailDTO.ProviderId = provider.Id; deviceDetailDTO.ProviderName = provider.Name; if (arlo.connectivity != null) { deviceDetailDTO.ConnectionStatus = arlo.connectivity.connected ? ConnectionStatus.Connected : ConnectionStatus.Unknown; deviceDetailDTO.Status = arlo.connectivity.connected ? true : false; // TODO STATE } else deviceDetailDTO.ConnectionStatus = ConnectionStatus.Unknown; deviceDetailDTO.Model = arlo.modelId; deviceDetailDTO.FirmwareVersion = arlo.interfaceVersion; // TODO switch (arlo.deviceType) { case "camera": deviceDetailDTO.Type = DeviceType.Camera; Dictionary properties = new Dictionary(); properties.Add("lastImageUploaded", arlo.lastImageUploaded); properties.Add("presignedLastImageUrl", arlo.presignedLastImageUrl); properties.Add("presignedFullFrameSnapshotUrl", arlo.presignedFullFrameSnapshotUrl); properties.Add("presignedSnapshotUrl", arlo.presignedSnapshotUrl); deviceDetailDTO.Properties = JsonConvert.SerializeObject(properties); break; case "siren": deviceDetailDTO.Type = DeviceType.Sound; break; case "basestation": deviceDetailDTO.Type = DeviceType.Gateway; break; } deviceDetailDTO.MeansOfCommunications = new List { MeansOfCommunication.Wifi // To check }; deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.UpdatedDate = DateTime.Now; createdArloDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, deviceDetailDTO, true)); } return new Dictionary>() { { "createdDevices", createdArloDevices } }; // TODO Check if exist not supported devices } public static Dictionary> CreateMerossDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, string homeId, List merossDevices, Provider provider) { List createdMerossDevices = new List(); List existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id); merossDevices = merossDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.uuid)).ToList(); foreach (var meross in merossDevices) { DeviceDetailDTO deviceDetailDTO = new DeviceDetailDTO(); deviceDetailDTO.ManufacturerName = provider.Type.ToString(); deviceDetailDTO.HardwareVersion = meross.hdwareVersion; deviceDetailDTO.Name = meross.devName; deviceDetailDTO.Description = meross.devName; // As description not exist, put name in description deviceDetailDTO.ServiceIdentification = meross.uuid; deviceDetailDTO.ProviderId = provider.Id; deviceDetailDTO.ProviderName = provider.Name; deviceDetailDTO.ConnectionStatus = meross.onlineStatus == 1 ? ConnectionStatus.Connected : ConnectionStatus.Disconnected; // deviceDetailDTO.Status = meross. ? true : false; // TODO STATE deviceDetailDTO.Model = meross.deviceType; switch (deviceDetailDTO.Model) // TODO { case "mss425f": deviceDetailDTO.Type = DeviceType.Multiplug; break; case "mss310": deviceDetailDTO.Type = DeviceType.Plug; break; case "msh300": deviceDetailDTO.Type = DeviceType.Gateway; break; default: deviceDetailDTO.Type = DeviceType.Actuator; break; } deviceDetailDTO.FirmwareVersion = meross.firmwareVersion; // TODO Dictionary properties = new Dictionary(); foreach (var property in meross.channels) { if (property.type != null) properties.Add(property.devName, property.type); } // deviceDetailDTO.SupportedOperations = supportedOperationsDTO; TODO 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)); } return new Dictionary>() { { "createdDevices", createdMerossDevices } }; // TODO Check if exist not supported devices } public static Dictionary> CreateYeelightDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, string homeId, List yeelightDevices, Provider provider) { List createdYeelightDevices = new List(); List existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id); yeelightDevices = yeelightDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.Id)).ToList(); foreach (var light in yeelightDevices) { DeviceDetailDTO deviceDetailDTO = new DeviceDetailDTO(); deviceDetailDTO.ManufacturerName = provider.Type.ToString(); deviceDetailDTO.Name = light.Name; deviceDetailDTO.Description = light.Name; // As description not exist, put name in description deviceDetailDTO.IpAddress = light.Hostname; deviceDetailDTO.ServiceIdentification = light.Id; deviceDetailDTO.ProviderId = provider.Id; deviceDetailDTO.ProviderName = provider.Name; deviceDetailDTO.ConnectionStatus = ConnectionStatus.Connected; deviceDetailDTO.Status = false; deviceDetailDTO.Model = light.Model.ToString(); deviceDetailDTO.Type = DeviceType.Light; // TO CHECK deviceDetailDTO.Port = light.Port; deviceDetailDTO.FirmwareVersion = light.FirmwareVersion; Dictionary properties = new Dictionary(); foreach (var property in light.Properties) { properties.Add(property.Key, property.Value); } deviceDetailDTO.Properties = JsonConvert.SerializeObject(properties); List supportedOperationsDTO = new List(); foreach (var supportedOperation in light.SupportedOperations) { supportedOperationsDTO.Add(supportedOperation.ToString()); } deviceDetailDTO.SupportedOperations = supportedOperationsDTO; deviceDetailDTO.MeansOfCommunications = new List { MeansOfCommunication.Wifi }; deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.UpdatedDate = DateTime.Now; createdYeelightDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, deviceDetailDTO, true)); } return new Dictionary>() { { "createdDevices", createdYeelightDevices } }; // TODO Check if exist not supported devices } public static Dictionary> CreateOrUpdateNetatmoDevices(DeviceDatabaseService _DeviceDatabaseService, ProviderDatabaseService _ProviderDatabaseService, RoomDatabaseService _RoomDatabaseService, string homeId, List netatmoHomes, List netatmoCoachDevices, Provider provider) { List createdNetatmoDevices = new List(); List existingDevices = _DeviceDatabaseService.GetByProviderId(provider.Id); List netatmoDevices = new List(); foreach (var netatmoHome in netatmoHomes) { netatmoDevices.AddRange(netatmoHome.modules); } //netatmoDevices = netatmoDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd.id)).ToList(); foreach (var netatmoDevice in netatmoDevices) { bool isExist = existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(netatmoDevice.id); var device = existingDevices.FirstOrDefault(ed => ed.ProviderId == provider.Id && ed.ServiceIdentification == netatmoDevice.id); DeviceDetailDTO deviceDetailDTO = isExist && device != null ? device.ToDTO() : new DeviceDetailDTO(); if (!isExist) { deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.ServiceIdentification = netatmoDevice.id; deviceDetailDTO.ProviderId = provider.Id; deviceDetailDTO.ProviderName = provider.Name; deviceDetailDTO.Name = netatmoDevice.name; deviceDetailDTO.Description = netatmoDevice.name; // As description not exist, put name in description deviceDetailDTO.Model = netatmoDevice.type; deviceDetailDTO.IpAddress = netatmoDevice.bridge; deviceDetailDTO.ManufacturerName = provider.Type.ToString(); deviceDetailDTO.Model = netatmoDevice.type; } deviceDetailDTO.ConnectionStatus = ConnectionStatus.Connected; switch (netatmoDevice.type) { case "NCO": //Détecteur de Monoxyde de Carbone Intelligent deviceDetailDTO.Type = DeviceType.Environment; deviceDetailDTO.Battery = true; break; case "NACamera": deviceDetailDTO.Type = DeviceType.Camera; break; case "NAPlug": deviceDetailDTO.Type = DeviceType.Gateway; break; case "NATherm1": deviceDetailDTO.Type = DeviceType.Thermostat; deviceDetailDTO.IsTemperature = true; break; case "NRV": deviceDetailDTO.Type = DeviceType.Valve; deviceDetailDTO.IsTemperature = true; break; } deviceDetailDTO.MeansOfCommunications = new List { MeansOfCommunication.Wifi }; deviceDetailDTO.UpdatedDate = DateTime.Now; createdNetatmoDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, deviceDetailDTO, !isExist)); } //netatmoCoachDevices = netatmoCoachDevices.Where(yd => !existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(yd._id)).ToList(); foreach (var netatmoCoachDevice in netatmoCoachDevices) { bool isExist = existingDevices.Select(ed => ed.ServiceIdentification).ToList().Contains(netatmoCoachDevice._id); var device = existingDevices.FirstOrDefault(ed => ed.ProviderId == provider.Id && ed.ServiceIdentification == netatmoCoachDevice._id); DeviceDetailDTO deviceDetailDTO = isExist && device != null ? device.ToDTO() : new DeviceDetailDTO(); if (!isExist) { deviceDetailDTO.CreatedDate = DateTime.Now; deviceDetailDTO.ServiceIdentification = netatmoCoachDevice._id; deviceDetailDTO.ProviderId = provider.Id; deviceDetailDTO.ProviderName = provider.Name; deviceDetailDTO.Name = netatmoCoachDevice.station_name; deviceDetailDTO.Description = netatmoCoachDevice.module_name; deviceDetailDTO.Model = netatmoCoachDevice.type; deviceDetailDTO.ManufacturerName = provider.Type.ToString(); } deviceDetailDTO.ConnectionStatus = netatmoCoachDevice.reachable ? ConnectionStatus.Connected : ConnectionStatus.Unknown; switch (netatmoCoachDevice.type) { case "NHC": //Home coach classique (?) deviceDetailDTO.Type = DeviceType.Environment; deviceDetailDTO.Battery = false; deviceDetailDTO.FirmwareVersion = netatmoCoachDevice.firmware.ToString(); //deviceDetailDTO.SupportedOperations = netatmoCoachDevice.data_type; deviceDetailDTO.IsTemperature = true; deviceDetailDTO.Temperature = netatmoCoachDevice.dashboard_data.Temperature; deviceDetailDTO.IsHumidity = true; deviceDetailDTO.Humidity = netatmoCoachDevice.dashboard_data.Humidity; deviceDetailDTO.IsPressure = true; deviceDetailDTO.Pressure = netatmoCoachDevice.dashboard_data.Pressure; deviceDetailDTO.IsCO2 = true; deviceDetailDTO.CO2 = netatmoCoachDevice.dashboard_data.CO2; deviceDetailDTO.IsNoise = true; deviceDetailDTO.Noise = netatmoCoachDevice.dashboard_data.Noise; //TODO healthy index ! break; } deviceDetailDTO.MeansOfCommunications = new List { MeansOfCommunication.Wifi }; deviceDetailDTO.UpdatedDate = DateTime.Now; createdNetatmoDevices.Add(CreateOrUpdate(_DeviceDatabaseService, _ProviderDatabaseService, _RoomDatabaseService, homeId, deviceDetailDTO, !isExist)); } return new Dictionary>() { { "createdDevices", createdNetatmoDevices } }; } 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; } } }