npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

weathercloud-js

v1.0.1

Published

reverse engineering of weathercloud's API in nodeJS

Downloads

47

Readme

Weathercloud JS API 📡

What is it?

weathercloud.net is a web application that logs and makes publicly available weather data from personal weather stations.

This is a reverse engineering of the private API used to retrieve stations data.

Table of contents

Installation

npm install weathercloud-js

Usage / Example

import { getWeather } from "weathercloud-js";

(async () => {
  // Get the weather for station ID 4172447340
  const weather = await getWeather("4172447340");
  console.log(weather);
})();

See more examples here

Docs

Station_id

Station ID can be:

  • A 10-digit string for devices.
  • A 9-digit string for devices.
  • A 4-letter string for METAR (following ICAO airport codes).
  const deviceId = "5692854635";
  const metarId = "LSGG";

login()

Log in to a WeatherCloud account

await login(mail: string, password: string, storecredentials?: boolean = false): boolean; // Returns true if logged in successfully

getWeather()

Get general weather data from a station

await getWeather(StationId:string) : {
  // included most of the time
  epoch: number, // time of the last update (unix seconds)
  bar: number, // pressure (hPa)
  wdir: number, // wind direction (degree)
  wdiravg: number, // average wind direction (degree)
  wspd?: number, // wind speed (m/s)
  wspdhi?: number, // wind gust (m/s)
  wspdavg?: number, // average wind speed (m/s)
  rainrate?: number, // rainrate (mm/hour)
  rain?: number, // rained today (mm)
  temp?: number, // temperature (°C)
  hum?: number, // humidity (%)
  dew?: number, // dew point (°C)
  
  // optional
  temp02?: number, // 2nd temperature (°C)
  hum02?: number, // 2nd humidity (%)
  chill?: number, // wind-chill (°C)
  heat?: number, // heat index (°C)
  thw?: number, // Temperature-Humidity-Wind Index or feel like (°C)
  solarrad?: number, // solar radiation (W/m²)
  uvi?: number, // UV index
  vis?: number, // visibility mainly for metar (m)

  // logged only
  tempin?: number, // in temperature (°C)
  humin?: number, // in humidity (%)
  dewin?: number, // in dew point (°C)
  heatin?: number, // in heat index (°C)
  computed: { // added via logic based on above data
    cloudsHeight: number | null, // height of the cloud (m)
    feel: number | null, // feel index (°C)
    weatherAvg: string | null, // avg state of weather in english (exemple "cloud")
  }
};

getProfile()

Get station profile

await getProfile(stationId:string): {
  // Not present for metar
  observer?: { // owner infos
    name: string,
    nickname: string,
    company: string
  },
  device?: { // device informations
    brand: string,
    model: string
  },
  // present every time
  followers: { // follower of this station
    number: string // (this is a number in a string)
  }
};

getInfos()

Get device information

await getInfos(stationId:string): {
  device: { // infos
    account: number|string, // ...
    status: string, // 0: metar 2: device 1: offline
    city: string, // city
    image: null|string, // optional url of device banner image
    isWebcam: boolean, // is there a webcam
    favorite: boolean, // is station favourite (false when not logged)
    social: boolean, // is there a twitter account linked
    altitude: string, // elevation of the station (m)
    update: number // seconds since last update
  },
  values: { // some of the station data 
    temp: number, // temperature (°C) 
    hum: number, // humidity (%)
    dew: number, // dew point (°C)
    wspdavg: number, // average wind speed (m/s)
    wdiravg: number, // average wind direction (degree)
    bar: number, // pressure (hPa)
    rain: number, // rained today (mm)
    rainrate?: number, // rainrate (mm/hour)
    solarrad?: number, // solar radiation (W/m²)
    uvi?: number, // UV index
    vis?: number // visibility mainly for metar (m)
  }
};

getLastUpdate()

Get update infos

await getLastUpdate(stationId:string): {
  update: number, // time elapsed since the last update (seconds)
  server_time: number, // server time when requested (unix seconds)
  status: string // "2" => OK; others => some kind of error
};

getWind()

Get wind data (directions and forces over directions)

await getWind(stationId:string): {
  date: number, // time of the update
  wdirproportions: number[], // array of proportion of wind, each one is a cardinals
  calm: number, // proportion of calm wind time (%)
  wspddistData: number[], // array of wind speeds, each one is a cardinals
  raw: data // original values gl to know what this is exactly
};

getStatistics()

Get statistics (max/min for day/month/year)

await getStationStatus(stationId:string): {
  last_update: number // time of the last update (unix seconds)
  temp_current: [
    number, // time of measurement
    number // value of measurement
  ],
  temp_day_max: [ number, number ], // number index are the same patern for every entries
  temp_day_min: [ number, number ],
  temp_month_max: [ number, number ],
  temp_month_min: [ number, number ],
  temp_year_max: [ number, number ],
  temp_year_min: [ number, number ],
  
  dew_current: [ number, number ],
  dew_day_max: [ number, number ],
  dew_day_min: [ number, number ],
  dew_month_max: [ number, number ],
  dew_month_min: [ number, number ],
  dew_year_max: [ number, number ],
  dew_year_min: [ number, number ],
  
  hum_current: [ number, number ],
  // all elements as temp or dew
  bar_current: [ number, number ],
  // ...
  wspdavg_current: [ number, number ],
  // ...
  wspdhi_current: [ number, number ],
  // ...
  wdiravg_current: [ number, number ],
  // ...
  rain_current: [ number, number ],
  // ...
  
  // optional
  wspd_current?: [ number, number ],
  // ...
  rainrate_current?: [ number, number ],
  // ...
  solarrad_current?: [ number, number ],
  // ...
  uvi_current?: [ number, number ],
  // ...
  chill_current?: [ number, number ],
  // ...
  heat_current?: [ number, number ],
  // ...
  
  // visibility for some reason divided by 100
  vis_current?: [ number, number ],
  // ...

  // logged only
  tempin_current?: [ number, number ],
  // ...
  humin_current?: [ number, number ],
  // ...
  dewin_current?: [ number, number ],
  // ...
  heatin_current?: [ number, number ]
  // ...
};

getNearest()

Get station in given radius of a GPS point

await getNearest(latitude: string|number, longitude: string|number, radius: string|number): {
  type: "device"|"metar",
  code: string, // id of station
  name: string, // name
  // position
  city: string,
  latitude: string,
  longitude: string,
  elevation: string // (m)

  image: string // image profile url of the station
  account: number|string // ...
  isFavorite: boolean // is station favourite (false when not logged)
  update: number // seconds elapsed since last update
  status?: string // 0: METAR, 2: Device OK 1: Device error
  distance: number // distance from point (km)
  values: Object // just like data from getWeather
}[];

getTop()

Get top station by views, follows, or newest in a country, other a timeframe

await getTop(stat:"newest"|"followers"|"popular", countryCode:string, period?:"day"|"week"|"month"|"year"|"all"): { // timeframe not used for newest else mandatory
  type: "device"|"metar",
  code: string, // id of station
  name: string, // name
  // position
  city: string,
  latitude: string,
  longitude: string,
  elevation: string // (m)

  image: string // image profile url of the station
  account: number|string // ...
  isFavorite: boolean // is station favourite (false when not logged)
  update: number // seconds elapsed since last update
  status?: string // 0: METAR, 2: Device OK 1: Device error
  age?: number // distance from point (km) -- for newest only
  views?: number // distance from point (km) -- for popular only
  followers?: number // distance from point (km) -- for followers only
  values: Object // just like data from getWeather
}[];

getAllDevices()

List ALL device /!\ very heavy return

await getAllDevices(parseDevice?:boolean=false): { // parseDevice optional to let choice between easy work on data, or easyier for machine
  code: string, // station id
  name: string, // station name
  type: "metar"|"device",
  lat: string, // GPS loc
  lon: string, // GPS loc
  status: number, // 0: metar 2: device 1: offline
  isWebcam: boolean, // is a webcam
  temp: null | number, // temperature (°C)
  hum: null | number, // humidity (%)
  bar: number, // pressure (hPa)
  wspdavg: null | number, // average wind speed (m/s)
  wdiravg: null | number, // average wind direction (degree)
  rain: null | number, // rained today (mm)
  rainrate: null | number, // rainrate (mm/hour)
  solarrad: null | number, // solar radiation (W/m²)
  uvi: null | number, // UV index
} | // depending of parseDevice
[ // not parsed
  string, // ID (in base36 for devices)
  string, // name
  number, // latitude
  number, // longitude
  number, // status - 0: metar 2: device 1: offline
  number, // is webcam
  number | "", // temperature (°C*10) string if undefined
  number | "", // humidity string if undefined
  number, // pressure (hPa*10)
  number | "", // average wind speed (m/s*10) string if undefined
  number | "", // average wind direction (deg) string if undefined
  number | "", // rain (mm*10) string if undefined
  number | "", // rainrate (mm/h*10) string if undefined
  number | "", // solarrad string if undefined
  number | "", // uvi string if undefined
];

getStationStatus()

[LOGGED ONLY] Get the uptime of the station over the past month

await getStationStatus(stationId:string): { // METAR unsuported
  date: number, // day (unix seconds)
  value: number // uptime (%)
  // maybe some more data for compatible and owned stations
}[];

getOwn()

[LOGGED ONLY] Get owned and favorites devices

await getOwn(): {
  favorites: [ // favorites devices list
    {
      type: "device"|"metar",
      code: string, // id of station
      name: string, // name
      // position
      city: string,
      latitude: string,
      longitude: string,
      elevation: string // (m)

      image: string // image profile url of the station
      account: number|string // ...
      isFavorite: boolean // is station favourite (false when not logged)
      update: number // seconds elapsed since last update
      status?: string // 0: METAR, 2: Device OK 1: Device error
      values: Object // just like data from getWeather
    }
  ]
  devices: [ // owned devices list
    // just like favorite
  ]
};

isFavorite()

[LOGGED ONLY] Know if a device is favourited

await isFavorite(stationId:string): boolean;

addFavorite()

[LOGGED ONLY] Add a station to favorites

await addFavorite(stationId:string): boolean; // return true if success

removeFavorite()

[LOGGED ONLY] Remove a station to favorites

await removeFavorite(stationId:string): boolean; // return true if success

API documentation

API docs are now separate, you can find them in api-documentation.md

License

Distributed under the MIT License. See LICENSE.txt for more information.

Links