1   Introduction

This post reports on my efforts to learn ways to send messages between hosts (nodes, devices) on a local network (LAN). It describes my attempts to learn technologies that might be useful in implementing capabilities that enable the IoT (Internet of things).

pyre is a Python implementation of zyre.

A brief description of pyre:

"Pyre - an open-source framework for proximity-based peer-to-peer applications -- Pyre does local area discovery and clustering. A Pyre node broadcasts UDP beacons, and connects to peers that it finds. This class wraps a Pyre node with a message-based API."

You can learn about pyre here: https://github.com/zeromq/pyre.

And, information about zyre is here: https://github.com/zeromq/zyre.

Both pyre and zyre are built on top of ZeroMQ. See: http://zeromq.org/ and https://github.com/zeromq.

1.1   Requirements and what it runs on

It requires Python and pyre. pyre requires pyzmq.

I've tested the attached scripts with both Python 2.7 and Python 3.x.

I've run the dealer and clients on a Raspberry Pi (running Raspbian GNU/Linux 8 (jessie)), a laptop (running Ubuntu 17.10 GNU/Linux), and a desktop machine (also running Ubuntu 17.10 GNU/Linux).

So, that gives us some breadth of platforms on which to run pyre. You will have to try it in order to learn whether it runs on your device.

2   Installing pyre

I use virtualenv and virtualenvwrapper. See: https://virtualenvwrapper.readthedocs.io/en/latest/

Then, install pyre with this:

$ pip install https://github.com/zeromq/pyre/archive/master.zip

I normally use pyre under Python 3, but it seems to work fine under Python 2.7, also.

3   Sample code

There is some sample code:

You should be able to start the client on several hosts in your local network, and then start the dealer/server to send messages to those clients. You will need to repeatedly press Enter on the clients and the dealer to send each individual message.

4   Notes about the sample code

4.1   The dealer

pyre_dealer01.py creates a pyre node and sets the header.

It then sends messages to members of the group. The message content and the number of messages sent depend on command line options.

The body of the message (the "payload") is a Python dictionary that was converted to JSON.

Because that payload is a Python string, we send it with node.shouts('group1', string_payload). If the payload were a byte array (Python type bytes), we would send it using node.shout('group1', bytes_payload).

4.2   The client

pyre_client01.py creates a pyre node, the joins the group "group1".

The client uses node.recv() to wait for and receive messages.

Each message is a list. The first item in the list is the message type.

The client skips messages until it receives a message whose type is b'SHOUT', which is a message to the group.

It prints a message and then waits for the user to press Enter or enter a "q" to quit.

5   Hints and suggestions

5.1   Sending messages

Summary:

  • To send messages to a group, use node.shout('group1', bytes) or node.shouts('group1', string). This assumes that each peer that is to receive the message has done node.join('group1').
  • To send messages to a specific node, use node.whisper(uuid, bytes) or node.whispers(uuid, string). You can use node.peers() to get a list of the UUIDs of active peers
  • To send messages that are byte arrays, use node.whisper(uuid, byte_array) or node.shout(group, byte_array).
  • To send messages that are strings, use node.whispers(uuid, message_string) or node.shouts(group, message_string).

5.2   Peers and UUIDs

Start a peer with the following:

node = pyre.Pyre()
node.set_header('description', 'peer on host apple')
node.set_header('hostname', 'apple')
node.start()

Once peers have been started, then on another host machine, you can get a list of the UUIDs of all the peers that have been started with the following:

peers = node.peers()

5.3   Headers

Each call node.set_header(key, value) adds an item to a dictionary. So, on one host, you could do:

node = pyre.Pyre()
node.set_header('description', 'peer on host apple')
node.set_header('hostname', 'apple')
node.start()

And, then on another host in the same LAN, you could do:

peers = node.peers()
headers = node.peer_headers(peers[0])
hostname = headers.get('hostname')
description = headers.get('description')

- Dave Kuhlman