package main
import (
"encoding/json"
"log"
"net/url"
"time"
"github.com/gorilla/websocket"
)
const key = "mts_live_YOUR_KEY"
var channels = []string{"metar.obs.eglc", "metar.obs.rksi"}
type frame struct {
Type string `json:"type"`
Plan string `json:"plan,omitempty"`
Code string `json:"code,omitempty"`
Channel string `json:"channel,omitempty"`
Data struct {
Station string `json:"station"`
TempC string `json:"temp_c"`
ReportTime string `json:"report_time"`
Raw string `json:"raw"`
} `json:"data,omitempty"`
}
func stream() error {
u := url.URL{Scheme: "wss", Host: "stream.metar.ws", Path: "/v1/ws",
RawQuery: url.Values{"key": {key}}.Encode()}
ws, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
return err
}
defer ws.Close()
var ack frame
if err := ws.ReadJSON(&ack); err != nil {
return err
}
log.Printf("connected: plan=%s", ack.Plan)
sub := map[string]any{"action": "subscribe", "channels": channels}
if err := ws.WriteJSON(sub); err != nil {
return err
}
for {
var msg frame
if err := ws.ReadJSON(&msg); err != nil {
return err
}
switch msg.Type {
case "publication":
log.Printf("%s: %s degC at %s", msg.Data.Station, msg.Data.TempC, msg.Data.ReportTime)
case "error":
log.Printf("error: %s %s", msg.Code, msg.Channel)
}
}
}
func main() {
for { // reconnect loop
if err := stream(); err != nil {
log.Printf("disconnected: %v, reconnecting in 3s", err)
}
time.Sleep(3 * time.Second)
}
}
On the Sandbox plan, subscribe to
sandbox.demo instead and trigger a message with Send test alert on the Billing page in the portal.Python
The same client using websockets
Node.js
The same client using ws
Browser
A minimal client for internal dashboards
