Author Topic: Apps Script from MyAcurite to WU, Windy, PWSWeather, OWM, WindGuru, and/or CWOP  (Read 2511 times)

0 Members and 1 Guest are viewing this topic.

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
Hello all!

I've built a solution that periodically grabs data directly from MyAcurite and forwards it on to Wunderground, Windy.com, PWSWeather, OpenWeatherMap, WindGuru, and/or NOAA CWOP. It's built on the free Google Apps Script infrastructure and is available on Github:

https://github.com/leoherzog/WundergroundStationForwarder

I've been developing and using it for a few years now and it's pretty battle-tested. Give it a try and let me know your thoughts!
« Last Edit: July 17, 2023, 12:05:52 PM by xd1936 »

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
I appreciate someone finally taking the time to make this script. I am trying to send my data from either Wunderground or Myacurite to CWOP. So far I'm having trouble with the setup and getting this error:  TypeError: Cannot read properties of undefined (reading 'id')

I have used my Wunderground api and station and get this error. I then tried for MyAcurite, I'm not sure what is meant by HubName and StationName. I used 'Access' as HubName and New Mandy Farms Atlas for StationName since that is what shows up on the MyAcurite app.

Any help is appreciated and thank again for making this script.

Chris

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
Hi Chris!

Sure thing. Does the error say what Line it's happening on?

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
When I try using Wunderground (ibm), which is my preference, I get this error. Seems to not like the url

11:59:11 AM   Error   
Problem fetching https://api.weather.com/v2/pws/observations/current?stationId=KNCMOREH2&format=json&units=e&numericPrecision=decimal&apiKey=b8b4c3b0
fetchJSON_   @ Code.gs:745
refreshFromIBM_   @ Code.gs:112
Schedule   @ Code.gs:73

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
Hrm. When I load up
Code: [Select]
https://api.weather.com/v2/pws/observations/current?stationId=KNCMOREH2&format=json&units=e&numericPrecision=decimal&apiKey={myapikey}it loads as expected... Are you sure your API Key is correct in the code? It should be a good 32 characters long...

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
That was it! I was using the wrong api!

Thanks for the help, looks like it ran!

Chris

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
Oh, one last question, How do you schedule it in the Google Scripts?

Thanks

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
When you run the "Run" function, it automatically schedules all of the enabled services to periodically run in the "Triggers" tab on the left sidebar. You can see all of the subsequent runs in the "Executions" tab.

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
Thanks! Everyone is running fine now. One last question, does the Google Apps have to be open for the triggers to run. If I close that tab, will the triggers keep running. I have it set to every 15 minutes.

Chris

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
Of course! That'd be pretty wild if you had to keep that tab open. No, Apps Script runs server-side on Google's servers, and will continue to run day and night even if your computer is off.

Offline DoctorKnow

  • Forecaster
  • *****
  • Posts: 1984
It must have taken a lot of work, but I'm glad to see a way for everyone to send weather where they want now from Atlas sensors. I bought a Ambient clone to do what I wanted...

Can you take the temperature from another sensor instead of the Atlas or 5 in 1?

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
Anything's possible with some customization! You want to take readings from MyAcurite, but have temp pulled from one station/device and all other readings from another station/device?

Offline DoctorKnow

  • Forecaster
  • *****
  • Posts: 1984
Yes. It would be really unique if you could take the temperature and humidity from a lightning tower for example and all other readings from an Atlas or 5 in 1. All the sensors report to Myacurite if you use the Access, which is no longer even being sold apparently.

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
Well...

As you can see in the "refreshFromMyAcurite" function (https://github.com/leoherzog/WundergroundStationForwarder/blob/v2.3.1/code.gs#L176-L317), I do a bunch of authenticating with a MyAcurite account, but then I end up with an object called "sensors" (https://github.com/leoherzog/WundergroundStationForwarder/blob/v2.3.1/code.gs#L257-L260), which is a list of all of the different hubs and sensors and stuff in your account. I then find the one that matches "acuriteStationName" and use all of its readings (https://github.com/leoherzog/WundergroundStationForwarder/blob/v2.3.1/code.gs#L262-L315).

You could modify that last part to instead look something like this:

Code: [Select]
  let acuriteConditions;

  // start off pulling info from one sensor
  acuriteConditions = sensors.devices.find(device => device.name === "Name of Sensor One");
  // console.log(JSON.stringify(acuriteConditions));

  let conditions = {};
  conditions.time = new Date(acuriteConditions.last_check_in_at).getTime();
  conditions.latitude = sensors.latitude;
  conditions.longitude = sensors.longitude;
  let temp = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'Temperature');
  if (temp != null) conditions.temp = {
    "f": temp.chart_unit === 'F' ? Number(temp.last_reading_value).toFixedNumber(1) : Number(temp.last_reading_value).cToF().toFixedNumber(1),
    "c": temp.chart_unit === 'C' ? Number(temp.last_reading_value).toFixedNumber(1) : Number(temp.last_reading_value).fToC().toFixedNumber(1)
  }
  let dewpoint = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'Dew Point');
  if (dewpoint != null) conditions.dewpoint = {
    "f": dewpoint.chart_unit === 'F' ? Number(dewpoint.last_reading_value).toFixedNumber(1) : Number(dewpoint.last_reading_value).cToF().toFixedNumber(1),
    "c": dewpoint.chart_unit === 'C' ? Number(dewpoint.last_reading_value).toFixedNumber(1) : Number(dewpoint.last_reading_value).fToC().toFixedNumber(1)
  }

  // then switch to a different one
  acuriteConditions = sensors.devices.find(device => device.name === "Name of Sensor Two");
  // console.log(JSON.stringify(acuriteConditions));

  let windspeed = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'WindSpeedAvg');
  if (windspeed != null) conditions.windSpeed = {
    "mph": windspeed.chart_unit === 'mph' ? Number(windspeed.last_reading_value) : Number(windspeed.last_reading_value).kphToMPH().toFixedNumber(0),
    "mps": windspeed.chart_unit === 'km/h' ? Number(windspeed.last_reading_value).kphToMPS().toFixedNumber(0) : Number(windspeed.last_reading_value).mphToMPS().toFixedNumber(0),
    "knots": windspeed.chart_unit === 'mph' ? Number(windspeed.last_reading_value).mphToKnots().toFixedNumber(0) : Number(windspeed.last_reading_value).kphToKnots().toFixedNumber(0)
  }
  let windgust = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'Wind Speed');
  if (windgust != null) conditions.windGust = {
    "mph": windgust.chart_unit === 'mph' ? Number(windgust.last_reading_value) : Number(windgust.last_reading_value).kphToMPH().toFixedNumber(0),
    "mps": windgust.chart_unit === 'km/h' ? Number(windgust.last_reading_value).kphToMPS().toFixedNumber(0) : Number(windgust.last_reading_value).kphToMPS().toFixedNumber(0),
    "knots": windspeed.chart_unit === 'mph' ? Number(windgust.last_reading_value).mphToKnots().toFixedNumber(0) : Number(windgust.last_reading_value).kphToKnots().toFixedNumber(0)
  }
  let winddir = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'Wind Direction');
  if (winddir != null) conditions.winddir = Number(winddir.last_reading_value);
  let pressure = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'Barometric Pressure');
  if (pressure != null) conditions.pressure = {
    "inHg": pressure.chart_unit === 'inHg' ? Number(pressure.last_reading_value).toFixedNumber(0) : Number(pressure.last_reading_value).hPaToinHg().toFixedNumber(0),
    "hPa": pressure.chart_unit === 'hPa' ? Number(pressure.last_reading_value).toFixedNumber(0) : Number(pressure.last_reading_value).inHgTohPa().toFixedNumber(0)
  }
  let humidity = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'humidity');
  if (humidity != null) conditions.humidity = humidity.last_reading_value;
  let uv = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'UV'); // TODO: Unable to test, may be wrong sensor code
  if (uv != null) conditions.uv = uv.last_reading_value;
  let lightIntensity = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'Light Intensity'); // TODO: Unable to test, may be wrong sensor code
  if (lightIntensity != null) conditions.solarRadiation = lightIntensity.last_reading_value;
  let rain = acuriteConditions.sensors.find(sensor => sensor.sensor_code === 'Rainfall');
  if (rain != null) conditions.precipRate = {
    "in": rain.chart_unit === 'in' ? Number(rain.last_reading_value) : Number(rain.last_reading_value).mmToIn().toFixedNumber(0),
    "mm": rain.chart_unit === 'mm' ? Number(rain.last_reading_value) : Number(rain.last_reading_value).inTomm().toFixedNumber(0)
  }

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
Hey,
Question about taking data from MyAcurite. I have been using Weather Underground, but their servers are always having issues.
I'm confused on what exactly goes in these variables:
acurite username:
acurite password:
acurite HubName:
acurite StationName:

Is the username and password, you acurite login email and password?
Where are the HubName and StationName located?

Thanks again for this great script!

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
Good question! In my case, I have an Acurite Access named "Access" in my account and a 5-in-1 Acurite Iris reporting to it named "Lakeside". That would be the Hub Name and Sensor Name for me respectively. If you go to Settings → Manage Devices in the MyAcurite mobile app, then tap on your "Connection", you'll see the Hub Name and Sensor Name both on that next screen.

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
I think I've discovered my issue with Acurite. I have had this Access for awhile and it was a beta test version which I kept. To log into Acurite to see the data, you have to go to staging.myacurite.com   then enter the username and password. I have never been able to access this Access (haha) from the regular myacurite.com page. Is there any way to tweak the code so that it is logging into staging.myacurite.com? 

Thanks for your help!

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
The address is atlasapi.staging.myacurite.com 

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
Woah. I've never heard of this staging stuff. Bizarre.

It sounds like you'll need simply to find and replace all of the `marapi.myacurite.com` API URLs with `atlasapi.staging.myacurite.com` in the `refreshFromMyAcurite_()` function? Though I don't have a way to test that to see if it works. Report back!

https://github.com/leoherzog/WundergroundStationForwarder/blob/v2.3.3/code.gs#L176

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
I tried changing the urls and get this error:

Exception: DNS error: https://atlasapi.staging.myacurite.com/accounts

Chris

Offline ctccbc

  • Senior Contributor
  • ****
  • Posts: 276
  • Acurite 01035, Weather Display
    • Chris Collins Morehead City, NC Weather
I found a typo and fixed it, now get this error:

Exception: Request failed for https://atlasapi-staging.myacurite.com returned code 404. Truncated server response: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the s... (use muteHttpExceptions option to examine full response)
refreshFromAcurite_   @ Code.gs:190
Schedule   @ Code.gs:77

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
I don't know. Maybe try marapi-staging.myacurite.com?

Offline Rgv20

  • Member
  • *
  • Posts: 9
Thank you! Thanks to your script I'm now sending data to CWOP from my Atlas. For some reason could not send the data from MyAcurite but was able to send it from Wunderground.

Offline robbywan

  • Member
  • *
  • Posts: 2
Hi,
thanks for this work !

I tried at first with weather underground as the source, it worked pretty well but it seemed there are frequent issues with WU server, so I wanted to give it a try with datas directly from myAcurite ; unfortunately I'm experiencing an error :
Code: [Select]
Erreur
TypeError: conditions.temp.f.windChill is not a function
refreshFromAcurite_ @ Code.gs:307
Schedule @ Code.gs:82

Code: [Select]
307 "f": conditions.temp.f.windChill(conditions.windSpeed.mph).toFixedNumber(1),
82  refreshFromAcurite_();

Could someone please help me figuring out the error ?
I understand windChill is not recognized as a function, but don't know what to do with that information.

Many thanks in advance.

Offline xd1936

  • Member
  • *
  • Posts: 22
    • About Me
Thank you for bringing this to my attention! I had an error in the code. Give the latest version a try and let me know if that fixes it for you?