Tag Archives: SDK

Auto Message Popups in ArcGIS Desktop Explorer From RabbitMQ

19 Apr
Message sent from terminal to ArcGIS Desktop Explorer Extension.

Message sent from terminal to ArcGIS Desktop Explorer Extension.

My previous post showed how to send messages to GIS from a terminal using Python-Pika, RabbitMQ, and C#. It required the user to click a button to receive them. I have modified code from several sources to make it run on a thread- as an extension to ArcGIS Desktop Explorer. Every 2 seconds, the extension checks for messages.

I modified code from:

LosTechies – For C#.

RabbitMQ Tutorial – For Python Producer.

And the ArcGIS Resource Center for the threading info.

I can send you the Addin .EAZ if you wish. Here is what I came up with:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using RabbitMQ.Client;

using ESRI.ArcGISExplorer;
using ESRI.ArcGISExplorer.Application;
using ESRI.ArcGISExplorer.Mapping;
using ESRI.ArcGISExplorer.Geometry;
using ESRI.ArcGISExplorer.Data;
using ESRI.ArcGISExplorer.Threading;
namespace RabbitMQgisExtension
{
public class Extension : ESRI.ArcGISExplorer.Application.Extension
{
string msg;
static IConnection connection;
static IModel channel;
System.Timers.Timer _t = new System.Timers.Timer(2000);

public override void OnStartup()
{
_t.Start();
_t.Elapsed += new System.Timers.ElapsedEventHandler(_t_Elapsed);

}

public override void OnShutdown()
{
_t.Stop();
channel.Close();
connection.Close();
}

void _t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
var connectionFactory = new ConnectionFactory();

connection = connectionFactory.CreateConnection();
channel = connection.CreateModel();
channel.ExchangeDeclare(“GIS”, ExchangeType.Direct);
channel.QueueDeclare(“GIS”, false, false, false, null);
channel.QueueBind(“GIS”, “GIS”, “PAUL”);
BasicGetResult result = channel.BasicGet(“GIS”, true);

if (result != null)
{
msg = Encoding.UTF8.GetString(result.Body);
MessageBox.Show(msg, “You’ve Got a Message!”);
//If set Message to send coords in form “35,-106” Next lines will draw points.
//string[] coords = msg.Split(‘,’);
// float x = float.Parse(coords[0]);
// float y = float.Parse(coords[1]);
//Note fromRabbit = new Note(“From RabbitMQ”, new ESRI.ArcGISExplorer.Geometry.Point(y, x));
//ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay.Map.ChildItems.Add(fromRabbit);
}
}

 

and the Python Producer – EXAMPLE: python send.py KEY TEXT

(python send.py PAUL message to you):

import pika
import sys

connection = pika.BlockingConnection(pika.ConnectionParameters(
host=’localhost’))
channel = connection.channel()

channel.exchange_declare(exchange=’GIS’,
type=’direct’)

to = sys.argv[1]
message = ‘ ‘.join(sys.argv[2:])

channel.basic_publish(exchange=’GIS’,
routing_key=to,
body=message)
print “Sent %r:%r” % (to, message)
connection.close()

Advertisements

Public Safety GIS 2: Python, MongoDB, C# and ArcGIS Desktop Explorer

17 Apr

I wrote a plugin for ArcGIS Desktop explorer that called a python script and passed the map center as an argument. The python script queried a MongoDB and wrote out a csv of closest points. The button then loads the csv as points. I had to do this because I didn’t know how to do it in C#. Well, I figured it out.

Now C# does all the work querying the database and drawing the points. I still have a python script that reads data from a csv export from sharepoint, geocodes it and creates the mongoDB.

Here is my code:

PYTHON TO CREATE THE DB:

from pymongo import Connection,GEO2D
import urllib, urllib2, simplejson
import csv

data = csv.reader(open(‘C:\Documents and Settings…\myfile.csv’))
fields=data.next()
db=Connection().rtcc
db.cnau.create_index([(“loc”,GEO2D)])

for row in data:
try:
address=row[0]
combinedaddress=address+”,albuquerque, NM”

param = {‘q’: combinedaddress,’output’: ‘json’, ‘oe’: ‘utf8’}
url = ‘http://maps.google.com/maps/geo?’ + urllib.urlencode(param)
rawreply = urllib2.urlopen(url).read()
reply = simplejson.loads(rawreply)
print reply[‘Placemark’][0][‘Point’][‘coordinates’][0]
long=reply[‘Placemark’][0][‘Point’][‘coordinates’][0]
lat=reply[‘Placemark’][0][‘Point’][‘coordinates’][1]
z={“loc”:[long,lat],”Activity”:row[1]}

db.cnau.insert(z)
except KeyError:
pass

 

C# TO PLUGIN ARCGIS DESKTOP EXLPORER:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGISExplorer;
using ESRI.ArcGISExplorer.Application;
using ESRI.ArcGISExplorer.Mapping;
using ESRI.ArcGISExplorer.Geometry;
using ESRI.ArcGISExplorer.Data;
using ESRI.ArcGISExplorer.Threading;

using MongoDB;
using MongoDB.Bson;
using MongoDB.Driver.Linq;
using MongoDB.Driver;
using MongoDB.Driver.Builders;

namespace MongoC
{
public class Button : ESRI.ArcGISExplorer.Application.Button
{

public override void OnClick()
{

Folder folderMapItem = new Folder();
MapDisplay mdisp = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay;

//use this to change the projections 35,-106
FeatureLayer proj = FeatureLayer.OpenShapefile(“C:\\Documents and Settings…\\forProjection.shp”);
// Path for Windows 7: FeatureLayer proj = FeatureLayer.OpenShapefile(“C:\\Users\\user\\…\\forProjection.shp”);
mdisp.CoordinateSystem2D = proj.CoordinateSystem;
string center = mdisp.Center.ToString();
folderMapItem.Name = “Close To Me”;
string[] c = center.Split(null);
String lon = c[3];
String lat = c[6];

MongoClient client = new MongoClient(); // connect to localhost. Deploy at: “mongodb://ip.of.host:27017”
MongoServer server = client.GetServer();
MongoDatabase db = server.GetDatabase(“rtcc”);

var collection = db.GetCollection<BsonDocument>(“cnau”);

var query = Query.Near(“loc”, double.Parse(c[3]), double.Parse(c[6]));
//var cursor = collection.Find(query); Put this in foreach so dont need it anymore.
foreach (BsonDocument item in collection.Find(query).SetLimit(5))
{
BsonElement loc = item.GetElement(“loc”);
string g = loc.Value.ToString();
string x = g.Trim(new Char[] { ‘[‘, ‘]’ });
String[] a = x.Split(‘,’);
// BsonElement name = item.GetElement(“name”); Work for all indexes in MongoDB
// Pass the other data to the notes popups below

ESRI.ArcGISExplorer.Geometry.Point mypoint = new ESRI.ArcGISExplorer.Geometry.Point(double.Parse(a[0]), double.Parse(a[1]));

// Create a Note using the Point geometry.
Note mypointNote = new Note(“MyNote”, mypoint, Symbol.Marker.Pushpin.Orange);

// Populate the Note popup with information about the Point geometry using the ToString method.
StringBuilder info = new StringBuilder(@”<p><a href=””http://google.com””>Google</a></p>&#8221;);
info.AppendLine(@”<p>” + mypoint.ToString() + @”</p>”);

//MapDisplay disp = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay;
mypointNote.Popup.Content = info.ToString();

// Add the Note to the current Map.
//mdisp.Map.ChildItems.Add(mypointNote);
folderMapItem.ChildItems.Add(mypointNote);
}

mdisp.Map.ChildItems.Add(folderMapItem);
}
}
}

Launch External Script in ArcGIS Desktop Explorer

24 Jan

arcgis_explorer_15001

I have started to toy with the ArcGIS Desktop Explorer API. My first few attempts at functionality required only the use of C# Libraries and not the actual SDK Library – with the exception of getting the button in.

If you have the SDK installed, you can start a new project in Visual Studio Express and select the GIS Button. This first example will allow you to execute a script or program on your machine. Where it tells you to insert your code, enter the following line:

 System.Diagnostics.Process.Start(“myPythonFile.py”);

This will run the python file. You could also use launch system applications like calc or notepad.

My next test was to launch a website from a button.  Same as the above, except enter the URL of the site. This will open the page in your default browser.

System.Diagnostics.Process.Start(“http://google.com&#8221;);

One thing I had trouble with was how do I add several buttons in a single Namespace? I copied the button that was created by default and pasted it in to the namespace. Then you need to change the name and the functionality. Lastly, you need to edit the AddIns.xml file. Copy the first button and paste it. Then modify the values to math your new button. I have put the values that MUST change in bold. You should change the captions too. Also, drag any images to the images folder. 32×32 for large and 16×16 for small.

<button
id=”Button1
assembly=”WebLaunchButtons.dll”
className=”WebLaunchButtons.Button1
caption=”Google”
tooltip=”Quick Access to Google.”
helpString=”http://mydomain.com&#8221;
largeImage=”Images\google.png”
smallImage=”Images\google_SmallImage.png” />

<button
id=”Button2
assembly=”WebLaunchButtons.dll”
className=”WebLaunchButtons.Button2
caption=”Yahoo!”
tooltip=”Quick Access to Yahoo.”
helpString=”http://mydomain.com&#8221;
largeImage=”Images\yahoo.png”
smallImage=”Images\yahoo_SmallImage.png” />

Now you will have 2 buttons in a frame with a single group title – you set this in the initial project settings.

My last example will connect to an FTP site, grab a shapefile, and load it. The code is a mashup of code from MSDN and ESRI as well as some modifications on my part.

public override void OnClick()
        {
            m_disp = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay;

            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(“ftp://ftp1.freebsd.org/pub/FreeBSD/README.TXT”); //this would be to a shapefile but I dont have an FTP server.
            request.Method = WebRequestMethods.Ftp.DownloadFile;

           
            //request.Credentials = new NetworkCredential(“me”, “mypassword”);

            FtpWebResponse response = (FtpWebResponse)request.GetResponse();

            Stream responseStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(responseStream);
            System.IO.StreamWriter file = new System.IO.StreamWriter(“c:\\downloaded.txt”); //your shapefile
            file.WriteLine(reader.ReadToEnd());
            
            reader.Close();
            response.Close();
            file.Close();

            FeatureLayer fl = FeatureLayer.OpenShapefile(“C:\\downloaded.shp”); // the file you saved
            fl.Renderer.SetSymbol(CreateSymbol(fl.GeometryType));
            m_disp.Map.ChildItems.Add(fl);
            m_disp.ZoomTo(fl.Extent);

            
        }

        private Symbol CreateSymbol(GeometryType geomType)
        {
            //Create a new symbol for the feature layer data being added based on feature type
            Symbol sym = null;
            switch (geomType)
            {
                case GeometryType.Point:
                    sym = Symbol.Marker.Pushpin.LightBlue;
                    break;
                case GeometryType.Polygon:
                    sym = Symbol.CreateFill(System.Drawing.Color.Aqua, System.Drawing.Color.Black);
                    break;
                case GeometryType.Polyline:
                    sym = Symbol.Line.Solid.Purple;
                    break;
            }

            return sym;
        }

    }

In my next post, I will show how to send an SMS text message from GIS.