I received a Tempest Weather Station for Father’s Day last year. However, I’m a designer and I’m unhappy with the appearance of the data display in the app. I wanted to give it some slick dials and nice typography and throw it in a web app wrapper on an older iPad I use as a display. Today I built a simple working prototype using the REST API and it works fine. However, I wasn’t happy with the update interval for wind speed. Then I learned about websockets, which I’ve never used before.
I built out a fairly simple example just displaying the air temp and RH. Didn’t even get into the rapid wind stuff yet. However, it’s outputting the wrong values. I fussed with it for hours, checked against repositories on Github and pulled their scripts that connect to websockets and parse their data to compare against. I could not find the issue. Even ChatGPT 4 seemed stumped. It’s like it’s pulling from a different station entirely? But it returns my accurate station ID. I wasn’t sure if it was returning some kind of test data because I was doing something wrong, so I tried changing my ID and tried changing my key. Either change seemed to halt the connection from feeding data, so it seemed like those were both fine, especially since they work with the REST API.
So I lurked around these forums, and found a user who posted a supposedly working example for a magic mirror project. I plugged in my key and station ID, and it was returning the same incorrect values: 56F and 88% humidity. It also displays the time as 5:38pm, and this value never changes. I checked the code and it’s correctly pulling from index 7 and 8 for air temp and RH, respectively.
Here is what the REST API returns with my personal info REDACTED:
{"elevation":REDACTED,"is_public":true,"latitude":REDACTED,"longitude":REDACTED,"obs":[{"air_density":1.26634,"air_temperature":1.2,"barometric_pressure":997.3,"brightness":1,"delta_t":0.2,"dew_point":0.8,"feels_like":1.2,"heat_index":1.2,"lightning_strike_count":0,"lightning_strike_count_last_1hr":0,"lightning_strike_count_last_3hr":0,"lightning_strike_last_distance":41,"lightning_strike_last_epoch":1705046530,"precip":0.0,"precip_accum_last_1hr":0.0,"precip_accum_local_day":0.0,"precip_accum_local_day_final":0.0,"precip_accum_local_yesterday":0.0,"precip_accum_local_yesterday_final":0.0,"precip_analysis_type_yesterday":0,"precip_minutes_local_day":0,"precip_minutes_local_yesterday":0,"precip_minutes_local_yesterday_final":0,"pressure_trend":"steady","relative_humidity":97,"sea_level_pressure":1023.8,"solar_radiation":0,"station_pressure":997.3,"timestamp":1706355133,"uv":0.0,"wet_bulb_globe_temperature":1.1,"wet_bulb_temperature":1.0,"wind_avg":0.3,"wind_chill":1.2,"wind_direction":316,"wind_gust":1.3,"wind_lull":0.0}],"outdoor_keys":["timestamp","air_temperature","barometric_pressure","station_pressure","pressure_trend","sea_level_pressure","relative_humidity","precip","precip_accum_last_1hr","precip_accum_local_day","precip_accum_local_day_final","precip_accum_local_yesterday_final","precip_minutes_local_day","precip_minutes_local_yesterday_final","wind_avg","wind_direction","wind_gust","wind_lull","solar_radiation","uv","brightness","lightning_strike_last_epoch","lightning_strike_last_distance","lightning_strike_count","lightning_strike_count_last_1hr","lightning_strike_count_last_3hr","feels_like","heat_index","wind_chill","dew_point","wet_bulb_temperature","wet_bulb_globe_temperature","delta_t","air_density"],"public_name":"REDACTED","station_id":REDACTED,"station_name":"REDACTED","station_units":{"units_direction":"cardinal","units_distance":"mi","units_other":"imperial","units_precip":"in","units_pressure":"inhg","units_temp":"f","units_wind":"mph"},"status":{"status_code":0,"status_message":"SUCCESS"},"timezone":"America/Chicago"}
Here is the code sample from these forums that I am using, with the CSS removed for clarity:
<!DOCTYPE html>
<html lang="en">
<head></head>
<script type="text/javascript">
var personal_token = 'TOKEN_REMOVED_BEFORE_POSTING_TO_FORUM'
var tempest_ID = 'ID_REMOVED_BEFORE_POSTING_TO_FORUM'
let socket = new WebSocket('wss://ws.weatherflow.com/swd/data?api_key=' + personal_token);
socket.onopen = function(e) {
socket.send('{"type":"listen_start",' + ' "device_id":' + tempest_ID + ',' + ' "id":"Tempest"}');
};
socket.onmessage = function(event) {
var obj = JSON.parse(event.data);
var date_time = obj.obs[0][0];
var date_time = parseInt(date_time);
var date_time = date_time*1000;
var date_time = new Date(date_time);
var date = date_time.toLocaleDateString();
var date = "On " + date;
var time = date_time.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
document.getElementById('Time').innerHTML = time;
var temp = obj.obs[0][7];
var temp = parseFloat(temp);
var temp = temp*9/5+32;
var temp = Math.round(temp);
var temp = temp + "°";document.getElementById('LocalTemp').innerHTML = temp;
var Speed = obj.obs[0][2];
var Speed = Math.round(Speed*2.24);
var Speed = Speed + " MPH";
document.getElementById('Speed').innerHTML = Speed;
var RHumid = obj.obs[0][8];
var RHumid = RHumid + " %";
document.getElementById('RHumid').innerHTML = RHumid;
};
function start() {
intervalID = setInterval(getData, 60000);
}
function getData(){
fetch('https://swd.weatherflow.com/swd/rest/better_forecast?station_id=ID_REMOVED_BEFORE_POSTING_TO_FORUM&token=TOKEN_REMOVED_BEFORE_POSTING_TO_FORUM')
.then((res) => res.json()).
then(function(res){currentConditions = res.forecast.daily[0].conditions;
precipPercent = (res.forecast.daily[0].precip_probability)+" %";
windDirection = res.current_conditions.wind_direction_cardinal;
precipAccum = ((res.current_conditions.precip_accum_local_day)/25.4)+" in.";
precipAccum = parseFloat(precipAccum);
precipAccum = precipAccum.toFixed(2);
document.getElementById('Conditions').innerHTML = currentConditions;
document.getElementById('Direction').innerHTML = windDirection;
document.getElementById('precipPercent').innerHTML = precipPercent;
document.getElementById('precipAccum').innerHTML = precipAccum;
})
};
</script>
<body onload="getData(); "start();">
<table class="center">
<tbody>
<tr>
<td id="Title">Current Conditions at </td>
<td id="Time"> </td>
</tr>
<tr>
<td rowspan="5" id="LocalTemp"> </td>
</tr>
<tr>
<td id="windTitle">Wind: </td>
<td id="Speed"> </td>
</tr>
<tr>
<td id="directionTitle">From the: </td>
<td id="Direction"> </td>
</tr>
<tr>
<td id="RHTitle"> RH: </td>
<td id="RHumid"> </td>
</tr>
<tr>
<td id="precipTitle"> Chance: </td>
<td id="precipPercent"> </td>
</tr>
<tr>
<td id="Conditions"></td>
<td id="precipAmtTitle"> Rain Today: </td>
<td id="precipAccum"></td>
</tr>
</tbody>
</table>
</body>
</html>
I hope that this is an easy one to figure out. Like I said, I am new to websockets, but this one is just strange. And yes, I’ve tried logging the data to the console and it matches the limited data displayed to screen. Here is the inner array from the obs object that the websocket is returning, if you need it. Even the battery voltage on 16 and the air pressure, etc don’t match my current station obs. It’s so weird!!
0 1668209895
1 null
2 null
3 null
4 null
5 300
6 976.1
7 12.1
8 88
9 0
10 0
11 0
12 0
13 0
14 0
15 0
16 2.11
17 1
18 0
19 0
20 0
21 0
Thanks! And if someone who works here wants to DM me (I assume that’s a thing on this forum) I can give you my personal info to help debug. Thanks again.