Tag Archives: Messaging

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()

Send Message to GIS or Revit from a Terminal using RabbitMQ, Python, Pika and C#

19 Apr

I have been playing with messaging in software applications. Using RabbitMQ, C# and Python, I got the bright idea to send messages to GIS from a python console – which will later be another program or windows form, but for demo purposes I just needed to verify the possibility. The SDK for my GIS is in C#, and so is the SDK for Revit.
I will show you what I did in GIS and then explain how this would work in Revit.
First, I sent a message to the GIS software.
20130419-081234.jpg
The DOS window is my command center that sends the messages. You can see that there are two commands: one has JOE and one has PAUL in it. You can send messages to every listener, or you can specify a keyword or word pattern – in this case PAUL and JOE are the keywords. My GIS app will only receive messages sent to PAUL. When you click the button, it grabs all waiting messages.
If I can send text, I can send data too. What if I send coordinates? I can draw them in the map.
20130419-081352.jpg
Now it takes the message and does something with it. This example has the sender and receiver on the same machine, but they do not have to be. So for Revit, what if we had a window that could update schedules in Revit with data. A user could input the data and the Revit user could press a button to update the model with the new data. Perfect for additional fields in a schedule. Or you could set it to run as a thread so when a message comes in the box pops up automatically. Here is the Code for the Plugin:
string msg = null;
var connectionFactory = new ConnectionFactory();
IConnection connection = connectionFactory.CreateConnection();
IModel 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, “Status”);

}
else
{
MessageBox.Show(“No Messages Waiting.”, “Status”);
}
And the sender in python:
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()

Messaging in Python with RabbitMQ and Pika

17 Apr

I just started using RabbitMQ and Pika and sent a message – “hello world!” Cool, but so what. I threw an IF statement in my code to simulate reading the message and doing different tasks based on the content of the message. This is better, but still interested in doing more. How about sending binary data – files?

Sure!

I modified the simple tutorial producer and consumer to send a JPG. The producer opens a jpg image in binary mode RB and reads it to a variable. It then sends that variable to the queue.

The consumer knows to expect a jpg – but you could code all this in assuming it doesn’t know. It opens a blank file, gets the message and writes it to the file in binary mode – wb.

This is cool. Now we can send tasks – files to be operated on. And these tasks can be sent to multiple workers.

Here is the code:

SEND.PY

import pika
import logging
f=open(“image.jpg”,”rb”)
i=f.read()

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

channel.queue_declare(queue=’hello’)

channel.basic_publish(exchange=”,routing_key=’hello’,body=i)
print ” [x] Sent ‘Hello World!'”
connection.close()

 

CONSUME.PY

import pika

f=open(“outputimage.jpg”,”wb”)

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

channel.queue_declare(queue=’hello’)

print ‘ [*] Waiting for messages. To exit press CTRL+C’

def callback(ch, method, properties, body):
f.write(body)
f.close()
channel.basic_consume(callback,
queue=’hello’,
no_ack=True)

channel.start_consuming()

RabbitMQ, Python and C#

17 Apr
C# consuming a message from python producer via RabbitMQ.

C# consuming a message from python producer via RabbitMQ.

I don’t know much about software patterns. My applications tend to be more of the script variety – though I throw some OOP in for fun. I recently came across RabbitMQ – a message broker. It sits between producers and consumers of messages – it is the queue. I tested out the python hello world example and then got the bright idea to use C# as one piece. The thing about RabbitMQ is that it uses a standard Advanced Messaging Queuing Protocol. This means any language or application that implements that protocol can communicate – think HTTP or FTP protocols.

Here is the python producer taken from the RabbitMQ Tutorial. You will need pika.

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

channel.queue_declare(queue=’hello’)

channel.basic_publish(exchange=”,routing_key=’hello’,body=’Hello World!’)
print ” [x] Sent ‘Hello World!'”
connection.close()

 

Simple enough. Now I wrote a C# form that consumes the messages onClick of a button and displays them in a text box – appending the new messages as they come in.

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;

 

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
var connectionFactory = new ConnectionFactory();
IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel();
channel.QueueDeclare(“hello”, false, false, false, null);
BasicGetResult result = channel.BasicGet(“hello”, true);
if (result != null)
{
string message = Encoding.UTF8.GetString(result.Body);

textBox1.Text += message+”\r\n”;
}

channel.Close();
connection.Close();
}
}
}