Web Socket Retrieving Incorrect Data

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 + "&deg";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&nbsp;</td>
			<td id="Time"> </td>
		</tr>
		<tr>
			<td rowspan="5" id="LocalTemp"> </td>
		</tr>
		<tr>
			<td id="windTitle">Wind:&nbsp; </td>
			<td id="Speed"> </td>
		</tr>
		<tr>
			<td id="directionTitle">From the:&nbsp; </td>
			<td id="Direction"> </td>
		</tr>
		<tr>
			<td id="RHTitle"> RH:&nbsp;</td>
			<td id="RHumid"> </td>
		</tr>
		<tr>
			<td id="precipTitle"> Chance:&nbsp;</td>
			<td id="precipPercent"> </td>
		</tr>
		<tr>
			<td id="Conditions"></td>
			<td id="precipAmtTitle"> Rain Today:&nbsp;</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.

I never used websocket before, but I tried your example (leaving out the parts that deviate from the metric system) and I checked that my temperature and humidity are spot on. Did you perhaps mix up the device id with the station id somewhere?
Perhaps first try it with the rest api (use the online working interface by hitting the API button on the top of this page.

Thanks for responding, but I just can’t figure this out. I’ve quintuple checked my station ID and personal token and even generated a new token and nothing seems to work. What’s strange is when I iterate up my station ID, such as adding 1 to it, within the first 5-6 times of doing this, I get different condition results back. How is that possible if this is authorized by my personal token? It should only give results for my station ID. And the station ID itself, it’s in the URL for your station, correct? Such as https://tempestwx.com/station/XXXXXX/ where the six X’s are my station ID. Because that has the correct data there. And before I built the web socket version, I built the REST version and it connects fine, using the same key and station ID, and it accurately shows the conditions. It just doesn’t update frequently enough for wind. This is really driving me crazy…

OK I have a solution. I was digging through the code of the weewx websocket driver on GitHub here (GitHub - livysdad27/tempestWS: Weatherflow Tempest WebSocket Driver) trying to figure out what I was missing and noticed in the ReadMe it noted “Note that your device ID is different than the ST number or the station ID ou may see in your device’s website or mobile application. You can find the correct id under the settings → stations → your station name → status options in your app.” and sure enough under Device ID was this weird ID I’ve never seen before.

So what I don’t get, then, is why does the REST API work fine with my Station ID but the WS needs a Device ID? I think that’s what was causing me problems because I built it using the REST API first which worked fine but then WS wasn’t working. Also confusing is how the WS was returning some random data for my Station ID which makes it even more confusing, because shouldn’t it return no data if the ID and token don’t match? This is all very confusing to me.

1 Like

I think the device ID is used because it allows you to choose the proper device in a multi-device station.

3 Likes

Glad you found out that you did mix up device id with station id.
When I run your code I get the correct results but I always get (using the browser’s debugger)
Uncaught TypeError: obj.obs is undefined

onmessage file:///C:/Users/frans/Desktop/ws.html:13

EventHandlerNonNull* file:///C:/Users/frans/Desktop/ws.html:11

2 [ws.html:13:19](file:///C:/Users/frans/Desktop/ws.html)

onmessage file:///C:/Users/frans/Desktop/ws.html:13

(Async: EventHandlerNonNull)
file:///C:/Users/frans/Desktop/ws.html:11

when I change the device id and station id to something non-existent I get in addition to that:
Uncaught (in promise) TypeError: res.forecast is undefined
getData file:///C:/Users/frans/Desktop/ws.html:38
promise callback*getData file:///C:/Users/frans/Desktop/ws.html:38
onload file:///C:/Users/frans/Desktop/ws.html:1

and it doesn’t print any data.
Hope that helps, as I’m not a web developper at all, so I don’t know what is going on here.