• New Feature! Feed Webhooks

    New Feature: Feed Webhooks

    What’s a webhook? According to Wikipedia:

    A webhook in web development is a method of augmenting or altering the behaviour of a web page, or web application, with custom callbacks. These callbacks may be maintained, modified, and managed by third-party users and developers who may not necessarily be affiliated with the originating website or application.

    For Adafruit IO, webhooks are unique URLs that you can use to send data to your feeds from anywhere on the internet, without having to share you IO API secret keys. They’re kind of like one-off API endpoints that you can manage separately from your security credentials and feed privacy.

    There have long been requests for “shared write access” to feeds, which can be done using the feed sharing feature already built into IO, but that requires everyone sending data to have an Adafruit IO account and use their credentials to send data. That, unfortunately, limits you from, for example, creating a simple web form to publish data directly to a feed.

    There are a few use cases we’ve come up with so far, but we hope to be surprised with what the community can come up with. Here’s two things you can try.

    One-off IFTTT Applets

    First, other web services that can publish to Webhook URLs like IFTTT’s maker webhooks can be used to directly send data to a feed without entering Adafruit credentials or signing into your Adafruit IO account through IFTTT.

    IFTTT applet that makes a web request

    We already support IFTTT directly, but we can’t support every service that exists on the web. We can work with any service that knows how to send webhook-style requests, though :D

    Public write-only connections to IO feeds

    Second, webhook URLs can be used directly in simple HTML forms, to create a deploy-anywhere application that sends data directly to your feed. For example:

    <form target="_blank" action="https://io.adafruit.com/api/v2/webhooks/feed/dQTc61soU5S4tMv8jSuSjY9uSqVz" method="post">
            Make a choice:
            <select name="value">
                <option value="YES" selected>Yes</option>
                <option value="NO">No</option>
        <button type="submit">Save my vote!</button>

    And the actual form in action:

    After clicking “Save my vote!” you should see a standard Adafruit IO data record on a new tab, which means your vote was recorded. If you see a “request failed - Throttle error” message instead, that’s because this particular webhook URL’s data rate limit of 3 events per minute has already been reached.

    By setting a very low data rate for the webhook, I can share the URL publicly without risking my account, unlike sharing my Adafruit IO Keys. Even better, if the webhook ends up flooded with data, I can just delete it from my account to shut off the stream. And because webhook URLs are write-only, I don’t need to make the feed public.

    Publicly controllable Christmas light displays? Crowd-sourced weather monitoring system? GitHub -> Discord -> Adafruit IO cross-posting webhook circle of fun? Let us know what you come up with. Join us in the forum or on Discord in the adafruit-io channel with questions, comments, or suggestions!

  • New Feature: External Service Integrations

    Adafruit IO knows the weather!

    Or, more accurately, Dark Sky knows the weather and now Adafruit IO knows how to pass it on.

    But wait, there’s more!

    Adafruit IO ❤️’s Services

    We’re excited to introduce you to Adafruit IO’s new “External Service Integration” feature. Also known as “Service Integrations”, also known as “Services”. You can find a link to the new Services page in the navigation sidebar.

    service link in the IO navigation sidebar

    The first thing you may notice if you’ve used If This Then That (IFTTT) with Adafruit IO is that we moved that service over to the new Services page.

    External Service Integrations home page

    We’ve also started building out a Zapier integration–currently in private beta–so if you prefer Zapier to IFTTT or you’d just like to keep your options open, you’ll find that on the services homepage also.

    But the star of the show is the new Dark Sky-powered weather service.

    Weather Data in Adafruit IO

    We have wanted to add weather data to Adafruit IO for a long time, and even made an attempt more than two years ago. The biggest issues we faced are that: 1) free weather data services are inconsistent or have very low API limits and 2) even paid weather services often don’t include interesting weather data.

    With Dark Sky, we were able to overcome the second problem, but the first still puts some limits on the service we’re able to offer. This means that at launch the weather service is also our first IO Plus exclusive feature.

    When you create a new weather location, you have direct access to Dark Sky’s Developer API data through Adafruit IO with some minor limits. Specifically, we’re passing sending a subset of all available forecast data (~4KB of JSON) instead of all available forecast data (~30KB of JSON), and limiting MQTT subscriptions to just one type of data at a time. For example: just the current weather, 5 minute forecast, or 1 day forecast rather than all current and forecasted data with every update.

    The Weather API is available via HTTP GET requests or MQTT subscriptions from any authenticated device. IO Plus subscribers can find full documentation for the weather service on the weather service home page.

    This is just the first iteration of the Weather API and we’re very interested in hearing your feedback. If you’re an Adafruit IO Plus subscriber, give it a try and let us know what you think.

    Random Data Service

    Also available now, and to all Adafruit IO accounts, is our brand new Random Data Service! We’ve picked a few types of data (randomly, ha!) to generate and built the system in a way that allows separate Adafruit IO accounts to receive the same data based on the seed value used.

    Once every minute, MQTT subscribers get a brand new, hand-crafted (kind of), guaranteed random value. You could build a pair of one time password devices, a color-cycling sculpture, a nonsense Tweeting robot, a dice roller / coin flipper / choose your own adventure pilot…? We don’t know! We just built the thing and hoping that you’ll find an interesting use for it.

    We wrote a Ruby library to go along with it for generating word and color values and we’re 100% open to pull requests (celebrate Hacktoberfest with us!) or feature requests if you have an idea for new kinds of data that can be randomly generated.

    We’re Just Getting Started

    We’re going to be spending a lot of our time in the coming year connecting new services directly to Adafruit IO and improving our existing Triggers system. Keep checking back and please feel encouraged to get in touch with us on the Adafruit IO forum with any questions, concerns, or bug reports.

  • Dashboard Updates: Indicator and Icon Blocks, Drag-and-Drop Images

    We’re excited to tell you about two new blocks we’ve added to Adafruit IO dashboards this week to help you build richer interfaces. Icons and Indicators, two features that have been requested a lot in the last few years.


    Icon blocks take a feed value and display the appropriate icon, when the feed value is a string selected from the collection shown here.

    click to download video

    You can use Icon blocks as live changeable visual displays by sending different values to the feed, as in the example above, or as permanent labels to improve the display of your data. Drop a text block next to an icon block on your dashboard and drop some icons into the text block to see how they look.


    Indicator blocks let you pick an ON color and an OFF color and then describe which state the Indicator block should be in based on conditions you set. The block compares the selected feed’s current value to the given conditions and chooses a color accordingly.

    indicator block settings with conditions highlighted

    You can use one condition or as many as you like. Conditions, by default, use Javascript’s parseFloat function to attempt to convert the feed’s current value and the condition values to a number for comparison. If either value, the feed or the string, can’t be converted to a number (isNaN(f_value) === true), then the condition is compared string-to-string.

    For example, I could create an indicator for a temperature sensor that stays in the ON state as long as the value is between 70 and 78.

    indicator condition in given range

    In Javascript, those conditions would be evaluated like this:

    function compare(feed_value) {
      return feed_value >= 70 && feed_value <= 78;

    Or I could create an indicator that turns on whenever my feed matches a particular value.

    indicator condition in set

    In this case, the code equivalent would be:

    function compare(feed_value) {
      return feed_value === "ALPHA" ||
          feed_value === "BETA" ||
          feed_value === "GAMMA" ||
          feed_value === "BONANZA";

    We don’t do any checking on your conditions to make sure they’re logically consistent. The conditions editor will happily let you enter impossible conditions (for example < 2 and > 2 or = 1 and = 0), so make sure to do your own testing before creating the block.

    You may notice in the block editor screenshot above that we’ve given you access the “Test Value” that’s used in the block preview. That should help in testing your conditional logic to make sure the indicator turns on and off at the times you are expecting. Set your conditions and play with the value to see when they trigger. No data is sent to IO when you change the test value, so it’s safe to play with settings on any block.

    BONUS! Drag and drop for image blocks

    It’s now possible to drag and drop images onto any Image dashboard block to automatically publish the properly formatted Base64 image data string to your feed.

    There are some important things to keep in mind when using this feature. Normal feeds are limited to 1KB of data, or about 1024 bytes, for publishing. Turning off feed history from the feed settings page allows publishing up to 100KB, or 102400 bytes, of data. Image conversion from binary to Base64 happens inside the browser, with no image pre-compression, and more importantly, conversion from binary to Base64 expands the size of the image data.

    You’ll have to do your own testing to figure out what an appropriate image size and format (png, gif, or bmp) for you are. For example, the .png image used for testing below has an on disk size of 68089 bytes, but a Base64 value of 90788 bytes, an expansion factor of about 150%, which is really close to the limit.

    sample image for upload test image

    image upload testing in block editor test publishing in block editor

    One funny artifact of the drag and drop feature is that IO doesn’t actually care if you’re using the block to publish image data. Any file that can be converted into Base64 (which is any file) can be dropped onto an image block and sent to MQTT subscribers.

    Let us know what you’re making!

    Join us in the Adafruit IO forum or on Discord in the adafruit-io channel with questions, comments, or suggestions. We love seeing what you all come up with when we add new features to Adafruit IO!

  • New Feature Launch: Feed Sharing

    New Feature Launch: Feed Sharing!

    You’ve always been able to make your feeds completely public or completely private. Private feeds are hidden from the outside world, no other user can see them and no one browsing Adafruit IO can stumble across them. Public feeds are available as a read-only data source to anyone in the world. Until now, though, there hasn’t been a way to receive data from other Adafruit IO users in your feeds and no way to share your data with just one person.

    Feed sharing introduces the ability to share a particular feed with a particular user as a read-only or read-write feed. This means you can keep a feed “private” as far as the whole world is concerned, but allow another Adafruit IO account to send data to it and read data from it.

    There are a few new features we had to add to Adafruit IO to make sharing directly with other users possible. Here’s a quick guide to sharing and how to find your way around the new parts of Adafruit IO.

    Sharing a feed

    Step 1 is to invite another account to share your feed. You can do that from any existing feed page using the new “Sharing” form.

    Sharing link in the sidebar on a full-browser feed page

    Sharing form on a full-browser feed page

    When you invite an account, the person you invite will receive a brief notification email and see the invitation on their shares page. If you share to an email address and they haven’t signed up yet, the person you shared with will have the chance to create a new Adafruit IO account.

    new user sharing invite email

    If you share with an existing Adafruit IO user via the email address on their Adafruit account or their Adafruit IO username, they’ll be able to review and approve your invitation immediately. After you’ve shared, the user you’re sharing with will get an email:

    existing user sharing invite email

    And a link to the sharing invitation review page:

    reviewing a sharing invitation from another user

    The sharing page

    This is the hub for all your sharing information. Right now you’ll see listings for feeds you are sharing with other Adafruit IO users, and feeds other Adafruit IO users are sharing with you. If you’re blocking any users from inviting you to share with you, you’ll see those accounts listed on this page too.

    sharing review page

    As we add sharing features to Adafruit IO, this will be where they show up first.

    Sharing feed writes

    Since you’re able to share feeds as read/write data streams with other registered Adafruit IO users, data rate limiting has to come into the picture. For this new feature, all data rate usage comes from the publishing user. That means when you share your feed with another user and they publish data to it, your data rate usage will remain unchanged while theirs will be affected.

    In order to support in-browser MQTT subscriptions to other users’ shared, non-public feeds, we’ve made changes to the output of our */json MQTT topics. Because these topics aren’t used in any of our libraries and aren’t highlighted in our guides, this change will have very little impact on existing MQTT subscribers. Less than 0.4% of MQTT subscriptions will be affected.

    Before, the output of a subscription to test_username/feeds/feed-a/json looked like this:

      "username": "test_username",
      "owner": {
        "id": 1,
        "username": "test_username"
      "id": 4,
      "name": "Feed B",
      "description": null,
      "history": true,
      "unit_type": null,
      "unit_symbol": null,
      "last_value": "-23.908",
      "visibility": "private",
      "license": null,
      "created_at": "2018-05-21T20:52:17Z",
      "updated_at": "2018-07-26T18:38:00Z",
      "status_notify": false,
      "status_timeout": 60,
      "enabled": true,
      "key": "feed-b",
      "groups": [
          "id": 1,
          "key": "default",
          "name": "Default",
          "user_id": 1

    That’s the same JSON record you would get if you used the HTTP API to retrieve /api/v2/test_username/feeds/feed-b, which is helpful if you want information about the feed, but kind of unhelpful if you actually want the new feed data record that prompted the MQTT message.

    After the launch of feed sharing, the same MQTT subscription output looks like this:

      "last_value": "-23.908",
      "updated_at": "2018-07-26 18:38:00 UTC",
      "key": "feed-b",
      "data": {
        "created_at": "2018-07-26T18:38:00.560Z",
        "value": "-23.908",
        "location": [
        "id": "0DY1QDB7K3VN8YDCYCAD538Z5Q"

    Because of the always-on nature of the MQTT API and the difficulty of changing topics all at once on client devices, we include the legacy last_value field in the new JSON output. If you have a client using */json MQTT topic subscriptions, you should update from json.last_value to json.data.value to access your feed’s data. After a few months of this new MQTT JSON output format, we will deprecate the last_value field and remove it from the MQTT API.

    Social web services and your safety and security

    Because Adafruit IO is an open web service, we don’t review every single feed sharing invitation before it’s sent. In order to prevent repetitive unwelcome sharing invitations from anyone, we will always give you the ability to: ignore individual invites, block a user from being able to invite you to share, or unsubscribe from all sharing invitation emails.

    When you ignore an invite, it will be cleared from your sharing page and the user who invited you won’t be able to invite you to that feed again, but they will be able to invite you to share any other feed they own.

    When you block a user, they will no longer be able to share any feeds with you at all. Users will never be explicitly informed that you have blocked them, but they may be able to infer it if they can’t share anything with you. Sharing blocks are permanent until and unless you remove them.

    Choosing to unsubscribe from sharing invitation emails will keep your inbox clean, so you’ll have to visit your sharing page to see if you have any new sharing invitations.

    Adding a social layer to Adafruit IO has always been part of our plan, but we’ll never make your shares public. If you keep every feed and do all your sharing through direct user-to-user feed sharing, your public Adafruit IO page will still exist but remain empty. We believe that your information should be private by default.

    While we do not require moderator approval for social activity on Adafruit IO, we do monitor use of the platform. If we believe a feature is being abused for any reason, we continue to reserve the right to disable the feature or limit your use of Adafruit IO. We care about building the best Internet of Things platform for makers and part of that is making sure that it continues to be a safe space for everyone who uses it.

    Guides are coming!

    We’ll be adding more information to the Adafruit IO welcome guide with most of this information and we’re always checking the Adafruit IO forums, so if you have any questions about feed sharing please stop by and ask.

    This is the first iteration of a pretty new feature for us and we’re excited to see how people use it! Join us in the forum or on Discord in the adafruit-io channel with questions, comments, or suggestions.

  • IO Updates - Python Client and Arduino Client

    Hello Adafruit IO Community,

    We have a lot to talk about this week. We’ve been focusing development on our Arduino and Python Adafruit IO client libaries in the last couple of weeks and we’re ready to share information about them.

    Adafruit IO Python Library


    We’ve officialy released version 2.0.0 of the Adafruit IO Python Client Library. This is a major update which not only adds a lot of under-the-hood enhancements, but also a bunch of new requested features. We’re going to support versions =>2.0.0 of this library going forwards. We’ve also switched this library over to Python 3, support for Python 2 has officially been dropped.

    Notable Features

    • API-V2 Support: Adafruit IO Python now uses the Adafruit IO REST API v2

    • Location Support: Sending Adafruit IO Feeds locational values is now possible from this library (lat/lon/ele). Usage example for this feature, location.py, added in examples/basics. (#48)

    • MQTT Security: The MQTT Client now establishes a secure connection with Adafruit IO by default. (#45)

      • You can unset this by defining a secure=false boolean in the client initialization: client = MQTTClient(username, key, secure=False)

      • Time Topic Subscriptions:** Want to get the current time, date, or year? We added support for time/seconds, time/milliseconds and time/ISO-8601 topic subscriptions. Usage example for this feature, time_topics.py added in examples/basics. (#54)

    • MQTT Error Handling: We added a few verbose error checks for when the mqtt_client.py encounters an error. This means error messages will be easier to understand, and your programs will be easier to troubleshoot as a result. (#44)

    • New Documentation: We gave the documentation previously on the readme some t.l.c and a facelift. Documentation for this project is available on ReadTheDocs.

    • Examples: New examples have been added to /examples/basics, including some usage examples for Adafruit CircuitPython with the Raspberry Pi (more on this soon!)

    Breaking Changes

    • Python 2 support has been discontinued. We are only supporting Python Version >=3.6.

    • Adafruit IO REST API v1 support has been discontinued. We are only supporting the API v2.

    • MQTT on_message method no longer requires the retain flag.

    We actively maintain, develop and improve this library with the support of the community. If you’d like to see an ehancement or feature to this libary, let us know by filing an issue on the GitHub repository for the IO Python Client.

    Adafruit IO Arduino Library


    We’ve also been working on the Adafruit IO Arduino Library.

    Features and Notes

    • ESP32 Compatability: We’ve added compatabilty for the Feather HUZZAH32 (and other ESP32-based-boards) to this library.

    • New Documentation: Just like the Python library, the Arduino Library now has a dedicated documentation page on ReadTheDocs

    • Time Topic Subscriptions: Don’t have any available pins to use a RTC? Just poll the Adafruit IO Server’s time feeds instead.

      • Adafruit_IO_Arduino client library updated to support three types of time helpers: time/seconds, time/milliseconds, and time/ISO-8601.
      • Example for subscribing to all three of the feed subscriptions added to examples/adafruitio_17_time_subscribe/adafruitio_17_time_subscribe.ino

    Get in touch with us on the Adafruit IO forums or ping @adam.io or @brentru on the Adafruit Discord, #adafruit-io channel if you have any questions.

  • IO Updates - Dashboard Improvements and New Ruby Client

    Hello IO community!

    In IO news this week: a few updates to IO dashboards and a final development push to bring our Ruby IO client library up to date with version 2 of the Adafruit IO API.

    Dashboard Updates

    We’ve made two changes to line charts on IO dashboards in the last couple weeks, one that will be visible and one behind the scenes.

    First, we’ve replaced the fixed legend in all line charts with one that follows your mouse cursor while you’re hovering over the chart. We think it’s a better way to show the value and location on the timeline of the data point or points you’re focusing on, and we also happen to like the style :D. You can see the new “hover legend” on all your dashboard charts now.

    Line chart with hover legend displayed

    The second, less visible change involves memory usage on long-lived IO dashboards. We’ve known for a while that we have a problem with dashboards + line charts + browsers crashing after a few hours of live streaming data, and it stinks.

    The cause is a memory leak and we haven’t solved it 100%, but we’ve improved the situation. We’re continuing to research performance and memory usage issues with dashboards. It’s difficult to balance user friendliness, beautiful interactive web interfaces, responsive soft-real time data rendering, and long lived pages. We’re going to keep improving and we hope you’ll keep joining us on the journey.

    Ruby IO Library

    We’ve officially released version 2.0.0 of the Adafruit io-client-ruby library. This version has been a long time coming and is the first client library we’ve released supports all the major endpoints for version 2 of our HTTP API. The library now also includes support for MQTT connections.

    We’re continuing work on our other libraries–including Arduino, Python, Javascript, and Go–and we welcome community contributions. All our client libraries are open source and available freely for use in your projects.

    Get in touch with us on the Adafruit IO forums or ping @adam.io on Discord if you have any questions.

  • IO Updates - Yearly Billing and MQTT get

    Hello IO community! Over the last few weeks we’ve released some changes to Adafruit IO that should be useful to everyone using the platform.

    IO+ Yearly Billing

    We’ve added the option to pay for IO+ on an annual basis at a reduced rate of $99 per year. So instead of paying $10 each month–$120 total for a year of service–you can pay $99 once and get the same year of IO+ features.

    If you’re already an IO+ subscriber (thanks for your support!) and you want to switch, you can change to yearly billing on your profile page when you’re logged in to Adafruit IO. We’ve also added an Adafruit IO+ 1 Year Subscription Pass to the Adafruit shop, so you can buy one for yourself and gift a subscription to a friend!

    Profile page with billing cycle change highlighted

    MQTT /get and the case of the missing retain flag

    MQTT is a tremendously useful protocol for building small connected devices and is relatively simple to understand and implement (if implementing networking protocols is your thing). Unfortunately, a few features of the Adafruit IO platform make it difficult for us to support the entire MQTT 3.1+ protocol specification in our broker. I’m going to talk briefly about one particular feature: the publish retain flag.

    In the MQTT protocol, setting the retain flag on a published message asks the MQTT broker (server) to store that message. Then any new clients which connect and subscribe to that topic will immediately receive the retained message. Retain makes writing basic MQTT-only Internet of Things clients easier, without it, a client that connects and subscribes to a feed topic has to wait until a new value is published on the feed to know what state it should be in. In the case of slowly updated feeds, there could be hours between updates which means a device that disconnects and reconnects (for example, due to power cycling or sleeping) might lose the current value for a long time between updates.

    Among other factors, our scale, our mix of MQTT & HTTP APIs, the speed at which we’re taking in new data, and the fact that we’re already storing almost every message that is sent mean that a “simple” feature like retain becomes difficult to support without making MQTT service performance worse for everyone.

    Since we don’t actually store data in the broker but at a lower level and can’t support PUBLISH retain directly, we’re proposing a different solution for the retaining problem: the /get topic modifier.

    The way it works is that for any given Adafruit IO MQTT feed topic (groups coming soon), subscribe to the feed topic, then add /get to the topic and publish anything to that new topic (our Arduino library uses the null character: '\0') . IO will immediately publish, just for that client, the most recent value received on the feed.

    For example, if I have a Feather HUZZAH subscribed to a counter feed: abachman/f/counter, and I want to get the latest value when I connect, I could publish to abachman/f/counter/get and immediately receive a message on abachman/f/counter with the last value that feed received.

    The feature is live on Adafruit IO and in version 2.7.3 of the Adafruit IO Arduino library which was released today. If you’re already using the library, you can add /get support to your project in one line of code.

    // ... from the adafruitio_01_subscribe example sketch
    AdafruitIO_Feed *counter = io.feed("counter");
    void setup() {
      // 1. start IO connection
      // 2. prepare MQTT subscription with handler function
      // 3. wait for successful connection
      while(io.mqttStatus() < AIO_CONNECTED) {
      // 4. send /get message, requesting last value
      counter->get(); // ask Adafruit IO to resend the last value
    // ....

    You can see the get() function in action in the example sketches in the updated Adafruit IO Arduino library.

    Platform Upgrades

    Early in the afternoon of April 18, we swapped out about 60% of the servers that are running IO and deployed an upgrade one of the primary software frameworks IO is built on (Ruby on Rails). Because framework upgrades are part of the boring, behind the scenes parts of software development and maintenance, you shouldn’t notice any change to IO except that data is processed about 4% faster on average. :D

    No data in transit was lost, but there was a period of about 5 minutes of delayed MQTT data processing. A few early bugs were caught and fixed, so there may be some devices that were sending data successfully that failed for a brief time.

    Get in touch with us on the Adafruit IO forums or ping @adam.io on Discord if you have any questions.

  • State of IO 03.21.18

    Here are the stats for the past week:

    * 97.8 million inserts of logged data in the last 7 days
    * 37,663 online feeds (140,620 feeds total)

    We’re responding to issues you may run into on our Adafruit IO Forum. Please post any issues with as much detail as you can. It definitely helps us out when fixing the bugs.

    Also, if you’re still using version 1 of our API, you may want to upgrade to the latest version 2. It has more features, and is generally better designed and easier to use than our previous API. The default for our docs is V2 now as well.

  • IO New Features - Feedback Forms and Public Pages

    Hello everyone and happy Friday! It’s been a busy few weeks and there are a couple new features at Adafruit IO we’d like to mention.

    First off, we’ve added a new feedback form directly into Adafruit IO, so you can inform us quickly about any trouble with the site or ask any questions about the Adafruit IO+ plan without having to go through the forums. We included a few options for feedback and while we will do our best to address any issues with the site or our client libraries quickly and directly via email, we aren’t able to respond to every feedback request. If you’re having trouble with your personal code or hardware projects, the Adafruit IO forum is still the best place to go for help.

    Screenshot of feedback form in Firefox

    You can find a link to the Feedback form at the bottom of the left hand sidebar on most pages.

    Second, and something I’m personally excited about, we’re introducing public pages for every user. You can see mine here. There are a few pieces of Adafruit IO you can make visible to the public as read-only data. Right now that’s Dashboards and Feeds. With the public pages, we now have a one-stop location for listing everything you have shared so you can see what’s public and you can share the link with anyone who might be interested.

    Screenshot of public pages Firefox

    Our intention isn’t to make Adafruit IO yet-another-social-media platform, but we firmly believe that things can turn out better when we work together, so we try to make that easier when we can. Stop by the forums or our Discord chat server and talk about what you’re working on!

  • December 2017 Throttle Updates

    December 2017 Throttle Updates

    MQTT Group Publish Data Rate Correction

    Hello IO friends!

    We’ve found and corrected a problem with our data rate tracking system that was allowing MQTT group publish events to be counted as a single event for the purpose of data rate monitoring instead of tracking each feed as a separate event. This means publishing to a group with five feed values was counted as 1 data point, even though we were storing 5 data points.

    The correction updates our MQTT broker to count a group message with 5 feeds as 5 data points against your accounts total available data rate.

    Free Plan Changes in 2018

    Speaking of IO+, IO Free, and permitted data rates: starting in January 2018 we will begin lowering the current allowed IO Free data rate from 60 points-per-minute to the advertised 30 points-per-minute. For the vast majority of people using Adafruit IO Free accounts, this shouldn’t be a problem, but we’ll be making the change gradually to avoid disabling a vast swathe of devices all at once.

    Each week we’ll be dropping the data rate by 5 points-per minute until it’s down to 30. That’s plenty of useable bandwidth and storage for any of the Adafruit IO projects on the Adafruit Learning System.

    Why so many data rate changes?

    Our ultimate goal with data rate monitoring and limiting is to make sure we provide a good balance of data storage and response speed across the entire Adafruit IO platform for every user whether they have a free account or an IO+ account.

    While IO+ has a higher data rate and more data storage, every message should still move through IO from publish to IO back out to subscribers at the same speed. By our measurements that speed is around 35ms on average for a round-trip from a device to IO and back out to a device. The way we keep that speed steady and available for everyone is making sure no account is able to take an unfair amount of it.

    When we make changes like this that can feel restrictive, it’s to make sure resources are shared fairly. The good news is that over a longer amount of time, improving the efficiency of Adafruit IO means we’ll be able to give more away. So, some pain now for more good stuff in the future. If or when we can find a way to double the amount of data we can process at the same cost-per-user we’re at right now, we’re probably going double the data rate for everyone!

    Just for comparison and since I was curious about the numbers, Adafruit IO Free provides a steady 30-data-points-per-second data rate which over 30 days comes out to 1296000 messages possible: 30 messages-per-minute * 60 minutes-in-an-hour * 24 hours-in-a-day * 30 days. To use a lower-level Internet of Things service provider as an example, in this case Amazon, you can achieve a much higher data rate (up to 100 messages-per-second per-client, 9000 per-second per-account), but for the same amount of data we provide for free you’d pay about $5 a month at their $5 per million messages price (retrieved December 2017). Your dashboards would also be way less pretty, but that’s another story :D

    Stop by the Adafruit IO forum or the adafruit-io room on our Discord server if you have any questions or comments. We’d love to hear what you’re making with Adafruit IO!

  • Groups, Feeds, and Proper MQTT Topics

    Groups, Feeds, and Proper MQTT Topics

    We’re deploying a fix to a subtle bug in our MQTT subscription topics today and wanted to write a quick post describing the problem and the fix for people who might currently be using workarounds. MQTT subscription behavior is going to change slightly (for the better) in a way that may break existing systems.

    Publishing to “composite” feed keys through our HTTP or MQTT APIs has worked since we introduced that feature with API version 2–that’s anything in the form of group.feed.

    You can see an example of those keys here:


    But, due to the way our internal MQTT message routing system worked, subscribing to a composite key hasn’t worked until today. Publishing to a feed at username/feeds/group_key.feed_key only sent data to subscribers that used topics that looked like username/feeds/feed_key. From this point in time forwards, however, data published to username/feeds/group_key.feed_key will always only be sent to subscribers to username/feeds/group_key.feed_key.

    We are considering this a bug fix, but it introduces some subtle effects for people who add feeds to multiple groups. Here are the three things you need to keep in mind with Adafruit IO and MQTT. The

    MQTT Feed Subscription Data Routing

    First and most critically, MQTT subscriptions to username/feeds/feed_key for all feeds that are not in your default group will stop working. Some users found that using the bare feed key worked for MQTT subscriptions, but it’s a workaround and not something we want to continue supporting now that we have a fix for it.

    Second, subscriptions to feeds that belong to multiple groups will only produce data that is published over MQTT to that group + feed combination. However, all data sent to that feed will still be shown on that feed on the Adafruit IO feed page and any dashboard blocks that use the feed, regardless of the group or groups it belongs to. A practical example of that would be a feed belonging to two groups.

    For example, in the case of a group named “Signal” belonging to the “Garage” and “Office” groups, I would end up with something that looks like this on my feeds page:


    “Signal” is a single Feed object, but shared between two different groups. If publish to one of those feed keys:

    PUBLISH abachman/feeds/garage.signal "1"

    Then only MQTT subscribers to abachman/feeds/garage.signal will see the value “1” come through. If I publish to both feed keys:

    PUBLISH abachman/feeds/garage.signal "1"
    PUBLISH abachman/feeds/office.signal "2"
    PUBLISH abachman/feeds/garage.signal "3"
    PUBLISH abachman/feeds/office.signal "4"

    Then the abachman/feeds/garage.signal subscription will only see:

    SUBSCRIBE abachman/feeds/garage.signal
    >>> "1"
    >>> "3"

    Likewise, group subscriptions will only see the messages published to that feed in the context of that group. So if instead of abachman/feeds/garage.signal I subscribed to abachman/groups/garage I would see:

    SUBSCRIBE abachman/groups/garage
    >>> {"feeds":{"signal":"1"}}
    >>> {"feeds":{"signal":"3"}}

    Over MQTT, feed subscriptions in the context of a given group will only produce messages that were published to that group + feed.

    HTTP Feed Data Requests

    Finally, all HTTP data queries for a given feed, regardless of the group context (group.feed key), will produce all data published to that feed. In the case of the example above, that means HTTP GET requests to /api/v2/abachman/feeds/garage.signal and /api/v2/abachman/feeds/office.signal will both produce the same data.

    $ export KEY='860b36ff6537fa01e9ee755be3ae18d4fake'
    $ export API_URL='https://io.adafruit.com/api/v2'
    $ curl -H "X-AIO-Key: $KEY" $API_URL/abachman/feeds/garage.signal/data.csv?limit=4
    0DQAZP2V6NZ37PA1662SG30R7G,4,30,garage.signal,2017-11-01 21:43:11 UTC,,,,,1509572591,2017-12-01T21:43:11Z
    0DQAZP1ADTNFJ990QGSZ6HG9F4,3,30,garage.signal,2017-11-01 21:43:06 UTC,,,,,1509572586,2017-12-01T21:43:06Z
    0DQAZNZSJJR9ZP5NSS1R6YV56Q,2,30,garage.signal,2017-11-01 21:43:01 UTC,,,,,1509572581,2017-12-01T21:43:01Z
    0DQAZNY8VC0FS8KMA9TZWBV77Z,1,30,garage.signal,2017-11-01 21:42:56 UTC,,,,,1509572576,2017-12-01T21:42:56Z
    $ curl -H "X-AIO-Key: $KEY" $API_URL/abachman/feeds/office.signal/data.csv?limit=4
    0DQAZP2V6NZ37PA1662SG30R7G,4,30,office.signal,2017-11-01 21:43:11 UTC,,,,,1509572591,2017-12-01T21:43:11Z
    0DQAZP1ADTNFJ990QGSZ6HG9F4,3,30,office.signal,2017-11-01 21:43:06 UTC,,,,,1509572586,2017-12-01T21:43:06Z
    0DQAZNZSJJR9ZP5NSS1R6YV56Q,2,30,office.signal,2017-11-01 21:43:01 UTC,,,,,1509572581,2017-12-01T21:43:01Z
    0DQAZNY8VC0FS8KMA9TZWBV77Z,1,30,office.signal,2017-11-01 21:42:56 UTC,,,,,1509572576,2017-12-01T21:42:56Z

    This is because although the feed belongs to two different groups, it’s still the same underlying Feed record.

    Receiving ALL Messages

    If you need to see all data published to a specific Feed, you can use the raw feed id value. You can find the corresponding MQTT topic on the “Feed Information” form associated with the Feed you want to track.

    Alternatively, every user account has a global data feed at the MQTT topic :username/dashboard/stream/create where :username is your account username. This topic produces a data record for every new data point stored:

    SUBSCRIBE abachman/dashboard/stream/create
    >>> {
      "id": "0DQBM1EPCDA0J6Z89CE1YC26D1",
      "value": "5",
      "feed_id": 30,
      "feed_key": "garage.signal",
      "created_at": "2017-11-02T16:41:32Z",
      "location": null,
      "lat": null,
      "lon": null,
      "ele": null,
      "created_epoch": 1509640892,
      "expiration": "2017-12-02T16:41:32Z"

    With Feeds + Groups, we’ve created a powerful tool for flexibly routing and storing messages over MQTT. A single feed can be used multiple ways by adding it to different groups, which can be helpful if you’re still using a feed-limited plan like IO Basic. IO Plus gives you an unlimited number of feeds, so reuse is less critical, but we expect the flexibility described to be useful in certain cases or else we wouldn’t have built it :D

    I’ve published a short GitHub Gist that includes code demonstrating the topic described in this post, you can find that here: https://gist.github.com/abachman/a04694748ad887d5aa7e644e3292fa81.

    Thank you for for joining us as we continue to extend and improve Adafruit IO. As always, stop by the Adafruit IO forum or our Discord server in the #adafruit-io room to share any questions or comments, especially when it comes to details of our MQTT support. We’d love to hear about what you’re building!

  • New MQTT topic for tracking connections

    NEW FEATURE: Tracking MQTT Client Connections

    New feature!

    We’ve added a new MQTT topic at :username/clients (where :username is replaced with your username) and a section on the IO Monitor page to track live MQTT client connections. We aren’t doing anything fancy with the data (yet!), so it’s “stateless” / streaming only for now.

    What you’ll see if you subscribe to the topic is a JSON object with the connection status, time of event (at), and an object containing information about the client. At this moment it’s only the client’s self-reported MQTT id. For example:

        // on connection
        // on disconnectiohn

    We use that bit of data on your IO monitor page to show when clients are connecting and disconnecting in real time.

    IO Monitor with /clients feed

    Using the /clients topic

    We’re not yet storing detailed client connection state, we’re just reporting on it live. So how is this useful? The first and easiest way to use the topic is just to track clients as they connect and disconnect and catch funny business before you get throttled. The feed only shows authenticated client connections, so you won’t see failed attempts, but you will be able to track any hardware, software, or browser sessions as they connect and disconnect.

    Since the only piece of identifying information that’s sent along with connection updates is the id, we can use that to record which specific clients is doing the [dis]connecting. Most MQTT clients generate a random identifier if one is not specified. So, by setting a custom client ID, we can pass some information through the system to see which device is acting up.

    For example, on my home environmental monitor, which is running on an Arduino MKR1000, I can use the Adafruit MQTT Library to manually specify the MQTT client ID I use. Using the Adafruit_MQTT_Client constructor that takes a clientid argument, my code looks like this:

    Adafruit MQTT Client with custom clientid

    Which shows up on my monitor page with the custom clientid value!

    IO monitor with custom clientid

    Choosing a client ID value

    Now, not just any client ID will do, there are a few guidelines:

    1. Stick with printable bytes, anything else won’t be helpful for tracking.
    2. Only the first 32 bytes of your clientid will be displayed, so keep the IDs at or under 32 bytes in length. The MQTT v3.1 spec requires that we allow at least 23, but lets us handle more. Internally IO can use more than 32 bytes to track clients, but only the first 32 will be published on the /clients topic.
    3. Make sure it’s unique! Only one client with the given ID can be present on the network at a time. A good pattern for creating a client ID might be: your username + a device name + something random. Then you’ll know whether it’s the lamp controller or the weather station that keeps dropping its connection.

    This is just a step towards a more complete device tracking / monitoring system, but gives a lot more insight into what’s happening on your IO account. Let us know how you’re using IO or IO+ on the forums or in our Discord chat room

  • LIVE NOW - IO Plus! The Adafruit IO Subscription Plan

  • State of IO 10.13.17

    Here are the stats for the past week:

    * 82.1 million inserts of logged data in the last 7 days
    * 30,816 online feeds (105,563 feeds total)

    We’re responding to issues you may run into on our Adafruit IO Forum. Please post any issues with as much detail as you can. It definitely helps us out when fixing the bugs.

    Also, if you’re still using version 1 of our API, you may want to upgrade to the latest version 2. It has more features, and is generally better designed and easier to use than our previous API. The default for our docs is V2 now as well.

  • COMING SOON - IO Plus! The Adafruit IO Subscription Plan

    IO Plus, The Adafruit IO Subscription Plan

    COMING SOON After a long time in beta testing mode, IO is getting a subscription plan, IO Plus! It’s been in our minds since we started this project a few years ago and “How can I get more feeds?” has been the most frequent and persistent question from people using and interested in IO, which is GREAT! The good news is that we finally have an answer for you. Say hello to IO+!

    Say hello to IO+

    Here is what’s coming (we have not decided on a date yet!):

    1. For a flat $10 per month, you can subscribe to IO+ and get unlimited feeds, unlimited dashboards, and two months of data storage.
    2. We will always continue to provide a free plan, but for new subscribers, the free plan will be limited to 5 feeds and everyone on the free plan will be limited to 30 new data points per minute.
    3. As a thank you to everyone who’s been with us this far, we’re giving away three months of IO+ free when you subscribe1. You won’t pay anything unless you keep your subscription after the third month. Additionally, if you have more than 5 feeds when we move to the new account limits, you can keep the extras2.
    4. No more “Beta” ;)

    It’s always been our goal with Adafruit IO to make the best designed Internet of Things platform for makers of all ages and skill levels. We want it to work well with the connected devices and kits we sell and we built it with an open API to make sure it can work with any device that can speak HTTP or MQTT. Additionally, as a business, we need a way to make the service self-sustaining financially, without making it inaccessible to the makers we are trying to serve.

    IO+ will provide more functionality at a single flat rate to the people who need it while our continuing free plan will let anyone build a project on IO, whether it’s their first time working with the Internet of Things or their hundredth.

    We will keep standing up for everything we’ve said before in our Internet of Things Bill of Rights, whether you’re using IO+ or IO Free. Our platform is built on open technologies and you control your clients and devices. You own your data and you will always be able to decide what is public and what is private. We want to keep building a system that is easier to use for good and harder to use maliciously. We hope you’ll join us!

    So that’s the big news, IO+ is coming in the beginning of October. If all goes as planned, it will be available Monday, October 2. Please stop by the IO Forum or our Discord chat server to ask questions or communicate with us. We’d love to hear from you.

    Other changes

    We’ll also be launching some changes to the IO interface to clean up navigation and make sure you know what’s up with your plan. Since those changes will go live with the IO+ launch, here are some screenshots to give you a preview:

    New landing page

    An updated landing page. Way more information and an attractive new design.

    New site navigation

    We’ve cleaned up the site navigation and made it easier to tell when you’re looking at Adafruit IO and not www.adafruit.com.

    New feeds page

    All Feeds and Groups are now on a single page. This should make it easier to see how Groups and Feeds are related, and also easier to manage them.

    New user profile page

    A new account profile page. This one is going to see more work in the coming months, but for now it’s the one-stop screen to see which plan you’re running and to get access to your account settings.

    Updated account data download

    The account download feature has been rebuilt to be more robust and reliable. (this feature has already launched)

    There will, of course, be design tweaks as we get closer to launch and we’re always working on the site, so small things will continue to get better.

    That’s all … for now!

    We’re still hard at work on IO and there’s lots more to come. If you’re already using Adafruit IO, thank you for continuing on this journey with us, and if you haven’t yet signed up, now is a great time :D

    1: The “IO Beta Thank You” coupon is for any user who has had an account since before September 1, 2017 and will be applied automatically at checkout.

    2: If you keep your free account after IO+ launches, we’re not going to delete your feeds, but you won’t be able to create new feeds if you already have more than 5, the IO Free plan limit. If you choose to subscribe to IO+ and then cancel, however, your feeds will be dropped back down to 5 after your subscription ends but you will have plenty of time to download all your data before that happens.

    We’ll continue to clarify details as we get closer to launching and if you have any questions please stop by the forums and get in touch.

    Just remember this is coming soon, we have not set a date yet 🙂

  • State of IO 08.10.17

    Here are the stats for the past week:

    * 81.4 million inserts of logged data in the last 7 days
    * 31,742 users
    * 27,295 online feeds (94,065 feeds total)

    We’re responding to issues you may run into on our Adafruit IO Forum. Please post any issues with as much detail as you can. It definitely helps us out when fixing the bugs.

    Also, if you’re still using version 1 of our API, you may want to upgrade to the latest version 2. It has more features, and is generally better designed and easier to use than our previous API. The default for our docs is V2 now as well.

  • State of IO 07.19.17

    Here are the stats for the past week:

    * 78.9 million inserts of logged data in the last 7 days
    * 30,780 users
    * 26300 online feeds (90,680 feeds total)

    Since the last state of io post we’ve updated our Adafruit IO Arduino client library. We’ve added a few new features to dashboards, such as customizing buttons with colors, unified throttling with our new throttle, and many fixes behind the scenes as well as issues reported on our forums (thanks!).

    We’re also responding to issues you may run into on our Adafruit IO Forum. Please post any issues with as much detail as you can. It definitely helps us out when fixing the bugs.

    Also, if you’re still using version 1 of our API, you may want to upgrade to the latest version 2. It has more features, and is generally better designed and easier to use than our previous API. The default for our docs is V2 now as well.

  • Important Client Library Update

    Note: The library has now been updated to 2.6.0 with this required change.

    There is an important update to the Adafruit IO Arduino client library that will be released tomorrow. We will perform this update as a coordinated update with the SSL certificates for io.adafruit.com. The client library contains an SSL fingerprint that checks the validity of the connection.

    You will need to download the library update, and then compile/upload to your devices once the update is released tomorrow. We will update this post once the update has been pushed.

  • State of IO 07.07.17

    Here are the stats for the past week:

    * 76.4 million inserts of logged data in the last 7 days
    * 30,188 users
    * 25607 online feeds (88,417 feeds total)

    The biggest new feature is a new download system for your data. It’s a more robust way to download your data and doesn’t make you wait for it to complete, along with a few other neat features. If you want to try it out, visit your feed or settings page to download your data.

    We’ve also updated our throttling algorithm. Please see this post for more details.

    Another update that we can talk about is that we are that we’re currently working on our Ruby and Python client libraries. Porting them to the api v2, and adding new features. If you want to play with alpha/beta code, feel free to check those out in their respective repository and api-v2 branches.

    We’re continuing to work on a few major new features, but we aren’t quite ready to talk about them yet.

    We’re also responding to issues you may run into on our Adafruit IO Forum. Please post any issues with as much detail as you can. It definitely helps us out when fixing the bugs.

    Also, if you’re still using version 1 of our API, you may want to upgrade to the latest version 2. It has more features, and is generally better designed and easier to use than our previous API. The default for our docs is V2 now as well.

  • Changes to Throttling in Adafruit IO

    We’re changing throttling in Adafruit IO for the better. We’re moving from a fixed-window, long period throttle rate that can lock out clients for up to 15 minutes in some cases to a rolling-window, short period throttle rate that can reset sooner when clients are well behaved.

    In the past, hitting our authentication or data limits could result in a lock on your account for up to 15 minutes. If you’ve ever seen the red bar at the top of your browser window while you’re working on an IoT project, that was most likely a throttle. The short explanation for that is that we were using a fixed-window throttling algorithm that resulted in message bursting when we made the window of time too small. The best solution we had at the time was to make the window longer, which resulted in the 15 minute lock-outs mentioned above.

    With our new system, very similar to the one described here, once you’re throttled on authentication or sending data, stopping sending will be guaranteed to reset your throttle in less than 1 minute. The tradeoff is that continuing to send messages at a greater-than-limit rate will cause you to remain throttled forever. Where the old system would let you back in for authentication after 15 minutes, the new system could lock you out forever if you have a large enough collection of misbehaving devices you’re unable to stop.

    To avoid being throttled, make sure you set delays on all reconnection attempts of at least 10 seconds and make sure you’re sending at most 1 message per second across all your devices and browser sessions. For example, our Arduino library delays for 60,000 milliseconds between reconnection attempts after it’s been throttled. Client libraries will let you post data as fast as you’d like, so it’s a good idea to keep a subscription to the MQTT $username/throttle topic open somewhere you can see it while you’re writing code.

    Some additional benefits of the new system going forward:

    • We can now manage throttling across the MQTT and HTTP APIs.
    • We now have a few additional variables we can tweak to make the experience of building an IoT device or application nicer. For example, we can set minimum distances between messages and scale the rate/window to smaller slices (10 messages / 10 seconds rather than 60 / 60). We’ll be keeping an eye on throttling once we’ve deployed the new system.
    • Refactoring our throttle logic lets us customize throttle rates across accounts, which will support Adafruit IO paid subscriptions in the future.

    It’s tricky to be brief, but we put a lot of thought into changes like this and we like to share. :D

    Please speak up on the forums with any questions or thoughts. We’d love to hear how you’re using IO!

  • State of IO 06.15.17

    Here are the stats for the past week:

    * 84.7 million inserts of logged data in the last 7 days
    * 29,181 users
    * 24,509 online feeds (84,764 feeds total)

    Since our last State of IO post, we’ve been mostly heads down on new features that aren’t quite ready yet for production. We’ve also made some major performance improvements to our backend that has helped with general system stability.

    We’re also responding to issues you may run into on our Adafruit IO Forum. Please post any issues with as much detail as you can. It definitely helps us out when fixing the bugs.

    Also, if you’re still using version 1 of our API, you may want to upgrade to the latest version 2. It has more features, and is generally better designed and easier to use than our previous API. The default for our docs is V2 now as well.

  • State of IO 05.16.17

    Here are the stats for the past week:

    * 80.2 million inserts of logged data in the last 7 days
    * 27,729 users
    * 23,248 online feeds (79,685 feeds total)
  • State of IO 04.25.17

    Here are the stats for the past week:

    * 81.4 million inserts of logged data in the last 7 days
    * 26,662 users
    * 22,161 online feeds (75,819 feeds total)
    * ~132 inserts per second via MQTT
    * ~10 inserts per second via REST API
  • State of IO 04.05.17

    Here are the stats for the past week:

    * 75.8 million inserts of logged data in the last 7 days
    * 25,738 users
    * 21,038 online feeds (72,237 feeds total)
    * ~120 inserts per second via MQTT
    * ~10 inserts per second via REST API
  • State of IO 03.22.17

    Here are the stats for the past week:

    * 60.7 million inserts of logged data in the last 7 days
    * 24,942 users
    * 19,888 online feeds (68,525 feeds total)
    * ~95 inserts per second via MQTT
    * ~12 inserts per second via REST API

    This past week we’ve been focusing on mostly behind the scenes functionality as we prepare to migrate data to a new backend. Most of our focus right now is on maintaining a high uptime. New features are in the works as well.

    We’re also responding to issues you may run into on our Adafruit IO Forum. Please post any issues with as much detail as you can. It definitely helps us out when fixing the bugs.

    Also, if you’re still using version 1 of our API, you may want to upgrade to the latest version 2. It has more features, and is generally better designed and easier to use than our previous API. The default for our docs is V2 now as well.

  • State of IO 02.21.17

    Here are the stats for the past week:

    * 63.5 million inserts of logged data in the last 7 days
    * 23,365 users
    * 18,096 online feeds (63,209 feeds total)
    * ~100 inserts per second via MQTT
    * ~15 inserts per second via REST API

    This past week we’ve increased the size of at least one server, and made a fairly major database migration that is the first step towards long-term stability and speed. We have more changes in the pipeline, and will make announcements here and on the forums when they are ready to go.

    We’re also responding to issues you may run into on our Adafruit IO Forum. Please post any issues with as much detail as you can. It definitely helps us out when fixing the bugs.

    Also, if you’re still using version 1 of our API, you may want to upgrade to the latest version 2. It has more features, and is generally better designed and easier to use than our previous API. The default for our docs is V2 now as well.

  • User Submitted Tutorial - Guide for using Adafruit IO with Raspberry Pi and IFTTT

    A user on a reddit post has put together a great guide on general connectivity with IO from a Raspberry Pi and IFTTT. They cover the end-to-end setup from signing up for IO, IFTTT and example sketches.

    I’ll describe the basic steps for sending data from the RPi to Adafruit.io and then getting IFTTT to take an action based on it, but you can go in the other direction too: have IFTTT post information to Adafruit.io then have the RPi take some action based on that.

    We also have a guide that explains how to setup a door sensor that triggers through IFTTT as well.

    If you would like your Adafruit IO tutorial to be featured, share it with us via Twitter (@adafruit) or Instagram (@adafruit) by using the hashtag #adafruitio.

  • State of IO 01.18.17

    Here are the stats for the past week:

    * 70.2 million inserts of logged data in the last 7 days
    * 21,682 users
    * 16,420 online feeds (57,551 feeds total)
    * ~110 inserts per second via MQTT
    * ~12 inserts per second via REST API
  • Adafruit IO User Interface Update

    We’ve deployed an all-new Adafruit IO user interface that should be faster, more responsive and streamlined than our previous UI. Beyond being faster and generally nicer to look at, another benefit of this change is it’s going to allow us to develop new features and fix existing bugs much more quickly than before. The high level changelog of the new features is below.

    This should only impact the front-end browser UI. There should be no impact to your device connectivity or API/MQTT calls.

    The UI is now directly using our API V2. It’s recommended that you also utilize the API V2 going forward. We’re working on updating our documentation and tutorials to indicate this as well. Also, if you’re using one of the many compatible devices, we highly recommend using our new client library that significantly simplifies and wraps the boilerplate needed to get a project going: https://github.com/adafruit/Adafruit_IO_Arduino

    IO Changelog (high level):

    • Updated design across the site
    • Faster, more responsive and streamlined than before
    • New charting features
    • New Dashboard layout engine
    • More granular permissions (in API V2) for your data
    • New Activity page which should be more useful than before
    • New functional sidebar in feeds page
    • New dashboard block creation experience
    • Bug fixes and performance optimizations
  • State of IO 01.10.17

    Here are the stats for the past week:

    * 70.0 million inserts of logged data in the last 7 days
    * 21,259 users
    * 16,063 online feeds (56,401 feeds total)
    * ~110 inserts per second via MQTT
    * ~12 inserts per second via REST API
  • State of IO 12.14.16

    Here are the stats for the past week:

    * 65.3 million inserts of logged data in the last 7 days
    * 19,940 users
    * 15,004 online feeds (52,527 feeds total)
    * ~100 inserts per second via MQTT
    * ~12 inserts per second via REST API
  • Quick Tip: Adding a Power Switch to your Feather

    Here’s a quick tip from @ladyada that will show you how you can use the EN (enable) pin to control the power on your Adafruit Feather with a SPDT slide switch.

    Power Switch

    Here is how to connect the switch to your Feather:

    • Feather GND -> Center pin on the switch
    • Feather EN -> One of the outer pins on the switch

    You can now turn your Feather off by flipping the switch to the side that is connected to the EN pin.

    For more info about the EN (enable) pin, check out this guide.

  • User Submitted Tutorial - Magnetic Door Spy

  • State of IO 12.06.16

    Here are the stats for the past week:

    * 63.6 million inserts of logged data in the last 7 days
    * 19,537 users
    * 14,583 online feeds (51,303 feeds total)
    * ~100 inserts per second via MQTT
    * ~10 inserts per second via REST API
  • Loading Data from Adafruit IO into Pandas


    If you are logging sensor data to Adafruit IO, you may have a need to do a deeper examination of your data. One popular option is the pandas data analysis library for Python.

    Here is a description from the pandas website:

    pandas is an open source, BSD-licensed library providing high-performance, easy-to-use data structures and data analysis tools for the Python programming language.

    Let’s take a quick look at how to load data into pandas from a public Adafruit IO feed.


    You will need Python 3.5 installed, and you will also need to install pip if it wasn’t included with your Python install.

    Once Python and pip are installed, you can install pandas by running:

    $ pip install pandas

    For this example, we will be pointing pandas at a public Adafruit IO feed. If your feed is currently private, you will need to make it public.

    Public Feed

    Importing Feed Data

    To get started, you will need to open up a new Python file in your favorite editor, and start by importing pandas:

    import pandas as pd

    Next, we need to pull in feed data via the read_json method. Replace USERNAME and FEED_KEY with your Adafruit IO username, and the key of the feed you wish to load.

    feed_data = pd.read_json('https://io.adafruit.com/api/v2/USERNAME/feeds/FEED_KEY/data')

    If you are not sure where to find your feed’s key, you can find it below the feed name.

    Feed Key

    Date Conversion

    Next, we will convert the created_at column from a string to datetime, and set it as the index for the data frame:

    feed_data['created_at'] =  pd.to_datetime(feed_data['created_at'], infer_datetime_format=True)
    feed_data = feed_data.set_index('created_at')

    Plot Values on a Chart

    Now that the data has a valid date column, we can load the feed values into a time series, and plot the values:

    values = pd.Series(feed_data['value'])

    Pandas Line

    Another simple example is to resample the data into daily averages, and plot them on a bar chart:

    daily = values.resample('1d').mean()

    Pandas Bar

    You can do a wide range of useful operations with Time Series, and you should refer to the documentation for more details.

  • State of IO 11.23.16

    Here are the stats for the past week:

    * 56.1 million inserts of logged data in the last 7 days
    * 18,941 users
    * 14,043 online feeds (49,321 feeds total)
    * ~90 inserts per second via MQTT
    * ~10 inserts per second via REST API
  • State of IO 11.07.16

    Here are the stats for the past week:

    * 54.7 million inserts of logged data in the last 7 days
    * 18,147 users
    * 13,309 online feeds (46,968 feeds total)
    * ~77 inserts per second via MQTT
    * ~10 inserts per second via REST API
  • State of IO 10.05.16

    Here are the stats for the past week:

    * 48.2 million inserts of logged data in the last 7 days
    * 16,798 users
    * 12,383 online feeds (42,857 feeds total)
    * ~75 inserts per second via MQTT
    * ~10 inserts per second via REST API
  • SSH Config Includes

    OpenSSH version 7.3 introduced a very handy Include feature, which is great for people who have to manage connection info for multiple servers. This makes it easy for us to generate updated SSH configs via AWS CLI for the multiple EC2 instances that serve Adafruit IO.

    Here is how you can use Include to pull in separate SSH config files from your main ~/.ssh/config. First, you will need to install OpenSSH version 7.3 or higher. If you are using Linux, you will need to install version 7.3+ via your package manager (yum,apt-get, etc), or build it from source.

    On OS X, you can do this via homebrew:

    $ brew install homebrew/dupes/openssh

    Confirm that you are now running 7.3 or higher by running ssh -V:

    $ ssh -V
    OpenSSH_7.3p1, OpenSSL 1.0.2j  26 Sep 2016

    Now you can create a new child config file in ~/.ssh using a text editor. For example, we can create an example child config at ~/.ssh/pi_config and add configuration info just as we would in the main SSH config file:

    Host pi-1
      User pi
      IdentityFile ~/.ssh/pi_cluster
    Host pi-2
      User pi
      IdentityFile ~/.ssh/pi_cluster
    Host pi-3
      User pi
      IdentityFile ~/.ssh/pi_cluster

    From your main ~/.ssh/config, add the following line at the top:

    Include ~/.ssh/pi_config

    You should now be able to connect to your servers as you normally would:

    $ ssh pi-1

    That’s it! Check out this OpenSSH feature request if you would like more info.

  • State of IO 09.20.16

    Here are the stats for the past week:

    * 45.3 million inserts of logged data in the last 7 days
    * 16,227 users
    * 11,985 online feeds (41,024 feeds total)
    * ~75 inserts per second via MQTT
    * ~10 inserts per second via REST API
  • Exporting Data from Adafruit IO

    Here’s a quick tip to help you export one of your Adafruit IO feeds as CSV, Excel, JSON, or XML. First, you will need to navigate to io.adafruit.com/feeds. Once your feed list has loaded, select the feed you wish to export:

    Feed Select

    Then, click the download button below the chart:

    Download Feed

    A modal will pop up and allow you to download your feed as CSV, Excel, JSON, or XML:

    Feed Format

    If you would like to download all a copy of all of your Adafruit IO data, you can do this by navigating to io.adafruit.com/settings, and clicking the Download All Data button. This button will currently only allow you to download your data in JSON format.

    Download All

    Was this tip helpful? Please visit our IO forum to ask questions or share your thoughts.

  • State of IO 09.06.16

    Here are the stats for the past week:

    * 44.40 million inserts of logged data in the last 7 days
    * 15,671 users
    * 11,503 online feeds (39,364 feeds total)
    * ~70 inserts per second via MQTT
    * ~10 inserts per second via REST API
  • Hardware Testing with Jenkins & TAP

    Jenkins CI

    At Adafruit, when we push or merge changes to one of our hundreds of Arduino libraries on GitHub, we have to ask ourselves “Does this change work?”. In a lot of cases, the best answer we can give, even after extensive manual testing, is “Maybe?”. For Adafruit IO, it is important that we are able to easily answer “Yes.” to that question. A large portion of Adafruit IO users could be impacted by a bug in a library such as the Adafruit IO Arduino Library, and we want to make sure our client code is reliable.

    The hard truth is that there aren’t enough hours in the day to test each change to every library on all of the supported platforms, so most of the time we have to settle with testing one or two platforms manually, and hoping for the best on the rest of the supported platforms.

    What do we mean by platform? In this case, we are talking about the multiple microcontrollers that are supported in the Arduino IDE via the Arduino 1.6.x Third Party Hardware Specification. Arduino Uno, ESP8266, Feather M0 (ATSAMD21), and the Feather WICED (STM32F205) are all good examples different platforms that require separate testing.

    First Attempt: Build Verification using Travis CI

    We had previously attempted automated build checking using Travis CI, and that method works great for checking if sketches build on multiple platforms.

    Travis CI

    As you may have guessed, this leaves us with a huge blind spot. A passing build does not mean the code will do what you expect it to do.

    Second Attempt: Manual Compatibility Testing

    Our next attempt involved building a ‘compatibility matrix’ web app that allowed for easy logging of the results of manual tests on supported platforms. The app pushes test results to a GitHub repo as JSON (in case we need to access it programatically). It also automatically adds/updates a compatibility table in the README of the target library.

    Compatibility Matrix

    Here’s an example of the README output:

    Compatibility README Example

    This method is very effective for answering “Does this change work?”, but it is very impractical to manually test the daily changes to libraries on every supported platform.

    Latest Attempt: Running Tests on Hardware

    Our latest approach to this problem uses Jenkins CI running on an AWS EC2 instance, and small fleet of local Raspberry Pi test nodes. Each node uploads and runs unit & integration tests on hardware attached to USB ports.


    Each Raspberry Pi can support multiple platforms, and each platform can be targeted by the test. The tests themselves output results using the TAP protocol over a serial connection, and the Raspberry Pi sends the results back to Jenkins so we are aware when builds fail.

    Here’s a visual overview of how it works:

    Jenkins Workflow

    Test status can be monitored in real time from anywhere, and we are able to view the raw console output from the test nodes when needed.

    Jenkins Stage View

    TAP results are also parsed and attached to each build:

    Jenkins TAP View

    We will be sharing the details of this in a tutorial soon, but if you would like to take a look at our early experiments with Jenkins, head to jenkins.adafruit.com or check out our Jenkins Pipeline Library on GitHub.

  • State of IO 08.23.16

    Here are the stats for the past week:

    * 37.3 million inserts of logged data in the last 7 days
    * 15,121 users
    * 11,080 online feeds (37,600 feeds total)
  • Adafruit IO Arduino v2.0 Beta Release

    We have been working hard on a new version of the Adafruit IO Arduino Library. We are releasing it in ‘beta’ form today for existing IO users to try, and we will be adding new tutorials and updating existing tutorials with usage examples very soon.

    Device Independence

    v2.0.0 of the library provides a simple device independent interface for interacting with Adafruit IO. This allows you to switch beween WiFi (ESP8266, M0 WINC1500, & WICED), Cellular (32u4 FONA), and Ethernet (Ethernet FeatherWing) with only a two line change in your sketch. No changes are required to the sketch to switch between any of the supported Feather WiFi boards.

    The included examples focus on specific concepts without extra boilerplate related to setting up the specific WiFi, cell, or ethernet hardware being used. This will allow you to prototype your sketch on WiFi hardware, and easily move to cellular or ethernet with a very small change to your config file.


    The library makes it simple to publish GPS location info with your data. For example, if you wanted to publish your location with your current speed, you would send it like this:

    car->save(speed, lat, lon, ele);

    You could then use the map block on io.adafruit.com to display your location info. The included adafruitio_04_location example demonstrates how to send and receive location info.

    Type Conversion

    The library adds type conversion helpers for both publishing and receiving data. You can publish any data type to the save(value) method of your feed, and you can use helpers like toInt(), toBool(), & toFloat() to easily convert received messages to the appropriate data type. The included adafruitio_05_type_conversion example demonstrates converting to and from all available types.

    Updating to v2.0.0

    IO Library

    The README for the library has more info about required dependencies, and you should check there to make sure you have all of the requirements for the hardware you are using. Make sure you install v2.0.0 or higher of the Adafruit IO Arduino Library, and v0.16.0 of the Adafruit MQTT Library using the Arduino IDE’s Library Manager.

    MQTT Library

  • State of IO 08.10.16

    Here are the stats for the past week:

    * 37.6 million inserts of logged data in the last 7 days
    * 14,701 users
    * 10,713 online feeds (36,320 feeds total)
    * ~60 inserts per second via MQTT
    * ~10 inserts per second via REST API
  • State of IO 07.19.16

    Here are the stats for the past week:

    * 37.3 million inserts of logged data in the last 7 days
    * 13,840 users
    * 10,138 online feeds (33,776 feeds total)
    * ~60 inserts per second via MQTT
    * ~10 inserts per second via REST API

    To help with the increased load, we have added an additional sidekiq server to help process jobs, and it has helped with ensuring that messages from users are processed as soon as they arrive. The image below shows how adding the new server has helped smooth out job processing over the last day.

    MQTT Graph

    This week Adafruit IO passed the 10,000 online feeds milestone!

    10k Online Feeds

    We have some exciting new things coming soon, and we are always looking for feedback about Adafruit IO. Please post any questions, feature requests, or show off your project in the Adafruit IO forum.

  • Naming Feeds

    There’s an old joke that in computer science, there are only two hard problems: cache invalidation, naming things, and off-by-one errors.

    It’s taken us a bit of time to get a handle on how we give things inside Adafruit IO names, but we’re making progress. Today we deployed an update to the way Feeds are identified within Adafruit IO that may have short-term negative effects, but should, in the long run, make the whole MQTT / HTTP API easier to understand, anticipate, and use.

    I’d like to talk briefly about how we identify Feeds in Adafruit IO and how the rules we’ve set up will effect your code. You can also find this guide at https://learn.adafruit.com/naming-things-in-adafruit-io.

    The Two Feed Identifiers

    Feeds have two properties that we regularly interact with when we’re talking to the Adafruit IO API: Name and Key.


    The Name is the user provided name for this Feed. It should be a “human readable” descriptive term that helps you find your Feed in the web-based user interface and keep track of which code is talking to what feed.

    The rules for Feed names are:

    • A Feed Name MUST include at least one ASCII letter.
    • A Name MAY include any upper or lower case ASCII letters, numbers, spaces, dashes, or underscores (“ “, “-“, or “_”, respectively).
    • A new Feed Name MAY NOT be the same as an existing Feed’s Key if the Feeds are in the same group. By default, all newly created Feeds are part of the Group whose name matches your username.
    • Names are case-sensitive. This means “Blender” and “BLENDER” are treated as two different Names.

    Names are helpful because they let us associate a human friendly word with our data. We see names when we browse io.adafruit.com on the web and when we get Feed records from the HTTP API. We use names when subscribing or publishing to a Feed with the MQTT API.

    Some examples of valid, possibly useful names are:

    • Temperature
    • door one
    • 99 Red Balloons
    • books_I_would_like_to_read_before_2022


    The Key is a system-generated, URL-safe identifier based on the given Feed Name that can be used in API requests to refer to a particular Feed. Keys are generated based on the Name given when the Feed is created and follows strict rules. The rules for Feed keys are simple:

    • A Feed Key MAY ONLY contain lower case ASCII letters, numbers, and the dash character (“-“).
    • Two Feeds in the same Group may not have the same Key.

    These rules in combination with the default Group all Feeds are added to means means a new Feed cannot be created if it will use a duplicate Key and a Feed’s Name cannot be modified if the new Name will produce a Key that conflicts with another Feed in any of the Feed’s Groups.

    The rules Adafruit IO uses to generate Keys from Names are roughly:

    1. Remove formatting. This step requires a lot of discrete operations, but boils down to transliterating Unicode to ASCII and replacing any non-URL safe characters with “-“.
    2. Collapse whitespace and replace with “-“.
    3. Collapse all instances of “-“ into a single “-“ and remove them from the beginning and end of the string.
    4. Make the whole thing lowercase.

    It’s also important to note that when you change a Feed’s Name the Key will also update. We keep Keys in sync with Names whenever a Feed is updated.

    Keys are handy because they let us use a human friendly URL when communicating with the AIO API. For example, https://io.adafruit.com/abachman/feeds/beta-test and abachman/f/beta-test are nicer and easier to remember than https://io.adafruit.com/abachman/feeds/588995 or abachman/f/588995.

    Aside: Naming things in MQTT

    MQTT has its own rules for naming things and in MQTT the things we’re concerned with are called “topics”. If you read Todd’s recent post on MQTT in Adafruit IO, you know we are like an MQTT broker, but we’ve got some extra guidelines. Anyhow, here are the official rules: (you don’t need to memorize these, we handle it for you. They’re just included here for illustration)

    • All Topic Names and Topic Filters MUST be at least one character long
    • Topic Names and Topic Filters are case sensitive
    • Topic Names and Topic Filters can include the space character
    • A leading or trailing ‘/’ creates a distinct Topic Name or Topic Filter
    • A Topic Name or Topic Filter consisting only of the ‘/’ character is valid
    • Topic Names and Topic Filters MUST NOT include the null character (Unicode U+0000)
    • Topic Names and Topic Filters are UTF-8 encoded strings, they MUST NOT encode to more than 65535 bytes

    Retrieved from the MQTT Version 3.1.1 OASIS Standard, July 8, 2016.

    The full MQTT topic used to describe a Feed in Adafruit IO is in the form: username/feeds/identifier where username should be replaced with the username of the account that owns the Feed and identifier should be replaced with the Name or Key that uniquely identifies the Feed you’re talking about.

    So, MQTT considers the whole topic test_username/feeds/identifier when validating names but for the purposes of describing Feeds, we’re only considering the identifier portion.

    Naming and Accessing Feeds From the io.adafruit.com MQTT API

    Naming a Feed on the fly and then referring to it reliably can be tricky. Here are the rules we’re using right now to generate new Feeds and provide continuing access to them from the MQTT interface. For the purposes of demonstration, we’ll be using the example code provided here, but any MQTT publisher or subscriber code should work the same.

    1. Listening

    Start an MQTT subscription to topic in the form username/f/identifier, for the purpose of the following examples I’ll be using, test_username/f/Test Mode. A Feed with the name “Test Mode” doesn’t exist yet, but that’s okay with the MQTT API. The subscription will remain active and start receiving whenever you start publishing to a Feed whose Name or Key matches the given identifier value exactly.

    NOTE: no new Feeds are created in this step.

    $ AIO_FEED_NAME='Test Mode' ruby adafruit-errors-sub.rb
    CONNECT TO mqtts://test_username:12345@io.adafruit.com
    SUB test_username/f/Test Mode

    We’ll also start an MQTT subscriber listening to test_username/errors. This will let us see when there are problems with publishing or subscribing to Feeds.

    $ ruby adafruit-errors-sub.rb
    CONNECT TO mqtts://test_username:12345@io.adafruit.com

    2. Initial MQTT publish / creating a new Feed

    To create the Feed in Adafruit IO and to start populating it with data, we’ll need to publish and MQTT message to the appropriate topic. In this case, we’re subscribing to a Feed named “Test Mode”, so we’ll need to publish on a Feed with the same name.

    Using the example script provided, we’ll publish a simple MQTT message with the topic test_username/f/Test Mode:

    $ AIO_FEED_NAME='Test Mode' ruby adafruit-pub.rb
    CONNECT TO mqtts://test_username:12345@io.adafruit.com
    PUBLISHING TO test_username/f/Test Mode
    PUB 2609815 to test_username/f/Test Mode at 2016-07-11 12:53:23 -0400

    If this is your first time publishing to the Feed, the subscriber that’s listing to test_username/f/Test Mode should receive its first message:

    [test_username/f/Test Mode 2016-07-11 12:53:23 -0400] 2609815

    This first is a Feed created message and the second is the actual data received message.

    3. Tweaking Names: Publish to a Feed by name with capitalization changed

    Once the Feed has been established, publishing to any named Feed whose Key is the same as an existing Feed will add Data to the existing Feeds stream.

    PUB 3124870 to test_username/f/test mode at 2016-07-11 12:39:34 -0400

    And the original Feed subscriber, which is still watching test_username/f/Test Mode, receives:

    [test_username/f/Test Mode 2016-07-11 12:39:34 -0400] 3124870

    4. Tweaking Names: Publish to a Feed by key

    Once the Feed has been established, publishing to an existing Feed’s Key will add Data to the existing Feeds stream.

    PUB 1181702 to test_username/f/test-mode at 2016-07-11 12:42:28 -0400

    The Feed subscriber, still watching test_username/f/Test Mode, receives:

    [test_username/f/Test Mode 2016-07-11 12:42:28 -0400] 1181702

    5. Valid name variations for publishing

    When publishing, the method Adafruit IO uses internally to convert a given topic in the form username/feeds/identifier to a specific, existing Feed works like this:

    1. Find the Feed belonging to username whose Key is exactly the same as identifier.
    2. If no Feed is found, convert the given identifier using the Name-to-Key translation (described above) and find the Feed belonging to username whose Key is exactly the same as the converted value.
    3. If no Feed is found, find the Feed belonging to username whose Name is exactly the same as identifier.

    Thanks to the Name-to-Key conversion rules, the following topics will all publish to the original Feed created in step 2 and be received by the subscriber at test_username/f/Test Mode:

    • test_username/f/Test_Mode
    • test_username/f/Test-Mode
    • test_username/f/Test Mode
    • test_username/f/ Test Mode
    • test_username/f/Test Mode
    • test_username/f/Test -Mode
    • test_username/f/ Test - Mode

    And so on, including any variation of modified capitalization.

    Some variations that include symbols will be converted to URL-safe Keys when looking up the requested Feed:

    • test_username/f/Test(Mode
    • test_username/f/Test\[Mode
    • test_username/f/Test{Mode
    • test_username/f/test modé
    • test_username/f/test' mode

    6. Valid name variations for subscribing

    Subscriptions, on the other hand, must use an exact Name or Key. So, for the given examples, the only topics that will produce the Feed we care about are:

    • test_username/f/Test Mode
    • test_username/f/test-mode

    Naming and Accessing Feeds From the io.adafruit.com HTTP API

    The HTTP API follows the same Feed identifying and Name-to-Key conversion rules as the MQTT API because under the hood they’re talking to the same backend. This means if you’re using the Ruby IO client library, the following will produce publications to the same feed as the MQTT examples given above.

    require 'rubygems'
    require 'adafruit/io'
    client = Adafruit::IO::Client.new(key: ENV['AIO_KEY'])
      'Test Mode',
      'test mode',
    ].each do |feed_ident|

    Potential Problems With Naming

    It really stinks to get taken by surprise in a negative way when working with code. Reducing surprise of the unpleasant sort and increasing predictability and stability are the primary motivating factors for the subtle changes this guide introduces.

    Publishing to an invalid name

    While the Name-to-Key converter keeps things feeling pretty loose and improvisational in terms of referring to Feeds once they exist, if your initial publish is to a Feed that can’t be found it will be rejected if it doesn’t match the rules for valid Feed names.

    In the case of our MQTT example, a publish that looks like this:

    PUB 2948554 to test_username/f/Test Modes[ at 2016-07-11 15:42:31 -0400

    would trigger a message on the error feed that looks like this:

    [test_username/errors 2016-07-11 15:42:31 -0400] "Validation failed: Name may contain only letters, digits, underscores, spaces, or dashes"

    If the Feed named “Test Modes” already existed, then the publish would work fine, but because it doesn’t Adafruit IO tries to create a Feed with the given identifier, “Test Modes[” as a Name. Since “Test Modes[” is an invalid name, Adafruit IO rejects it :(

    Publishing to the wrong identifier

    If you set up your MQTT subscription first, it’s important to note that no feed will be created, so the Name-to-Key rules laid out above won’t have the effect you may have anticipated. This happens when the Feed you eventually publish to doesn’t end up with the Key or Name your subscriber has requested. The end result is a subscriber that’s silent while your device is merrily publishing away. Maddening! This is a common error of subscription and publishing when trying to juggle the different identifiers that point to a given Feed.

    The safest way to avoid this situation is to make sure that your subscribing topic and your publishing topic are exactly the same. If you want to switch to a different identifier–for example, using a Key instead of a Name–copy the value directly from Adafruit IO. When in doubt, use the Name value.

    The Feed we’re publishing to in the MQTT examples above has the following identifiers:

    key:  test-mode
    name: "Test Mode"

    The Name-to-Key translator is how all the “valid name variations” shown above for publishing work, but they only after the Feed already exists. The only way to create this Feed from the MQTT interface is to publish to test_username/f/Test Mode.

    Keeping a browser open to your Feeds page while setting up or programming your Adafruit IO devices is recommended.

    Modifying a name or key

    Remember, changing a Feed’s name will automatically update its Key. This is a change to existing behavior and will require modifications to any systems you’re running that refer to Feeds by Key, but it prevents more confusing situations from occurring.

    Here’s a non-hypothetical scenario that illustrates the trouble when we don’t keep Keys and Names in sync:

    • I make a new Feed and call it, “Light Switch” (IoT light switch, low risk). In JSON, the Feed looks like:
        "name": "Light Switch",
        "key": "light-switch"
    • I have a Feather Huzzah controlling a relay, acting as a subscriber listening to username/f/light-switch and a publisher sending data to username/f/Light Switch. Things talk, everything is great with the world.
    • I move the hardware over to a new spot and rename the Feed, “Blender Toggle” (IoT blender, high risk). In a non-sync world, the Feed’s new Name is “Blender Toggle” and it’s Key is still “light-switch. The Feed is now:
        "name": "Blender Toggle",
        "key": "light-switch"
    • My subscriber is still listening to username/f/light-switch, so it still gets all the Feed’s messages.
    • I build a new remote control and have it publish to username/f/Blender Toggle and it works, because there is a Feed with that exact name. Everything just keeps working, which is okay for now.
    • Later on, I decide I’d like to build another remote control light switch, so I put together an Arduino MKR1000 publishing to username/f/Light Switch.
    • My new light switch controlling, MKR1000-powered, motion sensor publishes a message to username/f/Light Switch and my blender turns on! What the heck! Hope you’re wearing Kevlar gloves!

    The MQTT Feed routing rules described above mean that a message received on the topic username/f/Light Switch gets routed to the Feed whose Key matches light-switch, which already exists. And controls the blender. Which should not turn on unexpectedly when the room gets dark :P

    This is why we keep all Feed Keys updated to match to their respective Feed Names. In Adafruit IO, renaming the Feed to “Blender Toggle” changes the Key to “blender-toggle”.

    Old Feed:

        "name": "Light Switch",
        "key": "light-switch"

    Change Name to “Blender Toggle” and the Feed now looks like:

        "name": "Blender Toggle",
        "key": "blender-toggle"

    My existing subscriber would immediately stop working because none of the messages sent to username/f/Blender Toggle (new Name) will get routed to the subscriber listening to username/f/light-switch (old Key). This doesn’t mean the subscriber breaks or shuts down, only that it stops getting messages for now. This is my chance to realize something is wrong and debug my system.

    Here’s the tricky bit, if I go in and make a new Feed and name it “Light Switch”, it’ll get the Key “light-switch”. If I didn’t update my subscriber when it stopped working, that means it’s still listening to username/f/light-switch. When I start posting to my new Feed at username/f/Light Switch, the old subscriber at username/f/light-switch will start getting messages again.

    The best defense against confusion is to refer to the Adafruit IO web interface to double check what the Feed you’re working with has for Name and Key values. And, when you make changes in Adafruit IO always make sure the cooperating systems are updated, especially when dealing with control systems that interact with the world.


    If you got this far, I hope it’s clear that this is an area of Adafruit IO we’ve put a particular amount of thought into. Our intention continues to be building a clear, simple, powerful platform for connecting the things you build and we think this refinement supports that intention.

    Please join us at the Adafruit IO forum and share your thoughts, projects, questions, or requests. We’d love to talk to you about what we’re building!

  • Running Code at Intervals Using Adafruit IO

    We introduced time utilities to Adafruit IO about a month ago, but we haven’t provided any examples of how to use the feature. To correct this oversight, we added an example to v0.14.2 of the Adafruit MQTT Arduino Library. This example was a response to a feature request from @phlemoine in the io-issues GitHub repo:

    I am looking for a way to trigger at a specific time in the day… how can I set up the time the trigger starts ? Same for a 12 hours or even 4 hours …

    Here is the relevant code that allows code to be run at 4 hour intervals (midnight, 4am, 8am, etc):

    Adafruit_MQTT_Subscribe timefeed = Adafruit_MQTT_Subscribe(&mqtt, "time/seconds");
    // set timezone offset from UTC
    int timeZone = -4; // UTC - 4 eastern daylight time (nyc)
    int interval = 4; // trigger every X hours
    int hour = 0; // current hour
    void timecallback(uint32_t current) {
      // stash previous hour
      int previous = hour;
      // adjust to local time zone
      current += (timeZone * 60 * 60);
      // calculate current hour
      hour = (current / 60 / 60) % 24;
      // only trigger on interval
      if((hour != previous) && (hour % interval) == 0) {
        Serial.println("Run your code here");

    The full example can be found in the Adafruit_MQTT Arduino Library on GitHub. You will need to install or update the Adafruit MQTT Library to version 0.14.2 in the Arduino Library Manager, and open the adafruitio_time_esp8266 example to get started.

    Are these examples helpful? Please visit our IO forum and share your thoughts.

  • Callbacks Added to the Adafruit MQTT Library for Arduino

    v0.14.1 of the Adafruit MQTT Library for Arduino introduces subscription callbacks. This change will allow users to organize their code into separate blocks by attaching callbacks to feed and group subscriptions. Here’s a simplified example of what the change looks like:

    setup() {
      // add the rest of setup code here
      // register callback for feed
    loop() {
      // Ensure the connection to the MQTT server is alive (this will make the first
      // connection and automatically reconnect when disconnected).
      // See the MQTT_connect function in the full example for more info.
      // wait 10 seconds for subscription messages
      // since we have no other tasks in this example.
      // keep the connection alive
    void onoffcallback(char *data, uint16_t len) {
      Serial.print("Hey we're in a onoff callback, the button value is: ");

    In the example above, you can see that we added the call to mqtt.processPackets(10000);. This tells the library to wait 10 seconds (10000ms) for incoming packets before moving on to the next task, and it will block all other code execution. If your sketch is only waiting for subscription messages, then 10 seconds might be a good timeout, but if your sketch handles other tasks, you may want to reduce the timeout to 1 second (1000ms).

    The full example with multiple feed subscriptions can be found in the Adafruit_MQTT Arduino Library on GitHub. You will need to install or update the Adafruit MQTT Library to version 0.14.1 in the Arduino Library Manager, and open the mqtt_esp8266_callback example to get started.

    Are these examples helpful? Please visit our IO forum and share your thoughts.

  • MQTT Error Reporting

    Unlike HTTP, the MQTT protocol does not provide a standard way of reporting errors to connected clients. This poses a problem for Adafruit IO, because there are multiple reasons why sending data to Adafruit IO might fail.

    Here are a few common examples:

    • Publishing data to an invalid topic
    • Publishing data to an unauthorized topic
    • Publishing data too fast (rate limit)
    • Exceeding the number of feeds for your account (10 currently)
    • Sending too large of a payload

    Adafruit IO is not a standard MQTT broker. Normally MQTT brokers will rebroadcast published data to any authorized subscribed client as soon as the data is received, so errors are rarely encountered.

    The standard MQTT pub/sub workflow looks something like this:

    standard mqtt flow

    Adafruit IO’s message flow is a bit more complicated, and looks something like this:

    adafruit io mqtt flow

    In the simplified example above, you can see that there are multiple steps that need to be completed before data is rebroadcasted to subscribed clients. If any of these steps fail, data will not make it back to subscribed clients. The reasons for failure are often unclear to users, so we added two special MQTT topics that will help inform users of any issues related to publishing data.

    The first topic you can subscribe to is the error topic for your user. This topic will receive any errors related to data validation and database saves. The topic path looks like this:


    For example, if your username was ladyada, you would subscribe to the following topic using your favorite MQTT client:


    The second topic you can subscribe to is the throttle topic for your user. This topic contains any messages related to rate limits on your account. You might see these if you are publishing too fast. The topic path looks like this:


    Again, if your username was ladyada, you would subscribe to the following topic:


    If you are using the Adafruit MQTT Library, you can define the throttle and error subscriptions at the top of your sketch like this:

    /*************************** Error Reporting *********************************/
    const char ERRORS[] PROGMEM = AIO_USERNAME "/errors";
    Adafruit_MQTT_Subscribe errors = Adafruit_MQTT_Subscribe(&mqtt, ERRORS);
    const char THROTTLE[] PROGMEM = AIO_USERNAME "/throttle";
    Adafruit_MQTT_Subscribe throttle = Adafruit_MQTT_Subscribe(&mqtt, THROTTLE);

    Then, subscribe to the topics at the bottom of the setup function:

    void setup() {
      // ...network connection setup code here
      // MQTT subscriptions for throttle & error messages

    Finally, inside of the main loop, print any errors to the serial monitor:

    void loop() {
      // Ensure the connection to the MQTT server is alive (this will make the first
      // connection and automatically reconnect when disconnected).  See the MQTT_connect
      // function definition further below.
      // this is our 'wait for incoming subscription packets' busy subloop
      // try to spend your time here
      Adafruit_MQTT_Subscribe *subscription;
      while ((subscription = mqtt.readSubscription(5000))) {
        if(subscription == &errors) {
          Serial.print(F("ERROR: "));
          Serial.println((char *)errors.lastread);
        } else if(subscription == &throttle) {
          Serial.print(F("THROTTLED: "));
          Serial.println((char *)throttle.lastread);

    You can see the full example for the ESP8266 in the Adafruit_MQTT Arduino Library on GitHub. Install or update the Adafruit MQTT Library to version 0.13.3 in the Arduino Library Manager, and open the adafruitio_errors_esp8266 example to get started.

    Are these examples helpful? Please visit our IO forum and share your thoughts.

  • IoT Security: Connecting Your ESP8266 to Adafruit IO with SSL/TLS

    The ESP8266 based Adafruit HUZZAH breakout and the Adafruit Feather HUZZAH are both popular options to use with Adafruit IO. Because ESP8266 SSL/TLS support is fairly new, most of our Adafruit IO examples use the insecure MQTT port 1883.

    Why is this a problem? The MQTT protocol is an insecure protocol on it’s own. All data (including username & password) are sent in the clear, so SSL/TLS is required to protect any sensitive information.

    What are SSL & TLS? Transport Layer Security (TLS) and its predecessor, Secure Sockets Layer (SSL), are cryptographic protocols that you use whenever you browse the internet. Have you ever noticed the lock symbol 🔒 in your browser’s URL bar? That lock symbol represents a secure connection between your browser & a web site over SSL/TLS. We use those same protocols to secure traffic between your ESP8266 and Adafruit IO.

    We have added an example to the Adafruit_MQTT Arduino Library that you can use to secure communication between your ESP8266 and Adafruit IO. Install or update the Adafruit MQTT Library to version 0.13.2 in the Arduino Library Manager, and open the adafruitio_secure_esp8266 example to get started.


    The main changes to the standard ESP8266 example are that WiFiClientSecure is used in place of WiFiClient, and port 8883 is used instead of MQTT port 1883. The sketch also checks the fingerprint for the io.adafruit.com certificate using the verifyFingerprint function.

    A simplified summary of the changes can be seen below:

    #define AIO_SERVER      "io.adafruit.com"
    #define AIO_SERVERPORT  8883                   // 8883 for MQTTS
    // WiFiFlientSecure for SSL/TLS support
    WiFiClientSecure client;
    // io.adafruit.com SHA1 fingerprint
    const char* fingerprint = "26 96 1C 2A 51 07 FD 15 80 96 93 AE F7 32 CE B9 0D 01 55 C4";
    void verifyFingerprint() {
      const char* host = AIO_SERVER;
      Serial.print("Connecting to ");
      if (! client.connect(host, AIO_SERVERPORT)) {
        Serial.println("Connection failed. Halting execution.");
      if (client.verify(fingerprint, host)) {
        Serial.println("Connection secure.");
      } else {
        Serial.println("Connection insecure! Halting execution.");
  • From the Forums: Two Buttons & Two LEDs

    User smcculley posted a useful example in the IO Forum:

    I have had some requests from people to share my code to talk to Adafruit IO using MQTT and being able to trigger two LED’s.

    Note that I am using the latest AdafruitIO MQTT code from GitHub, as it has the latest fixes available: https://github.com/adafruit/Adafruit_MQTT_Library

    In Adafruit IO, I created two feeds, called ledone and ledtwo, and added them to a group called leds. I then created a dashboard with two toggle switches, and tied them to the feeds (one to each, obviously) using the default ON and OFF button text.

    Check out the post for more details. Thanks for sharing!

  • Extending the MQTT Protocol

    Last month we deployed a change to Adafruit IO’s MQTT broker that allowed us to rate limit connection attempts. Although we don’t like to throttle or ban users, the change was necessary to protect Adafruit IO from abuse, and ensure the overall health of the service.

    This presented a problem: How do we inform users when they have been throttled or banned? Ideally the MQTT protocol would allow for us to inform the user using a standard response, but currently the connection acknowledgement packet (CONNACK) has a limited set of response codes.

    The MQTT v3.1.1 protocol has the following values defined for the CONNACK packet response code:


    Return Code Response



    0x00 Connection Accepted

    Connection accepted


    0x01 Connection Refused, unacceptable protocol version

    The Server does not support the level of the MQTT protocol requested by the Client


    0x02 Connection Refused, identifier rejected

    The Client identifier is correct UTF-8 but not allowed by the Server


    0x03 Connection Refused, Server unavailable

    The Network Connection has been made but the MQTT service is unavailable


    0x04 Connection Refused, bad user name or password

    The data in the user name or password is malformed


    0x05 Connection Refused, not authorized

    The Client is not authorized to connect



    Reserved for future use

    The current set of codes didn’t allow us to clearly communicate the reason for disconnects to our users. We have extended the list of codes in the CONNACK packet to include connection throttle (0x06) and ban (0x07).


    Return Code Response



    0x06 Connection Refused, throttled

    Client has exceeded connection rate limit. Please try again later.


    0x07 Connection Refused, banned

    The client has been banned by the server administrator.

    We have submitted these two new codes to the OASIS MQTT Technical Committee for comment, and we are adding support to our MQTT client libraries. If you would like to comment on these changes, please visit our IO forum and share your thoughts.

  • Using MQTT Last Will with Adafruit IO

    MQTT’s last will feature allows you to ask the Adafruit IO servers to publish a message to a feed or group on your behalf. This is helpful if you would like to track when your device unexpectedly disconnects due to issues like network or power outages.

    Here are some helpful tips from the IO forum that might help you if you are looking to use MQTT’s last will feature with Adafruit IO:

    • The last will topic must match the normal IO MQTT topic format for feeds or group publishes.
    • Last will is only published by the MQTT broker if the client fails to disconnect cleanly by sending the MQTT disconnect packet.
    • Last will is only published by the MQTT broker if the the keep alive timeout expires, and the last will is not sent if your device reconnects within the timeout window. The Adafruit MQTT Library for Arduino has a default keep alive timeout of 5 minutes.

    Here’s an example of setting a last will message using the Adafruit MQTT Library for Arduino:

    // always set the last will message before calling connect.
    // if the device unexpectedly disconnects, the 'disconnect'
    // feed will receive the 'water monitor disconnected' message.
    mqtt.will("your_username_here/feeds/disconnect", "water monitor disconnected");
  • State of IO 6.14.16

    We’re continuing forward with refactoring our UI so that we can get to a point where it’s easier and quicker to build out new features. The front-end is also going to use the same API V2 that will be the future default API. As another reminder, it would be a good idea to explicitly set ‘/api/v1’ in your paths until you’re ready to upgrade to the ‘/api/v2’.

    Stability of the entire system has been an ongoing project for us. We’re getting there, and continue to add more monitoring and fixes to reduce any future downtime.

    Also, we’re updating our client libraries with new features and bug fixes. If you haven’t tried out the Go client library, now is a good time! If you have any suggestions for our libraries, please let us know in the forums.

    Here are the stats for the past week:

    * 35.6 million inserts of logged data in the last 7 days
    * 12578 users
    * 8,900 online feeds (29554 feeds total)
  • Postmortem 06.07.16


    We had a brief outage this morning due to a disk space issue on our Sidekiq EC2 instance. One set of log files grew to almost 20GB, which is strange because they are setup to be rotated using logrotate. The files should have been limited to 700MB max. According to logrotate status, it last ran on 6-1-16, when it should run daily via cron.


    logrotate is now setup to run hourly, and we are going have monit monitor disk space on all of our EC2 instances so we can catch this issue in the future.

  • New Client Library in Go

    We are pleased to announce the release of a new officially supported client library for the Adafruit IO API! We now have an client library for Go. This client meets a few goals for us, and hopefully provides a useful hook into Adafruit IO for curious and interested web developers.

    It’s my (Adam) first project with the IO team, and so is a good starting place for exploring both the external API and the internal systems that drive it. It’s also a good chance for me to introduce my teammates to Go which is a very pleasant language to write web-connected code in. I’m a Rubyist by trade but exploring Go for lower level and Machine-to-Machine web services. I like it.

    More client libraries means broader coverage of the Adafruit IO API. As web developers, we aren’t often forced to think of the systems we build from the outside in. By making a public API and building the client libraries for it, we have a chance to see what works and doesn’t work. That’s both from a design perspective–is this API “friendly”?–and from a very practical perspective. For example, I committed two bug fixes to Adafruit IO’s core codebase while building io-client-go, huge success! Today, this library covers version 1 of the Adafruit IO API, but we’re hard at work on version 2.

    More client libraries means more open doors for new developers. Adafruit IO’s primary goal is to be the easiest way to get your Internet of Things project online. That involves a big team of people at Adafruit working at every part of the stack: engineers building new hardware and writing new firmware, makers coming up with new projects and spending a lot of time on clearly communicating what they’re doing, web developers inventing new ways of building an accessible Internet of Things platform, and, MOST IMPORTANTLY, an awesome crowd of people who can think of things to do with the tools we build that we cannot think of ourselves.

    This library isn’t the ending place for anyone’s project, but it could be the starting place for all kinds of interesting work. We don’t know! That’s the point! Here, take this, we made it for you, enjoy! :D

    This isn’t the first client library we’ve built and it won’t be the last. If Go isn’t your style yet, make sure to check out similar tools in Python, Javascript, and Ruby. And when you’re using the things we’ve built in the Things you’re building, feel free to talk to us and tell us what’s good, what’s bad, or what you’d like to see. Leave a note in the bug tracker, on the forum, or in the respective client library’s GitHub repository.

    And please, show us what you’re making! We would LOVE to see it almost as much as (I hope) you loved to build it. Also, speaking as a new member of the Adafruit team, I have never met a group of people more genuinely committed to supporting people at every level of experience than here at Adafruit.

    As always, Adafruit’s open source work is supported by the clever, creative folks who shop at Adafruit and by the community that contributes in code to any of our open source projects.

    Current status:
  • MQTT Time Utilities

    We will be deploying a new feature to our MQTT broker tomorrow morning. We will start broadcasting the current time in two formats at time/ISO-8601 and time/seconds at one second intervals. This should allow users to easily keep track of the current time from devices without real time clocks.

    Here are a couple examples of the payloads:


    topic: time/ISO-8601
    payload: 2016-06-01T21:34:12.629Z

    Seconds since Unix epoch:

    topic: time/seconds
    payload: 1464816851
  • MQTT Connection Throttle

    We did some profiling of our node MQTT workers using the --prof flag today, and we found that our workers were spending an excessive amount of time handling MQTT connection authorization. It turns out that a few users were hammering our servers with failed auth attempts, so we decided to implement a rate limit for MQTT connection attempts.

    The new connection rate limit allows for 50 connection attempts in a 15 minute window, and attempts past the limit will be rejected for the remainder of the window. If you would like to comment on this change, please visit our IO forum.

  • Please welcome Adam to the Adafruit team!

    Hello all you lovely makers! I am very excited to introduce myself: my name is Adam Bachman, I am here to write code and chew bubblegum, and I am all out of bubblegum! As of May 23, 2016, I am the newest member of the Adafruit team and will mainly be working with Justin, Todd, Tyler, and the rest of the incredibly talented folks making Adafruit IO the best it can be.

    I’ve been a resident of Baltimore City, making my way through the world as a software developer for the last 10 years. By day building software for Fortune 500’s, startups, bootstrapped artist-loving theater makers, and a few in between. On my own time I’ve been an Adafruit customer since 2007, started a hackerspace in 2009, and I’m super into Processing and creative code in general.

    You can follow me on Github or Twitter if you like, though I can’t promise to be half as interesting as the people at the middle of this incredible enterprise :D

    ENOUGH ABOUT ME! I look forward to connecting with anyone crossing boundaries from software to hardware and back again. Artists, makers, hobbyists, professionals, first-timers, long-timers, indie, corporate, all of you, everyone, cats, maybe not so much dogs, whatever! I am psyched to get started, let’s make amazing things!

  • AIO Keys Backend Updates

    We’ve made some more backend changes to how the AIO Keys are generated and maintained. If you run into any authentication or strange AIO Key issues please let us know as soon as possible in the IO forum or Issues Tracker.

    Most of the changes were security enhancements, but we’re laying the groundwork for more features specifically related to the AIO Keys, including added administration functionality.

  • Multicolumn Index Order in Postgres

    We started to notice some speed issues yesterday with certain queries in one of the largest tables (~50 million rows) in our PostgresSQL database, and we wanted to share some of the results of the investigation.

    During our tests today, we noticed that the slow queries ordered by id DESC were running in about 5 seconds, and queries that were ordered by created_at DESC were running in 0.1 milliseconds. Multicolumn indexes were present for both queries to use, and EXPLAIN ANALYZE showed that the queries hitting those indexes with an index scan.

    This led to the obvious question: wtf?

    After some investigation, we found that the order of columns in the index were reversed. One had the columns defined as (feed_id, created_at DESC) and the other had the columns defined as (id DESC, feed_id). After looking at the PostgresSQL docs for multicolumn indexes, the issue was clear.

    It turns out that you need to define your indexes with a constraint (feed_id) first, so that you are only scanning a portion of the index. By defining id first, the full index was scanned, which resulted in very slow queries. We switched the order of the columns in the index to (feed_id, id DESC) and the queries are now running in the ~0.1 ms range, so you should notice that things are now much more responsive.

    Please check out the relevant docs in the PostgresSQL 9.5 manual if you would like more info about multicolumn indexes.

  • State of IO 05.01.16

    We are considering a change to the way IO handles the retain flag on MQTT publish packets. The retain flag is used to allow the MQTT broker to retain the sent value, and will tell the server to pass it to any new subscribers as soon as they connect. We found that this feature was a little hard for people to understand at first, so we decided to force the retain flag to true for users by default. This change ensured that users always got the current state of their IO feeds as soon as they connected, without having to send a HTTP request to the REST API for the current value.

    The decision to force the retention of values caused issues with some users, because they lost the option to decide which values were cached. We are planning to revert this change, and give people the option to cache the values using the retain flag.

    In addition to this change, we are thinking of extending the meaning of the retain flag, and also allowing users to decide which values are logged to the database. So for example, if you wanted to push out temperature values every second to your connected devices, but only wanted to log the temperature value every minute, you could do so by only setting the retain flag to true for the values you wish to log. This should allow for greater flexibility when logging, and will result in increased speed for feeds that are focused on realtime interaction. We welcome your feedback in the IO forum.

    If you would like to read more about the MQTT retain flag, please check out this article on HiveMQ’s blog.

    Here are the stats for the past week:

    * 29.03 million inserts of logged data in the last 7 days
    * 10,969 users
    * 8,675 online feeds (24,277 feeds total)
  • REST API v2 Deployment on April 21st

    On Thursday, April 21st we will be deploying Version 2 of our API. This version is quite different from our existing API V1.

    IMPORTANT: Your code or sketches will need to be updated if you are using the REST API.

    From now until Thursday, you will want to update your code or sketches to change ‘/api/…’ to ‘/api/v1/’ so that you continue using v1 of the API until you are ready to upgrade to the latest version.

    Here are some of the highlights (not including bug fixes):


    • New permission system that will allow for sharing read and write access to your feeds, groups, & dashboards with other users.
    • New AWS inspired HTTP request signing to help avoid exposing the user’s AIO key over insecure connections.
    • Dashboards, blocks, & triggers will be able to be modified via the REST API.


    • Username will be a required component of the URL.
    • You will no longer be able to access feeds & groups via numeric ID. Feed key & group keys will be used as the unique identifier in API v2.
    • Feeds will be able to be added to many groups, and the feed’s data will be namespaced to the group the data is pushed to. You will also be able to access all of the feed’s data by accessing the feed directly.
  • Trigger Emails Temporarily Disabled

    We’re temporarily disabling the email triggers until we can make them more robust in a near future update. In the meantime, the alternative would be to use our IFTTT channel, which can do pretty much the same thing as our internal trigger emails.

    We want to build a much more robust system. As is, there are some weaknesses in our current design that can trigger emails to be sent far too often, or without a way for them to reset after the trigger threshold has been hit.

    If you have any suggestions on what you’d like to have implemented with this feature, please let us know at the our IO forum.

  • State of IO 4.17.16

    This week we will be deploying two major changes to IO. We will be deploying v2 of the REST API, and we will be moving our MQTT services from mosca to aedes. This should allow us to squeeze even more performance out of our MQTT workers, and will also allow us to support MQTT QoS 2.

    Here are the stats for the past week:

    * 28.69 million inserts of logged data in the last 7 days
    * 10,512 users
    * 8,077 online feeds (22,695 feeds total)
  • State of IO 4.10.16

    Here are the stats for the past week:

    * 30.21 million inserts of logged data in the last 7 days
    * 10,086 users
    * 7,766 online feeds (21,498 feeds total)
    * ~50 inserts per second via MQTT
    * ~5 inserts per second via REST API

    After some load testing, it seems that our current server configuration is able to handle more traffic. Our current theory is that the inserts per second aren’t rising evenly with the increased online feed count because users are using IO for real-time interaction, and not data logging. Inserts per second only seem to rise with heavy and persistent data logging projects.

    LoRa IO

    We have been testing the new Feather LoRa Radios with IO, and they seem to be a fantastic pair. We were able to send messages to IO through a LoRa gateway from 1.27 miles away in the rolling hills of central Maryland using a small wire antenna.

    LoRa IO

    Pretty impressive for not having line of sight to the gateway!

    LoRa Mesurement

  • State of IO 4.3.16

    We added support for AWS v4 inspired request signing to IO’s v2 REST API this week. This change should allow devices that don’t support TLS/SSL to communicate with Adafruit IO without sending their AIO Key in the clear. Because the requests are signed using a HMAC, users also will be able to ensure that their requests were not manipulated by things like man-in-the-middle attacks. This change will also reduce the risk of replay attacks by including a timestamp in the signature, so the request will only be valid within a 15 minute window.

    We are considering requiring signed requests for any API v2 requests that don’t use a TLS/SSL connection. If you think this is a bad idea, please let us know in the forums. We will be updating the Adafruit IO client libraries this week to support the new request signatures.

    Here are the stats for the past week:

    * 27.4 million inserts of logged data in the last 7 days
    * 9,744 users
    * 7,537 online feeds (20,474 feeds total)
    * ~50 inserts per second via MQTT
    * ~5 inserts per second via REST API

    Inserts per second seem to be holding steady, despite the increase in online feeds. We are going to add another queue worker and monitor the inserts per second to see if that fixes the bottleneck.

  • State of IO 3.25.16

    We have been working on finishing up v2 of the REST API this past week, and you can read more about that here.

    We are also in the process of finishing up transitioning our frontend javascript to React from jQuery and Backbone. When combined with API v2, this change should increase performance, and also will make development easier and faster. We will post more about this change in the next few days.

    Here are the stats for the past week:

    * 25,951,672 inserts of logged data in the last 7 days
    * 9,296 users
    * 6,949 online feeds (19,084 feeds total)
    * ~50 inserts per second via MQTT
    * ~5 inserts per second via REST API
  • REST API v2 Development

    We are currently in the process of developing version 2.0 of the Adafruit IO REST API, which should address a large portion of user requests. The current version of the REST API (v1.0) will still be available at io.adafruit.com/api/v1/.

    Here are some of the highlights (not including bug fixes):


    • New permission system that will allow for sharing read and write access to your feeds, groups, & dashboards with other users.
    • New AWS inspired HTTP request signing to help avoid exposing the user’s AIO key over insecure connections.
    • Dashboards, blocks, & triggers will be able to be modified via the REST API.


    • Username will be a required component of the URL.
    • You will no longer be able to access feeds & groups via numeric ID. Feed key & group keys will be used as the unique identifier in API v2.
    • Feeds will be able to be added to many groups, and the feed’s data will be namespaced to the group the data is pushed to. You will also be able to access all of the feed’s data by accessing the feed directly.
  • AIO Key Length Changes

    We had a request in the forums to reduce the length of the AIO Key to 32 characters, and we decided to use UUID v4 (with the dashes stripped) to generate keys. Version 4 UUIDs are randomly generated, so they should work well as AIO Keys:

    …after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%.

  • Testing Cassandra Reads

    We have been writing user’s feed data to both Cassandra 3.3 and PostgreSQL 9.5 for the past couple weeks as the first step in transitioning fully to Cassandra as the primary data store for feed data. We will still be using Postgres as our primary database for relational data, but it should be much easier to scale Cassandra horizontally as the large amount of logged data increases.

    Here’s the current write performance data from Cassandra’s nodetool tablestats:

    Write Count: 59051081
    Write Latency: 0.012758596713919598 ms.

    That’s a little over 59 million writes in the past ~17 days, with the load on a m4.large barely ever passing 0.05.

    load average: 0.01, 0.01, 0.05

    Today, we have also started testing read performance in production. For now users are still receiving their data from Postgres, but we are also hitting Cassandra to see if our configuration can handle production loads. We’ll post an update once we have more info about how reads are performing.

    Here’s some early info after the deploy:

    Read Count: 314
    Read Latency: 0.6644044585987261 ms.
  • Sending Commands to Multiple EC2 Instances Using dsh

    We moved Adafruit IO’s node.js services to a group of t2.nano EC2 instances, and I wanted to document my dsh setup. I used it reguarly a couple years ago for managing the backend workers when working on other services, but I had forgot how it was configured. It came in really handy when I needed to quickly check or kick anything on the servers.

    First, you will need to install dsh using brew, apt-get, yum, etc:

    $ brew install dsh

    You will need to make a couple config directories for your user:

    $ mkdir -p ~/.dsh/group

    Create a new dsh.conf file using your favorite text editor:

    $ vim ~/.dsh/dsh.conf

    Paste the following config into ~/.dsh/dsh.conf, and save the file:

    showmachinenames = 1
    remoteshell = ssh

    Now, you can create a dsh group for the set of servers you would like to send commands to. Create a new file called example in the ~/.dsh/group folder using your favorite text editor:

    $ vim ~/.dsh/group/example

    Enter the host names for your servers, and save the file:


    Now you can send commands (like uptime) to all servers in the group using the following command:

    $ dsh -g example -w 'uptime'
    example-1.adafruit.com:  14:17:44 up 17:15,  0 users,  load average: 0.08, 0.03, 0.05
    example-2.adafruit.com:  14:17:43 up 16:36,  0 users,  load average: 0.00, 0.01, 0.05
    example-3.adafruit.com:  14:17:45 up 16:41,  0 users,  load average: 0.00, 0.01, 0.05
    example-4.adafruit.com:  14:17:45 up 16:41,  0 users,  load average: 0.00, 0.01, 0.05

    Using -w will send the command to each server in the order they appear in the group config, and will wait for a response before continuing. If you want to send the commands concurrently to all servers in the list, use the -c option to send the command:

    $ dsh -g example -c 'uptime'
    example-1.adafruit.com:  14:22:42 up 17:20,  0 users,  load average: 0.00, 0.01, 0.05
    example-3.adafruit.com:  14:22:42 up 16:46,  0 users,  load average: 0.00, 0.01, 0.05
    example-2.adafruit.com:  14:22:41 up 16:41,  0 users,  load average: 0.00, 0.01, 0.05
    example-4.adafruit.com:  14:22:42 up 16:46,  0 users,  load average: 0.10, 0.05, 0.05

    You can get an interactive shell for all servers in the group by using the -c and -i commands together. Use CTRL-D to exit the session:

    $ dsh -g -c -i
  • State of IO 3.18.16

    Adafruit IO has been growing steadily, and we decided to add a changelog so it’s easier for users to see what we are up to. We will be posting here reguarly whenever we add or update features, and we will also be posting stats so you have more information about the growth of IO.

    We have moved IO to a handful of Amazon EC2 instances, and we are finding it much easier to deal with increased load. The individual services are now split out into separate instances, which will allow us to scale horizontally.

    Here’s a screenshot of what it looks like when we are monitoring the state of the new EC2 instances:

    IO on EC2

    We have added IO to the Adafruit Status Page, which will allow you to check and see if any of IO’s components are currently down. You can also follow @adafruitstatus if you would like to be notified of outages.

    Adafruit Status Page

    Here are the stats for the past week:

    * 24,290,428 inserts in the last 7 days
    * 8,997 users
    * ~6,700 online feeds (~18,200 feeds total)
    * ~50 inserts per second via MQTT
    * ~5 inserts per second via REST API