ProjectSPAN / android-manet-manager

SPAN - Android Manet Manager
72 stars 37 forks source link

Details on how best to integrate with Manet-Manager #4

Open duhmojo opened 11 years ago

duhmojo commented 11 years ago

Hi. I've been working with olsrd and MeshTether as a MANET base for a OSM Map based app where MANET nodes can broadcast and share their location with each other. (other ideas and features to follow) I just recently found out about the great work you're doing with the SPAN project and Manet Manager. (great stuff, I'm particularly jazzed about the quality of the code)

I'm at the point where I need to collect routing and topology information for my app in order to draw node arcs. This is particularly helpful when viewing nodes on a map and trying to determine if a structure is blocking communication, etc...

I took a look at your code and noticed that you build olsrd with the txtplugin running on port 2006. If I switched to Manet Manager, which seems much more functional that MeshTether, txtplugin is already running, but given that you're building a suite of apps that build on Manet Manager, I thought you might have another app-to-app integration approach, such as broadcasting intents wider than just the Manet Manager app.

If you do, please let me know so I can start looking at it. Thanks and keep up the great work.

jrobble commented 11 years ago

Cool. We've had a mesh-enabled map app on our wishlist for a while now but no time to work in it. We're glad to hear about your project.

Thanks for the code quality comment. Our focus is on developing a mesh platform and API for developers like you to write your apps.

Initially the Manet Manager app was two separate apps, the Manet Service and the Manet Manager (a simple GUI front end to the Manet Service). The division is still clear in the package hierarchy: org.span.manager and org.span.service

The Manet Manager interacts with the Manet Service by using the ManetHelper object. Take a look at line 110 here: https://github.com/ProjectSPAN/android-manet-manager/blob/master/AndroidManetManager/src/org/span/manager/MainActivity.java

// ... app.manet.registerObserver(this); // ...

In this line the MainActivity registers with the ManetHelper. The registerObserver() method takes a ManetObserver as a parameter. The MainActivity implements the ManetObserver interface so it can receive callbacks, which are listed here: https://github.com/ProjectSPAN/android-manet-manager/blob/master/AndroidManetManager/src/org/span/service/ManetObserver.java

Specifically, you're interested in the onRoutingInfoUpdated() callback, which gets invoked when ManetHelper.sendRoutingInfoQuery() is called.

To make things short:

  1. Include libmanet.jar in your app.
  2. Have your activity implement ManetObserver.
  3. Create a ManetHelper object.
  4. Register your activity with the ManetHelper.
  5. Invoke ManetHelper.connectToService().
  6. Invoke ManetHelper.sendRoutingInfoQuery().
  7. Do whatever you want with the routing info passed in as a parameter to the ManetObserver.onRoutingInfoUpdated() method implemented by your activity.

Right now the routing info is passed as a String, so it needs to be parsed. You can use ManetParser.parseOLSR() to do that for you. It will return an array of strings of the form "A>B", where A is the IP address of node A and B is the IP address of node B. "A>B" represents a directed edge. The Manet Visualizer app makes use of this edge info.

You can also look into ManetHelper.sendPeersQuery() and ManetObserver.onPeersUpdated(). The latter method will return a set of Node objects to you, where each node has an IP address, list of Edges, and other useful info. The "peers" methods are meant to replace the "routingInfo" methods.

The Manet Voice Chat app makes use of the ManetHelper to periodically get a list of peers.

I hope this helps. Let us know if you run into any problems.

duhmojo commented 11 years ago

Wow, thanks for the great write up. I'll try implementing my own ManetObserver as a way of triggering changes in my app. From what I can tell onRoutingInfoUpdated should include basically the output from txtinfo-plugin (when using Olsrd), which is great.

As for my Mapping app, I used OSMdroid (http://code.google.com/p/osmdroid/). It's tries to mimic Google's Maps API, with some differences and limitations, but it does allow for offline map loadings and caching. If you just use the API as is, anything you visit in the map will be automatically cached in a tile store on the device. But I spent some time digging and was able to load my own offline map tile sets created with MOBAC (Mobile Atlas Creator). The map atlas file needs to be loaded into your app, I ended up including it as a raw file for now. The great thing about using a Mapping API is nodes can be arranged based on their real GPS location and the easiest way to do this is with a Mapping API that already deals with map tiles and GeoPoint locations. Zooming, callbacks for single and long presses are all there. Google Maps API doesn't support offline or map tile caching. It's against their terms of service and the API actually missing functionality for caching.

I can't share this project on Github as is, but I think after I finish put together a Manet Manager Mapping app to plot other connected devices. Handling the map tiles in a user friendly way is the only challenge.

Thanks again.

jrobble commented 11 years ago

Yep, onRoutingInfoUpdated() is just a text dump of the txtinfo-plugin.

We're looking forward to trying out your Manet Mapping app. Once cool thing to plot is the effective range of each device so you know when you're in range, out of range, and where to position yourself to maximize hopping distance. You can use a 200 ft radius as a good heuristic.

Good luck!

daviddoria commented 11 years ago

I have only been concerned with starting the Manet Manager, not stopping it. But to facilitate that, I added a function to ManetHelper:

public void bindToService() {
    Intent i = new Intent().setComponent(new ComponentName("org.span", "org.span.service.core.ManetService"));
    serviceConn = new ManetServiceConnection();
    context.bindService(i, serviceConn, Context.BIND_AUTO_CREATE);

    mBound = true;
}

that binds to the service without (re)starting it. This seems to behave better for me and is much faster.

daviddoria commented 11 years ago

I've also been using this: https://gist.github.com/daviddoria/e34c6ee2c4b5447a8800 as a way to force the user to wait until the ad-hoc mode is enabled before returning focus to the app.

jrobble commented 11 years ago

Do you use bindToService() instead of connectToService()? Note that the startService() call is idempotent:

"If this service is not already running, it will be instantiated and started (creating a process for it if needed); if it is running then it remains running."

jrobble commented 11 years ago

Thanks for sharing ManetStarter. It stresses the importance of waiting to call sendStartAdhocCommand() until the after onServiceConnected() callback has been invoked.

daviddoria commented 11 years ago

I do use bindToService() instead of connectToService(). I think I was getting an error or a delay or something. I should have taken better notes... I'll try it again at some point (but can't promise how soon...).

jrobble commented 11 years ago

One important piece that seems to be lacking from bindToService() that's in connectToService() is the following:

// create receive messenger receiveMessenger = new Messenger(new IncomingHandler());

daviddoria commented 11 years ago

Did you forget to paste something :) ?

jrobble commented 11 years ago

I edited the comment with the code.

daviddoria commented 11 years ago

Ah, I forgot to mention some other things I did. I believe I left out creating a new Messenger with each call to bindToService because I was getting errors when the device orientation changed (it was trying to restart to the service each time, complaining about things being re-registered, etc.). I made ManetHelper a singleton and made my UI a fragment and made the fragment persistent. Therefore once connectToService was called once, that was enough to keep everything connected. I was pretty sure you would not want that as the standard behavior, so I did not submit a patch to that effect.

jrobble commented 11 years ago

I see. Thanks for the explanation.