For the smartthermostat I’m working on, I was looking for a way to get the outside temperature without placing a real sensor outside.

There exists services like openweathermap that can be useful for this. But I’ve found another way that seems (subjective feeling) to be more accurate to me.

Airports reports weather information using the metar format. This metar information is available for all airports at https://tgftp.nws.noaa.gov/data/observations/metar/stations/.

For example EBAW is the airport at Belgium Antwerp (Deurne) which is close to the village where I live.

By parsing the content, I can get the outside temperature.

My solution in java:

package be.janwagemakers;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

public class Main {

    public static void main(String[] args) {
        Metar metar = new Metar();
        metar.update("EBAW");
        System.out.println("T=" + metar.getTemperature() + "°C P=" + metar.getPressure() + "hPa");
    }
}
package be.janwagemakers;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

public class Metar {

    private int temperature;
    private int pressure;

    public void update(String airport) {
        try {
            URL url = new URL("https://tgftp.nws.noaa.gov/data/observations/metar/stations/" + airport + ".TXT");
            BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));

            int counter = 0;
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                // System.out.println(counter + " " + inputLine);
                // inputLine="EBAW 112220Z AUTO 27003KT 9999 // FEW028/// M05/02 Q1032";
                if (counter == 1) {
                    for (int i = 0; i < inputLine.length() - 4; i++) {
                        char c = inputLine.charAt(i);
                        char c1 = inputLine.charAt(i + 1);
                        char c2 = inputLine.charAt(i + 2);
                        char c3 = inputLine.charAt(i + 3);
                        char c4 = inputLine.charAt(i + 4);
                        if ((c == ' ' || c == 'M') && Character.isDigit(c1) && Character.isDigit(c2) && c3 == '/') {
                            temperature = Integer.parseInt("" + c1 + c2);
                            if (c == 'M') temperature = temperature * -1;
                        }
                        if ((c == 'Q' || c == 'A') && Character.isDigit(c1) && Character.isDigit(c2) && Character.isDigit(c3) && Character.isDigit(c4)) {
                            pressure = Integer.parseInt("" + c1 + c2 + c3 + c4);
                            if (c == 'A') {
                                float p = pressure * 1.3333f * 25.4f / 100; // hg -> hectopascal / inch -> mm
                                pressure = Math.round(p);
                            }
                        }
                    }
                }
                counter++;
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public int getTemperature() {
        return temperature;
    }

    public int getPressure() {
        return pressure;
    }
}

Also available at gitlab.


Comments