using System; using System.Drawing; using System.Text; using System.Windows.Forms; using uPLibrary.Networking.M2Mqtt; using uPLibrary.Networking.M2Mqtt.Messages; using Newtonsoft.Json; using System.Globalization; using LiveCharts; using LiveCharts.Wpf; namespace Wetterstation { public partial class Hintergrund : Form { //Variable fuer den Debugmodues private bool debug = false; private MqttClient myClient; //Objekt für die Settings erstellen SettingsModel WeatherstationSettings = new SettingsModel(); String graphLastTimestamp = null; //Sensorobjekte erstellen (fuer jede Messtelle und fuer Openweathermap) Sensor node1In = new Sensor(); Sensor node1Out = new Sensor(); Sensor owm = new Sensor(); public Hintergrund() { InitializeComponent(); //Settings aus der Datenbank laden WeatherstationSettings = SqliteDataAccess.LoadWeatherstationSettings(); lbCity.Text = WeatherstationSettings.city; // Start a timer for date and time Timer t = new Timer(); t.Interval = 1000; t.Tick += new EventHandler(this.t_DateTime); t.Start(); mqttStart(); updateChart(); } //Historiediagramm auf den neuesten Stand bringen private void updateChart() { cartesianChart1.Series = new SeriesCollection { new LineSeries { Title = "Temperatur", Values = new ChartValues<double> {}, ScalesYAt = 0, PointGeometry = null }, new LineSeries { Title = "Luftfeuchtigkeit", Values = new ChartValues<int> {}, ScalesYAt = 1, PointGeometry = null }, new LineSeries { Title = "Luftdruck", Values = new ChartValues<int> {}, ScalesYAt = 2, PointGeometry = null }, new LineSeries { Title = "Wind Geschwindigkeit", Values = new ChartValues<double> {}, ScalesYAt = 3, PointGeometry = null } }; cartesianChart1.AxisY.Add(new Axis { LabelFormatter = val => val + " °C", IsEnabled = false, Position = AxisPosition.LeftBottom }); cartesianChart1.AxisY.Add(new Axis { LabelFormatter = val => val + " %", IsEnabled = false, Position = AxisPosition.LeftBottom }); cartesianChart1.AxisY.Add(new Axis { LabelFormatter = val => val + " hPa", IsEnabled = true, Position = AxisPosition.RightTop }); cartesianChart1.AxisY.Add(new Axis { LabelFormatter = val => val + " ms", IsEnabled = false, Position = AxisPosition.LeftBottom }); cartesianChart1.AxisX.Add(new Axis { Title = "Uhrzeit", Labels = new[] { "" } }); cartesianChart1.LegendLocation = LegendLocation.Right; //modifying the series collection will animate and update the chart //cartesianChart1.Series.Add(new LineSeries //{ // Values = new ChartValues<double> { 5, 3, 2, 4, 5 }, // LineSmoothness = 0, //straight lines, 1 really smooth lines //}); //modifying any series values will also animate and update the chart } //Uhreit und Datum bestimmen und anzeigen private void t_DateTime(object sender, EventArgs e) { lbUhr.Text = DateTime.Now.ToLongTimeString(); lbDatum.Text = DateTime.Now.ToShortDateString(); } // MQTT connect public void mqttStart() { String topic_publish = "/wetterstation/backend/" + WeatherstationSettings.frontendId + "/"; String topic_subscribe = "/wetterstation/frontend/" + WeatherstationSettings.frontendId + "/#"; System.Console.WriteLine("Mqtt wird gestartet ...."); // Create Client instance this.myClient = new MqttClient("mqtt.itstall.de"); // Register to message received myClient.MqttMsgPublishReceived += client_recievedMessage; string clientId = Guid.NewGuid().ToString(); this.myClient.Connect("", "wetterstation", "wetterstation"); // Subscribe to topic this.myClient.Subscribe(new String[] { topic_subscribe }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE }); this.myClient.Publish(topic_publish, Encoding.UTF8.GetBytes("Request_frontend")); } // Send message per MQTT public void msgPublish(String topic, String message) { Console.Write("Sending via MQTT: "); Console.Write("Topic: " + topic); Console.WriteLine("Message: " + message); this.myClient.Publish(topic, Encoding.UTF8.GetBytes(message)); } // Got message from MQTT private void client_recievedMessage(object sender, MqttMsgPublishEventArgs e) { // Handle message received var message = System.Text.Encoding.Default.GetString(e.Message); if (e.Topic.Equals(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/weather")) { this.updateFormWeather(message); } else if (e.Topic.Equals(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/forecast")) { this.updateFormForecast(message); } else if (e.Topic.Equals(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/forecastNext")) { this.updateFormForecastNext(message); } else if (e.Topic.Equals(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/sensors")) { this.updateFormSensors(message); } else if (e.Topic.Equals(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/graph")) { Console.WriteLine(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/graph"); this.updateFormChart(message); } } // Update graph on frontend public void updateFormChart(String message) { double temp; int humidity; int pressure; double windSpeed; dynamic weatherData = JsonConvert.DeserializeObject(message.ToString()); if (graphLastTimestamp == null) { //Json String aufdroeseln und Werte rotierend abspeichern int i = 0; foreach (var result in weatherData["results"][0]["series"][0]["values"]) { if (result[2] == null) temp = 0; else temp = result[1]; if (result[1] == null) humidity = 0; else humidity = result[2]; if (result[3] == null) pressure = 0; else pressure = result[3]; if (result[4] == null) windSpeed = 0; else windSpeed = result[4]; cartesianChart1.Series[0].Values.Add(Math.Round(temp, 1)); cartesianChart1.Series[1].Values.Add(humidity); cartesianChart1.Series[2].Values.Add(pressure); cartesianChart1.Series[3].Values.Add(Math.Round(windSpeed, 1)); } graphLastTimestamp = weatherData["results"][0]["series"][0]["values"][96][0].ToString(); } else { //Prüfen ob sich Timestamp geändert hat if (graphLastTimestamp != weatherData["results"][0]["series"][0]["values"][96][0].ToString()) { cartesianChart1.Series[0].Values.RemoveAt(0); cartesianChart1.Series[1].Values.RemoveAt(0); cartesianChart1.Series[2].Values.RemoveAt(0); cartesianChart1.Series[3].Values.RemoveAt(0); //prüfen ob Daten geliefert wurden. Wenn icht Wert auf 0 ansonsten auf gelieferten Wert if (weatherData["results"][0]["series"][0]["values"][96][1] == null) temp = 0; else temp = weatherData["results"][0]["series"][0]["values"][96][1]; if (weatherData["results"][0]["series"][0]["values"][96][2] == null) humidity = 0; else humidity = weatherData["results"][0]["series"][0]["values"][96][2]; if (weatherData["results"][0]["series"][0]["values"][96][3] == null) pressure = 0; else pressure = weatherData["results"][0]["series"][0]["values"][96][3]; if (weatherData["results"][0]["series"][0]["values"][96][4] == null) windSpeed = 0; else windSpeed = weatherData["results"][0]["series"][0]["values"][96][4]; //Container mit Werten fuellen cartesianChart1.Series[0].Values.Add(Math.Round(temp, 1)); cartesianChart1.Series[1].Values.Add(humidity); cartesianChart1.Series[2].Values.Add(pressure); cartesianChart1.Series[3].Values.Add(Math.Round(windSpeed, 1)); graphLastTimestamp = weatherData["results"][0]["series"][0]["values"][96][0].ToString(); } } } // Update general weather objects on frontend public void updateFormWeather(String message) { Console.WriteLine("Entered updateFormWeather"); Console.WriteLine(message); try { //JSON Daten aufdroesseln dynamic weatherData = JsonConvert.DeserializeObject(message.ToString()); //Wenn keine Daten von den Sensoren vorliegen nimm die Werte von Openweathermap if (!node1Out.temperature) { lbAussenTemp.Invoke(new Action(() => { lbAussenTemp.Text = weatherData.temp + " °C"; })); lbTempOutMin.Invoke(new Action(() => { lbTempOutMin.Text = weatherData.tempMin + " °C"; })); lbTempOutMax.Invoke(new Action(() => { lbTempOutMax.Text = weatherData.tempMax + " °C"; })); owm.Temperatures = weatherData.temp; //Tendenzpfeil entsprechend setzen u.o. ausblenden if (owm.tempTendenz() == -1) pbTendenzTempOut.Invoke(new Action(() => { pbTendenzTempOut.Visible = false; })); else pbTendenzTempOut.Invoke(new Action(() => { pbTendenzTempOut.Visible = true; })); pbTendenzTempOut.Invoke(new Action(() => { pbTendenzTempOut.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("Tendenz"), owm.tempTendenz()); })); } if(!node1Out.humidity) { lbLuftfeuchtAussen.Invoke(new Action(() => { lbLuftfeuchtAussen.Text = weatherData.humidity + " %"; })); owm.Humiditys = (double)weatherData.humidity; if (owm.humidityTendenz() == -1) lbTendenzHumidityOut.Invoke(new Action(() => { lbTendenzHumidityOut.Visible = false; })); else lbTendenzHumidityOut.Invoke(new Action(() => { lbTendenzHumidityOut.Visible = true; })); lbTendenzHumidityOut.Invoke(new Action(() => { lbTendenzHumidityOut.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("Tendenz"), owm.humidityTendenz()); })); } if(!node1Out.windSpeed) { lbWindSpeed.Invoke(new Action(() => { lbWindSpeed.Text = weatherData.windSpeed + " ms"; })); } if (!node1Out.windDegre) { lbWindricht.Invoke(new Action(() => { lbWindricht.Text = weatherData.windDeg + " °"; })); pbKompassrose.Invoke(new Action(() => { pbKompassrose.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("WindRose_neu"), (int)weatherData.windDeg); })); } if (!node1Out.pressure && !node1In.pressure) { lbLuftdruck.Invoke(new Action(() => { lbLuftdruck.Text = weatherData.pressure + " mbar"; })); owm.Pressures = (double)weatherData.pressure; if (owm.pressureTendenz() == -1) pbTendenzPressure.Invoke(new Action(() => { pbTendenzPressure.Visible = false; })); else pbTendenzPressure.Invoke(new Action(() => { pbTendenzPressure.Visible = true; })); pbTendenzPressure.Invoke(new Action(() => { pbTendenzPressure.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("Tendenz"), owm.pressureTendenz()); })); } if(!node1Out.rain) { lbRain1h.Invoke(new Action(() => { lbRain1h.Text = weatherData.rain1h + " mm"; })); } lbRain3h.Invoke(new Action(() => { lbRain3h.Text = weatherData.rain3h + " mm"; })); if (!node1Out.snow) { lbSnow1h.Invoke(new Action(() => { lbSnow1h.Text = weatherData.snow1h + " mm"; })); } lbSnow3h.Invoke(new Action(() => { lbSnow3h.Text = weatherData.snow3h + " mm"; })); } catch (Exception ignored) { Console.WriteLine(ignored.Message); } } // Rotate an image private Bitmap RotateImage(Bitmap bmp, float angle) { float height = bmp.Height; float width = bmp.Width; int hypotenuse = System.Convert.ToInt32(System.Math.Floor(Math.Sqrt(height * height + width * width))); Bitmap rotatedImage = new Bitmap(hypotenuse, hypotenuse); using (Graphics g = Graphics.FromImage(rotatedImage)) { g.TranslateTransform((float)rotatedImage.Width / 2, (float)rotatedImage.Height / 2); //set the rotation point as the center into the matrix g.RotateTransform(angle); //rotate g.TranslateTransform(-(float)rotatedImage.Width / 2, -(float)rotatedImage.Height / 2); //restore rotation point into the matrix g.DrawImage(bmp, (hypotenuse - width) / 2, (hypotenuse - height) / 2, width, height); } return rotatedImage; } // Update forecast images public void updateFormForecast(String message) { Console.WriteLine("Entered updateFormForecast"); try { dynamic weatherData = JsonConvert.DeserializeObject(message.ToString()); if (weatherData[0].icon1 != null) lbForecastImage1.Invoke(new Action(() => { lbForecastImage1.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[0].icon1 + "_2x"); })); lbForecastTemp1.Invoke(new Action(() => { lbForecastTemp1.Text = weatherData[0].temp + " °C"; })); lbForecastDay1.Invoke(new Action(() => { lbForecastDay1.Text = getDayFromDateString(weatherData[0].from.ToString()); })); if (weatherData[1].icon1 != null) lbForecastImage2.Invoke(new Action(() => { lbForecastImage2.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[1].icon1 + "_2x"); })); lbForecastTemp2.Invoke(new Action(() => { lbForecastTemp2.Text = weatherData[1].temp + " °C"; })); lbForecastDay2.Invoke(new Action(() => { lbForecastDay2.Text = getDayFromDateString(weatherData[1].from.ToString()); })); if (weatherData[2].icon1 != null) lbForecastImage3.Invoke(new Action(() => { lbForecastImage3.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[2].icon1 + "_2x"); })); lbForecastTemp3.Invoke(new Action(() => { lbForecastTemp3.Text = weatherData[2].temp + " °C"; })); lbForecastDay1.Invoke(new Action(() => { lbForecastDay1.Text = getDayFromDateString(weatherData[0].from.ToString()); })); lbForecastDay3.Invoke(new Action(() => { lbForecastDay3.Text = getDayFromDateString(weatherData[2].from.ToString()); })); if (weatherData[3].icon1 != null) lbForecastImage4.Invoke(new Action(() => { lbForecastImage4.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[3].icon1 + "_2x"); })); lbForecastTemp4.Invoke(new Action(() => { lbForecastTemp4.Text = weatherData[3].temp + " °C"; })); lbForecastDay4.Invoke(new Action(() => { lbForecastDay4.Text = getDayFromDateString(weatherData[3].from.ToString()); })); if (weatherData[4].icon1 != null) lbForecastImage5.Invoke(new Action(() => { lbForecastImage5.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[4].icon1 + "_2x"); })); lbForecastTemp5.Invoke(new Action(() => { lbForecastTemp5.Text = weatherData[4].temp + " °C"; })); lbForecastDay5.Invoke(new Action(() => { lbForecastDay5.Text = getDayFromDateString(weatherData[4].from.ToString()); })); } catch (Exception ignored) { } } // Update next forecast public void updateFormForecastNext(String message) { Console.WriteLine("Entered updateFormForecastNext"); try { dynamic weatherData = JsonConvert.DeserializeObject(message.ToString()); if (weatherData.icon1 != null) pbForecastNext.Invoke(new Action(() => { pbForecastNext.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData.icon1 + "_2x"); })); lbForecastNextFrom.Invoke(new Action(() => { lbForecastNextFrom.Text = getTimeFromDateString(weatherData.from.ToString()); })); lbForecastNextClouds.Invoke(new Action(() => { lbForecastNextClouds.Text = weatherData.clouds; })); lbForecastNextHumidity.Invoke(new Action(() => { lbForecastNextHumidity.Text = weatherData.humidity; })); lbForecastNextPressure.Invoke(new Action(() => { lbForecastNextPressure.Text = weatherData.pressure; })); lbForecastNextRain.Invoke(new Action(() => { lbForecastNextRain.Text = weatherData.rain3h; })); lbForecastNextSnow.Invoke(new Action(() => { lbForecastNextSnow.Text = weatherData.snow3h; })); lbForecastNextTemp.Invoke(new Action(() => { lbForecastNextTemp.Text = weatherData.temp; })); lbForecastNextWindSpeed.Invoke(new Action(() => { lbForecastNextWindSpeed.Text = weatherData.windSpeed; })); } catch (Exception ignored) { } } public String getTimeFromDateString(String strDate) { DateTime dt = DateTime.ParseExact(strDate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); CultureInfo culture = new CultureInfo("de-DE"); return dt.ToString("HH:mm"); } public String getDayFromDateString(String strDate) { DateTime dt = DateTime.ParseExact(strDate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); CultureInfo culture = new CultureInfo("de-DE"); return culture.DateTimeFormat.GetDayName(dt.DayOfWeek).Substring(0, 2).ToString(); } public void updateFormSensors(String message) { Console.WriteLine("Entered updateFormSensors"); Console.WriteLine(message); try { dynamic weatherData = JsonConvert.DeserializeObject(message.ToString()); if (weatherData[0]["client"] == WeatherstationSettings.node1Id && weatherData[0]["sensor"] == WeatherstationSettings.node1Innen) { node1In.host = weatherData[0]["client"]; node1In.name = weatherData[0]["sensor"]; } if (weatherData[0]["client"] == WeatherstationSettings.node1Id && weatherData[0]["sensor"] == WeatherstationSettings.node1Aussen) { node1Out.host = weatherData[0]["client"]; node1Out.name = weatherData[0]["sensor"]; } if (weatherData[0]["client"] == node1In.host && weatherData[0]["sensor"] == node1In.name && weatherData[0]["temperature"] != null) { node1In.temperature = true; if (node1In.tempMin == 0) node1In.tempMin = weatherData[0]["temperature"]; if (node1In.tempMax == 0) node1In.tempMax = weatherData[0]["temperature"]; if ((double)weatherData[0]["temperature"] > node1In.tempMax) node1In.tempMax = weatherData[0]["temperature"]; if ((double)weatherData[0]["temperature"] < node1In.tempMin) node1In.tempMin = weatherData[0]["temperature"]; lbInnenTemp.Invoke(new Action(() => { lbInnenTemp.Text = weatherData[0]["temperature"] + " °C"; })); lbTempInMin.Invoke(new Action(() => { lbTempInMin.Text = node1In.tempMin + " °C"; })); lbTempInMax.Invoke(new Action(() => { lbTempInMax.Text = node1In.tempMax + " °C"; })); node1In.Temperatures = (double)weatherData[0]["temperature"]; if (node1In.tempTendenz() == -1) pbTendenzTempIn.Invoke(new Action(() => { pbTendenzTempIn.Visible = false; })); else pbTendenzTempIn.Invoke(new Action(() => { pbTendenzTempIn.Visible = true; })); pbTendenzTempIn.Invoke(new Action(() => { pbTendenzTempIn.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("Tendenz"), node1In.tempTendenz()); })); } if (weatherData[0]["client"] == node1In.host && weatherData[0]["sensor"] == node1In.name && weatherData[0]["humidity"] != null) { node1In.humidity = true; lbLuftFeuchtInnen.Invoke(new Action(() => { lbLuftFeuchtInnen.Text = weatherData[0]["humidity"] + " %"; })); node1Out.Humiditys = (double)weatherData[0]["humidity"]; if (node1In.humidityTendenz() == -1) lbTendenzHumidityIn.Invoke(new Action(() => { lbTendenzHumidityIn.Visible = false; })); else lbTendenzHumidityIn.Invoke(new Action(() => { lbTendenzHumidityIn.Visible = true; })); lbTendenzHumidityIn.Invoke(new Action(() => { lbTendenzHumidityIn.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("Tendenz"), node1In.humidityTendenz()); })); } if (weatherData[0]["client"] == node1In.host && weatherData[0]["sensor"] == node1In.name && weatherData[0]["pressure"] != null) { node1In.pressure = true; lbLuftdruck.Invoke(new Action(() => { lbLuftdruck.Text = weatherData[0]["pressure"] + " hPa"; })); node1In.Pressures = (double)weatherData[0]["pressure"]; if (node1In.pressureTendenz() == -1) pbTendenzPressure.Invoke(new Action(() => { pbTendenzPressure.Visible = false; })); else pbTendenzPressure.Invoke(new Action(() => { pbTendenzPressure.Visible = true; })); pbTendenzPressure.Invoke(new Action(() => { pbTendenzPressure.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("Tendenz"), node1In.pressureTendenz()); })); } if (weatherData[0]["client"] == node1Out.host && weatherData[0]["sensor"] == node1Out.name && weatherData[0]["temperature"] != null) { node1Out.temperature = true; if (node1In.tempMin == 0) node1Out.tempMin = weatherData[0]["temperature"]; if (node1In.tempMax == 0) node1Out.tempMax = weatherData[0]["temperature"]; if ((double)weatherData[0]["temperature"] > node1Out.tempMax) node1Out.tempMax = weatherData[0]["temperature"]; if ((double)weatherData[0]["temperature"] < node1Out.tempMin) node1Out.tempMin = weatherData[0]["temperature"]; lbAussenTemp.Invoke(new Action(() => { lbAussenTemp.Text = weatherData[0]["temperature"] + " °C"; })); lbTempOutMin.Invoke(new Action(() => { lbTempOutMin.Text = node1Out.tempMin + " °C"; })); lbTempOutMax.Invoke(new Action(() => { lbTempOutMax.Text = node1Out.tempMax + " °C"; })); node1Out.Temperatures = (double)weatherData[0]["temperature"]; if (node1Out.tempTendenz() == -1) pbTendenzTempOut.Invoke(new Action(() => { pbTendenzTempOut.Visible = false; })); else pbTendenzTempOut.Invoke(new Action(() => { pbTendenzTempOut.Visible = true; })); pbTendenzTempOut.Invoke(new Action(() => { pbTendenzTempOut.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("Tendenz"), node1Out.tempTendenz()); })); } if (weatherData[0]["client"] == node1Out.host && weatherData[0]["sensor"] == node1Out.name && weatherData[0]["humidity"] != null) { node1Out.humidity = true; lbLuftfeuchtAussen.Invoke(new Action(() => { lbLuftfeuchtAussen.Text = weatherData[0]["humidity"] + " %"; })); node1Out.Humiditys = (double)weatherData[0]["humidity"]; if (node1Out.humidityTendenz() == -1) lbTendenzHumidityOut.Invoke(new Action(() => { lbTendenzHumidityOut.Visible = false; })); else lbTendenzHumidityOut.Invoke(new Action(() => { lbTendenzHumidityOut.Visible = true; })); lbTendenzHumidityOut.Invoke(new Action(() => { lbTendenzHumidityOut.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("Tendenz"), node1Out.humidityTendenz()); })); } } catch (Exception ignored) { Console.WriteLine(ignored.Message); } } public void updateFormComplete() { WeatherstationSettings = SqliteDataAccess.LoadWeatherstationSettings(); lbCity.Text = WeatherstationSettings.city; } public void updateSettings2Mqtt() { Console.WriteLine(JsonConvert.SerializeObject(WeatherstationSettings).ToString()); this.msgPublish(WeatherstationSettings.mqtt_topic_backend + "settings", JsonConvert.SerializeObject(WeatherstationSettings).ToString()); } private void BtSystemKnopf_Click(object sender, EventArgs e) { Form settings = new Settings(); // Settings als Dialog starten, dann wird das Frontend geblockt und auf abschluss gewartet settings.ShowDialog(); updateFormComplete(); // MQTT beenden und Verbindung neu aufbauen this.myClient.Disconnect(); this.mqttStart(); // Neue Einstellungen an Backend senden this.updateSettings2Mqtt(); } private void Hintergrund_FormClosed(object sender, FormClosedEventArgs e) { this.myClient.Disconnect(); Application.Exit(); } } }