22
33author: Sebastian Zug, Galina Rudolf & André Dietrich
44email: sebastian.zug@informatik.tu-freiberg.de
5- version: 1.0.3
5+ version: 1.0.4
66language: de
77narrator: Deutsch Female
88comment: Zusammenfassung und Ausblick
1212import: https://github.com/liascript/CodeRunner
1313
1414import: 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
4439Wie gehen wir mit Schlüsseln, Passwörtern usw. in unseren Codes um?
@@ -85,144 +80,234 @@ Console.WriteLine(APIsecret);
8580
8681Lassen 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
9986using 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 ;
10987using System .Net ;
88+ using System .Text .Json ;
11089using 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 ($" \n Wetter 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 ($" \n Wetterdaten 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