<< Summary
Control the Raspberry PI through email, in Java 
Content
You'll find many articles showing how to use a web server like Apache to control your Raspberry PI over the Internet.
What they don't say - or don't say loud enough - is that to do so, your web server needs to be visible to (and from) the outside world.
Otherwise, you cannot access it outside of your home or ad-hoc network.
What those articles present is a nice way to:
- Know what the conditions are on the Raspberry PI
- Ask remotely to the Raspberry PI to take some action
- For example
-
You are at work, the Raspberry PI is at home.
Your Raspberry PI has a temperature sensor connected to it, and it is also connected to some heater switch.
- When the temperature in the home drops below a given threshold, it sends you a message (through whatever channel, WebSocket or so)
- On reception of the message, you - wherever you are - decide to ask the Raspberry PI to turn the heater on
To do so, you need to be on the same network as the Raspberry PI, or the network the Raspberry PI is on needs to
be visible from your location.
This does not happen if you don't have a registered IP address for your Raspberry PI.
It kind of kills the story...
A way to address this problem is to use emails.
This will not implement real-time messaging - like WebSocket would - but this will allow a form of communication,
only relying on email service - like Yahoo! or Google. Those providers offer free email accounts, which is all you
would need.
All you need on the client side (ie you, at work) is a browser, from which you can send and receive emails.
On the server side (ie the Raspberry PI, at home) you will need:
The json parser is used to parse the content of the email messages. We choosed this technology in this example; others can be used as well, like XML, plain text messages, etc. Your call.
All the sources are available in an archive you can get at the bottom of this document.
- email.properties
-
All properties concerning the emails accounts are externalized in this properties file.
Lines 1 to 5 concern the origins, and the destinations of the emails going back and forth, as well as the subjects used
for the emails (events, acknowledgements, and requests).
Notice the URL at the top of the file (line 7), it could help you to find the servers you are interested in.
- pi4j.gpio.RaspberryPIEventListener.java
-
This is the interface used for the callback invoked when an event is triggered on the Reaspberry Pi's side.
Namely, when the button will be pressed.
1 package pi4j.gpio;
2
3 import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
4
5 public interface RaspberryPIEventListener
6 {
7 public void manageEvent(GpioPinDigitalStateChangeEvent event);
8 }
- pi4j.email.EmailReceiver.java
-
This is the utility class used to receive emails. Its behavior heavily depends on the values
set in
email.properties.
Do check out the method named setProps() (line 119). It might need to be tweaked to fit your
email environment.
1 package pi4j.email;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.InputStreamReader;
10 import java.io.OutputStream;
11
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Properties;
15 import java.util.Set;
16
17 import javax.mail.Address;
18 import javax.mail.Flags;
19 import javax.mail.Folder;
20 import javax.mail.Message;
21 import javax.mail.Multipart;
22 import javax.mail.Part;
23 import javax.mail.PasswordAuthentication;
24 import javax.mail.Session;
25 import javax.mail.Store;
26 import javax.mail.internet.InternetAddress;
27 import javax.mail.search.AndTerm;
28 import javax.mail.search.FlagTerm;
29 import javax.mail.search.FromStringTerm;
30 import javax.mail.search.OrTerm;
31 import javax.mail.search.SearchTerm;
32 import javax.mail.search.SubjectTerm;
33
34 public class EmailReceiver
35 {
36 private static String protocol;
37 private static int outgoingPort;
38 private static int incomingPort;
39 private static String username;
40 private static String password;
41 private static String outgoing;
42 private static String incoming;
43 private static String replyto;
44 private static boolean smtpauth;
45
46 private static String sendEmailsTo;
47 private static String acceptEmailsFrom;
48 private static String acceptSubject;
49 private static String ackSubject;
50
51 private static boolean verbose = "true".equals(System.getProperty("verbose", "false"));
52
53 private EmailSender emailSender = null; // For Ack
54 private String provider = null;
55
56 public EmailReceiver(String provider) throws RuntimeException
57 {
58 this.provider = provider;
59 EmailReceiver.protocol = "";
60 EmailReceiver.outgoingPort = 0;
61 EmailReceiver.incomingPort = 0;
62 EmailReceiver.username = "";
63 EmailReceiver.password = "";
64 EmailReceiver.outgoing = "";
65 EmailReceiver.incoming = "";
66 EmailReceiver.replyto = "";
67 EmailReceiver.smtpauth = false;
68
69 EmailReceiver.sendEmailsTo = "";
70 EmailReceiver.acceptEmailsFrom = "";
71 EmailReceiver.acceptSubject = "";
72 EmailReceiver.ackSubject = "";
73
74 Properties props = new Properties();
75 String propFile = "email.properties";
76 try
77 {
78 FileInputStream fis = new FileInputStream(propFile);
79 props.load(fis);
80 }
81 catch (Exception e)
82 {
83 System.out.println("email.properies file problem...");
84 throw new RuntimeException("File not found:email.properies");
85 }
86 EmailReceiver.sendEmailsTo = props.getProperty("pi.send.emails.to");
87 EmailReceiver.acceptEmailsFrom = props.getProperty("pi.accept.emails.from");
88 EmailReceiver.acceptSubject = props.getProperty("pi.email.subject");
89 EmailReceiver.ackSubject = props.getProperty("pi.ack.subject");
90
91 EmailReceiver.protocol = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.protocol");
92 EmailReceiver.outgoingPort = Integer.parseInt(props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "outgoing.server.port", "0"));
93 EmailReceiver.incomingPort = Integer.parseInt(props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "incoming.server.port", "0"));
94 EmailReceiver.username = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.username", "");
95 EmailReceiver.password = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.password", "");
96 EmailReceiver.outgoing = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "outgoing.server", "");
97 EmailReceiver.incoming = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "incoming.server", "");
98 EmailReceiver.replyto = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.replyto", "");
99 EmailReceiver.smtpauth = "true".equals(props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.smtpauth", "false"));
100
101 if (verbose)
102 {
103 System.out.println("Protocol:" + EmailReceiver.protocol);
104 System.out.println("Usr/pswd:" + EmailReceiver.username + "/" + EmailReceiver.password);
105 }
106 }
107
108 private static SearchTerm[] buildSearchTerm(String str)
109 {
110 String[] sa = str.split(",");
111 List<SearchTerm> lst = new ArrayList<SearchTerm>();
112 for (String s : sa)
113 lst.add(new FromStringTerm(s.trim()));
114 SearchTerm[] sta = new SearchTerm[lst.size()];
115 sta = lst.toArray(sta);
116 return sta;
117 }
118
119 private Properties setProps()
120 {
121 Properties props = new Properties();
122 props.put("mail.debug", verbose?"true":"false");
123
124 // TASK smtp should be irrelevant for a receiver
125 props.put("mail.smtp.host", EmailReceiver.outgoing);
126 props.put("mail.smtp.port", Integer.toString(EmailReceiver.outgoingPort));
127
128 props.put("mail.smtp.auth", "true");
129 props.put("mail.smtp.starttls.enable", "true"); // See http://www.oracle.com/technetwork/java/faq-135477.html#yahoomail
130 // props.put("mail.smtp.starttls.required", "true");
131 props.put("mail.smtp.ssl.enable", "true");
132
133 if ("pop3".equals(EmailReceiver.protocol))
134 {
135 props.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
136 props.setProperty("mail.pop3.socketFactory.fallback", "false");
137 props.setProperty("mail.pop3.port", Integer.toString(EmailReceiver.incomingPort));
138 props.setProperty("mail.pop3.socketFactory.port", Integer.toString(EmailReceiver.incomingPort));
139 }
140
141 if ("imap".equals(protocol))
142 {
143 props.setProperty("mail.imap.starttls.enable", "false");
144 // Use SSL
145 props.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
146 props.setProperty("mail.imap.socketFactory.fallback", "false");
147
148 props.setProperty("mail.imap.port", Integer.toString(EmailReceiver.incomingPort));
149 props.setProperty("mail.imap.socketFactory.port", Integer.toString(EmailReceiver.incomingPort));
150
151 props.setProperty("mail.imaps.class", "com.sun.mail.imap.IMAPSSLStore");
152 }
153 return props;
154 }
155
156 public boolean isAuthRequired()
157 {
158 return EmailReceiver.smtpauth;
159 }
160
161 public String getUserName()
162 {
163 return EmailReceiver.username;
164 }
165
166 public String getPassword()
167 {
168 return EmailReceiver.password;
169 }
170
171 public String getReplyTo()
172 {
173 return EmailReceiver.replyto;
174 }
175
176 public String getIncomingServer()
177 {
178 return EmailReceiver.incoming;
179 }
180
181 public String getOutgoingServer()
182 {
183 return EmailReceiver.outgoing;
184 }
185
186 public List<String> receive()
187 throws Exception
188 {
189 return receive(null);
190 }
191
192 public List<String> receive(String dir)
193 throws Exception
194 {
195 if (verbose) System.out.println("Receiving...");
196 List<String> messList = new ArrayList<String>();
197 Store store = null;
198 Folder folder = null;
199 try
200 {
201 // Properties props = System.getProperties();
202 Properties props = setProps();
203
204 if (verbose)
205 {
206 Set<Object> keys = props.keySet();
207 for (Object o : keys)
208 System.out.println(o.toString() + ":" + props.get(o).toString());
209 }
210 if (verbose) System.out.println("Getting session...");
211 // Session session = Session.getInstance(props, null);
212 Session session = Session.getInstance(props,
213 new javax.mail.Authenticator()
214 {
215 protected PasswordAuthentication getPasswordAuthentication()
216 {
217 return new PasswordAuthentication(username, password);
218 }
219 });
220 session.setDebug(verbose);
221 if (verbose) System.out.println("Session established.");
222 store = session.getStore(EmailReceiver.protocol);
223 if (EmailReceiver.incomingPort == 0)
224 store.connect(EmailReceiver.incoming, EmailReceiver.username, EmailReceiver.password);
225 else
226 store.connect(EmailReceiver.incoming, EmailReceiver.incomingPort, EmailReceiver.username, EmailReceiver.password);
227 if (verbose) System.out.println("Connected to store");
228 folder = store.getDefaultFolder();
229 if (folder == null)
230 throw new RuntimeException("No default folder");
231
232 folder = store.getFolder("INBOX");
233 if (folder == null)
234 throw new RuntimeException("No INBOX");
235
236 folder.open(Folder.READ_WRITE);
237 if (verbose) System.out.println("Connected... filtering, please wait.");
238 SearchTerm st = new AndTerm(new SearchTerm[] { new OrTerm(buildSearchTerm(sendEmailsTo)),
239 new SubjectTerm(acceptSubject),
240 new FlagTerm(new Flags(Flags.Flag.SEEN), false) });
241 // st = new SubjectTerm("PI Request");
242 Message msgs[] = folder.search(st);
243 // Message msgs[] = folder.getMessages();
244
245 if (verbose) System.out.println("Search completed, " + msgs.length + " message(s).");
246 for (int msgNum=0; msgNum<msgs.length; msgNum++)
247 {
248 try
249 {
250 Message mess = msgs[msgNum];
251 Address from[] = mess.getFrom();
252 String sender = "";
253 try
254 {
255 sender = from[0].toString();
256 }
257 catch(Exception exception)
258 {
259 exception.printStackTrace();
260 }
261 // System.out.println("Message from [" + sender + "], subject [" + subject + "], content [" + mess.getContent().toString().trim() + "]");
262
263 if (true)
264 {
265 if (!mess.isSet(javax.mail.Flags.Flag.SEEN) &&
266 !mess.isSet(javax.mail.Flags.Flag.DELETED))
267 {
268 String txtMess = printMessage(mess, dir);
269 messList.add(txtMess);
270 mess.setFlag(javax.mail.Flags.Flag.SEEN, true);
271 mess.setFlag(javax.mail.Flags.Flag.DELETED, true);
272 // Send an ack - by email.
273 if (this.emailSender == null)
274 this.emailSender = new EmailSender(this.provider);
275 this.emailSender.send(new String[] { sender },
276 ackSubject,
277 "Your request [" + txtMess.trim() + "] is being taken care of.");
278 if (verbose) System.out.println("Sent an ack to " + sender);
279 }
280 else
281 {
282 if (verbose) System.out.println("Old message in your inbox..., received " + mess.getReceivedDate().toString());
283 }
284 }
285 }
286 catch(Exception ex)
287 {
288 // System.err.println(ex.getMessage());
289 ex.printStackTrace();
290 }
291 }
292 }
293 catch(Exception ex)
294 {
295 throw ex;
296 }
297 finally
298 {
299 try
300 {
301 if (folder != null)
302 folder.close(true);
303 if (store != null)
304 store.close();
305 }
306 catch(Exception ex2)
307 {
308 System.err.println("Finally ...");
309 ex2.printStackTrace();
310 }
311 }
312 return messList;
313 }
314
315 public static String printMessage(Message message, String dir)
316 {
317 String ret = "";
318 try
319 {
320 String from = ((InternetAddress)message.getFrom()[0]).getPersonal();
321 if(from == null)
322 from = ((InternetAddress)message.getFrom()[0]).getAddress();
323 if (verbose) System.out.println("From: " + from);
324 String subject = message.getSubject();
325 if (verbose) System.out.println("Subject: " + subject);
326 Part messagePart = message;
327 Object content = messagePart.getContent();
328 if (content instanceof Multipart)
329 {
330 // messagePart = ((Multipart)content).getBodyPart(0);
331 int nbParts = ((Multipart)content).getCount();
332 if (verbose) System.out.println("[ Multipart Message ], " + nbParts + " part(s).");
333 for (int i=0; i<nbParts; i++)
334 {
335 messagePart = ((Multipart)content).getBodyPart(i);
336 if (messagePart.getContentType().toUpperCase().startsWith("APPLICATION/OCTET-STREAM"))
337 {
338 if (verbose) System.out.println(messagePart.getContentType() + ":" + messagePart.getFileName());
339 InputStream is = messagePart.getInputStream();
340 String newFileName = "";
341 if (dir != null)
342 newFileName = dir + File.separator;
343 newFileName += messagePart.getFileName();
344 FileOutputStream fos = new FileOutputStream(newFileName);
345 ret = messagePart.getFileName();
346 if (verbose) System.out.println("Downloading " + messagePart.getFileName() + "...");
347 copy(is, fos);
348 if (verbose) System.out.println("...done.");
349 }
350 else // text/plain, text/html
351 {
352 if (verbose) System.out.println("-- Part #" + i + " --, " + messagePart.getContentType().replace('\n', ' ').replace('\r', ' ').replace("\b", "").trim());
353 InputStream is = messagePart.getInputStream();
354 BufferedReader br = new BufferedReader(new InputStreamReader(is));
355 String line = "";
356 while (line != null)
357 {
358 line = br.readLine();
359 if (line != null)
360 {
361 if (verbose) System.out.println("[" + line + "]");
362 if (messagePart.getContentType().toUpperCase().startsWith("TEXT/PLAIN"))
363 ret += line;
364 }
365 }
366 br.close();
367 if (verbose) System.out.println("-------------------");
368 }
369 }
370 }
371 else
372 {
373 // System.out.println(" .Message is a " + content.getClass().getName());
374 // System.out.println("Content:");
375 // System.out.println(content.toString());
376 ret = content.toString();
377 }
378 if (verbose) System.out.println("-----------------------------");
379 }
380 catch(Exception ex)
381 {
382 ex.printStackTrace();
383 }
384 return ret;
385 }
386
387 private static void copy(InputStream in, OutputStream out)
388 throws IOException
389 {
390 synchronized(in)
391 {
392 synchronized(out)
393 {
394 byte buffer[] = new byte[256];
395 while (true)
396 {
397 int bytesRead = in.read(buffer);
398 if(bytesRead == -1)
399 break;
400 out.write(buffer, 0, bytesRead);
401 }
402 }
403 }
404 }
405 }
- pi4j.email.EmailSender.java
-
Same as the previous, but for outgoing emails. Notice that the two can be different.
You might very well send emails using Yahoo! and receive others using Google.
This way, the Raspberry PI and you would have your own email addresses.
As before, check out the method named setProps() (line 164). It might need to be tweaked to fit your
email environment.
1 package pi4j.email;
2
3 import com.sun.mail.smtp.SMTPTransport;
4
5 import java.io.FileInputStream;
6
7 import java.util.Properties;
8
9 import javax.activation.DataHandler;
10 import javax.activation.DataSource;
11 import javax.activation.FileDataSource;
12
13 import javax.mail.BodyPart;
14 import javax.mail.Message;
15 import javax.mail.MessagingException;
16 import javax.mail.Multipart;
17 import javax.mail.PasswordAuthentication;
18 import javax.mail.Session;
19 import javax.mail.Transport;
20 import javax.mail.internet.AddressException;
21 import javax.mail.internet.InternetAddress;
22 import javax.mail.internet.MimeBodyPart;
23 import javax.mail.internet.MimeMessage;
24 import javax.mail.internet.MimeMultipart;
25
26 public class EmailSender
27 {
28 private static String protocol;
29 private static int outgoingPort;
30 private static int incomingPort;
31 private static String username;
32 private static String password;
33 private static String outgoing;
34 private static String incoming;
35 private static String replyto;
36 private static boolean smtpauth;
37
38 private static String sendEmailsTo;
39 private static String eventSubject;
40
41 private static boolean verbose = "true".equals(System.getProperty("verbose", "false"));
42
43 public EmailSender(String provider) throws RuntimeException
44 {
45 EmailSender.protocol = "";
46 EmailSender.outgoingPort = 0;
47 EmailSender.incomingPort = 0;
48 EmailSender.username = "";
49 EmailSender.password = "";
50 EmailSender.outgoing = "";
51 EmailSender.incoming = "";
52 EmailSender.replyto = "";
53 EmailSender.smtpauth = false;
54 EmailSender.sendEmailsTo = "";
55 EmailSender.eventSubject = "";
56
57 Properties props = new Properties();
58 String propFile = "email.properties";
59 try
60 {
61 FileInputStream fis = new FileInputStream(propFile);
62 props.load(fis);
63 }
64 catch (Exception e)
65 {
66 System.out.println("email.properies file problem...");
67 throw new RuntimeException("File not found:email.properies");
68 }
69 EmailSender.sendEmailsTo = props.getProperty("pi.send.emails.to");
70 EmailSender.eventSubject = props.getProperty("pi.event.subject");
71
72 EmailSender.protocol = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.protocol");
73 EmailSender.outgoingPort = Integer.parseInt(props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "outgoing.server.port", "0"));
74 EmailSender.incomingPort = Integer.parseInt(props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "incoming.server.port", "0"));
75 EmailSender.username = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.username", "");
76 EmailSender.password = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.password", "");
77 EmailSender.outgoing = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "outgoing.server", "");
78 EmailSender.incoming = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "incoming.server", "");
79 EmailSender.replyto = props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.replyto", "");
80 EmailSender.smtpauth = "true".equals(props.getProperty("pi." + (provider != null ? (provider + ".") : "") + "mail.smtpauth", "false"));
81
82 if (verbose)
83 {
84 System.out.println("-------------------------------------");
85 System.out.println("Protocol : " + EmailSender.protocol);
86 System.out.println("Usr/pswd : " + EmailSender.username + "/" + EmailSender.password);
87 System.out.println("Incoming server: " + EmailSender.incoming + ":" + EmailSender.incomingPort);
88 System.out.println("Outgoing server: " + EmailSender.outgoing + ":" + EmailSender.outgoingPort);
89 System.out.println("replyto : " + EmailSender.replyto);
90 System.out.println("SMTPAuth : " + EmailSender.smtpauth);
91 System.out.println("-------------------------------------");
92 }
93 }
94
95 public boolean isAuthRequired()
96 {
97 return EmailSender.smtpauth;
98 }
99
100 public String getUserName()
101 {
102 return EmailSender.username;
103 }
104
105 public String getPassword()
106 {
107 return EmailSender.password;
108 }
109
110 public String getReplyTo()
111 {
112 return EmailSender.replyto;
113 }
114
115 public String getIncomingServer()
116 {
117 return EmailSender.incoming;
118 }
119
120 public String getOutgoingServer()
121 {
122 return EmailSender.outgoing;
123 }
124
125 public String getEmailDest()
126 {
127 return EmailSender.sendEmailsTo;
128 }
129
130 public String getEventSubject()
131 {
132 return EmailSender.eventSubject;
133 }
134
135 public void send(String[] dest,
136 String subject,
137 String content)
138 throws MessagingException, AddressException
139 {
140 send(dest, subject, content, null);
141 }
142
143 public void send(String[] dest,
144 String subject,
145 String content,
146 String attachment)
147 throws MessagingException, AddressException
148 {
149 Properties props = setProps();
150
151 // Session session = Session.getDefaultInstance(props, auth);
152 Session session = Session.getInstance(props,
153 new javax.mail.Authenticator()
154 {
155 protected PasswordAuthentication getPasswordAuthentication()
156 {
157 return new PasswordAuthentication(username, password);
158 }
159 });
160 session.setDebug(verbose);
161 Transport tr = session.getTransport("smtp");
162 if (!(tr instanceof SMTPTransport))
163 System.out.println("This is NOT an SMTPTransport:[" + tr.getClass().getName() + "]");
164
165 Message msg = new MimeMessage(session);
166 msg.setFrom(new InternetAddress(EmailSender.replyto));
167 if (dest == null || dest.length == 0)
168 throw new RuntimeException("Need at least one recipient.");
169 msg.setRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(dest[0]));
170 for (int i=1; i<dest.length; i++)
171 msg.addRecipient(javax.mail.Message.RecipientType.CC, new InternetAddress(dest[i]));
172 msg.setSubject(subject);
173
174 if (attachment != null)
175 {
176 BodyPart messageBodyPart = new MimeBodyPart();
177 messageBodyPart.setText(content);
178 Multipart multipart = new MimeMultipart();
179 // Set text message part
180 multipart.addBodyPart(messageBodyPart);
181 // Part two is attachment
182 messageBodyPart = new MimeBodyPart();
183 String filename = attachment;
184 DataSource source = new FileDataSource(filename);
185 messageBodyPart.setDataHandler(new DataHandler(source));
186 messageBodyPart.setFileName(filename);
187 multipart.addBodyPart(messageBodyPart);
188 // Send the complete message parts
189 msg.setContent(multipart);
190 }
191 else
192 {
193 msg.setText(content != null ? content : "");
194 msg.setContent(content, "text/plain");
195 }
196 msg.saveChanges();
197 if (verbose) System.out.println("sending:[" + content + "], " + Integer.toString(content.length()) + " characters");
198 Transport.send(msg);
199 }
200
201 private Properties setProps()
202 {
203 Properties props = new Properties();
204 props.put("mail.debug", verbose?"true":"false");
205 props.put("mail.smtp.host", EmailSender.outgoing);
206 props.put("mail.smtp.port", Integer.toString(EmailSender.outgoingPort));
207
208 props.put("mail.smtp.auth", "true");
209 props.put("mail.smtp.starttls.enable", "true"); // See http://www.oracle.com/technetwork/java/faq-135477.html#yahoomail
210 // props.put("mail.smtp.starttls.required", "true");
211 props.put("mail.smtp.ssl.enable", "true");
212 return props;
213 }
214 }
- pi4j.gpio.GPIOController.java
-
Interaction with the GPIO on the Raspberry PI.
Notice the pins we use:
- Yellow led on pin #01 (line 23)
- Green led on pin #04 (line 24)
- Button on pin #02 (line 25)
We will need to make sure the wiring matches this setup.
1 package pi4j.gpio;
2
3 import com.pi4j.io.gpio.GpioController;
4 import com.pi4j.io.gpio.GpioFactory;
5 import com.pi4j.io.gpio.GpioPinDigitalInput;
6 import com.pi4j.io.gpio.PinPullResistance;
7 import com.pi4j.io.gpio.RaspiPin;
8 import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
9 import com.pi4j.io.gpio.event.GpioPinListenerDigital;
10
11 public class GPIOController
12 {
13 private GpioController gpio = null;
14 private OneLed yellowLed = null;
15 private OneLed greenLed = null;
16 private GpioPinDigitalInput button = null;
17 private RaspberryPIEventListener caller = null;
18
19 public GPIOController(RaspberryPIEventListener listener)
20 {
21 this.caller = listener;
22 this.gpio = GpioFactory.getInstance();
23 this.yellowLed = new OneLed(this.gpio, RaspiPin.GPIO_01, "yellow");
24 this.greenLed = new OneLed(this.gpio, RaspiPin.GPIO_04, "green");
25 this.button = this.gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN);
26 this.button.addListener(new GpioPinListenerDigital()
27 {
28 @Override
29 public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event)
30 {
31 caller.manageEvent(event);
32 }
33 });
34 }
35
36 public void shutdown()
37 {
38 this.gpio.shutdown();
39 }
40
41 public void switchYellow(boolean on)
42 {
43 if (on)
44 yellowLed.on();
45 else
46 yellowLed.off();
47 }
48
49 public void switchGreen(boolean on)
50 {
51 if (on)
52 greenLed.on();
53 else
54 greenLed.off();
55 }
56 }
- pi4j.gpio.OneLed.java
-
Utility class for led management.
1 package pi4j.gpio;
2
3
4 import com.pi4j.io.gpio.GpioController;
5 import com.pi4j.io.gpio.GpioPinDigitalOutput;
6 import com.pi4j.io.gpio.Pin;
7 import com.pi4j.io.gpio.PinState;
8
9 public class OneLed
10 {
11 private GpioPinDigitalOutput led = null;
12 private String name;
13
14 public OneLed(GpioController gpio, Pin pin, String name)
15 {
16 this.name = name;
17 led = gpio.provisionDigitalOutputPin(pin, "Led", PinState.LOW);
18 }
19
20 public void on()
21 {
22 if ("true".equals(System.getProperty("verbose", "false")))
23 System.out.println(this.name + " is on.");
24 led.high();
25 }
26
27 public void off()
28 {
29 if ("true".equals(System.getProperty("verbose", "false")))
30 System.out.println(this.name + " is off.");
31 led.low();
32 }
33 }
- pi4j.email.PIControllerMain.java
-
This is the main, the one to start from the Raspberry PI (see below)
1 package pi4j.email;
2
3 import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
4
5 import java.text.SimpleDateFormat;
6
7 import java.util.Date;
8 import java.util.List;
9
10 import org.json.JSONObject;
11
12 import pi4j.gpio.GPIOController;
13 import pi4j.gpio.RaspberryPIEventListener;
14
15 public class PIControllerMain implements RaspberryPIEventListener
16 {
17 private final static SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
18 private static boolean verbose = "true".equals(System.getProperty("verbose", "false"));
19
20 private static String providerSend = "google";
21 private static String providerReceive = "google";
22
23 EmailSender sender = null;
24
25 /**
26 * Invoked like:
27 * java pi4j.email.PIControllerMain [-verbose] -send:google -receive:yahoo -help
28 *
29 * This will send emails using google, and receive using yahoo.
30 * Default values are:
31 * java pi4j.email.PIControllerMain -send:google -receive:google
32 *
33 * Do check the file email.properties for the different values associated with email servers.
34 *
35 * @param args See above
36 */
37 public static void main(String[] args)
38 {
39 for (int i=0; i<args.length; i++)
40 {
41 if ("-verbose".equals(args[i]))
42 {
43 verbose = true;
44 System.setProperty("verbose", "true");
45 }
46 else if (args[i].startsWith("-send:"))
47 providerSend = args[i].substring("-send:".length());
48 else if (args[i].startsWith("-receive:"))
49 providerReceive =args[i].substring("-receive:".length());
50 else if ("-help".equals(args[i]))
51 {
52 System.out.println("Usage:");
53 System.out.println(" java pi4j.email.PIControllerMain -verbose -send:google -receive:yahoo -help");
54 System.exit(0);
55 }
56 }
57
58 PIControllerMain lmc = new PIControllerMain();
59 GPIOController piController = new GPIOController(lmc);
60 EmailReceiver receiver = new EmailReceiver(providerReceive); // For Google, pop must be explicitely enabled at the account level
61 try
62 {
63 System.out.println("Waiting for instructions.");
64 boolean keepLooping = true;
65 while (keepLooping)
66 {
67 List<String> received = receiver.receive();
68 if (verbose || received.size() > 0)
69 System.out.println(SDF.format(new Date()) + " - Retrieved " + received.size() + " message(s).");
70 for (String s : received)
71 {
72 // System.out.println(s);
73 String operation = "";
74 try
75 {
76 JSONObject json = new JSONObject(s);
77 operation = json.getString("operation");
78 }
79 catch (Exception ex)
80 {
81 System.err.println(ex.getMessage());
82 System.err.println("Message is [" + s + "]");
83 }
84 if ("exit".equals(operation))
85 {
86 keepLooping = false;
87 System.out.println("Will exit next batch.");
88 // break;
89 }
90 else
91 {
92 if ("turn-green-on".equals(operation))
93 {
94 System.out.println("Turning green on");
95 piController.switchGreen(true);
96 }
97 else if ("turn-green-off".equals(operation))
98 {
99 System.out.println("Turning green off");
100 piController.switchGreen(false);
101 }
102 else if ("turn-yellow-on".equals(operation))
103 {
104 System.out.println("Turning yellow on");
105 piController.switchYellow(true);
106 }
107 else if ("turn-yellow-off".equals(operation))
108 {
109 System.out.println("Turning yellow off");
110 piController.switchYellow(false);
111 }
112 try { Thread.sleep(1000L); } catch (InterruptedException ie) { ie.printStackTrace(); }
113 }
114 }
115 }
116 piController.shutdown();
117 System.out.println("Done.");
118 System.exit(0);
119 }
120 catch (Exception ex)
121 {
122 ex.printStackTrace();
123 }
124 }
125
126 public void manageEvent(GpioPinDigitalStateChangeEvent event)
127 {
128 if (sender == null)
129 sender = new EmailSender(providerSend);
130 try
131 {
132 String mess = "{ pin: '" + event.getPin() + "', state:'" + event.getState() + "' }";
133 System.out.println("Sending:" + mess);
134 sender.send(sender.getEmailDest().split(","),
135 sender.getEventSubject(),
136 mess);
137 }
138 catch (Exception ex)
139 {
140 ex.printStackTrace();
141 }
142 }
143 }
This diagram shows the name of the pins you want to use on the GPIO Connector of the Raspberry PI.
As we said before, we need to use the GPIO pins 1, 4, and 2.
Attention!:
GPIO pin 1 is the pin #12
GPIO pin 4 is the pin #16
GPIO pin 2 is the pin #13
The two leds need a 220 Ohms resistor inline between their anode (+) and the GPIO pin they're connected on.
Their cathode (-) is connected on the Ground (pin #6)
The Raspberry PI is connected to the home wireless network with the small wireless dongle you can see on the pictures below.
An ethernet cable would have done the same job.
Also notice that there is no keyboard, mouse, nor screen connected to the device.
We used ssh to connect to a Linux session, from which we started the Java program, in background.
The Raspberry PI, connected to a breadboard.
At this point, the Raspberry PI is up and running, the java program has been started:
Prompt> sudo ./run -send:google -receive:google [&]
Hint: there is an help option.
Prompt> ./run -help
Usage:
java pi4j.email.PIControllerMain -verbose -send:google -receive:yahoo -help
Prompt>
The run script looks like this:
#!/bin/bash
CP=./classes
CP=$CP:/home/pi/pi4j/pi4j-distribution/target/distro-contents/lib/pi4j-core.jar
CP=$CP:./lib/javax.mail_1.1.0.0_1-4-4.jar
CP=$CP:./lib/json.jar
#
java -classpath $CP pi4j.email.LedControllerMain $*
Notice the different components on the breadboard:
- A green led
- A yellow led
- A push button
Event on the Raspberry PI side. Button pushed.
Some event happens on the Raspberry PI's side. Someone pushed - and the released - the button.
Two emails have been sent:
from : olivier.lediouris@gmail.com
subject: PI Event
content: { pin: '"GPIO 2" <GPIO 2>', state:'HIGH' }
from : olivier.lediouris@gmail.com
subject: PI Event
content: { pin: '"GPIO 2" <GPIO 2>', state:'LOW' }
Now, you send the following email (in plain text), from your laptop, desktop, smart phone, tablet, what not:
to : olivier.lediouris@gmail.com
subject: PI Request
content: { operation: "turn-green-on" }
Green led is on.
The email is received by the Raspberry PI, the green led is turned on.
And you receive an acknowledgement, by email:
from : olivier.lediouris@gmail.com
subject: PI Robot Ack
content: Your request [{operation:"turn-green-on"}] is being taken care of.
Now you send the following email:
to : olivier.lediouris@gmail.com
subject: PI Request
content: { operation: "turn-yellow-on" }
Yellow led is on.
The email is received by the Raspberry PI, the yellow led is turned on.
And you receive an acknowledgement, by email:
from : olivier.lediouris@gmail.com
subject: PI Robot Ack
content: Your request [{operation:"turn-yellow-on"}] is being taken care of.
Now you send the following emails:
to : olivier.lediouris@gmail.com
subject: PI Request
content: { operation: "turn-yellow-off" }
to : olivier.lediouris@gmail.com
subject: PI Request
content: { operation: "turn-green-off" }
to : olivier.lediouris@gmail.com
subject: PI Request
content: { operation: "exit" }
Everything off, program terminated.
You receive all the acknowledgements, as usual.
All leds are turned off, and the program exits.
Done! Back to base.
Oliv did it