Giter Site home page Giter Site logo

dorita980's Introduction

dorita980

Build Status dependencies Status npm version

Unofficial iRobot Roomba 980 node.js library (SDK).

With this library you can send commands to your Roomba 980 through the iRobot cloud API or directly from your LAN and integrate your roboot with your own Home Automation or IoT project.

See rest980 if you need a HTTP REST API interface.

Firmware 2.x.x documentation

All this document is only for firmware 2.x.x. Check your robot version!

If you have firmware version 1.6.x click here to see the old documentation.

There are some breaking changes between 1.6.x and 2.x.x in this API (dorita980 v2 and v3).

Features

  • Get your username/password easily
  • Auto discovery robot IP (optional)
  • Local API control (from your LAN)
  • Simplified Cleaning Preferences settings.
  • Firmware 2.0.0 compatible.
  • See rest980 if you need a HTTP REST API interface to use dorita980 throw.

iRobot Roomba 980 cleaning map using dorita980 lib

Video: Realtime cleaning map using dorita980 lib in rest980.

Install

First you need node.js installed and then:

$ npm install dorita980 --save

Quick start via Local request on your LAN

You can control the robot from your local network.

Create myapp.js file with this content:

var dorita980 = require('dorita980');

var myRobotViaLocal = new dorita980.Local('MyUsernameBlid', 'MyPassword', '192.168.1.104'); // robot IP address

myRobotViaLocal.on('connect', function () {
  myRobotViaLocal.start().then(() => {
    myRobotViaLocal.end(); // disconnect to leave free the channel for the mobile app.
  }).catch((err) => {
    console.log(err);
  });
});

Then install dorita980 using npm and run your program:

$ npm install dorita980 --save
$ node myapp.js

Examples

Pause the robot via Local request:

var dorita980 = require('dorita980');

var myRobotViaLocal = new dorita980.Local('MyUsernameBlid', 'MyPassword', '192.168.1.104'); // robot IP address 

myRobotViaLocal.on('connect', function () {
  // Pause!
  myRobotViaLocal.pause().then(() => {
    myRobotViaLocal.end(); // disconnect to leave free the channel for the mobile app.
  }).catch((err) => {
    console.log(err);
  });
});

Get robot week schedule

var dorita980 = require('dorita980');

var myRobotViaLocal = new dorita980.Local('MyUsernameBlid', 'MyPassword', '192.168.1.104'); // robot IP address 

myRobotViaLocal.on('connect', function () {
  myRobotViaLocal.getWeek().then((weekConfig) => {
    console.log(weekConfig)
    myRobotViaLocal.end(); // disconnect to leave free the channel for the mobile app.
  }).catch((err) => {
    console.log(err);
  });
});

How to get your username/blid and password

(Needed for Cloud and Local requests)

Download or clone this repo then install, then run npm run getpassword. You need to know your robot IP address (look in your router or scan your LAN network with nmap to find it). Or use dorita980.getRobotIP() method.

$ git clone https://github.com/koalazak/dorita980.git
$ cd dorita980
$ npm install
$ npm run getpassword <robotIP>

Example Output:

$ cd dorita980
$ npm install
$ npm run getpassword 192.168.1.103
> node ./bin/getpassword.js "192.168.1.103"

Make sure your robot is on the Home Base and powered on. Then press and hold the HOME button on your robot until it plays a series of tones (about 2 seconds). Release the button and your robot will flash WIFI light.
Then press any key...
Looking for robots...
Robot found! with blid/username: xxxxxxxxxxxxx
{ ver: '2',
  hostname: 'Roomba-xxxxxxxxxxxxx',
  robotname: 'Dorita',
  ip: '192.168.1.103',
  mac: '12:12:12:12:12:12',
  sw: 'v2.0.0-34',
  sku: 'R98----',
  nc: 0,
  proto: 'mqtt' }
Password=> :1:1486937829:gktkDoYpWaDxCfGh <= Yes, all this string.
Use this credentials in dorita980 lib :)

Auto discover IP address for local request:

If you dont known the robot IP address to use in dorita980.Local() you can use dorita980.getRobotIP() to find it. This process takes 1 or 2 seconds, so if you know the IP just use it explicity.

You need UDP brodcast enable in your network!

var dorita980 = require('dorita980');

dorita980.getRobotIP(function (ierr, ip) {
  if (!ierr) {
    var myRobotViaLocal = new dorita980.Local('MyUsernameBlid', 'MyPassword', ip);

    myRobotViaLocal.getMission().then((response) => {
      console.log(response);
    }).catch((err) => {
      console.log(err);
    });
  } else {
    console.log('error looking for robot IP');
  }
});

You can also use .discovery method to get all the robots discovery data:

You need UDP brodcast enable in your network!

var dorita980 = require('dorita980');

dorita980.discovery(function (ierr, data) {
  console.log(data);
});

Will print:

{ ver: '2',
  hostname: 'Roomba-xxxxxxxxxxxxx',
  robotname: 'Dorita',
  ip: '192.168.1.103',
  mac: '12:12:12:12:12:12',
  sw: 'v2.0.0-34',
  sku: 'R98----',
  nc: 0,
  proto: 'mqtt' }

Local API

The library send commands direclty over wifi to your robot. You dont need internet connection.

Methods

end()

Close the connection to the robot. Its important if you want to send commands via the official mobile app via Local network. There's maximum 1 connection at any time in local ntwork, so if your app is connected, the official mobile app only works via cloud access.

Meanwhile dorita980 is connect you can call other methods to send commands and listen for the events to get data. Just not call .end() method if you want. Meanwhile dorita980 is connected the official mobile app will then just go via the cloud to send commands to your robot.

getRobotState(Array waitForFields)

Get robot state but wait for waitForFields fields before return.

The robot push data to this state all the time. The state object start empty and the robot will increasing the data here over the time.

myRobotViaLocal.getRobotState(['batPct', 'bbchg3']).then((actualState) => {
  console.log(actualState);
});

Full state should contains:

{ netinfo:
   { dhcp: true,
     addr: 4294967040,
     mask: 4294967040,
     gw: 4294967040,
     dns1: 4294967040,
     dns2: 0,
     bssid: '12:12:12:12:12:12',
     sec: 4 },
  wifistat: { wifi: 1, uap: false, cloud: 4 },
  wlcfg: { sec: 7, ssid: '123123123123123123123123' },
  mac: '34:34:34:34:34:34',
  country: 'US',
  cloudEnv: 'prod',
  svcEndpoints: { svcDeplId: 'v005' },
  localtimeoffset: -180,
  utctime: 1487103319,
  pose: { theta: 61, point: { x: 171, y: -113 } },
  batPct: 100,
  dock: { known: true },
  bin: { present: true, full: false },
  audio: { active: false },
  cleanMissionStatus:
   { cycle: 'none',
     phase: 'charge',
     expireM: 0,
     rechrgM: 0,
     error: 0,
     notReady: 0,
     mssnM: 2,
     sqft: 29,
     initiator: 'manual',
     nMssn: 324 },
  language: 2,
  noAutoPasses: false,
  noPP: false,
  ecoCharge: false,
  vacHigh: false,
  binPause: false,
  carpetBoost: true,
  openOnly: false,
  twoPass: false,
  schedHold: false,
  lastCommand: { command: 'dock', time: 1487103424, initiator: 'manual' },
  langs:
   [ { 'en-US': 0 },
     { 'fr-FR': 1 },
     { 'es-ES': 2 },
     { 'de-DE': 3 },
     { 'it-IT': 4 } ],
  bbnav: { aMtrack: 45, nGoodLmrks: 15, aGain: 12, aExpo: 9 },
  bbpanic: { panics: [ 8, 8, 8, 14, 8 ] },
  bbpause: { pauses: [ 15, 0, 0, 0, 0, 0, 0, 0, 0, 17 ] },
  bbmssn:
   { nMssn: 323,
     nMssnOk: 218,
     nMssnC: 99,
     nMssnF: 1,
     aMssnM: 35,
     aCycleM: 31 },
  bbrstinfo: { nNavRst: 41, nMobRst: 0, causes: '0000' },
  cap: { pose: 1, ota: 2, multiPass: 2, carpetBoost: 1 },
  sku: 'R98----',
  batteryType: 'lith',
  soundVer: '31',
  uiSwVer: '4582',
  navSwVer: '01.09.09',
  wifiSwVer: '20902',
  mobilityVer: '5309',
  bootloaderVer: '3580',
  umiVer: '5',
  softwareVer: 'v2.0.0-34',
  tz:
   { events: [ { dt: 0, off: -180 }, { dt: 0, off: -180 }, { dt: 0, off: 0 } ],
     ver: 2 },
  timezone: 'America/Buenos_Aires',
  name: 'robotNAme',
  cleanSchedule:
   { cycle: [ 'none', 'none', 'none', 'none', 'none', 'none', 'none' ],
     h: [ 17, 10, 10, 12, 10, 13, 17 ],
     m: [ 0, 30, 30, 0, 30, 30, 0 ] },
  bbchg3:
   { avgMin: 158,
     hOnDock: 6110,
     nAvail: 1280,
     estCap: 12311,
     nLithChrg: 233,
     nNimhChrg: 0,
     nDocks: 98 },
  bbchg: { nChgOk: 226, nLithF: 0, aborts: [ 4, 4, 4 ] },
  bbswitch: { nBumper: 55889, nClean: 300, nSpot: 47, nDock: 98, nDrops: 300 },
  bbrun:
   { hr: 211,
     min: 48,
     sqft: 566,
     nStuck: 17,
     nScrubs: 85,
     nPicks: 592,
     nPanics: 178,
     nCliffsF: 1532,
     nCliffsR: 2224,
     nMBStll: 0,
     nWStll: 1,
     nCBump: 0 },
  bbsys: { hr: 6522, min: 54 },
  signal: { rssi: -43, snr: 40 } }

getPreferences()

Get full robot state but wait for ['cleanMissionStatus', 'cleanSchedule', 'name', 'vacHigh', 'pose'] fields before return.

Alias for getRobotState(['cleanMissionStatus', 'cleanSchedule', 'name', 'vacHigh', 'pose', 'signal'])

Waiting for 'signal' we are sure we have the full state object.

setPreferences(newPreferences)

Partial overwrite the robot state to configure it.

var newPreferences = { 
 binPause: false
};

myRobotViaLocal.setPreferences(newPreferences)

Response:

{"ok":null}

getMission()

With this you can draw a map :)

{ cleanMissionStatus:
   { cycle: 'none',
     phase: 'charge',
     expireM: 0,
     rechrgM: 0,
     error: 0,
     notReady: 0,
     mssnM: 15,
     sqft: 0,
     initiator: 'localApp',
     nMssn: 323 },
  pose: { theta: -160, point: { x: 166, y: -11 } } }

getWirelessStatus()

{ wifistat: { wifi: 1, uap: false, cloud: 4 },
  netinfo:
   { dhcp: true,
     addr: 3232235880,
     mask: 4294967040,
     gw: 3232235777,
     dns1: 3232235777,
     dns2: 0,
     bssid: 'c0:56:27:70:3b:fe',
     sec: 4 } }

getTime()

1487100141

getBbrun()

 { hr: 211,
   min: 48,
   sqft: 566,
   nStuck: 17,
   nScrubs: 85,
   nPicks: 592,
   nPanics: 178,
   nCliffsF: 1532,
   nCliffsR: 2224,
   nMBStll: 0,
   nWStll: 1,
   nCBump: 0 }

getLangs()

 [ { 'en-US': 0 },
   { 'fr-FR': 1 },
   { 'es-ES': 2 },
   { 'de-DE': 3 },
   { 'it-IT': 4 } ]

getSys()

{ bbrstinfo: { nNavRst: 41, nMobRst: 0, causes: '0000' },
  cap: { pose: 1, ota: 2, multiPass: 2, carpetBoost: 1 },
  sku: 'R98----',
  batteryType: 'lith',
  soundVer: '31',
  uiSwVer: '4582',
  navSwVer: '01.09.09',
  wifiSwVer: '20902',
  mobilityVer: '5309',
  bootloaderVer: '3580',
  umiVer: '5',
  softwareVer: 'v2.0.0-34',
  audio: { active: false },
  bin: { present: true, full: false } }

getWirelessLastStatus()

{ wifi: 1, uap: false, cloud: 4 },
  wlcfg: { sec: 7, ssid: '1234567890796857336364' }

getWeek()

Monday disable and every day start at 10:30am

{ cycle: [ 'none', 'none', 'none', 'none', 'none', 'none', 'none' ],
  h: [ 17, 10, 10, 12, 10, 13, 17 ],
  m: [ 0, 30, 30, 0, 30, 30, 0 ] }

setWeek(newWeek)

Disable Sunday and set every day at 10:30am

var newWeek = {"cycle":["none","start","start","start","start","start","start"],"h":[10,10,10,10,10,10,10],"m":[30,30,30,30,30,30,30]}
myRobotViaLocal.setWeek(newWeek)

Response:

{"ok":null}

getCloudConfig()

prod

start()

{"ok":null}

pause()

{"ok":null}

stop()

{"ok":null}

resume()

{"ok":null}

dock()

Note: before dock you need to pause() or stop() your robot.

{"ok":null}

Simplifications to set Cleaning Preferences:

This methods use setPreferences() with the correct flags for each setting.

setCarpetBoostAuto()

{"ok":null}

setCarpetBoostPerformance()

setCarpetBoostEco()

setEdgeCleanOn()

setEdgeCleanOff()

setCleaningPassesAuto()

setCleaningPassesOne()

setCleaningPassesTwo()

setAlwaysFinishOn()

setAlwaysFinishOff()

Events

connect event

Emitted on successful Connection.

function () {}

Put your code inside this callback.

close event

Emitted after a disconnection.

offline event

Emitted when the client goes offline.

update event

Emitted every time the Robot publish a new message to the mqtt bus.

function (data) {}

  • data Data published by the Robot
myRobotViaLocal.on('update', function (data) {
 console.log(data);
});

Will print:

{ state:
   { reported:
      { soundVer: '31',
        uiSwVer: '4582',
        navSwVer: '01.09.09',
        wifiSwVer: '20902',
        mobilityVer: '5309',
        bootloaderVer: '3580',
        umiVer: '5',
        softwareVer: 'v2.0.0-34' } } }

mission event

Emitted every emitIntervalTime milliseconds with the mission data. (util for mapping)

function (data) {}

  • data Mission data with cleanMissionStatus and pose state properties.
var cleanMissionStatus = 300; // default is 800ms
var myRobotViaLocal = new dorita980.Local('MyUsernameBlid', 'MyPassword', '192.168.1.104', 2, cleanMissionStatus); // Note Firmware version.

myRobotViaLocal.on('mission', function (data) {
  console.log(data);
});

Will print each 300ms:

{ cleanMissionStatus:
   { cycle: 'none',
     phase: 'charge',
     expireM: 0,
     rechrgM: 0,
     error: 0,
     notReady: 0,
     mssnM: 15,
     sqft: 0,
     initiator: 'localApp',
     nMssn: 323 },
  pose: { theta: -160, point: { x: 166, y: -11 } } }

state event

Emitted every time the Robot publish a new message to the mqtt bus.

function (data) {}

  • data Full robot state object
myRobotViaLocal.on('state', function (data) {
 console.log(data);
});

Will print the Full robot state!

Cloud API

Not implemented yet in Firmware 2.0.0. Help wanted!

Note for node.js v0.10 users

dorita980 is compatible with node.js > 4.0 But you can use the getpassword feature in node.js < 4.0 using --harmony flag like that:

$ node --harmony ./bin/getpassword.js "192.168.1.104"

Author

dorita980's People

Contributors

koalazak avatar kavod avatar jtscott avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.