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

ring-api

v3.0.7

Published

Unofficial API for ring doorbells and other devices

Downloads

66

Readme

Ring API

An unofficial, friendly Javascript API for ring doorbells, cameras, etc.

  • Happy in node or browsers
  • Promised-based
  • Glosses over ring's API weirdness
  • Hides http polling behind an event-driven interface

Requires a JS runtime that supports ES6 async/await or else traspilation

usage

const RingApi = require( 'ring-api' );

// note that RingApi returns a promise - the promise resolves when you are authenticated/
// authorised and have a session ready to start interacting with your ring deviecs. This
// promise will reject if for some reason you are not able to log in
const ringApi = await RingApi( {

    // note - that the email and password can also be given by setting the RING_USER 
    // and RING_PASSWORD environment variables. For example if you want to keep
    // passwords out of your source code
    email: '[email protected]',
    password: 'password you use on ring.com',

    // the user agent parameter has been removed since Ring have started rejecting
    // unrecognised agent strings
    //userAgent: 'any string',

    // OPTIONAL: if true, ring-api will poll behind the scenes.
    // Listening for events only works if this is on.
    // True by default.
    poll: true,
    
    // OPTIONAL
    // Set this if you need to run in a browser behind a proxy, for example
    // to get around x-origin request restrictions. Ring don't have CORS headers.
    // once set, all requests will be made relative to this value
    // default is 'https://api.ring.com/clients_api'
    // If running in node, you almost certainly want to leave this out
    serverRoot: 'http://example.com'
} );

Listening for activity on your ring devices

const logActivity = activity => console.log( 'there is a activity', activity );

ringApi.events.on('activity', logActivity);

The event will be fired on rings and motion detected. To distinguish between then, use the activity.kind property.

Where the activity object looks like:

{
   kind: 'motion',  // 'motion' or 'ring',
   // note - id will be a string - Javascript Number can't do large integers
   id: '6500907085284961754',
   id_str: '6500907085284961754', // same as id
   state: 'ringing',
   protocol: 'sip',
   doorbot_id: 3861978, // id of the device that is ringing
   doorbot_description: 'Back garden',
   device_kind: 'hp_cam_v1',
   motion: true,
   snapshot_url: '',  // seems to always be blank   
   expires_in: 175,
   now: Date, // js Date object
   optimization_level: 1,

   // various sip-related fields for the video:
   sip_server_ip: '...',
   sip_server_port: 15063,
   sip_server_tls: true,
   sip_session_id: '...',
   sip_from: '...',
   sip_to: '..',
   audio_jitter_buffer_ms: 300,
   video_jitter_buffer_ms: 300,
   sip_endpoints: null,
   sip_token: 'long hex token',
   sip_ding_id: '6500907085284961754', // seems to always be the same as the id
}

Getting a list of devices

// returns a promise
ringApi.devices();

Where the promise will resolve to an object like:

{
    all: [ /* all your devices in one array */ ],
    doorbells: [ /* array of doorbells */ ]
    authorizedDoorbells: [], // other people's doorbells you are authorised for
    chimes: [ /* array of chimes */ ],
    cameras: [ /* array of cameras, floodlight cams, spotlight cams etc */ ] ],
    baseStations: [] // presumably if you have a chime pro with the wifi hotspot built in
}

Turning lights on and off

const prompt = require('node-ask').prompt;

async function lightsOnAndOff() {

   const devices = await ringApi.devices();

   console.log( `turning on all lights` );

   // note that .lightOn() returns a promise
   // with the magic of promises we can turn them all on asynchronously
   await Promise.all( devices.cameras.map( c => c.lightOn() ) );

   await prompt( 'all your lights are now on, hit return to turn them off' ); 

   await Promise.all( devices.cameras.map( c => c.lightOff() ) );

   console.log( 'they\'re all off again!');
};

lightsOnAndOff();

Getting device history and videos

async function logMyRingHistory() {

   const history = await ringApi.history();
   const firstVideoUrl = await history[0].videoUrl();

   console.log( 'latest video is at', firstVideoUrl );
   
   const allRecentVideos = Promise.all( history.map( h => h.videoUrl() ) );
   
   console.log( 'list of all recent videos:', await allRecentVideos );   
};

starting a livestream

So far this only works so far as getting the SIP details of the stream. To get this, can do:

// returns a promise that will resolve to the livestream SIP information:
devices.doorbells[0].liveStream();

getting device health

async function printHealth( device ) {
   const strength = (await device.health()).latest_signal_strength;
   console.log( `${device.description} wifi strength is ${strength}` );
}

// asynchronously print the health of the first of each kind of device,
// without worrying about the order they are printed in:
const devices = await ringApi.devices();
printHealth( devices.doorbells[0] );
printHealth( devices.chimes[0] );
printHealth( devices.cameras[0] );

debugging

To get extended debugging info, since ring-api uses https://www.npmjs.com/package/debug you can set the DEBUG environment variable to ring-api (or add ring-api to it if it is already set)

For example, to run the example script from bash with debugging you might do:

env DEBUG="$DEBUG ring-api" ./examples/example-script

Thanks to