[Modul] OpenWeatherMap

Ich hab das alles in einer Datei:

<html>
	<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
	<script src="https://code.highcharts.com/highcharts.js"></script>
	<script src="https://code.highcharts.com/modules/windbarb.js"></script>
	<script src="https://code.highcharts.com/modules/exporting.js"></script>
	<script src="https://highcharts.github.io/pattern-fill/pattern-fill-v2.js"></script>
	<script src="https://github.com/highcharts/highcharts/blob/master/js/themes/dark-unica.js"></script>
	<div id="container" style="max-width: 800px; min-width: 380px; height: 300px; margin: 0 auto">
		<div style="margin-top: 100px; text-align: center" id="loading">
			<i class="fa fa-spinner fa-spin"></i> Lade Daten vom Wetterdienst
		</div>
	</div>
	
	<script>
	function Meteogram(xml, container) {
		// Parallel arrays for the chart data, these are populated as the XML/JSON file
		// is loaded
		this.symbols = [];
		this.precipitations = [];
		this.precipitationsError = []; // Only for some data sets
		this.winds = [];
		this.temperatures = [];
		this.pressures = [];
		// Initialize
		this.xml = xml;
		this.container = container;
		// Run
		this.parseYrData();
	}
	/**
	 * Function to smooth the temperature line. The original data provides only whole degrees,
	 * which makes the line graph look jagged. So we apply a running mean on it, but preserve
	 * the unaltered value in the tooltip.
	 */
	Meteogram.prototype.smoothLine = function (data) {
		var i = data.length,
			sum,
			value;
		while (i--) {
			data[i].value = value = data[i].y; // preserve value for tooltip
			// Set the smoothed value to the average of the closest points, but don't allow
			// it to differ more than 0.5 degrees from the given value
			sum = (data[i - 1] || data[i]).y + value + (data[i + 1] || data[i]).y;
			data[i].y = Math.max(value - 0.5, Math.min(sum / 3, value + 0.5));
		}
	};
	/**
	 * Draw the weather symbols on top of the temperature series. The symbols are
	 * fetched from yr.no's MIT licensed weather symbol collection.
	 * https://github.com/YR/weather-symbols
	 */
	Meteogram.prototype.drawWeatherSymbols = function (chart) {
		var meteogram = this;
		$.each(chart.series[0].data, function (i, point) {
			if (meteogram.resolution > 36e5 || i % 2 === 0) {
				chart.renderer
					.image(
						'https://cdn.jsdelivr.net/gh/YR/weather-symbols@6.0.2/dist/svg/' +
							meteogram.symbols[i] + '.svg',
						point.plotX + chart.plotLeft - 8,
						point.plotY + chart.plotTop - 30,
						30,
						30
					)
					.attr({
						zIndex: 5
					})
					.add();
			}
		});
	};
	/**
	 * Draw blocks around wind arrows, below the plot area
	 */
	Meteogram.prototype.drawBlocksForWindArrows = function (chart) {
		var xAxis = chart.xAxis[0],
			x,
			pos,
			max,
			isLong,
			isLast,
			i;
		for (pos = xAxis.min, max = xAxis.max, i = 0; pos <= max + 36e5; pos += 36e5, i += 1) {
			// Get the X position
			isLast = pos === max + 36e5;
			x = Math.round(xAxis.toPixels(pos)) + (isLast ? 0.5 : -0.5);
			// Draw the vertical dividers and ticks
			if (this.resolution > 36e5) {
				isLong = pos % this.resolution === 0;
			} else {
				isLong = i % 2 === 0;
			}
			chart.renderer.path(['M', x, chart.plotTop + chart.plotHeight + (isLong ? 0 : 28),
				'L', x, chart.plotTop + chart.plotHeight + 32, 'Z'])
				.attr({
					'stroke': chart.options.chart.plotBorderColor,
					'stroke-width': 1
				})
				.add();
		}
		  // Center items in block
		chart.get('windbarbs').markerGroup.attr({
			translateX: chart.get('windbarbs').markerGroup.translateX + 8
		});
	};
	/**
	 * Get the title based on the XML data
	 */
	Meteogram.prototype.getTitle = function () {
		return 'Meteogram für ' + this.xml.querySelector('location name').textContent +
			', ' + this.xml.querySelector('location country').textContent;
	};
	/**
	 * Build and return the Highcharts options structure
	 */
	Meteogram.prototype.getChartOptions = function () {
		var meteogram = this;
		return {
			chart: {
				renderTo: this.container,
				marginBottom: 70,
				marginRight: 40,
				marginTop: 50,
				plotBorderWidth: 1,
				height: 270,
				alignTicks: false,
				scrollablePlotArea: {
					minWidth: 720
				}
			},
			defs: {
				patterns: [{
					'id': 'precipitation-error',
					'path': {
						d: [
							'M', 3.3, 0, 'L', -6.7, 10,
							'M', 6.7, 0, 'L', -3.3, 10,
							'M', 10, 0, 'L', 0, 10,
							'M', 13.3, 0, 'L', 3.3, 10,
							'M', 16.7, 0, 'L', 6.7, 10
						].join(' '),
						stroke: '#68CFE8',
						strokeWidth: 1
					}
				}]
			},
			title: {
				text: this.getTitle(),
				align: 'left',
				style: {
					whiteSpace: 'nowrap',
					textOverflow: 'ellipsis'
				}
			},
			tooltip: {
				shared: true,
				useHTML: true,
				headerFormat:
					'<small>{point.x:%A, %b %e, %H:%M} - {point.point.to:%H:%M}</small><br>' +
					'<b>{point.point.symbolName}</b><br>'
			},
			xAxis: [{ // Bottom X axis
				type: 'datetime',
				tickInterval: 2 * 36e5, // two hours
				minorTickInterval: 36e5, // one hour
				tickLength: 0,
				gridLineWidth: 1,
				gridLineColor: (Highcharts.theme && Highcharts.theme.background2) || '#F0F0F0',
				startOnTick: false,
				endOnTick: false,
				minPadding: 0,
				maxPadding: 0,
				offset: 30,
				showLastLabel: true,
				labels: {
					format: '{value:%H}'
				},
				crosshair: true
			}, { // Top X axis
				linkedTo: 0,
				type: 'datetime',
				tickInterval: 24 * 3600 * 1000,
				labels: {
					format: '{value:<span style="font-size: 12px; font-weight: bold">%a</span> %b %e}',
					align: 'left',
					x: 3,
					y: -5
				},
				opposite: true,
				tickLength: 20,
				gridLineWidth: 1
			}],
			yAxis: [{ // temperature axis
				title: {
					text: null
				},
				labels: {
					format: '{value}°',
					style: {
						fontSize: '10px'
					},
					x: -3
				},
				plotLines: [{ // zero plane
					value: 0,
					color: '#BBBBBB',
					width: 1,
					zIndex: 2
				}],
				maxPadding: 0.3,
				minRange: 8,
				tickInterval: 1,
				gridLineColor: (Highcharts.theme && Highcharts.theme.background2) || '#F0F0F0'
			}, { // precipitation axis
				title: {
					text: null
				},
				labels: {
					enabled: false
				},
				gridLineWidth: 0,
				tickLength: 0,
				minRange: 10,
				min: 0
			}, { // Air pressure
				allowDecimals: false,
				title: { // Title on top of axis
					text: 'hPa',
					offset: 0,
					align: 'high',
					rotation: 0,
					style: {
						fontSize: '10px',
						color: Highcharts.getOptions().colors[2]
					},
					textAlign: 'left',
					x: 3
				},
				labels: {
					style: {
						fontSize: '8px',
						color: Highcharts.getOptions().colors[2]
					},
					y: 2,
					x: 3
				},
				gridLineWidth: 0,
				opposite: true,
				showLastLabel: false
			}],
			legend: {
				enabled: false
			},
			plotOptions: {
				series: {
					pointPlacement: 'between'
				}
			},
			series: [{
				name: 'Temperature',
				data: this.temperatures,
				type: 'spline',
				marker: {
					enabled: false,
					states: {
						hover: {
							enabled: true
						}
					}
				},
				tooltip: {
					pointFormat: '<span style="color:{point.color}">\u25CF</span> ' +
						'{series.name}: <b>{point.value}°C</b><br/>'
				},
				zIndex: 1,
				color: '#FF3333',
				negativeColor: '#48AFE8'
			}, {
				name: 'Precipitation',
				data: this.precipitationsError,
				type: 'column',
				color: 'url(#precipitation-error)',
				yAxis: 1,
				groupPadding: 0,
				pointPadding: 0,
				tooltip: {
					valueSuffix: ' mm',
					pointFormat: '<span style="color:{point.color}">\u25CF</span> ' +
						'{series.name}: <b>{point.minvalue} mm - {point.maxvalue} mm</b><br/>'
				},
				grouping: false,
				dataLabels: {
					enabled: meteogram.hasPrecipitationError,
					formatter: function () {
						if (this.point.maxvalue > 0) {
							return this.point.maxvalue;
						}
					},
					style: {
						fontSize: '8px',
						color: 'gray'
					}
				}
			}, {
				name: 'Precipitation',
				data: this.precipitations,
				type: 'column',
				color: '#68CFE8',
				yAxis: 1,
				groupPadding: 0,
				pointPadding: 0,
				grouping: false,
				dataLabels: {
					enabled: !meteogram.hasPrecipitationError,
					formatter: function () {
						if (this.y > 0) {
							return this.y;
						}
					},
					style: {
						fontSize: '8px',
						color: 'gray'
					}
				},
				tooltip: {
					valueSuffix: ' mm'
				}
			}, {
				name: 'Air pressure',
				color: Highcharts.getOptions().colors[2],
				data: this.pressures,
				marker: {
					enabled: false
				},
				shadow: false,
				tooltip: {
					valueSuffix: ' hPa'
				},
				dashStyle: 'shortdot',
				yAxis: 2
			}, {
				name: 'Wind',
				type: 'windbarb',
				id: 'windbarbs',
				color: Highcharts.getOptions().colors[1],
				lineWidth: 1.5,
				data: this.winds,
				vectorLength: 18,
				yOffset: -15,
				tooltip: {
					valueSuffix: ' m/s'
				}
			}]
		};
	};
	/**
	 * Post-process the chart from the callback function, the second argument to Highcharts.Chart.
	 */
	Meteogram.prototype.onChartLoad = function (chart) {
		this.drawWeatherSymbols(chart);
		this.drawBlocksForWindArrows(chart);
	};
	/**
	 * Create the chart. This function is called async when the data file is loaded and parsed.
	 */
	Meteogram.prototype.createChart = function () {
		var meteogram = this;
		this.chart = new Highcharts.Chart(this.getChartOptions(), function (chart) {
			meteogram.onChartLoad(chart);
		});
	};
	Meteogram.prototype.error = function () {
		$('#loading').html('<i class="fa fa-frown-o"></i> Fehler beim Laden der Daten. Bitte versuchen Sie es später noch einmal.');
	};
	/**
	 * Handle the data. This part of the code is not Highcharts specific, but deals with yr.no's
	 * specific data format
	 */
	Meteogram.prototype.parseYrData = function () {
		var meteogram = this,
			xml = this.xml,
			pointStart,
			forecast = xml && xml.querySelector('forecast');
		if (!forecast) {
			return this.error();
		}
		// The returned xml variable is a JavaScript representation of the provided
		// XML, generated on the server by running PHP simple_load_xml and
		// converting it to JavaScript by json_encode.
		Highcharts.each(
			forecast.querySelectorAll('tabular time'),
			function (time, i) {
				// Get the times - only Safari can't parse ISO8601 so we need to do
				// some replacements
				var from = time.getAttribute('from') + ' UTC',
					to = time.getAttribute('to') + ' UTC';
				from = from.replace(/-/g, '/').replace('T', ' ');
				from = Date.parse(from);
				to = to.replace(/-/g, '/').replace('T', ' ');
				to = Date.parse(to);
				if (to > pointStart + 4 * 24 * 36e5) {
					return;
				}
				// If it is more than an hour between points, show all symbols
				if (i === 0) {
					meteogram.resolution = to - from;
				}
				// Populate the parallel arrays
				meteogram.symbols.push(
					time.querySelector('symbol').getAttribute('var')
						.match(/[0-9]{2}[dnm]?/)[0]
				);
				meteogram.temperatures.push({
					x: from,
					y: parseInt(
						time.querySelector('temperature').getAttribute('value'),
						10
					),
					// custom options used in the tooltip formatter
					to: to,
					symbolName: time.querySelector('symbol').getAttribute('name')
				});
				var precipitation = time.querySelector('precipitation');
				meteogram.precipitations.push({
					x: from,
					y: parseFloat(
						Highcharts.pick(
							precipitation.getAttribute('minvalue'),
							precipitation.getAttribute('value')
						)
					)
				});
				if (precipitation.getAttribute('maxvalue')) {
					meteogram.hasPrecipitationError = true;
					meteogram.precipitationsError.push({
						x: from,
						y: parseFloat(precipitation.getAttribute('maxvalue')),
						minvalue: parseFloat(precipitation.getAttribute('minvalue')),
						maxvalue: parseFloat(precipitation.getAttribute('maxvalue')),
						value: parseFloat(precipitation.getAttribute('value'))
					});
				}
				if (i % 2 === 0) {
					meteogram.winds.push({
						x: from,
						value: parseFloat(time.querySelector('windSpeed')
							.getAttribute('mps')),
						direction: parseFloat(time.querySelector('windDirection')
							.getAttribute('deg'))
					});
				}
				meteogram.pressures.push({
					x: from,
					y: parseFloat(time.querySelector('pressure').getAttribute('value'))
				});
				if (i === 0) {
					pointStart = (from + to) / 2;
				}
			}
		);
		// Smooth the line
		this.smoothLine(this.temperatures);
		// Create the chart when the data is loaded
		this.createChart();
	};
	// End of the Meteogram protype
	 // On DOM ready...
	// Set the hash to the yr.no URL we want to parse
	var place,
		url;
	if (!location.hash) {
		place = 'Germany/North_Rhine-Westphalia/Bonn';
		location.hash = 'https://www.yr.no/place/' + place + '/forecast_hour_by_hour.xml';
	}
	// Then get the XML file through Highcharts' CORS proxy. Our proxy is limited to
	// this specific location. Useing the third party, rate limited cors.io service
	// for experimenting with other locations.
	url = location.hash.substr(1);
	$.ajax({
		dataType: 'xml',
		url: url === 'https://www.yr.no/place/Germany/North_Rhine-Westphalia/Bonn/forecast_hour_by_hour.xml' ?
			'https://www.highcharts.com/samples/data/cors.php?url=' + url :
			'https://cors.io/?' + url,
		success: function (xml) {
			window.meteogram = new Meteogram(xml, 'container');
		},
		error: Meteogram.prototype.error
	});
	</script>
</html>
1 „Gefällt mir“

@nws - Danke. Tja schade die Sache mit dem Proxy. Leider bekomme ich auch die Fehlermeldung.

Fehler_Datei.PNG

Es geht mir um die Formatierung der Variable „Zusammenfassung des Wetters“.
Die Einheiten sind bei mir um eine Zeile verrutscht. Ist das bei Euch auch so?

Gruß,
Michael

Nach einem Tipp von tomschl bin ich jetzt umgestiegen auf diese Lösung hier:

Meteogram Weather Charts Generator with Interactive Map

only £0.001 per API call
500 free API calls per month
seven-day free trial

sieht dann z.B. so aus:

https://nodeserver.cloud3squared.com/getMeteogram/{"theme"%3A"dark-gradient"%2C"chartFontGroup"%3A"Noto"}

Ist für ganz kleines Geld zu haben, kann super angepasst werden und man kann die Daten auch vom DWD beziehen.

Hallo,
ich habe heute nach etwas längererzeit meine Module aktualisiert und bekomme bei Abruf der Daten von Openweather einen Fehler bei der Windstärke und bei Windstärke als Text.

openweather-fehler1.png

Bei Aktivierung der Variable Windstärke als Text kommt folgender Fehler.

Im Objektbau wird die Variable in englicher Sprache jetzt eingetragen. Jetzt „Windstrength“ vorher „Windstärke“

Demel kannst Du wenn Zeit ist bitte einmal schauen was geändert wurde.
Ich habe die Windstärke vorerst deaktiviert.

Desweiteren ist mir noch aufgefallen, dass neu aktivierte Optionen z.B Wetterbedingungen nicht mehr in der angegeben Sprache übersetzt werden.
Im Objektbaum steht hier jetzt die engl. Bezeichnung Conditions.

Grüße aus Gera
Thomas

ich habe meine Module auf ‚stritt_types‘ umgestellt und da kommen ab und dan Fehler raus, die mir bei Tests nicht aufgefallen sind
ist gefixed mit 1.18

das ist bei mir nicht nachvollziehbar, ich habe die Variablen frisch angelegt und die sind in D, sowohl die Variable als auch der Inhalt.


Gruß
demel

Hallo

Danke für die schnelle Hilfe. Nach den Aktivieren der beiden Parameter sind die Fehlermeldungen weg.
Leider das mit der Übersetzung noch nicht.
Der Variablenname kommt bei beiden in Englisch. Der Inhalt bei Winstärke in englisch , bei Wetterdedingung in Deutsch.

IPS Version 5.2

Gruß Thomas

hallo,

zu der Übersetzung habe ich keine Idee, Es scheint so zu sein, das bei dir Translate() nicht (mehr) richtig funktioniert.
In dem locale.json sind alle Übersetzungen drin, auch die Windstärke-Texte - funktioniert ja auch bei mir. Das die Bedingungen auf D erscheinen kommt daher, das der Text von OpenWeather so geliefert wird.

Translate() wird ja gesteuert über die Spracheinstellung des IPs-Servers. Wie steh denn bei dir die Systemsprache?

gruß
demel

Hallo demel,

Du hast recht der Fehler lag an der locale. Das umstellen über die armbian-config hat immer einen Fehler im Hintergrund ausgegeben, den ich nicht sofort bemerkt habe. Habe jetzt die locale von Hand gefüllt und es geht.

Danke
Thomas

Hallo,

ich stelle gerade mein IPS auf ipvccu um. Obwohl alles auf Deutsch eingestellt ist, bekomme ich die Variablennamen und Einheiten in Englisch. Wo muss da ggf. noch etwas nachjustiert werden?

Gruß
Marc

Falls die Frage kommt, ob ich auch de eingestellt habe:
root@tinkerboard:/# echo $LANG
de_DE.UTF-8
root@tinkerboard:/#

Spracheinstellung in der Instanz auf „de“ :wink:

Die Instanz nutzt eine eigene Konfiguration und nicht das Betriebssystem.

Danke für den Hinweis. Steht aber auf „de“.

Hallo,

die Frage kann ich dir leider nicht beantworten, hat mix mit dem Modul zu tun. Vielleicht hat den Vor-Poster eine Idee.

Nur für den Fall, das es relevant ist: wenn eine Variable bzw ein Variablenprofil einmal angelegt ist, wird es nicht mehr geändert, man muss die Variable/das Profil löschen.

Gruß
demel

Die Variablen habe ich auch schon gelöscht und auch das Modul bzw. die Instanz. Kommt aber alles in Englisch wieder.
Was ist mit Profil gemeint?

Mit welchem Browser nutzt Du denn die Webconsole, auf was sind in dem Browser die Spracheinstellungen gesetzt?

Variablenprofil, das kannst Du individuell anpassen bzw. Dir auch ein eigenes Variablenprofil zuweisen. Die Variable kannst Du auch umbenennen, das ist einem Modul egal, die Identifikation erfolgt über die Ident nicht den Variablennamen.

Ich benutze ein und denselben Browser für beide Symcon Verwaltungskonsolen.
Eine Konsole (Docker) wird abgelöst von der neuen Konsole Tinkerboard mit ipvccu. Ich habe die neue Konsole komplett neu und zu Fuß angelegt. Da ist also nichts kopiert. Mir war das aber auch schon bei dem „Discovergy-Modul“ (Stromzähler) aufgefallen. Auch da waren die Variablen in Englisch. Das hatte ich aber nicht weiter beachtet, da ich dachte, dass das mit dem Update der API Daten von Discovergy zusammenhing.
Die Konsole selber redet ja auch Deutsch mit mir und wie schon erwähnt, ist bei Eingabe des Befehls ‚echo $LANG‘ die Ausgabe, dass das Betriebssystem ebenfalls auf Deutsch ‚de_DE.UTF-8‘ eingestellt ist.
Das Umbennenen der Variablen bringt mir auch nichts, da bei diesem Modul dann auch die Textausgaben in Englisch sind. Und letztere kann ich nicht damit beeinflussen.
Es wird da wohl in einer versteckten Datei unter ipvccu noch eine Änderung gemacht werden müssen.

Gruß
Marc

Die Konsole wird doch nicht bei dir ersetzt. Sondern der Dienst selber.
Die Konsole richtet sich bei der Sprache nach dem Browser bzw. der Sprache von dem OS unter welchen du den Browser nutzt.

Der Dienst, und somit die Benennung von Variablen erfolgt auf Basis der Sprache vom Host unter dem der Symcon Dienst läuft.
Da scheint bei dir irgendwas nicht zu stimmen.
Hier ist es wichtig, dass der User unter dem der Dienst läuft, auf deutsch steht.

Der Inhalt von String Variablen wiederum kann irgendwas sein.
Manchmal wird es auf Basis der Sprache vom Dienst übersetzt (wie auch die Profile). Oder wie hier durch eine Einstellung im Modul, da diese Daten aus der verwendeten API kommen und bestimmte Sprachen unterstützen.
Wichtig ist nicht alles über den Kamm zu scheren, sondern differenziert zu schauen.
Michael

Ok. Das habe ich verstanden. Wie finde ich denn heraus, unter welchem user der Dienst installiert wurde?
Mit dem Befehl: ‚less /etc/group‘ sehe ich nur root und einen Benutzer auf dem IPS mWn. installiert wurde.
Beide sind auf deutsch eingestellt.

Da auf meiner pivccu nichts läuft außer dem CCU3 Container, keine Ahnung :slight_smile:
Unter Linux habe ich IPS bisher auf dem Rpi mit dem empfohlen Image und unter Ubuntu getestet, das Image der pivccu für das Tinkerboard kenne ich nicht.
Und Linux Guru bin ich auch kein Stück…
Michael

Mein Hilfegesuch war auch nicht an eine Person gebunden. Vielleicht hat da noch einer eine Idee. Der Einsatz eines Tinkerboards mit pivccu3 ist ja durchaus gängig.
VG
Marc