

{"id":7556,"date":"2017-12-14T23:31:00","date_gmt":"2017-12-15T04:31:00","guid":{"rendered":"https:\/\/rud.is\/b\/?p=7556"},"modified":"2018-03-07T16:45:02","modified_gmt":"2018-03-07T21:45:02","slug":"inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/","title":{"rendered":"Inter-operate with &#8216;MQTT&#8217; Message Brokers With R (a.k.a. Live! BBC! Subtitles!)"},"content":{"rendered":"<p>Most of us see the internet through the lens of browsers and apps on our laptops, desktops, watches, TVs and mobile devices. These displays are showing us &#8212; for the most part &#8212; content designed for human consumption. Sure, apps handle API interactions, but even most of that communication happens over ports 80 or 443. But, there are <em>lots<\/em> of ports out there; <code>0:65535<\/code>, in fact (at least TCP-wise). And, all of them have some kind of data, and most of that is still targeted to something for us.<\/p>\n<p>What if I told you the machines are also talking to <em>each other<\/em> using a thin\/efficient protocol that allows one, tiny sensor to talk to hundreds &#8212; if not <em>thousands<\/em> &#8212; of systems without even a drop of silicon-laced sweat? How can a mere, constrained sensor do that? Well, it doesn&#8217;t do it alone. Many of them share their data over a fairly new protocol dubbed <a href=\"http:\/\/mqtt.org\/\">MQTT<\/a> (Message Queuing Telemetry Transport).<\/p>\n<p>An MQTT <em>broker<\/em> watches for devices to <em>publish<\/em> data under various <a href=\"https:\/\/www.hivemq.com\/blog\/mqtt-essentials-part-5-mqtt-topics-best-practices\"><em>topics<\/em><\/a> and then also watches for other systems to <em>subscribe<\/em> to said topics and handles the rest of the interchange. The protocol is lightweight enough that fairly low-powered (CPU- and literal electric-use-wise) devices can easily send their data chunks up to a broker, and the entire protocol is robust enough to support a plethora of connections and an equal plethora of types of data.<\/p>\n<h2>Why am I telling you all this?<\/h2>\n<p>Devices that publish to MQTT brokers tend to be in the spectrum of what folks sadly call the &#8220;Internet of Things&#8221;. It&#8217;s a terrible, ambiguous name, but it&#8217;s all over the media and most folks have some idea what it means. In the context of MQTT, you can think of it as, say, a single temperature sensor publishing it&#8217;s data to an MQTT broker so many other things &#8212; including programs written by humans to capture, log and analyze that data &#8212; can receive it. This is starting to sound like something that might be right up R&#8217;s alley.<\/p>\n<p>There are also potential use-cases where an online data processing system might want to publish data to many clients without said clients having to poll a poor, single-threaded R server constantly.<\/p>\n<p>Having MQTT connectivity for R could be really interesting.<\/p>\n<p>And, now we have the beginnings of said connectivity with the <a href=\"https:\/\/github.com\/hrbrmstr\/mqtt\"><code>mqtt<\/code>? package<\/a>.<\/p>\n<h2>Another Package? Really?<\/h2>\n<p>Yes, really.<\/p>\n<p>Besides the huge potential for having a direct R-bridge to the MQTT world, I&#8217;m work-interested in MQTT since we&#8217;ve found over 35,000 of them on the default, plaintext port for MQTT (1883) alone:<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"7557\" data-permalink=\"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/mqttmap-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?fit=2797%2C1249&amp;ssl=1\" data-orig-size=\"2797,1249\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"mqttmap\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?fit=510%2C228&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?resize=510%2C228&#038;ssl=1\" alt=\"\" width=\"510\" height=\"228\" class=\"aligncenter size-full wp-image-7557\" \/><\/a><\/p>\n<p>There are enough of them that I don&#8217;t even need to show a base map.<\/p>\n<p>Some of these servers require authentication and others aren&#8217;t doing much of anything. But, there are a number of them hosted by corporations and individuals that are exposing real data. <a href=\"http:\/\/owntracks.org\/\">OwnTracks<\/a> seems to be one of the more popular self-\/badly-hosted ones.<\/p>\n<p>Then, there are others &#8212; like <code>test.mosquitto.org<\/code> &#8212; which deliberately run open MQTT servers for &#8220;testing&#8221;. There definitely is testing going on there, but there are also real services using it as a production broker. The <code>mqtt<\/code> package is based on the <a href=\"https:\/\/mosquitto.org\/documentation\/\">mosquitto C library<\/a>, so it&#8217;s only fitting that we show a few examples from its own test site here.<\/p>\n<p>For now, there&#8217;s really one function: <code>topic_subscribe()<\/code>. Eventually, R will be able to publish to a broker and do more robust data collection operations (say, to make a live MQTT dashboard in Shiny). The <code>topic_subscribe()<\/code> function is an all-in one tool that enables you to:<\/p>\n<ul>\n<li>connect to a broker<\/li>\n<li>subscribe to a topic<\/li>\n<li>pass in R callback functions which will be executed on connect, disconnect and when new messages come in<\/li>\n<\/ul>\n<p>That&#8217;s plenty of functionality to do some fun things.<\/p>\n<p>(Update: if you had tried this during the ~24 hours after the blog post was up, you may have run into an issue where the client id was not unique and got wonky results. That&#8217;s fixed, now, but it&#8217;s a good idea to use your own, unique client id when making MQTT requests).<\/p>\n<h2>What&#8217;s the <strike>frequency<\/strike>temperature, Kenneth?<\/h2>\n<p>The mosquitto test server has one topic &#8212; <code>\/outbox\/crouton-demo\/temperature<\/code> &#8212; which is a fake temperature sensor that just sends data periodically so you have something to test with. Let&#8217;s capture 50 samples and plot them.<\/p>\n<p>Since we&#8217;re using a callback we have to use the tricksy <code>&lt;&lt;-<\/code> operator to store\/update variables outside the callback function. And, we should pre-allocate space for said data to avoid needlessly growing objects. Here&#8217;s a complete code-block:<\/p>\n<pre id=\"mqtt01\"><code class=\"language-r\">library(mqtt) # devtools::install_github(&quot;hrbrmstr\/mqtt&quot;)\r\nlibrary(jsonlite)\r\nlibrary(hrbrthemes)\r\nlibrary(tidyverse)\r\n\r\ni &lt;- 0 # initialize our counter\r\nmax_recs &lt;- 50 # max number of readings to get\r\n\r\nreadings &lt;- vector(&quot;character&quot;, max_recs)\r\n\r\n# our callback function\r\ntemp_cb &lt;- function(id, topic, payload, qos, retain) {\r\n\r\n  i &lt;&lt;- i + 1 # update the counter\r\n  readings[i] &lt;&lt;- readBin(payload, &quot;character&quot;) # update our larger-scoped vector\r\n\r\n  return(if (i==max_recs) &quot;quit&quot; else &quot;go&quot;) # need to send at least &quot;&quot;. &quot;quit&quot; == done\r\n\r\n}\r\n\r\ntopic_subscribe(\r\n  topic = &quot;\/outbox\/crouton-demo\/temperature&quot;,\r\n  message_callback=temp_cb\r\n)\r\n\r\n# each reading looks like this:\r\n# {&quot;update&quot;: {&quot;labels&quot;:[4631],&quot;series&quot;:[[68]]}}\r\nmap(readings, fromJSON) %&gt;%\r\n  map(unlist) %&gt;%\r\n  map_df(as.list) %&gt;%\r\n  ggplot(aes(update.labels, update.series)) +\r\n  geom_line() +\r\n  geom_point() +\r\n  labs(x=&quot;Reading&quot;, y=&quot;Temp (F)&quot;, title=&quot;Temperature via MQTT&quot;) +\r\n  theme_ipsum_rc(grid=&quot;XY&quot;)<\/code><\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/temp.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"7560\" data-permalink=\"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/temp\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/temp.png?fit=1692%2C812&amp;ssl=1\" data-orig-size=\"1692,812\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"temp\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/temp.png?fit=510%2C245&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/temp.png?resize=510%2C245&#038;ssl=1\" alt=\"\" width=\"510\" height=\"245\" class=\"aligncenter size-full wp-image-7560\" \/><\/a><\/p>\n<p>We setup <code>temp_cb()<\/code> to be our callback and <code>topic_subscribe()<\/code> ensures that the underlying mosquitto library will call it every time a new message is published to that topic. The chart really shows how synthetic the data is.<\/p>\n<h2>Subtitles from the Edge<\/h2>\n<p>Temperature sensors are just the sort of thing that MQTT was designed for. But, we don&#8217;t need to be stodgy about our use of MQTT.<\/p>\n<p>Just about a year ago from this post, the BBC launched <a href=\"http:\/\/www.bbc.co.uk\/mediacentre\/latestnews\/2016\/BBC-launches-subtitles-for-live-channels-on-BBC-iPlayer-in-world-first\">live subtitles for iPlayer<\/a>. Residents of the Colonies may not know what iPlayer is, but it&#8217;s the &#8220;app&#8221; that lets UK citizens watch BBC programmes on glowing rectangles that aren&#8217;t proper tellys. Live subtitles are <em>hard<\/em> to produce well (and get right) and the BBC making the effort to do so also on their digital platform is quite commendable. We U.S. folks will likely be charged $0.99 for each set of digital subtitles now that net neutrality is gone.<\/p>\n<p>Now, some clever person(s) wired up some of these live subtitles to MQTT topics. We can wire up our own code in R to read them live:<\/p>\n<pre id=\"mqtt02\"><code class=\"language-r\">bbc_callback &lt;- function(id, topic, payload, qos, retain) {\r\n  cat(crayon::green(readBin(payload, &quot;character&quot;)), &quot;\\n&quot;, sep=&quot;&quot;)\r\n  return(&quot;&quot;) # ctrl-c will terminate\r\n}\r\n\r\nmqtt::topic_subscribe(topic = &quot;bbc\/subtitles\/bbc_news24\/raw&quot;,\r\n                      connection_callback=mqtt::mqtt_silent_connection_callback,\r\n                      message_callback=bbc_callback)<\/code><\/pre>\n<p>In this case, <code>control-c<\/code> terminates things (cleanly).<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqtt.gif?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"7561\" data-permalink=\"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/mqtt\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqtt.gif?fit=1410%2C856&amp;ssl=1\" data-orig-size=\"1410,856\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"mqtt\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqtt.gif?fit=510%2C310&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqtt.gif?resize=510%2C310&#038;ssl=1\" alt=\"\" width=\"510\" height=\"310\" class=\"aligncenter size-full wp-image-7561\" \/><\/a><\/p>\n<p>You could easily modify the above code to have a bot that monitors for certain keywords then sends windowed chunks of subtitled text to some other system (Slack, database, etc). Or, create an online tidy text analysis workflow from them.<\/p>\n<h2>Shiny MQTT<\/h2>\n<p>This is an update to the post. I had posited (below) the potential for future use in a Shiny context. If some missed points are acceptable, you <em>can<\/em> use this in Shiny now. Here&#8217;s code for a live viewer of the first temperature data example (above). (NOTE: I heavily <strike>borrowed<\/strike>stole from Miles\/Alicia&#8217;s cool <a href=\"https:\/\/github.com\/ropenscilabs\/webrockets\"><code>webrockets<\/code><\/a> example for this:<\/p>\n<pre id=\"mqtt03\"><code class=\"language-r\">library(shiny)\r\nlibrary(mqtt)\r\nlibrary(hrbrthemes)\r\nlibrary(tidyverse)\r\n\r\nui &lt;- fluidPage(\r\n  plotOutput(&#039;plot&#039;)\r\n)\r\n\r\nserver &lt;- function(input, output) {\r\n\r\n  get_temps &lt;- function(n) {\r\n\r\n    i &lt;- 0\r\n    max_recs &lt;- n\r\n    readings &lt;- vector(&quot;character&quot;, max_recs)\r\n\r\n    temp_cb &lt;- function(id, topic, payload, qos, retain) {\r\n      i &lt;&lt;- i + 1\r\n      readings[i] &lt;&lt;- readBin(payload, &quot;character&quot;)\r\n      return(if (i==max_recs) &quot;quit&quot; else &quot;go&quot;)\r\n    }\r\n\r\n    mqtt::topic_subscribe(topic = &quot;\/outbox\/crouton-demo\/temperature&quot;,\r\n                    connection_callback = mqtt::mqtt_silent_connection_callback,\r\n                    message_callback = temp_cb)\r\n\r\n    purrr::map(readings, jsonlite::fromJSON) %&gt;%\r\n      purrr::map(unlist) %&gt;%\r\n      purrr::map_df(as.list)\r\n\r\n  }\r\n\r\n  values &lt;- reactiveValues(x = NULL, y = NULL)\r\n\r\n  observeEvent(invalidateLater(450), {\r\n    new_response &lt;- get_temps(1)\r\n    if (length(new_response) != 0) {\r\n      values$x &lt;- c(values$x, new_response$update.labels)\r\n      values$y &lt;- c(values$y, new_response$update.series)\r\n    }\r\n  }, ignoreNULL = FALSE)\r\n\r\n  output$plot &lt;- renderPlot({\r\n    xdf &lt;- data.frame(xval = values$x, yval = values$y)\r\n    ggplot(xdf, aes(x = xval, y=yval)) + \r\n      geom_line() +\r\n      geom_point() +\r\n      theme_ipsum_rc(grid=&quot;XY&quot;)\r\n  })\r\n\r\n}\r\n\r\nshinyApp(ui = ui, server = server)<\/code><\/pre>\n<h2>FIN<\/h2>\n<p>The code is <a href=\"https:\/\/github.com\/hrbrmstr\/mqtt\">on GitHub<\/a> and all input\/contributions are welcome and encouraged. Some necessary TBDs are authentication &amp; encryption. But, how would <em>you<\/em> like the API to look for using it, say, in Shiny apps? What should publishing look like? What helper functions would be useful (ones to slice &amp; dice topic names or another to convert raw message text more safely)? Should there be an R MQTT &#8220;DSL&#8221;? Lots of things to ponder and so many sites to &#8220;test&#8221;!<\/p>\n<h2>P.S.<\/h2>\n<p>In case you are concerned about the unusually boring R package name, I wanted to use <code>RIoT<\/code> (lower-cased, of course) but <code>riot<\/code> is, alas, already taken.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Most of us see the internet through the lens of browsers and apps on our laptops, desktops, watches, TVs and mobile devices. These displays are showing us &#8212; for the most part &#8212; content designed for human consumption. Sure, apps handle API interactions, but even most of that communication happens over ports 80 or 443. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":7557,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":3,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":""},"categories":[805,91],"tags":[810],"class_list":["post-7556","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-mqtt","category-r","tag-post"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Inter-operate with &#039;MQTT&#039; Message Brokers With R (a.k.a. Live! BBC! Subtitles!) - rud.is<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Inter-operate with &#039;MQTT&#039; Message Brokers With R (a.k.a. Live! BBC! Subtitles!) - rud.is\" \/>\n<meta property=\"og:description\" content=\"Most of us see the internet through the lens of browsers and apps on our laptops, desktops, watches, TVs and mobile devices. These displays are showing us &#8212; for the most part &#8212; content designed for human consumption. Sure, apps handle API interactions, but even most of that communication happens over ports 80 or 443. [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2017-12-15T04:31:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-03-07T21:45:02+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?fit=2797%2C1249&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"2797\" \/>\n\t<meta property=\"og:image:height\" content=\"1249\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"hrbrmstr\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"hrbrmstr\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"Inter-operate with &#8216;MQTT&#8217; Message Brokers With R (a.k.a. Live! BBC! Subtitles!)\",\"datePublished\":\"2017-12-15T04:31:00+00:00\",\"dateModified\":\"2018-03-07T21:45:02+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/\"},\"wordCount\":1193,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2017\\\/12\\\/mqttmap-1.png?fit=2797%2C1249&ssl=1\",\"keywords\":[\"post\"],\"articleSection\":[\"mqtt\",\"R\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/\",\"name\":\"Inter-operate with 'MQTT' Message Brokers With R (a.k.a. Live! BBC! Subtitles!) - rud.is\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2017\\\/12\\\/mqttmap-1.png?fit=2797%2C1249&ssl=1\",\"datePublished\":\"2017-12-15T04:31:00+00:00\",\"dateModified\":\"2018-03-07T21:45:02+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2017\\\/12\\\/mqttmap-1.png?fit=2797%2C1249&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2017\\\/12\\\/mqttmap-1.png?fit=2797%2C1249&ssl=1\",\"width\":2797,\"height\":1249},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/12\\\/14\\\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/rud.is\\\/b\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Inter-operate with &#8216;MQTT&#8217; Message Brokers With R (a.k.a. Live! BBC! Subtitles!)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/\",\"name\":\"rud.is\",\"description\":\"&quot;In God we trust. All others must bring data&quot;\",\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/rud.is\\\/b\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\",\"name\":\"hrbrmstr\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"width\":460,\"height\":460,\"caption\":\"hrbrmstr\"},\"logo\":{\"@id\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\"},\"description\":\"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7\",\"sameAs\":[\"http:\\\/\\\/rud.is\"],\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/author\\\/hrbrmstr\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Inter-operate with 'MQTT' Message Brokers With R (a.k.a. Live! BBC! Subtitles!) - rud.is","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/","og_locale":"en_US","og_type":"article","og_title":"Inter-operate with 'MQTT' Message Brokers With R (a.k.a. Live! BBC! Subtitles!) - rud.is","og_description":"Most of us see the internet through the lens of browsers and apps on our laptops, desktops, watches, TVs and mobile devices. These displays are showing us &#8212; for the most part &#8212; content designed for human consumption. Sure, apps handle API interactions, but even most of that communication happens over ports 80 or 443. [&hellip;]","og_url":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/","og_site_name":"rud.is","article_published_time":"2017-12-15T04:31:00+00:00","article_modified_time":"2018-03-07T21:45:02+00:00","og_image":[{"width":2797,"height":1249,"url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?fit=2797%2C1249&ssl=1","type":"image\/png"}],"author":"hrbrmstr","twitter_card":"summary_large_image","twitter_misc":{"Written by":"hrbrmstr","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"Inter-operate with &#8216;MQTT&#8217; Message Brokers With R (a.k.a. Live! BBC! Subtitles!)","datePublished":"2017-12-15T04:31:00+00:00","dateModified":"2018-03-07T21:45:02+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/"},"wordCount":1193,"commentCount":1,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"image":{"@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?fit=2797%2C1249&ssl=1","keywords":["post"],"articleSection":["mqtt","R"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/","url":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/","name":"Inter-operate with 'MQTT' Message Brokers With R (a.k.a. Live! BBC! Subtitles!) - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/#primaryimage"},"image":{"@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?fit=2797%2C1249&ssl=1","datePublished":"2017-12-15T04:31:00+00:00","dateModified":"2018-03-07T21:45:02+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/#primaryimage","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?fit=2797%2C1249&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?fit=2797%2C1249&ssl=1","width":2797,"height":1249},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2017\/12\/14\/inter-operate-with-mqtt-message-brokers-with-r-a-k-a-live-bbc-subtitles\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"Inter-operate with &#8216;MQTT&#8217; Message Brokers With R (a.k.a. Live! BBC! Subtitles!)"}]},{"@type":"WebSite","@id":"https:\/\/rud.is\/b\/#website","url":"https:\/\/rud.is\/b\/","name":"rud.is","description":"&quot;In God we trust. All others must bring data&quot;","publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rud.is\/b\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886","name":"hrbrmstr","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","width":460,"height":460,"caption":"hrbrmstr"},"logo":{"@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1"},"description":"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7","sameAs":["http:\/\/rud.is"],"url":"https:\/\/rud.is\/b\/author\/hrbrmstr\/"}]}},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/12\/mqttmap-1.png?fit=2797%2C1249&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p23idr-1XS","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":7579,"url":"https:\/\/rud.is\/b\/2017\/12\/17\/mqtt-development-log-on-dsls-rcpp-modules-and-custom-formula-functions\/","url_meta":{"origin":7556,"position":0},"title":"mqtt Development Log : On DSLs, Rcpp Modules and Custom Formula Functions","author":"hrbrmstr","date":"2017-12-17","format":false,"excerpt":"I know some folks had a bit of fun with the previous post since it exposed the fact that I left out unique MQTT client id generation from the initial 0.1.0 release of the in-development package (client ids need to be unique). There have been some serious improvements since said\u2026","rel":"","context":"In &quot;mqtt&quot;","block_context":{"text":"mqtt","link":"https:\/\/rud.is\/b\/category\/mqtt\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1824,"url":"https:\/\/rud.is\/b\/2012\/12\/13\/the-fing-corollary\/","url_meta":{"origin":7556,"position":1},"title":"The &#8216;fing&#8217; Corollary","author":"hrbrmstr","date":"2012-12-13","format":false,"excerpt":"Back in 2011, @joshcorman posited \"HD Moore's Law\" which is basically: Casual Attacker power grows at the rate of Metasploit I am officially submitting the 'fing' corollary to said law: Fundamental defender efficacy can be ascertained within 10 'fings' The tool 'fing' : http:\/\/overlooksoft.com\/fing : is a very lightweight-yet-wicked-functional network\u2026","rel":"","context":"In &quot;Information Security&quot;","block_context":{"text":"Information Security","link":"https:\/\/rud.is\/b\/category\/information-security\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":6154,"url":"https:\/\/rud.is\/b\/2017\/08\/13\/r%e2%81%b6-exploring-macos-applications-with-codesign-gatekeeper-r\/","url_meta":{"origin":7556,"position":2},"title":"R\u2076 \u2014 Exploring macOS Applications with codesign, Gatekeeper &#038; R","author":"hrbrmstr","date":"2017-08-13","format":false,"excerpt":"(General reminder abt \"R\u2076\" posts in that they are heavy on code-examples, minimal on expository. I try to design them with 2-3 \"nuggets\" embedded for those who take the time to walk through the code examples on their systems. I'll always provide further expository if requested in a comment, so\u2026","rel":"","context":"In &quot;macOS&quot;","block_context":{"text":"macOS","link":"https:\/\/rud.is\/b\/category\/macos\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":11427,"url":"https:\/\/rud.is\/b\/2018\/08\/24\/friday-rstats-twofer-finding-macos-32-bit-apps-processing-data-from-system-commands\/","url_meta":{"origin":7556,"position":3},"title":"Friday #rstats twofer: Finding macOS 32-bit apps &#038; Processing Data from System Commands","author":"hrbrmstr","date":"2018-08-24","format":false,"excerpt":"Apple has run the death bell on 32-bit macOS apps and, if you're running a recent macOS version on your Mac (which you should so you can get security updates) you likely see this alert from time-to-time: If you're like me, you click through that and keep working but later\u2026","rel":"","context":"In &quot;Apple&quot;","block_context":{"text":"Apple","link":"https:\/\/rud.is\/b\/category\/apple\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":4772,"url":"https:\/\/rud.is\/b\/2016\/12\/22\/pipes-everywhere\/","url_meta":{"origin":7556,"position":4},"title":"Pipes (%>%) Everywhere","author":"hrbrmstr","date":"2016-12-22","format":false,"excerpt":"An R user asked a question regarding whether it's possible to have the RStudio pipe (%>%) shortcut (Cmd-Shift-M) available in other macOS applications. If you're using Alfred then you can use this workflow for said task (IIRC this requires an Alfred license which is reasonably cheap). When you add it\u2026","rel":"","context":"In &quot;Alfred&quot;","block_context":{"text":"Alfred","link":"https:\/\/rud.is\/b\/category\/alfred\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":5796,"url":"https:\/\/rud.is\/b\/2017\/04\/07\/r%e2%81%b6-rstudio-server-client-make-an-app-for-that\/","url_meta":{"origin":7556,"position":5},"title":"R\u2076 \u2014 RStudio Server Client? Make An App For That!","author":"hrbrmstr","date":"2017-04-07","format":false,"excerpt":"RStudio is a great way to work through analyses tasks, and I suspect most folks use the \"desktop\" version of the product on their local workstations. The fine folks at RStudio also make a server version (the codebase for RStudio is able to generate server or desktop and they are\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/7556","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/comments?post=7556"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/7556\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media\/7557"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=7556"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=7556"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=7556"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}