Ejemplo n.º 1
0
        public void Observe(string entityId, object state, IDictionary <string, object> attributes)
        {
            lock (LockObject)
            {
                var entityDomain = GetDomainFromEntity(entityId);

                if (state != null)
                {
                    if (!DomainsStates.TryGetValue(entityDomain, out var domainStates))
                    {
                        DomainsStates[entityDomain] = domainStates = new HashSet <string>();
                    }

                    domainStates.Add(state.ToString());
                }

                if (!DomainAttributeCounts.TryGetValue(entityDomain, out var allAttributes))
                {
                    DomainAttributeCounts[entityDomain] = allAttributes = new Dictionary <string, IDictionary <string, int> >();
                }

                foreach (var attribute in attributes)
                {
                    var key   = attribute.Key;
                    var value = attribute.Value;

                    if (!allAttributes.TryGetValue(key, out var values))
                    {
                        allAttributes[key] = values = new Dictionary <string, int>();
                    }

                    if (value != null)
                    {
                        values.TryGetValue(value.ToString(), out var currentCount);
                        values[value.ToString()] = currentCount + 1;
                    }
                    else
                    {
                        if (!DomainAttributeNullability.TryGetValue(entityDomain, out var attributeNullability))
                        {
                            DomainAttributeNullability[entityDomain] = attributeNullability = new HashSet <string>();
                        }

                        attributeNullability.Add(key);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public string GenerateCode()
        {
            var sb = new StringBuilder();
            var entityStateDeserializers = new List <string>();

            foreach (var domainAttributes in DomainAttributeCounts)
            {
                var domain     = domainAttributes.Key;
                var attributes = domainAttributes.Value;

                var domainClassPrefix = domain.FromSnakeToPascalCase();

                DomainAttributeNullability.TryGetValue(domain, out var nullableAttributes);

                sb.AppendLine($"    public class {domainClassPrefix}StateAttributes");
                sb.AppendLine(@"    {");
                var first = true;

                var totalAttributeObservations = attributes.Values.SelectMany(x => x).Max(x => x.Value);

                foreach (var attributeValues in attributes)
                {
                    var attribute = attributeValues.Key;
                    var values    = attributeValues.Value;

                    var attributeName = attribute.FromSnakeToPascalCase(out var requiresSerializationOverride);
                    var isNullable    = nullableAttributes?.Contains(attribute) ?? false;
                    var attributeType = GetBestType(values, totalAttributeObservations, isNullable, false, null, out _);

                    if (requiresSerializationOverride)
                    {
                        if (!first)
                        {
                            sb.AppendLine();
                        }

                        sb.AppendLine($"        [JsonProperty(\"{attribute}\")]");
                        sb.AppendLine($"        public {attributeType} {attributeName} {{ get; set; }}");
                    }
                    else
                    {
                        sb.AppendLine($"        public {attributeType} {attributeName} {{ get; set; }}");
                    }

                    first = false;
                }

                sb.AppendLine(@"    }");
                sb.AppendLine();

                var domainHasStates = DomainsStates.TryGetValue(domain, out var states);
                if (domainHasStates)
                {
                    var statesWithFakeObservations = states.ToDictionary(x => x, x => totalAttributeObservations);
                    var stateType = GetBestType(statesWithFakeObservations, totalAttributeObservations, false, true, domainClassPrefix, out var isEnum);
                    if (isEnum)
                    {
                        sb.AppendLine($"    public enum {domainClassPrefix}StateValue");
                        sb.AppendLine(@"    {");
                        sb.AppendLine(@"        Unavailable,");

                        for (var idx = 0; idx < states.ToArray().Length; idx++)
                        {
                            var value = states.ToArray()[idx];
                            if (value == "unavailable")
                            {
                                continue;
                            }

                            var valueFormat = value.FromSnakeToPascalCase(out var requiresSerializationOverride);
                            if (requiresSerializationOverride)
                            {
                                sb.AppendLine();
                                sb.AppendLine($"        [EnumMember(Value = \"{value}\")]");
                                sb.AppendLine($"        {valueFormat}{(idx < states.Count - 1 ? "," : string.Empty)}");
                            }
                            else
                            {
                                sb.AppendLine($"        {valueFormat}{(idx < states.Count - 1 ? "," : string.Empty)}");
                            }
                        }

                        sb.AppendLine(@"    }");
                        sb.AppendLine();

                        sb.AppendLine($"    public class {domainClassPrefix}EntityState : {nameof(EntityState)}<{domainClassPrefix}StateValue, {domainClassPrefix}StateAttributes>");
                        sb.AppendLine(@"    {");
                        sb.AppendLine(@"    }");
                    }
                    else
                    {
                        sb.AppendLine($"    public class {domainClassPrefix}EntityState : {nameof(EntityState)}<{stateType}, {domainClassPrefix}StateAttributes>");
                        sb.AppendLine(@"    {");
                        sb.AppendLine(@"    }");
                    }
                }
                else
                {
                    sb.AppendLine($"    public class {domainClassPrefix}EntityState : {nameof(EntityState)}<{domainClassPrefix}StateAttributes>");
                    sb.AppendLine(@"    {");
                    sb.AppendLine(@"    }");
                }

                sb.AppendLine();
                sb.AppendLine($"    public class {domainClassPrefix}EntityStateDeserializer : BaseStateDeserializer<{domainClassPrefix}EntityState>");
                sb.AppendLine(@"    {");
                sb.AppendLine($"        public override string TargetDomain {{ get; }} = \"{domain}\";");
                sb.AppendLine(@"        public override bool CanDeserialize(IDictionary<string, object> attributes) => true;");
                sb.AppendLine(@"    }");

                entityStateDeserializers.Add($"{domainClassPrefix}EntityStateDeserializer");
                sb.AppendLine();
            }

            sb.AppendLine(@"    public static class HomeAssistantClientConfigurationBuilderExtensions");
            sb.AppendLine(@"    {");
            sb.AppendLine(@"        public static IHomeAssistantClientConfigurationBuilder WithStateCodeGenerator(this IHomeAssistantClientConfigurationBuilder configurationBuilder)");
            sb.AppendLine(@"        {");
            if (entityStateDeserializers.Count > 0)
            {
                sb.AppendLine(@"            return configurationBuilder");
                for (var idx = 0; idx < entityStateDeserializers.Count; idx++)
                {
                    var entityState = entityStateDeserializers[idx];
                    sb.AppendLine($"                .WithStateDeserializer<{entityState}>(){(idx == entityStateDeserializers.Count - 1 ? ";" : string.Empty)}");
                }
            }
            else
            {
                sb.AppendLine(@"            return configurationBuilder;");
            }

            sb.AppendLine(@"        }");
            sb.AppendLine(@"    }");

            return(sb.ToString());
        }