public ZigbeeDevice NewDevice(string friendlyName, string zigbeeId, string modelId) { ZigbeeDevice device = null; Bridge Update(Bridge state) { device = state.Devices.FirstOrDefault(d => d.FriendlyName.Equals(friendlyName)); if (device == null) { device = new ZigbeeDevice.Builder { FriendlyName = friendlyName, IsAvailable = true, ZigbeeId = zigbeeId, ModelId = modelId }; state = state.WithDevices(devices => devices.Add(device)); } return(state); } ImmutableInterlocked.Update(ref _currentState, Update); return(device); }
public void SetDeviceAvailability(string friendlyName, bool isOnline) { Bridge Update(Bridge state) { var device = state.Devices.FirstOrDefault(d => d.FriendlyName.Equals(friendlyName)); if (device == null) { device = new ZigbeeDevice.Builder { FriendlyName = friendlyName, IsAvailable = isOnline }; state = state.WithDevices(devices => devices.Add(device)); } if (device.IsAvailable == isOnline) { return(state); } ZigbeeDevice newDevice = device.WithIsAvailable(isOnline); state = state.WithDevices(devices => devices.Replace(device, newDevice)); return(state); } UpdateState(Update); }
public ZigbeeDevice UpdateDevice(string friendlyName, string jsonPayload, out bool forceLastSeen) { ZigbeeDevice device = null; var json = JObject.Parse(jsonPayload); var linkQuality = json["linkquality"]?.Value <ushort>(); var battery = json["battery"]?.Value <decimal>(); forceLastSeen = !ParseDateTimeOffset(json["last_seen"], out var lastSeen); Bridge Update(Bridge state) { device = state.Devices.FirstOrDefault(d => d.FriendlyName.Equals(friendlyName)); if (device == null) { device = new ZigbeeDevice.Builder { FriendlyName = friendlyName, LastSeen = lastSeen }; state = state.WithDevices(devices => devices.Add(device)); } if (lastSeen.HasValue || battery.HasValue) { ZigbeeDevice.Builder builder = device; if (lastSeen.HasValue) { builder.LastSeen = lastSeen; } if (battery.HasValue) { builder.BatteryLevel = battery; } ZigbeeDevice newDevice = builder; if (newDevice != device) { state = state.WithDevices(devices => devices.Replace(device, newDevice)); device = newDevice; } } return(state); } UpdateState(Update); return(device); }
public void UpdateDevices(string payload) { var json = JArray.Parse(payload); Bridge Update(Bridge state) { foreach (var deviceJson in json) { var friendlyName = deviceJson["friendly_name"]?.Value <string>(); var zigbeeId = deviceJson["ieeeAddr"]?.Value <string>(); if (string.IsNullOrWhiteSpace(friendlyName)) { if (deviceJson["type"]?.Value <string>().Equals("Coordinator", StringComparison.InvariantCultureIgnoreCase) ?? false) { state = state.WithCoordinatorZigbeeId(zigbeeId); } continue; } var device = state.Devices.FirstOrDefault(d => d.FriendlyName.Equals(friendlyName) || (d.ZigbeeId?.Equals(zigbeeId) ?? false)); ZigbeeDevice newDevice = (device ?? new ZigbeeDevice.Builder { FriendlyName = friendlyName }) .WithZigbeeId(zigbeeId) .WithType(deviceJson["type"]?.Value <string>()) .WithModel(deviceJson["modelId"]?.Value <string>().Trim().Trim((char)0)) .WithModelId(deviceJson["model"]?.Value <string>().Trim().Trim((char)0)) .WithNetworkAddress(deviceJson["nwkAddr"]?.Value <uint>()) .WithHardwareVersion(deviceJson["hwVersion"]?.Value <long>()) .WithManufacturer(deviceJson["manufName"]?.Value <string>().Trim().Trim((char)0)); if (device != newDevice) { state = device == null ? state.WithDevices(devices => devices.Add(newDevice)) : state.WithDevices(devices => devices.Replace(device, newDevice)); } } return(state); } ImmutableInterlocked.Update(ref _currentState, Update); }
public ZigbeeDevice UpdateDevice(string friendlyName, string jsonPayload) { ZigbeeDevice device = null; var json = JObject.Parse(jsonPayload); var linkQuality = json["linkquality"]?.Value <ushort>(); var lastSeen = json["last_seen"]?.Value <DateTime>(); Bridge Update(Bridge state) { device = state.Devices.FirstOrDefault(d => d.FriendlyName.Equals(friendlyName)); if (device == null) { device = new ZigbeeDevice.Builder { FriendlyName = friendlyName, LastSeen = lastSeen }; state = state.WithDevices(devices => devices.Add(device)); } if (lastSeen.HasValue) { var newDevice = device.WithLastSeen(lastSeen); if (newDevice != device) { state = state.WithDevices(devices => devices.Replace(device, newDevice)); device = newDevice; } } return(state); } ImmutableInterlocked.Update(ref _currentState, Update); return(device); }
public void UpdateRenamedDevice(string from, string to) { Bridge Update(Bridge state) { var device = state.Devices.FirstOrDefault(d => d.FriendlyName.Equals(from)); if (device == null) { return(state); } ZigbeeDevice newDevice = device.WithFriendlyName(to); if (newDevice != device) { state = state.WithDevices(devices => devices.Replace(device, newDevice)); } return(state); } UpdateState(Update); }
public IReadOnlyCollection <IReadOnlyCollection <ZigbeeDevice> > GetRoutesToCoordinator(ZigbeeDevice forDevice) { var state = _currentState; var processedDevices = new List <ZigbeeDevice>(state.Devices.Length - 1); IEnumerable <IReadOnlyCollection <ZigbeeDevice> > GetRoutes(ZigbeeDevice d) { if (processedDevices.Contains(d)) { yield break; // already processed routed through this device } } return(GetRoutes(forDevice).ToImmutableArray()); }
public HomeAssistantEntity SetDeviceEntity( string zigbeeId, string entityClass, string component, string configPayload, Func <string, string> friendlyNameFromTopicDelegate) { HomeAssistantEntity entity = null; var json = JObject.Parse(configPayload); var entityName = json["name"]?.Value <string>(); var entityId = json["unique_id"]?.Value <string>(); var deviceName = json["device"]["name"]?.Value <string>(); var deviceIds = json["device"]["identifiers"]?.FirstOrDefault()?.Value <string>(); Bridge Update(Bridge state) { var device = state.Devices.FirstOrDefault(d => d.ZigbeeId != null && d.ZigbeeId.Equals(zigbeeId)); if (device == null) { // no device with this zigbeeId is known, try to find device from payload var topic = json["state_topic"].Value <string>() ?? json["json_attributes_topic"].Value <string>() ?? json["availability_topic"].Value <string>(); if (topic == null) { _logger.LogWarning($"Unable to find a source topic for entity {zigbeeId}-{entityClass}-{component}."); return(state); // there's nothing we can do here } var friendlyName = friendlyNameFromTopicDelegate(topic); if (friendlyName == null) { _logger.LogWarning($"Unable to find friendly name from topic {topic} in entity {zigbeeId}-{entityClass}-{component}."); return(state); // there's nothing we can do here } device = state.Devices.FirstOrDefault(d => d.FriendlyName.Equals(friendlyName)); if (device == null) { device = new ZigbeeDevice.Builder { FriendlyName = friendlyName, UniqueId = zigbeeId, ZigbeeId = zigbeeId }; state = state.WithDevices(devices => devices.Add(device)); } } if (device.ZigbeeId != zigbeeId) { ZigbeeDevice newDevice = device.WithUniqueId(zigbeeId); if (newDevice != device) { state = state.WithDevices(devices => devices.Replace(device, newDevice)); device = newDevice; } } entity = device.Entities.FirstOrDefault(e => e.Component.Equals(component)); if (entity == null) { entity = new HomeAssistantEntity.Builder { EntityId = entityId, Component = component, Name = entityName, DeviceClass = entityClass }; ZigbeeDevice newDevice = device.WithEntities(entities => entities.Add(entity)); if (newDevice != device) { state = state.WithDevices(devices => devices.Replace(device, newDevice)); device = newDevice; } } if (deviceName != null || deviceIds != null) { ZigbeeDevice newDevice = device .WithName(deviceName) .WithUniqueId(deviceIds); if (newDevice != device) { state = state.WithDevices(devices => devices.Replace(device, newDevice)); device = newDevice; } } return(state); } ImmutableInterlocked.Update(ref _currentState, Update); return(entity); }
public void UpdateDevices(string payload) { var json = JToken.Parse(payload); if (json.Type == JTokenType.Object && json["type"]?.Value <string>() == "devices") { json = json["message"]; } if (json.Type != JTokenType.Array) { _logger.LogWarning($"Invalid/unknown devices payload received. root element type is {json.Root.Type}: {payload.Substring(0, Math.Min(40, payload.Length))}... -- will be ignored."); return; } Bridge Update(Bridge state) { foreach (var deviceJson in json) { var friendlyName = deviceJson["friendly_name"]?.Value <string>(); var zigbeeId = deviceJson["ieeeAddr"]?.Value <string>(); var deviceType = deviceJson["type"]?.Value <string>(); if (string.IsNullOrWhiteSpace(friendlyName)) { if (deviceType?.Equals("Coordinator", StringComparison.InvariantCultureIgnoreCase) ?? false) { state = state.WithCoordinatorZigbeeId(zigbeeId); friendlyName = "Coordinator"; } else { _logger.LogWarning($"Unable to understand device with json {deviceJson} -- will be ignored."); continue; // unable to qualify this device } } var device = state.Devices.FirstOrDefault(d => d.FriendlyName.Equals(friendlyName) || (d.ZigbeeId?.Equals(zigbeeId) ?? false)); var networkAddress = (deviceJson["nwkAddr"] ?? deviceJson["networkAddress"])?.Value <uint>(); var model = (deviceJson["modelId"] ?? deviceJson["modelID"])?.Value <string>().Trim().Trim((char)0); var modelId = deviceJson["model"]?.Value <string>().Trim().Trim((char)0); var manufacturer = (deviceJson["manufName"] ?? deviceJson["manufacturerName"])?.Value <string>().Trim().Trim((char)0); var hardwareVersion = (deviceJson["hwVersion"] ?? deviceJson["hardwareVersion"])?.Value <long>(); ZigbeeDevice newDevice = (device ?? new ZigbeeDevice.Builder { FriendlyName = friendlyName }) .WithZigbeeId(zigbeeId) .WithType(deviceType) .WithNetworkAddress(networkAddress) .WithModel(model) .WithModelId(modelId) .WithManufacturer(manufacturer) .WithHardwareVersion(hardwareVersion); if (ParseDateTimeOffset(deviceJson["lastSeen"], out var lastSeen)) { newDevice = newDevice.WithLastSeen(lastSeen); } if (device != newDevice) { state = device == null ? state.WithDevices(devices => devices.Add(newDevice)) : state.WithDevices(devices => devices.Replace(device, newDevice)); } } return(state); } UpdateState(Update); }
public ZigbeeDevice UpdateDevice(string friendlyName, string jsonPayload, out bool forceLastSeen) { ZigbeeDevice device = null; if (!TryParseJson(jsonPayload, out var json)) { forceLastSeen = false; return(null); } var linkQuality = json["linkquality"]?.Value <ushort>(); forceLastSeen = !ParseDateTimeOffset(json["last_seen"], out var lastSeen); Bridge Update(Bridge state) { device = state.Devices.FirstOrDefault(d => d.FriendlyName.Equals(friendlyName)); if (device == null) { device = new ZigbeeDevice.Builder { FriendlyName = friendlyName, LastSeen = lastSeen }; state = state.WithDevices(devices => devices.Add(device)); } var battery = json["battery"]?.Value <decimal>(); var updateAvailable = json["update_available"]?.Value <bool?>(); if (!lastSeen.HasValue && !battery.HasValue && !updateAvailable.HasValue) { return(state); } ZigbeeDevice.Builder builder = device; if (lastSeen.HasValue) { builder.LastSeen = lastSeen; } if (battery.HasValue) { builder.BatteryLevel = battery; } if (updateAvailable.HasValue) { builder.IsOtaAvailable = updateAvailable; } ZigbeeDevice newDevice = builder; if (newDevice == device) { return(state); } state = state.WithDevices(devices => devices.Replace(device, newDevice)); device = newDevice; return(state); } UpdateState(Update); return(device); }