Skip to content

Commit aab8bbf

Browse files
committed
Revise L29
1 parent ca63b6b commit aab8bbf

1 file changed

Lines changed: 199 additions & 114 deletions

File tree

29_Anwendungen.md

Lines changed: 199 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
author: Sebastian Zug, Galina Rudolf & André Dietrich
44
email: sebastian.zug@informatik.tu-freiberg.de
5-
version: 1.0.3
5+
version: 1.0.4
66
language: de
77
narrator: Deutsch Female
88
comment: Zusammenfassung und Ausblick
@@ -12,6 +12,7 @@ logo:
1212
import: https://github.com/liascript/CodeRunner
1313
1414
import: https://raw.githubusercontent.com/TUBAF-IfI-LiaScript/VL_Softwareentwicklung/master/config.md
15+
https://raw.githubusercontent.com/liascript-templates/plantUML/master/README.md
1516
1617
-->
1718

@@ -33,12 +34,6 @@ import: https://raw.githubusercontent.com/TUBAF-IfI-LiaScript/VL_Softwareentwick
3334

3435
---------------------------------------------------------------------
3536

36-
## Bits&Bytes
37-
38-
https://liascript.github.io/course/?https://raw.githubusercontent.com/SebastianZug/RoboLabVortraege/main/19_Fussball/README.md#1
39-
40-
![](https://raw.githubusercontent.com/SebastianZug/RoboLabVortraege/main/19_Fussball/image/football_results.png)
41-
4237
## Nachfrage: Secrets
4338

4439
Wie gehen wir mit Schlüsseln, Passwörtern usw. in unseren Codes um?
@@ -85,144 +80,234 @@ Console.WriteLine(APIsecret);
8580

8681
Lassen Sie die Inhalte der Lehrveranstaltung anhand eines Codereviews Revue passieren lassen.
8782

88-
https://cobwebsonmymind.wordpress.com/2011/04/13/thingspeak-net-class/
89-
90-
Wir fokussieren uns auf zwei Methoden für das grundsätzliche Schreiben eines Wertes auf den Server.
91-
92-
> __Aufgabe:__ Bewerten Sie den Code im Hinblick auf:
93-
>
94-
> - Verwendbarkeit des Beispiels
95-
> - Entwurfsqualität
96-
> - Implementierung
83+
> Sie erhalten ein C# Programm und sollen es überarbeiten - welche Mängel finden Sie?
9784
9885
```csharp
9986
using System;
100-
using System.Data;
101-
using System.Configuration;
102-
using System.Web;
103-
using System.Web.Security;
104-
using System.Web.UI;
105-
using System.Web.UI.HtmlControls;
106-
using System.Web.UI.WebControls;
107-
using System.Web.UI.WebControls.WebParts;
108-
using System.Text;
10987
using System.Net;
88+
using System.Text.Json;
11089
using System.IO;
11190

112-
namespace ThingSpeak
91+
using Microsoft.Extensions.Configuration;
92+
93+
class Program
11394
{
114-
public class ThingSpeak
95+
static void Main()
11596
{
116-
private const string _url = "http://api.thingspeak.com/";
117-
private const string _APIKey = "YOUR_KEY_HERE";
118-
119-
public static Boolean SendDataToThingSpeak(string field1, string field2, string field3, string field4, string field5, string field6, string field7, string field8, out Int16 TSResponse)
97+
var config = new ConfigurationBuilder()
98+
.AddUserSecrets<Program>()
99+
.Build();
100+
101+
var apiKey = config["OpenWeatherMap:ApiKey"];
102+
var thingSpeakApiKey = config["ThingSpeak:ApiKey"]; // ThingSpeak Write API Key
103+
string city = "Freiberg";
104+
105+
WebClient client = new WebClient();
106+
string city_url = $"http://api.openweathermap.org/geo/1.0/direct?q={city}&limit=1&appid={apiKey}";
107+
string city_json = client.DownloadString(city_url);
108+
Console.WriteLine(city_json);
109+
110+
JsonDocument cityDoc = JsonDocument.Parse(city_json);
111+
JsonElement cityRoot = cityDoc.RootElement;
112+
double lat = cityRoot[0].GetProperty("lat").GetDouble();
113+
double lon = cityRoot[0].GetProperty("lon").GetDouble();
114+
115+
string weather_url = $"http://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={apiKey}&units=metric";
116+
Console.WriteLine(weather_url);
117+
118+
string weather_json = client.DownloadString(weather_url);
119+
Console.WriteLine(weather_json);
120+
121+
JsonDocument weatherDoc = JsonDocument.Parse(weather_json);
122+
JsonElement weatherRoot = weatherDoc.RootElement;
123+
string wetter = weatherRoot.GetProperty("weather")[0].GetProperty("description").GetString();
124+
double temp = weatherRoot.GetProperty("main").GetProperty("temp").GetDouble();
125+
double wind = weatherRoot.GetProperty("wind").GetProperty("speed").GetDouble();
126+
127+
Console.WriteLine($"\nWetter in {city}:");
128+
Console.WriteLine($"Beschreibung: {wetter}");
129+
Console.WriteLine($"Temperatur: {temp}°C");
130+
Console.WriteLine($"Windgeschwindigkeit: {wind} m/s");
131+
132+
// CSV-Datei erstellen/erweitern
133+
string csvFilePath = "wetterdaten.csv";
134+
string csvLine = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss},{city},{wetter},{temp},{wind}";
135+
136+
// Prüfen ob CSV-Datei bereits existiert
137+
if (!File.Exists(csvFilePath))
120138
{
121-
StringBuilder sbQS = new StringBuilder();
122-
123-
// Build the querystring
124-
sbQS.Append(_url + "update?key=" + _APIKey);
125-
if (field1 != null) sbQS.Append("&field1=" + HttpUtility.UrlEncode(field1));
126-
if (field2 != null) sbQS.Append("&field2=" + HttpUtility.UrlEncode(field2));
127-
if (field3 != null) sbQS.Append("&field3=" + HttpUtility.UrlEncode(field3));
128-
if (field4 != null) sbQS.Append("&field4=" + HttpUtility.UrlEncode(field4));
129-
if (field5 != null) sbQS.Append("&field5=" + HttpUtility.UrlEncode(field5));
130-
if (field6 != null) sbQS.Append("&field6=" + HttpUtility.UrlEncode(field6));
131-
if (field7 != null) sbQS.Append("&field7=" + HttpUtility.UrlEncode(field7));
132-
if (field8 != null) sbQS.Append("&field8=" + HttpUtility.UrlEncode(field8));
133-
// The response will be a "0" if there is an error or the entry_id if > 0
134-
TSResponse = Convert.ToInt16(PostToThingSpeak(sbQS.ToString()));
135-
if (TSResponse > 0)
136-
{
137-
return true;
138-
}
139-
else
140-
{
141-
return false;
142-
}
143-
139+
// Header schreiben falls Datei nicht existiert
140+
string header = "Datum,Stadt,Beschreibung,Temperatur_C,Windgeschwindigkeit_ms";
141+
File.WriteAllText(csvFilePath, header + Environment.NewLine);
144142
}
145-
146-
private static string PostToThingSpeak(string QueryString)
143+
144+
// Wetterdaten anhängen
145+
File.AppendAllText(csvFilePath, csvLine + Environment.NewLine);
146+
147+
Console.WriteLine($"\nWetterdaten wurden in '{csvFilePath}' gespeichert.");
148+
149+
// ThingSpeak Daten senden
150+
if (!string.IsNullOrEmpty(thingSpeakApiKey))
147151
{
148-
StringBuilder sbResponse = new StringBuilder();
149-
byte[] buf = new byte[8192];
150-
151-
// Hit the URL with the querystring and put the response in webResponse
152-
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(QueryString);
153-
HttpWebResponse webResponse = (HttpWebResponse)myRequest.GetResponse();
152+
string thingSpeakUrl = $"https://api.thingspeak.com/update?api_key={thingSpeakApiKey}&field1={temp}&field2={wind}";
153+
154154
try
155155
{
156-
Stream myResponse = webResponse.GetResponseStream();
157-
int count = 0;
158-
// Read the response buffer and return
159-
do
156+
string thingSpeakResponse = client.DownloadString(thingSpeakUrl);
157+
Console.WriteLine($"ThingSpeak Response: {thingSpeakResponse}");
158+
159+
if (int.TryParse(thingSpeakResponse, out int entryId) && entryId > 0)
160+
{
161+
Console.WriteLine($"Daten erfolgreich an ThingSpeak gesendet! Entry ID: {entryId}");
162+
}
163+
else
160164
{
161-
count = myResponse.Read(buf, 0, buf.Length);
162-
if (count != 0)
163-
{
164-
sbResponse.Append(Encoding.ASCII.GetString(buf, 0, count));
165-
}
165+
Console.WriteLine("Fehler beim Senden an ThingSpeak.");
166166
}
167-
while (count > 0);
168-
return sbResponse.ToString();
169167
}
170-
catch (WebException ex)
168+
catch (Exception ex)
171169
{
172-
return "0";
170+
Console.WriteLine($"Fehler beim Senden an ThingSpeak: {ex.Message}");
173171
}
174-
172+
}
173+
else
174+
{
175+
Console.WriteLine("ThingSpeak API Key nicht gefunden. Daten werden nicht gesendet.");
175176
}
176177
}
177178
}
178179
```
179180

180-
Ablauf eines Schreibprozesses:
181+
[SOLID](https://liascript.github.io/course/?https://raw.githubusercontent.com/TUBAF-IfI-LiaScript/VL_Softwareentwicklung/master/15_UML_Modellierung.md#4)
181182

182-
1. Initiierung:
183+
## Erster Entwurf mit LLM
183184

184-
+ der Nutzer spezifiziert die Kanalkonfiguration und den Kanalnamen
185+
```text @plantUML.png
186+
@startuml
187+
skinparam classAttributeIconSize 0
188+
189+
class Program
190+
191+
class WeatherAggregator {
192+
-geoService: IGeoLocationService
193+
-weatherProvider: IWeatherProvider
194+
-sinks: List<IDataSink>
195+
-processors: List<IWeatherDataProcessor>
196+
+AddSink(sink: IDataSink)
197+
+AddProcessor(proc: IWeatherDataProcessor)
198+
+FetchAndDistribute(city: string)
199+
+event WeatherDataReceived
200+
}
201+
202+
interface IGeoLocationService {
203+
+GetCoordinates(city: string): (double lat, double lon)
204+
}
205+
206+
class OpenWeatherMapGeoService {
207+
-apiKey: string
208+
+GetCoordinates(city: string)
209+
}
210+
211+
interface IWeatherProvider {
212+
+GetWeather(lat: double, lon: double): WeatherData
213+
}
214+
215+
class OpenWeatherMapWeatherProvider {
216+
-apiKey: string
217+
+GetWeather(lat: double, lon: double)
218+
}
219+
220+
interface IWeatherDataProcessor {
221+
+Process(data: WeatherData): WeatherData
222+
}
223+
224+
class WindWarningProcessor {
225+
+Process(data: WeatherData): WeatherData
226+
}
227+
228+
interface IDataSink {
229+
+OnWeatherDataReceived(data: WeatherData): void
230+
}
231+
232+
class CsvSink {
233+
-filePath: string
234+
+OnWeatherDataReceived(data: WeatherData)
235+
}
236+
237+
class ThingSpeakSink {
238+
-apiKey: string
239+
+OnWeatherDataReceived(data: WeatherData)
240+
}
241+
242+
class ConsoleSink {
243+
+OnWeatherDataReceived(data: WeatherData)
244+
}
245+
246+
class WeatherData {
247+
+City: string
248+
+Description: string
249+
+TemperatureC: double
250+
+WindSpeed: double
251+
+Warning?: string
252+
}
253+
254+
Program --> WeatherAggregator
255+
256+
WeatherAggregator --> IGeoLocationService
257+
WeatherAggregator --> IWeatherProvider
258+
WeatherAggregator --> IDataSink
259+
WeatherAggregator --> IWeatherDataProcessor
260+
261+
OpenWeatherMapGeoService ..|> IGeoLocationService
262+
OpenWeatherMapWeatherProvider ..|> IWeatherProvider
263+
264+
WindWarningProcessor ..|> IWeatherDataProcessor
265+
266+
CsvSink ..|> IDataSink
267+
ThingSpeakSink ..|> IDataSink
268+
ConsoleSink ..|> IDataSink
269+
270+
WeatherAggregator --> WeatherData : emits event
271+
@enduml
272+
```
185273

186-
2. Laufzeit:
187274

188-
+ Schreiben der Werte
189-
+ Versenden
190-
+ Evaluation des Erfolgs und "Markierung" der bereits versandten Daten
191275

192276
## Resumee
193277

278+
194279
<!--data-type="none"-->
195-
| Woche | Tag | Inhalt der Vorlesung |
196-
| :---- | --------- | :------------------------------------------------ |
197-
| 1 | 5. April | Organisation, Einführung von GitHub und LiaScript |
198-
| 2 | 8. April | Softwareentwicklung als Prozess |
199-
| | 12. April | Konzepte von Dotnet und C# |
200-
| 3 | 15. April | Elemente der Sprache C# I |
201-
| | 19. April | Elemente der Sprache C# II |
202-
| 4 | 22. April | Strukturen / Konzepte der OOP |
203-
| | 26. April | Säulen Objektorientierter Programmierung |
204-
| 5 | 29. April | Klassenelemente in C# / Vererbung |
205-
| | 3. Mai | Klassenelemente in C# / Interfaces |
206-
| 6 | 6. Mai | Generics |
207-
| | 10. Mai | Container |
208-
| 7 | 13. Mai | Versionsmanagement im SWE-Prozess I |
209-
| | 17. Mai | Versionsmanagement im SWE_Pprozess II |
210-
| 8 | 20. Mai | _Pfingstmontag_ |
211-
| | 24. Mai | UML Konzepte |
212-
| 9 | 27. Mai | UML Diagrammtypen |
213-
| | 31. Mai | UML Anwendungsbeispiel |
214-
| 10 | 3. Juni | Testen |
215-
| | 7. Juni | Dokumentation und Build Toolchains |
216-
| 11 | 10. Juni | Continuous Integration in GitHub |
217-
| | 14. Juni | Delegaten |
218-
| 12 | 17. Juni | Events |
219-
| | 21. Juni | Threadkonzepte in C# |
220-
| 13 | 24. Juni | Taskmodell |
221-
| | 28. Juni | Design Pattern |
222-
| 14 | 1. Juli | Language Integrated Query |
223-
| | 5. Juli | GUI - MAUI |
224-
| 15 | 8. Juli | GUI - MAUI |
225-
| | 12. Juli | Anwendungungsfälle |
280+
| Woche | Tag | SWE |
281+
| :---- | --------- | :--------------------------------------- |
282+
| 1 | 4. April | Organisation, Einführung |
283+
| 2 | 7. April | Softwareentwicklung als Prozess |
284+
| | 11. April | Konzepte von Dotnet und C# |
285+
| 3 | 14. April | Elemente der Sprache C# I |
286+
| | 18. April | _Karfreitag_ |
287+
| 4 | 21. April | _Ostermontag_ |
288+
| | 25. April | Elemente der Sprache C# II |
289+
| 5 | 28. April | Strukturen / Konzepte der OOP |
290+
| | 2. Mai | Säulen Objektorientierter Programmierung |
291+
| 6 | 5. Mai | Klassenelemente in C# / Vererbung |
292+
| | 9. Mai | Klassenelemente in C# / Interfaces |
293+
| 7 | 12. Mai | Versionsmanagement im SWE-Prozess I |
294+
| | 16. Mai | Versionsmanagement im SWE_Pprozess II |
295+
| 8 | 19. Mai | Generics |
296+
| | 23. Mai | Container |
297+
| 9 | 26. Mai | UML Konzepte |
298+
| | 30. Mai | UML Diagrammtypen |
299+
| 10 | 2. Juni | UML Anwendungsbeispiel |
300+
| | 6. Juni | Testen |
301+
| 11 | 9. Juni | _Pfingstmontag_ |
302+
| | 13. Juni | Dokumentation und Build Toolchains |
303+
| 12 | 16. Juni | Continuous Integration in GitHub |
304+
| | 20. Juni | Delegaten |
305+
| 13 | 23. Juni | Events |
306+
| | 27. Juni | Threadkonzepte in C# |
307+
| 14 | 30. Juni | Taskmodell |
308+
| | 4. Juli | Design Pattern |
309+
| 15 | 7. Juli | Language Integrated Query |
310+
| | 11. Juli | GUI - MAUI (leider nicht geschafft) |
226311

227312

228313
## Aus die Maus

0 commit comments

Comments
 (0)