Get Weather data from OGN - thezenox/breezedude GitHub Wiki
I got some requests asking how to integrate Breezedude data (or FANET based wind stations in general) to websites showing wind data. It is easy, use OGN. No 3rd party API keys or dependencies required.
I will not support adding OGN data to weatherunderground or similar platforms with very restricted data sharing policies. If you want your favorite wind website to include breezedude data, send them a link to this page.
Here is a simple nodeJS example on how to parse weather station data and station names
const net = require('node:net');
// Todo: send heartbeat to avoid 48h disconnect
let host = 'aprs.glidernet.org';
let port_filter = 14580;
let login = "user N0CALL pass -1 vers node-ogn-client 0.1 filter p/FNT\n"
var pattern_ws = /(?<name>.*)>.*,(?<received_by>.*):\/(?<time>(([0-1]\d|2[0-3])[0-5]\d[0-5]\dh|([0-2]\d|3[0-1])([0-1]\d|2[0-3])[0-5]\dz))(?<latitude>9000\.00|[0-8]\d{3}\.\d{2})(?<latitude_sign>N|S)(?<symbol_table>.)(?<longitude>18000\.00|1[0-7]\d{3}\.\d{2}|0\d{4}\.\d{2})(?<longitude_sign>E|W)(?<symbol>.)(?<wind_direction>(\d{3}|\.{3}))\/(?<wind_speed>(\d{3}|\.{3}))g(?<wind_speed_peak>(\d{3}|\.{3}))t(?<temperature>(\d{3}|\.{3}))(r(?<rainfall_1h>\d{3}))?(p(?<rainfall_24h>\d{3}))?(h(?<humidity>\d{2}))?(b(?<barometric_pressure>\d{5}))?(?:\s(?<comment>.*))/;
var pattern_name = /(?<name>.*)>.*,(?<received_by>.*):>(?<time>(([0-1]\d|2[0-3])[0-5]\d[0-5]\dh|([0-2]\d|3[0-1])([0-1]\d|2[0-3])[0-5]\dz)) Name="(?<station_name>.*?)( \((?<alt>\d{1,4})m\))?"(?:\s(?<comment>.*))/;
let reconnectDelay = 1000; // initial delay
const maxReconnectDelay = 30000;
async function process_data(a) {
// console.log(a.toString())
// get weather data message
let r = a.toString().match(pattern_ws);
if (r) {
//console.log([r.groups])
let data = {};
data.name = r.groups.name;
data.time = new Date().toUTCString();
data.lat = parseFloat((r.groups.latitude).slice(0,2))+ parseFloat(r.groups.latitude.slice(2,7))/60;
if(r.groups.latitude_sign == 'S'){ data.lat = -data.lat;}
data.lon= parseFloat(r.groups.longitude.slice(0,3))+ parseFloat(r.groups.longitude.slice(3,8))/60;
if(r.groups.longitude_sign == 'W'){ data.lon = -data.lon;}
data.wind_dir = parseFloat(r.groups.wind_direction);
data.wind_speed = parseFloat(r.groups.wind_speed) * 0.5144/0.27778;
data.wind_gust = parseFloat(r.groups.wind_speed_peak) * 0.5144/0.27778;
data.temp = (5/9) * (parseFloat(r.groups.temperature) - 32)
data.humd = parseFloat(r.groups.humidity);
data.baro = parseFloat(r.groups.barometric_pressure)/10;
console.log(data);
// handle data storage
// Get name message
} else{
let r = a.toString().match(pattern_name);
if (r) {
console.log(r.groups)
// handle name matching
}
}
}
function makeConnection() {
const socket = new net.Socket();
socket.on('connect', () => {
console.log('OGN connected');
reconnectDelay = 1000; // reset delay on success
socket.write(login);
});
socket.on('data', (data) => {
process_data(data);
});
socket.on('end', () => {
console.log('OGN ended');
});
socket.on('timeout', () => {
console.log('OGN timeout');
socket.destroy();
});
socket.on('error', (err) => {
console.log('Error connecting to Server on host:', host, 'port:', port_filter, err.message);
socket.destroy();
});
socket.on('close', (hadError) => {
console.log('Connection closed. Reconnecting in', reconnectDelay, 'ms...');
setTimeout(makeConnection, reconnectDelay);
reconnectDelay = Math.min(reconnectDelay * 2, maxReconnectDelay); // exponential backoff
});
socket.connect(port_filter, host);
}
makeConnection();