Ejemplo n.º 1
0
        //
        // Database events
        //

        private async Task DeviceDiscoveredAsync(TasmotaStatus tasmotaDevice)
        {
            _logger.LogInformation("Received status for '{hostname}' ({ipAddress}). Updating database...", tasmotaDevice.StatusNet.HostName, tasmotaDevice.StatusNet.IpAddress);
            var device = new Device()
            {
                _id = tasmotaDevice.StatusNet.Mac,

                HostName         = tasmotaDevice.StatusNet.HostName,
                Ipv4Address      = IPAddress.Parse(tasmotaDevice.StatusNet.IpAddress),
                Ipv4SubnetPrefix = ConvertToPrefixLength(IPAddress.Parse(tasmotaDevice.StatusNet.SubnetMask)),
                Ipv4Gateway      = IPAddress.Parse(tasmotaDevice.StatusNet.Gateway),
                Ipv4NameServer   = IPAddress.Parse(tasmotaDevice.StatusNet.DnsServer),

                TopicName     = tasmotaDevice.Status.Topic,
                FriendlyNames = tasmotaDevice.Status.FriendlyName,

                FirmwareVersion = tasmotaDevice.StatusFwr.Version.Replace("(tasmota)", ""),
                FirmwareSizeKb  = tasmotaDevice.StatusMem.ProgramSize,
                FlashSizeKb     = tasmotaDevice.StatusMem.FlashSize,
                Hardware        = tasmotaDevice.StatusFwr.Hardware,

                RestartReason    = tasmotaDevice.StatusPrm.RestartReason,
                TelemetrySeconds = tasmotaDevice.StatusLog.TelePeriod,

                TemplateDefinition = tasmotaDevice.Template,
                TemplateName       = ExtractTemplateName(tasmotaDevice.Template),

                Status  = tasmotaDevice.StatusSts.ToDeviceStatus(),
                Offline = false
            };
            var updatedDevice = await _deviceRepository.UpdateDeviceAsync(device, true);

            if (!updatedDevice.AdoptedAt.HasValue)
            {
                _logger.LogInformation("Device '{hostname}' ({ipAddress}) is not adopted. Testing its Mqtt configuration...", device.HostName, device.Ipv4Address);
                await _tasmotaService.TestMqttConfigurationAsync(device.Ipv4Address, device.TopicName, device._id);
            }
        }
Ejemplo n.º 2
0
        private static DeviceEmulator CreateDeviceEmulator(IServiceProvider sp)
        {
            // https://stackoverflow.com/questions/850650/reliable-method-to-get-machines-mac-address-in-c-sharp#comment107946437_7661829
            var nic = NetworkInterface.GetAllNetworkInterfaces()
                      .FirstOrDefault(nic => nic.OperationalStatus == OperationalStatus.Up &&
                                      nic.NetworkInterfaceType != NetworkInterfaceType.Loopback);

            var ipProperties = nic.GetIPProperties();

            var ipAddress = ipProperties
                            .UnicastAddresses.FirstOrDefault(a => a.Address.AddressFamily == AddressFamily.InterNetwork)
                            ?.Address?.ToString();

            var gateway = ipProperties
                          .GatewayAddresses.FirstOrDefault(a => a.Address.AddressFamily == AddressFamily.InterNetwork)
                          ?.Address?.ToString();

            var subnetMask = ipProperties
                             .UnicastAddresses.FirstOrDefault(a => a.Address.AddressFamily == AddressFamily.InterNetwork)
                             ?.IPv4Mask?.ToString();

            var dnsServer = ipProperties
                            .DnsAddresses.FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork)
                            ?.ToString();

            var macSegments = nic.GetPhysicalAddress()
                              .GetAddressBytes();

            var macSegmentsHex = macSegments
                                 .Select(b => b.ToString("x2"));

            var topicSuffixHex = macSegments
                                 .Skip(3)
                                 .Select(b => b.ToString("X2"));

            var topic             = "tasmota_" + string.Join("", topicSuffixHex);
            var hostnameSuffixDec = (macSegments[4] << 8 | macSegments[5]) % 10000;

            var status = new TasmotaStatus()
            {
                Status = new DeviceStatus()
                {
                    FriendlyName = new[] { "Tasmota" },
                    Topic        = topic
                },
                StatusPrm = new ParametersStatus
                {
                    RestartReason = "Powered on"
                },
                StatusFwr = new FirmwareStatus
                {
                    Version  = "1.0.0",
                    Hardware = "Emulator"
                },
                StatusLog = new LogStatus
                {
                    TelePeriod = 300
                },
                StatusMem = new MemoryStatus
                {
                    ProgramSize = 999,
                    FlashSize   = 999
                },
                StatusNet = new NetworkStatus
                {
                    HostName   = $"{topic}-{hostnameSuffixDec}",
                    IpAddress  = ipAddress ?? string.Empty,
                    Gateway    = gateway ?? string.Empty,
                    SubnetMask = subnetMask ?? string.Empty,
                    DnsServer  = dnsServer ?? string.Empty,
                    Mac        = string.Join(":", macSegmentsHex)
                },
                StatusSts = new TelemetryStatus
                {
                    UptimeSec = 0,
                    Heap      = 24,
                    LoadAvg   = 0,
                    MqttCount = 0,
                    Power     = "OFF",
                    WiFi      = new TelemetryStatus.WifiStatus
                    {
                        Rssi      = 100,
                        Signal    = -30,
                        LinkCount = 0,
                        Downtime  = "0T00:00:00",
                    }
                },
                Template = "{\"NAME\":\"Generic\",\"GPIO\":[255,255,255,255,255,255,255,255,255,255,255,255,255],\"FLAG\":15,\"BASE\":18}",
            };

            var hubContext = sp.GetService <IHubContext <DeviceHub, IDeviceHubClient> >();

            var client = sp.GetService <IMqttClient>();

            var result = new DeviceEmulator(status, client);

            result.DeviceChanged += (s, e) => hubContext.Clients.All.DeviceChanged(result);

            var logger = sp.GetService <ILogger <DeviceEmulator> >();

            logger.LogInformation("Device emulator created with initial status = " + JsonConvert.SerializeObject(status, Formatting.Indented));

            return(result);
        }