evaluation of the zero mq socket library

71
Evaluation of the Zero MQ Socket Library by Alan Matthews This report is submitted in partial fulfilment of the requirements of the B.Sc. Honours Degree in Networking Applications & Services, of the Dublin Institute of Technology March 15 th , 2014 Supervisor: Mr Frank Duignan School of Electrical and Electronic Engineering

Upload: al-matthews

Post on 29-Dec-2015

106 views

Category:

Documents


4 download

DESCRIPTION

The principle objective of this paper is to investigate the Zmq messaging library.This was achieved using a Raspberry PI acting as a home monitoring system with several sensors. This system used the ZMQ messaging library, to send data to a server, which decides on appropriate action and sends messages back to the PI and alerts through social media and text.

TRANSCRIPT

Page 1: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ Socket Library

by

Alan Matthews

This report is submitted in partial fulfilment of the requirements of the B.Sc.

Honours Degree in Networking Applications & Services, of the Dublin

Institute of Technology

March 15th

, 2014

Supervisor: Mr Frank Duignan

School of Electrical and Electronic Engineering

Page 2: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 2 of 71

Acknowledgements

I would just like to take this opportunity to thank Ms Paula Kelly for her suggestions and

input on messaging oriented middleware, and Ms Brid Mcloughlin for her proof reading

and editorial services and most of all Mr Frank Duignan, for his time, effort and patience in

guiding and motivating me towards the completion of the project. His help and expertise,

were invaluable, and his contribution to the project was far beyond what was required or

expected of him.

Declaration

This final year project is presented in partial fulfilment of the requirements for a the B.Sc.

Honours Degree in Networking Applications & Services It is entirely my own work and

has not been submitted to any other university or higher education institutio n, or for any

other academic award in this University. The work was completed under the guidance of

Mr Frank Duignan. Furthermore, I took reasonable care to ensure that the work is original,

and, to the best of my knowledge, does not breach copyright law, and has not been taken

from other sources except where such work has been cited and acknowledged within the

text.

Signed _____________________________________________________

D.I.T Student Number _________________________________________

Date _______________________________________________________

Page 3: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 3 of 71

Table of Contents

Acknowledgements................................................................................................................ 2

Declaration............................................................................................................................. 2

Abstract .................................................................................................................................. 4

Chapter 1 Introduction ........................................................................................................... 5

Chapter 2 What is ZeroMQ ................................................................................................. 7

Chapter 3 ZeroMQ Sockets ................................................................................................... 9

Chapter 5 ZMQ Pattern Examples:...................................................................................... 19

Chapter 6 Implementation Motion sensor ........................................................................... 29

Chapter 7 Implementation Twitter....................................................................................... 32

Chapter 8 Implementation Analogue sensors ...................................................................... 34

Chapter 9 Implementation Adding the camera .................................................................... 39

Chapter 10 Implementation push button and outputs .......................................................... 42

Chapter 12 Implementation Outputs.................................................................................... 46

Chapter 13 Implementation Email ....................................................................................... 48

Chapter 14 Implementation Text Messaging....................................................................... 51

Chapter 15 Implementation Facebook ................................................................................. 54

Chapter 16 Discussion ......................................................................................................... 55

Conclusion ........................................................................................................................... 56

Bibliography ........................................................................................................................ 57

Appendices .......................................................................................................................... 58

Page 4: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 4 of 71

Abstract

The principle objective of this paper is to investigate the Zmq messaging library.

This was achieved using a Raspberry PI acting as a home monitoring system with several

sensors. This system used the ZMQ messaging library, to send data to a server, which

decides on appropriate action and sends messages back to the PI and alerts through social

media and text.

Some challenging aspects of this project were using analogue sensors with a digital system,

deciding on which ZMQ pattern to use, and adding an image to the text updates.

Each Module was built and tested separately before being integrated into the main system

The system successfully demonstrates a basic ZMQ Pattern.

Page 5: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 5 of 71

Chapter 1 Introduction

The initial plan for this project was for the Raspberry PI to act as a home monitoring

system with several sensors including both analogue and digital sensors. This system

would use the ZMQ messaging library to send data to a server, which would then decide

on appropriate action and send alerts through social media and text.

Several problems had to be addressed in this project including:

Which ZeroMQ messaging pattern to use?

How to integrate analogue sensors into a digital system?

How to decide and take action for each condition?

How to integrate social media updating into the system?

How to send a text message from a pi system?

How to automatically send an update at a certain time?

How to use a received message to activate an action?

It was decided to use a Request Reply ZeroMQ pattern as each input from the sensors

would require action. For example, if it was dark the PI would be required to turn on a

light. The system also would be required to send updates on a timed basis as to the status.

In the sensor array, the sensors required were a digital motion sensor, a temperature sensor,

a light sensor, and a push or panic button. The temperature and light sensors were analogue

sensors and as the Raspberry PI has no analogue input, an analogue to digital converter

would be required.

An If-else conditional statement was used to monitor the status of the sensors and if one of

the conditions was found to be true to send a message using a separate Publish function,

this same function would listen for a reply from the server and take appropriate action

when said message was received.

On the server, the received message is checked to see if it is one of a list of known

statements, if the statement is true, respond with the appropriate message, and update the

communications suite.

The communications suite would consist of functions to update e-mail, text, Twitter and

Facebook.

Page 6: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 6 of 71

For example, if the light level drops below a certain level, the system will “Publish” the

message “it’s dark”, on the server side. When the message “it’s dark” is received, the

server responds with the message “turn on lights” and updates the communications suite.

On the client side, when the message “turn on lights” is received, the pi sends a voltage

high out through assigned pin to activate an external light.

Page 7: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 7 of 71

Chapter 2 What is ZeroMQ?

ZeroMQ (ØMQ/ZMQ) is a high-performance asynchronous messaging library aimed at

use in scalable distributed or concurrent applications. It provides a message queue, but

unlike message-oriented middleware, a ZeroMQ system can run without a dedicated

message broker. The library is designed to have a familiar socket-style API (Hintjens,

March 2013)

Berkeley Sockets (BSD) are the de-facto API for all network communication. With roots

from the early 1980's, it is the original implementation of the TCP/IP suite, and is one of

the most widely supported and critical components of any operating system today. The

BSD sockets that we are familiar with are peer-to-peer connections, which require explicit

setup, teardown, choice of transport (TCP, UDP) ,error handling, and so on. Once you

solve all of the above problems you are into the world of application protocols (ex: HTTP),

which require additional framing, buffering, and processing logic. In other words, it is no

wonder that a high-performance network application is difficult to write (Grigorik, 2010).

The ZeroMQ networking library allows you to abstract some of the low-level details of

different socket types, connection handling, framing, or even routing. ZeroMQ sockets

provide a layer of abstraction on top of the traditional socket API, which allows it to hide

much of the everyday complexity we are forced to repeat in applications. To begin, instead

of being stream (TCP) or datagram (UDP) oriented, ZeroMQ communication is message-

oriented. This means that if a client socket sends a 150kb message, then the server socket

will receive a complete, identical message on the other end without having to implement

any explicit buffering or framing. Of course, we could still implement a streaming

interface, but doing so would require an explicit application-level protocol. (Grigorik,

2010)

Switching from a streaming/datagram to a message-oriented model is a minor change but

one that carries many implications. As ZeroMQ handles all of the buffering and framing,

the client and server applications become simpler, more secure, and much easier to write.

"It gives you sockets that carry whole messages across various transports like inproc, IPC,

TCP, and multicast; you can connect sockets N-to-N with patterns like fanout, pubsub, task

distribution, and request-reply" .

Page 8: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 8 of 71

The ZeroMQ API provides sockets (a kind of generalisation over the traditional IP and

Unix domain sockets), each of which can represent a many-to-many connection between

endpoints. Operating with a message-wise granularity, they require that a messaging

pattern be used, and are particularly optimized for that kind of pattern.

The key differences to conventional sockets are that, generally speaking, conventional

sockets present a synchronous interface to either connection-oriented reliable byte streams

or connection-less unreliable datagrams. In comparison, 0MQ sockets present an

abstraction of an asynchronous message queue, with the exact queuing details depending

on the socket type in use. Where conventional sockets transfer streams of bytes or discrete

datagrams, 0MQ sockets transfer discrete messages.

0MQ sockets, being asynchronous, mean that the timings of the physical connection setup

and teardown, reconnection and delivery are transparent to the user and organized by 0MQ

itself. Further to this, messages may be queued in the event that a peer is unavailable to

receive them.

Conventional sockets allow only strict one-to-one (two peers), many-to-one (many clients,

one server), or in some cases one-to-many (multicast) relationships. With the exception of

ZMQ::PAIR, 0MQ sockets may be connected to multiple endpoints using connect(), while

simultaneously accepting incoming connections from multiple endpoints bound to the

socket using bind(), thus allowing many-to-many relationships.

Programming with ZeroMQ

ZeroMQ as a library works through sockets by following certain network communication

patterns. It is designed to work asynchronously, and that is where the MQ suffix to its

name comes - from queuing messages before sending them.

ZeroMQ offers four different types of transport for communication. These are:

• In-Process (INPROC): Local (in-process) communication transport.

• Inter-Process (IPC): Local (inter-process) communication transport.

• TCP: Unicast communication transport using TCP.

• PGM: Multicast communication transport using PGM.

Page 9: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 9 of 71

Chapter 3 ZeroMQ Sockets

ZeroMQ Socket Types

Conventional sockets allow only strict one-to-one (two peers), many-to-one (many clients,

one server), or in some cases one-to-many (multicast) relationships. With the exception of

ZMQ_PAIR, ZMQ sockets can be connected to multiple endpoints using zmq_connect(),

while simultaneously accepting incoming connections from multiple endpoints bound to

the socket using zmq_bind(), thus allowing many-to-many relationships

ZeroMQ sockets being asynchronous means that the timings of the physical connection

setup and tear down, reconnect and delivery, are transparent to the user and organized by

ZeroMQ itself. Further, messages may be queued in the event that a peer is unavailable to

receive them.

ZeroMQ sockets are not thread safe. Applications MUST NOT use a socket from multiple

threads except after migrating a socket from one thread to another with a "full fence"

memory barrier. This ensures that all load and store operations prior to the fence will have

been committed prior to any loads and stores issued following the fence ( iMatix

Corporation, 2012).

Socket types:

To recap briefly what ZeroMQ does, it routes and queues messages according to precise

recipes called patterns. These patterns provide ZeroMQ's intelligence. ZeroMQ's patterns

are hard-coded and are implemented by pairs of sockets with matching types. In other

words, to understand ZeroMQ patterns you need to understand socket types and how they

work together.

The following present the socket types defined by ZeroMQ, grouped by the general

messaging pattern, which is built from related socket types. The way these sockets work

depend on the type of socket chosen and the flow of messages being sent depends on the

chosen patterns.

Page 10: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 10 of 71

The socket combinations that are valid for a connect-bind pair (either side can bind):

• PUB and SUB

• REQ and REP

• REQ and ROUTER

• DEALER and REP

• DEALER and ROUTER

• DEALER and DEALER

• ROUTER and ROUTER

• PUSH and PULL

• PAIR and PAIR

Sockets have life in four parts, just like BSD sockets:

Creating and destroying sockets (zmq_socket(), zmq_close()).

Configuring sockets by setting options on them and checking them if necessary (zmq_setsockopt(),zmq_getsockopt()).

Plugging sockets into the network topology by creating ZeroMQ connections to and from them (zmq_bind(), zmq_connect()).

Using the sockets to carry data by writing and receiving messages on them (zmq_send(),zmq_recv()).

Note: that sockets are always void pointers and messages are structures. So sockets are passed as such, in all functions that work with messages, like zmq_send() and zmq_recv().

Creating, destroying, and configuring sockets works as you would expect for any object.

The ZMQ_HWM option sets the high water mark for the specified socket. The high water mark is a hard limit on the maximum number of outstanding messages ZeroMQ will queue

in memory for any single peer that the specified socket is communicating with. If this limit has been reached the socket enters an exceptional state and depending on the socket type, ZeroMQ takes appropriate action such as blocking or dropping sent messages( iMatix

Corporation, 2012).

Page 11: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 11 of 71

ZMQ_REQ Socket:

A socket of type ZMQ_REQ is used by a client to send requests to and receive replies from

a service. This socket type allows only an alternating sequence of zmq_send(request) and

subsequent zmq_recv(reply) calls. Each request sent is round robined among all services,

and each reply received is matched with the last issued request.

When a ZMQ_REQ socket enters an exceptional state due to having reached the high water

mark for all services, or if there are no services at all, then any zmq_send() operations on

the socket shall block until the exceptional state ends or at least one service becomes

available for sending; messages are not discarded. ( iMatix Corporation, 2012)

Table 1 ZMQ REQ Charachteristics

Summary of ZMQ_REQ characteristics

Compatible peer sockets ZMQ_REP

Direction Bidirectional

Send/receive pattern Send, Receive, Send, Receive, …

Outgoing routing strategy Round-robin

Incoming routing strategy Last peer

ZMQ_HWM option action Block

( iMatix Corporation, 2012)

Page 12: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 12 of 71

ZMQ_REP Socket:

A socket of type ZMQ_REP is used by a service to receive requests from and send replies

to a client. This socket type allows only an alternating sequence of zmq_recv(request) and

subsequent zmq_send(reply) calls. Each request received is fair-queued from among all

clients, and each reply sent is routed to the client that issued the last request. If the original

requester doesn't exist anymore the reply is silently discarded.

When a ZMQ_REP socket enters an exceptional state due to having reached the high water

mark for a client, then any replies sent to the client in question shall be dropped until the

exceptional state ends.

Table 2 ZMQ REP Charachteristics

Summary of ZMQ_REP characteristics

Compatible peer sockets ZMQ_REQ

Direction Bidirectional

Send/receive pattern Receive, Send, Receive,

Send, …

Incoming routing strategy Fair-queued

Outgoing routing strategy Last peer

ZMQ_HWM option action Drop

(iMatix Corporation, 2012)

Page 13: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 13 of 71

ZMQ_PUB socket:

A socket of type ZMQ_PUB is used by a publisher to distribute data. Messages sent are

distributed in a fan out fashion to all connected peers. The zmq_recv() function is not

implemented for this socket type.

When a ZMQ_PUB socket enters an exceptional state due to having reached the high water

mark for a subscriber, then any messages that are sent to the subscriber in question shall

instead be dropped until the exceptional state ends. The zmq_send() function shall never

block for this socket type.

Table 3 ZMQ PUB Charachteristics

Summary of ZMQ_PUB characteristics

Compatible peer sockets ZMQ_SUB

Direction Unidirectional

Send/receive pattern Send only

Incoming routing strategy N/A

Outgoing routing strategy Fan out

ZMQ_HWM option action Drop

(iMatix Corporation, 2012)

Page 14: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 14 of 71

ZMQ_SUB socket:

A socket of type ZMQ_SUB is used by a subscriber, to subscribe to data distributed by a

publisher. Initially a ZMQ_SUB socket is not subscribed to any messages, use the

ZMQ_SUBSCRIBE option of zmq_setsockopt() to specify which messages to subscribe to.

The zmq_send() function is not implemented for this socket type.

Table 4 ZMQ SUB Charachteristics

Summary of ZMQ_SUB characteristics

Compatible peer sockets ZMQ_PUB

Direction Unidirectional

Send/receive pattern Receive only

Incoming routing strategy Fair-queued

Outgoing routing strategy N/A

ZMQ_HWM option action Drop

( iMatix Corporation, 2012)

Page 15: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 15 of 71

ZMQ_PUSH

A socket of type ZMQ_PUSH is used by a pipeline node to send messages to downstream

pipeline nodes. Messages are round-robined to all connected downstream nodes. The

zmq_recv() function is not implemented for this socket type.

When a ZMQ_PUSH socket enters an exceptional state due to having reached the high

water mark for all downstream nodes, or if there are no downstream nodes at all, then any

zmq_send() operations on the socket shall block until the exceptional state ends or at least

one downstream node becomes available for sending; messages are not discarded.

Deprecated alias: ZMQ_DOWNSTREAM.

Table 5 ZMQ PUSH Charachteristics

Summary of ZMQ_PUSH characteristics

Compatible peer sockets ZMQ_PULL

Direction Unidirectional

Send/receive pattern Send only

Incoming routing strategy N/A

Outgoing routing strategy Round-robin

ZMQ_HWM option action Block

(iMatix Corporation, 2012)

Page 16: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 16 of 71

ZMQ_PULL

A socket of type ZMQ_PULL is used by a pipeline node to receive messages from

upstream pipeline nodes. Messages are fair-queued from among all connected upstream

nodes. The zmq_send() function is not implemented for this socket type.

Deprecated alias: ZMQ_UPSTREAM.

Table 6 ZMQ PULL Characteristics

Summary of ZMQ_PULL characteristics

Compatible peer sockets ZMQ_PUSH

Direction Unidirectional

Send/receive pattern Receive only

Incoming routing strategy Fair-queued

Outgoing routing strategy N/A

ZMQ_HWM option action N/A

( iMatix Corporation, 2012)

Page 17: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 17 of 71

ZMQ_DEALER

A socket of type ZMQ_DEALER is an advanced pattern used for extending request/reply

sockets. Each message sent is round-robined among all connected peers, and each message

received is fair-queued from all connected peers.

When a ZMQ_DEALER socket enters an exceptional state due to having reached the high

water mark for all peers, or if there are no peers at all, then any zmq_send() operations on

the socket shall block until the exceptional state ends or at least one peer becomes

available for sending; messages are not discarded.

When a ZMQ_DEALER socket is connected to a ZMQ_REP socket, each message sent

must consist of an empty message part, the delimiter, followed by one or more body parts.

Table 7 ZMQ Dealer Characteristics

Summary of ZMQ_DEALER characteristics

Compatible peer sockets ZMQ_ROUTER, ZMQ_REQ, ZMQ_REP

Direction Bidirectional

Send/receive pattern Unrestricted

Outgoing routing strategy Round-robin

Incoming routing strategy Fair-queued

ZMQ_HWM option action Block

( iMatix Corporation, 2012)

Page 18: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 18 of 71

ZMQ_ROUTER

A socket of type ZMQ_ROUTER is an advanced pattern used for extending request/reply

sockets. When receiving messages the socket pre-appends a message part containing the

identity of the originating peer to the message before passing it to the application.

Messages received are fair-queued from among all connected peers. When sending

messages a ZMQ_ROUTER removes the first part of the message and uses it to determine

the identity of the peer that the message shall be routed to. If the peer does not exist

anymore, the message is silently discarded.

When a ZMQ_ROUTER socket enters an exceptional state of the high water mark for all

peers, or if there are no peers at all, then any messages sent to the socket shall be dropped

until the exceptional state ends. Likewise, any messages routed to a non-existent peer or a

peer for which the individual high water mark has been reached shall also be dropped.

When a ZMQ_REQ socket is connected to a ZMQ_ROUTER socket, in addition to the

identity of the originating peer, each message received shall contain an empty delimiter

message part. Hence, the entire structure of each received message as seen by the

application becomes: one or more identity parts, delimiter part, one or more body parts, all

replies to a ZMQ_REQ socket must include the delimiter part.

Table 8 ZMQ Router Characteristics

Summary of ZMQ_ROUTER characteristics

Compatible peer sockets ZMQ_DEALER, ZMQ_REQ, ZMQ_REP

Direction Bidirectional

Send/receive pattern Unrestricted

Outgoing routing strategy See text

Incoming routing strategy Fair-queued

ZMQ_HWM option action Drop

Page 19: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 19 of 71

Chapter 5 ZMQ Pattern Examples:

Messaging pattern is a network-oriented architectural pattern, which describes how two

different parts of a message passing system connect and communicate with each other.

The following are the three main patterns used in building an application from ZeroMQ

Each section shall have a brief explanation, a diagram and some python code (Java

language examples are available on the appendix CD). There is also a brief example of a

dealer router implementation

1. Request/Reply Pattern:

The request-reply pattern is used for sending requests from a client to one or more

instances of a service, and for also receiving subsequent replies to each request sent.

Figure 1Request Reply Pattern

(Hintjens, March 2013)

In the above example the CLIENT sends the message “Hello”. The SERVER sends a

“World” back

The REQ socket can send a message, but must not send anything else until it gets a

response or ZMQ will error. Likewise a REP socket cannot send a message unless it first

receives one.

Page 20: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 20 of 71

Figure 2 REP-REQ Pattern Client Python Code

# Server

import zmq

context = zmq.Context()

# Socket to talk to server

print("Connecting to hello world server…")

socket = context.socket(zmq.REP)

socket.bind("tcp://*:5555")

while True:

print("waiting for client request")

msg = socket.recv()

print("Message received %s “ % msg)message = socket.send("World” )

Figure 3 REP-REQ Server Python Code

# Client import zmq

context = zmq.Context() print("Connecting to hello world server…")

socket = context.socket(zmq.REQ) socket.connect("tcp://localhost:5555") for request in range(10):

print("Sending request %s …" % request)

socket.send("Hello")

# Get the reply. message = socket.recv() print("Received reply %s [ %s ]" %(request, message))

Page 21: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 21 of 71

2. Publish/Subscribe Pattern

The Publish-Subscribe Pattern is used for one-to-many distribution of data from a single

publisher to multiple subscribers in a fan out fashion.

Figure 4 Publish Subscribe

(Hintjens, March 2013)

Some points about the Publish-Subscribe (PUB-SUB) pattern:

A subscriber can connect to more than one publisher using one connect call each

time. Data will then arrive and be interleaved, "fair-queued", so that no single

publisher drowns out the others.

If a publisher has no connected subscribers then it will simply drop all messages.

If using TCP and a subscriber is slow, messages will queue up on the publisher.

Publishers are protected against this using the "high-water mark" in sockets.

Page 22: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 22 of 71

Figure 5 PUB-SUB Publisher Python Code

import zmq from random import randint

context = zmq.Context() socket = context.socket(zmq.PUB)

socket.bind("tcp://*:5556") while True:

zipcode = randint(1, 10)

temperature = randint(-20, 50) humidity = randint(10, 15) print “Publish data:”,(zipcode,temperature, humidity) socket.send("%d %d %d" % (zipcode,temperature, relhumidity))

Figure 6 PUB-SUB Subscriber Python Code

import zmq import sys

context = zmq.Context() socket = context.socket(zmq.SUB)

socket.connect("tcp://localhost:5556") zip_filter = sys.argv[1] if len(sys.argv) > 1 else “” print “Collectin updates from weather service%s” % zip_filter

socket.setsockopt(zmq.SUBSCRIBE, zip_filter)

#process 5 records for record in range(5):

data = socket.recv()

Page 23: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 23 of 71

3. Pipeline Pattern

The Pipeline Pattern is used for distributing data to nodes arranged in a pipeline. Data

always flows down the pipeline and each stage of the pipeline is connected to at least one

node. When a pipeline stage is connected to multiple nodes data is round-robined among

all connected nodes.

Figure 7 parallel pipeline

(Hintjens, March 2013)

The workers connect upstream to the ventilator and downstream to the sink. This means

you can add workers arbitrarily. If the workers are bound to their endpoints, you would

need (a) more endpoints and (b) to modify the ventilator and/or the sink each time you

added a worker. We say that the ventilator and sink are stable parts of our architecture and

the workers are dynamic parts of it.

We have to synchronize the start of the batch with all workers being up and running. This

is a fairly common gotcha in ZeroMQ and there is no easy solution. The ZMQ_connect

Page 24: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 24 of 71

method takes a certain amount of time. So when a set of workers connect to the ventilator,

the first one to successfully connect will get a whole load of messages in that short time

while the others are also connecting. If you don't synchronize the start of the batch

somehow, the system won't run in parallel at all. Try removing the wait in the ventilator,

and see what happens.

The ventilator's PUSH socket distributes tasks to workers evenly, assuming they are all

connected before the batch starts going out. This is called load balancing and it's something

that will be addressed below in more detail.

The sink's PULL socket collects results from workers evenly. This is called fair-queuing.

Page 25: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 25 of 71

Figure 8 Ventilator Code Python Example

# Task ventilator

# Binds PUSH socket to tcp://localhost:5557

# Sends batch of tasks to workers via that socket

#

# Author: Lev Givon <lev(at)columbia(dot)edu> import zmq

import random

import time try:

raw_input except NameError:

# Python 3

raw_input = input context = zmq.Context() # Socket to send messages on

sender = context.socket(zmq.PUSH)

sender.bind("tcp://*:5557") # Socket with direct access to the sink: used to syncronize start of

batch

sink = context.socket(zmq.PUSH)

sink.connect("tcp://localhost:5558") print("Press Enter when the workers are ready: ")

_ = raw_input()

print("Sending tasks to workers…") # The first message is "0" and signals start of batch

sink.send(b'0') # Initialize random number generator

random.seed() # Send 100 tasks

total_msec = 0 for task_nbr in range(100): # Random workload from 1 to 100 msecs

workload = random.randint(1, 100)

total_msec += workload sender.send_string(u'%i' % workload) print("Total expected cost: %s msec" % total_msec) # Give 0MQ time to deliver

time.sleep(1)

( iMatix Corporation, 2012)

Page 26: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 26 of 71

Figure 9 Worker Code In Python

# Task worker

# Connects PULL socket to tcp://localhost:5557

# Collects workloads from ventilator via that socket

# Connects PUSH socket to tcp://localhost:5558

# Sends results to sink via that socket

#

# Author: Lev Givon <lev(at)columbia(dot)edu> import sys

import time

import zmq context = zmq.Context() # Socket to receive messages on

receiver = context.socket(zmq.PULL)

receiver.connect("tcp://localhost:5557") # Socket to send messages to

sender = context.socket(zmq.PUSH)

sender.connect("tcp://localhost:5558") # Process tasks forever

while True:

s = receiver.recv() # Simple progress indicator for the viewer

sys.stdout.write('.')

sys.stdout.flush() # Do the work

time.sleep(int(s)*0.001) # Send results to sink

sender.send(b'') ( iMatix Corporation, 2012)

Page 27: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 27 of 71

Figure 10 Sink Code Python Example

# Task sink

# Binds PULL socket to tcp://localhost:5558

# Collects results from workers via that socket

#

# Author: Lev Givon <lev(at)columbia(dot)edu> import sys

import time

import zmq context = zmq.Context() # Socket to receive messages on

receiver = context.socket(zmq.PULL)

receiver.bind("tcp://*:5558") # Wait for start of batch

s = receiver.recv() # Start our clock now

tstart = time.time() # Process 100 confirmations

total_msec = 0

for task_nbr in range(100):

s = receiver.recv()

if task_nbr % 10 == 0:

sys.stdout.write(':')

else:

sys.stdout.write('.')

sys.stdout.flush() # Calculate and report duration of batch

tend = time.time()

print("Total elapsed time: %d msec" % ((tend-tstart)*1000)) ( iMatix Corporation, 2012)

Page 28: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 28 of 71

4. Dealer Router Multithreading

Figure 11 Dealer Router Multithreading:

(Hintjens, March 2013)

In the above example, the CLIENT sends a message to ROUTER and waits for a response.

The ROUTER then processes message and sends to some Worker via the DEALER.

The DEALER sends a message to Worker and waits for one response. The WORKER

processes the message and sends a response back. The DEALER gets the message from

WORKER, sends along to ROUTER. The ROUTER gets message and sends back to

CLIENT, and the CLIENT does something with it!

Page 29: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 29 of 71

Chapter 6 Implementation Motion sensor

It was decided to use a Request Reply ZeroMQ pattern as each input from the sensors

would require action. For example, if a motion was detected the pi would be required to

turn on a light/sound a buzzer.

The a 5V Passive Infrared (PIR) motion sensor was wired to the pi as shown in Figure

12.The motion sensor sets a single output pin High whenever it detects movement within

its field of view. It holds this pin High (3.3V) for a minimum period. If continuous

movement is detected the output pin will stay high. When the time has elapsed and no

more movement is detected the output pin returns Low (0V). Both time and sensitivity are

adjustable on the sensor.

Figure 12 Motion sensor

On the Raspberry PI the a program was written to monitor the pin on which the motion

sensor was connected when this pin goes high a “Publish” Function is called, This Publish

function enacts a Zmq context, binds to the server address and sends a message . It waits or

listens for a reply. When the reply is received the system returns to the monitoring state.

Highlighted in Figure 13 below is the code for the main motion detector monitoring

function and in Figure 14 is the code for the publish function.

Page 30: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 30 of 71

Figure 13 Client Code Main Program

import re ,os, sys, time

import zmq

import RPi.GPIO as GPIO

GPIO.cleanup()

# Use BCM GPIO references

# instead of physical pin numbers

GPIO.setmode(GPIO.BCM)

def main():

# Define GPIO to use on Pi

GPIO_PIR = 24

print "PIR Module Test (CTRL-C to exit)"

# Set pin as input

GPIO.setup(GPIO_PIR,GPIO.IN) # Echo

Current__State = 0

Previous_State = 0

#try defining motion

try:

print "Waiting for PIR to settle ..."

# Loop until PIR output is 0

#PIR Warm up time

while GPIO.input(GPIO_PIR)==1:

Current_State = 0

print 'Ready'

# Loop until users quits with CTRL-C

while True :

# Read PIR state

Current_State = GPIO.input(GPIO_PIR)

if Current_State==1 and Previous_State==0:

# PIR is triggered

print " Motion detected!"

#call Publish function and pass the text “motion”

Publish("Motion")

# Record previous state

Previous_State=1

elif Current_State==0 and Previous_State==1:

# PIR has returned to ready state

print " Ready"

Previous_State=0

# Wait for 10 milliseconds

time.sleep(0.01)

# Keyboard interrupt Error catching

except KeyboardInterrupt:

print " Quit"

# Reset GPIO settings

GPIO.cleanup()

return

if __name__ == "__main__":

main()

Page 31: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 31 of 71

Figure 14 Client Code Publish Function

def Publish(Text):

#Set context

context = zmq.Context()

#Set the passed in variable to str

str = Text

#bind to server addreess

bind_to = "tcp://192.168.2.6:5555"

# Socket to talk to server

print("Connecting to server¦")

#set socket tho zmq Socket context REQ

socket = context.socket(zmq.REQ)

#connect to the server addreess

socket.connect(bind_to)

#Print the message being sent

print("Sending request %s " % str)

#send Message str

socket.send(str)

# Get the reply

message = socket.recv()

# Print the Reply

print("Received reply %s " % (message))

# set reply equal to X

X = message

# Use x to print message.

if X == "Detected":

print "Turning on light "

else:

print "ERROR: Unexpected Message"

return

Figure 15 Server Code

def Server():

#start of ZmQ Server or main program

#Create context object to a zmq Context

context = zmq.Context()

#Set socket contex to Rep, for a REQ-REP socket

socket = context.socket(zmq.REP)

#Bind Socket to "tcp://Localhost:Portnumber"

socket.bind("tcp://192.168.2.5:5561")

#loop ctrl-c

while True:

# Wait for next request from client

message = socket.recv()

#Print The message to the screen

print "Received request: ", text

# Do some 'work' time.sleep (1) # Do some 'work' # Send reply back to client socket.send("Detected")

Page 32: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 32 of 71

Chapter 7 Implementation Twitter

In order to use the Twitter API (the interface that is used to post new Tweets and interact

with Twitter from an external source), it was required to register as a developer and create

a new app. This was done at https://dev.twitter.com/ . By default, the app is set to read-

only so it was changed to Read and Write to allow posts to the twitter feed. Four sets of

access tokens are required to log in and post. These are: consumer key, consumer secret,

access key and access secret. These where generated in the developers section of Twitter

and inputted into the function, as seen below in

Figure 17.

It was discovered that a repetitive message on Twitter throws an error., To overcome this

the current time was added to the message posted.

The function Tweet is called in the server code as seen below in Figure 16 and the text

“motion detected” is passed to the function:

Figure 16 Tweet Function Call

if text == "Motion":

#Pass variables to functions and set text to

Tweet("Motion Detected @ ")

socket.send("Detected")

Figure 17 Twitter Function Code

def Tweet(Text):

#set the localtime variable

localtime = time.asctime( time.localtime(time.time()))

#Set The message variable"msg" = The alert plus localTime,

msg = Text+(localtime)

#Twitter Access Keys

CONSUMER_KEY = 'RbwVNyNI25q3U1y2TKhdw'

CONSUMER_SECRET = '09dK2OkqVuVo9I12mUzltm01gi4YtnTXSZfvLwpA4'

ACCESS_KEY = '2317027770-HgSg4Q4Xn4uzDpZwKpABUz67QxFVb8ah57LB51D'

ACCESS_SECRET = 'a8FiPxgpbBif93qaUQpa3w5zaq0bq6KizUkvV8SDnJZZn'

#Use Twython api To sign in to twitter

api = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)

try:

#Update satus

api.update_status(status=msg )

# error handling

except TwythonError as e:

print e

This was tested first on in Linux then on the Raspberry Pi before being implemented by the

motion sensor. The results are below in Figure 18

Page 33: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 33 of 71

Figure 18 Tweet Results

Page 34: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 34 of 71

Chapter 8 Implementation Analogue sensors

Now that the basic system was functioning the extra sensors were added.

The Raspberry PI computer does not have a way to read analogue inputs. It is a digital-

only computer. The temperature and light sensor for the home monitoring system are

analogue so a way to make the Pi analogue-friendly was needed. This was achieved by

using the SPI bus on the Raspberry PI and a MCP3008 analogue to digital converter

(ADC).

In the SPI BUS, devices communicate using a master/slave relationship in which the

master initiates the data frame. When the master generates a clock and selects a slave

device, data may be transferred in either or both directions simultaneously. In fact, as far as

SPI is concerned, data is always transferred in both directions. It is up to the master and

slave devices to know whether a received byte is meaningful or not. So a device must

discard the received byte in a "transmit only" frame or generate a dummy byte for a

"receive only" frame.

Figure 19 Single Master Slave Implementation

(Kalinsky, 2002)

SPI specifies four signals: clock (SCLK); master data output, slave data input (MOSI);

master data input, slave data output (MISO); and slave select (ÇSS),Figure 19 shows these

signals in a single-slave configuration. SCLK is generated by the master and input to all

slaves. MOSI carries data from master to slave. MISO carries data from slave back to

master. A slave device is selected when the master asserts its CSS

In addition to these wires we have ‘n’ wires for ‘n’ slave devices on the bus. Each one of these wires carries the

these wires carries the chip select signal (SS or CS) for its respective device. Only one slave device can have its slave device can have its chip select signal asserted by the master controller at a time. These relationships are

These relationships are illustrated in

Figure 20 Single Master, Multiple Slave Implementation.

Page 35: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 35 of 71

Figure 20 Single Master, Multiple Slave Implementation

(Kalinsky, 2002)

The operation of the SPI bus is conceptually simple. Both the master controller and each

slave device contain a shift register. When the chip select signal of a slave device is

asserted (usually by being pulled low), the MISO wires are used to connect its shift register

with that of the master device. Clock pulses are then generated by the master device, to

shift data between the two shift registers enabling communication. In this sense the read

and write operation are combined. For example, by shifting the contents of the master

device shift register to that of the slave device, we are also shifting the data in the slave

device shift register to that of the master.

Figure 21 Shifting from Master to Slave

Page 36: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 36 of 71

Finally, there are 4 different SPI modes that can be used. Each mode defines a particular

clock phase (CPHA) and polarity (CPOL) with respect to the data. In this project SPI mode

0 which is also known as mode (0,0) or mode (CPHA=0,CPOL=0) was used. (Al-Hertani.,

2013).

The Linux Kernel in recent Raspberry Pi Releases supports the SPI as a native device so

doesn’t require bit-banging. However, as it’s disabled by default it needs to load the

module before we can use the SPI device. Additionally the permissions and/or ownerships

of the files in /dev/ need to be changed so that they can be accessed from out programs

without needing to be root or run them with sudo.

The MCP3008 chip is an SPI based analogue to digital converter (ADC). It has 8 analogue

input channels that can be configured for single ended and differential ADC conversions.

The MCP3008 is a 10-bit ADC that can convert 200 kilo samples per second (200ksps).

Figure 22 MCP3008 Pin Out

(Microchip, n.d.)

As shown in Figure 23 the VDD pin was connected to the 3.3V power source from the

Raspberry PI. The AGND (Analog ground) and DGND (Digitalground) pins were

connected directly to ground as a reference point. The VREF pin is the reference voltage,

which is the largest possible voltage that the ADC can interpret. The largest voltage the

Raspberry pi can accept is 3.3V so the VREF pin was connected to 3.3V. So if 3.3V is

Page 37: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 37 of 71

sampled on any of the ADC’s channels it would be interpreted as the maximum digital

value that can be represented by this 10-bit ADC (i.e. – 2). Similarly, the

smallest analogue voltage that the ADC can detect (also known as the LSB size) is

, which in this case is , represents a digital value of 1. The

equation that converts between the analogue voltage and its digital interpretation is given

by: where VIN is the analogue input voltage

and VREF is the reference voltage. (Al-Hertani., 2013)

Figure 23 Setup of Analogue Sensors

To check the setup and implementation of the sensors, a convert temps, convert volts and read channel functions

were added to the client as seen in Figure 24, and the code in

Figure 25 was added to the main program.

Figure 24 Analogue Sensor code

# Analogue Sensor Input

######################################################

#resets all ports back to input mode

GPIO.cleanup()

# Open SPI bus

spi = spidev.SpiDev()

spi.open(0,0)

# Use BCM GPIO references instead of physical pin numbers

# referring to the pins by the "Broadcom SOC channel" number

GPIO.setmode(GPIO.BCM)

# Function to read SPI data from MCP3008 chip

# Channel must be an integer 0-7(8 total inputs)

def ReadChannel(channel):

adc = spi.xfer2([1,(8+channel)<<4,0])

data = ((adc[1]&3) << 8) + adc[2]

Page 38: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 38 of 71

return data

# Function to convert data to voltage level,

# rounded to specified number of decimal places.

def ConvertVolts(data,places):

volts = (data * 3.3) / float(1023)

volts = round(volts,places)

return volts

# Function to calculate temperature from

# TMP36 data, rounded to specified

# number of decimal places.

def ConvertTemp(data,places):

# ADC Value

# (approx) Temp Volts

# 0 -50 0.00

# 78 -25 0.25

# 155 0 0.50

# 233 25 0.75

# 310 50 1.00

# 388 75 1.25

# 465 100 1.50

# 543 125 1.75

# 620 150 2.00

# 698 175 2.25

# 775 200 2.50

# 853 225 2.75

# 930 250 3.00

# 1008 275 3.25

# 1023 280 3.30

temp = ((data * 330)/float(1023))-50

temp = round(temp,places)

return temp

# Define sensor channels

light_channel = 0

temp_channel = 1

# Define delay between readings

delay = 5

Figure 25 Code to Read from analogue sensors

# Read the light sensor data

light_level = ReadChannel(light_channel)

light_volts = ConvertVolts(light_level,2)

# Read the temperature sensor data

temp_level = ReadChannel(temp_channel)

temp_volts = ConvertVolts(temp_level,2)

temp = ConvertTemp(temp_level,2)

# When temp below approx 11 Degrees

if temp_level <180:

print "Brrr It's Cold"

Publish("Cold")

# When temp above approx 30 Degrees

if temp_level >300:

print "Dam Its hot"

Publish("Hot")

# From trial and error Dark Room

if light_level<1000:

print "Its Dark"

Publish("Dark")

# Wait for 10 milliseconds

Page 39: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 39 of 71

time.sleep(0.01)

Page 40: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 40 of 71

Chapter 9 Implementation Adding the camera

The Raspberry Pi camera was added to the system setup and tested as per instructions on

http://www.raspberrypi.org/camera . This enables the sending of photos and videos from

the Pi sensor array.

A function was added to the client to allowed the capture of pictures, see Figure 26, this

allowed a photo to be captured by calling CapturePic(). The same file name is used and the

image is overwritten each time. As the image will be Tweeted, e-mailed and Facebooked,

it does not require unique saving.

Figure 26 Capture Pic Code

def CapturePic():

# Explicitly open a new file called my_image.jpg

# wb is open as write binary

my_file = open('my_image.jpg', 'wb')

#the with keyword is used when working with unmanaged resources (like

file streams) it ensures resources are cleaned up afterwards.

with picamera.PiCamera() as camera:

camera.start_preview()

time.sleep(2)

camera.capture(my_file)

# Note that at this point the data is in the file cache, but may

# not actually have been written to disk yet

my_file.close()

# Now the file has been closed, other processes should be able to

# read the image successfully

The addition of pictures to the message proved a challenge. The message is sent as a

string. The text is already a string, and converting temperature and light from integers to

strings are quite simple. Adding the image was difficult but a solution was found in

converting every pixel of the image into a hexadecimal word and the base 64 library. The

base 64 algorithms is used for encoding and decoding arbitrary binary strings into text

strings .This enabled the system to have 4 separate text strings: a text string of the image, a

standard text string, temperature string, and light levels string.

The next problem was how to combine all these strings and then separate them on the other

side. To combine strings In Python you simply add them, for example string1 + string 2 =

new string. But in order to separate them a unique character is required to split. After some

research it was found that “:” is unique. Thus, to combine the strings into a separable

message became msg = text +":"+ image +":"+light+":"+temp: and to split them the

message is split at (":"). Thus text, image, light, temp = message.split(":"), this splits the

Page 41: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 41 of 71

message at : and puts each element into its relative variable. For example, the received

message is “some text”: “an Image” :”Light level”:” a Temperature ”: .

The image is then re-encoded into an image from a string using base64.The variables and

image are used for decision-making, and are passed into the various functions.

Figure 27 client Code

light_level = ReadChannel(light_channel) temp_level = ReadChannel(temp_channel)

temp = ConvertTemp(temp_level,2)

#camm camera function

CapturePic()

#open file "my_image.jpg" and rb read binary as imageFile

with open("my_image.jpg", "rb") as imageFile:

#convert image to string

img = base64.b64encode(imageFile.read())

#print img

#set socket contex

context = zmq.Context()

#convert light to string

light = str(light_level)

#convert temp to string

tm = str(temp)

#set the text element of message

text = Text

#Combine strings into msg

msg = text +":"+ img +":"+light+":"+tm

#bind to server addreess

bind_to = "tcp://192.168.2.5:5561"

print("Connecting to server")

#Socket for talking to server

socket = context.socket(zmq.REQ)

#connect socket to bind_to Address

socket.connect(bind_to)

# Send request waiting each time for a response

print"Sending ", text

#send message

socket.send(msg)

Page 42: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 42 of 71

Figure 28 Server code

# Wait for next request from client

message = socket.recv()

#Split the recived message at: to seprate out the image , and

variables from the string

text, Image, light, temp = message.split(":")

#Print variables to screen

print "Received request: ", text

print "The text is = ", text

print "The Temp is = ", temp,"°C"

print "The Light is =", light," lumina"

#uncomment below to see Image as a string

#print "The Image is = ",Image

#open image file in "wb" (writeable and binary mode).

f = open("my_image.jpg", "wb")

#Deccode back to an image from string using base64

f.write(Image.decode('base64'))

# close file

f.close()

Figure 29 Results of Camera and analogue sensor addition

Page 43: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 43 of 71

Chapter 10 Implementation Push Button and Outputs

A Push button switch was added to the system as seen in

Figure 30. To implement this, the following code was added to assign a BCM pin and a pin

mode:

Button = 25 satus = 0

print "PIR Module Test (CTRL-C to exit)"

# Set pin as input

GPIO.setup(PIR,GPIO.IN)

#Set the button to input

GPIO.setup(Button,GPIO.IN)

And the following was added to the If-Else output string in the client.

if GPIO.input(Button)==1:

print "button pushed"

Publish("Button")

Figure 30 Push button

Page 44: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 44 of 71

Figure 31 Push button results

The if else with all sensors in it now reads as seen in Figure 32

Figure 32 All Sensors IF Else

# Read PIR state

if GPIO.input(PIR)==1:

# PIR is triggered

print " Motion detected!"

Publish("Motion")

# If button high (pushed)

if GPIO.input(Button)==1:

print "button pushed"

Publish("Button")

# When temp below approx 11 Degrees

if temp_level <180:

print "Brrr It's Cold"

Publish("Cold")

# When temp above approx 30 Degrees

if temp_level >300:

print "Dam Its hot"

Publish("Hot")

# From trial and error Dark Room

if light_level>1000:

print "Its Dark"

Publish("Dark")

# Wait for 10 milliseconds

time.sleep(0.01)

Page 45: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 45 of 71

Figure 33 Server If else all sensors:

#IF Else srting of possiable requests

if text == "Motion":

#Pass variables to functions and set text to

Tweet("Motion Detected @ ",temp,light)

time.sleep (1)

#Send reply back to client

socket.send("Detected")

elif text == "Button":

Tweet("Button Pressed @",temp,light)

time.sleep(1)

socket.send("Pressed")

#condition for low light

elif text == "Dark":

Tweet("It's dark in Here @",temp,light)

time.sleep (1)

message = socket.recv()

#Split the recived message at: to separate out the image , and

variables from the string

text, Image, light, temp = message.split(":")

#Print variables to screen

print "Received request: ", text

print "The text is = ", text

print "The Temp is = ", temp,"°C"

print "The Light is =", light," lumina"

#uncomment below to see Image as a string

#print "The Image is = ",Image

#open image file in "wb" (writeable and binary mode).

f = open("my_image.jpg", "wb")

#Deccode back to an image from string using base64

f.write(Image.decode('base64'))

# close file

f.close()

# Send reply back to client

socket.send("LightOn")

#conditon for Cold

elif text == "Cold":

Tweet("It's Cold In Here @",temp,light)

time.sleep (1)

#Send reply back to client

socket.send("HeatOn")

#Condition for Hot

elif text == "Hot":

Tweet("It's Getting Hot In Here @ ",temp,light)

time.sleep (1)

#Send reply back to client

socket.send("FanOn")

#Condition for timed satus update

elif text == "Satus Update":

Tweet("Satus Update From Pi @",temp,light)

#Send reply back to client

socket.send("Satus Recived")

#If unknown message received reply

else:

# Do some 'work'

time.sleep (1)

# Send reply back to client

print("Unknown Message")

# Send reply back to unblock port if error

socket.send("Unknown Message")

Page 46: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 46 of 71

Figure 34 Publish function:

#camm camera function

CapturePic()

#open file "my_image.jpg" and rb read binary as imageFile

with open("my_image.jpg", "rb") as imageFile:

#convert image to string

img = base64.b64encode(imageFile.read())

#print img

#set socket contex

context = zmq.Context()

#convert light to string

light = str(light_level)

#convert temp to string

tm = str(temp)

#set the text element of message

text = Text

#Combine strings into msg

msg = text +":"+ img +":"+light+":"+tm

#get the reply

message = socket.recv()

print ("Received Reply ", message)

#copy message to X

X = message

#If Else String for returned value from server

if X == "Detected":

print "light led"

time.sleep(1)

elif X == "Pressed":

print "sound alarm "

elif X == "HeatOn":

print "Turning on Heat "

elif X == "FanOn":

print "Turning on Fan "

elif X == "LightOn":

print "Turning on The lights "

elif X == "Satus Updated":

print "Satus updated"

else:

print "Did Nothing"

Page 47: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 47 of 71

Chapter 12 Implementation Outputs

Now that all sensors are connected, tested, and working, some outputs where added to the

Pi. Although initially planned to be relay switches, it was found that the Pi produced

insufficient current to drive these switches when all sensors where attached. Following

extensive research, solutions were found but deemed impractical for this demonstration

project.

Thus, LEDs where used to represent these external items such as heaters, fans, lights etc.

The LEDs where connected as shown in Figure 35 and a current limiting resistor was added

to each one.

Figure 35 LED

The client code was updated to activate each LED, as its message arrives which can be

seen in Figure 36.

Figure 36 LED Output code client

socket.send(msg)

# Get the reply

message = socket.recv()

print ("Received Reply ", message)

#copy message to X

X = message

#If Else String for returned value from server

if X == "Detected":

print "Turning on Red light "

# Define GPIO pin to use on Pi

GPIO_RLED = 17

print "Led Module Test (CTRL-C to exit)"

Page 48: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 48 of 71

#Set Gpio Mode to output

GPIO.setup(GPIO_RLED,GPIO.OUT)

#Set value to high (LED on)

GPIO.output(GPIO_RLED, True)

#time for 5 sceonds

time.sleep(5)

#Set value to low (LED off)

GPIO.output(GPIO_RLED, False)

time.sleep(1)

elif X == "Pressed":

print "sound alarm "

#Define GPIO to use on Pi

GPIO_YLED = 22

print "Led Module Test (CTRL-C to exit)"

GPIO.setup(GPIO_YLED,GPIO.OUT)

GPIO.output(GPIO_YLED, True)

time.sleep(5)

GPIO.output(GPIO_YLED, False)

time.sleep(1)

elif X == "HeatOn":

print "Turning on Heat "

elif X == "FanOn":

print "Turning on Fan "

print "Turning on Yellow light "

#Define GPIO to use on Pi

GPIO_YLED = 18

print "Led Module Test (CTRL-C to exit)"

GPIO.setup(GPIO_YLED,GPIO.OUT)

GPIO.output(GPIO_YLED, True)

time.sleep(5)

GPIO.output(GPIO_YLED, False)

time.sleep(1)

elif X == "LightOn":

GPIO_GLED = 27

print "Led Module Test (CTRL-C to exit)"

GPIO.setup(GPIO_GLED,GPIO.OUT)

GPIO.output(GPIO_GLED, True)

time.sleep(5)

GPIO.output(GPIO_GLED, False)

time.sleep(1)

print "Turning on The lights "

elif X == "Satus Updated":

print "Satus updated"

else:

print "Did Nothing"

Page 49: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 49 of 71

Chapter 13 Implementation Email

The e-mail package in python is a library for managing email messages including

Multipurpose Internet Mail Extensions (MIME). As its name suggests, MIME is a set of

extensions to standard internet e-mail. MIME has been in use for some time and it may

now be safe to say that MIME is the standard for internet email.

To implement the e-mail system, simply required an email account, username, address and

password and a list of addresses for the message to be sent to, the SMTP host address and

port number. This allows the sending e-mail address to login and allows a text only

message to be sent. The Mine library allows the addition of attachments to this text

message. The Mine library MimeMultipart allows multiple attachments, it divides the

message into parts and each part has headers including the type of data, filename and

encoding used. This finds the type of attachment and attaches it to the standard message.

The coding for this is in Figure 38 and the results of this can be seen in Figure 39.

To send an email, the Publish function calls the e-mail function and passes it a predefined

text, temperature and light level. The e-mail program opens the image file from the disk

itself as shown in Figure 37.

Figure 37 Calling Email function

if text == "Motion":

#Pass variables to functions and set text to

FaceBook("Motion Detected @",temp,light)

Tweet("Motion Detected @ ",temp,light)

Figure 38 Email function

# Email function

######################################################

#Pass the variables into the email function

def Email (Text,temp,light):

#From Address Can be any address

fromaddr = "[email protected]"

# Address To Must be a valid addresses

tolist = "[email protected]"

# Message body

text = Text+"\nCurrent Conditions"+"\nTemp is ="+temp+" Degrees

C"+"\nLight Level is ="+light+" lumina"

# Attachment location /path/to/file in this instance file is in same

folder so name is sufficent

filename = 'my_image.jpg'

# Credentials

username = "[email protected]"

password = "Al1981mat"

#SMTP host address and port number

host = 'smtp.gmail.com'

port = 587

# Create a stmp object clled server

Page 50: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 50 of 71

server = smtplib.SMTP()

#connect to smtp host

server.connect( host,port)

#start Transport Layer Security

server.starttls()

#Login to mail server

server.login(username,password)

#Sbject Field

sub = ('Subject: Update From PI ')

#Mimemultipart allows Multiple attachments Divides the message into

parts, Each part has headers including the type of data, filename,

encoding used

msg = email.MIMEMultipart.MIMEMultipart()

msg['From'] = fromaddr

msg['To'] = toaddrs

msg['Subject'] = sub

msg.attach(MIMEText(text))

msg.attach(MIMEText('\nsent via python From PI Server', 'plain')) #

'plain ' is a plain text type

#file import file as read only in bytewise process

f = open(filename,'rb')

#ctypy provides C compatible data types, and allows calling functions in

DLLs or shared libraries.

#load file and guess what it is.

ctype, encoding = mimetypes.guess_type(filename)

if ctype is None or encoding is not None:

ctype = 'application/octet-stream'

maintype, subtype = ctype.split('/', 1)

if maintype == 'text':

part = MIMEText(f.read(), _subtype=subtype)

elif maintype == 'image':

part = MIMEImage(f.read(), _subtype=subtype)

elif maintype == 'audio':

part = MIMEAudio(f.read(), _subtype=subtype)

else:

part = MIMEBase(maintype, subtype)

msg.set_payload(f.read())

#attach the file

part.add_header('Content-Disposition', 'attachment; filename="%s"' %

os.path.basename(filename))

msg.attach(part)

#close the file

f.close()

#send the mail

server.sendmail(username,tolist,msg.as_string())

#Quit server

server.quit()

# code refrence http://docs.python.org/2/library/email-examples.html

return

Page 51: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 51 of 71

Figure 39 Email Results:

Page 52: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 52 of 71

Chapter 14 Implementation Text Messaging

To send a text message from the publish function, a text function was created and an

internet based SMS service was used. After researching several different services, it was

decided to use the TextLocal service (http://www.textlocal.com/). Although they did not

have any python examples, they had extensive examples in other languages and allowed a

certain number of development messages to be sent for free.

The text function is called in the same way as the e-mail function, see Figure 37.

The message is sent to the text local send URL along with a unique app hash code, this

sends the message contents to a numbers list. The code seen below is adapted from a PHP

example.

This function was originally planned to be a multimedia messaging service but at this time

text local did not offer this service to Irish numbers, only UK based mobile numbers.

Page 53: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 53 of 71

Figure 40 Text Function Code

#Function text taking in text , temp and light variables

def Text (Text,temp,light):

#This was originally meant to be an mms message service but mms is un available

in ireland from this service.

#There is no Python api for txtlocal(webbased sms service) this is adapted from a

pHp version

#set the localtime variable

localtime = time.asctime( time.localtime(time.time()) )

#Set The message variable"str = The alert plus Time

message = Text+(localtime)+"\nCurrent Conditions"+"\nTemp is

=\t"+temp+"°C"+"\nLight Level is =\t"+light+" lumina"

# Set username and sender name.

# Sender name between 3 and 11 characters in length

username = "[email protected]"

sender = "Pi Project"

# unique hash Gotten from textlocal Php program

hash = "e373cafb7f4919f3b4f729781b2e7bb17e42cdc2"

# Set the phone number you wish to send the message to.

# Multiple numbers separated by comma

numbers = ("353872924405")

# Set flag to 1 to simulate for testing

# To send real message set this flag to 0

test_flag = 0

#PHP arrays are ordered mappings, so used a Python OrderedDict instead of a

regular dict so that the order of insertion is preserved

values = {"test" : test_flag,

"uname" : username,

"hash" : hash,

"message" : message,

"from" : sender,

"selectednums" : numbers }

#url texts are sent from

url = "http://www.txtlocal.com/sendsmspost.php"

#Convert a mapping object or a sequence of two-element tuples to a “percent-

encoded” string, suitable to pass to urlopen()

postdata = urllib.urlencode(values)

#Open the URL url, which is the Request object Postdata.

req = urllib2.Request(url, postdata)

#Try to send

print "Attempt to send SMS ..."

try:

#Open the URL

response = urllib2.urlopen(req)

response_url = response.geturl()

if response_url==url:

print "SMS sent!"

except urllib2.URLError, e:

print "Send failed!"

print e.reason

return

Page 54: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 54 of 71

Page 55: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 55 of 71

Chapter 15 Implementation Facebook

To post a message on a Facebook wall from an external system, a Facebook account is

required. This account can generate an access token and app I.D. from the Facebook

developers section.

Figure 41 Facebook Function

######################################################

# FACEBOOK WALL UPDATER

######################################################

# Variables ,Text,Temp, and light passed in from main (server ) program.

def FaceBook(Text,temp,light):

#Variable localtime set to current time using time module

localtime = time.asctime( time.localtime(time.time()))

#Contents of post

message=Text+(localtime)+"\nCurrent Conditions"+"\nTemp is

=\t"+temp+"°C"+"\nLight Level is =\t"+light+" lumina"

#FaceBook Api Access Token and App ID

access_token='CAACEdEose0cBAMi7w6VtbzOO3DS2cQwK6MIc4Fx1CZBabqUJELzRT6NXAo

CRrKZA9y7DpXzhQzVQmmqYeey7Te5U4mM3IG6pA10wOTanoxSr8JcxCzsstDDZByhBl279RoR

He0Hn2hdxwI6XAMZBeKnmTo72wPZC6I8mD0bvaiguN4Mb0VabbEXdG4zn8A68ZD'

FACEBOOK_APP_ID =100007647638324

#Create a FaceBook Graph object

facebook_graph = facebook.GraphAPI(access_token)

#Posting Text only To Wall To attach a pic must be registered as a

developer.

facebook_graph.put_wall_post(message,profile_id='me')

print "Facebook Wall Updated"

Figure 42 FaceBook Wall Post

Page 56: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 56 of 71

Chapter 16 Discussion

ZeroMQ is not a message broker. It is often mistaken for one because of its name. What

ZeroMQ is, is a library that supports certain network communication patterns using

sockets. The "MQ" part comes in because ZeroMQ uses queues internally to buffer

messages so that you do not block your application when sending data. When you say

socket.send(...), ZeroMQ actually enqueues a message to be sent later by a dedicated

communication thread. This communication thread and its state are encapsulated in the

ZeroMQ context object.

The ZeroMq system is an excellent high speed messaging library upon which to build your

own broker. It is aimed at high volume speed critical applications where cost and

saleability are paramount. As such it was probably a bad choice for a domestic monitoring

system but would be a very good choice if one decides to design a program such as the

next Twitter, for example.

Despite this, even using it in this context could have been improved. In the client server

REP REQ pattern, if the server and client had been swapped it would have allowed for

greater flexibility. Currently the system detects motion (on the PI/Client), sends a message

to the server and waits for response, blocking all ports. Whereas if swapped, upon power

up a ready message would be sent to the PI (now server), and when the PI detects motion it

sends the response to the external system (now Client), this then uses that message to do

work (update the communications suite).

5. Ideally however, a dealer router pattern as seen in Dealer Router Multithreading

Figure 11 could have been used. This would have allowed full proper multi-threading inside

the system. In addition, I believe that it would have allowed much better performance and

possibly for ZMQ to handle the social media aspect as well as just the machine to machine

messaging. This however would have required writing the API’s from scratch.

The python programing language is simple and powerful. It allows to be done is a few

lines of code what would take hundreds of lines in C++ for example. The programs

themselves are tiny in size compared to what the equivalent C++, or Java program would

be. Both programs together are less than 20kb. This makes it ideal for programming in

space sensitive areas.

Page 57: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 57 of 71

Conclusion

This project fulfils all the sections of the initial brief. It uses the Raspberry Pi as a

monitoring system and uses Zmq to send a message to the server. The server controls what

output will go to the Pi and through that server the system interacts with social media.

As with any project of this type it is never complete, it can always be improved or refined

but given the time constraints it performs well.

As a learning experience, this project has been excellent. It allowed me to cover a lot of

ground from learning about the Python programming language, message oriented

middleware, low end of the communication protocols, and the interaction of social media

APIs.

Page 58: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 58 of 71

Bibliography

iMatix Corporation, 2012. ØMQ API Reference. [Online]

Available at: http://api.zeromq.org/

[Accessed 7 03 2014].

Al-Hertani., H., 2013. http://hertaville.com/. [Online]

Available at: http://hertaville.com/2013/07/24/interfacing-an-spi-adc-mcp3008-chip-to-the-

raspberry-pi-using-c/

[Accessed 07 01 2014].

Amy Brown, G. W., 08 May 2012. The Architecture of Open Source Applications, Volume

II. 1st ed. California: Creative Commons: Attribution.

Anon., n.d. [Online]

Available at: http://elinux.org/RPi_Low-level_peripherals

Anon., n.d. [Online]

Available at: http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-

Peripherals.pdf

Grigorik, I., 2010. http://www.igvita.com/. [Online]

Available at: http://www.igvita.com/2010/09/03/zeromq-modern-fast-networking-stack/

[Accessed 21 01 2014].

halherta, July 24, 2013 . http://hertaville.com/. [Online]

Available at: http://hertaville.com/2013/07/24/interfacing-an-spi-adc-mcp3008-chip-to-the-

raspberry-pi-using-c/

[Accessed 07 03 2014].

Hintjens, P., March 2013. ZeroMQ Messaging for Many Applications. 1st ed. Sebastopol,

CA: O'Reilly Media.

Kalinsky, D. K. a. R., 2002. embedded.com. [Online]

Available at: http://www.embedded.com/electronics-blogs/beginner-s-

corner/4023908/Introduction-to-Serial-Peripheral-Interface

Microchip, n.d. MCP3004/3008 Data sheet. [Online]

Available at: http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf

Page 59: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 59 of 71

Scherfke, S., 2012. Designing and Testing PyZMQ Applications, Oldenburg, Germany:

OFFIS – Institute for Information Technology Oldenburg, Germany.

Tezer, O., n.d. [Online]

Available at: https://www.digitalocean.com/community/articles/how-to-work-with-the-

zeromq-messaging- library

Appendices

MCP3008 DataSheet

http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf

TM36 Datasheet:

http://www.analog.com/static/imported-files/data_sheets/TMP35_36_37.pdf

Figure 1Request Reply Pattern ............................................................................................ 19

Figure 2 REP-REQ Pattern Client Python Code ................................................................. 20

Figure 3 REP-REQ Server Python Code ............................................................................. 20

Figure 4 Publish SubScribe ................................................................................................. 21

Figure 5 PUB-SUB Publisher Python Code ........................................................................ 22

Figure 6 PUB-SUB Subscriber Python Code ...................................................................... 22

Figure 7 parallel pipeline ..................................................................................................... 23

Figure 8 Ventalator Code Python Example ......................................................................... 25

Figure 9 Worker Code In Python......................................................................................... 26

Figure 10 Sink Code Python Example................................................................................. 27

Figure 11 Dealer Router Multithreading: ............................................................................ 28

Figure 12 Motion sensor ...................................................................................................... 29

Figure 13 Client Code Main Program ................................................................................. 30

Page 60: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 60 of 71

Figure 14 Client Code Publish Function ............................................................................ 31

Figure 15 Server Code ......................................................................................................... 31

Figure 16 Tweet Function Call ............................................................................................ 32

Figure 17 Twitter Function Code ........................................................................................ 32

Figure 18 Tweet Results ...................................................................................................... 33

Figure 19 Single Master Slave Implementation .................................................................. 34

Figure 20 Single master, multiple slave implementation .................................................... 35

Figure 21 .............................................................................................................................. 35

Figure 22 MCP3008 Pin Out ............................................................................................... 36

Figure 23 Setup of Analogue Sensors ................................................................................. 37

Figure 24 Analogue Sensor code ......................................................................................... 37

Figure 25 Code to Read from analogue sensors .................................................................. 38

Figure 26 Capture Pic Code................................................................................................. 39

Figure 27 client Code........................................................................................................... 40

Figure 28 Server code .......................................................................................................... 41

Figure 29 Results of Camera and analogue sensor addition ................................................ 41

Figure 30 Push button .......................................................................................................... 42

Figure 31 Push button results .............................................................................................. 43

Figure 32 All Sensors IF Else .............................................................................................. 43

Figure 33 Server If else all sensors:..................................................................................... 44

Figure 34 Publish function: ................................................................................................. 45

Figure 35 LED ..................................................................................................................... 46

Figure 36 LED Output code client....................................................................................... 46

Figure 37 Calling Email function ........................................................................................ 48

Figure 38 Email function ..................................................................................................... 48

Figure 39 Email Results: ..................................................................................................... 50

Page 61: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 61 of 71

Figure 40 Text Function Code ............................................................................................ 52

Figure 41 Facebook Function .............................................................................................. 54

Figure 42 FaceBook Wall Post ............................................................................................ 54

Code:

Client Code:

## #!/usr/bin/python

# -*- coding: latin-1 -*-

# Alan Matthews

# Rep Req Client

#192.168.2.4location of all sensors and outputs

# Connects REQ socket to tcp://localhost:5555

#########################################################################

########################

#

import os

#

import sys

#

import re

#

import io

#

import zmq

#

import RPi.GPIO as GPIO

#

import time

#SPI(Serial Peripheral Interface bus) is a synchronous serial data link

import spidev

#

import base64

#

import picamera

#

import threading

#

import datetime

#########################################################################

#######################

# Analogue Sensor Input

#########################################################################

######################

#resets all ports back to input mode

GPIO.cleanup()

# Open SPI bus

spi = spidev.SpiDev()

spi.open(0,0)

# Use BCM GPIO references instead of physical pin numbers

# referring to the pins by the "Broadcom SOC channel" number

GPIO.setmode(GPIO.BCM)

# Function to read SPI data from MCP3008 chip

Page 62: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 62 of 71

# Channel must be an integer 0-7(8 total inputs)

def ReadChannel(channel):

adc = spi.xfer2([1,(8+channel)<<4,0])

data = ((adc[1]&3) << 8) + adc[2]

return data

# Function to convert data to voltage level,

# rounded to specified number of decimal places.

def ConvertVolts(data,places):

volts = (data * 3.3) / float(1023)

volts = round(volts,places)

return volts

# Function to calculate temperature from

# TMP36 data, rounded to specified

# number of decimal places.

def ConvertTemp(data,places):

# ADC Value

# (approx) Temp Volts

# 0 -50 0.00

# 78 -25 0.25

# 155 0 0.50

# 233 25 0.75

# 310 50 1.00

# 388 75 1.25

# 465 100 1.50

# 543 125 1.75

# 620 150 2.00

# 698 175 2.25

# 775 200 2.50

# 853 225 2.75

# 930 250 3.00

# 1008 275 3.25

# 1023 280 3.30

temp = ((data * 330)/float(1023))-50

temp = round(temp,places)

return temp

# Define sensor channels

light_channel = 0

temp_channel = 1

# Define delay between readings

delay = 5

def CapturePic():

# Explicitly open a new file called my_image.jpg

my_file = open('my_image.jpg', 'wb')

with picamera.PiCamera() as camera:

camera.start_preview()

time.sleep(2)

camera.capture(my_file)

# Note that at this point the data is in the file cache, but may

# not actually have been written to disk yet

my_file.close()

# Now the file has been closed, other processes should be able to

# read the image successfully

def Publish(Text):

light_level = ReadChannel(light_channel)

temp_level = ReadChannel(temp_channel)

Page 63: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 63 of 71

temp = ConvertTemp(temp_level,2)

#camm camera function

CapturePic()

#open file "my_image.jpg" and rb read binary as imageFile

with open("my_image.jpg", "rb") as imageFile:

#convert image to string

img = base64.b64encode(imageFile.read())

#print img

#set socket contex

context = zmq.Context()

#convert light to string

light = str(light_level)

#convert temp to string

tm = str(temp)

#set the text element of message

text = Text

#Combine strings into msg

msg = text +":"+ img +":"+light+":"+tm

#bind to server addreess

bind_to = "tcp://192.168.2.5:5561"

print("Connecting to server")

#changed from Req to Push

#Socket for talking to server

socket = context.socket(zmq.REQ)

#connect socket to bind_to Address

socket.connect(bind_to)

# Send request waiting each time for a response

print"Sending ", text

#send message

socket.send(msg)

# Get the reply

message = socket.recv()

print ("Received Reply ", message)

#copy message to X

X = message

#If Else String for returned value from server

if X == "Detected":

print "Turning on Red light "

# Define GPIO pin to use on Pi

GPIO_RLED = 17

print "Led Module Test (CTRL-C to exit)"

#Set Gpio Mode to output

GPIO.setup(GPIO_RLED,GPIO.OUT)

#Set value to high (LED on)

GPIO.output(GPIO_RLED, True)

#time for 5 sceonds

time.sleep(5)

#Set value to low (LED off)

GPIO.output(GPIO_RLED, False)

time.sleep(1)

elif X == "Pressed":

print "sound alarm "

#Define GPIO to use on Pi

GPIO_YLED = 22

print "Led Module Test (CTRL-C to exit)"

GPIO.setup(GPIO_YLED,GPIO.OUT)

GPIO.output(GPIO_YLED, True)

time.sleep(5)

GPIO.output(GPIO_YLED, False)

time.sleep(1)

Page 64: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 64 of 71

elif X == "HeatOn":

print "Turning on Heat "

elif X == "FanOn":

print "Turning on Fan "

print "Turning on Yellow light "

#Define GPIO to use on Pi

GPIO_YLED = 18

print "Led Module Test (CTRL-C to exit)"

GPIO.setup(GPIO_YLED,GPIO.OUT)

GPIO.output(GPIO_YLED, True)

time.sleep(5)

GPIO.output(GPIO_YLED, False)

time.sleep(1)

elif X == "LightOn":

GPIO_GLED = 27

print "Led Module Test (CTRL-C to exit)"

GPIO.setup(GPIO_GLED,GPIO.OUT)

GPIO.output(GPIO_GLED, True)

time.sleep(5)

GPIO.output(GPIO_GLED, False)

time.sleep(1)

print "Turning on The lights "

elif X == "Satus Updated":

print "Satus updated"

else:

print "Did Nothing"

def main():

# Define GPIO to use on Pi

PIR = 24

Button = 25

satus = 0

print "PIR Module Test (CTRL-C to exit)"

# Set pin as input

GPIO.setup(PIR,GPIO.IN)

#Set the button to input

GPIO.setup(Button,GPIO.IN)

Current__State = 0

Previous_State = 0

try:

print "Waiting for PIR to settle ..."

# Loop until PIR output is 0

while GPIO.input(PIR)==1:

Current_State = 0

print 'Ready'

# Loop until users quits with CTRL-C

while True :

#Set satus to false

satus = 0

#Get the time and set variable equal to it

upDateTime = datetime.datetime.now()

#UpDate on the hour and half hour,(by adding day this could be

set to any time or day)

if (upDateTime.minute ==00 or upDateTime.minute ==30) and

(upDateTime.second ==30):

#set satus to true

satus = 1

# Read the light sensor data

Page 65: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 65 of 71

light_level = ReadChannel(light_channel)

light_volts = ConvertVolts(light_level,2)

# Read the temperature sensor data

temp_level = ReadChannel(temp_channel)

temp_volts = ConvertVolts(temp_level,2)

temp = ConvertTemp(temp_level,2)

# When The time is righ UpDate

if satus==1:

print "Time for Update"

Publish("Satus Update")

satus ==0

# Read PIR state

if GPIO.input(PIR)==1:

# PIR is triggered

print " Motion detected!"

Publish("Motion")

# If button high (pushed)

if GPIO.input(Button)==1:

print "button pushed"

Publish("Button")

# When temp below approx 11 Degrees

if temp_level <180:

print "Brrr It's Cold"

Publish("Cold")

# When temp above approx 30 Degrees

if temp_level >300:

print "Dam Its hot"

Publish("Hot")

# From trial and error Dark Room

if light_level>1000:

print "Its Dark"

Publish("Dark")

# Wait for 10 milliseconds

time.sleep(0.01)

except KeyboardInterrupt:

print " Quit"

# Reset GPIO settings

GPIO.cleanup()

return

if __name__ == "__main__":

main()

Server Code:

#!/usr/bin.python

# -*- coding: latin-1 -*-

# Author: Alan Matthews

# PI Monitor server in Python

# Binds REP socket to tcp://*:5555

# 02/03/14

# Added Exception handling

# Version 0.1.3

#########################################################################

###########################################

Page 66: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 66 of 71

#For more information on amy modules please see

http://docs.python.org/2.7/

#The ZeroMQ Liblary

import zmq

#JSON (JavaScript Object Notation)used as a lightweight data interchange

format

import json

#provides data encoding and decoding

import base64

#This module provides various time-related functions

import time

#This module provides access to variables used or maintained by the

interpreter and functions that interact with the interpreter.

import sys

#This module defines an SMTP client session object that can be used to

send mail to any Internet machine with an SMTP

import smtplib

#This module provides a way of using operating system functionality.e.g

to read or write a file

import os

#The email module is a library for managing email messages, including

MIME

import email

#Python's email package contains many classes and functions for composing

and parsing email messages

#by only importing only the classes we need, this saves us from having to

use the full module name later.

from email.MIMEMultipart import MIMEMultipart

from email.Utils import COMMASPACE

from email.MIMEBase import MIMEBase

from email.parser import Parser

from email.MIMEImage import MIMEImage

from email.MIMEText import MIMEText

from email.MIMEAudio import MIMEAudio

#For guessing MIME type based on file name extension

import mimetypes

#twython is a pure Python wrapper for the Twitter API. Supports both

normal and streaming Twitter APIs

from twython import Twython, TwythonError

#Facebook graph Api

import facebook

#This module provides a high-level interface for fetching data across the

World Wide Web.

# module defines functions and classes which help in opening URLs and

breaking URL strings up into components

import urllib,urllib2,urlparse

#########################################################################

###########################################

# FACEBOOK WALL UPDATER

#########################################################################

###########################################

# Variables ,Text,Temp, and light passed in from main (server ) program.

def FaceBook(Text,temp,light):

#Variable localtime ste to current time using time module

localtime = time.asctime( time.localtime(time.time()))

#Contents of post

message=Text+(localtime)+"\nCurrent Conditions"+"\nTemp is

=\t"+temp+"°C"+"\nLight Level is =\t"+light+" lumina"

#FaceBook Api Access Token and App ID

Page 67: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 67 of 71

access_token='CAACEdEose0cBAMi7w6VtbzOO3DS2cQwK6MIc4Fx1CZBabqUJELzRT6NXAo

CRrKZA9y7DpXzhQzVQmmqYeey7Te5U4mM3IG6pA10wOTanoxSr8JcxCzsstDDZByhBl279RoR

He0Hn2hdxwI6XAMZBeKnmTo72wPZC6I8mD0bvaiguN4Mb0VabbEXdG4zn8A68ZD'

FACEBOOK_APP_ID =100007647638324

#Create a FaceBook Graph object

facebook_graph = facebook.GraphAPI(access_token)

#Posting Text only To Wall To attach a pic must be registered as a

developer.

facebook_graph.put_wall_post(message,profile_id='me')

print "Facebook Wall Updated"

#########################################################################

###########################################

# Twitter Function

#########################################################################

###########################################

def Tweet(Text,temp,light):

#set the localtime variable

localtime = time.asctime( time.localtime(time.time()))

#Set The message variable"msg" = The alert plus localTime, + temp and

light

msg = Text+(localtime)+"\nCurrent Conditions"+"\nTemp is

=\t"+temp+"°C"+"\nLight Level is =\t"+light+" lumina"

#Twitter Access Keys

CONSUMER_KEY = 'RbwVNyNI25q3U1y2TKhdw'

CONSUMER_SECRET = '09dK2OkqVuVo9I12mUzltm01gi4YtnTXSZfvLwpA4'

ACCESS_KEY = '2317027770-HgSg4Q4Xn4uzDpZwKpABUz67QxFVb8ah57LB51D'

ACCESS_SECRET = 'a8FiPxgpbBif93qaUQpa3w5zaq0bq6KizUkvV8SDnJZZn'

#Use Twython api To sign in to twitter

api = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)

#Open jpg image, "rb" is read only byte for

photo = open('my_image.jpg', 'rb')

try:

#Update satus

api.update_status_with_media(status=msg, media=photo)

# error handling

except TwythonError as e:

print e

#########################################################################

###########################################

# Text Message Service

#########################################################################

###########################################

#Function text taking in text , temp and light variables

def Text (Text,temp,light):

#This was originaly ment to be an mms message service but mms is un

avaiable in ireland from this service.

#There is no Python api for txtlocal(webbased sms service) this is

adapted from a pHp version

#set the localtime variable

localtime = time.asctime( time.localtime(time.time()) )

#Set The message variable"str = The alert plus Time

message = Text+(localtime)+"\nCurrent Conditions"+"\nTemp is

=\t"+temp+"°C"+"\nLight Level is =\t"+light+" lumina"

# Set username and sender name.

# Sender name between 3 and 11 characters in length

Page 68: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 68 of 71

username = "[email protected]"

sender = "Pi Project"

# unique hash Gotten from textlocal Php program

hash = "e373cafb7f4919f3b4f729781b2e7bb17e42cdc2"

# Set the phone number you wish to send the message to.

# Multiple numbers seprated by comma

numbers = ("353872924405")

# Set flag to 1 to simulate for testing

# To send real message set this flag to 0

test_flag = 0

#PHP arrays are ordered mappings, so used a Python OrderedDict instead

of a regular dict so that the order of insertion is preserved

values = {"test" : test_flag,

"uname" : username,

"hash" : hash,

"message" : message,

"from" : sender,

"selectednums" : numbers }

#url texts are sent from

url = "http://www.txtlocal.com/sendsmspost.php"

#Convert a mapping object or a sequence of two-element tuples to a

“percent-encoded” string, suitable to pass to urlopen()

postdata = urllib.urlencode(values)

#Open the URL url, which is the Request object Postdata.

req = urllib2.Request(url, postdata)

#Try to send

print "Attempt to send SMS ..."

try:

#Open the URL

response = urllib2.urlopen(req)

response_url = response.geturl()

if response_url==url:

print "SMS sent!"

except urllib2.URLError, e:

print "Send failed!"

print e.reason

return

#########################################################################

###########################################

# Email function

#########################################################################

###########################################

#Pass the three variables into the email function

def Email (Text,temp,light):

#From Address Can be any address

fromaddr = "[email protected]"

# Address To Must be a valid addresses

tolist = "[email protected]"

# Message body

text = Text+"\nCurrent Conditions"+"\nTemp is ="+temp+" Degrees

C"+"\nLight Level is ="+light+" lumina"

# Attachment location /path/to/file in this instance file is in same

folder so name is sufficent

filename = 'my_image.jpg'

# Credentials

username = "[email protected]"

password = "Al1981mat"

#SMTP host address and port number

Page 69: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 69 of 71

host = 'smtp.gmail.com'

port = 587

# Create a stmp object clled server

server = smtplib.SMTP()

#connect to smtp host

server.connect( host,port)

#start Transport Layer Security

server.starttls()

#Login to mail server

server.login(username,password)

#Sbject Field

sub = ('Subject: Update From PI ')

#Mimemultipart allows Multiple attachments Divides the message into

parts, Each part has headers including the type of data, filename,

encoding used

msg = email.MIMEMultipart.MIMEMultipart()

msg['From'] = fromaddr

msg['To'] = toaddrs

msg['Subject'] = sub

msg.attach(MIMEText(text))

msg.attach(MIMEText('\nsent via python From PI Server', 'plain')) #

'plain ' is a plain text type

#file import file as read only in bytewise process

f = open(filename,'rb')

#ctypy provides C compatible data types, and allows calling functions in

DLLs or shared libraries.

#load file and guess what it is.

ctype, encoding = mimetypes.guess_type(filename)

if ctype is None or encoding is not None:

ctype = 'application/octet-stream'

maintype, subtype = ctype.split('/', 1)

if maintype == 'text':

part = MIMEText(f.read(), _subtype=subtype)

elif maintype == 'image':

part = MIMEImage(f.read(), _subtype=subtype)

elif maintype == 'audio':

part = MIMEAudio(f.read(), _subtype=subtype)

else:

part = MIMEBase(maintype, subtype)

msg.set_payload(f.read())

#attach the file

part.add_header('Content-Disposition', 'attachment; filename="%s"' %

os.path.basename(filename))

msg.attach(part)

#close the file

f.close()

#send the mail

server.sendmail(username,tolist,msg.as_string())

#Quit server

server.quit()

# code refrence http://docs.python.org/2/library/email-examples.html

return

#########################################################################

###########################################

# Main server program

#########################################################################

###########################################

def Server():

#start of ZmQ Server or main program

Page 70: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 70 of 71

#Create context object to a zmq Context

context = zmq.Context()

#Set socket contex to Rep, for a REQ-REP socket

socket = context.socket(zmq.REP)

#Bind Socket to "tcp://Localhost:Portnumber"

socket.bind("tcp://192.168.2.5:5561")

#loop ctrl-c

while True:

# Wait for next request from client

message = socket.recv()

#Split the recived message at: to seprate out the image , and

variables from the string

text, Image, light, temp = message.split(":")

#Print variables to screen

print "Received request: ", text

print "The text is = ", text

print "The Temp is = ", temp,"°C"

print "The Light is =", light," lumina"

#uncomment below to see Image as a string

#print "The Image is = ",Image

#open image file in "wb" (writeable and binary mode).

f = open("my_image.jpg", "wb")

#Deccode back to an image from string using base64

f.write(Image.decode('base64'))

# close file

f.close()

#IF Else srting of possiable requests

if text == "Motion":

#Pass variables to functions and set text to

FaceBook("Motion Detected @",temp,light)

Tweet("Motion Detected @ ",temp,light)

Email("Motion Detected ",temp,light)

Text("Motion Detected @",temp,light)

time.sleep (1)

#Send reply back to client

socket.send("Detected")

elif text == "Button":

FaceBook("Button Pressed @",temp,light)

Tweet("Button Pressed @",temp,light)

Email("Button Pressed ",temp,light)

Text("Button Pressed @",temp,light)

time.sleep(1)

socket.send("Pressed")

#condition for low light

elif text == "Dark":

FaceBook("It's dark in Here @",temp,light)

Tweet("It's dark in Here @",temp,light)

Email("It's dark in Here",temp,light)

Text("It's Dark in Here @",temp,light)

time.sleep (1)

# Send reply back to client

socket.send("LightOn")

#conditon for Cold

elif text == "Cold":

FaceBook("It's Cold In Here @",temp,light)

Tweet("It's Cold In Here @",temp,light)

Email("It's Cold In Here",temp,light)

Text("It's Cold In Here @",temp,light)

Page 71: Evaluation of the Zero MQ Socket Library

Evaluation of the Zero MQ socket library DT080B

Page 71 of 71

time.sleep (1)

#Send reply back to client

socket.send("HeatOn")

#Condition for Hot

elif text == "Hot":

FaceBook("It's Getting Hot In Here @ ",temp,light)

Tweet("It's Getting Hot In Here @ ",temp,light)

Email("It's Getting Hot In Here",temp,light)

Text("It's Getting Hot In Here @",temp,light)

time.sleep (1)

#Send reply back to client

socket.send("FanOn")

#Condition for timed satus update

elif text == "Satus Update":

FaceBook("Satus Update From Pi @",temp,light)

Tweet("Satus Update From Pi @",temp,light)

Email("Satus Update From Pi",temp,light)

Text("Satus Update From Pi",temp,light)

#Send reply back to client

socket.send("Satus Recived")

#If unknown mwssage reciver reply

else:

# Do some 'work'

time.sleep (1)

# Send reply back to client

print("What'chu talkin' 'bout, Willis?")

socket.send("What'chu talkin' 'bout, Willis?")

#########################################################################

###########################################

# Main Program

#########################################################################

###########################################

def main():

#run till control c

print "Hit control-c to Quit"

try:

Server()

except KeyboardInterrupt:

print "You hit control-c Goodbye"

if __name__ == "__main__":

main()