Current conditions?

I’ve written a little HTML/Javascript page to display on my Magic Mirror (https://magicmirror.builders/) that includes some basic data (air temp, wind speed, RH, etc.) from my Tempest. I see from my public data page that it includes “current conditions”. However, I don’t see that field on the list for the Tempest using the websocket API. Just wondering where I go about getting that information??? Thanks in advance for any guidance!

You can get the current conditions from the forecast REST API endpoint. The current conditions are not available in the websocket packets.

OK…thanks for the reply.

So, where would one buy the mirror hardware? Is where to buy the mirror hardware described anywhere in the linked documents?

The Magic Mirror is pretty much a DIY project involving a monitor, mirror (optional) and a Raspberry Pi (although it will run on other platforms). The only commercial product that I know of that’s similar is DAKboard (DAKboard - A customizable display for your photos, calendar, news, weather and more!).

Thank you for the info. So, when I looked at the Magic Mirror project I only saw software… is that all that it is? One would have to figure out from scratch how to create the mirror hardware, if not using a monitor? (I’m using a Sceptre 20" monitor, currently, that I hung on my wall with a special bracket.)

Yes, it’s primarily software. It installs on a Raspberry Pi connected to a monitor. There are default modules to do basic things like time, calendar, weather, stocks, etc. There are dozens of third-party modules for doing a wide-range of things. The user community is very active and, I’ve found to be, very helpful.

yup… I’m using a raspberry pi and a monitor to display my stock portfolio and the tempest weather using java software that I wrote… so I was interested in the mirror hardware to potentially replace the monitor.

@dwburger
I am playing around with a new magic mirror setup as well. For you to get some of the Tempest data displayed on the MM did you use any of the default weather modules or did you have to create this all from scratch?

Any info would be much appreciated.

I used the MMM-Widget module to get Tempest data displayed on my MM2. MMM-Widget allows you to insert HTML/Javascript code into its “config” section. I wrote some simple/basic HTML/Javascript code to access the Tempest data I wanted to display (e.g. air temp, windspeed, wind direction, RH, chance of rain and total rain today). That HTML/Javascript code was then inserted into the “html” part of the MMM-Widget config. I got the HTML/Javascript running on its own before inserting it into the MMM-Widget module. To get that accomplished I had to basically put all the code on a single line (e.g. no line feeds, etc.).

@dwburger Do you mind sharing the HTML/Javascript code that you created? I wanted to try using this on a simple webpage to pull data from my Tempest. And thank you for bringing up the MagicMirror project. I hadn’t seen this and will be checking this out too.

Sure…I’ve pasted the code I placed in the MM2 config.sys file below. Since MMM-Widget struggles with code that is formatted to be easily read, the code below is hard to read. However, it works. I’ve removed my personal key information.

{
  module: "MMM-Widget",
  config: {
    widgets: [
      {
        html:`
<head>
<meta charset="utf-8">
<style>
body {background-color:#cedcf2;font-family: Arial;color: #336699;font-size: 10px;}
table.center {margin-left:auto;margin-right:auto;}
.column {float: left;width: 25%;padding: 10px;height: 10px;}
.justRight {text-align:right;}
#Title{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 25px;text-align: right;}
#Time{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 25px;align-content: left;}
#tempTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 20px;text-align: right;
padding: 5px 0;}
#LocalTemp{align-content: left;background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 90px;
font-weight:bold; color: #044cbf;}
#windTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
padding: 5px 0;}
#directionTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
padding: 5px 0;}
#Speed{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
color: #00cc00;align-content: left;}
#Direction{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;color: #00cc00;
align-content: left;}
#RHTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
padding: 6px 0;}
#RHumid{background: #cedcf2;grid-area: RHumid;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
color: black;align-content: center;}
#precipTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
padding: 6px 0;}
#precipPercent{background: #cedcf2;grid-area: RHumid;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
color: black;align-content: center;}
#precipAmtTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
padding: 6px 0;}
#precipAccum{background: #cedcf2;grid-area: RHumid;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
color: black;align-content: center;}
#Conditions{font-size:35px;color:red;}
</style>
</head>
<script type="text/javascript">
    var personal_token = '**YourPersonalToken**'
    var tempest_ID = '**YourTempestID**'
    let socket = new WebSocket('wss://ws.weatherflow.com/swd/data?api_key=' + personal_token);
    socket.onopen = function(e) {
        //alert("[open] Connection established");
        //alert("Sending to server");
        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=**YourStationID**&token=**YourToken**')
.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>
        `,
        position: "top_right",
        width: "350px",
        height: "200px",
        backgroundColor: "#FFF"
      }
2 Likes

just for reference, if you want to paste code without having like a book long post you can use some trick in this forum

start your code with 3 back ticks (```)
and finish with the same to close it and you will get a more friendly view

I just did so with post above

1 Like

Sorry the question, I’m an amateur coder here. But I took your code and put it into an HTML file, changed the station ID and token. I had also downloaded the MMM-Widget.js and put it in the same directory as the HTML. When I try to load the page, it only loads the wind direction, chance of rain, rain today, type of weather “Clear”. But no temp, wind speed, or RH.

At the top it shows this:
{ module: “MMM-Widget”, config: { widgets: [ { html:`

At the bottom it shows this:
`, position: “top_right”, width: “350px”, height: “200px”, backgroundColor: “#FFF” } ] } }
Screenshot 2021-09-02 092641

I’m not sure how the code will work outside of the MM2. Try deleting the:

{ module: “MMM-Widget”, config: { widgets: [ { html:

and

, position: “top_right”, width: “350px”, height: “200px”, backgroundColor: “#FFF” } ] } }

from your HTML file and see if that solves the problem. That part of the code is specific to the WWW-Widget module as it tries to interpret the HTML code that’s been placed in the config.js file for the MM2.

PS I’m an amateur too! :wink:

That got rid of the errors, but same results. At least I think I have a better understanding of the HTML. I thought that MMM-Widget was needed as backend code, even for just a basic webpage.

Try the code pasted below. Copy and paste into an editor and save it as an HTML file. It is all you need to get data from Tempest displayed in an HTML file. It has the basic HTML to create a table, the styling for that table and the Javascript to get data from the Tempest and populate the table.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tempest Data</title>
<meta name="description" content="Tempest Data">
    <style>
        body {background-color:#cedcf2;font-family: Arial;color: #336699;font-size: 10px;}
        table.center {margin-left:auto;margin-right:auto;}
        .column {float: left;width: 25%;padding: 10px;height: 10px;}
        .justRight {text-align:right;}
        #Title{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 25px;text-align: right;}
        #Time{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 25px;align-content: left;}
        #tempTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 20px;text-align: right;
        padding: 5px 0;}
        #LocalTemp{align-content: left;background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 90px;
        font-weight:bold; color: #044cbf;}
        #windTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 5px 0;}
        #directionTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 5px 0;}
        #Speed{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
        color: #00cc00;align-content: left;}
        #Direction{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;color: #00cc00;
        align-content: left;}
        #RHTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 6px 0;}
        #RHumid{background: #cedcf2;grid-area: RHumid;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
        color: black;align-content: center;}
        #precipTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 6px 0;}
        #precipPercent{background: #cedcf2;grid-area: RHumid;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
        color: black;align-content: center;}
        #precipAmtTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 6px 0;}
        #precipAccum{background: #cedcf2;grid-area: RHumid;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
        color: black;align-content: center;}
        #Conditions{font-size:35px;color:red;}
    </style>
</head>

<script type="text/javascript">
            var personal_token = 'YourPersonalToken'
            var tempest_ID = 'YourTempestID'
            let socket = new WebSocket('wss://ws.weatherflow.com/swd/data?api_key=' + personal_token);
            socket.onopen = function(e) {
                //alert("[open] Connection established");
                //alert("Sending to server");
                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=YourStationID&token=YourToken')
        .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>```
2 Likes

Ok I got this all working thanks to @dwburger initial HTML code. I simplified the data retrieval by putting in the units of measure I wanted so no conversions are needed except for the Time/Date.

<html>

<head>
	<meta charset="utf-8">
	<title>Tempest Data</title>
	<meta name="description" content="Tempest Data">

    <style>
        body {background-color:#cedcf2;font-family: Arial;color: #336699;font-size: 10px;}
        table.center {margin-left:auto;margin-right:auto;}
        .column {float: left;width: 25%;padding: 10px;height: 10px;}
        .justRight {text-align:right;}
        #Title{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 25px;text-align: right;}
        #Time{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 25px;align-content: left;}
        #tempTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 20px;text-align: right;
        padding: 5px 0;}
        #LocalTemp{align-content: left;background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 90px;
        font-weight:bold; color: #044cbf;}
        #windTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 5px 0;}
        #directionTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 5px 0;}
        #Speed{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
        color: #00cc00;align-content: left;}
        #Direction{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;color: #00cc00;
        align-content: left;}
        #RHTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 6px 0;}
        #RHumid{background: #cedcf2;grid-area: RHumid;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
        color: black;align-content: center;}
        #precipTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 6px 0;}
        #precipPercent{background: #cedcf2;grid-area: RHumid;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
        color: black;align-content: center;}
        #precipAmtTitle{background: #cedcf2;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;text-align: right;
        padding: 6px 0;}
        #precipAccum{background: #cedcf2;grid-area: RHumid;border-radius:var(--main-radius);padding-top:var(--main-padding);font-size: 22px;
        color: black;align-content: center;}
        #Conditions{font-size:35px;color:red;}
    </style>
</head>

<script>
	var personal_token = 'YourPersonalToken'
	var tempest_ID = 'YourTempestID'
	
	function start() {intervalID = setInterval(getData, 60000);}
	function getData(){fetch('https://swd.weatherflow.com/swd/rest/better_forecast?station_id='+ tempest_ID + '&units_temp=f&units_wind=mph&units_pressure=inhg&units_precip=in&units_distance=mi&token='+ personal_token)
	.then((res) => res.json()).
	then(function(res){
		LocalTime = res.current_conditions.time;
			var LocalTime = parseInt(LocalTime);
			var LocalTime = LocalTime*1000;
			var LocalTime = new Date(LocalTime);
			var LocalDate = LocalTime.toLocaleDateString();
			var LocalDate = " " + LocalDate;
			var LocalTime = LocalTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
			var LocalTime = LocalTime + LocalDate
		LocalTemp = (res.current_conditions.air_temperature)+ "&deg";
		Speed = (res.current_conditions.wind_gust)+ " mph";
		windDirection = res.current_conditions.wind_direction_cardinal;
		RelHumidity = (res.current_conditions.relative_humidity)+" %";
		precipPercent = (res.forecast.daily[0].precip_probability)+" %";
		currentConditions = res.forecast.daily[0].conditions;
		precipAccum = (res.current_conditions.precip_accum_local_day)+" in.";
			precipAccum = parseFloat(precipAccum);
			precipAccum = precipAccum.toFixed(2);
			
	document.getElementById('Time').innerHTML = LocalTime;
	document.getElementById('LocalTemp').innerHTML = LocalTemp;
	document.getElementById('Speed').innerHTML = Speed;
	document.getElementById('Direction').innerHTML = windDirection;
	document.getElementById('RHumid').innerHTML = RelHumidity;
	document.getElementById('precipPercent').innerHTML = precipPercent;
	document.getElementById('Conditions').innerHTML = currentConditions;
	document.getElementById('precipAccum').innerHTML = precipAccum;
	
	})};
</script>

<body onload="getData(); "start();">
	<table class="center">
		<tbody>
			<tr>
				<td id="Title">Current Conditions</td>
			</tr>
			<tr>
				<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>
2 Likes

sweeeet. Got this going.