Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for FW version 3 and Braava m6 #103

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

peci1
Copy link

@peci1 peci1 commented Dec 26, 2019

I got Roomba i7 and Braava m6, both with firmware 3.2. I needed to do some changes to support FW version 3, and also to support Braava robots. I'm not sure I captured all the differences between v2 and v3, and between roomba and braava robots. But I think this could be a good start.

This might also be a solution for koalazak/rest980#44 .

@koalazak
Copy link
Owner

nice! @peci1 can you update the readme to reflect the new version option. Also update the package.json to increase the minor version value?
is npm run test passing with your changes?

Also, I don't own a m6 robot to test your changes, So to be cautious I would like someone else to test and confirm that all this branch is working with several robots models.

I'm going to leave the PR open until someone else tests this, ok? HELP WANTED!

thank you very much!

@peci1
Copy link
Author

peci1 commented Jan 14, 2020

I fixed a few style hints from the linter. Otherwise, tests run fine.

@thorazine-12
Copy link

thorazine-12 commented Jan 20, 2020

@peci1, does updated getMission() work with your i7/m6? It doesn't work for me (on my i7/m6), will check this more deeply tomorrow.

Also I try to get info required for cleanRoom, but my m6 reports lasCommand data this way:

lastCommand: {
    command: 'start',
    initiator: 'rmtApp',
    time: 1579099749,
    ordered: 0,
    pmap_id: '1lHG_7bGROmxe5Tcg8U1qQ',
    regions: [ [Object] ],
    user_pmapv_id: '200112T134556'
  },

How can I decode regions data?

@peci1
Copy link
Author

peci1 commented Jan 20, 2020

What do you mean by updated getMission()? Did you try with the robots activated (i.e. not sleeping) and parked in home base? For me, getMission() doesn't work on sleeping robots. Try to give it a task with your phone, then stop them, park them, and try getMission(). Or you can even try calling getMission() during an actual mission, that should work. On my irobots, the experimental map feature works, and it is based on getMission().

Also, are you sure your robots have up-to-date firmware?

Do you try using the API directly or via rest980? If latter, could test with koalazak/rest980#46 ?

About regions: I haven't investigated that yet...

@thorazine-12
Copy link

thorazine-12 commented Jan 21, 2020

Well I think that I have newest firmware: 3.2.4 (Roomba) and 3.2.5 (Braava).
In fact getMission is not very important to me but cleanRoom is essential - especially for using m6.
Both i7 and m6 return [Object] data in the regions field - here is what I get from Roomba:

  lastCommand: {
    command: 'start',
    initiator: 'localApp',
    time: 1579632664,
    ordered: 0,
    pmap_id: 'RG3hl73tTq2vpwljyUv8yw',
    regions: [ [Object] ],
    user_pmapv_id: '200116T202620',
    event: null
  }

As to the getMission() - I've checked and getRobotState(['pose']) wait until robot starts its mission, if it is in dock/pause/stop it doesn't return any values.

Another issue: when I do getRobotState(['mopReady']) on m6 with updated dorita, I have:

pi@raspberrypi:~/www/plugins $ node test.js mopready
undefined

when I execute the same command, but with original (master) branch, I get:

pi@raspberrypi:~/www/plugins $ node test.js mopready
{ tankPresent: true, lidClosed: true }

EDITED:
I've just solved problem with [Object] reply in regions field :)
It seems that [Object] reply is returned when I do getRobotState with more than 1 params, for example when I execute getRobotState['cleanMissionStatus', 'lastCommand'].
But with getRobotState['lastCommand'] I get proper values:

{
  command: 'start',
  initiator: 'rmtApp',
  time: 1579099749,
  ordered: 0,
  pmap_id: '1lHG_7bGROmxe5Tcg8U1qQ',
  regions: [
    {
      region_id: '23',
      region_name: 'Kuchnia',
      region_type: 'dining_room'
    }
  ],
  user_pmapv_id: '200112T134556'
}

@thorazine-12
Copy link

I find out why dorita generated 'undefined' reply for some request.
It seems that my braava was not recognized correctly in local.js.
Since I don't know how to fix it, I just changed this

  const modelProps = {
    'roomba': ['bin'],
    'braava': ['detectedPad', 'mopReady', 'padWetness']
  };

to this:

  const modelProps = {
    'roomba': ['bin'],
    'braava': ['blahblah']
  };

to make sure I can get with getRobotState any field I want.
And now it works, I can get info about mopReady and detectedPad with no problem.

I don't know why m6 is not recognized. This is what I get with getRobotState(['sku']):

pi@raspberrypi:~/www/plugins $ node irobot.js roomba get sku
i755040
pi@raspberrypi:~/www/plugins $ node irobot.js braava get sku
m613840

@peci1
Copy link
Author

peci1 commented Jan 29, 2020

@thorazine-12 could you please try getRobotState() on all of 'detectedPad', 'mopReady', 'padWetness' separately? So that we can know which one of these doesn't work for you...

@sohsatoh
Copy link

sohsatoh commented Aug 31, 2020

The problem is that there is no 'pose' information when it is not cleaning.
I have confirmed it with my braava m6.

@sohsatoh
Copy link

sohsatoh commented Aug 31, 2020

I tested it by editing the local.js file as follows

...
// Added
 const defaultPose= {
    "theta":0,
    "point": {
      "x":0,
      "y":0
    }
  }
...
  client.on('packetreceive', function (packet) {
    if (packet.payload) {
      try {
        const msg = JSON.parse(packet.payload.toString());
        robotState = Object.assign(robotState, msg.state.reported);
        if(!robotState.pose) {
         // Added
          console.log('pose could not find');
          robotState.pose = defaultPose;
        }
        client.emit('update', msg);
        client.emit('state', robotState);
        if (robotState.cap) {
          cap = {};
          cap = Object.assign(cap, robotState.cap);
        }
        if (robotState.sku && robotState.sku.toLowerCase().startsWith('m6')) {
          model = 'braava';
        }
      } catch (e) {}
    }
  });

Then getMission worked fine.
This is not a beautiful fix though.

To my understanding, the way of Braava m6 locating their position is based on the position where it docked at home base.
When Braava m6 is docked, the positional values will be 0 for both angles, x, and y. So there is no need to return location information.

However, on my Roomba 960, here's the information when it's docked.
pose":{"theta":67,"point":{"x":-5,"y":-4}}
Presumably, all models with the Imprint Smart Mapping feature should return information like that, but I only have the Roomba 960 and Braava m6, so I can't be sure.

@dcmeglio
Copy link

dcmeglio commented Sep 8, 2020

Just curious, what's holding this up from getting merged? Really wish this project supported braava... seems like there hasn't been much movement other than a few readme updates lately.

@koalazak
Copy link
Owner

koalazak commented Sep 9, 2020

Hello @dcmeglio, I will merge the PR when the author and several people who own both type of robots (vaccum and mop) confirm that both robots works fine together at the same time and all features works fine at least in vaccum robot. At the moment looks like nobody confirm this ☝️ and there is no a solid PR, just suggestions and troubleshooting.
I do not own a bravaa so I can't test on my side to support it :/

donations are welcome to help me to get extra robots and extend features of this library: https://opencollective.com/dorita980

thank you

@dcmeglio
Copy link

I tested it by editing the local.js file as follows

...
// Added
 const defaultPose= {
    "theta":0,
    "point": {
      "x":0,
      "y":0
    }
  }
...
  client.on('packetreceive', function (packet) {
    if (packet.payload) {
      try {
        const msg = JSON.parse(packet.payload.toString());
        robotState = Object.assign(robotState, msg.state.reported);
        if(!robotState.pose) {
         // Added
          console.log('pose could not find');
          robotState.pose = defaultPose;
        }
        client.emit('update', msg);
        client.emit('state', robotState);
        if (robotState.cap) {
          cap = {};
          cap = Object.assign(cap, robotState.cap);
        }
        if (robotState.sku && robotState.sku.toLowerCase().startsWith('m6')) {
          model = 'braava';
        }
      } catch (e) {}
    }
  });

Then getMission worked fine.
This is not a beautiful fix though.

To my understanding, the way of Braava m6 locating their position is based on the position where it docked at home base.
When Braava m6 is docked, the positional values will be 0 for both angles, x, and y. So there is no need to return location information.

However, on my Roomba 960, here's the information when it's docked.
pose":{"theta":67,"point":{"x":-5,"y":-4}}
Presumably, all models with the Imprint Smart Mapping feature should return information like that, but I only have the Roomba 960 and Braava m6, so I can't be sure.

Your fix doesn't work for me, the m6 does not respond to getmission

@peci1
Copy link
Author

peci1 commented Sep 26, 2020

I've implemented the fix with returning zero pose when braava is sleeping. getMission() should now return even in the sleeping robot case.

@peci1
Copy link
Author

peci1 commented Sep 26, 2020

I don't understand your problems, @thorazine-12 . You say you're using getRobotState() and the results differ depending on how many fields you wait to. But getRobotState() always returns all fields, so it can't depend on the number of passed fields. It seems to me that you had to use some custom function to query the robot state. Anyways, the problem with [ [Object] ] is most probably just a visualization issue. It wouldn't matter if you'd parse the reponse in javascript. If you print the value and parse the printed value, then you need to go one level deeper in the object structure and print e.g. actualState['lastCommand']['regions'] instead of actualState['lastCommand']. Or you can use any of the methods mentioned here: https://stackoverflow.com/questions/10729276/how-can-i-get-the-full-object-in-node-jss-console-log-rather-than-object .

@peci1
Copy link
Author

peci1 commented Sep 26, 2020

I'm not sure what was the reason @thorazine-12's braava was incorrectly detected, as the detection is done based on SKU, and his SKU also starts with m6, but I've added an option to pass the robot model as a parameter to the Local V2 API.

@peci1
Copy link
Author

peci1 commented Sep 26, 2020

Another issue: when I do getRobotState(['mopReady']) on m6 with updated dorita, I have:

pi@raspberrypi:~/www/plugins $ node test.js mopready
undefined

@thorazine-12 in this part, you actually query mopready and not mopReady. That would explain the error...

@peci1
Copy link
Author

peci1 commented Sep 27, 2020

This is the output of my i7 when I query multiple fields and print just the lastCommand - I see no problem:

 myRobotViaLocal.getRobotState(['lastCommand', 'cleanMissionStatus']).then((actualState) => {
        lastCommand = actualState['lastCommand'];
        console.log(lastCommand);
  });
{
  command: 'start',
  initiator: 'localApp',
  time: 1601201384,
  ordered: 1,
  pmap_id: 'bkG1Rw8DQ1-vlGddUgnyyg',
  regions: [ { region_id: '1', type: 'rid' } ],
  user_pmapv_id: '191223T134605'
}

@peci1
Copy link
Author

peci1 commented Sep 27, 2020

It seems that braava m6 does not include regions in lastCommand at all. But that also might be given by the fact that my braava has only maps each with a single region...

@dcmeglio
Copy link

When I use rest980 and go to /api/local/info/mission for my m6, the browser just spins and doesn't load. Works fine for both of my i7's though. /api/local/info/state works fine for the m6. Nothing in syslog when I call mission. I'm using your latest code. Anything I can do to help track this down?

@peci1
Copy link
Author

peci1 commented Sep 29, 2020

Maybe the autodetection of robot type also doesn't work for you? You can try creating the local API with

myRobotViaLocal = Local(username, password, ip, 800, 3, "braava");

Also, are all of 'detectedPad', 'mopReady', 'padWetness' present in your state?

@dcmeglio
Copy link

dcmeglio commented Sep 29, 2020

I’ll have to test tomorrow when I’m at a pc, but yea those three values show up in the state output. And FYI my sku starts with m6

@dcmeglio
Copy link

@peci1 sorry I never replied. No, when I change to using what you pasted above it still doesn't work. As I said though, all those values appear in state. Calling /api/local/info/mission for my two i7s works fine though. Anything else I can do to help debug?

@peci1
Copy link
Author

peci1 commented Oct 25, 2020

How do you actually test the changes? Do you have a rest980 project checked out in some directory and edit dorita980 directly in the node_modules subdirectory? Also, do you test rest980 with the changes from koalazak/rest980#46 ?

@dcmeglio
Copy link

Yes to both your questions.

@sohsatoh
Copy link

@dcmeglio Please make sure your server address is not the same as the Roomba's, etc. It works fine in my environment.
{"cleanMissionStatus":{"cycle":"none","phase":"charge","expireM":0,"rechrgM":0,"error":0,"notReady":31,"mssnM":24,"sqft":75,"initiator":"rmtApp","nMssn":69},"pose":{"theta":0,"point":{"x":0,"y":0}},"batPct":100,"detectedPad":"reusableWet","mopReady":{"tankPresent":false,"lidClosed":true},"padWetness":{"disposable":2,"reusable":2}}

@dcmeglio
Copy link

If the ip were the issue, then no endpoint would work. Only the mission endpoint fails for me

@sohsatoh
Copy link

@dcmeglio Did you replace dorita980 in node_modules of rest980 properly?
I can't think of any other reason other than it's loading dorita980 from a higher level directory, etc.

@dcmeglio
Copy link

@dcmeglio Did you replace dorita980 in node_modules of rest980 properly?
I can't think of any other reason other than it's loading dorita980 from a higher level directory, etc.

You were absolutely right. There was a local copy I didn’t see causing the issue. Working fine now!

@peci1
Copy link
Author

peci1 commented Nov 11, 2020

@dcmeglio Great! Thanks for reporting.

@SerhiiAksiutin
Copy link

I replaced #103 in koalazak/rest980#46. Getting this error with "firmwareVersion": 3,:

> [email protected] start /home/pi/rest980
> node ./bin/www

/home/pi/rest980/node_modules/dorita980/lib/v2/cloud.js:7
  throw new Error('Not implemented.');
  ^

Error: Not implemented.
    at dorita980 (/home/pi/rest980/node_modules/dorita980/lib/v2/cloud.js:7:9)
    at new cloud (/home/pi/rest980/node_modules/dorita980/index.js:12:10)
    at /home/pi/rest980/routes/api.js:33:46
    at handleIP (/home/pi/rest980/routes/api.js:26:68)
    at Object.<anonymous> (/home/pi/rest980/routes/api.js:27:1)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/home/pi/rest980/app.js:11:16)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/home/pi/rest980/bin/www:7:11)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `node ./bin/www`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/pi/.npm/_logs/2021-06-21T09_29_14_385Z-debug.log```

@SerhiiAksiutin
Copy link

Anything?

@dcmeglio
Copy link

dcmeglio commented Nov 5, 2021

Are the fixes here ever going to be merged? I know many of us are using this. It really stinks that I can't use your npm package or docker container because this fix isn't applied

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants