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
constRingApi=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 inconstringApi=awaitRingApi({// 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 codeemail: 'you@example.com',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 outserverRoot: 'http://example.com'});constlogActivity=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 integersid: '6500907085284961754',id_str: '6500907085284961754',// same as idstate: 'ringing',protocol: 'sip',doorbot_id: 3861978,// id of the device that is ringingdoorbot_description: 'Back garden',device_kind: 'hp_cam_v1',motion: true,snapshot_url: '',// seems to always be blank expires_in: 175,now: Date,// js Date objectoptimization_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}// returns a promiseringApi.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 forchimes: [/* 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}constprompt=require('node-ask').prompt;asyncfunctionlightsOnAndOff(){constdevices=awaitringApi.devices();console.log(`turning on all lights`);// note that .lightOn() returns a promise// with the magic of promises we can turn them all on asynchronouslyawaitPromise.all(devices.cameras.map(c=>c.lightOn()));awaitprompt('all your lights are now on, hit return to turn them off');awaitPromise.all(devices.cameras.map(c=>c.lightOff()));console.log('they\'re all off again!');};lightsOnAndOff();asyncfunctionlogMyRingHistory(){consthistory=awaitringApi.history();constfirstVideoUrl=awaithistory[0].videoUrl();console.log('latest video is at',firstVideoUrl);constallRecentVideos=Promise.all(history.map(h=>h.videoUrl()));console.log('list of all recent videos:',awaitallRecentVideos);};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();asyncfunctionprintHealth(device){conststrength=(awaitdevice.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:constdevices=awaitringApi.devices();printHealth(devices.doorbells[0]);printHealth(devices.chimes[0]);printHealth(devices.cameras[0]);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- The doorbot source for getting me started
- This python API
- mitm proxy