{"id":377,"date":"2009-03-07T12:24:19","date_gmt":"2009-03-07T17:24:19","guid":{"rendered":"http:\/\/www.tigoe.net\/pcomp\/code\/?p=377"},"modified":"2009-03-07T12:29:10","modified_gmt":"2009-03-07T17:29:10","slug":"rfid-to-web-interface","status":"publish","type":"post","link":"https:\/\/www.tigoe.com\/pcomp\/code\/PHP\/377\/","title":{"rendered":"RFID to Web Interface"},"content":{"rendered":"<p>This tutorial introduces a <a href=\"http:\/\/www.processing.org\">Processing<\/a> interface sketch provides a GUI for the command-line interface written into the <a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/PHP\/347\">Arduino RFID example<\/a>. You should read that tutorial first. The sketch shown here also allows you to upload tags it reads to O&#8217;Reilly&#8217;s <a href=\"http:\/\/en.oreilly.com\/et2009\/public\/content\/home\">Emerging Technology Conference<\/a> <a href=\"https:\/\/en.oreilly.com\/et2009\/user\/account\/profile\">attendee portal<\/a>, and retrieves the resulting profile. The API for this was written by Edd Dumbill. The Processing sketch retrieves RFID tags from the Arduino reader serially, then\u00a0 passes the tag via a HTTP request to a PHP script on a remote server, shown below,\u00a0 that adds an authorized login to the O&#8217;Reilly site.<\/p>\n<p>Caveat: this tutorial was written specifically for the RFID workshop at <a href=\"http:\/\/en.oreilly.com\/et2009\/public\/content\/home\">Etech 2009<\/a>.\u00a0 If you&#8217;re doing this on your own, the uploader won&#8217;t work because your tags won&#8217;t be associated with records in the O&#8217;Reilly database, and the PHP script that it calls probably won&#8217;t be active on my site anymore.\u00a0 But you could build your own version on your own server. The PHP code that follows below gives you a start on that process, and the Processing code below can make a HTTP call to any web address you give it.<\/p>\n<p>The entire sketch can be downloaded here:<\/p>\n<p><a href=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/rfid_uploader_0002.zip\">rfid_uploader_0002<\/a><\/p>\n<h2><!--more--><\/h2>\n<h2>The Processing Interface<\/h2>\n<p>Attach the Arduino-based RFID reader to your computer before you start, because this sketch interfaces with it via a USB-to-serial link.\u00a0 When you run the Processing sketch that follows, you&#8217;ll get a graphic interface that allows you to read tags, delete and print the reader&#8217;s database, and upload the tags to the O&#8217;Reilly Emerging Tech database and retrieve the user associated with the tag.<\/p>\n<p>Initially, the screen looks like Figure 1:<\/p>\n<figure id=\"attachment_372\" aria-describedby=\"caption-attachment-372\" style=\"width: 426px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-372\" style=\"border: 0pt none;\" title=\"picture-1\" src=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-1.png\" alt=\"Figure 7. The Processing sketch GUI for the SM130 reader\" width=\"426\" height=\"303\" srcset=\"https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-1.png 710w, https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-1-300x213.png 300w\" sizes=\"auto, (max-width: 426px) 100vw, 426px\" \/><\/a><figcaption id=\"caption-attachment-372\" class=\"wp-caption-text\">Figure 1. The Processing sketch GUI for the SM130 reader<\/figcaption><\/figure>\n<p>After you scan a few tags, you&#8217;ll see a list in the Tags to upload field:<\/p>\n<figure id=\"attachment_373\" aria-describedby=\"caption-attachment-373\" style=\"width: 427px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-21.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-373\" style=\"border: 0pt none;\" title=\"picture-21\" src=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-21.png\" alt=\"Figure 8. Scanning tags in the Processing GUI\" width=\"427\" height=\"309\" srcset=\"https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-21.png 712w, https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-21-300x216.png 300w\" sizes=\"auto, (max-width: 427px) 100vw, 427px\" \/><\/a><figcaption id=\"caption-attachment-373\" class=\"wp-caption-text\">Figure 2. Scanning tags in the Processing GUI<\/figcaption><\/figure>\n<p>Finally, if you click upload, the GUI will retrieve a record from the O&#8217;Reilly site, like so:<\/p>\n<figure id=\"attachment_374\" aria-describedby=\"caption-attachment-374\" style=\"width: 411px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-374\" style=\"border: 0pt none;\" title=\"picture-3\" src=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-3.png\" alt=\"picture-3\" width=\"411\" height=\"308\" srcset=\"https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-3.png 685w, https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/picture-3-300x225.png 300w\" sizes=\"auto, (max-width: 411px) 100vw, 411px\" \/><\/a><figcaption id=\"caption-attachment-374\" class=\"wp-caption-text\">Figure 3. retrieved user record<\/figcaption><\/figure>\n<h2>The Processing Code<\/h2>\n<p>Now that you&#8217;ve got a picture of the basic functionality, here&#8217;s the code. It&#8217;s divided into three tabs in the Processing sketch.\u00a0 The main tab provides functionality to communicate with the Arduino module.\u00a0 The buttons tab provides methods for making and drawing user buttons on the screen.\u00a0 It&#8217;s basically the same as the buttons tab in the RFID writer tutorial. The profiler tab provides the functions necessary to make the HTTP request to the PHP scrips below, and to parse the XML record that comes back from the request.<\/p>\n<p>You&#8217;ll need to import the serial library to access the serial port.\u00a0 In addition, there are a few global variables at the top of the main tab to do some housekeeping, like manage the text in teh screen, keep track of the tags you&#8217;ve read from the reader, and save your own tag to a file on your computer so the sketch knows who you are.<\/p>\n<pre>import processing.serial.*;\r\n\r\nSerial myPort;                \/\/ the serial port\r\nint fontHeight = 14;          \/\/ font for drawing on the screen\r\nString messageString;         \/\/ the main display string\r\nint lineCount = 0;            \/\/ count of lines in messageString\r\nint maxLineCount = 5;         \/\/ largest that lineCount can be\r\n\r\nString tagsToUpload = \"\";     \/\/ CSV string of hex-encoded RFID tags\r\n\r\nboolean identifyingSelf = false;  \/\/ whether you're scanning your own tag\r\nString myTagId = \"\";              \/\/ your tag ID<\/pre>\n<p>The setup() method initializes the serial port and the font for drawing text on the screen, makes the user interface buttons, and checks to see if there&#8217;s a file with your RFID tag saved in the sketch folder.<\/p>\n<pre>void setup() {\r\n  \/\/ set  the window size:\r\n  size(600,400);\r\n  \/\/ list all the serial ports:\r\n  println(Serial.list()); \r\n\r\n  \/\/ based on the list of serial ports printed from the\r\n  \/\/previous command, change the 0 to your port's number:\r\n  String portnum = Serial.list()[0];\r\n  \/\/ initialize the serial port:\r\n  myPort = new Serial(this, portnum, 9600);\r\n  \/\/ clear the serial buffer:\r\n  myPort.clear();\r\n  \/\/ only generate a serialEvent() when you get a newline:\r\n  myPort.bufferUntil('n');\r\n\r\n  \/\/ create a font with the second font available to the system:\r\n  PFont myFont = createFont(PFont.list()[2], fontHeight);\r\n  textFont(myFont);\r\n\r\n  \/\/ initalize the message string:\r\n  messageString = \"waiting for reader to resetn\";\r\n  \/\/ make the UI buttons:\r\n  makeButtons();\r\n\r\n  \/\/ get the user's ID if it's saved:\r\n  String[] savedData = loadStrings(\"yourID.txt\");\r\n  if (savedData != null) {\r\n    if (savedData.length &gt; 0) {\r\n      myTagId = savedData[0];\r\n    }\r\n  }\r\n}<\/pre>\n<p>The draw() method is very simple. It calls two routines to draw the user interface buttons and the user profile if one has been retrieved from the web, and draws the text on the screen to let you know what&#8217;s been communicated to and from the reader.<\/p>\n<pre>void draw() {\r\n  \/\/ clear the screen:\r\n  background(0);\r\n  \/\/ draw the UI buttons:\r\n  drawButtons();\r\n  \/\/ show the last obtained user profile:\r\n  showProfile();\r\n  \/\/ draw the message string and tags to upload:\r\n  textAlign(LEFT);\r\n  text(\"Your tag ID:\" + myTagId, 10, 30);\r\n  text(messageString, 10, 50,300, 130);\r\n  text(\"Tags to upload:\", 10, 220);\r\n  text(tagsToUpload, 10, 240,500, 130);\r\n}<\/pre>\n<p>The serialEvent() method is called automatically every time there is new serial data available. The serial library buffers the serial data until a newline character (n) is received, then it generates the serialEvent(). The method itself calls another method called parseForTag() to look for an RFID tag string in the incoming data.\u00a0 If it finds one, it checks to see if you requested that this be saved as your own tag.\u00a0 If so, it saves the tag to a file in the sketch folder. If not, it adds it to a string of received tags:<\/p>\n<pre>void serialEvent(Serial myPort) {\r\n  \/\/ read the serial buffer:\r\n  String inputString = myPort.readStringUntil('n');\r\n\r\n  \/\/ if there's something there, act:\r\n  if (inputString != null) {\r\n    \/\/ see if the newest line contains an RFID tag:\r\n    String newTag = parseForTag(inputString);\r\n\r\n    \/\/ if you got a tag, add it to the list to upload:\r\n    if (newTag != null) {\r\n      if (identifyingSelf) {\r\n        myTagId = newTag;\r\n        identifyingSelf = false;\r\n        String[] dataToSave = new String[1];\r\n        dataToSave[0] = myTagId;\r\n        saveStrings(\"yourID.txt\", dataToSave);\r\n      }\r\n      else {\r\n        \/\/ add a comma if there's already text in the string:\r\n        if (tagsToUpload != \"\") {\r\n          tagsToUpload += \",\";\r\n        }\r\n        tagsToUpload += newTag;\r\n      }\r\n    }\r\n\r\n    \/\/ display the incoming lines, 5 lines at a time:\r\n    if (lineCount &lt; maxLineCount) {\r\n      messageString +=  inputString;\r\n      lineCount++;\r\n    }\r\n    else {\r\n      messageString = inputString;\r\n      lineCount = 0;\r\n    }\r\n  }\r\n}<\/pre>\n<p>The aforementioned parseForTag() method scans each line of text received and looks for a colon.\u00a0 It assumes anything after the colon is an RFID tag string. When it finds a tag, it returns it:<\/p>\n<pre>String parseForTag(String thisString) {\r\n  String thisTag = null;\r\n  \/\/ separate the string on the colon:\r\n  String[] tagElements = split(thisString, \":\");\r\n  \/\/ if you have at least 2 elements, extract the parts:\r\n  if (tagElements.length &gt; 1) {\r\n    \/\/ get the record number:\r\n    int recordNumber = int(tagElements[0]);\r\n\r\n    \/\/ if the tag ID is not \"0000\", get it:\r\n    if (!tagElements[1].substring(0,4).equals(\"0000\")) {\r\n      thisTag = tagElements[1];\r\n      thisTag = trim(thisTag);\r\n    }\r\n  }\r\n  return thisTag;\r\n}<\/pre>\n<p>A method called buttonPressed() is called when the user releases the mouse button over one of the user interface buttons. It determines which button was pressed and takes the appropriate action:<\/p>\n<pre>void buttonPressed(RectButton thisButton) {\r\n  \/\/ get the button number from the button passed to you:\r\n  int buttonNumber = buttons.indexOf(thisButton);\r\n\r\n  \/\/ do different things depending on the button number:\r\n  switch (buttonNumber) {\r\n  case 0: \/\/ get tags from reader:\r\n    tagsToUpload = \"\";\r\n    myPort.write(\"p\");\r\n    break;\r\n  case 1:  \/\/ upload tags to net:\r\n    if (tagsToUpload.equals(\"\")) {\r\n      messageString = \"No tags to upload.\";\r\n    }\r\n    else {\r\n      String[] theseTags = split(tagsToUpload, \",\");\r\n      for (int thisTag = 0; thisTag&lt; theseTags.length; thisTag++) {\r\n        makeRequest(theseTags[thisTag]);\r\n      }\r\n\r\n      \/\/ after you upload, clear tagsToUpload:\r\n      tagsToUpload = \"\";\r\n    }\r\n    break;\r\n  case 2:   \/\/ delete tags from reader:\r\n    messageString = \"deleting reader databasen\";\r\n    myPort.write(\"c\");\r\n    break;\r\n  case 3:    \/\/ scan your own tag\r\n    identifyingSelf = true;\r\n    messageString = \"Waiting for your personal tag\";\r\n  }\r\n}<\/pre>\n<p>That&#8217;s the end of the main tab.<\/p>\n<p>The profiler tab contains the functions necessary to upload a tag to the web and retrieve the results. It starts with some global variables to store the URL of the PHP script and the results of the retrieved user record:<\/p>\n<pre>\/\/ the URL of the PHP script that passes the tag to the database:\r\nString myUrl = \"http:\/\/tigoe.net\/workshops\/etech09\/lookupTag.php?tag=\";\r\n\r\nPImage photo;        \/\/ String containing the photo URL\r\nString[] profile;    \/\/ String array containing the HTML of the profile\r\nString username;     \/\/ String of the username\r\nString affiliation;  \/\/ String of the affiliation\r\nString twitter;      \/\/ String of the twitter username\r\nString tagNumber;    \/\/ String of the user tag number\r\nString country;      \/\/ String of the country\r\n\r\nint profileX = 350;  \/\/ horizontal position of the profile\r\nint profileY = 150;  \/\/ vertical position of the profile<\/pre>\n<p>The makeRequest() method adds the RFID tag string to the end of the URL string, makes the HTTP call, and waits for the results. Then it saves the results in a file. Finally, it parses the results for a valid XML record using the parseRecord() method:<\/p>\n<pre>\/\/ This method makes the HTTP request to the PHP script\r\n\/\/ that calls the O'Reilly database and stores it\r\n\/\/ in a file:\r\nvoid makeRequest(String whichTag) {\r\n  \/\/ make HTTP call:\r\n  String thisUrl = myUrl + whichTag;\r\n  \/\/ save the resulting file in an array:\r\n  String[] httpRequest = loadStrings(thisUrl);\r\n  saveStrings(\"person.xml\", httpRequest);\r\n  \/\/ parse the results:\r\n  parseRecord(\"person.xml\");\r\n}<\/pre>\n<p>The parseRecord() method does just that: it opens the file created by the previous method and parses it for the XML data.\u00a0 Processing&#8217;s XMLElement object always reads from a file, so that&#8217;s why the two methods use a file to exchange the record. Before parsing the XML, this method checks to see that the file begins with an XML header.\u00a0 If it doesn&#8217;t, the method stops, clears the record variables and returns. It does this because the O&#8217;Reilly API sometimes returns HTTP error messages instead of XML, for example, if you give it a tag that&#8217;s not in the database.<\/p>\n<pre>void parseRecord(String filename) {\r\n  \/\/ get the first line, make sure it's an XML file.\r\n  \/\/ if not, skip the rest of the substring and return:\r\n  String firstLine = loadStrings(filename)[0];\r\n  if (!(firstLine.substring(0, 5).equals(\"&lt;?xml\"))) {\r\n    \/\/ clear the profile variables:\r\n    photo = null;\r\n    profile = null;\r\n    username = null;\r\n    affiliation= null;\r\n    twitter = null;\r\n    tagNumber = null;\r\n    country = null;\r\n    return;\r\n  }\r\n\r\n  \/\/ open the XML record:\r\n  XMLElement xml = new XMLElement(this, filename);\r\n  int lines = xml.getChildCount();\r\n  \/\/ parse the record line by line:\r\n  for (int i = 0; i &lt; lines; i++) {\r\n    XMLElement thisRecord = xml.getChild(i);\r\n    String fieldName = thisRecord.getName();\r\n    String content = thisRecord.getContent();\r\n\r\n    if (fieldName.equals(\"photo\")) {\r\n      photo = loadImage(content);\r\n    }   \r\n\r\n    if (fieldName.equals(\"profile\")) {\r\n      profile = loadStrings(content);\r\n    }    \r\n\r\n    if (fieldName.equals(\"name\")) {\r\n      username = content;\r\n    }      \r\n\r\n    if (fieldName.equals(\"affiliation\")) {\r\n      affiliation = content;\r\n    }   \r\n\r\n    if (fieldName.equals(\"twitter\")) {\r\n      twitter = content;\r\n    }\r\n    if (fieldName.equals(\"rfid\")) {\r\n      tagNumber = content;\r\n    }\r\n    if (fieldName.equals(\"country\")) {\r\n      country = content;\r\n    }\r\n  }\r\n}<\/pre>\n<p>The final method in the profiler tab, showProfile(), draws the profile information to the screen. It&#8217;s called by the draw() method:<\/p>\n<pre>void showProfile() {\r\n    \/\/ text color:\r\n  fill(0);\r\n  int  lineNumber = profileY;\r\n  textAlign(LEFT);\r\n\r\n  \/\/ show profile results if the profile variables are populated:\r\n  if (photo != null) {\r\n    image(photo, profileX, lineNumber);\r\n    lineNumber = lineNumber + 130;\r\n  }\r\n\r\n  \/\/ not displaying profile because it's all HTML and I'm too lazy to\r\n  \/\/ strip out  the bio div. It's a good goal for someone else\r\n  if (username != null) {\r\n    text(username, profileX, lineNumber);\r\n    \/\/ increment the line vertical position:\r\n    lineNumber = lineNumber + fontHeight+4;\r\n  }\r\n  if (affiliation != null) {\r\n    text(affiliation, profileX, lineNumber, width - profileX, 40);\r\n    \/\/ increment the line vertical position:\r\n    lineNumber = lineNumber + 3*(fontHeight+4);\r\n  }\r\n  if (twitter != null) {\r\n    text(twitter, profileX, lineNumber);\r\n    \/\/ increment the line vertical position:\r\n    lineNumber = lineNumber + fontHeight+4;\r\n  }\r\n  if (tagNumber != null) {\r\n    text(tagNumber, profileX, lineNumber);\r\n    \/\/ increment the line vertical position:\r\n    lineNumber = lineNumber + fontHeight+4;\r\n  }\r\n  if (country != null) {\r\n    text(country, profileX, lineNumber);\r\n    \/\/ increment the line vertical position:\r\n    lineNumber = lineNumber + fontHeight+4;\r\n  }\r\n}<\/pre>\n<p>That&#8217;s the main code for the sketch.\u00a0 The final tab in the sketch that generates the buttons. It&#8217;s based on <a href=\"http:\/\/www.processing.org\">Processing<\/a>&#8216;s buttons example (in the File menu &#8211;&gt; Examples &#8211;&gt; Topics &#8211;&gt; GUI &#8211;&gt; Buttons). For more details, see that example.<\/p>\n<p>Here&#8217;s the sketch in its entirety:<\/p>\n<p><a href=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/03\/rfid_uploader_0002.zip\">rfid_uploader_0002<\/a><\/p>\n<h2>The PHP script<\/h2>\n<p>The PHP script that the Processing sketch is pretty simple.\u00a0 It uses PHP&#8217;s cURL library to access the O&#8217;Reilly database and return the results.\u00a0 It doesn&#8217;t do any parsing, just passes the results straight back to the Processing sketch.\u00a0 It&#8217;s divided up into two files, to keep the password and username more secure. The access file looks like this:<\/p>\n<pre>&lt;?php\r\n\t$username=urlencode('you@yourserver.com'; \/\/ the email address you registered with\r\n\t$password=urlencode('l33+-h4x0r');\t  \/\/ your password\r\n?&gt;<\/pre>\n<p>The main PHP script is as follows:<\/p>\n<pre>&lt;?php\r\n\tinclude_once('access.php');\r\n\r\n\t\/\/ Where's the database:\r\n\t$url=\"https:\/\/en.oreilly.com\/event\/20\/admin\/api\/rfid\/show\/\";\r\n\r\n\t\/\/ get the tag from the call to this script:\r\n\t$url .= $_GET[\"tag\"];\r\n\r\n\t\/\/ initialize curl:\r\n\t$ch = curl_init();\r\n\t\/\/ set up the URL:\r\n\tcurl_setopt($ch, CURLOPT_URL, $url);\r\n        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);\r\n\tcurl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);\r\n\r\n\t\/\/ prepare to make a POST call:\r\n\tcurl_setopt($ch, CURLOPT_POST, 1);\r\n\t\/\/ set up authentication:\r\n\tcurl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);\r\n\tcurl_setopt($ch, CURLOPT_USERPWD, \"$username:$password\");\r\n\r\n        \/* censored line goes here  *\/\r\n\r\n\t\/\/ print the result:\r\n\tif (curl_errno($ch)) {\r\n\t\techo \"CURL Error: \" . curl_error($ch);\r\n\t} else {\r\n\t\t\/\/ Show the result\r\n\t\tvar_dump($response);\r\n\t\tcurl_close($ch);\r\n\t}\r\n?&gt;<\/pre>\n<p>You may notice a comment there that says \/*\u00a0\u00a0 censored line goes here\u00a0\u00a0 *\/.\u00a0 For reasons beyond my control, I cannot enter the curl command that goes there. It could be that <a href=\"http:\/\/www.wordpress.org\">WordPress<\/a> censors this line, or it could be that <a href=\"http:\/\/www.dreamhost.com\">dreamhost<\/a> does it. Either way, you&#8217;ll have to work out the line for yourself, but here&#8217;s a hint:<\/p>\n<pre>$response equals curl underscore exec ($ch) semicolon<\/pre>\n<p>If you want to duplicate this on your own server, you&#8217;ll need to change the URLs in the Processing sketch and the PHP script, of course, and you&#8217;ll have to make a database to replace the O&#8217;Reilly one that generates its own XML records.\u00a0 The XML records look like this:<\/p>\n<pre><span class=\"pi\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;<\/span>\r\n&lt;<span class=\"start-tag\">attendee<\/span>&gt;\r\n  &lt;<span class=\"start-tag\">photo<\/span>&gt;http:\/\/assets.en.oreilly.com\/1\/eventprovider\/1\/_@user_2071.jpg&lt;\/<span class=\"end-tag\">photo<\/span>&gt;\r\n  &lt;<span class=\"start-tag\">profile<\/span>&gt;http:\/\/en.oreilly.com\/et2009\/profile\/2071&lt;\/<span class=\"end-tag\">profile<\/span>&gt;\r\n  &lt;<span class=\"start-tag\">name<\/span>&gt;Tom Igoe&lt;\/<span class=\"end-tag\">name<\/span>&gt;\r\n  &lt;<span class=\"start-tag\">affiliation<\/span>&gt;Interactive Telecommunications Program, NYU&lt;\/<span class=\"end-tag\">affiliation<\/span>&gt;\r\n  &lt;<span class=\"start-tag\">twitter<\/span>&gt;tigoe&lt;\/<span class=\"end-tag\">twitter<\/span>&gt;\r\n  &lt;<span class=\"start-tag\">rfid<\/span>&gt;66bd00c0&lt;\/<span class=\"end-tag\">rfid<\/span>&gt;\r\n  &lt;<span class=\"start-tag\">country<\/span>&gt;US&lt;\/<span class=\"end-tag\">country<\/span>&gt;\r\n&lt;\/<span class=\"end-tag\">attendee<\/span>&gt;<\/pre>\n<p>That&#8217;s it!\u00a0 Happy tagging.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial introduces a Processing interface sketch provides a GUI for the command-line interface written into the Arduino RFID example. You should read that tutorial first. The sketch shown here also allows you to upload tags it reads to O&#8217;Reilly&#8217;s Emerging Technology Conference attendee portal, and retrieves the resulting profile. The API for this was &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.tigoe.com\/pcomp\/code\/PHP\/377\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;RFID to Web Interface&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,3,7],"tags":[50,47,48,49],"class_list":["post-377","post","type-post","status-publish","format-standard","hentry","category-arduinowiring","category-PHP","category-Processing","tag-mifare","tag-rfid","tag-sm130","tag-sonmicro"],"_links":{"self":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/377","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/comments?post=377"}],"version-history":[{"count":22,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/377\/revisions"}],"predecessor-version":[{"id":413,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/377\/revisions\/413"}],"wp:attachment":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/media?parent=377"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/categories?post=377"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/tags?post=377"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}