Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Fetching Weather using the dev code

ANSWERED
Hello, I have successfully gathered weather information using the code on the dev part of this site. Now I understand i can grab the data for the details set in this code : var ENDPOINT = "https://api.openweathermap.org/data/2.5/weather?"+"lat=52.7079&lon=-2.7541&units=metric"; Now in this line the latitude and longitude provide the temp and location data. The trouble is I have to enter these coordinates in the code which is fine for my location but that would be useless for others using my watch face Is there any way I can auto fill this ENDPOINT with with either user information based on settings or even better can I auto fill this information using the geolocation of the watch. I have looked at the weather module on github but it comes across long winded just to retrieve weather as this code is far more simple in its form. I would like to think I can auto fill this data based on the watch GPS or user input. Any help appreciated.
Best Answer
0 Votes
1 BEST ANSWER

Accepted Solutions

Hello, 

I know very well your feeling as the weather module on Guthub is way too complex.

I've made another sample but much more simple. It works well with the simulator but it seems I can't get the GPS fix when deployed to the actual device (ionic).

 

Here it is

App

 

// Import the messaging module
import * as messaging from "messaging";
import document from "document";

// Request weather data from the companion
function fetchWeather() {
  if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
    // Send a command to the companion
    messaging.peerSocket.send({
      command: 'weather'
    });
  }
}

// Display the weather data received from the companion
function processWeatherData(data) {
  console.log("The temperature is: " + data.temperature);
  console.log("The location is : " + data.location);
}

// Listen for the onopen event
messaging.peerSocket.onopen = function() {
  // Fetch weather when the connection opens
  fetchWeather();
}

// Listen for messages from the companion
messaging.peerSocket.onmessage = function(evt) {
  if (evt.data) {
    processWeatherData(evt.data);
  }
}

// Listen for the onerror event
messaging.peerSocket.onerror = function(err) {
  // Handle any errors
  console.log("Connection error: " + err.code + " - " + err.message);
}

Companion

 

// Import the messaging module
import * as messaging from "messaging";
import { geolocation } from "geolocation";

var API_KEY = "YOUR KEY HERE";

// Fetch the weather from OpenWeather
function queryOpenWeather() {
  geolocation.getCurrentPosition(locationSuccess, locationError);
  function locationSuccess(position) {
    var lat = position.coords.latitude;
    var long = position.coords.longitude;
    console.log("latitude: " + lat);
    console.log("langitude: " + long);
    var linkApi = "https://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon="  + long + "&units=metric" + "&APPID=" + API_KEY;
  fetch(linkApi)
  .then(function (response) {
      response.json()
      .then(function(data) {
        // We just want some data
        var weather = {
          temperature: data["main"]["temp"], humidity: data["main"]["humidity"], location: data["name"]
        }
        // Send the weather data to the device
        returnWeatherData(weather);
      });
  })
  .catch(function (err) {
    console.log("Error fetching weather: " + err);
  });
 };
 function locationError(error) {
  console.log("Error: " + error.code,
              "Message: " + error.message);
}
}

// Send the weather data to the device
function returnWeatherData(data) {
  if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
    // Send a command to the device
    messaging.peerSocket.send(data);
  } else {
    console.log("Error: Connection is not open");
  }
}

// Listen for messages from the device
messaging.peerSocket.onmessage = function(evt) {
  if (evt.data && evt.data.command == "weather") {
    // The device requested weather data
    queryOpenWeather();
  }
}

// Listen for the onerror event
messaging.peerSocket.onerror = function(err) {
  // Handle any errors
  console.log("Connection error: " + err.code + " - " + err.message);
}

View best answer in original post

Best Answer
24 REPLIES 24

Hello, 

I know very well your feeling as the weather module on Guthub is way too complex.

I've made another sample but much more simple. It works well with the simulator but it seems I can't get the GPS fix when deployed to the actual device (ionic).

 

Here it is

App

 

// Import the messaging module
import * as messaging from "messaging";
import document from "document";

// Request weather data from the companion
function fetchWeather() {
  if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
    // Send a command to the companion
    messaging.peerSocket.send({
      command: 'weather'
    });
  }
}

// Display the weather data received from the companion
function processWeatherData(data) {
  console.log("The temperature is: " + data.temperature);
  console.log("The location is : " + data.location);
}

// Listen for the onopen event
messaging.peerSocket.onopen = function() {
  // Fetch weather when the connection opens
  fetchWeather();
}

// Listen for messages from the companion
messaging.peerSocket.onmessage = function(evt) {
  if (evt.data) {
    processWeatherData(evt.data);
  }
}

// Listen for the onerror event
messaging.peerSocket.onerror = function(err) {
  // Handle any errors
  console.log("Connection error: " + err.code + " - " + err.message);
}

Companion

 

// Import the messaging module
import * as messaging from "messaging";
import { geolocation } from "geolocation";

var API_KEY = "YOUR KEY HERE";

// Fetch the weather from OpenWeather
function queryOpenWeather() {
  geolocation.getCurrentPosition(locationSuccess, locationError);
  function locationSuccess(position) {
    var lat = position.coords.latitude;
    var long = position.coords.longitude;
    console.log("latitude: " + lat);
    console.log("langitude: " + long);
    var linkApi = "https://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon="  + long + "&units=metric" + "&APPID=" + API_KEY;
  fetch(linkApi)
  .then(function (response) {
      response.json()
      .then(function(data) {
        // We just want some data
        var weather = {
          temperature: data["main"]["temp"], humidity: data["main"]["humidity"], location: data["name"]
        }
        // Send the weather data to the device
        returnWeatherData(weather);
      });
  })
  .catch(function (err) {
    console.log("Error fetching weather: " + err);
  });
 };
 function locationError(error) {
  console.log("Error: " + error.code,
              "Message: " + error.message);
}
}

// Send the weather data to the device
function returnWeatherData(data) {
  if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
    // Send a command to the device
    messaging.peerSocket.send(data);
  } else {
    console.log("Error: Connection is not open");
  }
}

// Listen for messages from the device
messaging.peerSocket.onmessage = function(evt) {
  if (evt.data && evt.data.command == "weather") {
    // The device requested weather data
    queryOpenWeather();
  }
}

// Listen for the onerror event
messaging.peerSocket.onerror = function(err) {
  // Handle any errors
  console.log("Connection error: " + err.code + " - " + err.message);
}
Best Answer

Last update: I was finally able to have it working on the device. Remember to give the authorization to connect to internet and location in the package.json file.

Let me know is something is not clear.

Best Answer
0 Votes

Brilliant, this worked a treat.  have unfortunately caused a conflict and wonder whether you could help. I also have this code running in the companion

let key = "theme";

let val = localStorage.getItem(key);
if (val) {
  try {
    val = JSON.parse(val); 
  } catch(ex) { 
    val = null;
  }
}

function sendVal(val) {
  if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) {
    messaging.peerSocket.send(val);
  }
}

messaging.peerSocket.onopen = function() {
  if (val) {
    sendVal(val);
  }
}

settingsStorage.onchange = function(evt) {
  let data = JSON.parse(evt.newValue);
  val = data["values"][0].value;
  localStorage.setItem(key, JSON.stringify(val));
  sendVal(val);
}

and this code running in the app

const SETTINGS_FILE = "settings.json";
let settings = loadSettings();
applyTheme(settings.foreground, settings.background);




function loadSettings() {
  let obj;
  try {
    obj = fs.readFileSync(SETTINGS_FILE, "json");
  } catch(ex) {
    obj = {
      foreground: "#ffffff",
      background: "#000000"
      }
  }
  return obj;
}



function applyTheme(foreground, background) {
  let items = document.getElementsByClassName("foreground");
  items.forEach(function(item) {
    item.style.fill = foreground;
  });
   settings.foreground = foreground;
  let items = document.getElementsByClassName("background");
  items.forEach(function(item) {
    item.style.fill = background;
  });
  settings.background = background;
}





messaging.peerSocket.onmessage = function(evt) {
  // console.log("device got: " + evt.data.background);
  applyTheme(evt.data.foreground, evt.data.background);
}



me.onunload = () => {
  fs.writeFileSync(SETTINGS_FILE, settings, "json");
}

When I run the watchface, not only does the theme not change but I also get NaN on the weather. Now I assume it has to do with a conflict from both messages being sent back to the app but as I am a relative noob, so to speak, i'm not quite advanced enough to figure the conflict out. Any pointers on this would be appreciated. 

Best Answer
0 Votes

First of all I'm happy my little simple code works for you. I built it just to make sure to understand what and how it does.

Second, I'm sorry but I'm now way an expert to understand what you are going to achieve and why it doesn't work. Hopefully somebody else is going to help you. Sorry again.

Best Answer
0 Votes

No problem, your goes does work. I did add this at the end in the app section to force an update every 30 mins, which works for getting regular updates. I'm sure I will find the solution to the other issue

setInterval(fetchWeather, 30 * 1000 * 60);
Best Answer

Hey! How do you show the weather data that you fetched on the watch face?

Do you use something like :

 const Temperature = document.getElementById("Temperature");

Temperature.text = (I don't know what goes in here, since I don't really understand the full fetching code... data.temperature or something like that maybe?);

 

 

Best Answer
0 Votes

Hello @innak,

I really understand how you feel as I learnt from scratch as well.

 

So, on your index.js file

 

// Get handle on text fields
let tempText = document.getElementById("tempText");

 

// Inside the processWeatherData block

 tempText.text = "Temp: " + Math.round(data.temperature) + " °C";

 

Don't hesitate to ask more if you need.

 

 

Best Answer

I have no idea what I am doing wrong. 

I used the dev.fitbit.com guides weather fetching example  and then I tried your code. I am not even getting anything in the console. No temperature and no errors. Console does not log anything.

And ofcourse in this case nothing is displayed on the watch face also.

Best Answer
0 Votes

Is your json file correct? in particular internet and location permission

Best Answer

Yes. Package.json is correct.

Everything else works fine. Even the payment on my watch face works (which also need Internet)

Best Answer
0 Votes

Excellent code - works 100%

 

But ... it will not provide rainfall - Keeps giving an erros sayiong "3h" is not recognised

 

Extract from Companion :

 

var linkApi = "https://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon="  + long + "&units=metric" + "&APPID=" + API_KEY;

  fetch(linkApi)

  .then(function (response) {

      response.json()

      .then(function(data) {

        // We just want some data

      var weather = {

          temperature: data["main"]["temp"],

          humidity:    data["main"]["humidity"],

          location:    data["name"],

          WindSpeed:   data["wind"]["speed"],

          WindDeg:     data["wind"]["deg"],

          Apressure:   data["main"]["pressure"],

          MaxTemp:     data["main"]["temp_max"],

          MinTemp:     data["main"]["temp_min"],

          MaxExpect:   data["main"]["max"],

          SunRise:     data["sys"]["sunrise"],

          SunSet:      data["sys"]["sunset"],

          rainfall:    data["rain"]["3h"],

        }

 

Extract from App

myWind.text= "Wind "+Math.floor(data.WindSpeed);

myHumid.text= "Humidity "+data.humidity+" %";

myRain.text= "Rainfall "+data.rainfall+" mm";

 

I get the Wind and Humidity - bit not the rain

 

I have tried setting a number of locations - London / NY / Chicago etc -making sure it is actually raining there at the time - but no joy

 

Any suggestions ?

 

 

Best Answer
0 Votes

@Lawson77 I've checked the API documentation at https://openweathermap.org/current and while indeed it mentions we should get rains data calling "3h" an actual call to the sample api doesn't show any rain "3h". I think therefore the API documentation is wrong.

 

You might want to try other weather providers.

Best Answer

@Giampi71I've used your code in my clock face and it works in the simulator on my computer but whenever I load it onto my watch it never loads the temp. The console logs just show it reading the latitude and longitude with no errors. On a Versa.

Best Answer
0 Votes
Have you specified internet access?
Peter McLennan
Gondwana Software
Best Answer

Yes I've even granted all permissions.

Best Answer
0 Votes

Your instruction and information is very well explained and easy to follow - many thanks.

 

I am finding the atmospheric pressure received from the provider very unreliable.

 

Is it possible to use the data from the cell phone barometer directly into code / app ?

 

I have a Samsung S7 - and reliable and instantaneous barometer.  Would be great to use that data instead of the downloaded data

Best Answer
0 Votes

@Lawson77 It is an interesting idea but I don't think it is possible. I will try to play around.

Best Answer
0 Votes

My update on this code is that it did work but not for me 😄 I tried it but as I wrote before, it did not work. So I decided to leave the code in just in case I want to try it later again. And published the clock face. And people started complaining that they are seeing weather (it was overlapping with the date, obviously I did not set css right, and did not position it because I did not see it on my watch). So I am thinking, can there be some kind of a region issue? I had no weather on my watch and other people did.

Best Answer
0 Votes

Definitely no regional lock. Could you please share the name of your app?

 

Thanks

Best Answer
0 Votes