Skip to content

jimhigson/ring-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

About

A promisified API for Ring Doorbell APIs

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published