<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ iot - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ iot - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 25 May 2026 22:37:52 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/iot/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Scale Bluetooth Across Android, iOS, and Embedded Devices ]]>
                </title>
                <description>
                    <![CDATA[ Bluetooth is one of those inventions that seems magical the first time you use it. You turn on a gadget, pair it with your phone, and suddenly they are talking to each other without a single wire in sight. Music plays through your headphones, your sm... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-scale-bluetooth-across-devices/</link>
                <guid isPermaLink="false">691742dfb6a85c7f18a5fc15</guid>
                
                    <category>
                        <![CDATA[ bluetooth ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ embedded systems ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Nikheel Vishwas Savant ]]>
                </dc:creator>
                <pubDate>Thu, 13 Nov 2025 23:00:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763131642774/dd2366f8-f491-4313-901e-acd4c1d937e2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Bluetooth is one of those inventions that seems magical the first time you use it. You turn on a gadget, pair it with your phone, and suddenly they are talking to each other without a single wire in sight. Music plays through your headphones, your smartwatch shows messages from your friends, and for a brief moment it feels like technology finally has its act together. Everything works and life is good.</p>
<p>Then you try to connect one more thing. Maybe a fitness band, a smart lock, or that tiny temperature sensor you ordered online because it was on sale. That is when the charm fades and reality walks in. Suddenly the connection drops, your phone cannot find the device anymore, and the once-friendly Bluetooth logo on your screen starts to feel like a taunt. You restart, you unpair, you try again, and somehow it only gets worse. What was once effortless turns into a puzzle with no clear solution.</p>
<p>Here is the secret that few people know: Bluetooth was never meant to handle the chaos we put it through today. When engineers designed it in the late 1990s, they imagined a world of simple one-to-one connections. A laptop talking to a mouse. A phone connecting to a headset. That was the whole idea. Fast-forward to the present and we are using the same technology to run entire networks of wearables, sensors, and smart appliances. We ask it to connect not just one or two devices but sometimes dozens of them at the same time, each running on different hardware and software. It is a miracle that it works at all.</p>
<p>To make things even more interesting, these devices live in very different worlds. Android devices are like an open playground where every manufacturer adds its own slide and swing set. iPhones live inside Apple’s carefully fenced garden where everything is polished but also tightly controlled. Embedded devices, like the ones built on tiny chips inside sensors or IoT boards, are the quiet introverts of the group. They have little memory, tiny batteries, and a strong preference for naps to save power. Getting all three to cooperate is a bit like trying to organize a band where one member only plays jazz, another insists on classical, and the third speaks in Morse code.</p>
<p>That is what engineers mean when they talk about scaling Bluetooth. It is not just about adding more devices. It is about making sure completely different systems can talk to each other reliably and continuously without draining their batteries or losing their minds. It requires design decisions that consider timing, power management, data formats, and even how the operating system schedules background tasks.</p>
<p>This article will guide you through that strange world. We will peel back the layers of how Bluetooth actually works and what happens when Android, iOS, and embedded devices try to share the same airwaves. We will explore why each one behaves the way it does and what you can do to build systems that stay connected instead of collapsing under their own complexity.</p>
<p>By the end, you will see that Bluetooth is not really broken. It is simply overworked. It is a polite translator trying to keep three very different languages in sync. Once you learn how to manage its quirks and give it the structure it needs, Bluetooth becomes not a source of frustration but a quiet, invisible network that holds the modern world together.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-bluetooth-has-two-personalities-meet-classic-and-ble">Bluetooth Has Two Personalities — Meet Classic and BLE</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-android-ios-and-embedded-devices-the-odd-trio">Android, iOS, and Embedded Devices — The Odd Trio</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-architecting-for-scale-herding-cats-but-wirelessly">Architecting for Scale — Herding Cats, but Wirelessly</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-connection-discovery-and-data-flow-the-bluetooth-dating-game">Connection, Discovery, and Data Flow — The Bluetooth Dating Game</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-platform-quirks-and-how-to-stay-sane">Platform Quirks — And How to Stay Sane</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-security-and-privacy-at-scale">Security and Privacy at Scale</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-power-and-performance-tuning">Power and Performance Tuning</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-provisioning-and-firmware-updates-welcome-to-device-kindergarten">Provisioning and Firmware Updates — Welcome to Device Kindergarten</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-debugging-monitoring-and-testing-across-platforms">Debugging, Monitoring, and Testing Across Platforms</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-architecture-example-when-bluetooth-finally-behaves">Real-World Architecture Example — When Bluetooth Finally Behaves</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-checklist-building-a-truly-scalable-bluetooth-system">Checklist — Building a Truly Scalable Bluetooth System</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrap-up-lessons-from-the-field">Wrap-Up — Lessons from the Field</a></p>
</li>
</ul>
<h2 id="heading-bluetooth-has-two-personalities-meet-classic-and-ble">Bluetooth Has Two Personalities — Meet Classic and BLE</h2>
<p><img src="https://elainnovation.com/wp-content/uploads/2021/12/Bluetooth-VS-BLE-EN.jpg.webp" alt="What is the difference between Bluetooth and Bluetooth Low Energy (BLE)?" width="600" height="400" loading="lazy"></p>
<p>Before we can talk about scaling Bluetooth, we have to understand that Bluetooth itself has a bit of an identity crisis. It actually comes in two flavors: Classic Bluetooth and Bluetooth Low Energy, also called BLE. They share the same name and sometimes even live on the same chip, but under the hood they behave very differently. Think of them as twins who went to completely different schools and now have opposite personalities.</p>
<p>Classic Bluetooth is the older sibling. It was designed for steady, high-speed data streams. This is the version your headphones, speakers, and car systems use. It is reliable for sending large amounts of data like audio, but it is also chatty and power-hungry. It likes to stay connected all the time, constantly keeping the line open so it can send sound packets smoothly. You could say Classic Bluetooth is like that one friend who calls instead of texting and keeps the conversation going even when there is nothing left to say.</p>
<p>Then there is Bluetooth Low Energy, the younger, more introverted sibling. BLE was designed for devices that need to last for weeks or months on tiny batteries. It does not keep a constant connection open. Instead, it wakes up, sends or receives a little bit of data, and then goes back to sleep. It is the protocol behind fitness trackers, heart rate monitors, smart locks, and most modern IoT devices. If Classic Bluetooth is a full-time conversation, BLE is more like sending quick text messages throughout the day, short, efficient, and battery-friendly.</p>
<p>The funny thing is that even though they share the same wireless spectrum and sometimes even the same antenna, these two modes do not talk to each other directly. A BLE device cannot communicate with a Classic Bluetooth-only device. This is why your wireless headphones can pair with your phone, but your BLE heart rate monitor cannot talk to your old Bluetooth speaker. They live in the same neighborhood but never attend the same parties.</p>
<p>Most of the world’s scaling problems come from BLE, not Classic Bluetooth. Classic has been around long enough that its use cases are stable and well understood. BLE, on the other hand, is used in thousands of different kinds of devices, each with different timing requirements, power limits, and operating systems. When you try to make Android, iOS, and embedded systems all use BLE together, you are juggling three slightly different interpretations of the same rulebook.</p>
<p>To make things trickier, each platform implements BLE its own way. Android exposes it through flexible but sometimes unpredictable APIs. iOS keeps it tidy under Apple’s strict Core Bluetooth framework. Embedded devices rely on lightweight vendor stacks that can vary from chip to chip. Every one of these stacks follows the same Bluetooth specification, but like recipes written by different chefs, the results can taste a little different.</p>
<p>Understanding this dual nature is key to building anything that scales. You must know when to use Classic Bluetooth for high-speed continuous data, when to use BLE for low-power bursts, and how to design your system so that the right devices use the right mode. It is the first step in turning Bluetooth from a confusing mystery into a reliable network you can actually control.</p>
<h2 id="heading-android-ios-and-embedded-devices-the-odd-trio">Android, iOS, and Embedded Devices — The Odd Trio</h2>
<p><img src="https://cdn.dca-design.com/uploads/images/News/_full_width_content_image/105358/Bluetooth_DCA_News_Article_003.webp?v=1749036238" alt="Working with Bluetooth Low Energy across Android and iOS - News - DCA Design" width="600" height="400" loading="lazy"></p>
<p>Now that we know Bluetooth has two personalities, let’s meet the three characters that make scaling it so complicated: Android, iOS, and embedded devices. They all speak Bluetooth, but in their own unique accents. Sometimes they understand each other perfectly, and other times it feels like they’re arguing in three different languages while pretending they’re on the same page.</p>
<p>Let’s start with Android. Android is the enthusiastic extrovert of the group. It gives you tons of control and freedom. You can scan, connect, advertise, read, write, and basically poke around every corner of the Bluetooth stack. But that freedom comes with chaos. Because Android runs on phones made by dozens of manufacturers, each one tweaks the Bluetooth implementation a little differently. On one phone, everything works flawlessly. On another, the same code randomly drops connections or refuses to scan in the background. Even Android engineers joke that if your Bluetooth works the same on every device, you’ve probably entered a parallel universe.</p>
<p>Android is powerful but unpredictable. It’s like a sports car that can win a race on a good day but sometimes refuses to start if it doesn’t like the weather. The trick is to write code that expects weird behavior, to build your own connection queues, add retries, and prepare for the occasional glitch. Developers who survive Android Bluetooth bugs don’t just gain experience, they gain humility.</p>
<p>Then there’s iOS, Apple’s polished and opinionated perfectionist. Unlike Android, iOS is consistent. The same code usually behaves the same way across every iPhone and iPad. Apple’s Bluetooth framework, called Core Bluetooth, is beautifully organized and well-documented. But Apple also has strict rules about what you can and can’t do. Background scanning? Only in very specific cases. Advertising? Only for certain UUIDs. Access to lower-level Bluetooth layers? Absolutely not. Apple’s approach is like a luxury hotel: everything looks gorgeous, but you’re not allowed in the kitchen.</p>
<p>Working with iOS feels calm at first. Your connections are stable, your APIs are clear, and your devices behave predictably. But the moment you need to do something slightly unconventional, like connecting to multiple peripherals at once or keeping the app alive in the background, iOS politely says, “No, that’s not how we do things here.” Developers often end up performing delicate dances with background modes, notifications, and clever reconnection tricks just to make things feel seamless for users.</p>
<p>And then we have the third member of the trio: embedded devices. These are the quiet, uncomplaining ones that actually do most of the work. They live inside your smart sensors, wearables, and IoT nodes. They’re usually built around tiny chips with limited memory and low-power processors. They don’t have fancy operating systems or flashy UI frameworks. All they know is how to advertise, connect, send data, and then go back to sleep to save battery.</p>
<p>Embedded devices are loyal but easily overwhelmed. They can’t handle constant large data transfers, and they get cranky if you make them maintain too many simultaneous connections. Imagine trying to run a marathon after eating one grape, that’s what it’s like for a small BLE chip to handle too much traffic. Yet, these little devices are the backbone of every scalable Bluetooth network. They measure your heart rate, control your smart lights, and track your environmental sensors, all while running quietly in the background.</p>
<p>The real challenge begins when you try to make these three cooperate. Android wants freedom, iOS wants structure, and embedded devices just want a nap. Getting them all to work together is like managing a group project where one person writes essays at midnight, another color-codes everything, and the third forgets to charge their laptop. But when you finally get it right, when Android, iOS, and your embedded nodes connect seamlessly, it feels like magic again.</p>
<p>In the next section, we’ll explore how to actually make that happen. You’ll see how to design a Bluetooth architecture that scales gracefully across these platforms instead of collapsing into a pile of logs and retries. It’s part engineering, part patience, and part diplomacy.</p>
<h2 id="heading-architecting-for-scale-herding-cats-but-wirelessly">Architecting for Scale — Herding Cats, but Wirelessly</h2>
<p>If there’s one secret to scaling Bluetooth, it’s this: treat it like herding cats. You’ll never truly <em>control</em> it, but with enough structure, patience, and a bit of catnip (or clever engineering), you can convince all the cats to move in roughly the same direction.</p>
<p>Building a Bluetooth system that spans Android, iOS, and embedded devices isn’t just about writing code that connects things. It’s about designing <em>relationships</em>, the rules and boundaries that keep those connections healthy. The key idea here is <strong>architecture</strong>, which is a fancy word for “deciding who does what, when, and how.” Without a solid architecture, your Bluetooth project quickly turns into a tangle of callbacks, disconnections, and unanswered packets.</p>
<p>The first principle of Bluetooth architecture is <strong>abstraction</strong>. Every platform has its own Bluetooth API, but the basic idea is always the same: scan for devices, connect, exchange data, and disconnect. So instead of writing separate logic for each platform, you create one unified interface, a sort of translator layer, that hides all the messy differences underneath. In practice, this means you can write something like <code>connect(device)</code> in your app, and whether you’re on Android, iOS, or even a Raspberry Pi, the underlying code figures out how to make it happen.</p>
<p>This abstraction layer is your peacekeeper. It prevents the rest of your app from needing to know whether it’s talking to a Nordic chip on a wristband, a smart bulb using an ESP32, or an iPhone pretending to be a peripheral. When you have hundreds or thousands of devices, abstraction isn’t just convenient, it’s survival.</p>
<p>Next comes <strong>connection management</strong>. BLE connections are like toddlers: they demand constant attention and can vanish the moment you look away. A scalable Bluetooth system can’t afford to panic every time a device disconnects. Instead, you design it to expect chaos. You add automatic retries, reconnection strategies, and timeouts that gracefully handle failures instead of freezing your app. Good systems don’t assume the network will always behave, they assume it won’t.</p>
<p>Then there’s <strong>data orchestration</strong>, deciding who talks first, how much data gets sent, and how you keep multiple connections from tripping over each other. Imagine you’re a conductor in an orchestra where half the instruments fall asleep randomly to save power. You need a plan that lets each device play its part in harmony without draining its battery. That’s what managing Bluetooth data flow feels like.</p>
<p>And finally, there’s <strong>power strategy</strong>. Embedded devices live on tight energy budgets. Every scan, advertisement, and data exchange eats into their lifespan. So, your architecture must schedule communication intelligently, let devices wake up briefly, share data, and return to sleep before they burn out. The best Bluetooth systems look lazy on the surface but are actually brilliant planners underneath.</p>
<p>When you put all of this together, abstraction, connection management, orchestration, and power control, you get something that <em>scales</em>. It doesn’t matter if you’re managing three wearables or three thousand sensors. The system behaves predictably, logs issues instead of panicking, and recovers from disconnections automatically.</p>
<p>Think of it like a well-run airport. Planes (your devices) take off and land constantly. The control tower (your app’s Bluetooth manager) keeps track of who’s in the air, who’s landing next, and who needs maintenance. No single pilot needs to know everything, they just follow the protocol.</p>
<p>Scaling Bluetooth isn’t about being clever with one device. It’s about designing systems that keep working even when dozens of devices act unpredictably. You don’t tame Bluetooth by force; you do it by creating a world where even chaos feels organized.</p>
<p>In the next section, we’ll dig deeper into how these connections actually behave in real time, how devices discover each other, exchange data, and, sometimes, break up without warning.</p>
<h2 id="heading-connection-discovery-and-data-flow-the-bluetooth-dating-game">Connection, Discovery, and Data Flow — The Bluetooth Dating Game</h2>
<p>Every Bluetooth connection starts like a modern love story. One device sends out signals into the air, announcing that it’s available. Another device scans the surroundings, hoping to find something compatible. When they finally spot each other, they exchange a few polite packets, decide they’re a good match, and try to make it official with a connection. It’s wireless romance, until one of them walks away without saying goodbye.</p>
<p>This is the heart of how Bluetooth works: <strong>advertising, discovery, and connection</strong>. An embedded sensor or wearable device usually plays the role of the advertiser. It broadcasts tiny packets called advertisements that contain just enough information to say, “Hey, I’m here, and I can measure temperature or heart rate or unlock your door.” These packets are intentionally small because transmitting data takes energy, and low-power devices have to conserve every drop of battery life.</p>
<p>Meanwhile, your phone or tablet acts as the scanner, it listens to the radio waves around it, searching for those signals. When it finds one that matches what it’s looking for, it sends a request to connect. If the peripheral accepts, they move into a new relationship phase: the <strong>GATT connection</strong>. GATT stands for Generic Attribute Profile, which is basically the language they use to talk. Once connected, your phone can ask the device for specific data, like reading a heart rate measurement or writing a configuration setting.</p>
<p>Now, if all of this sounds peaceful and predictable, that’s because we haven’t talked about what happens in the real world. In reality, devices move around, signals weaken, and phones go into power-saving modes that forget they were even connected. Connections drop. Pairing sometimes fails. And when you have ten or more devices talking at once, managing all those tiny wireless conversations becomes a circus act.</p>
<p>Scaling Bluetooth is all about keeping this circus under control. You can’t force every device to stay connected forever, that would drain batteries and jam the radio channels. Instead, you design a rhythm. Devices connect only when needed, exchange data quickly, and then disconnect to rest. This constant dance of connecting and disconnecting keeps the system efficient and stable.</p>
<p>Think of it like a well-run coffee shop. Customers (phones) walk in, place their order (data request), get their coffee (response), and leave. The barista (the embedded device) doesn’t serve one person all day, it serves everyone in quick cycles. The trick is to make sure no one gets stuck waiting for their latte forever.</p>
<p>Timing is everything in this dance. If a device advertises too infrequently, the phone might not discover it in time. If it advertises too often, it wastes power. If the phone sends too many requests at once, the device might crash or slow down. Bluetooth connections live in this delicate balance between performance and efficiency.</p>
<p>When you scale, you also have to think about coordination. Imagine one phone trying to talk to ten sensors at once. You can’t have it flood them all with requests simultaneously, it needs a queue, a polite way of saying “you first, then me.” This is called <strong>connection orchestration</strong>, and it’s one of the hardest parts of scaling BLE systems.</p>
<p>And then there’s the breakup. Devices disconnect all the time, sometimes intentionally, sometimes accidentally. The best Bluetooth systems treat disconnections not as failures but as normal events. The app automatically retries, reconnects, and syncs data without asking the user to “try again.” To users, it feels seamless. Underneath, there’s a lot of quiet heroism happening, background threads, timers, and reconnection logic all working together to patch up relationships on the fly.</p>
<p>So, at its core, Bluetooth is less like a stable marriage and more like speed dating with excellent scheduling. Everyone meets briefly, exchanges information, and moves on. When done right, this model scales effortlessly. When done wrong, it’s chaos.</p>
<p>In the next section, we’ll explore the quirks that make Android, iOS, and embedded devices behave differently in this dating game, and how to keep the peace when one of them inevitably ghosts the others.</p>
<h2 id="heading-platform-quirks-and-how-to-stay-sane">Platform Quirks — And How to Stay Sane</h2>
<p>Once you start scaling Bluetooth, you’ll notice something odd. The same code that works perfectly on one device suddenly refuses to behave on another. It’s like watching identical twins argue about who gets the last slice of pizza, they may look the same, but their personalities couldn’t be more different.</p>
<p>Let’s start with Android, the unpredictable one. Android gives developers more power than any other mobile platform. You can scan however you like, filter by services, read and write any characteristic, and even customize connection intervals. But that power comes at a price. Every phone manufacturer modifies the Bluetooth stack slightly. Samsung, Pixel, OnePlus, Xiaomi, each adds its own flavor of “enhancement,” which sometimes translates to “surprise, nothing works the same.”</p>
<p>One Android phone might handle ten connections at once without blinking. Another might drop all of them the moment the screen turns off. Some versions ignore Bluetooth permissions until you grant location access. Others claim they’re scanning when they actually stopped five minutes ago. Android developers eventually stop asking <em>why</em> and simply build more logging instead. The rule of thumb with Android Bluetooth is simple: test everything, assume nothing, and expect the unexpected.</p>
<p>Then there’s iOS, which at first feels like a breath of fresh air. Apple’s Core Bluetooth framework is clean, consistent, and almost elegant. You get predictable callbacks, smooth reconnections, and well-behaved devices. But if you step outside Apple’s boundaries, you’ll quickly find invisible fences. iOS doesn’t let apps scan in the background freely. It limits how often you can advertise. And if your app tries to keep too many simultaneous connections alive, iOS politely steps in and shuts them down.</p>
<p>Apple’s philosophy is control. It wants Bluetooth connections to behave in ways that don’t drain the battery or clutter the radio. That’s great for users, but for developers it can feel like being handed the keys to a Ferrari and told you can only drive in the parking lot. It works beautifully, as long as you color inside the lines.</p>
<p>And then we have embedded devices, which are in a category of their own. These are the little chips sitting inside your wearables, sensors, or IoT gadgets. They don’t have operating systems or background processes. They just run tiny loops of firmware that listen, respond, and sleep. Their quirks are more about physics than software. If the antenna isn’t tuned properly, signals drop. If the power supply fluctuates, the radio turns off. Sometimes they disconnect simply because a human walked between two devices and absorbed the signal.</p>
<p>Embedded Bluetooth stacks also differ by manufacturer. Nordic, Espressif, Silicon Labs, Texas Instruments, each has its own libraries, quirks, and limitations. Even small changes like increasing the packet size or adjusting the advertising interval can make or break communication. It’s a careful dance between efficiency and reliability.</p>
<p>Now imagine you’re trying to get all three of these worlds to cooperate. Android wants freedom, iOS enforces discipline, and embedded devices want long naps. Building a Bluetooth system that works across all of them is like running a daycare with overachievers, rule-followers, and kids who fall asleep mid-activity. You can’t treat them all the same, but you can design a routine that keeps everyone content.</p>
<p>The secret is resilience. Instead of expecting perfect behavior, build your system around imperfections. Add retries when connections fail. Cache data so you don’t lose progress during disconnections. Keep your embedded devices simple, your mobile apps forgiving, and your logs brutally honest.</p>
<p>If you design with these quirks in mind, your Bluetooth system will feel almost magical, even though, behind the scenes, it’s a web of error handling, reconnections, and polite compromise.</p>
<p>In the next section, we’ll take a look at another side of scaling: keeping everything secure and private while all these devices whisper secrets over the air.</p>
<h2 id="heading-security-and-privacy-at-scale">Security and Privacy at Scale</h2>
<p>Once your Bluetooth system starts working reliably, there’s another challenge waiting in the wings: keeping it <strong>secure</strong>. It’s one thing to get devices talking to each other, it’s another to make sure no one else is eavesdropping on the conversation. Bluetooth security can sound intimidating, but at its core, it’s about making sure your devices trust each other and that strangers can’t sneak into the chat.</p>
<p>Let’s start with pairing. Pairing is Bluetooth’s version of saying, “Hey, can I trust you?” It’s a handshake where two devices exchange keys that let them communicate securely in the future. There are a few ways this handshake can happen. The simplest is called <em>Just Works</em>, which basically means, “We’ll trust each other without asking too many questions.” It’s convenient but about as safe as leaving your front door unlocked because you live in a nice neighborhood. For harmless gadgets like wireless speakers, that’s fine. But for medical devices or smart locks, “Just Works” can turn into “Just Got Hacked.”</p>
<p>A safer approach is <strong>Passkey Entry</strong>, where one device shows a code and the other types it in, proving they’re physically near each other. Even better is <strong>Out-of-Band (OOB)</strong> pairing, where the devices exchange security information through another method, maybe a QR code, NFC tap, or even an optical blink, before connecting over Bluetooth. OOB pairing is like verifying someone’s identity face-to-face before continuing a conversation online.</p>
<p>Once paired, devices use <strong>encryption</strong> to scramble their communication. Anyone listening nearby will hear only gibberish. The strength of that encryption depends on the version of Bluetooth being used. Modern devices using Bluetooth 4.2 or later support something called <em>LE Secure Connections</em>, which is based on advanced cryptography. Older devices use weaker methods that are easier to crack. So, if you’re building something new, never rely on outdated pairing modes.</p>
<p>But security isn’t just about encryption. It’s also about <strong>privacy</strong>. Every Bluetooth device has an address, kind of like its phone number, that it uses when broadcasting. If that address stays the same, someone could track you by following your device’s broadcasts. That’s why newer standards support <em>random address rotation</em>, where devices periodically change their Bluetooth address. Your phone and smartwatch still recognize each other, but strangers can’t follow your signal around the city.</p>
<p>When you scale Bluetooth systems, these little details become critical. A single insecure device in your network can become the weak link that compromises everything. It’s like locking every door in your house but leaving one window open. Attackers don’t need to break the whole system, they just need to find the lazy one.</p>
<p>Building security into a large Bluetooth deployment means standardizing your pairing process, using strong encryption everywhere, and handling key storage carefully. On embedded devices, that can be tricky because they have limited memory and no secure element by default. Still, even small steps help, like regenerating keys periodically and disabling “Just Works” mode for devices that control anything important.</p>
<p>On mobile platforms, the rules are slightly different. Android and iOS handle much of the heavy lifting for you, but you still have to design your app logic carefully. Always confirm which device you’re connecting to before exchanging sensitive data. Always check bonding state before sending configuration commands. In short, treat Bluetooth communication with the same seriousness you’d give to a login session or an online payment.</p>
<p>At scale, security isn’t something you bolt on later. It’s part of the system’s DNA. You can’t fix a weak handshake by adding a stronger password later. You have to start from the first pairing and make sure every connection trusts the right partner.</p>
<p>The reward is worth it. When done right, your Bluetooth network becomes invisible but secure, a quiet, encrypted web of trust that just works. No drama, no leaks, and no nearby strangers hijacking your sensors.</p>
<p>In the next section, we’ll talk about another invisible problem that decides whether your Bluetooth network lives for days or months: power. Because what good is a secure device if its battery dies halfway through the handshake?</p>
<h2 id="heading-power-and-performance-tuning">Power and Performance Tuning</h2>
<p>If you’ve ever wondered why your Bluetooth gadget dies right when you need it most, you’ve just met the oldest enemy in wireless communication: power consumption. Bluetooth may be clever, flexible, and everywhere, but it also has a bit of a caffeine problem. It loves to talk, and talking burns energy. Keeping your devices alive longer, especially when you scale, means learning the quiet art of power management.</p>
<p>At first, it’s easy to assume that Bluetooth is low power by default. After all, it’s called <strong>Bluetooth Low Energy</strong>, right? But BLE’s efficiency only shines when it’s used correctly. A poorly tuned BLE system can drain a battery faster than streaming music over Classic Bluetooth. The magic lies in controlling when devices talk, how long they talk, and how much they say each time.</p>
<p>Let’s start with the <strong>advertising interval</strong>. This is how often a device shouts, “I’m here!” into the air. If you set it to broadcast every 20 milliseconds, you’ll discover devices quickly, but you’ll also burn through the battery like it’s running a marathon. Increase the interval to once every second, and your device will last much longer, but phones may take a moment to find it. It’s a tradeoff between speed and stamina. Every system has to find its sweet spot.</p>
<p>Next comes the <strong>connection interval</strong>, how often two connected devices exchange data. This is like deciding how frequently you check your messages. If you check every second, you stay perfectly up to date but never get anything else done. If you check once every minute, you save time but risk missing something important. In Bluetooth terms, a shorter connection interval means faster communication but higher power usage. Longer intervals conserve battery but add delay. Smart systems adjust these intervals dynamically depending on what the device is doing.</p>
<p>Then there’s the <strong>MTU</strong>, or Maximum Transmission Unit, the size of each Bluetooth data packet. Bigger packets mean fewer total transmissions for large chunks of data, which can improve efficiency. But some devices, especially older ones, can’t handle large MTUs, so finding the right balance is important.</p>
<p>Power management is not just about numbers, it’s about habits. A well-designed embedded device spends most of its life asleep. It wakes up only to advertise or exchange data, then returns to rest as quickly as possible. Imagine a hummingbird darting out for a sip of nectar and then zipping back to rest before anyone notices. That’s how efficient Bluetooth devices survive on coin-cell batteries for months or even years.</p>
<p>On the phone side, energy management is just as critical, especially when your app needs to handle multiple connections. Constant scanning, reconnecting, or keeping GATT channels open drains your user’s battery, and patience. Android and iOS both have built-in mechanisms that throttle background Bluetooth activity to save power. Developers have to work with these rules, not against them. The best apps schedule scans intelligently, reconnect only when necessary, and avoid holding connections open when no data needs to be sent.</p>
<p>Scaling Bluetooth systems makes these power decisions even more important. When you have one device, wasting a bit of energy doesn’t matter. When you have hundreds of devices, each one burning just a few extra milliwatts, the total waste adds up quickly. Power efficiency becomes the difference between a network that runs for months and one that collapses after a week.</p>
<p>The golden rule of power tuning is simple: talk less, talk smarter. A Bluetooth device that knows when to speak and when to stay quiet can scale beautifully, even in large networks. It’s not about being fast all the time, it’s about being clever with timing.</p>
<p>In the next section, we’ll look at how these devices join your network in the first place and what happens when you need to update their software later. Because once your system scales, you’re not just connecting devices, you’re managing an entire population.</p>
<h2 id="heading-provisioning-and-firmware-updates-welcome-to-device-kindergarten">Provisioning and Firmware Updates — Welcome to Device Kindergarten</h2>
<p>Imagine setting up one Bluetooth device. It’s easy: you pair it, give it a name, and maybe tweak a few settings. Now imagine doing that a hundred times. Or a thousand. Suddenly, what felt like a simple task starts to look like a factory assembly line powered by frustration. That’s where <strong>provisioning</strong> comes in, the process of onboarding new devices into your Bluetooth network so they can start working right away, without manual babysitting.</p>
<p>Provisioning is like a first day at school for your devices. Each new student needs to be identified, assigned to a class, and given a name tag. In the Bluetooth world, a newly manufactured device begins life in an “unprovisioned” state. It doesn’t belong to any network yet, so it advertises with a special signal that says, “Hey, I’m new here.” When your mobile app or gateway spots that advertisement, it can connect, authenticate the device, and hand over the credentials it needs to join the system.</p>
<p>The app usually performs a few key steps during provisioning. It verifies that the device is genuine, assigns it a unique identifier, and exchanges security keys so future connections can happen securely. It might also store metadata like which room the sensor belongs to or what type of data it will report. After provisioning, the device switches to its normal operation mode, where it advertises with its new identity and starts behaving like a member of the family.</p>
<p>When you have just one or two devices, you can do all this manually. But when you scale up to hundreds or thousands, manual setup becomes impossible. That’s when you start thinking about automation, QR codes on packaging, NFC tags for instant pairing, or out-of-band provisioning where a separate channel (like Wi-Fi or a wired link) handles secure onboarding. The goal is to make provisioning quick, repeatable, and error-free, even when your factory or users are adding new devices by the dozens.</p>
<p>Once your devices are out in the world, the next challenge appears: <strong>firmware updates</strong>. Every system eventually needs to fix bugs, patch security holes, or add new features. For Bluetooth devices, this means pushing new firmware over the same wireless link, a process known as <strong>FOTA</strong>, or firmware-over-the-air updates.</p>
<p>Updating firmware over Bluetooth can be nerve-wracking. The connection is relatively slow, and interruptions can leave a device half-updated and confused about who it is. Good update systems handle this carefully. They divide the firmware into chunks, verify each piece with checksums, and only switch to the new version once the whole update has been safely received and validated. If anything fails midway, the device rolls back to the old firmware instead of bricking itself.</p>
<p>Scaling makes this even more complex. Updating ten devices is fine. Updating a thousand can overwhelm your network if you try to do them all at once. Smart systems stagger the updates in waves, track which devices have finished, and retry the ones that didn’t. Some even let devices report their status back to a central dashboard, so you can see which ones are ready and which ones are still stuck halfway through.</p>
<p>Provisioning and firmware updates might not sound glamorous, but they’re the backbone of every scalable Bluetooth system. Without smooth onboarding and reliable updates, your network slowly falls apart as devices drift out of sync or miss critical fixes.</p>
<p>Think of it this way: provisioning is how devices <em>join the family</em>, and firmware updates are how they <em>grow up</em>. Both are essential if you want your Bluetooth ecosystem to stay healthy and dependable over time.</p>
<p>In the next section, we’ll talk about what happens when something inevitably goes wrong, how to debug and monitor a network full of devices without losing your mind.</p>
<h2 id="heading-debugging-monitoring-and-testing-across-platforms">Debugging, Monitoring, and Testing Across Platforms</h2>
<p>At some point, every Bluetooth developer faces the same moment of quiet despair. The logs look fine, the devices are paired, the code hasn’t changed, and yet… nothing works. Connections fail, packets vanish, and everything that worked yesterday now refuses to cooperate. Welcome to the wonderful, mysterious world of Bluetooth debugging, a place where logic takes a vacation and patience becomes your most valuable skill.</p>
<p>Debugging Bluetooth is tricky because so much of it happens invisibly. The data is flying through the air, hopping between frequencies dozens of times per second, and all you can see is whether the connection succeeds or fails. It’s like trying to diagnose a conversation between two people whispering in another room. You can tell they’re talking, but not what they’re saying.</p>
<p>The first rule of Bluetooth debugging is simple: <strong>log everything</strong>. Log when you start scanning, when you find a device, when you connect, and when you disconnect. Log the signal strength, the UUIDs you discover, the number of bytes you read, and the time it took. Bluetooth problems rarely announce themselves loudly, they hide in tiny details. A small delay in a callback or a missing acknowledgment can reveal exactly why your system seems haunted.</p>
<p>Different platforms give you different kinds of help. Android, for example, offers detailed Bluetooth logs through developer options or tools like <code>adb</code>. You can capture the raw Bluetooth HCI logs and analyze them later to see what really happened under the hood. iOS, on the other hand, gives you less direct visibility. Apple handles most of the Bluetooth stack internally, so your only clues come from Core Bluetooth callbacks. Embedded devices often let you log directly from the firmware, showing connection events, error codes, and sometimes even packet-level information if the stack supports it.</p>
<p>Testing across platforms is just as important as debugging. You can’t assume that if it works on one phone, it will work on another. Android devices, especially, have a habit of interpreting Bluetooth timing slightly differently. A system that’s rock-solid on a Pixel may stutter on a Samsung or freeze on a low-cost tablet. The only cure is diversity, test on multiple brands, OS versions, and firmware builds until you’re confident the system behaves everywhere.</p>
<p>For embedded devices, testing is a different challenge. Because they often run continuously, you need long-term endurance tests to catch issues that only appear after hours or days of operation. You might discover that a connection fails only after 300 reconnections, or that a memory leak appears after a week of normal use. Building test rigs that automate these scenarios: connecting, disconnecting, and verifying data repeatedly, is a huge time saver.</p>
<p>Monitoring is what happens after you’ve deployed your devices into the real world. It’s like keeping a health tracker on your entire Bluetooth network. Your mobile apps or gateways can collect statistics such as signal strength, connection failures, uptime, and battery levels. That data tells you which devices are performing well and which ones might be drifting toward trouble.</p>
<p>Adding this kind of visibility pays off enormously at scale. When you’re managing hundreds of devices, it’s impossible to check each one manually. Instead, you rely on trends, for example, if one location shows consistently weak signal strength, maybe there’s interference nearby. If multiple devices drop connections at the same time, maybe the central device needs a firmware update. Monitoring transforms guesswork into insight.</p>
<p>The truth is, debugging and monitoring never really end. Even after your system is stable, new versions of Android and iOS will appear with small Bluetooth changes that break something you didn’t know could break. Treat Bluetooth maintenance like car maintenance: routine, ongoing, and essential.</p>
<p>Once you learn to capture good logs, read them calmly, and build systems that report their own health, debugging stops being a nightmare and becomes a science. Bluetooth may always be a little mysterious, but with the right tools and attitude, you can keep the ghosts out of your connection list.</p>
<p>In the next section, we’ll put everything together with a real-world example of what scaling Bluetooth actually looks like when all the pieces: mobile apps, embedded devices, and architecture, finally work in harmony.</p>
<h2 id="heading-real-world-architecture-example-when-bluetooth-finally-behaves">Real-World Architecture Example — When Bluetooth Finally Behaves</h2>
<p>Let’s take everything we’ve talked about and bring it to life with a real-world scenario. Imagine you’re building a smart factory system with hundreds of Bluetooth sensors scattered across the floor. Each sensor measures temperature, vibration, or humidity. Some are attached to machines, others hang on walls, and a few are hidden in places even the janitor doesn’t know about. Your goal is simple on paper: collect data from all these sensors, send it to a central dashboard, and keep everything running smoothly.</p>
<p>The reality, of course, is much more complicated. Each sensor is an embedded device powered by a coin-cell battery that has to last for months. They advertise periodically to announce they’re alive. Your Android or iOS tablets, placed around the factory as gateways, act as Bluetooth centrals. Their job is to scan, connect to nearby sensors, read data, and upload it to the cloud. It sounds straightforward, but you’re juggling dozens of invisible connections at once, and they all have different moods.</p>
<p>The architecture begins with careful planning. Each gateway tablet knows which part of the factory it’s responsible for. That way, you avoid overcrowding the airwaves with multiple devices trying to connect to the same sensors. The sensors use slightly staggered advertising intervals so they don’t all shout at the same time. The gateways maintain a queue, connecting to a few sensors at a time, reading data, and then disconnecting before moving on to the next group. This rotation keeps everything balanced and prevents Bluetooth traffic jams.</p>
<p>Power management is built into every step. Each sensor wakes up, advertises briefly, sends its data when connected, and goes right back to sleep. The connection interval and MTU size are tuned for efficiency, large enough for smooth data transfer, but not so large that slower devices choke. Every byte is treated like gold because every transmission costs energy.</p>
<p>The gateways handle the messy parts: reconnections, retries, and data aggregation. They buffer readings in case the Wi-Fi link to the cloud goes down and sync later when it’s back. They also monitor each sensor’s signal strength, battery level, and uptime. If a sensor hasn’t reported in a while, the system flags it automatically so a technician can check on it.</p>
<p>Now imagine scaling this setup to multiple factory buildings. Suddenly, you’re managing thousands of sensors, dozens of gateways, and countless wireless interactions. At this scale, the design choices you made early, abstracted Bluetooth logic, retry mechanisms, power optimization, and logging, are the difference between a quiet, self-running network and a system that collapses into constant reconnections.</p>
<p>When everything works as intended, something beautiful happens. The sensors collect data silently. The gateways synchronize automatically. The dashboards stay green. Nobody has to restart anything, and Bluetooth quietly fades into the background where it belongs. It’s the rare moment when technology stops demanding attention and simply does its job.</p>
<p>This kind of architecture isn’t science fiction. Companies use it in factories, hospitals, and warehouses every day. From smart lighting systems to patient monitors, Bluetooth at scale can be astonishingly reliable, but only if you treat it like a distributed system, not a single gadget. Each device is a citizen of a larger ecosystem, and your job as the architect is to keep that ecosystem healthy.</p>
<p>The biggest takeaway is that success doesn’t come from fancy algorithms or expensive hardware. It comes from the small, deliberate decisions that make your system resilient: how you handle disconnections, how you schedule connections, how you monitor performance. Scaling Bluetooth is not about avoiding problems, it’s about designing a system that recovers gracefully when problems happen.</p>
<p>In the next section, we’ll wrap up everything we’ve learned into a practical checklist, a simple guide you can use whenever you’re designing a Bluetooth system that has to survive in the wild.</p>
<h2 id="heading-checklist-building-a-truly-scalable-bluetooth-system">Checklist — Building a Truly Scalable Bluetooth System</h2>
<p>By now, you’ve seen Bluetooth in all its moods, charming, confusing, unpredictable, and surprisingly capable when handled with care. So how do you actually put everything together? What makes a Bluetooth system <em>scalable</em> instead of just “working on my desk”? The answer isn’t a single trick or secret API. It’s a mindset, a way of designing your system to expect chaos and still function gracefully when it happens.</p>
<p>The first part of that mindset is consistency. Every Bluetooth system should have one clear and stable way of communicating. Keep your data formats simple, your GATT profiles predictable, and your naming conventions sensible. If you have ten devices made by ten different vendors, make them all speak the same language. The moment one device starts improvising, the whole orchestra sounds off.</p>
<p>Next comes patience, and in Bluetooth, patience means retries. Connections drop. Devices go out of range. A phone might go to sleep or decide that scanning is no longer fashionable. Instead of treating every disconnection as a crisis, treat it as part of the process. A good Bluetooth app quietly retries in the background, restores the connection, and carries on as if nothing happened. To the user, it feels seamless. Underneath, it’s a flurry of logic keeping the experience smooth.</p>
<p>Then there’s the question of power. Remember that every advertisement and connection eats into battery life. A scalable Bluetooth system doesn’t talk all the time, it talks <em>smart</em>. It plans when to wake up, when to exchange data, and when to stay silent. Devices that last longer need fewer replacements, fewer updates, and far less human attention. Power efficiency is the hidden currency of scalability.</p>
<p>Monitoring is another essential habit. If you can’t see what’s happening inside your system, you’re flying blind. Log your connections, track your signal strengths, record how often devices drop out, and visualize it somewhere. A simple dashboard that shows which devices are healthy and which ones are struggling can save you countless hours later. When you scale, visibility turns guesswork into control.</p>
<p>Security, too, can’t be an afterthought. Use secure pairing, proper encryption, and rotating addresses. The bigger your system gets, the more interesting it becomes to people who might want to peek at it. Make sure they can’t. A secure Bluetooth network doesn’t just protect users, it protects your reputation.</p>
<p>Finally, build for change. Bluetooth isn’t static, Android and iOS update their stacks every year, chip vendors release new firmware, and new security standards appear. A scalable system doesn’t break when something changes, it adapts. That’s why abstraction layers, modular code, and updatable firmware matter so much. They keep your system flexible long after the first version ships.</p>
<p>If you do all of this, keep it consistent, patient, efficient, observable, secure, and adaptable, something magical happens. Your Bluetooth system starts to feel less like a fragile web of devices and more like a living network. It keeps running, keeps healing, and quietly gets the job done without constant supervision. That’s when you know you’ve built something that scales.</p>
<p>In the final section, we’ll step back and reflect on the bigger picture, what scaling Bluetooth really teaches us about building technology that has to work not just once, but over and over again in the messy, beautiful real world.</p>
<h2 id="heading-wrap-up-lessons-from-the-field">Wrap-Up — Lessons from the Field</h2>
<p>If you’ve made it this far, you’ve probably realized that scaling Bluetooth isn’t really about Bluetooth at all. It’s about learning how complex systems behave when they leave the comfort of your desk and enter the real world. It’s about understanding that wireless connections are not just electrical signals, they’re relationships between unpredictable, battery-powered, opinionated little machines.</p>
<p>Bluetooth gets a bad reputation because people expect it to be simple. They imagine it’s like Wi-Fi or USB, plug and play, pair and forget. But in truth, Bluetooth is more like a polite conversation at a crowded party. Everyone is talking at the same time, the music is loud, and you have to keep repeating yourself until the other person hears you correctly. When you think of it that way, it’s a miracle that it works as well as it does.</p>
<p>Scaling Bluetooth across Android, iOS, and embedded devices teaches you humility. You stop assuming things will always behave, and instead you start building systems that <em>recover</em> when they don’t. You learn that error handling is not an afterthought, it’s the main event. You discover that batteries are precious, timing is everything, and the smallest design decisions can ripple through an entire ecosystem of devices.</p>
<p>You also start to appreciate the quiet beauty of resilience. There’s something deeply satisfying about watching dozens of sensors, gateways, and phones connect, share data, and disconnect, all without human intervention. When it works, it feels effortless. You forget about the retries, the power cycles, the reconnections, and the debugging sessions that made it possible. All you see is a smooth network humming quietly in the background, doing exactly what it was meant to do.</p>
<p>And that’s the real magic of Bluetooth, not the flashy tech demos or the pairing animations, but the invisible collaboration that happens beneath the surface. It’s the heartbeat of every wearable, every sensor, every tiny device that quietly makes our lives a little easier. Scaling it isn’t just an engineering challenge; it’s a lesson in patience, design, and empathy for systems that can’t always speak for themselves.</p>
<p>So, the next time your Bluetooth device disconnects, take a breath. Somewhere in the chaos, it’s just trying to reconnect, to find its partner again and pick up where it left off. Because deep down, that’s what Bluetooth really is: a network built on trust, persistence, and tiny packets of hope flying through the air.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The State of Bluetooth in 2025: What’s New, What’s Possible, and How to Use It ]]>
                </title>
                <description>
                    <![CDATA[ Introduction: Why Bluetooth Still Matters You probably don’t even think about Bluetooth anymore. It’s just there, quietly doing its job every single day. It’s what keeps your earbuds connected, your smartwatch synced, your car infotainment system tal... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-state-of-bluetooth-whats-new-whats-possible-and-how-to-use-it/</link>
                <guid isPermaLink="false">690e2801500cb51e735b5a9c</guid>
                
                    <category>
                        <![CDATA[ bluetooth ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Bluetooth Low Energy ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ connectivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MathJax ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Nikheel Vishwas Savant ]]>
                </dc:creator>
                <pubDate>Fri, 07 Nov 2025 17:10:25 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762533537259/3f9dec8a-690b-4fd8-a0a7-8e6b2667e55c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-introduction-why-bluetooth-still-matters">Introduction: Why Bluetooth Still Matters</h2>
<p>You probably don’t even think about Bluetooth anymore. It’s just there, quietly doing its job every single day. It’s what keeps your earbuds connected, your smartwatch synced, your car infotainment system talking to your phone, and your warehouse sensors awake and reporting.</p>
<p>The funny thing is, while most of us stopped paying attention, Bluetooth never stopped evolving. It just kept getting smarter.</p>
<p>Now it’s 2025, and Bluetooth has grown into something much bigger than a way to stream music. It has become a core ecosystem that connects nearly everything around us. From audio gear and IoT sensors to industrial automation and secure building access, Bluetooth is everywhere.</p>
<p>The newest versions, Bluetooth 5.4 and 6.0, completely redefine how devices talk to each other. We’re talking about encrypted broadcasts, smarter advertising, centimeter-level distance tracking, and a level of scalability that feels closer to magic than engineering.</p>
<p>In this article, we’ll take a tour through the newest Bluetooth technologies and see what’s happening under the hood. You’ll get a feel for what’s new, how these features work in real projects, and how developers can actually take advantage of them.</p>
<p>Grab your favorite dev board, and let’s dive in.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-the-evolution-from-classic-to-low-energy-to-60">The Evolution: From Classic to Low Energy to 6.0</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-deep-dive-technical-enhancements">Deep Dive: Technical Enhancements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-applications-in-2025">Real-World Applications in 2025</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-developer-guide-getting-started">Developer Guide: Getting Started</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-challenges-and-trade-offs">Challenges and Trade-Offs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-road-ahead-bluetooth-61-and-beyond">The Road Ahead: Bluetooth 6.1 and Beyond</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-the-evolution-from-classic-to-low-energy-to-60">The Evolution — From Classic to Low Energy to 6.0</h2>
<p>If you’ve been around Bluetooth for a while, you probably remember the early days when pairing a headset felt like solving a riddle. Back then, Bluetooth Classic ruled the scene, focused mainly on short-range audio and simple data links. Over the years, though, the story changed completely.</p>
<p>Today, Bluetooth has transformed from a simple cable-replacement protocol into a flexible framework for everything from earbuds to industrial robots. Each new version added fresh layers of intelligence, speed, and energy efficiency. The table below gives a quick timeline of how that evolution unfolded.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Version</strong></td><td><strong>Year</strong></td><td><strong>Key Features</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>2.0 + EDR</strong></td><td>2004</td><td>Faster data rate (3 Mbps)</td></tr>
<tr>
<td><strong>4.0</strong></td><td>2010</td><td>BLE introduced for low power</td></tr>
<tr>
<td><strong>5.0</strong></td><td>2016</td><td>2× speed, 4× range, 8× advertising capacity</td></tr>
<tr>
<td><strong>5.1</strong></td><td>2019</td><td>Direction Finding (AoA/AoD)</td></tr>
<tr>
<td><strong>5.2</strong></td><td>2020</td><td>LE Audio / Isochronous Channels</td></tr>
<tr>
<td><strong>5.3 – 5.4</strong></td><td>2021-2023</td><td>Encrypted Advertising, PAwR</td></tr>
<tr>
<td><strong>6.0</strong></td><td>2024</td><td>Channel Sounding, Decision-Based Filtering</td></tr>
<tr>
<td><strong>6.1</strong></td><td>2025</td><td>Minor updates on efficiency &amp; range</td></tr>
</tbody>
</table>
</div><p>The journey tells a bigger story. What started as a way to connect two devices for audio has turned into a foundation for massive IoT networks. Each revision introduced smarter physical layers, better energy profiles, and new roles for devices that once had very limited capability.</p>
<p><img src="https://www.mdpi.com/sensors/sensors-25-00996/article_deploy/html/images/sensors-25-00996-g003.png" alt="Sensors 25 00996 g003" width="600" height="400" loading="lazy"></p>
<p><em>Source: MDPI Sensors (2025), Bluetooth Core Specification Summary.</em></p>
<p>Above figure provides a visual snapshot of how Bluetooth has evolved across its major versions. It shows a clear chronological progression of features—from the launch of Bluetooth Low Energy (BLE) in version 4.0, to the introduction of secure connections, long-range PHYs, and direction-finding capabilities, all the way up to the latest breakthroughs like Channel Sounding and decision-based filtering in Bluetooth 6.0. The color-coded timeline highlights how each version refined both the physical and logical layers of communication, gradually expanding Bluetooth’s reach from simple peripherals to high-precision industrial and spatial applications. In essence, it maps Bluetooth’s transformation from a short-range wireless cable into a sophisticated, context-aware connectivity fabric that underpins modern audio, IoT, and automation ecosystems.</p>
<p>If you zoom out a bit, you’ll notice a clear pattern: Bluetooth keeps finding new neighborhoods to move into. From cars and headphones to factories and hospitals, the technology now feels less like a cable replacement and more like an invisible nervous system for the modern world.</p>
<h2 id="heading-whats-new-in-bluetooth-54-and-60">What’s New in Bluetooth 5.4 and 6.0</h2>
<p>When you hear that Bluetooth has a “new version,” it’s easy to shrug it off. After all, your headphones already work, right? But the jump from 5.3 to 5.4 and then 6.0 isn’t just a tiny step. It’s more like Bluetooth quietly taking on Wi-Fi’s job in certain places and pulling it off surprisingly well.</p>
<p>Let’s break it down by version so it’s easier to see what’s going on.</p>
<h3 id="heading-bluetooth-54-building-the-iot-backbone"><strong>Bluetooth 5.4: Building the IoT Backbone</strong></h3>
<p>This release might not have made flashy headlines, but engineers loved it. It focuses on letting thousands of low-power devices talk to a single gateway without choking the airwaves.</p>
<p>Let’s look at some of the key features and why they matter:</p>
<h4 id="heading-periodic-advertising-with-responses-pawr">Periodic Advertising with Responses (PAwR)</h4>
<p>Think of it as Bluetooth’s group chat for sensors. Devices can broadcast messages and still get short replies, all without the full connection setup that usually drains batteries. It’s perfect for large sensor networks like smart warehouses or retail stores with electronic shelf labels.</p>
<p><img src="https://devzone.nordicsemi.com/resized-image/__size/1296x466/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-28/7607.pastedimage1698068932789v3.png" alt="Periodic Advertising with Responses (PAwR): A practical guide - Software -  nRF Connect SDK guides - Nordic DevZone" width="600" height="400" loading="lazy"></p>
<p>Source: Nordic Semiconductor Developer Zone (2024)</p>
<p>Above diagram illustrates the timing structure of Bluetooth 5.4’s Periodic Advertising with Responses (PAwR) mechanism. Along the horizontal axis, it shows a repeating sequence of PAwR events separated by the overall <em>periodic advertising interval</em>. Within each PAwR event are several <em>subevents</em>—labeled #0, #1, #2, #3, and so on—each representing a defined window of time during which specific sensors or devices are allowed to communicate. The figure highlights that every subevent occurs at a fixed <em>periodic advertising subevent interval</em>, meaning devices can wake up only during their assigned slot, transmit or receive data, and then return to sleep. This predictable scheduling dramatically reduces radio collisions and power consumption, allowing a single gateway to coordinate thousands of low-power nodes such as electronic shelf labels or environmental sensors within a shared advertising cycle.</p>
<h4 id="heading-encrypted-advertising-data">Encrypted Advertising Data</h4>
<p>Broadcasts used to be open for anyone to sniff. Now they can be private and secure, which is essential for medical monitors and retail beacons carrying sensitive info.</p>
<p><img src="https://www.raytac.com/upload/news_m/ceac2577d996eda7e0197ec0ff7be7c8.png" alt="Raytac Corporation 勁達國際電子股份有限公司" width="600" height="400" loading="lazy"></p>
<p>Source: Raytac Technology (2024)</p>
<p>Above diagram breaks down the structure of the <strong>Encrypted Data Advertising Data (AD) type</strong> introduced in Bluetooth 5.4. It visually shows how encrypted advertising payloads are organized within a broadcast packet. At the top, the full advertising payload is represented, which includes the length (Len), Encrypted Data (ED Tag), and flags. Inside the encrypted section, the fields are expanded to show the <strong>Randomizer</strong>, <strong>Payload</strong>, and <strong>Message Integrity Check (MIC)</strong>. The payload itself may contain various elements such as the <strong>Electronic Shelf Label (ESL) Tag</strong>, <strong>ESL Payload</strong>, <strong>Local Name (LN Tag)</strong>, or other advertising segments. The color-coding differentiates which parts are encrypted (blue) versus unencrypted (gray or yellow), highlighting how Bluetooth 5.4 secures sensitive data while retaining key advertising identifiers for discovery. This layout helps engineers understand where encryption is applied within the advertising packet and how privacy and integrity are preserved during broadcast communication.</p>
<h4 id="heading-electronic-shelf-labels-esl-support">Electronic Shelf Labels (ESL) Support</h4>
<p>Bluetooth 5.4 was practically written with supermarkets in mind. Imagine thousands of digital price tags blinking updates at once, all running for months on coin-cell batteries.</p>
<p><img src="https://www.danidatasystems.com/wp-content/uploads/2023/10/ESL-work.jpg" alt="Electronic Shelf Label - Dani Data Systems India Pvt. Ltd." width="600" height="400" loading="lazy"></p>
<p>Source: Dani Data Systems (2023)</p>
<p>Above image illustrates the working architecture of a Bluetooth-based <strong>Electronic Shelf Label (ESL)</strong> system. On the left, a computer running ESL management software is shown, which allows retail staff to configure product data, prices, and display templates. The software communicates over a TCP/IP network connection with a <strong>Base Station</strong> positioned in the center of the diagram. This base station acts as a Bluetooth gateway, wirelessly transmitting the updated price and product information to numerous shelf labels throughout the store. On the right, a digital ESL display is shown featuring a price tag for a product labeled “Kaju Katali,” complete with product details, QR codes for mobile payments, and expiry dates. The blue wireless icon between the base station and ESL tag symbolizes Bluetooth communication. Together, the components demonstrate how Bluetooth 5.4 enables synchronized, low-power, and remotely managed price updates across thousands of retail shelf labels.</p>
<p>In short, 5.4 was the version that said, “Sure, we can handle massive IoT networks.”</p>
<h3 id="heading-bluetooth-60-the-game-changer"><strong>Bluetooth 6.0: The Game Changer</strong></h3>
<p>Bluetooth 6.0 feels like the point where the technology matured from “just wireless” into “smart wireless.” This version brings features that start blurring the line between Bluetooth and more advanced location systems.</p>
<h4 id="heading-channel-sounding">Channel Sounding</h4>
<p>This is a big one. Instead of using signal strength (which can be messy), Bluetooth 6.0 measures phase differences in radio waves to calculate distance. That means centimeter-level accuracy (enough for digital keys), precise tracking, and even AR interactions.</p>
<p><img src="https://amaldev.blog/wp-content/uploads/2025/01/BLEChannelSounding.png" alt="TechExplained: Bluetooth Channel Sounding - The Tech Blog" width="600" height="400" loading="lazy"></p>
<p>Source: Bluetooth SIG (2025)</p>
<p>Above image explains the concept of <strong>Bluetooth Channel Sounding</strong>, a new feature introduced in Bluetooth 6.0 that enables precise distance measurement between devices. The top half of the diagram compares three levels of spatial awareness—presence detection through advertising, coarse distance estimation using RSSI (Received Signal Strength Indicator), and fine-grained ranging achieved with Channel Sounding. It also shows how Direction Finding complements these methods by determining angular orientation. On the left, a smartphone (the initiator) communicates with a smart lock (the reflector), demonstrating how Bluetooth can estimate distance and direction simultaneously. The bottom portion visualizes two measurement techniques. The <strong>Phase-Based Ranging</strong> chart shows how two signals of different frequencies experience measurable phase shifts that correspond to distance. The <strong>Round Trip Time (RTT)</strong> diagram on the right depicts packets traveling between the initiator and reflector, with the elapsed time between transmission and reception used to calculate distance. Together, these visuals illustrate how Bluetooth 6.0 achieves centimeter-level accuracy for applications like digital keys, indoor navigation, and spatially aware IoT systems.</p>
<h4 id="heading-decision-based-advertising-filtering">Decision-Based Advertising Filtering</h4>
<p>Bluetooth devices now decide which advertisements to process and which to ignore, saving both power and bandwidth. It’s like teaching scanners to pay attention only when it’s worth it.</p>
<p><img src="https://www.bluetooth.com/wp-content/uploads/2024/08/Bluetooth_Core_6_Figure_11.png" alt="Bluetooth_Core_6_Figure_11" width="600" height="400" loading="lazy"></p>
<p>Source: Bluetooth SIG (2024)</p>
<p>Above diagram illustrates the architecture of <strong>Decision-Based Advertising Filtering</strong>, a new Bluetooth 6.0 feature that allows observers to process only relevant broadcast packets, reducing power consumption and unnecessary data handling. The figure depicts two parallel host–controller stacks: the <strong>Observer</strong> on the left and the <strong>Advertiser</strong> on the right. Each side includes an Application layer, Host Controller Interface (HCI), and Controller. On the advertiser side, the application generates <strong>Decision Data</strong> that passes through the HCI to the controller’s advertising engine, where it’s embedded into extended advertising packets known as <em>Decision PDUs</em>. On the observer side, incoming advertising data passes through a <strong>Filter Policy</strong> module in the controller, which selects or rejects packets according to preconfigured decision criteria before forwarding only the relevant <strong>Advertising Reports</strong> to the host application. Blue arrows show configuration and report flows, while the yellow HCI bands highlight the host–controller boundary. Together, the components show how Bluetooth 6.0 empowers devices to make intelligent, context-aware filtering decisions at the controller level, improving efficiency in dense radio environments.</p>
<h4 id="heading-advertiser-monitoring">Advertiser Monitoring</h4>
<p>Gateways can now keep tabs on the state of nearby advertisers, which is critical when hundreds of devices are broadcasting at once.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762412492836/223de7c4-c659-4c43-8514-8a505070a129.png" alt="223de7c4-c659-4c43-8514-8a505070a129" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Source: Bluetooth SIG (2024)</p>
<p>Above image depicts the fundamental interaction between two Bluetooth Low Energy (BLE) device roles — <strong>advertising</strong> and <strong>scanning</strong>. On the left, a smartphone icon represents the scanning device, which actively listens for nearby Bluetooth broadcasts. On the right, a small sensor or tag icon represents the advertising device, periodically transmitting packets that announce its presence, capabilities, or data updates. Blue concentric rings radiate outward from both devices, symbolizing the propagation of radio signals and the overlapping wireless coverage area where scanning and advertising events intersect. The minimalist design highlights the asymmetric nature of BLE communication: the advertiser periodically transmits small bursts of information, while the scanner remains receptive to detect, filter, or connect with those broadcasts — forming the foundation of all Bluetooth discovery, pairing, and data exchange processes.</p>
<h4 id="heading-negotiable-inter-frame-spacing">Negotiable Inter-Frame Spacing</h4>
<p>This lets devices adjust timing between packets to improve throughput and avoid interference in noisy environments.</p>
<p><img src="https://www.bluetooth.com/wp-content/uploads/2024/08/Bluetooth_Core_6_Figure_26.png" alt="Bluetooth_Core_6_Figure_26" width="600" height="400" loading="lazy"></p>
<p>Source: Bluetooth SIG (2024)</p>
<p>Above image illustrates the concept of <strong>Negotiable Inter-Frame Spacing (IFS)</strong> in Bluetooth 6.0, which optimizes the timing between consecutive data packets to improve throughput and reduce interference. The diagram shows two sequences of communication between a <strong>Central (C)</strong> and a <strong>Peripheral (P)</strong> device, represented as alternating blue (C→P) and green (P→C) data blocks. In the first sequence, packets are transmitted with a short, fixed inter-frame spacing labeled <strong>T_IFS</strong>, showing a rapid exchange of packets within a connection event. The second sequence demonstrates the enhanced Bluetooth 6.0 model, where devices can dynamically negotiate a longer spacing interval — indicated by the notation “≥ T_IFS” — to accommodate environmental conditions, controller processing delays, or congestion. The red horizontal arrows mark the overall connection event duration, while the vertical lines represent packet boundaries. By allowing flexible timing adjustments between frames, Bluetooth 6.0 reduces airtime collisions and improves coexistence with other 2.4 GHz systems, particularly in dense or interference-prone environments.</p>
<h4 id="heading-isoal-enhancements">ISOAL Enhancements</h4>
<p>Audio data, especially LE Audio streams, now move more smoothly thanks to improved support for large frames.</p>
<p><img src="https://www.bluetooth.com/wp-content/uploads/2024/08/Bluetooth_Core_6_Figure_22.png" alt="Bluetooth_Core_6_Figure_22" width="600" height="400" loading="lazy"></p>
<p>Source: Bluetooth SIG (2024)</p>
<p>Above diagram illustrates the internal data flow and timing structure of the <strong>Isochronous Adaptation Layer (ISOAL)</strong> in Bluetooth 5.2 and later, which supports synchronized audio and data transmission over LE Isochronous Channels. The figure is divided into three main sections: the <strong>Upper Layer</strong>, the <strong>ISOAL</strong>, and the <strong>Link Layer</strong>. At the top, the Upper Layer handles isochronous data in the form of Service Data Units (SDUs). Within the ISOAL layer, SDUs undergo several key processes — <strong>Fragmentation</strong> and <strong>Segmentation</strong> break data into smaller protocol units, while <strong>Recombination</strong> and <strong>Reassembly</strong> merge received fragments back into complete SDUs. Two important timing-related steps occur in parallel: the <strong>Inclusion of Timing Offsets</strong>, which ensures proper packet scheduling, and <strong>Timing Reconstruction</strong>, which synchronizes the playback or reassembly timing for received streams. These operations produce either <strong>Framed</strong> or <strong>Unframed Protocol Data Units (PDUs)</strong>, which are then passed to the <strong>Link Layer</strong> at the bottom for transmission over the <strong>Isochronous Stream</strong>. The diagram highlights how ISOAL bridges the upper and lower layers, managing timing alignment and packet structure to deliver low-latency, synchronized LE Audio or data streams across multiple devices.</p>
<p>When you put all that together, Bluetooth 6.0 starts looking a lot like Ultra-Wideband in terms of precision, but without needing new hardware. It’s faster, smarter, and somehow more polite on the airwaves.</p>
<h2 id="heading-deep-dive-technical-enhancements">Deep Dive — Technical Enhancements</h2>
<p>This is where Bluetooth starts to feel less like “a thing your phone just does” and more like a finely tuned machine. The new specs add layers of intelligence that make devices more aware of distance, timing, and context. It’s the kind of stuff that gets engineers grinning because it solves problems we’ve all quietly complained about for years.</p>
<p>Let’s walk through a few of the most important ones.</p>
<h3 id="heading-channel-sounding-and-distance-awareness">Channel Sounding and Distance Awareness</h3>
<p>If you’ve ever used RSSI values to guess how far a device is, you know how unpredictable it can be. RSSI measures how strong the signal sounds, not where it actually came from. A wall, a metal shelf, even a human body can distort it. Channel Sounding solves this by looking at <em>phase</em> instead of strength.</p>
<p>Here’s the idea: two devices exchange carefully crafted packets at multiple frequencies. Each frequency behaves like a different musical note. When those notes reach the receiver, their phases – how the peaks and troughs line up – shift slightly depending on distance. The receiver compares the original and received phases, then crunches the math:</p>
<p>$$[ \text{Distance} = \frac{c \times \Delta \phi}{2\pi f} ]$$</p><p>where:</p>
<ul>
<li><p>( c ) is the speed of light,</p>
</li>
<li><p>( \Delta \phi ) is the phase shift,</p>
</li>
<li><p>( f ) is the carrier frequency.</p>
</li>
</ul>
<p>This approach allows for precise distance measurement, achieving accuracy down to a few centimeters by analyzing the phase differences of signals received at multiple frequencies.</p>
<p>That level of precision changes the game. Cars can unlock automatically only when you’re physically beside the door. Smart-building systems can tell which room you’re standing in. Mixed-reality headsets can map your movements without extra sensors.</p>
<p>From a development point of view, you’ll need hardware that supports the new Channel Sounding PHY. Nordic’s nRF54 and Silicon Labs’ BG24 families already expose low-level APIs for it. Expect to work closer to the metal than usual: calibration, antenna diversity, and clock stability all affect measurement accuracy. It’s worth the effort, though. Few wireless technologies can deliver this precision without expensive dedicated hardware.</p>
<h3 id="heading-periodic-advertising-with-responses-pawr-1">Periodic Advertising with Responses (PAwR)</h3>
<p>For years, BLE advertising worked like shouting into a room and hoping someone heard you. The moment you wanted a reply, you had to form a full connection. That model doesn’t scale when you have ten-thousand tiny sensors that each wake up once a minute.</p>
<p>PAwR flips the model. Think of it as a scheduled town-hall meeting. A coordinator (the gateway) broadcasts a timeline. Each sensor has a reserved time slot to respond within that cycle. Because everyone speaks only during their assigned moment, collisions disappear and energy use plummets.</p>
<p>In practice, this lets one gateway handle tens of thousands of devices without ever maintaining individual connections. Supermarkets use it for electronic shelf labels that update prices in seconds. Factories deploy it for environmental sensors that report temperature and vibration periodically.</p>
<p>Developers integrating PAwR will notice that it doesn’t replace connections, it complements them. You can still open a full GATT session for configuration, but routine data flows through lightweight PAwR exchanges. Most modern SDKs, including Zephyr and ESP-IDF, now include PAwR APIs under their extended-advertising modules.</p>
<h3 id="heading-isochronous-audio-channels-amp-le-audio">Isochronous Audio Channels &amp; LE Audio</h3>
<p>Bluetooth’s original audio stack wasn’t built for what we expect today. It was designed for single-stream mono headsets, not for multi-earbud synchronized audio or broadcast systems. Isochronous Channels fix that by ensuring that every packet in a group shares the same clock reference.</p>
<p>Two modes exist:</p>
<ul>
<li><p><strong>Connected ISO Streams (CIS)</strong> handle one-to-one cases like stereo earbuds</p>
</li>
<li><p><strong>Broadcast ISO Streams (BIS)</strong> allow a transmitter to serve an unlimited audience, such as a gym or theater.</p>
</li>
</ul>
<p>Both rely on the <strong>LC3 codec</strong>, which delivers near-lossless sound at roughly half the bandwidth of SBC.</p>
<p>In real life, this means earbuds that stay perfectly in sync even if you walk between interference zones, hearing aids that seamlessly share the same stream, and venues that broadcast announcements directly to phones without dedicated receivers. Android 14 and iOS 17 have already exposed system-level LE Audio support, so app developers can finally build end-user experiences without vendor-specific hacks.</p>
<p>For embedded engineers, implementing LE Audio requires controller firmware that supports ISOAL (Isochronous Adaptation Layer) and host-side stack integration. Nordic, Qualcomm, and Dialog all provide reference implementations, but testing is key – timing drift between links can break audio quality faster than you might expect.</p>
<h3 id="heading-power-amp-efficiency-improvements">Power &amp; Efficiency Improvements</h3>
<p>Battery life has always been Bluetooth’s quiet superpower, and version 6.0 tightens the screws even more. Rather than one big change, it’s a collection of small ones that add up.</p>
<p>Negotiable inter-frame spacing lets devices adjust the delay between packets, smoothing out contention when the air is busy. Controllers now enter deeper sleep states automatically, waking only when the radio truly needs them. Smarter advertising filters prevent devices from wasting time processing duplicates, and new firmware offloads push repetitive tasks (like connection parameter updates) away from the CPU.</p>
<p>When engineers combine all these tricks, the numbers look impressive: about a ten to twenty percent battery gain in dense environments. That might not sound huge, but for a coin-cell tag meant to last three years, it’s the difference between hitting the spec or not.</p>
<h3 id="heading-security-amp-privacy-upgrades">Security &amp; Privacy Upgrades</h3>
<p>With great connectivity comes great responsibility. Bluetooth now sits at the heart of cars, locks, and health monitors, which makes security non-negotiable. The new stack finally treats it as a first-class citizen.</p>
<p>LE Secure Connections with numeric comparison are now standard, encrypted advertising data hides sensitive broadcasts, and Channel Sounding even enables distance-based access control. In plain language, a device can now verify that you’re physically nearby before sharing keys or unlocking features.</p>
<p>Still, protocol features alone aren’t enough. Developers should rotate identity-resolving keys regularly, invalidate old bonds on firmware updates, and avoid static passkeys. Security in Bluetooth is like security anywhere else: the spec provides the locks, but you’re responsible for turning the key.</p>
<p>Together, these improvements make Bluetooth feel more alive, more aware, and more efficient. The stack now senses distance, saves power, and defends privacy without breaking backward compatibility. It’s a quiet revolution hidden inside chips that most people never think about, yet it’s shaping how billions of devices will talk to each other over the next decade.</p>
<h2 id="heading-real-world-applications-in-2025">Real-World Applications in 2025</h2>
<p>It’s one thing to read about Channel Sounding or PAwR in a spec sheet. It’s another to see these features come alive in everyday products.</p>
<p>Bluetooth has quietly spread into nearly every corner of our lives, from the shelves of supermarkets to the dashboards of cars. By 2025, it’s no exaggeration to call it the most widely deployed wireless ecosystem on Earth.</p>
<p>Let’s look at where these new capabilities are already making an impact.</p>
<h3 id="heading-retail-electronic-shelf-labels-and-smart-inventory">Retail: Electronic Shelf Labels and Smart Inventory</h3>
<p>Walk into a modern supermarket in 2025 and look closely at the price tags. They aren’t paper anymore. Those little digital labels, changing prices in real time, are powered by Bluetooth 5.4’s <strong>Periodic Advertising with Responses (PAwR)</strong> and <strong>Encrypted Advertising Data</strong>.</p>
<p>Each label is a low-power sensor node, quietly listening for broadcast schedules from a gateway mounted above the aisle. When it’s their turn, the tags wake up, confirm their slot, and update the display – all in milliseconds and without forming a traditional Bluetooth connection. The result is a network of tens of thousands of nodes that consumes almost no energy.</p>
<p>Security matters here too. Encrypted advertising ensures that a competing store or curious shopper can’t sniff price data or inject bogus updates. Everything runs on coin-cell batteries that last several years, which saves retailers both time and maintenance costs.</p>
<h3 id="heading-smart-home-context-aware-unlocking-and-personal-audio">Smart Home: Context-Aware Unlocking and Personal Audio</h3>
<p>If you’ve ever fumbled with your phone to unlock a smart door, Bluetooth 6.0 might finally fix that. <strong>Channel Sounding</strong> makes proximity detection precise enough to trust. The system can tell whether you’re standing by the door or ten meters away in the driveway. Only when you’re truly within range does it trigger the unlock sequence.</p>
<p>The same precision is reshaping personal audio. Imagine walking from your living room to the kitchen and having your smart speaker hand off the song to your earbuds automatically. That’s <strong>LE Audio</strong> working behind the scenes with isochronous channels, keeping streams perfectly aligned across multiple endpoints. It feels invisible, which is exactly how good technology should feel.</p>
<h3 id="heading-healthcare-reliable-secure-patient-monitoring">Healthcare: Reliable, Secure Patient Monitoring</h3>
<p>Hospitals have long relied on wireless monitors, but interference and power limits made them tricky. With PAwR, a single access point can now coordinate thousands of small sensors that track vitals like heart rate, oxygen, or temperature. These devices communicate in brief, deterministic bursts, avoiding packet collisions that used to plague dense wards.</p>
<p>Privacy is critical, and that’s where encrypted advertising comes in. Patient identifiers and medical readings remain hidden even in broadcast form. Channel Sounding adds another layer by confirming proximity: only readers within a safe range can retrieve sensitive data.</p>
<p>Combined, these features help reduce misreads and protect patient confidentiality without adding extra setup steps for clinicians.</p>
<h3 id="heading-industry-40-asset-tracking-and-condition-monitoring">Industry 4.0: Asset Tracking and Condition Monitoring</h3>
<p>Factories and warehouses are some of Bluetooth’s biggest playgrounds. Equipment now comes with embedded Bluetooth 6.0 modules that use Channel Sounding for ultra-precise location tracking. Pallets, forklifts, and tools broadcast their position continuously, helping logistics teams know what’s where, all the time.</p>
<p>Add PAwR, and you get scalable telemetry for thousands of machines. Vibration, temperature, or pressure data can flow reliably to a single gateway. Some systems even combine Bluetooth data with AI analytics to predict failures before they happen. The ability to measure distance accurately also helps robots navigate crowded spaces safely.</p>
<h3 id="heading-wearables-hearables-ar-glasses-and-health-bands">Wearables: Hearables, AR Glasses, and Health Bands</h3>
<p>Wearable devices benefit more than any other category. Modern earbuds use LE Audio to keep both sides synchronized, whether you’re streaming a movie or on a call. Hearing aids receive direct broadcast audio in public venues without special adapters.</p>
<p>AR glasses are an even bigger frontier. They use Channel Sounding to sense spatial relationships between the wearer, nearby devices, and the environment. That allows context-aware overlays – navigation cues, health metrics, or notifications – that appear exactly where they make sense. Bluetooth’s low-power model keeps these systems lightweight enough to run all day.</p>
<h3 id="heading-automotive-digital-keys-and-vehicle-telemetry">Automotive: Digital Keys and Vehicle Telemetry</h3>
<p>Cars are fast becoming Bluetooth hubs on wheels. <strong>Digital Key Systems</strong> already use Bluetooth 6.0’s distance measurement to ensure you’re physically close before unlocking or starting the engine. It’s safer than older RSSI-based solutions that could be fooled by signal relays.</p>
<p>Onboard sensors rely on secure connections and encrypted advertising to stream data about tire pressure, cabin air quality, or driver posture. Maintenance centers can access diagnostic data automatically when a car pulls in, without plugging in a cable. In short, Bluetooth has quietly replaced several proprietary systems once needed for short-range communication inside vehicles.</p>
<h3 id="heading-the-big-picture">The Big Picture</h3>
<p>What’s striking is how flexible Bluetooth has become. The same fundamental protocol now powers medical wearables, industrial sensors, and entertainment systems. Each use case leans on a different mix of features – PAwR for scale, Channel Sounding for precision, LE Audio for experience, and encrypted advertising for privacy – but the foundation is consistent.</p>
<p>It’s this adaptability that explains why Bluetooth continues to thrive despite predictions of its demise. Rather than being replaced by Wi-Fi or UWB, it’s learning from them, borrowing their strengths, and finding new roles.</p>
<h2 id="heading-developer-guide-getting-started">Developer Guide — Getting Started</h2>
<p>Bluetooth 6.0 may sound futuristic, but the good news is that you don’t have to wait years to use it. Most of the new features are already landing in chipsets, SDKs, and development kits. If you’re an engineer or hobbyist itching to get your hands dirty, this section walks you through what to look for, how to get started, and a few pitfalls to watch out for along the way.</p>
<h3 id="heading-picking-the-right-chipset">Picking the Right Chipset</h3>
<p>The chipset you choose sets the tone for your entire project. If you’re building something simple, like a smart tag or sensor, you’ll want a microcontroller with integrated Bluetooth Low Energy and minimal power draw. But if you plan to experiment with Channel Sounding, LE Audio, or PAwR, you’ll need silicon that explicitly supports Bluetooth 5.4 or 6.0 features.</p>
<p>Current front-runners include the Nordic nRF54 series, Dialog DA1470x, and Silicon Labs BG24 family. These are developer-friendly chips with mature SDKs and good documentation. They also have flexible radio subsystems, which matter a lot when you’re testing features like Channel Sounding that depend on timing and signal stability.</p>
<p>A small tip from experience: always check the vendor’s firmware release notes. Some Bluetooth 6.0-capable chips still require you to enable experimental PHY layers or SDK flags to unlock certain features.</p>
<h3 id="heading-sdk-and-stack-support">SDK and Stack Support</h3>
<p>Once you’ve got your hardware, the next step is setting up your software stack. Most Bluetooth development happens through vendor SDKs or open platforms like Zephyr RTOS, ESP-IDF, or BlueZ on Linux.</p>
<p>If you’re targeting embedded systems, Zephyr is a great place to start. It’s modular, stable, and already includes PAwR and LE Audio APIs under its <code>bt_le_ext_adv</code> and <code>iso</code> modules. Silicon Labs’ Simplicity Studio also has strong tooling around Bluetooth mesh and PAwR.</p>
<p>On desktop or gateway platforms, Linux’s BlueZ stack supports extended advertising and secure connections out of the box, and work is underway to integrate Channel Sounding support via new HCI commands.</p>
<p>Always verify that your controller firmware is up to date before testing new features. Many “missing API” errors trace back to outdated controller images that don’t yet recognize the relevant HCI opcodes.</p>
<h3 id="heading-advertising-strategy">Advertising Strategy</h3>
<p>Advertising is still the heartbeat of Bluetooth, and now it’s smarter than ever. Here’s a simple example of setting up extended advertising in C-style pseudocode:</p>
<pre><code class="lang-plaintext">ble_adv_params params = {
    .type = ADV_EXTENDED,
    .interval = 160,   // 100ms interval
    .tx_power = 0      // default transmit power
};

ble_set_adv_data(payload, sizeof(payload));
ble_start_advertising(&amp;params);
</code></pre>
<p>Above pseudocode demonstrates how a Bluetooth Low Energy (BLE) device initializes and starts broadcasting advertisements so that nearby devices can discover it. The first block defines a structure named <code>ble_adv_params</code>, which contains the configuration settings for advertising. The <code>.type = ADV_EXTENDED</code> field specifies that the device will use <strong>Extended Advertising</strong>, a feature introduced in Bluetooth 5.0 that allows for larger payloads, better range, and the use of secondary channels beyond the traditional 31-byte limit of legacy advertising. The <code>.interval = 160</code> value sets the advertising interval, expressed in Bluetooth time units of 0.625 milliseconds, meaning the device transmits an advertising packet every 100 milliseconds—frequent enough for responsive discovery without excessive power consumption. The <code>.tx_power = 0</code> field sets the transmit power level to 0 dBm, which is the default radio output power and provides a balanced tradeoff between energy efficiency and signal range. After configuring the parameters, the function <code>ble_set_adv_data(payload, sizeof(payload))</code> loads the advertising data—typically a collection of identifiers such as the device name, UUIDs for available services, manufacturer-specific data, or other Bluetooth advertising fields. This is the information that other devices see when scanning nearby. Finally, <code>ble_start_advertising(&amp;params)</code> begins the actual transmission, instructing the BLE controller to start broadcasting the configured data on the standard advertising channels (37, 38, and 39). Once active, the device periodically transmits these packets until advertising is stopped manually or a central device establishes a connection. In essence, this short snippet encapsulates the three fundamental steps of BLE advertising: configuring the radio parameters, defining the broadcast data, and enabling the periodic advertisements that make the device visible to others.</p>
<p>This kind of setup works well for extended advertising and PAwR broadcast scheduling. When designing your advertising payloads, remember that the new encrypted format (introduced in 5.4) limits available space slightly, so plan for tighter data packing if you’re including custom fields.</p>
<p>If you’re building something that needs connection-less updates (like a sensor network), use PAwR or periodic advertising. For interactive applications, where you expect users to connect via a phone or hub, extended connectable advertising remains the right choice.</p>
<h3 id="heading-connection-optimization">Connection Optimization</h3>
<p>Tuning connection parameters is half art, half science. You’ll often find yourself trading latency for battery life. For streaming or LE Audio applications, intervals around <strong>24–40 ms</strong> usually strike the right balance. For sensors or telemetry, you can stretch that interval out to save energy.</p>
<p>Sniff subrating is another underrated feature. It lets a peripheral sleep longer while maintaining an active connection, reducing energy use without affecting responsiveness too much.</p>
<p>If you’re testing with multiple devices, simulate busy airspace using tools like Ellisys Bluetooth Analyzer or the nRF Sniffer. This helps uncover timing issues or packet loss that might only show up in dense radio environments.</p>
<h3 id="heading-power-testing">Power Testing</h3>
<p>It’s easy to claim low power on paper – but proving it is another story. Use your dev kit’s current profiling tools to measure sleep and active currents under different intervals and PHY settings.</p>
<p>Run your firmware through long-duration tests in “noisy” airspace – meaning multiple other Bluetooth or Wi-Fi devices nearby. The goal is to see how your firmware reacts when packet retries or interference increase. Sometimes small timing tweaks can make big differences in battery life.</p>
<p>As a general rule, always start testing on the <strong>1M PHY</strong> (the default) and only switch to <strong>2M</strong> for high-throughput use cases like audio. Long-range modes can be valuable for IoT, but remember that higher receive sensitivity often costs extra current.</p>
<h3 id="heading-security-checklist">Security Checklist</h3>
<p>Bluetooth 6.0 brings much stronger built-in security, but you’ll still need to wire it up correctly. Make sure to:</p>
<ul>
<li><p>Use LE Secure Connections instead of legacy pairing.</p>
</li>
<li><p>Rotate Identity Resolving Keys (IRK) periodically.</p>
</li>
<li><p>Encrypt advertising payloads whenever transmitting private or medical data.</p>
</li>
<li><p>Handle key storage securely on your device, preferably with hardware-backed encryption or secure flash.</p>
</li>
</ul>
<p>Also, watch for privacy gaps in the connection flow. Even encrypted devices can leak identity information if they reuse resolvable addresses or fail to clear bonds properly on reset.</p>
<h3 id="heading-backward-compatibility">Backward Compatibility</h3>
<p>Real-world devices won’t all jump to Bluetooth 6.0 overnight. Your code should always detect peer capabilities and fall back gracefully. The HCI layer provides read commands that reveal which features the remote device supports.</p>
<p>For example, if Channel Sounding isn’t available, default to RSSI-based proximity or skip distance-based logic entirely. Similarly, if LE Audio isn’t supported, fall back to classic A2DP. Designing your firmware with this flexibility keeps your products compatible with millions of existing devices.</p>
<h3 id="heading-testing-and-certification">Testing and Certification</h3>
<p>Once your prototype works, you’ll need to qualify it through the <strong>Bluetooth SIG Qualification Program</strong>. This process ensures your product complies with the spec and interoperates correctly with others. It might sound intimidating, but many vendors offer pre-qualified modules or test reports you can reuse to simplify the paperwork.</p>
<p>For debugging and validation, tools like the Ellisys Bluetooth Analyzer, Frontline BPA 600, or Nordic’s nRF Sniffer can capture over-the-air traffic and help verify packet sequences, timing, and encryption states.</p>
<p>Bluetooth development can be frustrating at first, as there’s lots of acronyms, layers, and hidden dependencies. But once you start seeing the system as a living conversation between devices, it clicks. The more you experiment with advertising intervals, connection timing, and PHY modes, the more you’ll appreciate how elegant and flexible the stack really is.</p>
<p>If you’ve ever wanted to build something that talks wirelessly and runs for months on a battery, this is your moment. The ecosystem has matured, the tools are ready, and the possibilities keep expanding.</p>
<h2 id="heading-challenges-amp-trade-offs">Challenges &amp; Trade-Offs</h2>
<p>It’s tempting to think of Bluetooth 6.0 as flawless – after all, it’s faster, more efficient, and infinitely scalable. But like every engineering advancement, it comes with trade-offs. Real deployments reveal quirks that the spec sheets don’t mention, and knowing these early can save hours of debugging (and a few late-night rants).</p>
<h3 id="heading-adoption-lag">Adoption Lag</h3>
<p>Every new Bluetooth spec sounds exciting on paper until you realize the hardware for it isn’t widely available yet. Controller vendors take time to integrate the latest features, and phone or OS support can lag by a year or two. You might find yourself reading about Channel Sounding or PAwR in the core spec, only to discover that your development kit still marks them as “experimental.”</p>
<p>This is normal. The Bluetooth SIG’s release cadence moves faster than the hardware ecosystem can follow. The best strategy is to design firmware that detects capabilities dynamically. Build your code to gracefully fall back to 5.0 or 5.2 modes if 6.0 features are missing. That way your product ships today, but it’s ready for the future.</p>
<h3 id="heading-environmental-interference">Environmental Interference</h3>
<p>Bluetooth still lives in the 2.4 GHz band, the same noisy neighborhood as Wi-Fi, microwaves, and countless IoT gadgets. In factories or dense apartments, you’ll see interference spikes that cause packet loss or delay. Even with adaptive frequency hopping, performance can dip if too many radios are talking at once.</p>
<p>Developers need to test in real environments, not just in quiet labs. Use spectrum analyzers or sniffers to visualize congestion. Adjust transmit power, advertisement intervals, or even antenna orientation to mitigate problems. Remember, radio design is part science, part art. Sometimes moving a board trace by a centimeter makes more difference than rewriting code.</p>
<h3 id="heading-power-versus-performance">Power Versus Performance</h3>
<p>Every Bluetooth generation tries to squeeze more precision and range out of roughly the same battery. Channel Sounding and high-speed PHY modes improve accuracy and throughput, but they also increase radio-on time and CPU load. You gain features but spend more energy to get them.</p>
<p>There’s no universal setting that fits all products. A hearing aid might value low latency over battery life, while a temperature sensor prioritizes sleeping as much as possible. Developers must tune intervals, transmission power, and frame spacing through measurement, not guesswork. The good news is that once you find the sweet spot, Bluetooth tends to be remarkably stable over long periods.</p>
<h3 id="heading-security-configuration">Security Configuration</h3>
<p>Modern Bluetooth has excellent built-in security, but only if you use it correctly. Misconfigured advertising, static passkeys, or unrotated identity keys can still leak information. Even encrypted advertising won’t help if your firmware accidentally reuses session data.</p>
<p>The takeaway: don’t assume “secure by default.” Review every pairing and bonding flow, handle key rotation on firmware updates, and wipe old bonds when a user resets the device. The protocol gives you powerful locks, but it’s up to you to actually turn the key.</p>
<h3 id="heading-software-complexity">Software Complexity</h3>
<p>The Bluetooth stack is getting heavier. Features like PAwR, Channel Sounding, and Isochronous Audio require new roles, new timing models, and new APIs. Developers who are used to simple GATT servers now have to think about scheduling, synchronization, and PHY coordination. Testing these features on multi-role devices can be especially tricky, since a single controller might handle multiple concurrent roles (central, peripheral, broadcaster, and observer).</p>
<p>If you’re working on an embedded platform, modular firmware design becomes essential. Split radio control, connection management, and application logic into distinct layers. It’s easier to debug timing bugs when your architecture mirrors the Bluetooth stack’s separation of concerns.</p>
<h3 id="heading-fragmentation">Fragmentation</h3>
<p>Perhaps the most persistent challenge is fragmentation. Not every OEM implements the same subset of features, and some phones or chipsets may partially support a spec while skipping optional sections. Developers quickly learn that “Bluetooth 6.0” can mean slightly different things depending on the vendor.</p>
<p>The practical fix is to build flexibility into your software. Use feature discovery at runtime, keep your update mechanism ready for OTA patches, and enable configuration flags for new features so you can toggle them per device. Testing across diverse hardware early in the process pays off more than any elegant design decision later.</p>
<h3 id="heading-mitigation-and-mindset">Mitigation and Mindset</h3>
<p>Despite these challenges, none of them are deal-breakers. They’re simply part of building systems that live in the real world. Think modular, plan for gradual rollouts, and make firmware updates painless. Bluetooth’s backward compatibility means your device won’t become obsolete overnight, and your users benefit from improvements as the ecosystem matures.</p>
<p>In short, the trick isn’t avoiding the trade-offs but managing them. When you design with flexibility, Bluetooth 6.0 becomes less of a moving target and more of a living platform that grows alongside your product.</p>
<h2 id="heading-the-road-ahead-bluetooth-61-and-beyond">The Road Ahead — Bluetooth 6.1 and Beyond</h2>
<p>If Bluetooth 6.0 was about awareness – knowing distance, filtering intelligently, and optimizing communication – then Bluetooth 6.1 is about refinement. It takes what already works and polishes it into something smoother, faster, and a little more elegant. It’s not a revolution, but it’s an important step in Bluetooth’s quiet transformation from a “wireless cable” into a context-aware network fabric for everyday devices.</p>
<h3 id="heading-small-tweaks-big-payoffs">Small Tweaks, Big Payoffs</h3>
<p>Bluetooth 6.1 focuses on tightening the nuts and bolts rather than changing the whole machine. The update improves Channel Sounding accuracy, enhances advertising efficiency, and introduces a few quality-of-life adjustments to make device coordination easier.</p>
<p>That might sound minor, but it matters. Channel Sounding, for example, becomes more reliable when multiple reflections or obstacles exist. In indoor positioning systems like airports, hospitals, or museums, even a five percent improvement in accuracy can reduce false detections by a wide margin. Advertising refinements also make large IoT deployments more predictable, allowing gateways to manage high-density environments with less radio congestion.</p>
<p>In simpler terms: Bluetooth 6.1 is like a firmware tune-up for an already fast car. You may not notice it day to day, but under heavy load, it performs better and wastes less energy.</p>
<h3 id="heading-the-emerging-themes">The Emerging Themes</h3>
<p>Beyond the incremental fixes, the Bluetooth community is thinking much bigger. The next few years will likely focus on four major themes: energy harvesting, AI-assisted radio optimization, hybrid positioning, and context-aware security.</p>
<h4 id="heading-1-energy-harvesting-bluetooth-devices">1. Energy-Harvesting Bluetooth Devices</h4>
<p>We’re starting to see early prototypes of Bluetooth tags and sensors that run entirely on harvested energy – light, heat, or vibration – with no traditional battery. This ties into the push for maintenance-free IoT devices, especially in logistics and environmental sensing. Future specifications will refine ultra-low-duty-cycle communication patterns to support these “powerless” nodes.</p>
<h4 id="heading-2-ai-driven-radio-management">2. AI-Driven Radio Management</h4>
<p>Imagine a Bluetooth controller that dynamically learns the noise profile of its environment and adjusts its PHY, transmit power, or advertising timing in real time. Instead of a static table of parameters, AI models embedded in the firmware could predict interference and choose the best channel map automatically. It sounds futuristic, but chipmakers are already experimenting with machine learning cores in connectivity modules.</p>
<h4 id="heading-3-cross-technology-fusion-bluetooth-wi-fi-uwb">3. Cross-Technology Fusion (Bluetooth + Wi-Fi + UWB)</h4>
<p>The border between short-range radios is blurring. Some systems already use Wi-Fi for throughput, Bluetooth for discovery, and UWB for pinpoint accuracy – all orchestrated by a single chipset. The goal isn’t to replace one with another but to fuse them, creating hybrid location frameworks that are more reliable than any single technology. Bluetooth’s Channel Sounding makes it a perfect partner in this mix.</p>
<h4 id="heading-4-context-aware-security">4. Context-Aware Security</h4>
<p>Future Bluetooth devices might decide access rights based not just on identity, but on <em>context</em>. For example, your smartwatch could unlock your laptop only if it detects that you’re sitting still and within one meter. That combination of motion, distance, and authentication could drastically reduce spoofing or relay attacks.</p>
<h3 id="heading-the-quiet-backbone-of-connectivity">The Quiet Backbone of Connectivity</h3>
<p>What’s fascinating about Bluetooth’s evolution is how quietly it happens. While other technologies make noise about high throughput or low latency, Bluetooth’s progress feels invisible but omnipresent. It doesn’t chase raw speed anymore – it chases <em>relevance</em>. The protocol is learning to sense, adapt, and coordinate, all qualities that make it essential for the next generation of ambient computing.</p>
<p>So while you might not notice Bluetooth 6.1 when it arrives, you’ll definitely feel its effects. Devices will sync faster, connections will drop less, audio will sound cleaner, and proximity-based features will just “know” what you want them to do. That’s the beauty of mature engineering: when it works so seamlessly that people stop thinking about it altogether.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Bluetooth has come a long way from its early days as a clunky pairing protocol for headsets. It’s now one of the quietest yet most influential technologies shaping how devices around us communicate. The newer generations – 5.4, 6.0, and soon 6.1 – show that Bluetooth’s evolution isn’t about flashy upgrades. It’s about <em>refinement</em>, about making wireless communication more precise, more private, and more power-aware.</p>
<p>At its core, Bluetooth’s story is about context. It’s learning to understand where you are, how far you are from something, and what kind of connection makes sense in that moment. Channel Sounding adds spatial awareness, PAwR makes massive IoT networks practical, LE Audio brings synchronized sound to earbuds, hearing aids, and broadcast systems, and encrypted advertising protects the information flowing through all of it.</p>
<p>For developers, this era of Bluetooth is exciting because it’s full of creative possibilities. You can build smarter sensors, more responsive wearables, or secure access systems that simply <em>know</em> when you’re nearby. The ecosystem is mature enough that you don’t need to be a radio engineer to experiment, but it’s still evolving fast enough to keep pushing boundaries.</p>
<p>The challenge now is not whether Bluetooth can handle the future. It’s how we, as developers and designers, decide to use it. Whether it’s powering ambient computing, healthcare networks, or next-gen audio, the technology is already ready.</p>
<p>So maybe the next time you put on your earbuds or unlock your car, take a moment to appreciate the quiet genius working behind the scenes. Bluetooth is thriving, adapting, and quietly building the connective tissue of our digital lives.</p>
<p>And for those of us who like tinkering with the unseen layers of technology, that’s a future well worth exploring.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Make Bluetooth on Android More Reliable ]]>
                </title>
                <description>
                    <![CDATA[ You may have had this happen before: your wireless earbuds connect perfectly one day, and the next they act like they’ve never met your phone. Or your smartwatch drops off in the middle of a run. Bluetooth is amazing when it works, but maddening when... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-bluetooth-on-android-more-reliable/</link>
                <guid isPermaLink="false">68b78f7fba46c4e7c6266797</guid>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ bluetooth ]]>
                    </category>
                
                    <category>
                        <![CDATA[ wireless network ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Nikheel Vishwas Savant ]]>
                </dc:creator>
                <pubDate>Wed, 03 Sep 2025 07:00:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1756860272946/83be340a-dcce-4d2f-a6eb-0d70164b11b6.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You may have had this happen before: your wireless earbuds connect perfectly one day, and the next they act like they’ve never met your phone. Or your smartwatch drops off in the middle of a run. Bluetooth is amazing when it works, but maddening when it doesn’t.</p>
<p>I work as a Bluetooth software engineer on wearable devices like smart-glasses, and I’ve spent more time than I’d like to admit chasing down why these things break.</p>
<p>In this article, I’ll give you a peek behind the curtain: how Android’s Bluetooth stack actually works, why it sometimes feels unpredictable, and what you can do as a developer to make your apps or system more reliable.</p>
<h2 id="heading-bluetooth-in-plain-english">Bluetooth in Plain English</h2>
<p>At its core, Bluetooth is just a conversation between two devices. But it isn’t one simple line of communication – it’s multiple layers stacked on top of each other.</p>
<ul>
<li><p><strong>The radio (Controller):</strong> Sends and receives the actual signals over the air medium.</p>
</li>
<li><p><strong>The software brain (Host stack):</strong> Decides whom to talk to and how, as well as if it wants to.</p>
</li>
<li><p><strong>Profiles:</strong> Define the purpose of the conversation – like streaming music or syncing health data.</p>
</li>
<li><p><strong>Protocols:</strong> Define how to talk to the other device.</p>
</li>
</ul>
<p>There are two big “flavors” of bluetooth:</p>
<ul>
<li><p><strong>Classic (BR/EDR):</strong> Used for things like headphones and car kits. Can lift more weight.</p>
</li>
<li><p><strong>Low Energy (LE):</strong> Used for fitness bands, beacons, and most wearables. Can sustain longer.</p>
</li>
</ul>
<p>Most modern gadgets use both at once. That’s powerful, but it also opens the door for more things to go wrong.</p>
<h2 id="heading-why-android-adds-its-own-quirks">Why Android Adds Its Own Quirks</h2>
<p><img src="https://source.android.com/static/docs/core/connect/bluetooth/images/fluoride_architecture.png" alt="Diagram showing the layers of the Android Bluetooth stack." width="600" height="400" loading="lazy"></p>
<p>On Android, Bluetooth isn’t just one neat package. It’s a chain of moving parts:</p>
<ul>
<li><p>Your app calls <code>BluetoothAdapter</code>.</p>
</li>
<li><p>Those go into <strong>system services</strong> like <code>AdapterService</code>.</p>
</li>
<li><p>Then into native code through <strong>JNI</strong> (Java Native Interface).</p>
</li>
<li><p>Then into the <strong>chip vendor’s Bluetooth stack</strong>.</p>
</li>
<li><p>Finally, it hits the <strong>radio hardware</strong>.</p>
</li>
</ul>
<p>Every phone maker ships a slightly different Bluetooth chip and firmware. That means the exact same Bluetooth app might behave differently on a Samsung, a Pixel, or any other budget phone running Android.</p>
<h2 id="heading-the-real-problems-behind-it-just-disconnected">The Real Problems Behind “It Just Disconnected”</h2>
<p>Here are a few of the common headaches I see, explained simply:</p>
<h3 id="heading-bonding-issues-the-lost-keys-problem"><strong>Bonding issues (the “lost keys” problem)</strong></h3>
<p>When two Bluetooth devices pair, they exchange encryption keys (link keys for Classic, Long Term Keys for LE) and store them in non-volatile memory. These keys are what let the devices recognize each other later and reconnect securely without asking the user again.</p>
<p>A “mismatched memory” problem happens when one device’s stored keys don’t match the other’s anymore. This can be caused by:</p>
<ul>
<li><p>A firmware update or OS upgrade that wipes or regenerates keys.</p>
</li>
<li><p>A factory reset or “forget device” on one side but not the other.</p>
</li>
<li><p>Keys being corrupted or evicted by the system to free up storage.</p>
</li>
</ul>
<p>From the user’s perspective, the device may still <em>look</em> paired (shows up in the Bluetooth menu), but connections mysteriously fail with errors like “Authentication Failed” or “Insufficient Encryption.” The only cure is usually to delete the device on both ends and re-pair, which feels ridiculous to non-technical users.</p>
<h3 id="heading-timing-mismatches"><strong>Timing mismatches</strong></h3>
<p>Bluetooth devices don’t just chat whenever they want, they agree on a connection interval – essentially a schedule for when each side will “wake up” and exchange packets. Think of it as two people agreeing to meet every 30 minutes at a café.</p>
<p>A mismatch happens when:</p>
<ul>
<li><p>The two sides negotiate different intervals but don’t fully agree (for example, one thinks it’s 30ms, the other 50ms).</p>
</li>
<li><p>One side’s firmware update or configuration change alters its timing policy.</p>
</li>
<li><p>Radio conditions cause one side to miss multiple scheduled check-ins, drifting the clocks apart.</p>
</li>
<li><p>Power-saving logic (like a phone going into Doze mode) silently stretches out the interval.</p>
</li>
</ul>
<p>This explains why a connection might work fine at first but start failing later: the devices initially synced on an interval, but then one side’s policy or behavior shifted. From the user’s perspective, it looks like audio stuttering, laggy input (on game controllers), or random disconnects after “it was working fine before.”</p>
<h3 id="heading-unexpected-disconnections"><strong>Unexpected disconnections</strong></h3>
<p>When a Bluetooth link ends, the radio layer (the controller) and the higher-level OS stack (the host) are supposed to exchange clear signals. The controller sends an HCI Disconnection Complete event (basically: <em>“Goodbye, we’re done”</em>). And the host should then update its internal state, clean up the GATT/ACL session, and be ready for reconnection.</p>
<p>But in practice, this doesn’t always line up:</p>
<ul>
<li><p>Sometimes the controller says goodbye cleanly, but the host stack doesn’t update its state properly. The app still “thinks” the connection is active, so reconnect attempts silently fail.</p>
</li>
<li><p>Some platforms aggressively cache connection state (especially iOS). If the OS believes the connection is still valid, it won’t trigger a new connection attempt until you toggle Bluetooth or reboot.</p>
</li>
<li><p>A race condition can occur if the disconnection event happens while another operation (for example, service discovery, bonding, or encryption setup) is in flight. The OS may get confused about what state the device is <em>really</em> in.</p>
</li>
<li><p>On some devices, a fast reconnect attempt after a clean disconnection collides with internal cooldown timers. The controller ignores it, leaving the app waiting.</p>
</li>
</ul>
<p>From the user’s perspective, the device looks “stuck.” The only way to recover is to toggle Bluetooth, restart the app, or power cycle the accessory, even though technically nothing “failed.”</p>
<h2 id="heading-how-developers-can-do-better">How Developers Can Do Better</h2>
<p>If you’re building a Bluetooth app, here are a few habits that save a lot of pain:</p>
<h3 id="heading-check-for-bonded-devices-first"><strong>Check for bonded devices first</strong></h3>
<p>One of the most common causes of failed connections is mismatched bonding information: the phone and the accessory no longer share the same encryption keys. Even if the device appears in the UI, the OS may have lost its keys.</p>
<p>Before attempting a connection, always query the system’s bonded device list with <code>BluetoothAdapter.getBondedDevices()</code>. For example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (adapter.getBondedDevices().contains(targetDevice)) {
    targetDevice.connectGatt(context, <span class="hljs-keyword">false</span>, gattCallback);
} <span class="hljs-keyword">else</span> {
    showToast(<span class="hljs-string">"Please re-pair this device to restore the connection."</span>);
}
</code></pre>
<p>This ensures you only attempt secure connects to devices the OS still trusts. If the target device isn’t in the bonded list, you can give the user a clear instruction (“Please re-pair this device”) instead of leaving them with confusing connection errors.</p>
<h3 id="heading-handle-callbacks-carefully"><strong>Handle callbacks carefully</strong></h3>
<p>Another subtle pitfall is assuming that a <code>STATE_CONNECTED</code> event means a connection was successful. In reality, <code>onConnectionStateChange()</code> can report a connected state even when the underlying operation failed, the real result is in the <code>status</code> argument. To avoid chasing phantom connections, always check both <code>status</code> and <code>newState</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (status == BluetoothGatt.GATT_SUCCESS &amp;&amp;
    newState == BluetoothProfile.STATE_CONNECTED) {
    gatt.discoverServices();
} <span class="hljs-keyword">else</span> {
    gatt.close();
}
</code></pre>
<p>This pattern prevents you from attempting service discovery on a dead connection and ensures stale sessions are closed promptly, leaving the stack ready for a clean retry.</p>
<h3 id="heading-expect-failures"><strong>Expect failures</strong></h3>
<p>Bluetooth connections fail all the time in the real world – devices drift out of range, interference spikes in the 2.4 GHz band, or the radio is simply busy. The worst thing an app can do is retry instantly in a tight loop, which drains the battery and makes the stack unstable.</p>
<p>A better approach is to implement exponential backoff like this:</p>
<pre><code class="lang-java"><span class="hljs-keyword">long</span> delay = (<span class="hljs-keyword">long</span>) Math.min(<span class="hljs-number">250</span> * Math.pow(<span class="hljs-number">2</span>, attempt), <span class="hljs-number">30000</span>);
<span class="hljs-keyword">new</span> Handler(Looper.getMainLooper()).postDelayed(connectAction, delay);
</code></pre>
<p>This means your first retry happens quickly (~250 ms), but subsequent retries slow down (500 ms, 1 s, 2 s…), capped at a reasonable maximum. Backoff makes your app resilient without overwhelming the radio or the OS.</p>
<h3 id="heading-use-the-right-tools"><strong>Use the right tools</strong></h3>
<p>Without visibility into what’s happening under the hood, connection problems look random. Tools like <em>nRF Connect</em> let you interactively scan, connect, and run GATT operations against your device, while Android’s Bluetooth HCI snoop log reveals the actual packets being exchanged. For example:</p>
<pre><code class="lang-bash">Settings.Secure.putInt(context.getContentResolver(), <span class="hljs-string">"bluetooth_hci_log"</span>, 1);
</code></pre>
<p>Once enabled, you can capture a logcat trace and confirm whether a failure is due to missing keys (<code>Insufficient Authentication</code>), a timing mismatch, or interference. Using these tools not only helps you debug your app, it also proves whether the issue lies in your code, the OS, or the accessory firmware.</p>
<p><img src="https://www.beaconzone.co.uk/blog/wp-content/uploads/2019/08/nrfconnectios.png" alt="Completely New nRF Connect for iOS – BeaconZone Blog" width="600" height="400" loading="lazy"></p>
<h2 id="heading-bigger-lessons">Bigger Lessons</h2>
<p>Working with Bluetooth taught me lessons that apply to engineering in general:</p>
<ul>
<li><p>Wireless is never perfect, so always build with recovery in mind.</p>
</li>
<li><p>Logs and metrics aren’t optional. They’re your map through the chaos.</p>
</li>
<li><p>The simplest solution usually survives best in the messy real world.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Bluetooth is messy because it’s a chain of hardware, firmware, and software all trying to cooperate. On Android, the variety of chips and vendors makes it even trickier.</p>
<p>But that doesn’t mean you’re helpless. By understanding how the layers work and designing your apps with retries, checks, and proper logging, you can make Bluetooth feel a lot less “weird” for your users.</p>
<p>The next time your earbuds misbehave, you’ll know – it’s not you. It’s just Bluetooth being Bluetooth.</p>
<p>⚡ <em>This is the first of a number of articles I’m going to write on Bluetooth development. In the next one, we’ll dive deeper into how to build a secure Bluetooth Low Energy (BLE) GATT client and server on Android. Stay tuned!</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Public Grafana-based Solar Monitoring Dashboard in Home Assistant ]]>
                </title>
                <description>
                    <![CDATA[ If you have a solar inverter setup, one thing you would agree on with me is that data from your solar inverter setup is really important. Another thing that is also important is having a way to show what your energy generation, consumption, and so on... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-public-grafana-based-solar-monitoring-dashboard-in-home-assistant/</link>
                <guid isPermaLink="false">68010bea439877985a5bf3e2</guid>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Home Assistant ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Grafana ]]>
                    </category>
                
                    <category>
                        <![CDATA[ InfluxDB ]]>
                    </category>
                
                    <category>
                        <![CDATA[ solar energy ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Anomfueme ]]>
                </dc:creator>
                <pubDate>Thu, 17 Apr 2025 14:10:50 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744899028552/8ad3f3c4-9b25-473d-b539-14dcb2f2b241.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you have a solar inverter setup, one thing you would agree on with me is that data from your solar inverter setup is really important. Another thing that is also important is having a way to show what your energy generation, consumption, and so on looks like publicly.</p>
<p>The thing is that most solar inverter brands have a form of remote data monitoring platform, from <a target="_blank" href="https://www.victronenergy.com/panel-systems-remote-monitoring/vrm">Victron’s VRM</a> to <a target="_blank" href="https://en.growatt.com/products/growatt-monitoring-platform">Growatt’s ShineServe</a>r to <a target="_blank" href="https://www.deyeinverter.com/product/accessory-monitoring-1/smart-pv-management-platform.html">Deye’s Cloud</a>, among others. But I’m a fan of self-hosting and local control of data. This is one of the best ways to visualize and showcase all that beautiful data you have publicly to fellow tinkerers, solar inverter users, and the general public without relying on the company’s cloud data logger solution.</p>
<p>In this article, we will be using data available in our Home Assistant setup, sending it to <a target="_blank" href="https://www.influxdata.com/products/influxdb/">InfluxDB</a> and making a <a target="_blank" href="https://grafana.com/oss/grafana/">Grafana</a> dashboard out of it. There are a good number of ways to connect your inverter to Home Assistant, depending on the manufacturer. I use a Growatt SPF ES 6000 inverter, and I shared a guide on how to make a local data logger for it that works with Home Assistant <a target="_blank" href="https://hackernoon.com/turn-your-dumb-solar-inverter-into-a-smart-one-with-this-home-assistant-hack">here</a>.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-and-configure-influxdb">How to Install and Configure InfluxDB</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-and-configure-grafana">How to Install and Configure Grafana</a></p>
</li>
<li><p><a class="post-section-overview" href="#how-to-create-the-grafana-solar-dashboard">How to Create the Grafana Solar Dashboard</a></p>
</li>
<li><p><a class="post-section-overview" href="#how-to-create-a-new-admin-user-and-delete-the-default-admin-user">How to Create a New Admin User and Delete the Default Admin User</a></p>
</li>
<li><p><a class="post-section-overview" href="#how-to-enable-remote-access-to-the-solar-dashboard">How to Enable Remote Access to the Solar Dashboard</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h3 id="heading-prerequisites"><strong>Prerequisites</strong></h3>
<ul>
<li><p>Home Assistant OS</p>
</li>
<li><p>A domain name</p>
</li>
<li><p>An inverter connected to your Home Assistant instance</p>
</li>
</ul>
<h2 id="heading-how-to-install-and-configure-influxdb">How to Install and Configure InfluxDB</h2>
<p>We will be starting by setting up InfluxDB. InfluxDB is an open-source time series database, which differs from the database that <a target="_blank" href="https://www.home-assistant.io/docs/backend/database/#:~:text=The%20default%20database%20used%20is,other%20databases%20can%20be%20used.">Home Assistant uses by default</a>, SQLite. We will be using InfluxDB v1, as it’s much easier to set up.</p>
<p>Go to your Home Assistant dashboard and go to Settings &gt; Add-ons and click on the Add-On Store.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744463486874/9dda1fca-24a9-4c30-a486-3b723e8535fe.png" alt="A screenshot of Home Assistant Add-ons" class="image--center mx-auto" width="1713" height="1378" loading="lazy"></p>
<p>Inside the Add-on Store, search for “InfluxDB“ and click on the Add-on. You should see the screen below, then install.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744463639772/75f66c35-e7b3-4c20-96ea-9e9154829ac5.png" alt="A screenshot of Home Assistant Add-ons, showing InfluxDB Add-on page" class="image--center mx-auto" width="1703" height="1350" loading="lazy"></p>
<p>Toggle the “Watchdog” on, as this allows the add-on to restart if it crashes. Also, toggle the “show in sidebar” on, which allows you to see the add-on on Home Assistant’s sidebar.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744465515531/0c9e9475-08c2-4bc3-afe5-baa4fdbae164.png" alt="A screenshot of InfluxDB Add-on installed and some configurations turned on" class="image--center mx-auto" width="1698" height="1252" loading="lazy"></p>
<p>Start the add-on and look at the logs to be sure it is working. The “Starting NGINX” is an indicator it’s working.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744465746577/f3adbd52-14cd-4e78-b2d7-789ad2c22b31.png" alt="A screenshot of InfluxDB Add-on logs" class="image--center mx-auto" width="1721" height="1246" loading="lazy"></p>
<p>Next, go to your Home Assistant sidebar and click on InfluxDB. You need to create a new database to hold your data and also create a new user that has admin privileges to read and write data. Go to the InfluxDB Admin tab.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744466323654/78f21741-e6ca-4094-8fc3-adc563b3dfc1.png" alt="A screenshot of InfluxDB Add-on Admin settings showing database available" class="image--center mx-auto" width="1722" height="1367" loading="lazy"></p>
<p>Click on Create Database – and you can name the database anything you want. I will be naming mine <strong>homeassistant</strong>.</p>
<p>By default, the retention policy for a created database is infinity (which is forever), but you can configure this to be any time frame you want. Retention policy refers to the time frame of data the database can hold. I prefer to stick with infinity as I want to keep as much data as possible and I have enough storage in my Home Assistant hardware for that.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744466625066/c2ae2012-44d8-4acb-91ae-25ad35fb18ff.png" alt="A screenshot of InfluxDB Add-on Admin settings showing the newly created database available" class="image--center mx-auto" width="1725" height="1350" loading="lazy"></p>
<p>Once the database is created, go to the Users tab so you can create the new admin user. Input a username and password for that user and click on Grant Admin, so the permission level can be set to all. I created a new user called <strong>root</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744467230710/6c025cb7-123a-4552-8090-6a9550e64ecf.png" alt="A screenshot of InfluxDB Add-on Admin settings showing users available" class="image--center mx-auto" width="1712" height="1350" loading="lazy"></p>
<p>At this point, what is left on the InfluxDB side is to tell Home Assistant to start sending sensor data to InfluxDB. You can do this by going to your Home Assistant <strong>configuration.yaml</strong> file and adding this config below to it. Your host is the IP of your Home Assistant, the port is the default port for the InfluxDB add-on, and the remaining values are based on the values you used during setup.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">influxdb:</span>
  <span class="hljs-attr">host:</span> <span class="hljs-number">192.168</span><span class="hljs-number">.8</span><span class="hljs-number">.12</span>
  <span class="hljs-attr">port:</span> <span class="hljs-number">8086</span>
  <span class="hljs-attr">database:</span> <span class="hljs-string">homeassistant</span>
  <span class="hljs-attr">username:</span> <span class="hljs-string">root</span>
  <span class="hljs-attr">password:</span> <span class="hljs-string">password</span>
  <span class="hljs-attr">max_retries:</span> <span class="hljs-number">3</span>
  <span class="hljs-attr">default_measurement:</span> <span class="hljs-string">state</span>
</code></pre>
<p>Restart your Home Assistant and go to InfluxDB. Click on the Explore tab, and check to see if you have a <strong>database.autogen</strong> file there<em>.</em> Click on it, and if you see some values under Measurements &amp; Tags, you are good to go.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744468647521/3082e165-04d9-4b7d-bfd7-8de0662c11a9.png" alt="A screenshot of InfluxDB Add-on Explore tab" class="image--center mx-auto" width="1712" height="1357" loading="lazy"></p>
<h2 id="heading-how-to-install-and-configure-grafana">How to Install and Configure Grafana</h2>
<p>Next on our agenda is to install and configure Grafana. The goal is to have Grafana query InfluxDB and make dashboards based on the queried data.</p>
<p>Go to the Add-on store, search for Grafana, and install it. Remember to toggle on those important settings, then start the add-on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744470196074/b3d69925-9ccc-45b9-8078-905866222d15.png" alt="A screenshot of Grafana Add-on page" class="image--center mx-auto" width="1715" height="1386" loading="lazy"></p>
<p>Once it has started, click on Grafana on the sidebar. You will arrive at Grafana’s homepage which is where you can create those dashboards.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744470431232/0e4541a5-344f-4f46-bd85-44f4d92ea53c.png" alt="A screenshot of Grafana Add-on homepage" class="image--center mx-auto" width="1703" height="1346" loading="lazy"></p>
<p>But before you do that, you need to connect InfluxDB to Grafana. Navigate to Grafana’s tab &gt;&gt; Connections. You should see an “Add new connection” page. Search for InfluxDB and choose it. Then click on the add new datasource button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744470636092/8dcb8f2b-7fcd-49d3-80d8-abce4f83ea07.png" alt="A screenshot of Grafana Add-on connection settings page" class="image--center mx-auto" width="1707" height="1355" loading="lazy"></p>
<p>Under HTTP, edit the URL and use <strong>http://ha_ip_address:8086</strong> – don’t omit the <code>http://</code> or try to use <code>localhost</code> with it. Scroll down to the InfluxDB Details and fill in the data you used while setting up InfluxDB. Then click on Save &amp; Test. If the config is correct, you should see a green tick and text saying “datasource is working…measurements found.”</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744471708830/5b0d0306-8b74-4c02-9163-cc23a7c3425c.png" alt="A screenshot of Grafana Add-on connection configuration for InfluxDB" class="image--center mx-auto" width="1700" height="1337" loading="lazy"></p>
<h2 id="heading-how-to-create-the-grafana-solar-dashboard">How to Create the Grafana Solar Dashboard</h2>
<p>With that, you should have InfluxDB running and connected to Grafana. Let’s get to building beautiful dashboards out of all the data being generated. This part is subjective, so you can feel free to edit and modify the design to your taste. We will be using this dashboard <a target="_blank" href="https://helio.openculture.org.ng/public-dashboards/cf813bfa739044129e125bdd65db7a65?ref=blog.openculture.org.ng">here</a> as the inspiration for our design.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744548823070/811cb6b1-d3f6-4880-b665-8af999d4c703.png" alt="A screenshot of a dashboard we want to recreate" class="image--center mx-auto" width="1918" height="941" loading="lazy"></p>
<p>So now go to your Grafana in Home Assistant, click on the + icon and create a new dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744544792278/0bbc6140-1335-4597-a972-80a5ddee1744.png" alt="A screenshot of Grafana homepage" class="image--center mx-auto" width="1721" height="1340" loading="lazy"></p>
<p>You should know that a dashboard in Grafana refers to the full space and each thing placed on the dashboard is a panel. Each visualization on the dashboard is a panel.</p>
<p>Let’s create a new panel. Pick InfluxDB as the data source, and at the <strong>FROM</strong> row, pick W which is the unit we want to create a visualization from. <strong>WHERE</strong> is entity_id::tag, as that is the way to sort the values by Home Assistant sensor entity name. Then pick the entity id of your panel – mine is <strong>growatt_pv1_charge_power.</strong> You can change the panel title, change the visualization to stat, and add the watt as the unit and the base colour to yellow.</p>
<p>The raw query looks like this:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> mean(<span class="hljs-string">"value"</span>) <span class="hljs-keyword">FROM</span> <span class="hljs-string">"W"</span> <span class="hljs-keyword">WHERE</span> (<span class="hljs-string">"entity_id"</span>::tag = <span class="hljs-string">'growatt_pv1_charge_power'</span>) <span class="hljs-keyword">AND</span> $timeFilter <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> <span class="hljs-built_in">time</span>($__interval) fill(<span class="hljs-literal">null</span>)
</code></pre>
<p>The Grafana edit page looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744550024020/bb50d494-c6bc-45f2-8ff0-17173e7255bc.png" alt="A screenshot of Grafana edit panel view" class="image--center mx-auto" width="1710" height="1258" loading="lazy"></p>
<p>At this point, you should be able to recreate the remaining parts of the dashboard. But I manually did all that, so you don’t have to go through it all yourself if you don’t want to.</p>
<p><a target="_blank" href="https://github.com/LifeofDan-EL/Grafana-Solar-Dashboard">Here</a> is the link to a GitHub repo that has the JSON file of this dashboard. When you go to create a dashboard, you will see an option to import from a JSON file. You can choose to copy and paste or upload the file, whichever works for you.</p>
<p>After importing, you only need to edit each panel through the GUI to use your own entity ID tag in Home Assistant and also the UID of your InfluxDB database.</p>
<p>Here is a picture of my finished result:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744559385614/57b58bfe-7fc2-4fa7-a0d2-19485558899a.png" alt="A screenshot of the finished product of the dashboard I built" class="image--center mx-auto" width="3436" height="1357" loading="lazy"></p>
<h2 id="heading-how-to-create-a-new-admin-user-and-delete-the-default-admin-user">How to Create a New Admin User and Delete the Default Admin User</h2>
<p>By default, the Grafana Add-on in Home Assistant uses an auth proxy and creates a default user (<code>admin</code>) with a password (<code>hassio</code>) that's synced with your HA login session. This prevents password or user changes through the UI.</p>
<p>For context, an auth proxy, or authentication proxy, acts as an intermediary between a client and a target resource, handling authentication and authorization on behalf of the client</p>
<p>As a security step, we need to create a new user for the Grafana Add-on and edit their permission to have admin privileges, then delete the default admin user. This is because you can’t change the default admin user password on the Add-on.</p>
<p>Go to Grafana’s menu &gt; Administration&gt; Users and access &gt; Users. Then create a new user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744571233206/daf2c674-4501-4774-89d9-76992227b531.png" alt="A screenshot of Grafana users setting page" class="image--center mx-auto" width="1721" height="1332" loading="lazy"></p>
<p>Next, give it admin privileges. Edit Grafana Admin to be yes and make sure the organization role is set to admin, then save.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744749794592/21e85eab-99ca-4c7d-9d18-19e9f31ea1da.png" alt="A screenshot of Grafana user setting" class="image--center mx-auto" width="1715" height="1387" loading="lazy"></p>
<p>Go back to the Add-on Configuration tab. Scroll to the Network setting and add a port to expose the Add-on. I will be using port 3000. Save and restart the Add-on. If you have SSL turned on and it isn’t configured, the add-on won’t start. You can disable it as we will have Cloudflare handle that.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744750541094/326aa725-7b81-4407-82ef-e6589a153b9c.png" alt="A screenshot of Grafana Add-on Configuration tab" class="image--center mx-auto" width="1712" height="1388" loading="lazy"></p>
<p>To confirm that the port has been exposed properly, go to <code>http://ha_ip:3000/</code> and confirm you see this Grafana login screen. Make sure it is http and not https.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744563139292/e17d2691-3b77-4faf-997d-95a0b3141066.png" alt="A screenshot of Grafana homepage accessed from outside Home Assistant url" class="image--center mx-auto" width="1698" height="1382" loading="lazy"></p>
<p>Log in as the new user you created. Then go to your list of users and delete the default admin user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744750661705/1d98e960-e325-4a5c-9746-64ff1819a573.png" alt="A screenshot of edit to the default admin user" class="image--center mx-auto" width="1718" height="1343" loading="lazy"></p>
<p>After that, go back to the Grafana Add-on Configuration tab. Click on the 3 dots on the Options row and choose Edit in YAML. Then add this line below to your configuration file and save.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">grafana_ingress_user:</span> <span class="hljs-string">usernameofnewuser</span>
</code></pre>
<h2 id="heading-how-to-enable-remote-access-to-the-solar-dashboard">How to Enable Remote Access to the Solar Dashboard</h2>
<p>At this point, we have the solar dashboard all ready and we can access it in Home Assistant while inside our home network. But we don’t want it only that way. We want anyone to be able to visit the link without having access to our home network.</p>
<p>I will be implementing this part with the aid of a Home Assistant Cloudflared Add-on that leverages Cloudflare Tunnel. Here is the <a target="_blank" href="https://github.com/brenner-tobias/addon-cloudflared">Github repository</a> – the installation is simple and stress-free.</p>
<p>After going through the setup and having remote access to your Home Assistant network (remember to have 2FA turned on), go to the Cloudflared Add-on configuration tab and edit the Additional Hosts part.</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">hostname:</span> <span class="hljs-string">subdomain_you_want.your_domain.xyz</span>
  <span class="hljs-attr">service:</span> <span class="hljs-string">http://ha_ip:3000</span>
  <span class="hljs-attr">disableChunkedEncoding:</span> <span class="hljs-literal">true</span>
</code></pre>
<p>Save and restart the Add-on and check the logs. You should see it creating a DNS entry for the hostname you added.</p>
<p>As another security step, go to your Grafana Add-on Configuration tab. Add these values to the environment variables.</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">GF_AUTH_ANONYMOUS_ENABLED</span>
  <span class="hljs-attr">value:</span> <span class="hljs-string">"true"</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">GF_AUTH_ANONYMOUS_ORG_ROLE</span>
  <span class="hljs-attr">value:</span> <span class="hljs-string">"Viewer"</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">GF_AUTH_DISABLE_LOGIN_FORM</span>
  <span class="hljs-attr">value:</span> <span class="hljs-string">"true"</span>
</code></pre>
<ul>
<li><p><code>GF_AUTH_ANONYMOUS_ENABLED</code>: Anyone who visits Grafana without logging in will still be allowed in.</p>
</li>
<li><p><code>GF_AUTH_ANONYMOUS_ORG_ROLE</code>: This sets the default permission for anonymous users. In this case, anonymous users will have the viewer role.</p>
</li>
<li><p><code>GF_AUTH_DISABLE_LOGIN_FORM</code>: Disables the login form on the Grafana login page. Make sure you are already logged in on the remote hostname. But you can always edit this on the Add-on Configuration tab if you get locked out.</p>
</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Finally, go to the Remote hostname for your Grafana and you should see the Grafana home page. Then go to your dashboards and click on the solar dashboard created. Share it and choose publicly. Now you can share that link (the URL on that page and not the actual copied URL from the share button) with anyone and they can get to see your beautiful dashboard.</p>
<p>This method serves as an all-in-one way of having everything done, through your Home Assistant machine. I hope you had fun tinkering, see you next time.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up a Home VPN Using Tailscale on a Raspberry Pi ]]>
                </title>
                <description>
                    <![CDATA[ In this article, you’ll learn how to set up a VPN which you can host on a Raspberry Pi. I am a fan of Raspberry Pis because these small form factor computers are a favourite tool for tinkerers, like me. This VPN will allow you to access your home net... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/set-up-a-home-vpn-using-tailscale-on-a-raspberry-pi/</link>
                <guid isPermaLink="false">67e6c11d423cd4f90a6350ab</guid>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Raspberry Pi ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vpn ]]>
                    </category>
                
                    <category>
                        <![CDATA[ networking ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Homelab ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Anomfueme ]]>
                </dc:creator>
                <pubDate>Fri, 28 Mar 2025 15:32:45 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743175949441/1a8c4705-556c-4a1f-899a-9ac8e968fdc3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, you’ll learn how to set up a VPN which you can host on a Raspberry Pi. I am a fan of Raspberry Pis because these small form factor computers are a favourite tool for tinkerers, like me.</p>
<p>This VPN will allow you to access your home network from anywhere as if you’re still at home. So why is this useful, you might ask? Well, it allows you to use your home network IP, no matter where you are, which is a good for privacy.</p>
<p>In this article, we’ll use <a target="_blank" href="https://github.com/tailscale/tailscale">Tailscale</a>, an open-source mesh VPN (Virtual Private Network) service that streamlines connecting devices and services securely across different networks. It enables encrypted point-to-point connections using the open-source <a target="_blank" href="https://www.wireguard.com/">WireGuard</a> protocol. This means that only devices on your private network can communicate with each other.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-install-raspberry-pi-os-lite-32-bit">Install Raspberry Pi OS Lite (32-bit)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-boot-the-raspberry-pi">Boot The Raspberry Pi</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-ssh-into-the-raspberry-pi-and-login">SSH Into The Raspberry Pi and Login</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-install-tailscale-on-raspberry-pi">Install Tailscale on Raspberry Pi</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-key-expiry">Key Expiry</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-configuring-the-raspberry-pi-as-an-exit-node">Configuring the Raspberry Pi as an Exit Node</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li><p>Raspberry Pi (I am working with a Raspberry Pi 5)</p>
</li>
<li><p><a target="_blank" href="https://www.raspberrypi.com/software/">Raspberry Pi Imager</a></p>
</li>
<li><p>A Micro SD Card (8GB is enough)</p>
</li>
<li><p>A Micro SD Card reader for your computer.</p>
</li>
<li><p>Home Router</p>
</li>
<li><p>A <a target="_blank" href="https://tailscale.com/">Tailscale</a> account</p>
</li>
</ul>
<h2 id="heading-install-raspberry-pi-os-lite-32-bit">Install Raspberry Pi OS Lite (32-bit)</h2>
<p>We’ll start this process by installing the Raspberry Pi OS Lite (32-bit) on the micro SD card we have. We will be making use of the Raspberry Pi Imager software which is available for free <a target="_blank" href="https://www.raspberrypi.com/software/">here</a>.</p>
<p>When you run the imager software, pick the Raspberry Pi Device, which for me is a Raspberry Pi 5.</p>
<p>Then in Operating System, click on Raspberry Pi OS (other), then scroll down to Raspberry Pi OS Lite (32-bit)</p>
<p>Next, select your SD card which you have inserted into the card reader, and the card reader into the computer. Your screen should look similar to what you see below. Click on next.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742929198415/b3cd3476-ed82-4db3-9472-f13df2207ca9.png" alt="A Screenshot of the Raspberry Pi Imager software start menu." class="image--center mx-auto" width="751" height="538" loading="lazy"></p>
<p>After next, you should see a pop-up asking if you would like to apply OS customisation settings.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742929274780/4482dd16-8f42-41ec-b1cd-af288180adcb.png" alt="A screenshot of the Raspberry Pi Imager software customisation prompt menu" class="image--center mx-auto" width="703" height="497" loading="lazy"></p>
<p>Next, click on edit settings. Enable set hostname and write the name you want to give the Pi. For this tutorial, I will be using <code>dapivpn</code><em>.</em> Then enable set username and password. Pick a username and a strong and secure password</p>
<p>You can enable configure wireless LAN if you plan to use Wifi, but if you are team Ethernet cable, you can skip this. I will be using WiFi in this tutorial though.</p>
<p>Now you’ll need to enable set local settings and pick your correct time zone and keyboard layout.</p>
<p>After that, go to the Services tab, then enable SSH and click on “Use password authentication”. Then click save, then yes on the apply customisation screen, and yes again. Remember this will erase all the data on the SD card, so make sure you’re using one without any important files on it.</p>
<p>This is how your Raspberry Pi Imager should look now:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742929363470/0c7663d4-a908-4be1-9865-caa665a2ee95.png" alt="A screenshot of the Raspberry Pi Imager software performing the write operation." class="image--center mx-auto" width="721" height="513" loading="lazy"></p>
<h3 id="heading-boot-the-raspberry-pi">Boot the Raspberry Pi</h3>
<p>After this is done, take the SD card and insert it into your Raspberry Pi. Then plug the power cable into the Raspberry Pi and wait some minutes for it to boot properly. You will know it is ready when the green LED light stays on.</p>
<p>Now you should go to your router and set a static IP to the Raspberry Pi. For mine, I set it to <code>192.168.8.21</code><em>.</em></p>
<h3 id="heading-ssh-into-the-raspberry-pi-and-login">SSH into the Raspberry Pi and Login</h3>
<p>Open up your command line terminal. Type “<code>ssh &lt;pi username&gt;@&lt;raspberry_pi_ip_address&gt;</code>”. For me, this would be:</p>
<pre><code class="lang-bash">ssh danpi@192.168.8.21
</code></pre>
<p>Then type in the password you used. You should see your username and the Pi hostname and this confirms you have logged in successfully to it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743088985613/480325b2-496c-4161-96c6-f150f4020922.png" alt="Command line interface showing a successful SSH process" class="image--center mx-auto" width="747" height="382" loading="lazy"></p>
<p>Type in:</p>
<pre><code class="lang-bash">sudo apt update &amp;&amp; sudo apt upgrade -y
</code></pre>
<p>You run this command to make sure everything is up to date locally.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742929744252/6200841f-98bb-4bfa-8c30-38159a963e2b.png" alt="Command line interface showing the update command running" class="image--center mx-auto" width="748" height="226" loading="lazy"></p>
<p>Now reboot your Pi after this by typing:</p>
<pre><code class="lang-bash">sudo reboot
</code></pre>
<h2 id="heading-install-tailscale-on-raspberry-pi">Install Tailscale on Raspberry Pi</h2>
<p>Now you’re going to add Tailscale’s package signing key and repository.</p>
<pre><code class="lang-bash">curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg &gt;/dev/null 
curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
</code></pre>
<p>Install Tailscale using these commands:</p>
<pre><code class="lang-bash">sudo apt-get update
sudo apt-get install tailscale
</code></pre>
<p>Next, you need to connect your Pi to your Tailscale network and authenticate. You can do that with the following command:</p>
<pre><code class="lang-bash">sudo tailscale up
</code></pre>
<p>Your browser should look like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742929786462/4d17cfae-0e87-449f-ac13-413a65f3f338.png" alt="Screenshot of the browser showing the authentication screen" class="image--center mx-auto" width="695" height="262" loading="lazy"></p>
<p>To locate the Tailscale IPv4 address for the Raspberry Pi, run this command:</p>
<pre><code class="lang-bash">tailscale ip -4
</code></pre>
<p>You can also see it on the Tailscale dashboard in your browser.</p>
<p>At this point, you’re done installing Tailsacle and you just need to do some finishing touches.</p>
<h2 id="heading-key-expiry">Key Expiry</h2>
<p>There is something you need to know when it comes to adding a device to Tailsacle. By default, and as a security feature, Tailscale requires devices to re-authenticate after a certain period of time has elapsed, usually 180 days.</p>
<p>If the re-authentication does not occur, keys expire and the connection stops working. It’s up to you to choose what you prefer, as this is a security feature that comes with some inconvenience.</p>
<p>I will be disabling the key expiry on the Raspberry Pi, as I fully trust it. To do this, you need to:</p>
<ul>
<li><p>Open the <a target="_blank" href="https://login.tailscale.com/admin/machines">Machines</a> page of the Tailscale admin console.</p>
</li>
<li><p>Find the Raspberry Pi on the row and select the option menu there.</p>
</li>
<li><p>Click on the Disable Key Expiry option. You should see an Expiry Disable label below the machine name.</p>
</li>
</ul>
<h2 id="heading-how-to-configure-the-raspberry-pi-as-an-exit-node">How to Configure the Raspberry Pi as an Exit Node</h2>
<p>Another thing you’ll need to know about when it comes to Tailscale is what an exit node is. A Tailscale exit node is a designated device in your Tailscale network that routes all of your internet traffic through it. No matter where you are, once you have this device activated as an exit node, when you turn on Tailscale, it routes your internet traffic through the device.</p>
<p>Ideally, you want a device that is powered on 24/7 to serve as your exit node. That’s why we are picking the Raspberry Pi, as it is a low-powered computer.</p>
<p>We are already 90% of the way, as we have Tailscale running on our Pi. Remember to also have Tailscale installed on as many devices on your local network as possible. What’s left is to allow your Pi to act as an exit node, so all your internet traffic or LAN traffic routes through it, giving you access to:</p>
<ul>
<li><p>Local network devices at home</p>
</li>
<li><p>Your home public IP</p>
</li>
<li><p>Internal services like NAS, printers, cameras, and so on</p>
</li>
</ul>
<p>To do this, SSH into your Raspberry Pi and follow these steps:</p>
<ul>
<li><p>Enable IP Forwarding. IP forwarding allows your Raspberry Pi to pass traffic between its network interfaces. Run the commands below line by line:</p>
<pre><code class="lang-bash">  <span class="hljs-built_in">echo</span> <span class="hljs-string">"net.ipv4.ip_forward=1"</span> | sudo tee -a /etc/sysctl.conf

  <span class="hljs-built_in">echo</span> <span class="hljs-string">"net.ipv6.conf.all.forwarding=1"</span> | sudo tee -a /etc/sysctl.conf

  sudo sysctl -p /etc/sysctl.conf
</code></pre>
</li>
<li><p>Advertise the Raspberry Pi as an exit node:</p>
<pre><code class="lang-bash">  sudo tailscale up --advertise-exit-node
</code></pre>
</li>
<li><p>Open the <a target="_blank" href="https://login.tailscale.com/admin/machines">Machines</a> page of the Tailscale admin console.</p>
</li>
<li><p>Find the Raspberry Pi on the row. You should see an Exit Node label on its name.</p>
</li>
<li><p>Click on the options menu there and select Edit Route Settings.</p>
</li>
<li><p>Check the box for Use as an exit node, then save.</p>
</li>
</ul>
<p>Now you should see the option of routing the internet through an exit node when you open up your Tailscale app on mobile or PC or anywhere you have it installed. When you see that option, you will also see the Raspberry Pi as an exit node option. You can also add more devices as an exit node if you want more options.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Using the Tailscale app on other devices, you can now route traffic securely through the Raspberry Pi by selecting it as an exit node. Tailscale also provides clear, <a target="_blank" href="https://tailscale.com/kb/1408/quick-guide-exit-nodes#use-an-exit-node">step-by-step guides</a> tailored to each device type for setting up and using an exit node.</p>
<p>You can now be away from your home internet but still connect to the internet as if you were home. See you next time.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn IoT Home Automation by Building a Project ]]>
                </title>
                <description>
                    <![CDATA[ Smart home automation brings convenience and innovation to everyday living, and now you can create your own smart system from scratch. By using ESP32 microcontrollers, LEDs, servo motors, and either a Raspberry Pi or your laptop, you’ll gain the skil... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-iot-home-automation-by-building-a-project/</link>
                <guid isPermaLink="false">677ee0c4af5f7b551e7f3581</guid>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 02 Jan 2025 05:00:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1736368285273/dd0f70a4-a8c5-4f1a-802f-bf5d8479bd2a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Smart home automation brings convenience and innovation to everyday living, and now you can create your own smart system from scratch. By using ESP32 microcontrollers, LEDs, servo motors, and either a Raspberry Pi or your laptop, you’ll gain the skills to build a complete home automation system with this project-based course. This course emphasizes industry-standard tools and best practices, making it an excellent resource for beginners and experienced developers alike.</p>
<p>We just published a <strong>Home Automation with ESP32</strong> course on the freeCodeCamp.org YouTube channel, created by Ebenezer Asabre. This course walks you through every step of building a smart system, from setting up the hardware to developing a web-based control interface. By the end of the course, you’ll have a fully functional system that you can customize and expand further.</p>
<h3 id="heading-what-youll-learn">What You’ll Learn</h3>
<ul>
<li><p><strong>Hardware Setup</strong>: You’ll start by setting up the ESP32 microcontroller, LEDs, and servo motors, establishing a solid hardware foundation for your smart system.</p>
</li>
<li><p><strong>System Architecture</strong>: Understand how different components—hardware, software, and communication protocols—work together to create a seamless system. You’ll also learn to design a software flowchart to guide your project development.</p>
</li>
<li><p><strong>MQTT Protocol</strong>: Learn how to configure the ESP32 as an MQTT client to send and receive messages. The MQTT protocol is a key technology for Internet of Things (IoT) projects, enabling efficient communication.</p>
</li>
<li><p><strong>Database Management</strong>: Use PostgreSQL to manage your system’s data and integrate it with a Node.js server. You’ll set up models for storing and handling automation system information.</p>
</li>
<li><p><strong>Server Design</strong>: Master the modular structure of a Node.js server with service, controller, and route modules, making your application maintainable and scalable.</p>
</li>
<li><p><strong>Real-Time Communication</strong>: Implement an MQTT broker and real-time communication using Socket.io to establish reliable connections between your ESP32 devices and control interface.</p>
</li>
<li><p><strong>Web-Based Control</strong>: Build a user-friendly front end using HTML and Embedded JavaScript (EJS). This interface will let you control your smart devices remotely and interact with your system intuitively.</p>
</li>
</ul>
<h3 id="heading-why-take-this-course">Why Take This Course?</h3>
<p>This course is perfect for anyone interested in IoT, whether you're a hobbyist exploring automation or a developer looking to expand your skill set. You'll gain practical experience with popular technologies like ESP32, MQTT, PostgreSQL, and Node.js, all while working on a real-world project. By the end of the course, you'll understand how to design, build, and deploy smart systems using industry-standard tools and techniques.</p>
<h3 id="heading-what-youll-achieve">What You’ll Achieve</h3>
<ul>
<li><p><strong>Practical Knowledge</strong>: Work hands-on with ESP32 microcontrollers and key IoT technologies.</p>
</li>
<li><p><strong>Software Development Skills</strong>: Create robust applications using Node.js, MQTT, and PostgreSQL.</p>
</li>
<li><p><strong>System Design Expertise</strong>: Learn to design and build scalable, real-time systems.</p>
</li>
<li><p><strong>A Portfolio Project</strong>: Develop a fully functional home automation system you can showcase to employers or use as a foundation for future projects.</p>
</li>
</ul>
<p>Watch the full course <a target="_blank" href="https://youtu.be/eidD14dXW8s">on the freeCodeCamp.org YouTube channel</a> (1-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/eidD14dXW8s" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up Zigbee2MQTT with Docker for Home Automation ]]>
                </title>
                <description>
                    <![CDATA[ Zigbee2MQTT is an open-source tool that lets you manage all of your Zigbee devices locally, so you don’t need cloud services or multiple proprietary hubs. This gives you more control and flexibility, whether used on its own or integrated with platfor... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-set-up-zigbee2mqtt-with-docker/</link>
                <guid isPermaLink="false">673c8cdcb7f79bc9aa2f300f</guid>
                
                    <category>
                        <![CDATA[ Internet of Things ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joyce Lin ]]>
                </dc:creator>
                <pubDate>Tue, 19 Nov 2024 13:04:28 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731778246828/8371f4de-6771-4f57-9e2c-9c57ad651950.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://www.zigbee2mqtt.io/">Zigbee2MQTT</a> is an open-source tool that lets you manage all of your <a target="_blank" href="https://en.wikipedia.org/wiki/Zigbee">Zigbee</a> devices locally, so you don’t need cloud services or multiple proprietary hubs. This gives you more control and flexibility, whether used on its own or integrated with platforms like <a target="_blank" href="https://www.home-assistant.io/">Home Assistant</a> or <a target="_blank" href="https://nodered.org/">Node-RED</a>.</p>
<p>In this guide, I’ll show you how to set it up using <a target="_blank" href="https://www.docker.com/">Docker</a> for a streamlined, privacy-focused smart home. Docker provides an efficient way to run Zigbee2MQTT as a standalone service, offering a lightweight, modular setup – no Home Assistant required.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731723376381/d983ba57-72ba-4e06-b994-c6b30ad36ca5.png" alt="Diagram showing the integration of Zigbee devices into a local network using Raspberry Pi" class="image--center mx-auto" width="1280" height="500" loading="lazy"></p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-key-iot-concepts-in-this-tutorial">Key IoT Concepts in this Tutorial</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-youll-need">What You’ll Need</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-youll-do">What You’ll Do</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-prepare-your-environment">How to Prepare Your Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-the-zigbee2mqtt-configuration">How to Set Up the Zigbee2MQTT Configuration</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-zigbee2mqtt-and-mqtt-broker-in-docker">How to Set up Zigbee2MQTT and MQTT Broker in Docker</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-launch-the-containers">Launch the Containers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pair-your-zigbee-devices">Pair Your Zigbee devices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-an-automation-script">How to Create an Automation Script</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-whats-next">What’s Next?</a></p>
</li>
</ul>
<h2 id="heading-key-iot-concepts-in-this-tutorial">Key IoT Concepts in this Tutorial</h2>
<p>Here are the key concepts related to the Internet of Things (IoT) and smart homes that you’ll be working with:</p>
<ul>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Zigbee">Zigbee</a> is a wireless communication protocol used in smart home devices. It relies on a Zigbee coordinator to communicate with devices like lights, sensors, and switches within a local mesh network. This network allows devices to relay signals to extend coverage and reliability.</p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/MQTT">MQTT (Message Queuing Telemetry Transport)</a> is a lightweight messaging protocol for low-bandwidth and high-latency environments. It uses an MQTT broker to manage communication between devices using a publish/subscribe (pub/sub) model, where devices can either send or receive messages based on specific topics.</p>
</li>
<li><p><a target="_blank" href="https://www.zigbee2mqtt.io/">Zigbee2MQTT</a> is a bridge application that connects Zigbee devices to an MQTT broker. It translates Zigbee signals into MQTT messages, and vice versa. Zigbee2MQTT supports a wide range of devices from different manufacturers.</p>
</li>
</ul>
<h2 id="heading-what-youll-need"><strong>What You’ll Need</strong></h2>
<ol>
<li><p>A Zigbee coordinator connected to your network or device. I have an <a target="_blank" href="https://smlight.tech/product/slzb-06/">SLZB-06</a> ($65 USD) connected to my network.</p>
</li>
<li><p>A device capable of running Docker, such as a Raspberry Pi or Linux server. I flashed a Raspberry Pi 4 - Model B.</p>
</li>
</ol>
<h2 id="heading-how-to-prepare-your-environment"><strong>How to Prepare Your Environment</strong></h2>
<ol>
<li><p>SSH into your Pi using the following command in your terminal window, where <code>pi</code> is the username of your Raspberry Pi OS and <code>&lt;RaspberryPi_IP&gt;</code> is the IP address of your Raspberry Pi on your local network.</p>
<pre><code class="lang-bash"> ssh pi@&lt;RaspberryPi_IP&gt;
</code></pre>
</li>
<li><p>Install Docker by inputting the following command at the SSH prompt.</p>
<pre><code class="lang-bash"> curl -sSL https://get.docker.com | sh
</code></pre>
</li>
<li><p>Give permissions to the current logged in user. You may then need to close the SSH connection, and re-connect, if the permissions hasn’t taken effect.</p>
<pre><code class="lang-bash"> sudo usermod -aG docker <span class="hljs-variable">$USER</span>
</code></pre>
</li>
</ol>
<h2 id="heading-how-to-set-up-the-zigbee2mqtt-configuration">How to Set Up the Zigbee2MQTT Configuration</h2>
<ol>
<li><p>Create a new project directory, and also a <code>/data</code> directory to store configuration files and data persistently.</p>
<pre><code class="lang-bash"> mkdir -p ~/zigbee2mqtt/data
</code></pre>
</li>
<li><p>Create the configuration file.</p>
<pre><code class="lang-bash"> touch ~/zigbee2mqtt/data/configuration.yaml
</code></pre>
</li>
<li><p>Open file with your preferred text editor, like using <code>nano</code> as shown below.</p>
<pre><code class="lang-bash"> nano ~/zigbee2mqtt/data/configuration.yaml
</code></pre>
</li>
<li><p>Paste the following YAML code into the configuration file from the text editor interface.</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">homeassistant:</span> <span class="hljs-literal">false</span>
 <span class="hljs-attr">permit_join:</span> <span class="hljs-literal">false</span>
 <span class="hljs-attr">mqtt:</span>
   <span class="hljs-attr">base_topic:</span> <span class="hljs-string">zigbee2mqtt</span>
   <span class="hljs-attr">server:</span> <span class="hljs-string">'mqtt://mqtt:1883'</span>
 <span class="hljs-attr">serial:</span>
   <span class="hljs-attr">port:</span> <span class="hljs-string">'tcp://&lt;IP_OF_ZIGBEE_COORDINATOR&gt;:&lt;PORT&gt;'</span>
 <span class="hljs-attr">frontend:</span>
   <span class="hljs-attr">port:</span> <span class="hljs-number">8080</span>
</code></pre>
</li>
<li><p>Update the following details within the <code>configuration.yaml</code> file, and save the changes.</p>
<ul>
<li><p><code>&lt;MQTT_BROKER_IP&gt;</code>: Your MQTT broker's IP or hostname.</p>
</li>
<li><p><code>port</code>: This value depends on how your Zigbee coordinator is connected:</p>
<ul>
<li><p>If your Zigbee coordinator is connected to the network, you can configure the <code>port</code> using TCP/IP as shown in the example above, for example <code>tcp://192.168.1.xxx:6638</code> where the SLZB-06 is located at <code>192.168.1.xxx</code> on the local network and <code>6638</code> is the default port for that Zigbee coordinator.</p>
</li>
<li><p>If the Zigbee coordinator is connected to your device, you can find the serial port (such as <code>/dev/ttyUSB0</code>) by running <code>ls /dev/tty*</code> before and after plugging in the adapter to your device.</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<h2 id="heading-how-to-set-up-zigbee2mqtt-and-mqtt-broker-in-docker">How to Set up Zigbee2MQTT and MQTT Broker in Docker</h2>
<ol>
<li><p>In the root of your project directory, create a <code>docker-compose.yaml</code> file to set up the <a target="_blank" href="https://hub.docker.com/r/koenkk/zigbee2mqtt/">Zigbee2MQTT container</a> and <a target="_blank" href="https://hub.docker.com/_/eclipse-mosquitto">Eclipse Mosquitto broker container</a> to handle communication between Zigbee2MQTT and other services.</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">services:</span>
   <span class="hljs-attr">zigbee2mqtt:</span>
     <span class="hljs-attr">container_name:</span> <span class="hljs-string">zigbee2mqtt</span>
     <span class="hljs-attr">image:</span> <span class="hljs-string">koenkk/zigbee2mqtt</span>
     <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>
     <span class="hljs-attr">volumes:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-string">./data:/app/data</span>
       <span class="hljs-bullet">-</span> <span class="hljs-string">/run/udev:/run/udev:ro</span>
     <span class="hljs-attr">ports:</span>
       <span class="hljs-comment"># Frontend port</span>
       <span class="hljs-bullet">-</span> <span class="hljs-number">8080</span><span class="hljs-string">:8080</span>
     <span class="hljs-attr">environment:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-string">TZ=American/Los_Angeles</span>
   <span class="hljs-attr">mqtt:</span>
     <span class="hljs-attr">image:</span> <span class="hljs-string">eclipse-mosquitto:2.0</span>
     <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>
     <span class="hljs-attr">volumes:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-string">"./mosquitto:/mosquitto"</span>
     <span class="hljs-attr">ports:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-string">"1883:1883"</span>
       <span class="hljs-bullet">-</span> <span class="hljs-string">"9001:9001"</span>
     <span class="hljs-attr">command:</span> <span class="hljs-string">"mosquitto -c /mosquitto-no-auth.conf"</span>
</code></pre>
</li>
<li><p>Update the <code>TZ</code> environment variable if you are located in a different time zone, and save any changes.</p>
</li>
</ol>
<h2 id="heading-launch-the-containers"><strong>Launch the Containers</strong></h2>
<ol>
<li><p>Run the containers.</p>
<pre><code class="lang-bash"> docker compose up -d
</code></pre>
</li>
<li><p>Test the setup by checking the logs to confirm Zigbee2MQTT is running without errors. And look for lines indicating successful connection to the MQTT broker and Zigbee network initialization.</p>
<pre><code class="lang-bash"> docker compose logs
</code></pre>
</li>
</ol>
<h2 id="heading-pair-your-zigbee-devices"><strong>Pair Your Zigbee devices</strong></h2>
<ol>
<li><p>Once Zigbee2MQTT is running smoothly, you can access the frontend at <code>http://&lt;your-device-IP&gt;:8080</code> from a web browser to pair and manage your Zigbee devices.</p>
</li>
<li><p>Enable pairing by clicking <strong>Permit Join (all)</strong>, and then pair your devices by putting them in pairing mode, for example holding down a reset button.</p>
</li>
<li><p>Finish pairing all the Zigbee devices that you wish to use in an automation. In the screenshot below, I have paired an Aqara button and Third Reality smart plug.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731775615109/616320a6-77d0-4d14-813e-7dfde9fb8f0a.png" alt="Aqara button and Third Reality smart plug in the Zigbee2MQTT frontend" class="image--center mx-auto" width="2888" height="836" loading="lazy"></p>
</li>
<li><p>Give your devices a friendly name by using the pencil icon. Make sure to choose a unique name to avoid messaging conflicts in the following steps. For example, if you have 2 smart plugs, you can name them <code>smart-plug-bedroom</code> and <code>smart-plug-office</code>.</p>
</li>
</ol>
<p>MQTT brokers follow a pub/sub messaging pattern which involves the following:</p>
<ul>
<li><p><strong>Subscribing to MQTT topics</strong> like <code>zigbee2mqtt/aqara-button</code> to monitor device states like listening for button presses.</p>
</li>
<li><p><strong>Publishing to MQTT topics</strong> like <code>zigbee2mqtt/third-reality/set</code> to send commands to devices like a smart plug to turn on a light.</p>
</li>
</ul>
<p>A topic such as <code>zigbee2mqtt/third-reality/set</code> is broken down into 3 parts:</p>
<ul>
<li><p><code>zigbee2mqtt</code> refers to the base topic (default for Zigbee2MQTT is <code>zigbee2mqtt</code>).</p>
</li>
<li><p><code>third-reality</code> refers to a specific device or group using the friendly name shown in the Zigbee2MQTT frontend.</p>
</li>
<li><p><code>set</code> allows you to control the device or group using a JSON message such as <code>{"state": "TOGGLE"}</code>.</p>
</li>
</ul>
<ol>
<li><p>Input the following command to see the MQTT messages being published to Zigbee2MQTT.</p>
<pre><code class="lang-bash"> docker logs -f zigbee2mqtt
</code></pre>
</li>
<li><p>Complete an action on a Zigbee device, for example pushing a button, and make a note of which topics you want to utilize in your automation for the next steps. For example, in the screenshot of the logs below, there is an MQTT topic published called <code>zigbee2mqtt/Aqara</code> when the Aqara button is pressed.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731550585620/2f043360-75e1-4ef8-9549-a6bfe576ceb0.png" alt="Logs from pressing the Agara button" class="image--center mx-auto" width="2162" height="86" loading="lazy"></p>
<h2 id="heading-how-to-create-an-automation-script"><strong>How to Create an Automation Script</strong></h2>
<p>To set up an automation, you can use an external system like Home Assistant or Node-RED, or use Zigbee2MQTT’s <a target="_blank" href="https://www.zigbee2mqtt.io/guide/configuration/more-config-options.html#external-converters">external converters</a> to respond to MQTT messages from the broker.</p>
<p>You won’t be doing that. Instead, let’s write a JavaScript script to handle this automation, to keep the functionality modular and independent.</p>
<ol>
<li><p>From the command line prompt of your terminal window, install the NodeSource setup script on your Raspberry Pi.</p>
<pre><code class="lang-bash"> curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
</code></pre>
</li>
<li><p>Install <a target="_blank" href="https://nodejs.org/en/download/package-manager">Node.js</a> to use as the runtime for your script.</p>
<pre><code class="lang-bash"> sudo apt install -y nodejs
</code></pre>
</li>
<li><p>Verify the installation went smoothly by showing the installed version.</p>
<pre><code class="lang-bash"> node -v
</code></pre>
</li>
<li><p>Install <a target="_blank" href="https://www.npmjs.com/package/mqtt">MQTT.js</a>, the MQTT client library for Node.js.</p>
<pre><code class="lang-bash"> npm install mqtt
</code></pre>
</li>
<li><p>Create a file called <code>automation.js</code> to contain the automation script. In this example, you can run the script on the Raspberry Pi. However, the file can be placed anywhere and doesn’t even need to run on the same device as the MQTT broker. As long as the program can connect to the MQTT broker over the local network, it will function correctly.</p>
<pre><code class="lang-bash"> touch automation.js
</code></pre>
</li>
<li><p>Open the file with your preferred text editor, like Nano shown here.</p>
<pre><code class="lang-bash"> nano automation.js
</code></pre>
</li>
<li><p>Paste the following code into the file.</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> mqtt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mqtt'</span>);

 <span class="hljs-comment">// MQTT broker connection details</span>
 <span class="hljs-keyword">const</span> MQTT_BROKER = <span class="hljs-string">'mqtt://localhost'</span>; <span class="hljs-comment">// Replace with your broker's address</span>
 <span class="hljs-keyword">const</span> BUTTON_TOPIC = <span class="hljs-string">'zigbee2mqtt/aqara-button'</span>; <span class="hljs-comment">// Replace with your button's topic</span>
 <span class="hljs-keyword">const</span> PLUG_TOPIC = <span class="hljs-string">'zigbee2mqtt/third-reality'</span>; <span class="hljs-comment">// Replace with your plug's topic</span>

 <span class="hljs-comment">// Connect to the MQTT broker</span>
 <span class="hljs-keyword">const</span> client = mqtt.connect(MQTT_BROKER);

 <span class="hljs-comment">// Handle connection events</span>
 client.on(<span class="hljs-string">'connect'</span>, <span class="hljs-function">() =&gt;</span> {
     <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Connected to MQTT broker'</span>);
     <span class="hljs-comment">// Subscribe to the button's topic</span>
     client.subscribe(BUTTON_TOPIC, <span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
         <span class="hljs-keyword">if</span> (!err) {
             <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Subscribed to topic: <span class="hljs-subst">${BUTTON_TOPIC}</span>`</span>);
         } <span class="hljs-keyword">else</span> {
             <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Failed to subscribe to topic: <span class="hljs-subst">${BUTTON_TOPIC}</span>`</span>, err);
         }
     });
 });

 <span class="hljs-comment">// Handle incoming messages</span>
 client.on(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">topic, message</span>) =&gt;</span> {
     <span class="hljs-keyword">if</span> (topic === BUTTON_TOPIC) {
         <span class="hljs-keyword">try</span> {
             <span class="hljs-keyword">const</span> payload = <span class="hljs-built_in">JSON</span>.parse(message.toString());
             <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Received message:'</span>, payload);
             <span class="hljs-keyword">const</span> desiredAction = payload.action;

             <span class="hljs-comment">// Check for possible actions</span>
             <span class="hljs-keyword">if</span> (desiredAction === <span class="hljs-string">'single'</span>) {
                 <span class="hljs-comment">// Send a message to the plug's topic to toggle the switch</span>
                 client.publish(<span class="hljs-string">`<span class="hljs-subst">${PLUG_TOPIC}</span>/set`</span>, <span class="hljs-built_in">JSON</span>.stringify({<span class="hljs-string">"state"</span>: <span class="hljs-string">"TOGGLE"</span>}));
                 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Toggling the switch'</span>)
             } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (desiredAction === <span class="hljs-string">'double'</span>) {
                 <span class="hljs-comment">// Send a message to the plug's topic to turn off the switch</span>
                 client.publish(<span class="hljs-string">`<span class="hljs-subst">${PLUG_TOPIC}</span>/set`</span>, <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">state</span>: <span class="hljs-string">'OFF'</span> }));
                 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Turning off the switch'</span>)
             }
         } <span class="hljs-keyword">catch</span> (err) { 
             <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to parse message:'</span>, err.message);
         }           

     }
 });

 <span class="hljs-comment">// Handle errors</span>
 client.on(<span class="hljs-string">'error'</span>, <span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
     <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'MQTT error:'</span>, err);
 });
</code></pre>
<p> This script connects to the MQTT broker and subscribes to the button’s topic (<code>zigbee2mqtt/aqara-button</code>). When a message is received, it examines the payload. If the action is a single click (<code>single</code>), the script sends a toggle command (<code>{state: "TOGGLE"}</code>) to the plug’s topic (<code>zigbee2mqtt/third-reality/set</code>), toggling the plug’s state. A <code>double</code> action turns the plug off.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731777295907/11549e51-c2f9-44cd-af73-a0ba97eeda1e.png" alt="MQTT pub/sub messaging pattern" class="image--center mx-auto" width="1280" height="500" loading="lazy"></p>
<p> Update the MQTT broker connection and topic details at the top of the script as needed to accommodate your own Zigbee devices, and save your changes.</p>
</li>
<li><p>Run the script from the terminal prompt.</p>
<pre><code class="lang-bash"> node automation.js
</code></pre>
</li>
<li><p>Test the setup by pressing the button. The script should log the button action and send a command to toggle on the smart plug. Check the MQTT broker logs if the light doesn’t turn on.</p>
</li>
<li><p>Optional*:* Once the script is working as expected, there are a few more optional steps to make sure the script restarts during reboots. Install a process manager like <a target="_blank" href="https://www.npmjs.com/package/pm2">PM2</a> from the command line prompt of the Raspberry Pi.</p>
<pre><code class="lang-bash">sudo npm install -g pm2
</code></pre>
</li>
<li><p>Start the script again.</p>
<pre><code class="lang-bash">pm2 start automation.js
</code></pre>
</li>
<li><p>Your app should now be daemonized, running in the background, and kept alive forever. Generate and configure a startup script to keep PM2 and your processes alive at every server restart.</p>
<pre><code class="lang-bash">pm2 startup
</code></pre>
</li>
<li><p>Copy and paste the command exactly as shown in the terminal output, and run the suggested command.</p>
</li>
<li><p>Save the process list so PM2 can restore it after a system reboot.</p>
<pre><code class="lang-bash">pm2 save
</code></pre>
</li>
</ol>
<h2 id="heading-whats-next"><strong>What’s Next?</strong></h2>
<p>Now that you’ve created a custom automation, there are more ways to grow your home automation setup.</p>
<ul>
<li><p><strong>Explore more Zigbee devices</strong>: Zigbee2MQTT supports <a target="_blank" href="https://www.zigbee2mqtt.io/supported-devices/">a wide range of devices</a> from various manufacturers.</p>
</li>
<li><p><strong>Add custom behaviors</strong>: Use Zigbee2MQTT’s <a target="_blank" href="https://www.zigbee2mqtt.io/guide/configuration/more-config-options.html#external-converters">external converters</a> to define unique functionality for both supported and unsupported devices.</p>
</li>
<li><p><strong>Scale your setup</strong>: This flexible, lightweight setup is good for beginners and power users alike, who don’t want to get locked into proprietary smart home platforms or cloud services.</p>
</li>
</ul>
<p>If you found this tutorial helpful, don’t forget to check out <a target="_blank" href="https://github.com/loopDelicious/home-automation/blob/main/README.md">my recommended Home Automation hardware</a> and <a target="_blank" href="https://www.youtube.com/@joycejetson">how-to videos on YouTube</a> for more inspiration!</p>
<p>You can watch the video version of this article here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/mGg_9FjDKHQ" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Raspberry Pi? Specs and Models (2021 Guide) ]]>
                </title>
                <description>
                    <![CDATA[ By Veronica Stork Introduction Are you curious about the IoT (Internet of Things?) Have you always wanted to try to make your own robot, smart mirror, or bird feeder camera? What about building a computer for a fraction of the cost of a commercially ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-raspberry-pi-specs-and-models-2021-guide/</link>
                <guid isPermaLink="false">66d46181787a2a3b05af4410</guid>
                
                    <category>
                        <![CDATA[ Internet of Things ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Raspberry Pi ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 25 Aug 2021 16:17:20 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/08/Raspberry-Pi-2-Bare-FL-bigger.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Veronica Stork</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Are you curious about the IoT (Internet of Things?) Have you always wanted to try to make your own robot, smart mirror, or bird feeder camera? What about building a computer for a fraction of the cost of a commercially available machine?</p>
<p>If you said yes to any of these questions, you might enjoy playing around with a Raspberry Pi. </p>
<p>In this article, I'll explain what a Raspberry Pi is (and what it’s not.) Then I'll show you some things you can use it for, and finally, I'll list all of the current models along with their specs.</p>
<h2 id="heading-what-is-raspberry-pi">What is Raspberry Pi?</h2>
<p>A Raspberry Pi is a single board computer (SBC) created in the United Kingdom by the <a target="_blank" href="https://www.raspberrypi.org/about/">Raspberry Pi Foundation</a>. It's a charity that "works to put the power of computing and digital making into the hands of people all over the world."</p>
<p>The first model of the Raspberry Pi was released in 2012, and as of 2021 there have been five generations of the boards. A microcontroller (more about that later), called the Pico was released in early 2021.</p>
<h3 id="heading-gpio-pins">GPIO Pins</h3>
<p>Something that sets the Pi apart from your average computer is the set of 40 GPIO (General Purpose Input Output) pins. </p>
<p>GPIO pins are pretty much exactly what they sound like. They are designed to input and output single bits. This means that you can use them to add all sorts of functionality to your Raspberry Pi using switches, buzzers, lights, sensors, and so on.</p>
<h3 id="heading-raspberry-pi-hats">Raspberry Pi HATs</h3>
<p>There are a number of add-on boards that you can attach to the Raspberry Pi using the GPIO pins. </p>
<p>Raspberry Pi HATs (Hardware Attached on Top) are add-on boards designed according to certain specifications. The Raspberry Pi can automatically detect and configure the HATs, making set-up easy.</p>
<p>There is a <em>huge</em> variety of HATs and other add-on boards that you can buy, but here are some notable ones:</p>
<ul>
<li><strong><a target="_blank" href="https://www.raspberrypi.org/products/poe-plus-hat/">PoE+ HAT</a></strong> – Power over Ethernet HAT</li>
<li><strong><a target="_blank" href="https://www.raspberrypi.org/products/sense-hat/">Sense HAT</a></strong> – Designed for the <a target="_blank" href="https://astro-pi.org/">Astro Pi mission</a>, the Sense HAT includes a gyroscope, an accelerometer, a magnetometer, and sensors for temperature, humidity, and Barometric pressure.  </li>
<li><strong><a target="_blank" href="https://shop.pimoroni.com/products/explorer-hat">Pimoroni Explorer HAT Pro</a></strong> – All-purpose board featuring touch pads, crocodile clip pads, and analog inputs</li>
<li><strong><a target="_blank" href="https://www.adafruit.com/product/2340">Adafruit Capacitive Touch HAT</a></strong> – Similar to a <a target="_blank" href="https://makeymakey.com/">Makey Makey</a>, this HAT allows you to use any conductive object to trigger events using Python.</li>
</ul>
<h3 id="heading-raspberry-pi-operating-systems">Raspberry Pi Operating Systems</h3>
<p>The Raspberry Pi often runs some form of Linux, but there are a ton of operating systems that you can use. </p>
<p>On the official website, you will find a list of <a target="_blank" href="https://www.raspberrypi.org/software/operating-systems/">operating system images</a> available for download. These include the official Raspberry Pi OS, Debian Buster, and Ubuntu (desktop, core, and server.) </p>
<p>You will also find RetroPie, a specialized gaming platform operating system, and LibreELEC, a lightweight Linux distribution specifically created for use with the open source media player <a target="_blank" href="https://kodi.tv/">Kodi</a>.</p>
<h3 id="heading-raspberry-pi-vs-arduino">Raspberry Pi VS Arduino</h3>
<p>You may have heard of Arduino boards and wondered what the difference is between them and the Raspberry Pi. </p>
<p>The main difference is that Pis (with the exception of the Pico and the RP2040) are full computers with operating systems. You can connect your Pi to a keyboard, mouse, and monitor and use it like you would use a Mac or PC. </p>
<p>The Arduino, on the other hand, is a microcontroller. It cannot function independently as a computer, but is programmed using a computer and then used to control things like cameras, lights, robots, and so on. </p>
<p>As the official Arduino website puts it: “Arduino boards are able to read inputs… and turn it into an output.”</p>
<h2 id="heading-what-is-the-raspberry-pi-used-for">What is the Raspberry Pi Used For?</h2>
<p>Search the internet and you will find a huge array of projects created using Raspberry Pis. </p>
<p>Common use cases include home automation, gaming consoles, servers, WiFi extenders, streaming devices, weather stations, and home computers. (Fun fact: much of this article was written on a Raspberry Pi.)</p>
<p>During the Covid-19 pandemic, Raspberry Pi's were even used to control <a target="_blank" href="https://www.engadget.com/raspberry-pi-ventilators-covid-19-163729140.html">ventilators</a> in some hard-hit areas.</p>
<h2 id="heading-raspberry-pi-models">Raspberry Pi Models</h2>
<p>All models of Raspberry Pi that are currently in production have 40 GPIO pins. </p>
<p>This list does not include the Raspberry Pi microcontrollers, the Pico and the RP2040. </p>
<p>You can find out where to purchase any of these boards on the <a target="_blank" href="https://www.raspberrypi.org/products/">Raspberry Pi website</a>.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Model</td><td>Processor</td><td>RAM</td><td>Connectivity</td><td>USB</td><td>HDMI</td><td>Power</td><td>Price</td></tr>
</thead>
<tbody>
<tr>
<td>Zero</td><td>BCM2835</td><td>512MB</td><td>None</td><td>Micro USB OTG</td><td>Mini HDMI</td><td>Micro USB</td><td>$5</td></tr>
<tr>
<td>Zero W</td><td>BCM2835</td><td>512MB</td><td>802.11 b/g/n wireless LAN</td><td>Micro USB OTG</td><td>Mini HDMI</td><td>Micro USB</td><td>$10</td></tr>
<tr>
<td>Raspberry Pi 1 Model A+</td><td>BCM2835</td><td>512MB</td><td>None</td><td>1x USB 2.0</td><td>Full-size HDMI</td><td>Micro USB</td><td>$25</td></tr>
<tr>
<td>Raspberry Pi 1 Model B+</td><td>BCM2835</td><td>512MB</td><td>100 base ethernet</td><td>4x USB 2.0</td><td>Full-size HDMI</td><td>Micro USB</td><td>$30</td></tr>
<tr>
<td>Raspberry Pi 3 Model A+</td><td>BCM2837B0</td><td>512MB</td><td>dual-band wireless, Bluetooth 4.2</td><td>1x USB 2.0</td><td>Full-size HDMI</td><td>5V DC via Micro USB</td><td>$25</td></tr>
<tr>
<td>Raspberry Pi 3 Model B</td><td>BCM2837</td><td>1GB</td><td>ethernet, wireless, BLE</td><td>4x USB 2.0</td><td>Full-size HDMI</td><td>2.1A via Micro USB</td><td>$35</td></tr>
<tr>
<td>Raspberry Pi 3 Model B+</td><td>BCM2837B0</td><td>1GB</td><td>dual-band wireless, Bluetooth 4.2, BLE</td><td>4x USB 2.0</td><td>Full-size HDMI</td><td>5V DC via Micro USB &amp; Power-over-Ethernet (PoE)</td><td>$35</td></tr>
<tr>
<td>Raspberry Pi 4 Model B</td><td>BCM2711</td><td>2GB, 4GB, or 8GB</td><td>Gigabit ethernet, dual-band wireless, Bluetooth</td><td>2x USB 3.0 &amp; 2x USB 2.0</td><td>2x micro HDMI</td><td>5V DC via USB-C</td><td>$35, $55, $75</td></tr>
<tr>
<td>Raspberry Pi 400</td><td>BCM2711</td><td>4GB</td><td>Gigabit ethernet, dual-band wireless, Bluetooth</td><td>2x USB 3.0 &amp; 1x USB 2.0</td><td>2x micro HDMI</td><td>5V DC via USB</td><td>$70</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion">Conclusion</h2>
<p>The Raspberry Pi is an affordable way to explore electronics, hardware, and computer programming. It can be used for a huge variety of projects, from the very silly (like a <a target="_blank" href="https://www.raspberrypi.org/blog/hamsters-all-the-way-down/">hamster powered hamster drawing machine</a>) to the very important (like <a target="_blank" href="https://www.raspberrypi.org/blog/building-computer-labs-in-western-africa/">computer labs</a> in developing nations.)</p>
<p>Now that you know the basics, why don't you go out and make something? Whether you hook a Capacitive Touch HAT up to your Raspberry Pi and turn it into a banana piano or install Linux on it and use it to do your homework, I hope you have a great time creating something cool and useful.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Connect the nRF9160 Feather to a Self-Hosted Mosquitto Instance ]]>
                </title>
                <description>
                    <![CDATA[ By Jared Wolff One thing that’s always tripped me up as an IoT developer is figuring out the best way to transmit data. There are many different kinds of radios and mediums. On top of that, there are different protocols to boot. As of this writing, t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-connect-the-nrf9160-feather-to-mosquitto/</link>
                <guid isPermaLink="false">66d8504d5a0b456f4d32147f</guid>
                
                    <category>
                        <![CDATA[ embedded systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mqtt ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 05 Aug 2020 16:29:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/Copy-of-Bluetooth-with-nRF9160-Feather.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jared Wolff</p>
<p>One thing that’s always tripped me up as an IoT developer is figuring out the best way to transmit data. There are many different kinds of radios and mediums. On top of that, there are different protocols to boot.</p>
<p>As of this writing, there is one protocol that has reigned supreme in the IoT world:</p>
<p>MQTT.</p>
<p>Unlike an HTTP server, a device can connect, publish, and subscribe to topics. These topics then get sent to a broker and distributed to other subscribed devices. It also happens that MQTT on Nordic’s nRF9160 is well supported.</p>
<p>In this post, I’ll show you how to connect the nRF9160 Feather to a self-hosted <a target="_blank" href="https://github.com/eclipse/mosquitto">Mosquitto</a> instance. You’ll learn how to generate your own certificates, and get a hang of how to test your connections.</p>
<p>Ready to play? Let’s get to it.</p>
<h2 id="heading-where-to-host">Where to host?</h2>
<p>If you want to host Mosquitto, you’ll need a server. Since Mosquitto is written in C it’s lightweight and can go almost anywhere. Plus it sips resources so you can install it on a budget VPS without much worry. That’s where a VPS provider like Digital Ocean or Vultr comes in.</p>
<p>To set up a new server here are some steps:</p>
<ul>
<li>Login to Digital Ocean. If you don’t have Digital Ocean and would like to support click <a target="_blank" href="https://m.do.co/c/9574d3846a29">here</a> to create an account.</li>
<li>Create a new Droplet</li>
</ul>
<p><img src="https://www.jaredwolff.com/how-to-connect-nrf9160-feather-to-mosquitto/images/Screen_Shot_2020-08-02_at_5.21.21_PM.png" alt="Create a new droplet" width="730" height="521" loading="lazy"></p>
<ul>
<li>Choose the FreeBSD 12.1 with UFS.</li>
</ul>
<p><img src="https://www.jaredwolff.com/how-to-connect-nrf9160-feather-to-mosquitto/images/Screen_Shot_2020-08-02_at_5.21.29_PM.png" alt="Create a FreeBSD 12.1 Droplet with UFS" width="730" height="521" loading="lazy"></p>
<ul>
<li>Choose the $5 instance. That’s usually more than enough.</li>
</ul>
<p><img src="https://www.jaredwolff.com/how-to-connect-nrf9160-feather-to-mosquitto/images/Screen_Shot_2020-08-02_at_5.21.42_PM.png" alt="Select tier of Droplet" width="730" height="521" loading="lazy"></p>
<ul>
<li>Make sure you import your public key. Otherwise, you won’t be able to immediately use password-less login.</li>
</ul>
<p><img src="https://www.jaredwolff.com/how-to-connect-nrf9160-feather-to-mosquitto/images/Screen_Shot_2020-08-02_at_5.21.50_PM.png" alt="Choose authentication method" width="730" height="521" loading="lazy"></p>
<ul>
<li>Hit that green <strong>Create Droplet</strong> button, and let’s get this show on the road.</li>
</ul>
<p><img src="https://www.jaredwolff.com/how-to-connect-nrf9160-feather-to-mosquitto/images/Screen_Shot_2020-08-02_at_5.21.54_PM.png" alt="Create Droplet button" width="730" height="521" loading="lazy"></p>
<h3 id="heading-important-extra-step">Important Extra step</h3>
<p>For the certs to work with Mosquitto, you’ll have to set a domain to point to your VPS IP address. A CNAME or A record works. If you’re unsure how to do that, <a target="_blank" href="https://misago.gitbook.io/docs/setup/domain">here’s a good guide.</a> Note which (sub)domain you’ve used. We’ll need it in a bit…</p>
<h2 id="heading-install-mosquitto">Install Mosquitto</h2>
<p>I run my servers inside of a FreeBSD jail using <a target="_blank" href="https://bastillebsd.org/">Bastille</a>. In this tutorial, we’ll be skipping the jail part and focusing on getting the nRF9160 Feather working.</p>
<ul>
<li>You should be set with a Digital Ocean instance (or similar) using FreeBSD. If you haven't done that yet, head back up to the <strong>Where to host?</strong> section.</li>
<li>Next, to install <code>mosquitto</code> on your droplet, run <code>pkg install mosquitto</code>. If you’re running something other than FreeBSD, this command may differ. <code>apt-get install mosquitto</code> works on Debian-based systems. If you want the most up to date repositories, make sure you run <code>sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa</code> beforehand. Here’s what the full output on FreeBSD looks like:</li>
</ul>
<pre><code class="lang-bash">$ pkg install mosquitto
The package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]: y
Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:12:amd64/quarterly, please <span class="hljs-built_in">wait</span>...
Verifying signature with trusted certificate pkg.freebsd.org.2013102301... <span class="hljs-keyword">done</span>
[mosquitto] Installing pkg-1.14.6...
[mosquitto] Extracting pkg-1.14.6: 100%
Updating FreeBSD repository catalogue...
[mosquitto] Fetching meta.conf: 100%    163 B   0.2kB/s    00:01
[mosquitto] Fetching packagesite.txz: 100%    6 MiB   6.6MB/s    00:01
Processing entries: 100%
FreeBSD repository update completed. 31943 packages processed.
All repositories are up to date.
Updating database digests format: 100%
The following 4 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        c-ares: 1.16.1
        ca_root_nss: 3.55
        e2fsprogs-libuuid: 1.45.6
        mosquitto: 1.6.7

Number of packages to be installed: 4

The process will require 2 MiB more space.
682 KiB to be downloaded.

Proceed with this action? [y/N]: y
[mosquitto] [1/4] Fetching mosquitto-1.6.7.txz: 100%  226 KiB 231.1kB/s    00:01
[mosquitto] [2/4] Fetching ca_root_nss-3.55.txz: 100%  285 KiB 291.5kB/s    00:01
[mosquitto] [3/4] Fetching e2fsprogs-libuuid-1.45.6.txz: 100%   34 KiB  34.7kB/s    00:01
[mosquitto] [4/4] Fetching c-ares-1.16.1.txz: 100%  138 KiB 140.9kB/s    00:01
Checking integrity... <span class="hljs-keyword">done</span> (0 conflicting)
[mosquitto] [1/4] Installing ca_root_nss-3.55...
[mosquitto] [1/4] Extracting ca_root_nss-3.55: 100%
[mosquitto] [2/4] Installing e2fsprogs-libuuid-1.45.6...
[mosquitto] [2/4] Extracting e2fsprogs-libuuid-1.45.6: 100%
[mosquitto] [3/4] Installing c-ares-1.16.1...
[mosquitto] [3/4] Extracting c-ares-1.16.1: 100%
[mosquitto] [4/4] Installing mosquitto-1.6.7...
===&gt; Creating users
Using existing user <span class="hljs-string">'nobody'</span>.
[mosquitto] [4/4] Extracting mosquitto-1.6.7: 100%
=====
Message from ca_root_nss-3.55:

--
FreeBSD does not, and can not warrant that the certification authorities
whose certificates are included <span class="hljs-keyword">in</span> this package have <span class="hljs-keyword">in</span> any way been
audited <span class="hljs-keyword">for</span> trustworthiness or RFC 3647 compliance.

Assessment and verification of trust is the complete responsibility of the
system administrator.

This package installs symlinks to support root certificates discovery by
default <span class="hljs-keyword">for</span> software that uses OpenSSL.

This enables SSL Certificate Verification by client software without manual
intervention.

If you prefer to <span class="hljs-keyword">do</span> this manually, replace the following symlinks with
either an empty file or your site-local certificate bundle.

  * /etc/ssl/cert.pem
  * /usr/<span class="hljs-built_in">local</span>/etc/ssl/cert.pem
  * /usr/<span class="hljs-built_in">local</span>/openssl/cert.pem
=====
Message from mosquitto-1.6.7:

--
The mosquitto MQTT Python driver is now provided by net/py-paho-mqtt
</code></pre>
<p>All installed package configuration lives at <code>/usr/local/etc/mosquitto/</code>. We’ll need to edit <code>mosquitto.conf</code> in that folder to use certificates. Here’s what it looks like:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Daemon configuration</span>
pid_file /var/run/mosquitto.pid
user nobody

<span class="hljs-comment"># Port to use for the default listener.</span>
port 8885

<span class="hljs-comment"># At least one of cafile or capath must be defined.</span>
cafile /root/pki/ca.crt

<span class="hljs-comment"># Path to the PEM encoded server certificate.</span>
certfile /root/pki/issued/mosquitto.crt

<span class="hljs-comment"># Path to the PEM encoded keyfile.</span>
keyfile /root/pki/private/mosquitto.key

<span class="hljs-comment"># Path to CRL file</span>
<span class="hljs-comment">#crlfile /root/pki/crl.pem</span>

<span class="hljs-comment"># Each client has their own cert</span>
require_certificate <span class="hljs-literal">true</span>
use_identity_as_username <span class="hljs-literal">true</span>

<span class="hljs-comment"># listener port-number [ip address/host name]</span>
listener 1883
protocol mqtt

<span class="hljs-comment"># listener port-number [ip address/host name]</span>
<span class="hljs-comment"># listener 8080</span>
<span class="hljs-comment"># protocol websockets</span>

<span class="hljs-comment"># =================================================================</span>
<span class="hljs-comment"># Logging</span>
<span class="hljs-comment"># =================================================================</span>
log_dest syslog

<span class="hljs-comment"># Types of messages to log.</span>
log_type all
<span class="hljs-comment">#log_type warning</span>
<span class="hljs-comment"># websockets_log_level 127</span>

<span class="hljs-comment"># -----------------------------------------------------------------</span>
<span class="hljs-comment"># Default authentication and topic access control</span>
<span class="hljs-comment"># -----------------------------------------------------------------</span>
<span class="hljs-comment"># password_file /usr/local/etc/mosquitto/pwfile</span>
</code></pre>
<p>Before we can start the server we’ll need to provision some RSA certificates. We’ll get to that in the next step.</p>
<h2 id="heading-provision-certs">Provision Certs</h2>
<p>You can use <strong>easy-rsa</strong> to generate a CA server and client certs. (These instructions come from <a target="_blank" href="https://github.com/OpenVPN/easy-rsa/blob/master/README.quickstart.md">this guide</a>.) For production, you should generate your keys and certs on an offline machine. That way your private keys are safe if your server becomes a target.</p>
<p>First, install <code>easy-rsa</code>:</p>
<pre><code class="lang-bash">$ pkg install easy-rsa
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 1 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        easy-rsa: 3.0.7

Number of packages to be installed: 1

44 KiB to be downloaded.

Proceed with this action? [y/N]: y
[mosquitto] [1/1] Fetching easy-rsa-3.0.7.txz: 100%   44 KiB  44.8kB/s    00:01
Checking integrity... <span class="hljs-keyword">done</span> (0 conflicting)
[mosquitto] [1/1] Installing easy-rsa-3.0.7...
[mosquitto] [1/1] Extracting easy-rsa-3.0.7: 100%
</code></pre>
<p>Then let's begin the cert creation process:</p>
<pre><code class="lang-fallback">$ easyrsa init-pki

Note: using Easy-RSA configuration from: /usr/local/share/easy-rsa/vars

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /root/pki
$
$ easyrsa build-ca

Note: using Easy-RSA configuration from: /usr/local/share/easy-rsa/vars
Using SSL: openssl OpenSSL 1.1.1d-freebsd  10 Sep 2019

Enter New CA Key Passphrase:
Re-Enter New CA Key Passphrase:
Generating RSA private key, 2048 bit long modulus (2 primes)
......................+++++
..................................................................................+++++
e is 65537 (0x010001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:testserver.jaredwolff.com

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/root/pki/ca.crt
</code></pre>
<p><strong>Note:</strong> You will be prompted for a password at the <code>build-ca</code> step. Make sure you keep this password handy.</p>
<p>Then to generate a server cert use:</p>
<pre><code class="lang-fallback">$ easyrsa gen-req mosquitto nopass

Note: using Easy-RSA configuration from: /usr/local/share/easy-rsa/vars
Using SSL: openssl OpenSSL 1.1.1d-freebsd  10 Sep 2019
Generating a RSA private key
...............+++++
........................................+++++
writing new private key to '/root/pki/easy-rsa-82720.X2NVQ0/tmp.akOxhO'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [mosquitto]:testserver.jaredwolff.com

Keypair and certificate request completed. Your files are:
req: /root/pki/reqs/mosquitto.req
key: /root/pki/private/mosquitto.key
$
$ easyrsa sign-req server mosquitto

Note: using Easy-RSA configuration from: /usr/local/share/easy-rsa/vars
Using SSL: openssl OpenSSL 1.1.1d-freebsd  10 Sep 2019

You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 825 days:

subject=
    commonName                = testserver.jaredwolff.com

Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
Using configuration from /root/pki/easy-rsa-82744.hyuGzt/tmp.lZHLEH
Enter pass phrase for /root/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'testserver.jaredwolff.com'
Certificate is to be certified until Nov  3 01:12:53 2022 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /root/pki/issued/mosquitto.crt
</code></pre>
<p>You’ll be prompted for both the Common Name (i.e. your server name) and the CA cert password in the above step. <strong>Important</strong>: the <strong>Common Name</strong> needs to match the domain name of your server! (Remember, we wrote that down earlier?)</p>
<p>To generate the nRF9160 cert, use:</p>
<pre><code class="lang-fallback">$ easyrsa gen-req nrf9160 nopass batch
$ easyrsa sign-req client nrf9160 batch
</code></pre>
<p>Follow the same procedure as earlier. The only difference is that we’re generating a <strong>client</strong> cert instead of a <strong>server</strong> cert.</p>
<p>Once complete, we’ll need some files. Here’s a full list:</p>
<p><strong>For your Mosquitto Server</strong></p>
<ul>
<li><code>/root/pki/ca.crt</code></li>
<li><code>/root/pki/private/mosquitto.key</code></li>
<li><code>/root/pki/issued/mosquitto.crt</code></li>
</ul>
<p><strong>For your nRF9160 Feather</strong></p>
<ul>
<li><code>/root/pki/ca.crt</code></li>
<li><code>/root/pki/private/nrf9160.key</code></li>
<li><code>/root/pki/issued/nrf9160.crt</code></li>
</ul>
<p>If you’re using the configuration from above, it’s already pointing to your server certificates. All we have to do now is start <code>mosquitto</code>!</p>
<pre><code class="lang-bash">$ service mosquitto start
Cannot <span class="hljs-string">'start'</span> mosquitto. Set mosquitto_enable to YES <span class="hljs-keyword">in</span> /etc/rc.conf or use <span class="hljs-string">'onestart'</span> instead of <span class="hljs-string">'start'</span>.
</code></pre>
<p>If you get an error about <code>mosquitto_enable</code> simply run:</p>
<pre><code class="lang-bash">$ sysrc mosquitto_enable=YES
$ service mosquitto start
Starting mosquitto.
</code></pre>
<p>This enables <code>mosquitto</code> to start when your system starts.</p>
<p>Now, check if <code>mosquitto</code> is running by using <code>ps aux</code>:</p>
<pre><code class="lang-bash">
$ ps aux
USER     PID %CPU %MEM   VSZ  RSS TT  STAT STARTED    TIME COMMAND
root   82401  0.0  0.2 11472 2424  -  SsJ  01:02   0:00.00 /usr/sbin/syslogd -ss
root   82457  0.0  0.2 11408 2284  -  IsJ  01:02   0:00.00 /usr/sbin/cron -J 60 -s
nobody 82900  0.0  0.6 16352 6212  -  SsJ  01:17   0:00.02 /usr/<span class="hljs-built_in">local</span>/sbin/mosquitto -c /usr/<span class="hljs-built_in">local</span>/etc/mosquitto/mosquitto.conf -d
root   82488  0.0  0.3 12096 2848  0  IJ   01:02   0:00.01 login [pam] (login)
root   82489  0.0  0.3 13092 3504  0  SJ   01:02   0:00.03 -csh (csh)
root   82902  0.0  0.3 11704 2540  0  R+J  01:17   0:00.00 ps aux
</code></pre>
<p>Now that we have a server loaded and running, let’s get the firmware working.</p>
<h2 id="heading-firmware-bits">Firmware bits</h2>
<p>Dealing with certificates on the nRF9160 Feather is a two-step process. The first step is to load the certificates using the <code>at_client</code> firmware. The second is to load the <code>mqtt_simple</code> library with added TLS support. Let’s tackle the certs first.</p>
<h3 id="heading-program-atclient-first">Program <code>at_client</code> first</h3>
<p>Change directories to <code>ncs/nrf/samples/nrf9160/at_client/</code> and start a fresh build:</p>
<pre><code class="lang-c">$ west build -b circuitdojo_feather_nrf9160ns -p
</code></pre>
<p>Then flash to your board using:</p>
<pre><code class="lang-c">$ west flash --erase
$ nrfjprog -r
</code></pre>
<p>We’ll need this sample on your board for the next step.</p>
<h3 id="heading-add-certs-to-device">Add certs to device</h3>
<p>To install our new certs, we’ll need nRF Connect Desktop installed. You can download it <a target="_blank" href="https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-desktop/Download#infotabs">by going here.</a></p>
<p>You’ll also need a custom version of <strong>LTE Link Monitor.</strong> You can get the modified version on <a target="_blank" href="http://localhost:3000/files/pc-nrfconnect-linkmonitor-1.1.1.tgz">docs.jaredwolff.com.</a></p>
<p>First, Install nRF Connect Desktop app. Then, copy the LTE Link Monitor .tgz file to <code>%USERPROFILE%\.nrfconnect-apps\local</code> (on Windows) or <code>$HOME/.nrfconnect-apps/local</code> (on Linux/macOS). Here’s an example of where it is on Windows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Close and re-open nRF Connect Desktop (if it’s open).</p>
<p>Then, click <em>Open</em> next to the v1.1.1 version of LTE Link Monitor. It will also have <strong>local</strong> written underneath it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-12.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, let’s launch it!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-13.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once you’ve opened the port, hit the reset button. Make sure you turn off <strong>Automatic requests.</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-14.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then in the command box send <strong>AT+CFUN=4</strong>. This will shut down your modem so it’s ready to upload certs. You can run <strong>AT+CFUN?</strong> to confirm your modem in that mode.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-15.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Open up the Certificate manager.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-16.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Make sure you set the security tag. In this case, I’m using 1234. This is an important identifier that you’ll need later. Make it whatever you want but I would avoid using 16842753. This is the default tag for NRF Cloud. You don’t want to blast away your nRF Cloud certs!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-17.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Copy and paste the contents of your <code>ca.crt</code>, <code>nrf9160.crt</code> and <code>nrf9160.key</code> into the boxes (in that order). You can easily get the certs by using <code>cat</code> on Unix/Linux:</p>
<pre><code class="lang-bash">$ cat cat.crt
-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgIUDLkBxLLQO9wosNDtA7E9qvqHOxMwDQYJKoZIhvcNAQEL
BQAwJDEiMCAGA1UEAwwZdGVzdHNlcnZlci5qYXJlZHdvbGZmLmNvbTAeFw0yMDA3
MzEwMTExNDJaFw0zMDA3MjkwMTExNDJaMCQxIjAgBgNVBAMMGXRlc3RzZXJ2ZXIu
amFyZWR3b2xmZi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3
de1v8k+FXzY/Im7Z2YKS7wwbBRft5CUxqP1sdYJgMvheS9LhFufk81URZ0lHD9pK
aNPxU1UEmnLvVDTGLJ+YAmMH08xn17FS1R1UVPYzi2ouwqRM2pR9EStsSlP9Zj44
1MsdizABnnlkZndUVLL/gjc4cNsNncMLBSEbsz6b5WzhtAGg3rOpdAxSSblZVSFw
bquCgg5hb2NUzy+JxGtUIsE5d6CxTDdSs4Z3FK/RRYjmCG6qsaya4N5W35yf8h5O
StfKRecl3kq2kCnWa6P+lErG4wuxIBtMkgz2zV+zd1tz4aHXxSdoZTqLz7dTVbFA
zEVnKD+ZReBG+4fwUL6rAgMBAAGjgZ4wgZswHQYDVR0OBBYEFIvdGnjrxRPzvXQi
7XJ70LzpZSOjMF8GA1UdIwRYMFaAFIvdGnjrxRPzvXQi7XJ70LzpZSOjoSikJjAk
MSIwIAYDVQQDDBl0ZXN0c2VydmVyLmphcmVkd29sZmYuY29tghQMuQHEstA73Ciw
0O0DsT2q+oc7EzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0B
AQsFAAOCAQEAIzz1nSSDkPueNPlADRYMDOMFNkxoKA+gRXwDVa7y39As7IZp7Fqr
KAH79U1XtGyDlt6FPKTvDJ7jtd4y8auIGVQO7z3AG9pVU1imIWZHoIqgBUCEhsjp
uMxD23kRCX5kd9dsmF9WOGGxb4kkMv83Rh2rCONQmvnozuI3fJv2ZFX/ORoADGLP
OPSJPl11x+2rxPxiLi+T8RyzDh3DwqnPVsSnbRWV7hosaN0ip/cbnSTaIul9mbCY
ID6qm9leqlY/gha9aZfg+tv1Lm6PT6o8Pzek2VeDoIS5YERBMOwV84hQrZjV3vIE
jT6y663HGsl7KvqVaWdV3fM6Cr7f0QdR5A==
-----END CERTIFICATE-----
</code></pre>
<p>You’ll need everything from <code>-----BEGIN CERTIFICATE-----</code> to <code>-----END CERTIFICATE-----</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-18.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Check the <strong>Log</strong> area for more details. If all went well, it should say that your certificates updated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-19.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-using-the-mqttsimple-example">Using the mqtt_simple example</h3>
<p>We’ll be using the <code>mqtt_simple</code> sample within the nRF Connect SDK repository. The full path is: <code>ncs/nrf/samples/nrf9160/mqtt_simple</code>. We’ll need to make a few edits to add full TLS compatibility. All the files are within the <code>mqtt_simple</code> directory.</p>
<p>First, we’ll have to update the <code>proj.conf</code> file. See the highlighted differences:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-20.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The <code># Set the PDP Context</code> section is especially important if you’re using a Hologram SIM card (included with the nRF9160 Feather). If you are using a SIM that doesn’t need it, you do not need this section.</p>
<p>Adopt your <code>CONFIG_MQTT_BROKER_HOSTNAME</code> to your hostname (configured at the beginning of this guide).</p>
<p>You’ll also have to add these lines in <code>KConfig</code>:</p>
<pre><code class="lang-c">config SEC_TAG
    <span class="hljs-keyword">int</span> <span class="hljs-string">"Security tag to use for the connection"</span>
    <span class="hljs-keyword">default</span> <span class="hljs-number">1234</span>

config PEER_VERIFY
    <span class="hljs-keyword">int</span> <span class="hljs-string">"Peer verify parameter for mqtt_client"</span>
    <span class="hljs-keyword">default</span> <span class="hljs-number">1</span>
    help
            Set to <span class="hljs-number">0</span> <span class="hljs-keyword">for</span> VERIFY_NONE, <span class="hljs-number">1</span> <span class="hljs-keyword">for</span> VERIFY_OPTIONAL, <span class="hljs-keyword">and</span> <span class="hljs-number">2</span> <span class="hljs-keyword">for</span> VERIFY_REQUIRED.
</code></pre>
<p>Finally in main add this block to the top of your file:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> defined(CONFIG_MQTT_LIB_TLS)</span>
<span class="hljs-keyword">static</span> <span class="hljs-keyword">sec_tag_t</span> sec_tag_list[] = { CONFIG_SEC_TAG };
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span> <span class="hljs-comment">/* defined(CONFIG_MQTT_LIB_TLS) */</span></span>
</code></pre>
<p>Then add this block to <code>client_init</code> under <code>#if defined(CONFIG_MQTT_LIB_TLS)</code></p>
<pre><code class="lang-c">  <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">mqtt_sec_config</span> *<span class="hljs-title">tls_config</span> = &amp;<span class="hljs-title">client</span>-&gt;<span class="hljs-title">transport</span>.<span class="hljs-title">tls</span>.<span class="hljs-title">config</span>;</span>

    client-&gt;transport.type = MQTT_TRANSPORT_SECURE;

    tls_config-&gt;peer_verify = CONFIG_PEER_VERIFY;
    tls_config-&gt;cipher_count = <span class="hljs-number">0</span>;
    tls_config-&gt;cipher_list = <span class="hljs-literal">NULL</span>;
    tls_config-&gt;sec_tag_count = ARRAY_SIZE(sec_tag_list);
    tls_config-&gt;sec_tag_list = sec_tag_list;
    tls_config-&gt;hostname = CONFIG_MQTT_BROKER_HOSTNAME;
</code></pre>
<p>The changes should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-21.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then build with:</p>
<pre><code class="lang-c">$ west build -b circuitdojo_feather_nrf9160ns -p
</code></pre>
<p>Finally, flash it using <code>west flash</code>:</p>
<pre><code class="lang-c">$ west flash --erase
$ nrfjprog -r
</code></pre>
<p>Open your serial terminal and double check that your nRF9160 Feather is connecting. You can also use LTE Link Monitor to view your progress as well (Example below).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-22.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Lots of the information above came from <a target="_blank" href="https://devzone.nordicsemi.com/nordic/cellular-iot-guides/b/software-and-protocols/posts/enabling-and-testing-tls-in-mqtt_5f00_simple">Nordic</a>'s post on the subject.</p>
<h2 id="heading-sending-a-message">Sending a message</h2>
<p>We’re almost there! You’ve configured your nRF9160 Feather to connect to Mosquitto using self-generated certificates. The last part is connecting another device to see if the nRF9160 Feather replies to a message.</p>
<p>I’ve created a new set of certs for this purpose. I called them <code>test</code>.</p>
<pre><code class="lang-bash">$ easyrsa gen-req <span class="hljs-built_in">test</span> nopass batch
$ easyrsa sign-req client <span class="hljs-built_in">test</span> batch
</code></pre>
<p>I copied them to my desktop using CyberDuck (a great little visual SFTP client):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/image-23.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can also use something like <code>scp</code> if you're confident in your command line file transfer abilities. Then, open a terminal and run:</p>
<pre><code class="lang-bash">mosquitto_sub --cafile ca.crt --cert test.crt --key test.key -q 1 -d -h testserver.jaredwolff.com -p 8885 -t <span class="hljs-string">"/my/publish/topic"</span> &amp;
mosquitto_pub --cafile ca.crt --cert test.crt --key test.key -q 1 -d -h testserver.jaredwolff.com -p 8885 -t <span class="hljs-string">"/my/subscribe/topic"</span> -m <span class="hljs-string">"hello there"</span>
</code></pre>
<p>You should see an output like this:</p>
<pre><code class="lang-bash">$ mosquitto_sub --cafile ca.crt --cert test.crt --key test.key -q 1 -d -h testserver.jaredwolff.com -p 8885 -t <span class="hljs-string">"/my/publish/topic"</span> &amp;
$ mosquitto_pub --cafile ca.crt --cert test.crt --key test.key -q 1 -d -h testserver.jaredwolff.com -p 8885 -t <span class="hljs-string">"/my/subscribe/topic"</span> -m <span class="hljs-string">"hello there"</span>
Client mosq-CczskQKzMKdtTo4O4s sending CONNECT
Client mosq-CczskQKzMKdtTo4O4s received CONNACK (0)
Client mosq-CczskQKzMKdtTo4O4s sending PUBLISH (d0, q1, r0, m1, <span class="hljs-string">'/my/subscribe/topic'</span>, ... (11 bytes))
Client mosq-CczskQKzMKdtTo4O4s received PUBACK (Mid: 1, RC:0)
Client mosq-CczskQKzMKdtTo4O4s sending DISCONNECT
MacBook-Pro:Downloads jaredwolff$ Client mosq-qK8tMlJk0Qri4Z7jUo sending PINGREQ
Client mosq-qK8tMlJk0Qri4Z7jUo received PINGRESP
MacBook-Pro:Downloads jaredwolff$ Client mosq-qK8tMlJk0Qri4Z7jUo received PUBLISH (d0, q0, r0, m0, <span class="hljs-string">'/my/publish/topic'</span>, ... (11 bytes))
hello there
</code></pre>
<p>Booyah! You have an active working connection to your very own Mosquitto server.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We’ve made it to the end! By this point in the post, you should have a Mosquitto server running and an nRF9160 connected. Now you can use your new-found skills to add more devices to your deployments and more.</p>
<p>If you haven’t had a chance to play with the nRF9160 you should check out the nRF9160 Feather. It has Nordic Semiconductor’s nRF9160 LTE-M, NB IoT + GPS Combo, plus flexible power supply, external flash, and low power shutdown. </p>
<p>Oh, and did I mention it’s 100% open source? Learn more by checking out the campaign on <a target="_blank" href="https://www.jaredwolff.com/store/nrf91-feather/">GroupGets and Hackster Launch.</a> ?</p>
<p><img src="https://www.jaredwolff.com/how-to-connect-nrf9160-feather-to-mosquitto/images/IMG_8749.jpg" alt="nRF9160 Feather Top Side" width="730" height="730" loading="lazy"></p>
<p><img src="https://www.jaredwolff.com/how-to-connect-nrf9160-feather-to-mosquitto/images/IMG_8750.jpg" alt="nRF9160 Feather Bottom Side" width="730" height="730" loading="lazy"></p>
<p>Photo credit to the awesome folks at <a target="_blank" href="https://www.groupgets.com/">GroupGets</a>!</p>
<p><strong>You can read this article and lots of other good stuff at <a target="_blank" href="https://www.jaredwolff.com/how-to-connect-nrf9160-feather-to-mosquitto/">jaredwolff.com</a>.</strong></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Meet Pyrinas - an IoT Development Kit For Your Particle Xenon ]]>
                </title>
                <description>
                    <![CDATA[ By Jared Wolff This post is a bit lengthy. If you prefer, signup to get the full PDF here. ? After Particle's Mesh deprecation announcement, many have been left to figure out how to deploy their low power sensor networks. There was always the option ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/meet-pyrinas-an-iot-development-kit-for-your-particle-xenon/</link>
                <guid isPermaLink="false">66d85060c15439a8d5631e83</guid>
                
                    <category>
                        <![CDATA[ Bluetooth Low Energy ]]>
                    </category>
                
                    <category>
                        <![CDATA[ embedded systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ particle ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 11 Mar 2020 13:49:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/Copy-of-Particle-Mesh-App-Updates.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jared Wolff</p>
<p>This post is a bit lengthy. If you prefer, <a target="_blank" href="https://www.jaredwolff.com/files/pyrinas-intro/">signup to get the full PDF here.</a> ?</p>
<p>After <a target="_blank" href="https://www.jaredwolff.com/particle-mesh-deprecation-livestream/">Particle's Mesh deprecation announcement</a>, many have been left to figure out how to deploy their low power sensor networks. There was always the option of using <a target="_blank" href="https://www.jaredwolff.com/how-to-use-particles-powerful-bluetooth-api/">Particle's Built in Bluetooth stack</a> but as it stands today it's not secure.</p>
<p>Previously I had helped form a very simple nRF SDK-based hub and spoke IoT deployment. Unfortunately, it was closed source and the company is no longer around.</p>
<p>So what's a guy to do?</p>
<p>Build another one and make it <em>open. (BSD licensed to be exact!)</em> Open and free for anyone to use adopt and improve upon. Plus if you're building a product that's using the code, <strong>you don't have to share your improvements or proprietary code with anyone.</strong></p>
<p>In this post I'll be talking about how to get started with Pyrinas. It uses Nordic's time tested SDK as a basis for the kernel of the system. The main concept of Pyrinas is to abstract as much IoT cruft away so you can focus on your application.</p>
<p>So without further ado, let's chat about what Pyrinas is and what it isn't.</p>
<h2 id="heading-what-pyrinas-is">What Pyrinas is</h2>
<ul>
<li>Is an embedded "kernel", written in C. It's open and permissive IoT development environment you can use for anything you want. Seriously. It's BSD licensed and can be used in closed source applications.</li>
<li>Using the power of Bluetooth 5.0 Long Range, Pyrinas allows you to communicate with many peripheral devices at one time. Currently Pyrinas has been tested with 3 simultaneous peripheral connections. Theoretically, it can support up to 20 simultaneous connections. (Thanks to <a target="_blank" href="https://cm.nordicsemi.com//Software-and-tools/Software/Bluetooth-Software">Nordic's S140 Softdevice</a>)</li>
<li><p>Pyrinas transports its data in two ways</p>
<ul>
<li>In a familiar string format used by Particle</li>
<li>A custom Protocol Buffer for raw data transmission.</li>
</ul>
<p>That way you have a <strong>choice</strong> of how you want to process and publish your data!</p>
</li>
</ul>
<h2 id="heading-what-pyrinas-isnt">What Pyrinas isn't</h2>
<ul>
<li>Pyrinas is not a RTOS (real time operating system). If you have a need to run multiple threaded applications on embedded, Pyrinas is not for you.</li>
<li>Pyrinas, at this time, does not support Mesh.</li>
<li>An OS for every single kind of Bluetooth SoC on the market. Due to the tight coupling with Nordic's nRF SDK, Pyrinas only works with Nordic's SoCs.</li>
<li>A turnkey solution for IoT. Pyrinas is early on it it's development process. The aim is for it to become a viable option for anyone to develop and publish IoT applications <em>the way they want to.</em> There's no vendor lock in. There's no surprises.</li>
</ul>
<h2 id="heading-things-youll-need">Things you'll need</h2>
<p>There are a few things you'll need in order to get going with Pyrinas.</p>
<ul>
<li>At least 2 Particle Xenons</li>
<li>At least 1 nRF Development board or J-link programmer</li>
<li>Associated USB cables</li>
</ul>
<h2 id="heading-getting-started-with-an-example">Getting started with an example</h2>
<p>Getting started with Pyrinas involves two repositories.</p>
<ul>
<li><a target="_blank" href="https://github.com/pyrinas-iot/pyrinas-os">The OS respository</a></li>
<li><a target="_blank" href="https://github.com/pyrinas-iot/pyrinas-template">The template</a></li>
</ul>
<p>The OS directory has all the source, SDK dependencies and toolchain you need to use Pyrinas.</p>
<p>The template is where you add all your application code. The template provides a starting point for you and your project.</p>
<p>Here's how everything goes together:</p>
<p>Clone the OS directory to some place on your machine:</p>
<pre><code class="lang-shell">git clone https://github.com/pyrinas-iot/pyrinas-os.git --recurse-submodules
</code></pre>
<p>Once complete, change directories to <code>pyrinas-os</code> and run <code>make setup</code></p>
<pre><code class="lang-shell">cd pyrinas-os
make setup
</code></pre>
<p>This will download your toolchain and SDK dependencies.</p>
<p>In order to use OTA DFU, you will need to also generate the DFU key for the process:</p>
<pre><code class="lang-shell">make gen_key
</code></pre>
<p>The files generated by this process will be used later.</p>
<p>Next, we'll want to use the template to make two new projects. In this example we'll have one "hub" and one "sensor." Simply navigate to the <a target="_blank" href="https://github.com/pyrinas-iot/pyrinas-template">template repository</a> and click the <strong>Use this template</strong> button.</p>
<p><img src="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Screen_Shot_2020-03-09_at_5.12.21_PM.png" alt="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Screen_Shot_2020-03-09_at_5.12.21_PM.png" width="730" height="420" loading="lazy"></p>
<p>Then name your new repository. Click the <strong>Create repository from template</strong> button when you're happy with everything.</p>
<p><img src="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Screen_Shot_2020-03-09_at_5.20.15_PM.png" alt="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Screen_Shot_2020-03-09_at_5.20.15_PM.png" width="730" height="449" loading="lazy"></p>
<p>Then clone your repository to the same directory as <code>pyrinas-os</code>. Make sure you replace <code>&lt;your username&gt;</code> and <code>&lt;repo name&gt;</code> with your own.</p>
<pre><code class="lang-shell">cd ..
git clone https://github.com/&lt;your username&gt;/&lt;repo name&gt;.git hub
</code></pre>
<p>After this is done, go back and create a new repository from the template. We'll be using this one for the <em>sensor</em> node.</p>
<p><img src="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Screen_Shot_2020-03-09_at_5.24.15_PM.png" alt="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Screen_Shot_2020-03-09_at_5.24.15_PM.png" width="730" height="449" loading="lazy"></p>
<p>Clone this repository once you're done setting it up in the same place as your <code>hub</code> and <code>pyrinas-os</code> repositories.</p>
<p>Now that we have all our repositories, let's start with our sensor node.</p>
<h3 id="heading-setting-up-the-sensor-node-repository">Setting up the sensor node repository</h3>
<p>Open up the sensor repository using a program like Microsoft's VS Code. If you have the command line shortcuts you can use <code>code</code> to open it from the terminal:</p>
<pre><code class="lang-shell">code sensor
</code></pre>
<p>Before we do anything we'll need to set up the symbolic link to <code>pyrinas-os</code>. Make sure you're in the <code>sensor</code> directory and then run <code>ln -s ../pyrinas-os/</code> using the terminal.</p>
<pre><code class="lang-shell">cd sensor
ln -s ../pyrinas-os/ .
</code></pre>
<p>This allows your project to use all the code, SDK and toolchains within the <code>pyrinas-os</code> repository! As an added bonus you can do this as many times as you want. Have multiple Pyrinas projects? No problem.</p>
<p>Alright! Now, let's check out the Makefile. You'll want to customize some of the definitions within the file:</p>
<pre><code class="lang-makefile"><span class="hljs-comment"># Start: Your configuration!</span>

<span class="hljs-comment"># Set this to the directory of pyrinas-os</span>
<span class="hljs-comment"># If you used a symbolic link this points to</span>
<span class="hljs-comment"># the `pyrinas-os` folder in this repository</span>
OS_DIR := pyrinas-os

<span class="hljs-comment"># This should be the serial number of your Jlink programmer.</span>
<span class="hljs-comment"># To find simply run `jlinkexe`</span>
PROG_SERIAL=1234678

<span class="hljs-comment"># This is your debugger port for Jlink's RTT. If you</span>
<span class="hljs-comment"># have mulitple, you will have to change this on each app</span>
<span class="hljs-comment"># your're using</span>
PROG_PORT=19021

<span class="hljs-comment"># This is where you set your board type. Here are the supported boards:</span>
<span class="hljs-comment"># xenon - Particle Xenon</span>
BOARD=xenon

<span class="hljs-comment"># This is where you can name your app something. Make it specific</span>
APP_FILENAME=pyrinas-template

<span class="hljs-comment"># This determines whether or not you're using debug mode</span>
<span class="hljs-comment"># Comment this out or change to false</span>
DEBUG=true

<span class="hljs-comment"># End: Your Configuration</span>
</code></pre>
<p>For example, you may want to setup your programmer serial. This allows you to use multiple programmers at the same time. (Very helpful in debugging both devices at the same time) To get your programmer's serial plug in your development board and run <code>jlinkexe</code>.</p>
<p>    jlinkexe
    SEGGER J-Link Commander V6.62a (Compiled Jan 31 2020 12:59:22)
    DLL version V6.62a, compiled Jan 31 2020 12:59:05</p>
<p>    Connecting to J-Link via USB...O.K.
    Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Jan 21 2020 17:30:48
    Hardware version: V1.00
    S/N: 581758669
    License(s): RDI, FlashBP, FlashDL, JFlash, GDB
    VTref=3.300V</p>
<p>    Type "connect" to establish a target connection, '?' for help
    J-Link&gt;</p>
<p>Find the <strong>S/N</strong> area. This is your serial number!</p>
<p>Alternatively you can look at the sticker on your development kit. It will contain the serial number for your device.</p>
<p>For the <code>PROG_PORT</code> you want to use different ports for each device you're simultaneously debugging. I've found <strong>19021</strong> and <strong>19020</strong> are perfectly good options for most two-device debugging sessions.</p>
<p>The Makefile also includes the ability to choose a board. In our case there's only one option: <code>xenon</code>. Future revisions of Pyrinas will have multiple options.</p>
<p><code>APP_FILENAME</code> is the name of your app. We'll rename ours to <code>pyrinas-sensor</code></p>
<p>Finally, <code>DEBUG</code> is used to halt execution either on an error or restart. For production this should be commented out or set to <code>false</code>. We can leave it as is for now.</p>
<p>The Makefile is also the source for some of the most important commands you'll need during development:</p>
<ul>
<li><code>make build</code> - builds your app.</li>
<li><code>make clean</code> - cleans all remnants of your app.</li>
<li><code>make debug</code> - opens up the <code>jlinkexe</code> debugger console.</li>
<li><code>make erase</code> - erases the chip attached to your programmer.</li>
<li><code>make flash</code> - flashes the current app to your connected device.</li>
<li><code>make flash_softdevice</code> - flashes the soft_device</li>
<li><code>make rtt</code> - opens up the debug console.</li>
<li><code>make ota</code> - generates a zip file used for BLE DFU</li>
</ul>
<h3 id="heading-basic-sensor-node-code">Basic sensor node code</h3>
<p><img src="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Copy_of_Particle_Mesh_App_Updates-3.jpg" alt="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Copy_of_Particle_Mesh_App_Updates-3.jpg" width="730" height="486" loading="lazy"></p>
<p>Now that we have some of the basics out of the way, let's create a very simple application that publishes on a set interval. If you look at <code>app.c</code>, you'll see some code in the <code>setup()</code> function. Let's delete all the commented out code. (We'll use it later for the hub though)</p>
<p>Your code should now look something like:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"app.h"</span></span>

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span>
</span>{
  BLE_STACK_PERIPH_DEF(init);

  <span class="hljs-comment">// Configuration for ble stack</span>
  ble_stack_init(&amp;init);

  <span class="hljs-comment">// Start advertising</span>
  advertising_start();
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">loop</span><span class="hljs-params">()</span>
</span>{
}
</code></pre>
<p>Now let's create a timer that we'll use to publish on a set interval. Under <code>#include "app.h"</code> create a new timer:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"app.h"</span></span>

timer_define(m_sensor_timer);
</code></pre>
<p>We also need to set it up in the <code>setup()</code> function:</p>
<pre><code class="lang-c"><span class="hljs-comment">// Sensor timer</span>
timer_create(&amp;m_sensor_timer, TIMER_REPEATED, sensor_timer_evt);
</code></pre>
<p>You'll notice that <code>timer_create</code> is referring to a event callback called <code>sensor_timer_evt</code>. We'll need to create that guy as well:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sensor_timer_evt</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-comment">// We'll come back in a sec</span>
}
</code></pre>
<p>The last thing is to start the timer. Let's do that underneath <code>timer_create</code>:</p>
<pre><code class="lang-c"><span class="hljs-comment">// Start</span>
timer_start(&amp;m_sensor_timer, <span class="hljs-number">1000</span>);
</code></pre>
<p>This will start our repeating timer on a 1 second interval.  (<code>timer_start</code> is configured using milliseconds)</p>
<p>Now, inside <code>sensor_timer_evt</code> we'll publish some data. First though we need to make sure that Bluetooth is connected using <code>ble_is_connected</code>.</p>
<pre><code class="lang-c"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> sensor_timer_evt
{
  <span class="hljs-comment">// Check if we're connected</span>
  <span class="hljs-keyword">if</span> (ble_is_connected())
  {
    <span class="hljs-comment">// Sends "ping" with the event name of "data"</span>
    ble_publish(<span class="hljs-string">"data"</span>, <span class="hljs-string">"ping"</span>);
  }
}
</code></pre>
<p>Inside the if statement, we'll use <code>ble_publish</code>. The first argument is the name of the event and the second is the value.</p>
<p>Next, in order to receive messages from the other end we'll need to setup a callback:</p>
<pre><code class="lang-c"><span class="hljs-comment">// Configuration for ble stack</span>
ble_stack_init(&amp;init);

<span class="hljs-comment">// Setup BLE callback</span>
ble_subscribe(<span class="hljs-string">"data"</span>, ble_evt);
</code></pre>
<p>We'll define <code>ble_evt</code> at the top of the file:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ble_evt</span><span class="hljs-params">(<span class="hljs-keyword">char</span> *name, <span class="hljs-keyword">char</span> *data)</span>
</span>{
  NRF_LOG_INFO(<span class="hljs-string">"%s: %s"</span>, name, data);
}
</code></pre>
<p>In this case we'll use <code>NRF_LOG_INFO</code> to print out the message from the hub.</p>
<p>Finally, in order to get the MAC address easily, we'll have to add a call to print it out in <code>setup()</code>.</p>
<pre><code class="lang-c"><span class="hljs-comment">// Print the address</span>
util_print_device_address();
</code></pre>
<p>In the end your file should look something like this:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"app.h"</span></span>

timer_define(m_sensor_timer);

<span class="hljs-comment">// Catch events sent over Bluetooth</span>
<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ble_evt</span><span class="hljs-params">(<span class="hljs-keyword">char</span> *name, <span class="hljs-keyword">char</span> *data)</span>
</span>{
  NRF_LOG_INFO(<span class="hljs-string">"%s: %s"</span>, name, data);
}

<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sensor_timer_evt</span><span class="hljs-params">()</span>
</span>{
  <span class="hljs-comment">// Check if we're connected</span>
  <span class="hljs-keyword">if</span> (ble_is_connected())
  {
    <span class="hljs-comment">// Sends "ping" with the event name of "data"</span>
    ble_publish(<span class="hljs-string">"data"</span>, <span class="hljs-string">"ping"</span>);
  }
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span>
</span>{
  BLE_STACK_PERIPH_DEF(init);

  <span class="hljs-comment">// Configuration for ble stack</span>
  ble_stack_init(&amp;init);

  <span class="hljs-comment">// Setup BLE callback</span>
  ble_subscribe(<span class="hljs-string">"data"</span>, ble_evt);

  <span class="hljs-comment">// Start advertising</span>
  advertising_start();

  <span class="hljs-comment">// Sensor sensor timer.</span>
  timer_create(&amp;m_sensor_timer, TIMER_REPEATED, sensor_timer_evt);

  <span class="hljs-comment">// Start</span>
  timer_start(&amp;m_sensor_timer, <span class="hljs-number">1000</span>);

  <span class="hljs-comment">// Print the address</span>
  util_print_device_address();
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">loop</span><span class="hljs-params">()</span>
</span>{
}
</code></pre>
<p>Next, we'll program it to some hardware!</p>
<h3 id="heading-flashing-the-basic-sensor-code">Flashing the basic sensor code:</h3>
<p>For this step you'll need to have a Xenon handy. You'll also need a programmer, programming cable and two Micro-B USB cables. Here's a picture of everything connected:</p>
<p><img src="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//IMG_4586.jpg" alt="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//IMG_4586.jpg" width="730" height="547" loading="lazy"></p>
<p>Once connected and powered run these commands:</p>
<pre><code class="lang-shell">make erase
make flash_softdevice
make flash
make debug
</code></pre>
<p>Then in a separate terminal window run</p>
<pre><code class="lang-shell">make rtt
</code></pre>
<p><code>make debug</code> and <code>make rtt</code> will create a debugging session. You can issue commands in the <code>make debug</code> terminal to control the device as well. For instance, <code>r</code> followed by <code>Enter</code> will restart the device. (By far my most common use case).</p>
<p>If you've flashed everything successfully, your device should start blinking green. That's a good sign!</p>
<p>Additionally, if you take a look at the <code>make rtt</code> side your output should be similar to this:</p>
<p>    ###RTT Client: Connecting to J-Link RTT Server via localhost:19021 ...</p>
<p>    ###RTT Client: Connected.</p>
<p>    SEGGER J-Link V6.62a - Real time terminal output
    J-Link OB-SAM3U128-V2-NordicSemi compiled Jan 21 2020 17:30:48 V1.0, SN=581758669
    Process: JLinkExe
     app_timer: RTC: initialized.
     app: Boot count: 4
     app: Pyrinas started.
     app: Address: 11:22:33:44:55:66</p>
<p>Take note of the address displayed above. We'll need that for the hub code!</p>
<h3 id="heading-setting-up-the-hub-repository">Setting up the hub repository</h3>
<p><img src="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Copy_of_Particle_Mesh_App_Updates-2.jpg" alt="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Copy_of_Particle_Mesh_App_Updates-2.jpg" width="730" height="486" loading="lazy"></p>
<p>If you haven't already, clone your hub repository locally. We'll want to do some of the same steps as we did with the sensor repo like:</p>
<ul>
<li>Setting up the symbolic link</li>
<li>Updating the Makefile<ul>
<li>Setting your <code>PROG_SERIAL</code></li>
<li>Setting <code>PROG_PORT</code> to a port not used by the sensor setup. <code>19020</code> in this case is fine.</li>
<li>Setting <code>APP_FILENAME</code> to <code>pyrinas-hub</code></li>
</ul>
</li>
</ul>
<p>If you need a reminder how any of these steps work, go back and review the earlier section.</p>
<p>Next, we'll want to open <code>app.c</code> and uncomment the central/hub based code. Plus you'll want to remove the default un-commented code. Your <code>setup()</code> should look something like this:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span>
</span>{
  <span class="hljs-comment">// Default config for central mode</span>
  BLE_STACK_CENTRAL_DEF(init);

  <span class="hljs-comment">// Add an addresses to scan for</span>
  <span class="hljs-keyword">ble_gap_addr_t</span> first = {
      .addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC,
      .addr = {<span class="hljs-number">0x81</span>, <span class="hljs-number">0x64</span>, <span class="hljs-number">0x4C</span>, <span class="hljs-number">0xAD</span>, <span class="hljs-number">0x7D</span>, <span class="hljs-number">0xC0</span>}};
  init.config.devices[<span class="hljs-number">0</span>] = first;

  <span class="hljs-keyword">ble_gap_addr_t</span> second = {
      .addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC,
      .addr = {<span class="hljs-number">0x7c</span>, <span class="hljs-number">0x84</span>, <span class="hljs-number">0x9d</span>, <span class="hljs-number">0x32</span>, <span class="hljs-number">0x8d</span>, <span class="hljs-number">0xe4</span>}};
  init.config.devices[<span class="hljs-number">1</span>] = second;

  <span class="hljs-comment">// Increment the device_count</span>
  init.config.device_count = <span class="hljs-number">2</span>;

  <span class="hljs-comment">// Configuration for ble stack</span>
  ble_stack_init(&amp;init);

  <span class="hljs-comment">// Start scanning.</span>
  scan_start();
}
</code></pre>
<p>You'll notice immediately that there are two clients/devices defined here. Let's remove the second one. Should you, in the future, want to connect more devices this is an example of how to do it.</p>
<p><strong>Reminder:</strong> also make sure that you change the <code>init.config.device_count</code> to <code>1</code>.</p>
<p>Then, you'll want to update the <code>.addr</code> field in <code>ble_gap_addr_t first</code> to match the address we got earlier from <code>make rtt</code>:</p>
<pre><code class="lang-c"><span class="hljs-comment">// Add an addresses to scan for</span>
<span class="hljs-keyword">ble_gap_addr_t</span> first = {
    .addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC,
    .addr = {<span class="hljs-number">0x11</span>,<span class="hljs-number">0x22</span>,<span class="hljs-number">0x33</span>,<span class="hljs-number">0x44</span>,<span class="hljs-number">0x55</span>,<span class="hljs-number">0x66</span>}};
init.config.devices[<span class="hljs-number">0</span>] = first;
</code></pre>
<p>The address field uses raw bytes, so it has to be represented that way. Remove the <code>:</code> and place <code>0x</code> in front of each byte. We end up going from <code>11:22:33:44:55:66</code> to <code>{0x11,0x22,0x33,0x44,0x55,0x66}</code></p>
<p>Now before we flash anything, let's also set up the Bluetooth event handler. As with earlier we'll use <code>ble_subscribe</code> to attach an event handler:</p>
<pre><code class="lang-c"><span class="hljs-comment">// Setup BLE callback</span>
ble_subscribe(<span class="hljs-string">"data"</span>, ble_evt);

Then place the function at the top of the file:

<span class="hljs-comment">// Catch events sent over Bluetooth</span>
<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ble_evt</span><span class="hljs-params">(<span class="hljs-keyword">char</span> *name, <span class="hljs-keyword">char</span> *data)</span>
</span>{
  NRF_LOG_INFO(<span class="hljs-string">"%s: %s"</span>, name, data);

  ble_publish(<span class="hljs-string">"data"</span>, <span class="hljs-string">"pong"</span>);
}
</code></pre>
<p>You'll notice we're printing out the message using <code>NRF_LOG_INFO</code>. We're also sending a message <em>back</em> to the sensor in the form of <code>ble_publish("data","pong");</code> In other-words we're playing a game of ping-pong between the two devices!</p>
<p>In the end your code should look something like this:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"app.h"</span></span>

<span class="hljs-comment">// Catch events sent over Bluetooth</span>
<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ble_evt</span><span class="hljs-params">(<span class="hljs-keyword">char</span> *name, <span class="hljs-keyword">char</span> *data)</span>
</span>{
  NRF_LOG_INFO(<span class="hljs-string">"%s: %s"</span>, name, data);

  ble_publish(<span class="hljs-string">"data"</span>, <span class="hljs-string">"pong"</span>);
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span>
</span>{
  <span class="hljs-comment">// Default config for central mode</span>
  BLE_STACK_CENTRAL_DEF(init);

  <span class="hljs-comment">// Add an addresses to scan for</span>
  <span class="hljs-keyword">ble_gap_addr_t</span> first = {
      .addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC,
      .addr = {<span class="hljs-number">0x11</span>, <span class="hljs-number">0x22</span>, <span class="hljs-number">0x33</span>, <span class="hljs-number">0x44</span>, <span class="hljs-number">0x55</span>, <span class="hljs-number">0x66</span>}};
  init.config.devices[<span class="hljs-number">0</span>] = first;

  <span class="hljs-comment">// Increment the device_count</span>
  init.config.device_count = <span class="hljs-number">1</span>;

  <span class="hljs-comment">// Configuration for ble stack</span>
  ble_stack_init(&amp;init);

  <span class="hljs-comment">// Setup BLE callback</span>
  ble_subscribe(<span class="hljs-string">"data"</span>, ble_evt);

  <span class="hljs-comment">// Start scanning.</span>
  scan_start();
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">loop</span><span class="hljs-params">()</span>
</span>{
}
</code></pre>
<p><strong>Reminder:</strong> make sure you set <code>ble_gap_addr_t first</code> or the two devices will not connect!</p>
<p>To program, connect the Xenon to program as you did before. We'll flash it using the same methods as before:</p>
<pre><code class="lang-shell">make erase
make flash_softdevice
make flash
make debug
</code></pre>
<p>Then in a separate terminal window run</p>
<pre><code class="lang-shell">make rtt
</code></pre>
<p>Then take a look at each of the <code>make rtt</code> screens. There should be some output! For the hub it should look something like this:</p>
<p>    Process: JLinkExe
     app: Boot count: 4
     app: Pyrinas started.
     ble_m_central: Connected to handle 0x0
     ble_m_central: Protobuf Service discovered
     app: data: ping
     app: data: ping</p>
<p>And the sensor side like this:</p>
<p>    Process: JLinkExe
     app_timer: RTC: initialized.
     app: Boot count: 4
     app: Pyrinas started.
     app: Address: 11:22:33:44:55:66
     ble_m_periph: Notifications enabled!
     app: data: pong
     app: data: pong</p>
<p>The ping and pong messages should continue until you stop them. Awesome! If you get any warnings like this one:</p>
<p>    Unable to write. Notifications not enabled!</p>
<p>Use the reset button on either of the devices. This should fix the problem.</p>
<p><strong>Side note:</strong> the pairing process for Bluetooth is inherently <strong><em>insecure</em></strong>. Once the pairing process is complete though, the devices are secure. (With the caveat that no one was sniffing the pairing process!) There may be improvements on security in the future.</p>
<p><strong>Congrats! ?</strong>If you've made it this far, you've deployed your first Pyrinas hub and sensor client! </p>
<p>For more information about what Pyrinas can do you should check out the header files under <code>pyrinas-os/include/</code>. Also, Pyrinas can do anything that you'd normally be able to do with Nordic's SDK. <a target="_blank" href="https://infocenter.nordicsemi.com/topic/struct_sdk/struct/sdk_nrf5_latest.html?cp=7_1">Nordic's Infocenter</a> is a great resource for learning more about what the SDK has to offer.</p>
<h2 id="heading-what-does-the-future-hold-for-pyrinas">What does the future hold for Pyrinas?</h2>
<p><img src="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Copy_of_Particle_Mesh_App_Updates-5.jpg" alt="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/images//Copy_of_Particle_Mesh_App_Updates-5.jpg" width="730" height="486" loading="lazy"></p>
<p>All future tasks for Pyrinas are shared openly on the <a target="_blank" href="https://github.com/pyrinas-iot/pyrinas-os/projects">Github Repo.</a> Here are some of the high level improvements on the roadmap:</p>
<ul>
<li>Particle Boron + LTE support - That's right! Cellular will be coming to Pyrinas. As of this writing, the first board to support Pyrinas LTE will be Particle's Boron.</li>
<li>MQTT (over TLS) and HTTPS support - Once we have cellular, we need something to communicate with. That's where MQTT and HTTPS come in. They're some of the most popular protocols for IoT today.</li>
<li>Built in remote OTA support - As it stands today, devices programmed with Pyrinas uses Nordic's Secure Bootloader. That means they can be updated over the air by a computer or cellphone nearby. This isn't sustainable for long term deployments though!
Instead, you will be able to push updates to Pyrinas devices over the Cloud. Yup. No reason to get off your couch, you can deploy your updates from anywhere.</li>
<li>Dynamic configuration and management - adding and removing devices from a Pyrinas system currently takes some effort. In future revisions, it will be easier to add and remove devices on the fly. This allows for remote device management with zero headaches.</li>
<li>Support for pre-certified modules and other development boards based on Nordic's nRF52840. Currently the Xenon is the only supported board. Development boards aren't great for full production though. Stay tuned for support for pre-certified modules from vendors like <a target="_blank" href="https://www.fanstel.com/bluenor-summaries">Fanstel</a> and more..</li>
<li>Support for more development environments. Currently Pyrinas supports Mac <em>only</em>.</li>
</ul>
<h3 id="heading-star-and-watch">Star and Watch!</h3>
<p>This is only the tip of the iceberg! Stay tuned for more updates and make you you star and watch <a target="_blank" href="https://github.com/pyrinas-iot/pyrinas-os">the repository</a>.</p>
<p>Or, better yet, looking to help out? Contributions are welcome!</p>
<p><strong>You can read other articles on my blog, <a target="_blank" href="https://www.jaredwolff.com/meet-pyrinas-a-new-way-to-use-your-xenon/">jaredwolff.com</a></strong></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How and Why You Should Build Internet of Things Devices with Node.js ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we will discuss why and how you can use Node.js for the server-side of your Internet of Things (IoT) devices. Understand the business opportunity In 2019, the market revenue of IoT reached $212 billion. There are about 26.66 billion ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/iot-and-node-js-how-to-catch-the-opportunity/</link>
                <guid isPermaLink="false">66be14bf0c9c630f4d48debd</guid>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oleh Romanyuk ]]>
                </dc:creator>
                <pubDate>Thu, 13 Feb 2020 14:54:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/02/Title_Images__1_-min.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we will discuss why and how you can use Node.js for the server-side of your Internet of Things (IoT) devices.</p>
<h2 id="heading-understand-the-business-opportunity">Understand the business opportunity</h2>
<p>In 2019, the <a target="_blank" href="https://www.statista.com/topics/2637/internet-of-things/">market revenue of IoT</a> reached $212 billion. There are about 26.66 billion connected IoT devices worldwide, and this number is set to reach 75.44 billion by 2025.  </p>
<p>The UN estimates that, in February 2020, the <a target="_blank" href="https://www.worldometers.info/world-population/">world population</a> is currently 7.7 billion people. Simple math tells us that the average person owns around 3 to 4 IoT devices. Do you have one? Maybe a smartwatch? A smart TV? Or a smart car?</p>
<p>Moving further, the population is expected to reach 8.1 billion people in 2025. The same math calculation shows us that, in 2025, an  average person will have from 9 to 10 smart devices in their possession. </p>
<p>Do you see where I am going with this? Do you want to join this lucrative market niche and make your IoT device one of these 9 to 10?</p>
<p><img src="https://images.ctfassets.net/6xhdtf1foerq/6WhTKrEU5mebpDRnrSEexi/064db656bf882e4da1aff24eedcc6095/mHealth_revenues_reached__23_billion_in_2017__3_.png?fm=png&amp;q=85&amp;w=1000" alt="Statistics retrieved from Statista and the United Nations." width="1000" height="1118" loading="lazy">
<em>Statistics retrieved from Statista and the United Nations.</em></p>
<h2 id="heading-choose-the-right-framework">Choose the right framework</h2>
<p>The client-side of an IoT device is represented by the hardware itself. It is programmed with C, C++, or Lua – low-level and difficult programming languages. But there is not much you can do about it because of hardware limitations. </p>
<p>Along with high performance, users of IoT devices prioritize low cost and energy-efficiency. Thus, at least for now, you should keep working with low-level languages.</p>
<p>On the other hand, the server side of IoT applications offers you more freedom of choice. Here, you are not limited by the hardware, so you can choose any coding language and framework you prefer. </p>
<p>I believe that the right one is Node.js. Here is why.</p>
<h3 id="heading-nodejs-is-fast-and-performant">Node.js is fast and performant</h3>
<p>First of all, any IoT device is constantly working with dynamically changing data. This means that you need a framework which can handle real-time applications and heavy data flows. </p>
<p>Node.js is built on Google’s V8 JS engine, which is highly effective and perfectly scalable. Thanks to this feature, <strong>Node.js is the number one framework to be used with real-time apps and platforms.</strong> Constantly changing data is not a challenge for it either.</p>
<h3 id="heading-nodejs-is-easy-to-integrate-with-iot-protocols">Node.js is easy to integrate with IoT protocols</h3>
<p>IoT applications actively use a publish-subscribe-based messaging protocol, MQTT. In turn, for transportation and encapsulation, this protocol uses WebSockets. <strong>Both MQTT and WebSockets are well-supported and easily integrated with Node.js.</strong></p>
<h3 id="heading-nodejs-modules-facilitate-iot-development">Node.js modules facilitate IoT development</h3>
<p><strong>Node.js is augmented with npm, the Node Package Manager, which features a lot of useful IoT modules.</strong> There are about 80 packages for Intel IoT Edison, Arduino, or Raspberry Pi. Also, it features over 30 packages for different sensors, beacons, and other tools. </p>
<p>This is why <a target="_blank" href="https://keenethics.com/services-internet-of-things">Internet of Things development</a> is simpler and faster with Node.js IoT modules.</p>
<h3 id="heading-nodejs-is-resource-efficient-and-scalable">Node.js is resource-efficient and scalable</h3>
<p>In general, developers prefer working with Node.js because it does not require a lot of resources. The CPU and RAM are not overloaded. </p>
<p>Also, Node.js is highly scalable, which is absolutely necessary for most modern companies.</p>
<h2 id="heading-beware-of-the-challenges">Beware of the challenges</h2>
<p>Entering the IoT niche can lead you down a path to success. No wonder, then, that there are a lot of challenges and traps awaiting you on your way – success is  never easy to achieve. And the first and foremost challenge you should be aware of is security. </p>
<p>Security is one of the top problems in IoT sphere, and one of the first pitfalls you will stumble upon. So what should you do?</p>
<h3 id="heading-secure-authentication">Secure authentication</h3>
<p>Let’s start with authentication. There are a lot of tools for authentication in Node.js: tokens, JSON web tokens, Auth0, and so on. Each has its advantages and disadvantages. To start, you should look at them from the perspective of IoT.</p>
<p><strong>On the one hand, tokens are effective but not 100 percent safe</strong>. They are a cool way to set up authentication as they let you identify a specific user and decide whether to grant or deny them access. A token can be encrypted with any algorithm. </p>
<p>However, the hardware (scanners, sensors, hubs, or other IoT things) should store this token or login/password data in firmware. This means that attackers can steal the token if they have physical access to the hardware. The same story goes for JWT or Auth0.</p>
<p><strong>On the other hand, we can use any tools for authentication on the server side.</strong> You can easily integrate any authentication tool on the Node.js platform. </p>
<p>There are a lot of npm packages which allow you to do this manually: Auth0, Passport, and JWT. There are also packages for integration with cloud IoT services: @azure-iot/authentication, aws-iot-device-sdk, and so on.</p>
<h3 id="heading-secure-http-requests">Secure HTTP requests</h3>
<p>Next, be careful with HTTP requests from your IoT devices. You should check if you get a request from a proper IoT device. </p>
<p>Firstly, you should implement HTTPS with your IoT devices. Hardware is not a browser and you should implement HTTPS manually on it. For the server-side, you can either do it manually or use hosting with HTTPS configuration and certificates. </p>
<p>In Node.js, it is quite easy to implement:</p>
<pre><code><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> https = <span class="hljs-built_in">require</span>(<span class="hljs-string">'https'</span>);
<span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);
<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
<span class="hljs-keyword">const</span> options = {
  <span class="hljs-attr">key</span>: fs.readFileSync(<span class="hljs-string">'path/to/your/key.pem'</span>),
  <span class="hljs-attr">cert</span>: fs.readFileSync(path/to/your/certificate.cert<span class="hljs-string">')
};
const app = express();
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);</span>
</code></pre><p>HTTPS uses SSL or TLS protocols for data encryption. However, to be sure that you have gotten a request from the necessary server or client, use additional data encryption. For example, this is how you can use a signature:</p>
<pre><code><span class="hljs-keyword">const</span> fetch = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node-fetch'</span>);
<span class="hljs-keyword">const</span> verifier = crypto.createVerify(<span class="hljs-string">'RSA-SHA1'</span>)
<span class="hljs-keyword">const</span> SIGNATURE_FORMAT = <span class="hljs-string">'base64'</span>;
<span class="hljs-comment">//check if it trusted url for your certificate</span>
<span class="hljs-keyword">const</span> trustedUrl = ‘https:<span class="hljs-comment">//trustedUrl/’</span>
<span class="hljs-keyword">const</span> isTrustedUrl = trustedUrl.match(url);
If (isTrustedUrl) {
verifier.update(req.body, <span class="hljs-string">'utf8'</span>)
    fetch(isTrustedUrl)
    .then(<span class="hljs-function"><span class="hljs-params">certificate</span> =&gt;</span> {
    <span class="hljs-comment">// check signature</span>
<span class="hljs-keyword">const</span> isValidSignature = verifier.verify(certificate, reg.header.signature, SIGNATURE_FORMAT);
   })
    .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(err));
}
</code></pre><p>To wrap up this part:</p>
<ol>
<li>First, you have to check the trusted URL of your certificate.</li>
<li>Then, you sign a request body with the public key from your certificate.</li>
<li>Finally, you compare the signed body with the signature from headers.</li>
</ol>
<p>It is extremely important to know that you're getting requests from the proper devices and that you're not facing a middle attack.</p>
<h2 id="heading-check-out-these-examples">Check out these examples</h2>
<h3 id="heading-asamahttpsasamatechipseng-tracking-the-movement-of-your-employees"><a target="_blank" href="https://asama.tech/ips/eng">Asama</a> – tracking the movement of your employees</h3>
<p><img src="https://images.ctfassets.net/6xhdtf1foerq/3RxIwnrJoPHrRqGfleU4gT/4072f4db0e1214a3c3bd8088d9cd9ced/Screen_Shot_2019-10-23_at_3.25.42_PM.png?fm=png&amp;q=85&amp;w=1000" alt="asama" width="1000" height="723" loading="lazy"></p>
<p>Asama is a micro-location system, which uses smartwatches and Bluetooth beacons to track movement and activity of employees. Beacons transmit a regular signal. </p>
<p>According to these signals, the smartwatch defines the location of an employee. The smartwatch also analyzes whether the right person is wearing it and if the employee is sleeping or working.</p>
<p><img src="https://images.ctfassets.net/6xhdtf1foerq/4PtS0ph8qnZrL8tENAIsqW/b82c319d1fd95b0e8c0cbd91e6ba7f85/Screen_Shot_2019-10-23_at_3.11.59_PM.png?fm=png&amp;q=85&amp;w=1000" alt="Asama beacon" width="1000" height="430" loading="lazy"></p>
<p><img src="https://images.ctfassets.net/6xhdtf1foerq/3757frFf2tQj7UBhOJsgXJ/b5edeb696b4944f36e980fb24dc036ed/Screen_Shot_2019-10-23_at_3.12.09_PM.png?fm=png&amp;q=85&amp;w=1000" alt="asama tracker" width="1000" height="430" loading="lazy"></p>
<p>The data is then transmitted to the mobile app, which is installed and configured on the employer’s phone. The system is powered by Node.js in IoT.</p>
<p>This way, managers can track their employees in real time, find the person they need right away, and optimize the workspace. Also, at the end of the week the employer receives an extensive report on employee activity. All this helps to boost the company's performance and productivity.</p>
<p>This solution might not suit a business with a small office and flexible hours. Yet, it works perfectly for industrial plants, construction sites, factories, warehouses, shopping centers, supermarkets, hotels, security agencies, restaurants, or stores. </p>
<p>It's well-suited anywhere you as an employer need to know if employees are coming too late or leaving too early, being absent at the working place, not working actively throughout the day, or not following routes and schedules.</p>
<p><img src="https://images.ctfassets.net/6xhdtf1foerq/1uoPqMXKlAZ1gG27fiy41Y/f406960d98805a8f747f130de2f4c9bf/Screen_Shot_2019-10-23_at_3.34.51_PM.png?fm=png&amp;q=85&amp;w=1000" alt="asama clients" width="1000" height="295" loading="lazy"></p>
<h3 id="heading-preehttpskeenethicscomproject-pree-finding-your-belongings"><a target="_blank" href="https://keenethics.com/project-pree">PREE</a> – finding your belongings</h3>
<p>PREE  is a system of BLE beacons and mobile software which helps people stop losing their stuff. It is a lifesaver for those who often forget their phone, bag, keys, wallet, or any other valuable belongings. </p>
<p>The user can see the location of their item in real time and share it with trusted contacts. Once the item is out of range, they will get a notification, and so will their friends or family members. It doesn't spam others with notifications when they are not needed – for example, when at home, the user can mute them for a certain area.</p>
<p>This Internet of Things IoT system is built with <a target="_blank" href="https://keenethics.com/services-web-development-node">Node.js</a>, <a target="_blank" href="https://keenethics.com/tech-back-end-express">Express</a>, and <a target="_blank" href="https://keenethics.com/tech-data-base-mongo">Mongo</a> on the backend and Ionic with <a target="_blank" href="https://keenethics.com/tech-apps-cordova">Cordova</a> for the frontend. The combination of these frameworks ensures the best user experience.</p>
<p><img src="https://images.ctfassets.net/6xhdtf1foerq/5egLeuuCpQFl0PFhtVdOn1/addd7e1d99ccd0b00dfe817db5c2c738/Screen_Shot_2019-10-23_at_3.42.38_PM.png?fm=png&amp;q=85&amp;w=1000" alt="PREE" width="1000" height="484" loading="lazy"></p>
<h2 id="heading-validate-your-idea">Validate your idea</h2>
<p>Once you have an idea for an IoT product, start with validating  it. You can do this in two ways:</p>
<ul>
<li>Hire an idea validation team, who will help you test the viability of your product before you invest in development, or</li>
<li>Hire a software design and development team, who will launch an extensive <a target="_blank" href="https://keenethics.com/blog/product-discovery">product discovery</a> process.</li>
</ul>
<h2 id="heading-postscript">Postscript</h2>
<p>I would like to send a huge thank you to Volodya Andrushchak, the IoT guru at KeenEthics, for contributing and basically breathing life into to this article.</p>
<p>If you have enjoyed the article, you should definitely read some more about Node.js: <a target="_blank" href="https://keenethics.com/blog/what-are-the-advantages-of-node-js">What are the Advantages of Node.JS?</a> or <a target="_blank" href="https://keenethics.com/blog/nodejs-vs-python">NodeJS vs Python: How to Choose the Best Technology to Develop Your Web App's Back End</a>.</p>
<p>The original article posted on KeenEthics blog can be found here: <a target="_blank" href="https://keenethics.com/blog/iot-and-node-js">IoT and Node.JS: How to Catch the Opportunity?</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Develop Particle IoT Apps Using NativeScript ]]>
                </title>
                <description>
                    <![CDATA[ By Jared Wolff If you're developing any type of IoT product, inevitably you'll need some type of mobile app. While there are easy ways, they're not for production use. In this tutorial, we'll talk about the basics of Particle app development. You'll ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-develop-particle-iot-apps-using-nativescript/</link>
                <guid isPermaLink="false">66d8504f29e30bc0ad47757b</guid>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mobile ]]>
                    </category>
                
                    <category>
                        <![CDATA[ NativeScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ particle ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 27 Jan 2020 17:42:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/01/NativeScript---Particle.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jared Wolff</p>
<p>If you're developing any type of IoT product, inevitably you'll need some type of mobile app. While <a target="_blank" href="https://www.jaredwolff.com/create-a-cross-platform-app-using-blynk/">there are easy ways</a>, they're not for production use.</p>
<p>In this tutorial, we'll talk about the basics of Particle app development. You'll learn about some of the many app frameworks you can take advantage of. Plus there's libraries, tricks, and tools along the way to make your life a lot easier.</p>
<h2 id="heading-app-frameworks">App Frameworks</h2>
<p>Sometimes it's dang near irritating to program multiple applications natively. You see, Swift (or Objective C ?) and Java aren't terrible at first glance (well, maybe except for Obj-C ?). But when you're resource constrained, you have to figure out a new game plan. That's where App Frameworks come in.</p>
<p>These frameworks allow an app developer to write, build and test cross platform apps. In some cases, the frameworks convert your app into native code. That means that they run as fast and as well as one written in Swift or Java.</p>
<p>I did the research and as of January 2020, here are some of the most supported frameworks:</p>
<ul>
<li><a target="_blank" href="https://github.com/framework7io/framework7">Framework7</a></li>
<li><a target="_blank" href="https://flutter.dev/">Flutter</a></li>
<li><a target="_blank" href="https://www.nativescript.org/">NativeScript</a></li>
<li><a target="_blank" href="https://github.com/facebook/react-native">ReactNative</a></li>
<li><a target="_blank" href="https://github.com/ionic-team/ionic">Ionic</a></li>
<li><a target="_blank" href="https://cordova.apache.org/">Cordova</a> / <a target="_blank" href="https://phonegap.com/">PhoneGap</a></li>
<li><a target="_blank" href="https://github.com/meteor/meteor">Meteor</a></li>
<li><a target="_blank" href="https://dotnet.microsoft.com/apps/xamarin">Xamarin</a></li>
</ul>
<p>The list goes on for days.</p>
<p>I've used a few of these frameworks in the past. I've built a Meteor app which (surprisingly) worked. In the end I had to pick one though. What did I go with?</p>
<p><strong>NativeScript.</strong></p>
<p>For the most part, NativeScript's documentation and on-boarding experience is fantastic. Not only can you preview your app inside an emulator but you can load it directly to your phone too!</p>
<p><img src="https://www.jaredwolff.com/how-to-develop-particle-iot-apps-using-nativescript/images/Apple_iPhone_6s_Gold_-__status-b1ad9325-8e81-4ee0-b72a-687b62adec29.png" alt="images/Apple_iPhone_6s_Gold_-__status-b1ad9325-8e81-4ee0-b72a-687b62adec29.png" width="730" height="605" loading="lazy"></p>
<p>One of the cool things about NativeScript is that it supports TypeScript. TypeScript is a superset of JavaScript with some extra wiz-bang features. </p>
<p>Unlike other languages, JavaScript technically has no types. If you've done any Particle development you likely know what a type is. We're talking about <code>int</code>, <code>String</code>, <code>float</code> and more. i.e. they're directives to to make sure your JavaScript code stays consistent.</p>
<p>NativeScript is also compatible with most major JavaScript web frameworks. This includes <a target="_blank" href="https://vuejs.org/">Vue.Js</a> and <a target="_blank" href="https://angular.io/">Angular</a>.</p>
<p>I've only noticed one major drawback thus far: the mobile preview mode (<code>tns preview</code> command) does not pay well with native libraries. If you have some native platform specific libraries, you'll have to use the emulator or a device (if you have one).</p>
<p>If you're gung-ho and you <em>want</em> to build multiple apps in their respective languages, the more power to you. There is an advantage over the above frameworks: tried and true Particle SDKs.</p>
<h2 id="heading-available-libraries-amp-sdks">Available Libraries &amp; SDKs</h2>
<p>Particle has gone out of their way to make app development a little easier. This is thanks to the massive development work that has gone into their own SDKs. Yup, gone are the days you have to write manual HTTP request handlers.</p>
<p>Here's a link to both the iOS and Android SDKs:</p>
<ul>
<li><a target="_blank" href="https://docs.particle.io/reference/SDKs/ios/">iOS</a></li>
<li><a target="_blank" href="https://docs.particle.io/reference/SDKs/android/">Android</a></li>
</ul>
<p>Though we won't be covering them here, they reflect all the potential calls that you can make using the <a target="_blank" href="https://docs.particle.io/reference/device-cloud/api/">Cloud API.</a></p>
<p>Speaking of Cloud API, Particle has also developed a <a target="_blank" href="https://docs.particle.io/reference/device-cloud/api/">Node.js</a> library as well. As you can imagine, you can use this for your server side code or JavaScript based app frameworks. Sadly, it doesn't work with NativeScript. Frameworks that use a <a target="_blank" href="https://www.tutorialspoint.com/android/android_webview_layout.htm">WebView</a> should be more compatible.</p>
<p>In the case of this tutorial, we'll be mostly focusing on the Cloud API. This way you have a good understanding of the overall system. It may seem intimidating but if you do it right, you'll get the hang of it real fast.</p>
<h2 id="heading-making-api-calls">Making API Calls</h2>
<p>In NativeScript you can't use libraries like <code>[request](https://github.com/request/request)</code>. (Which happens to be the library Particle's very own <a target="_blank" href="https://github.com/dmiddlecamp">DMC</a> used in the <a target="_blank" href="https://github.com/particle-iot/particle-cli">CLI</a> — DMC if you're reading this, Hi!) You'll have to use the provided <a target="_blank" href="https://docs.nativescript.org/ns-framework-modules/http">HTTP</a> module. </p>
<p>If you scroll all the way to the <a target="_blank" href="https://docs.nativescript.org/ns-framework-modules/http#http-post">bottom of that page</a>, you'll see a fully fledged <code>POST</code> example. I'll reproduce it here but with some Particle specific changes:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Create form post data</span>
<span class="hljs-keyword">var</span> data = <span class="hljs-keyword">new</span> FormData();
data.append(<span class="hljs-string">"name"</span>, <span class="hljs-string">"update"</span>);
data.append(<span class="hljs-string">"data"</span>, <span class="hljs-string">"It's hammer time!"</span>);
data.append(<span class="hljs-string">"private"</span>, <span class="hljs-string">"true"</span>);
data.append(<span class="hljs-string">"access_token"</span>, _token);

<span class="hljs-comment">// Configure the httpModule</span>
<span class="hljs-keyword">return</span> httpModule
    .request({
        url: <span class="hljs-string">`https://api.particle.io/v1/devices/events`</span>,
        method: <span class="hljs-string">"POST"</span>,
        content: data
    })
    .then(
        <span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
            <span class="hljs-keyword">const</span> result = response.content.toJSON();
            <span class="hljs-built_in">console</span>.log(result);
        },
        <span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> {
            <span class="hljs-keyword">if</span> (e) <span class="hljs-built_in">console</span>.log(e);
        }
    );
</code></pre>
<p>The above is an example of what's equivalent to <code>Particle.publish</code> in DeviceOS. Let's break down the parts.</p>
<p>First of all, one of the main gotchas of Particle's Web API is the data format. I first expected that they use JSON but I was sorely wrong. After actually <em>reading</em> the documentation I realized that most POST requests were actually <code>application/x-www-form-urlencoded</code>. That means when you submit data, it's the equivalent to hitting the submit button on an HTML form.</p>
<p>Fortunately, there is an easy way to assemble form data in Node/JavaScript. We can use the <code>FormData()</code> object. Take a look at the above. There should be some familiar parameter names in the <code>data.append</code> calls.</p>
<p><code>"name"</code> refers to the name of the event you're publishing to.</p>
<p><code>"data"</code> refers to the string formatted data that you're publishing.</p>
<p><code>"private"</code> dictates whether or not you want to broadcast this data to the whole Particle world, or just your little corner of it.</p>
<p><code>"access_token"</code> is a token that you can generate in order to make these API calls. Without a token though, you're dead in the water.</p>
<h3 id="heading-getting-a-token">Getting a Token</h3>
<p>Where do we get this elusive <code>access_token</code>?</p>
<p>At first I had no idea.</p>
<p>I created an OAuth user and secret in the console. That lead to a dead end. Fiddled around with different API calls and settings. Nothing. Then it hit me like a ton of bricks. There's an <code>access_token</code> attached to the curl request on every device page!</p>
<p>Open up any device, click the little console button near <em>Events.</em> A popup with instructions an a URL will pop up. Copy the text after <code>access_token=</code>. That is your <code>access_token</code>! See below:</p>
<p><img src="https://www.jaredwolff.com/how-to-develop-particle-iot-apps-using-nativescript/images/Screen_Shot_2020-01-25_at_8.55.21_AM.png" alt="images/Screen_Shot_2020-01-25_at_8.55.21_AM.png" width="730" height="298" loading="lazy"></p>
<p>You can use this token to make calls to the Particle API. This can be to subscribe, publish, write to a function, read variables and more.</p>
<h3 id="heading-through-the-command-line">Through the command line</h3>
<p>That's nice and everything but how the heck can you <em>programmatically</em> generate one? One way is with the command line.</p>
<p><code>particle token create</code> is the name of the command you need to know about. When you run it, you'll be prompted to login. (Also enter your Authenticator code if you use one.) Then the command line will spit out a shiny new <code>access_token</code> you can use with the API!</p>
<h3 id="heading-through-the-api-itself">Through the API itself</h3>
<p>If you couldn't guess, <code>particle token create</code> is a <a target="_blank" href="https://github.com/particle-iot/particle-cli/blob/20d02afc7b72ade0e79d4f4ec724ec6cce9fff1b/src/lib/api-client.js#L192">frontend to a raw API call</a>. You can make these API calls directly too. Here's what it looks like in NativeScript.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Create form post data</span>
<span class="hljs-keyword">var</span> data = <span class="hljs-keyword">new</span> FormData();
data.append(<span class="hljs-string">"username"</span>, <span class="hljs-string">"jaredwolff"</span>);
data.append(<span class="hljs-string">"password"</span>, <span class="hljs-string">"this is not my password"</span>);
data.append(<span class="hljs-string">"grant_type"</span>, <span class="hljs-string">"password"</span>);
data.append(<span class="hljs-string">"client_name"</span>, <span class="hljs-string">"user"</span>);
data.append(<span class="hljs-string">"client_secret"</span>, <span class="hljs-string">"client_secret_here"</span>);

<span class="hljs-comment">// Configure the httpModule</span>
<span class="hljs-keyword">return</span> httpModule
    .request({
        url: <span class="hljs-string">`https://api.particle.io/v1/oauth/token`</span>,
        method: <span class="hljs-string">"POST"</span>,
        content: data
    })
    .then(
        <span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
            <span class="hljs-keyword">const</span> result = response.content.toJSON();
            <span class="hljs-built_in">console</span>.log(result);
        },
        <span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> {
            <span class="hljs-keyword">if</span> (e) <span class="hljs-built_in">console</span>.log(e);
        }
    );
</code></pre>
<p>This call <em>may</em> get more complicated. Mostly in the case if you have two factor authorization setup. It's well worth it when you figure it all out. After all, no one wants to manually create auth tokens if they don't have to!</p>
<p>Now you're ready to write and read from your devices. There's one thing though that may trip you up. Subscribing to events can be troublesome with a regular HTTP client. So much so that if you try to do it with NativeScript's HTTP client, it will lock up and never return. Luckily there is a way to handle these special HTTP calls.</p>
<h2 id="heading-server-sent-what">Server Sent What?</h2>
<p>Server Sent Events (SSE for short) is an HTTP/S subscription functionality. It allows you to connect to a SSE end point and continuously listen for updates. It's a similar web technology to what companies use for push notifications. It does require some extra functionality under the hood though...</p>
<h3 id="heading-sse-library">SSE Library</h3>
<p>After much head scratching and searching I stumbled upon <code>nativescript-sse</code>. It looked simple enough that I could start using immediately. More problems arose when I tried to use it though.</p>
<p>First, it turns out you can't use the library in <code>tns preview</code> mode. The alternative is to use <code>tns run ios --emulator</code> or use <code>tns run ios</code> with your iPhone connected to your computer. The non-emulator command will automatically deliver your prototype app.</p>
<p><strong>Side note:</strong> I had already set up my phone in Xcode. You may have to do this yourself before <code>tns run ios</code> is able to find and deploy to your phone.</p>
<p>Secondly, once I got the library working, I noticed I would get some very nasty errors. The errors seemed to happen whenever a new message from Particle came along. </p>
<p>Turns out the underlying Swift library for iOS <a target="_blank" href="https://github.com/inaka/EventSource/issues/89">had fixed this last year.</a> So I took it upon myself to figure out how to upgrade the NativeScript plugin. I'll save you the time to say that it can be a pain and there is a learning curve!</p>
<p>Fortunately after some hacking I got something working. More instructions on how to compile the plugin are in the <a target="_blank" href="https://github.com/jaredwolff/nativescript-sse">README</a>. Alternatively, you can download a pre-built one on the <a target="_blank" href="https://github.com/jaredwolff/nativescript-sse/releases/tag/v4.0.3">Release page of the repository.</a></p>
<p>Download the <code>.tgz</code> file to wherever you like. Then, you can add it using <code>tns plugin add</code>. The full command looks like this:</p>
<pre><code>tns plugin add path/to/plugin/file.tgz
</code></pre><p>You can check to make sure the library is installed by running <code>tns plugin list</code></p>
<pre><code>**jaredwolff$ tns plugin list
<span class="hljs-attr">Dependencies</span>:
┌─────────────────────┬──────────────────────────────────────────────────────────────────────────────────┐
│ Plugin              │ Version                                                                          │
│ @nativescript/theme │ ~<span class="hljs-number">2.2</span><span class="hljs-number">.1</span>                                                                           │
│ nativescript-sse    │ file:../../Downloads/nativescript-sse/publish/package/nativescript-sse<span class="hljs-number">-4.0</span><span class="hljs-number">.3</span>.tgz │
│ tns-core-modules    │ ~<span class="hljs-number">6.3</span><span class="hljs-number">.0</span>                                                                           │
└─────────────────────┴──────────────────────────────────────────────────────────────────────────────────┘
Dev Dependencies:
┌──────────────────────────┬─────────┐
│ Plugin                   │ Version │
│ nativescript-dev-webpack │ ~<span class="hljs-number">1.4</span><span class="hljs-number">.0</span>  │
│ typescript               │ ~<span class="hljs-number">3.5</span><span class="hljs-number">.3</span>  │
└──────────────────────────┴─────────┘
<span class="hljs-attr">NOTE</span>:
If you want to check the dependencies <span class="hljs-keyword">of</span> installed plugin use npm view &lt;pluginName&gt; grep dependencies
If you want to check the dev dependencies <span class="hljs-keyword">of</span> installed plugin use npm view &lt;pluginName&gt; grep devDependencies**
</code></pre><p>Once installed, invoking the library takes a few steps. Here's an example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { SSE } <span class="hljs-keyword">from</span> <span class="hljs-string">"nativescript-sse"</span>;

sse = <span class="hljs-keyword">new</span> SSE(
            <span class="hljs-string">"https://api.particle.io/v1/events/blob?access_token=&lt;your access token&gt;"</span>,
            {}

<span class="hljs-comment">// Add event listener</span>
sse.addEventListener(<span class="hljs-string">"blob"</span>);

<span class="hljs-comment">// Add callback</span>
sse.events.on(<span class="hljs-string">"onMessage"</span>, <span class="hljs-function"><span class="hljs-params">data</span>=&gt;</span>{
    <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> do stuff with your event data here!</span>
    <span class="hljs-built_in">console</span>.log(data);
});

<span class="hljs-comment">// Connect if not already</span>
sse.connect();
</code></pre>
<p>First you need to import and create an instance of the library. When you create the instance, you will have to enter the URL that you want to use. </p>
<p>In this case we'll be doing the equivalent of <code>Particle.subscribe()</code>. It should look something similar to the above: <code>https://api.particle.io/v1/events/&lt;your event name&gt;?access_token=&lt;your access token&gt;</code>. </p>
<p>Replace <code>&lt;your event name&gt;</code> and <code>&lt;your access token&gt;</code> with the name of your event and your freshly created token!</p>
<p>Then you set up the library to listen for the event you care about. In this case <code>blob</code> is the event I most care about.</p>
<p>Then make sure you configure a callback! That way you can get access to the data when <code>blob</code> does come along. I've made a <code>TODO</code> note where you can access said data.</p>
<p>Finally, you can connect using the <code>.connect()</code> method. If you don't connect, SSE will not open a session and you'll get no data from Particle.</p>
<p>Placement of the code is up to you but from the examples it looks like within the <code>constructor()</code> of your model is a good place.(<a target="_blank" href="https://github.com/jaredwolff/nativescript-sse/blob/master/demo/app/main-view-model.ts">https://github.com/jaredwolff/nativescript-sse/blob/master/demo/app/main-view-model.ts</a>)</p>
<h3 id="heading-other-examples">Other Examples</h3>
<p>If you're curious how to use SSE in other places I have another great example: Particle's CLI.</p>
<p>Particle uses the <code>[request](https://github.com/request/request)</code> library to handle SSE events in the app. Whenever you call <code>particle subscribe blob</code> it invokes a <code>getStreamEvent</code> further inside the code.  You can <a target="_blank" href="https://github.com/particle-iot/particle-cli/blob/master/src/lib/api-client.js#L862">check it out here.</a> The <code>request</code> library has more information on streaming <a target="_blank" href="https://github.com/request/request#streaming">here</a>.</p>
<h2 id="heading-more-resources">More resources</h2>
<p>This is but the tip of the iceberg when it comes to connecting with Particle's API. Particle has some great documentation (as always) you can check out. Here are some important links:</p>
<ul>
<li><a target="_blank" href="https://docs.particle.io/reference/device-cloud/api/">API documentation</a></li>
<li><a target="_blank" href="https://docs.particle.io/reference/SDKs/javascript/">Javascript SDK</a></li>
<li><a target="_blank" href="https://docs.particle.io/reference/SDKs/ios/">iOS SDK</a></li>
<li><a target="_blank" href="https://docs.particle.io/reference/SDKs/android/">Android SDK</a></li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this post we've talked about app frameworks, NativeScript, NativeScript plugins and Server Sent Events. Plus all the Particle related things so you can connect your NativeScript app to Particle's API. </p>
<p>I hope you've found this quick tutorial useful. If you have any questions feel free to leave a comment or <a target="_blank" href="https://www.jaredwolff.com/contact/">send me a message</a>. Also be sure to check out my <a target="_blank" href="https://www.jaredwolff.com/the-ultimate-guide-to-particle-mesh/">newly released guide</a>. It has content just like this all about Particle's ecosystem.</p>
<p>Until next time!</p>
<p><strong>This post was originally from</strong> <a target="_blank" href="https://www.jaredwolff.com/how-to-develop-particle-iot-apps-using-nativescript/"><strong>https://www.jaredwolff.com/how-to-develop-particle-iot-apps-using-nativescript/</strong></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Make an Amazing Looking Iot Dashboard in No Time ]]>
                </title>
                <description>
                    <![CDATA[ By Jared Wolff This post is originally from www.jaredwolff.com In this post, I’m going to show you how to get started with Grafana and InfluxDB. All of this running docker container on Digital Ocean.  That way you can have pretty graphs like these: ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-an-amazing-looking-iot-dashboard-in-no-time/</link>
                <guid isPermaLink="false">66d85050f20d0925f8515af7</guid>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Iot Portal ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 03 Jun 2019 21:17:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/Dashboard-3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jared Wolff</p>
<p><strong>This post is originally from <a target="_blank" href="https://www.jaredwolff.com/how-to-make-an-amazing-looking-iot-dashboard-in-no-time/">www.jaredwolff.com</a></strong></p>
<p>In this post, I’m going to show you how to get started with Grafana and InfluxDB. All of this running docker container on Digital Ocean. </p>
<p>That way you can have pretty graphs like these:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-05_at_12.55.10_PM.png" alt="IoT Dashboard" width="600" height="400" loading="lazy"></p>
<p>The cost?</p>
<p><strong>$5 a month</strong></p>
<p>Let’s get to it.</p>
<h2 id="heading-steps">Steps</h2>
<ol>
<li>Login to Digital Ocean. If you don’t have Digital Ocean and would like to support this blog click <a target="_blank" href="https://m.do.co/c/9574d3846a29">here</a> to create an account.</li>
<li>Go to <code>Account Settings</code> -&gt; <code>Security</code> and make sure you have an SSH key setup.
<img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-07_at_9.14.07_AM.png" alt="Screen_Shot_2019-05-07_at_9.14.07_AM" width="600" height="400" loading="lazy"></li>
<li>Create a new droplet use their <a target="_blank" href="https://marketplace.digitalocean.com/apps/docker">docker image</a></li>
<li>Make sure you select the $5 a month plan. For simple installs, this is more than enough!</li>
<li>SSH in once you’re done: <code>ssh root@&lt;yourserverip&gt;</code></li>
<li><p>Set up InfluxDB</p>
<pre><code>   docker run --rm -e INFLUXDB_HTTP_AUTH_ENABLED=<span class="hljs-literal">true</span> -e INFLUXDB_DB=particle -e INFLUXDB_ADMIN_ENABLED=<span class="hljs-literal">true</span> -e INFLUXDB_ADMIN_USER=admin -e INFLUXDB_USER=grafana -v influxdb:<span class="hljs-regexp">/var/</span>lib/influxdb influxdb /init-influxdb.sh
</code></pre><p>   Watch the output of this command. It will generate passwords for both your <code>admin</code> and <code>grafana</code> user. Save these in a safe place!</p>
</li>
<li><p>Start influx</p>
<pre><code>   docker run -d -p <span class="hljs-number">8086</span>:<span class="hljs-number">8086</span> \
         -v influxdb:<span class="hljs-regexp">/var/</span>lib/influxdb \
         -e INFLUXDB_HTTP_AUTH_ENABLED=<span class="hljs-literal">true</span> \
         influxdb
</code></pre></li>
<li><p>Add firewall rule</p>
<pre><code>   ufw allow <span class="hljs-number">8086</span>
</code></pre><p>   This allows the outside world to get to your InfluxDB instance.</p>
</li>
<li><p>Set up curl from Particle</p>
<p>   Example equivalent call:</p>
<pre><code>   curl -i -XPOST <span class="hljs-string">'http://&lt;DOCKER IP HERE&gt;:8086/write?db=particle'</span> --data-binary <span class="hljs-string">'temperature,id=&lt;ID HERE&gt; value=22.1'</span>
</code></pre><p>   The version of this to put in the <strong>custom request</strong> would be:</p>
<pre><code>   temperature,id={{{PARTICLE_DEVICE_ID}}} value={{{temperature}}}
</code></pre><p>   <img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-04_at_9.19.59_PM.png" alt="Screen_Shot_2019-05-04_at_9.19.59_PM" width="600" height="400" loading="lazy"></p>
<p>   <strong>Note:</strong>  see under <code>QUERY PARAMETERS</code> that <code>db</code> is pointing to <code>particle</code>. This should point to whatever you  set <code>INFLUXDB_DB</code> to in step 6</p>
<p>   <strong>Second Note:</strong> make sure that the username and password is the one you set up on step 6 as well. In this example the username is <code>grafana</code></p>
<p>   <img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-04_at_9.19.54_PM.png" alt="Screen_Shot_2019-05-04_at_9.19.54_PM" width="600" height="400" loading="lazy"></p>
<p>   Here’s a more complex version:</p>
<pre><code>   temperature,id={{{PARTICLE_DEVICE_ID}}} value={{{temperature}}}
   humidity,id={{{PARTICLE_DEVICE_ID}}} value={{{humidity}}}
   tvoc,id={{{PARTICLE_DEVICE_ID}}} value={{{tvoc}}}
   c02,id={{{PARTICLE_DEVICE_ID}}} value={{{c02}}}
   {{#pm25}}pm25,id={{{PARTICLE_DEVICE_ID}}} value={{{pm25}}}{{/pm25}}
   {{#pm10}}pm10,id={{{PARTICLE_DEVICE_ID}}} value={{{pm10}}}{{/pm10}}
   {{#sgp30_tvoc}}sgp30_tvoc,id={{{PARTICLE_DEVICE_ID}}} value={{{sgp30_tvoc}}}{{/sgp30_tvoc}}
   {{#sgp30_c02}}sgp30_c02,id={{{PARTICLE_DEVICE_ID}}} value={{{sgp30_c02}}}{{/sgp30_c02}}
   {{#bme680_pres}}bme680_pres,id={{{PARTICLE_DEVICE_ID}}} value={{{bme680_pres}}}{{/bme680_pres}}
   {{#bme680_iaq}}bme680_iaq,id={{{PARTICLE_DEVICE_ID}}} value={{{bme680_iaq}}}{{/bme680_iaq}}
   {{#bme680_temp_calc}}bme680_temp_calc,id={{{PARTICLE_DEVICE_ID}}} value={{{bme680_temp_calc}}}{{/bme680_temp_calc}}
   {{#bme680_hum_calc}}bme680_hum_calc,id={{{PARTICLE_DEVICE_ID}}} value={{{bme680_hum_calc}}}{{/bme680_hum_calc}}
</code></pre><p>   For conditional data you can wrap the whole line in the variable that may or may not be there:</p>
<pre><code>   {{#bme680_pres}}&lt;insert stuff related to bme680_pres&gt;{{/bme680_pres}}
</code></pre></li>
<li><p>Next! Install Grafana with persistent storage</p>
<pre><code>  # create a persistent volume <span class="hljs-keyword">for</span> your data <span class="hljs-keyword">in</span> /<span class="hljs-keyword">var</span>/lib/grafana (database and plugins)
  docker volume create grafana-storage

  # start grafana
  docker run \
    -d \
    -p <span class="hljs-number">3000</span>:<span class="hljs-number">3000</span> \
    --name=grafana \
    -v grafana-storage:<span class="hljs-regexp">/var/</span>lib/grafana \
    grafana/grafana
</code></pre></li>
<li><p>Add firewall rule for graphana</p>
<pre><code>    ufw allow <span class="hljs-number">3000</span>
    <span class="hljs-string">`</span>
</code></pre></li>
<li><p>Login. This should be your Digital Ocean Droplet ip + :3000 appended. Example: <code>123.456.789.101:3000</code> (Default username and password is <strong>admin</strong> and <strong>admin</strong>)</p>
</li>
<li><p>Connect Grafana to Influx (should be one of the first options on a fresh Grafana install)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-04_at_9.24.02_PM_copy.png" alt="Screen_Shot_2019-05-04_at_9.24.02_PM_copy" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-04_at_9.25.39_PM_copy.png" alt="Screen_Shot_2019-05-04_at_9.25.39_PM_copy" width="600" height="400" loading="lazy"></p>
<p><strong>Note</strong> under user, you’ll have to put the username <code>grafana</code> and the generated password from step 6. Also the name of the database has been set as <code>particle</code> in the same step.</p>
</li>
<li><p>Test your connection by clicking <code>Save &amp; Test</code> It should come back quickly saying whether or not a connection has been successful.</p>
</li>
<li><p>Start up your device, if not already, and get it publishing to your InfluxDB database.</p>
<p>(Need data? <a target="_blank" href="https://www.jaredwolff.com/homemade-indoor-air-quality-sensor/">This project should get you some!</a>)</p>
</li>
<li><p>Create graphs!</p>
<p>Finally, the reason why you came to this page: <strong>pretty graphs</strong></p>
<p>Click the <strong>+</strong> icon on the left and create a <strong>new dashboard</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-07_at_9.32.49_AM.png" alt="Screen_Shot_2019-05-07_at_9.32.49_AM" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Select <code>Add Query</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-07_at_9.33.58_AM.png" alt="Screen_Shot_2019-05-07_at_9.33.58_AM" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Go down and click <code>select measurement</code> If your device has been publishing to your database, you should see some options for values.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-07_at_9.34.32_AM.png" alt="Screen_Shot_2019-05-07_at_9.34.32_AM" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Under <code>fill(null)</code> change that to <code>fill(none)</code>. That should give you a nice line between datapoints.</p>
</li>
<li>You should see the graph appear!
<img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-05-07_at_9.36.36_AM.png" alt="Screen_Shot_2019-05-07_at_9.36.36_AM" width="600" height="400" loading="lazy"></li>
<li>Click the back arrow button and then click the save button.</li>
<li>You now created a simple graph on the data directly from your device! I recommend you play around with the Grafana interface. It's fairly intuitive and takes only a few short minutes to get used to!</li>
</ol>
<h2 id="heading-httpsssl">HTTPS/SSL</h2>
<p>Installing HTTPS/SSL is fairly straight forward. Follow the steps below:</p>
<ol>
<li>Stop the Grafana instance if you haven't already</li>
<li><p>Start a new container with <code>nginx-proxy</code></p>
<pre><code>docker run --detach \
    --name nginx-proxy \
    --publish <span class="hljs-number">80</span>:<span class="hljs-number">80</span> \
    --publish <span class="hljs-number">443</span>:<span class="hljs-number">443</span> \
    --volume /etc/nginx/certs \
    --volume /etc/nginx/vhost.d \
    —volume /usr/share/nginx/html \
    —volume /<span class="hljs-keyword">var</span>/run/docker.sock:<span class="hljs-regexp">/tmp/</span>docker.sock:ro \
    jwilder/nginx-proxy
</code></pre></li>
<li><p>Run the <code>letsencrypt-nginx-proxy-companion</code></p>
<pre><code>docker run —detach \
    —name nginx-proxy-letsencrypt \
    —volumes-<span class="hljs-keyword">from</span> nginx-proxy \
    —volume /<span class="hljs-keyword">var</span>/run/docker.sock:<span class="hljs-regexp">/var/</span>run/docker.sock:ro \
    jrcs/letsencrypt-nginx-proxy-companion
</code></pre></li>
<li><p>Restart the Grafana container</p>
<pre><code>docker run \
  -d \
    --env <span class="hljs-string">"VIRTUAL_HOST=&lt;YOUR SUBDOMAIN ADDRESS&gt;"</span> \
  --env <span class="hljs-string">"VIRTUAL_PORT=3000"</span> \
  --env <span class="hljs-string">"LETSENCRYPT_HOST=&lt;YOUR SUBDOMAIN ADDRESS&gt;"</span> \
  --env <span class="hljs-string">"LETSENCRYPT_EMAIL=&lt;YOUR EMAIL ADDRESS&gt;"</span> \
  --name=grafana \
  -v grafana-storage:<span class="hljs-regexp">/var/</span>lib/grafana \
  grafana/grafana
</code></pre><p><strong>Note:</strong> make sure you replace <code>&lt;YOUR SUBDOMAIN ADDRESS&gt;</code> and <code>&lt;YOUR EMAIL ADDRESS&gt;</code> above with your own info.</p>
</li>
</ol>
<p>The proxy companion will generate an SSL certificate for the virtual host that you provided to the Grafana container. The proxy is used to forward all HTTP/HTTPS traffic to your Grafana container. It's clean, it's simple and it's secure!</p>
<p><strong>Note</strong> InfluxDB is a bit more difficult. You either need to make a separate subdomain or configure HTTPS to share the certs between Grafana and Influx. This <a target="_blank" href="https://www.grzegorowski.com/grafana-with-lets-encrypt-ssl-on-docker/">Docker Compose script</a> does it all if you haven't already installed everything. You can follow the same steps above if you want to run it on a separate sub-domain.</p>
<h2 id="heading-handy-links">Handy Links</h2>
<p>Here are some handy links that I found useful getting started with Grafana + InfluxDB</p>
<ul>
<li><a target="_blank" href="https://docs.docker.com/samples/library/influxdb/">influxdb | Docker Documentation</a></li>
<li><a target="_blank" href="https://grafana.com/docs/guides/getting_started/">Getting Started | Grafana Documentation</a></li>
<li><a target="_blank" href="https://grafana.com/docs/installation/docker/">Installing using Docker | Grafana Documentation</a></li>
<li><a target="_blank" href="https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion/">Let's Encrypt Nginx Proxy Companion</a></li>
<li><a target="_blank" href="https://www.grzegorowski.com/grafana-with-lets-encrypt-ssl-on-docker/">Very Handy about Setting up HTTPS for both Grafana and Influx</a></li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You made it. Enjoy your new Grafana + InfluxDB install!</p>
<p>If you liked this tutorial, please share with your friends and your enemies. Also if you’re craving more, <a target="_blank" href="https://www.jaredwolff.com/homemade-indoor-air-quality-sensor/">check out how to build your own air quality sensor using only a few parts.</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build an Affordable Air Quality Sensor for Your Home ]]>
                </title>
                <description>
                    <![CDATA[ By Jared Wolff This post is originally from www.jaredwolff.com I got my hands on some of the mesh based Particle boards not too long ago. I’ve been itching to try them out but haven’t quite figured out the project. One thing has been bothering me tho... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-an-affordable-and-proven-air-quality-sensor/</link>
                <guid isPermaLink="false">66d8504be86088251dd27bb9</guid>
                
                    <category>
                        <![CDATA[ Electronics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Google Docs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 03 Jun 2019 20:10:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/Copy-of-Particle-Sensor-3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jared Wolff</p>
<p><strong>This post is originally from <a target="_blank" href="https://www.jaredwolff.com/homemade-indoor-air-quality-sensor">www.jaredwolff.com</a></strong></p>
<p>I got my hands on some of the mesh based Particle boards not too long ago. I’ve been itching to try them out but haven’t quite figured out the project.</p>
<p>One thing has been bothering me though: air quality. I spend a good amount of time in my office tinkering, soldering, coding and writing. I sneeze occasionally so I always wondered, how bad is it? The house is also prone to mold exposure during the hot months which had me concerned.</p>
<p>So why not cook something up?</p>
<h2 id="heading-whats-needed">What’s needed</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/ingredients.jpg" alt="All the parts needed" width="600" height="400" loading="lazy"></p>
<p>The most important sensor is the <a target="_blank" href="https://www.honeywellscportal.com/honeywell-sensing-hpm-series-particle-sensors-datasheet-32322550-e-en.pdf">Honeywell HPM series</a> PM2.5/PM10 sensor. This tells you how many micrograms of material is floating around in a cubic volume of space. i.e. it counts the little particles flying around in your air.</p>
<p>Second to that, is the <a target="_blank" href="https://ams.com/documents/20143/36005/CCS811_DS000459_7-00.pdf">AMS CCS811</a>. This sensor tells you the total amount of volatile organic compounds are in the air along with things like C02. It’s another datapoint which is interesting to see. I’ve previously placed this sensor in our basement only to be surprised and see huge spikes in VOC and C02 levels from our (oil burning) furnace turning on in the morning. Time for better ventilation!</p>
<p>Finally,  the <a target="_blank" href="https://www.silabs.com/documents/public/data-sheets/Si7021-A20.pdf">Silicon Labs Si7021</a> temperature and humidity sensor. These two bits of environmental data are useful. More importantly they’re used by the algorithm in the CCS811 to compute the TVOC and C02.  Considering the cost of the CCS811, I’m surprised it doesn’t have these measurements on board but maybe in their next revision..</p>
<h2 id="heading-wiring-it-all-together">Wiring it all together</h2>
<p>It’s time to wire everything together. At the very least you’ll need:</p>
<ol>
<li>Solder-less breadboard hookup wire</li>
<li>A solder-less breadboard</li>
<li>A <a target="_blank" href="https://www.adafruit.com/product/3566">CCS811 breakout board</a> from Adafruit (<a target="_blank" href="https://learn.adafruit.com/adafruit-ccs811-air-quality-sensor?view=all">more details here</a>)</li>
<li>A <a target="_blank" href="https://www.adafruit.com/product/3251">Si7021 breakout  from Adafruit</a>(<a target="_blank" href="https://learn.adafruit.com/adafruit-si7021-temperature-plus-humidity-sensor?view=all">more details here</a>)</li>
<li><a target="_blank" href="https://www.particle.io/mesh/">A Particle board of your choice.</a></li>
<li>A <a target="_blank" href="https://www.jaredwolff.com/store/dust-sensor/">HPMA115 Particle sensor</a></li>
<li>Pre assembled Molex cable for the HPMA115 (Molex P/N 0151340803 or similar)</li>
<li>Some 0.1” pitch headers</li>
</ol>
<p>I’ve included a Fritzing example with this project. There’s also a hookup image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/particle-squared-hookup-diagram.jpg" alt="Fritzing Hookup Diagram" width="600" height="400" loading="lazy">
<strong>Note:</strong> the original Fritzing diagram was incorrect. Both Vin of the CCS811 and Si7021 should be connected to the 3.3V on the Particle</p>
<p>An Adafruit Feather is used to represent the Particle Argon. Particle does not have Fritzing models quite yet.</p>
<p>As you can see everything is hooked up except for the PM2.5 sensor. The pinout is included below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-23_at_12.31.03_PM.png" alt="Particle sensor pinout" width="600" height="400" loading="lazy"></p>
<p>The most important pins are the 5V, GND, RX and TX pins. The other ones can stay disconnected if you choose. Here are the connections called out:</p>
<p>    5V     -&gt; USB
    GND    -&gt; GND
    RX     -&gt; TX (on the Argon)
    TX     -&gt; RX (on the Argon).</p>
<p>Here’s a picture of everything assembled on a solder-less breadboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01397.jpg" alt="Everything assembled on breadboard" width="600" height="400" loading="lazy"></p>
<p>Another important note is that I modified the cable for the HPMA so they had male pins on the end. That made it easy to insert into the solder-less breadboard. Here’s a zoomed in shot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01370.jpg" alt="Soldered pin" width="600" height="400" loading="lazy"></p>
<p>When you purchase the cable for the PM2.5 sensor it came pre-populated with 8 wires. To make things simpler, you can remove 4 of the wires that are not used. The best way to do that is take a sharp tipped tool (dental pick, sewing needle, etc) and stick it under the clips I’ve pointed out in red below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01371.jpg" alt="Clips holding the wires in" width="600" height="400" loading="lazy"></p>
<p>Then, once you have your sharp implement underneath, tug on the wire and it should slide out.</p>
<p>Now you have less wire and less headache. You can use this technique to modify any Molex-like connector.</p>
<h2 id="heading-plumbing-the-firmware">Plumbing the firmware</h2>
<p>For this project I decided to keep my code consistent with the Wiring/Arduino-like API. That means object oriented C++. It’s been a while where I’ve coded in C++ so when you’re looking at the codebase and wondering “why the hell did he do that!?” Sorry, not sorry. ?</p>
<p>The best way to get started is to use Visual Code with the Particle plugins for this project. <a target="_blank" href="https://www.particle.io/workbench/">Click here to get started if you're not already setup.</a></p>
<h3 id="heading-si7021">Si7021</h3>
<p>The Si7021 is super simple. It only has 4 active pins out of the 6 on the chip.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-23_at_1.18.21_PM.png" alt="Si7021 pinout" width="600" height="400" loading="lazy">
(Copied directly from the Si7021 documentation)</p>
<p>The best say to read the temperature/humidity sensor is to issue a blocking read command. In an embedded world, this is not ideal. Unfortunately, there’s no way to know when the readings are ready because there is no interrupt pin.</p>
<p>As described in the data-sheet, you first write the command and then attempt to read directly from the device. The code looks something like this:</p>
<pre><code>    <span class="hljs-comment">// Si7021 Temperature</span>
    Wire.beginTransmission(SI7021_ADDRESS);
    Wire.write(SI7021_TEMP_HOLD_CMD); <span class="hljs-comment">// sends one byte</span>
    Wire.endTransmission();           <span class="hljs-comment">// stop transaction</span>
    Wire.requestFrom(SI7021_ADDRESS, <span class="hljs-number">2</span>);

    <span class="hljs-comment">// Get the raw temperature from the device</span>
    uint16_t temp_code = (Wire.read() &amp; <span class="hljs-number">0x00ff</span>) &lt;&lt; <span class="hljs-number">8</span> | (Wire.read() &amp; <span class="hljs-number">0x00ff</span>);
</code></pre><p>Wire the address of the device, write the command and then subsequently read the number of bytes necessary (Two in this case) The Si7021 will then stretch the clock until the reading has completed.</p>
<p>I didn’t mess around with other settings. Depending on your environment you may have to tweak how much current to feed the heater. You’re mileage may vary so prepare accordingly!</p>
<p>Finally, these readings are read on a reoccurring timer. I originally was using the <code>millis()</code> call and calculating the different of the start and current time but this eventually breaks (in 50 or so days). Instead I decided to use a system timer (similar to if not the same as the APP_TIMER in the NRF SDK)</p>
<pre><code>Timer timer(MEASUREMENT_DELAY_MS, timer_handler);
</code></pre><p>That way you get your interrupt always at <code>MEASUREMENT_DELAY_MS</code> no matter what! (In my case <code>MEASUREMENT_DELAY_MS</code> = 60000 ms == 60s)</p>
<h3 id="heading-the-ccs811">The CCS811</h3>
<p>The CCS811 gives you a bit more freedom to play but it comes with it’s own <em>specialness</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-23_at_2.34.14_PM.png" alt="CCS811 pinout" width="600" height="400" loading="lazy"></p>
<p>In most cases the ADDR pin is set low. This pin modifies one bit of the address. This is useful if you have two of the same device or two devices with the same address on the same I2C bus.</p>
<p>The CCS811 also has a few handy input and output pins. The most important is the interrupt pin. Whenever a reading is complete, this open drain pin will be pulled low. It will only get reset once you read the status  register. This is great for asynchronous reads that way you’re not locking up your MCU.</p>
<p>One important point is that the CCS811 does require you to issue a “start” command. This forces the internal MCU to start executing the TVOC/CO2 sensing algorithm. If you attempt to read the data registers before the application is started you will get bogus data. (The command is 0x90)</p>
<p>In the firmware, the CSS811 is processed in the same loop as the Si7021. The code pulls the available data from the CSS811 asynchronous readings. No blocking code!</p>
<h3 id="heading-the-hpma115">The HPMA115</h3>
<p>The particle sensor is a bit more tricky. When it is turned on, the device starts sending particulate data on a regular interval. i.e. it’s in auto-send mode every time it powers up.</p>
<p>I tried previously to configure the device but sometimes I wouldn’t get a response back. It was always hit and miss. It drove me crazy.</p>
<p>So, in order to turn the device off wen you’re not using it I highly suggest using a load switch of some kind. Not only will this save power but according to Honeywell, it will also increase the lifespan of the fan.</p>
<p>The flow of the readings:</p>
<ul>
<li>Every minute turn it on</li>
<li>Wait for data to be sent</li>
<li>Read the reading asynchronously via UART</li>
<li>Turn it off</li>
<li>Bundle that data into the JSON blob to be sent to the server</li>
</ul>
<p>This way there’s no need to mess with any registers. All the more reason why I2C and even SPI are better data buses than UART. I just want it to work!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/DSC01372.jpg" alt="Holding HPMA115S0" width="600" height="400" loading="lazy"></p>
<p>I originally chose this sensor a while back for it’s enclosed nature. In my option, it’s easier to integrate. My electrical engineer brain doesn’t want to deal with complex stuff. Give me a box and lets go.</p>
<h2 id="heading-getting-everything-working">Getting everything working</h2>
<p>During the development phase of this project I happened to be traveling abroad. The crappy wifi was not cutting it and it was taking forever to iterate on the code. The Argon also had a hard time connected to my iPhone’s AP so I gave up on that idea early on.</p>
<p>So, in order to develop the code that didn’t require the internet I placed the device into manual mode. What does manual mode do? It allows the code to start execution despite not being connected to the Particle cloud. That way you can take readings all day but you don’t have to be connected to Wifi.  You can put the device in manual mode by putting this define in your <code>.ino</code> file:</p>
<pre><code>SYSTEM_MODE(MANUAL);
</code></pre><p>In battery powered applications, this is ideal. Wifi is expensive power-wise and you don’t need to be running it if you don’t have to!</p>
<p>In a previous experiment, I found that it took about 10-15 seconds from nothing to sending data to the Particle cloud. That’s a <strong>long time</strong> in the embedded world. That’s one of the main reasons I suspect Particle came out with their mesh system. This allows sleepy end nodes (or nodes that are taking data and periodically sending it to a central point) to run much longer than their Wifi based cousins.</p>
<p>Remember you will have to run the <code>Particle.connect()</code> function in order to connect to wifi in manual mode. Or if you’re ready for it to re-connect, remove <code>SYSTEM_MODE(MANUAL);</code> from your <code>.ino</code> file.</p>
<h3 id="heading-changing-wifi-credentials">Changing Wifi Credentials</h3>
<p>During my experiment in trying to get my wifi to work I did discover a few handy Particle tools to change wifi credentials etc. By holding the mode button during operation, the device eventually starts blinking blue. Once blinking blue, you can issue a <code>particle serial wifi</code> which will walk you through the process of changing the credentials.</p>
<p>The above process is light years faster than using the iPhone/Android app. I thought the app was cool at first but man does it take a long time to scan and get your devices connected.</p>
<p><a target="_blank" href="https://docs.particle.io/tutorials/device-os/led/argon/#network-reset-fast-blinking-blue-">More info on this procedure go here.</a></p>
<h3 id="heading-recovering-when-things-go-awry">Recovering when things go awry</h3>
<p>I had to recover my Argon during my development process. I did some digging and found that re-programming the OS, App and Bootloader seemed to do the trick.</p>
<p>Get the files here: <a target="_blank" href="https://github.com/particle-iot/device-os/releases/tag/v0.9.0">Release 0.9.0 (Gen 3) · particle-iot/device-os · GitHub</a> (As of this writing the latest is 0.9.0)</p>
<p>Then program these files in <a target="_blank" href="https://docs.particle.io/tutorials/device-os/led/photon/#dfu-mode-device-firmware-upgrade-">DFU mode</a> by holding the <code>mode</code> button after tapping the <code>reset</code> button once.</p>
<pre><code>particle flash --usb system-part1<span class="hljs-number">-0.9</span><span class="hljs-number">.0</span>-argon.bin
particle flash --usb tinker<span class="hljs-number">-0.9</span><span class="hljs-number">.0</span>-argon.bin
</code></pre><p>Program this one in <a target="_blank" href="https://docs.particle.io/tutorials/device-os/led/photon/#listening-mode">Listening mode:</a></p>
<pre><code>particle flash --serial bootloader<span class="hljs-number">-0.9</span><span class="hljs-number">.0</span>-argon.bin
</code></pre><p><em>Note:</em> the <code>-argon</code> suffix may be different depending on what you’re programming to. Other options are <code>-boron</code> and <code>-xenon</code>.</p>
<h2 id="heading-monitoring-on-the-command-line">Monitoring on the command line</h2>
<p>Finally, one of the most useful commands is this one:</p>
<p><code>particle serial monitor --follow</code></p>
<p>This allows you to use the USB <code>Serial</code> interface to receive debug messages from he device. This is akin to connecting an FTDI device to an Arduino.</p>
<p>For instance, I may be debugging part of the code so I want to see some data. In the <code>Setup()</code> function I’ll be sure to run <code>Serial.begin()</code>, then later on I’ll make a <code>Serial.printf(“data: %d”,data.tvoc);</code> in order for it to be sent over the USB Serial interface.</p>
<p>Serial UART for debugging, it’s a beautiful thing.</p>
<h2 id="heading-publishing">Publishing</h2>
<p>One thing I did discover during the development process was the publishing limits of the Particle platform. For a single device, you cannot <code>Particle.Publish</code> more than 4 pieces of data in one second. Even though I was taking data every minute, I was sending 6 pieces of individual data to the server at the same time. After testing I soon started to wonder why the heck my C02 and TVOC readings disappeared.</p>
<p>I had found the culprit.</p>
<p>So, in order to make things work, I had to format it as a JSON blob. See how I did it exactly below:</p>
<pre><code><span class="hljs-built_in">String</span> out = <span class="hljs-built_in">String</span>::format(<span class="hljs-string">"{\"temperature\":%.2f,\"humidity\":%.2f,\"pm25\":%d,\"pm10\":%d,\"tvoc\":%d,\"c02\":%d}"</span>,si7021_data.temperature,si7021_data.humidity,hpma115_data.pm25,hpma115_data.pm10,ccs811_data.tvoc,ccs811_data.c02);
Particle.publish(<span class="hljs-string">"blob"</span>, out , PRIVATE, WITH_ACK);
</code></pre><p>I created a JSON structure and then used <code>String::format</code> to insert each piece where they needed to be. If you are running your device over LTE this will cause you to send more data than necessary. There are better options like <a target="_blank" href="https://www.jaredwolff.com/how-to-define-your-own-bluetooth-low-energy-configuration-service-using-protobuf/">Protocol Buffers</a> or using <a target="_blank" href="https://msgpack.org">MessagePack</a>. If you’re dealing with complex data, I recommend the former because of its programatic nature. Plus, you can use it with just about any programming language. So web to embedded? No problem.</p>
<p>After every minute, I only send the data when all three sensors have been read. I use three separate boolean values to determine the state of the sensor readings. Once they have all been set to <code>true</code> do I invoke the <code>Particle.Publish</code>call.</p>
<p>Then after publishing, I reset all variables like so:</p>
<pre><code>ccs811_data_ready = <span class="hljs-literal">false</span>;
si7021_data_ready = <span class="hljs-literal">false</span>;
hpma115_data_ready = <span class="hljs-literal">false</span>;
</code></pre><p>Then, everything starts all over again. You can also create a status struct which has each of these flags neatly inside. Considering I only have three data points, I didn’t go the extra mile there.</p>
<h2 id="heading-using-adafruit-io">Using Adafruit IO</h2>
<p>One way to publish is by using Adafruits IO platform. Here's how to get started.</p>
<ol>
<li>Create an account here: https://io.adafruit.com</li>
<li><p>Next is to create feeds for each of the data types. We’ll need 6 in total.
<img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-19_at_6.47.38_PM.png" alt="Create a feed in Adafruit IO" width="600" height="400" loading="lazy"></p>
</li>
<li><p>For each feed, add a Webhook.
<img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-19_at_6.45.27_PM.png" alt="Add a webhook for data" width="600" height="400" loading="lazy"></p>
</li>
<li>Take each webhook address and create a new Webhook in the Particle console</li>
<li>Change the <code>Request format</code> to JSON</li>
<li>Then under <code>Advanced Settings</code> click on <code>Custom</code> for the <strong>JSON DATA</strong></li>
<li><p>Replace what’s there using <a target="_blank" href="https://docs.particle.io/reference/device-cloud/webhooks/#variable-substitution">mustache templates</a>. Adafruit IO is looking for a JSON key called <code>value</code>. So set it like this:</p>
<pre><code>{
 “value”:”{{{c02}}}”
}
</code></pre><p>You can replace <code>c02</code> with any of the keys in your JSON blob. As a reminder the current JSON blob looks something like this:</p>
<pre><code>{
 “temperature”:<span class="hljs-number">21.2</span>,
 “humidity”:<span class="hljs-number">30</span>,
 “pm10”:<span class="hljs-number">2</span>,
 “pm25”:<span class="hljs-number">1</span>,
 “tvoc”:<span class="hljs-number">650</span>,
 “c02”:<span class="hljs-number">1001</span>
}
</code></pre></li>
<li>Repeat this as necessary until all feeds have a corresponding Webhook configured.</li>
<li>Finally, you can create a dashboard to see them all in one place. This is straight forward just follow the on screen prompts. :)</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-19_at_7.04.16_PM.png" alt="List of Feeds" width="600" height="400" loading="lazy">
<img src="https://www.freecodecamp.org/news/content/images/2020/08/Screen_Shot_2019-03-19_at_7.16.17_PM.png" alt="Graphs of Feeds" width="600" height="400" loading="lazy"></p>
<p>You can check out my <a target="_blank" href="https://io.adafruit.com/jaredwolff/dashboards/air-quality-sensor">live dashboard here</a>. It’s nifty and just another way to display your data.</p>
<p><strong>Sidenote:</strong> My first impressions on Adafruit IO are good. It was easy to setup and start using. The main drawback that it’s tedious especially if you have more than a handful of data points. But maybe they’ll fix that in the future!</p>
<p><strong>Update:</strong> If you have multiple pieces of data. You can point your Particle integration to a single endpoint. Just make sure the data is in the same group! Here's an example of multiple values sent to the same group:</p>
<pre><code>{
  <span class="hljs-string">"feeds"</span>: [
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"tvoc"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{tvoc}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"c02"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{c02}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"temperature"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{temperature}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"humidity"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{humidity}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"pm2-dot-5"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{pm25}}}"</span>
    },
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"pm10"</span>,
      <span class="hljs-string">"value"</span>: <span class="hljs-string">"{{{pm10}}}"</span>
    }
  ]
}
</code></pre><p>Where your URL should look something like:</p>
<pre><code>https:<span class="hljs-comment">//io.adafruit.com/api/v2/&lt;USERNAME&gt;/groups/&lt;GROUPNAME&gt;/data</span>
</code></pre><p>That should keep your Particle integration page a little more sane!</p>
<h2 id="heading-making-sense-of-the-readings">Making sense of the readings</h2>
<p>The readings can be confusing. Here’s the breakdown of how they work:</p>
<ol>
<li>Humidity is showing in relative percentage points. This is the relative humidity we know and love. Remember it may differ with what’s outside. This depends on if your house is air conditioned or if you’re running a heater etc.</li>
<li>Temperature is in degrees C (can be modified in firmware if you so choose)</li>
<li>TVOC is in ppb (parts per billion). VOCs can be in the form of harmful chemicals you have around the house. More information about VOCs check out this<a target="_blank" href="https://www.epa.gov/indoor-air-quality-iaq/volatile-organic-compounds-impact-indoor-air-quality">link from the EPA</a>.</li>
<li>C02 is in ppm (parts per million). We breathe in oxygen and exhale carbon dioxide. You may find your VOC and C02 levels rising when you’re in the room. C02 does correlate to VOCs as well. <a target="_blank" href="https://ams.com/documents/20143/36005/CCS811_DS000459_7-00.pdf">More info in the data sheet.</a></li>
<li>PM10. Is in µg/m3 (micrograms per meter cubed). The particle sensor uses a scattered laser when then shines across the air chamber to a sensor on the other side. The more the rays are blocked, the more particles in the air. The particle sensor then does some calculations to determine the amount of particles in a certain volume and thus your µg/m3.</li>
<li>PM2.5 is the same as above but it tracks much smaller particles. (Less than or equal to 2.5µm in size!) <a target="_blank" href="https://www.epa.gov/pm-pollution/particulate-matter-pm-basics">More information on the EPA’s website here.</a></li>
</ol>
<h2 id="heading-dont-care-for-something-you-have-no-control-over">Don't care for something you have no control over?</h2>
<p><a target="_blank" href="https://www.jaredwolff.com/how-to-make-an-amazing-looking-iot-dashboard-in-no-time/">Check out my tutorial on creating your own amazing looking IoT dashboard.</a></p>
<h2 id="heading-you-did-it">You did it!</h2>
<p>Congrats. You've made it this far. You deserve a day at the spa. Or maybe some chocolate ice cream. Or if you're really feeling adventurous, both, at the same time?? ?</p>
<p>After building one of these you may feel like your time is worth investing elsewhere. Maybe you want to build a cool web backend with fancier charts and algorithms. Maybe even use some machine learning (why not!)</p>
<p>If you want something already assembled and available you should check out the Particle^2 (Pronounced Particle Squared). It has everything here including the ability to switch on and off the HPM particle sensor. You can even run it on batteries! So put that sucker anywhere you want. <a target="_blank" href="https://www.jaredwolff.com/store/particle-squared/">Check it out here.</a></p>
<p>Here's the full video on the Particle Squared.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/IR2W0GmRKk8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-code-and-source">Code and Source</h2>
<p>This whole project is released under the Creative Commons Share-Alike license. <a target="_blank" href="https://www.jaredwolff.com/files/air-quality/#main">Get the source code and hardware files here.</a></p>
<h2 id="heading-get-ready-for-the-ultimate-guide">Get Ready for the Ultimate Guide</h2>
<p>This post is an excerpt from my upcoming Ultimate Guide on Particle Mesh. Early subscribers get a discount when it becomes available! <a target="_blank" href="https://www.jaredwolff.com/the-ultimate-guide-to-particle-mesh/">Click here to get signed up.</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to get started with IoT using NodeMCU Devkit and Firebase database ]]>
                </title>
                <description>
                    <![CDATA[ By Jibin Thomas “The Internet will disappear. There will be so many IP addresses, so many devices, sensors, things that you are wearing, things that you are interacting with, that you won’t even sense it. It will be part of your presence all the tim... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-get-started-with-iot-using-nodemcu-devkit-and-firebase-database-d43e8a408a88/</link>
                <guid isPermaLink="false">66c35253765a634c3485fe2a</guid>
                
                    <category>
                        <![CDATA[ internet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 24 Apr 2019 16:21:40 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*St_hPlFBBczBVkmPtB0RqQ.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jibin Thomas</p>
<blockquote>
<p><strong><em>“The Internet will disappear. There will be so many IP addresses, so many devices, sensors, things that you are wearing, things that you are interacting with, that you won’t even sense it. It will be part of your presence all the time. Imagine you walk into a room, and the room is dynamic. And with your permission and all of that, you are interacting with the things going on in the room.”</em></strong></p>
</blockquote>
<p>Nowadays many devices that we use day to day are connected to the internet like Television, smart speakers, refrigerators, etc. These devices extend their primary functions which allows them to interact with other devices on the internet and to be controlled remotely.</p>
<p>You can build your own IoT devices using some sensors and microcontrollers. There are many development boards that will help you get started with IoT like Arduino, NodeMCU, Raspberry Pi, etc. You can automate your home by building from these devices.</p>
<p>In this post, we will be using NodeMCU devkit and Firebase for turning on and off LED remotely. NodeMCU devkit and Firebase are the best combinations to get started with building some IoT projects. NodeMCU is cheap and has built-in wifi for internet connectivity, and the Firebase free plan is more than enough.</p>
<h3 id="heading-setting-up-development-environment">Setting up Development Environment</h3>
<ol>
<li><p>We will be using Arduino IDE for writing code and we will flash the code to the device. Download the latest version of the IDE <a target="_blank" href="https://www.arduino.cc/en/main/software">here</a>.</p>
</li>
<li><p>Since we are using NodeMCU which is not officially supported by Arduino IDE, we have to add the JSON file of the device. In Arduino IDE add this URL in</p>
</li>
</ol>
<blockquote>
<p>Open File &gt; Preferences &gt; Additional Board Manager URLs</p>
<p><a target="_blank" href="http://arduino.esp8266.com/stable/package_esp8266com_index.json">http://arduino.esp8266.com/stable/package_esp8266com_index.json</a></p>
</blockquote>
<ol start="3">
<li>Select your Board from</li>
</ol>
<blockquote>
<p>Tools &gt; Board &gt; NodeMCU 1.o</p>
</blockquote>
<ol start="4">
<li><p>To use firebase database in NodeMCU you need to download the firebase-arduino library which abstracts the REST API of the firebase. <a target="_blank" href="https://github.com/FirebaseExtended/firebase-arduino.git">Download firebase-arduino here</a>.</p>
</li>
<li><p>Include the downloaded zip file on Arduino IDE.</p>
</li>
</ol>
<blockquote>
<p>Sketch &gt; Include library &gt; Add .zip &gt; Select zip file</p>
</blockquote>
<ol start="6">
<li>You also need to install the ArduinoJson library which can be downloaded from Arduino IDE itself.</li>
</ol>
<p>Note: The library version should not be 6.x.x — use the latest 5.x.x</p>
<blockquote>
<p>Sketch &gt; Include library &gt; Manage Libraries &gt; Search for ArduinoJson by Benoit Blanchon</p>
</blockquote>
<h3 id="heading-setting-up-firebase-database">Setting up Firebase Database</h3>
<ol start="7">
<li><p>Create a new firebase project from the <a target="_blank" href="https://console.firebase.google.com/">console</a> and head towards the database section. Select the firebase real-time database.</p>
</li>
<li><p>Copy the database secret for authentication from Settings Panel &gt; Service accounts.</p>
</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*PQUqPFsKYw4XFWX3cFV-LA.png" alt="Image" width="800" height="479" loading="lazy">
<em>Database secret</em></p>
<ol start="9">
<li>Add a led node to the firebase database. This value will decide whether to turn on or off the LED.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*cpN78XVvwFe6O0AcoCBHiA.png" alt="Image" width="800" height="322" loading="lazy"></p>
<h3 id="heading-configuring-arduino-ide-and-firebase-database-to-work-together">Configuring Arduino IDE and firebase database to work together</h3>
<p>Now that all the setup procedures are done let’s start coding.</p>
<p>You need to create a macro for your database URL and firebase secret which you had copied in Step 8.</p>
<blockquote>
<p>#define FIREBASE_HOST “yourfirebasedatabase.firebaseio.com”</p>
<p>#define FIREBASE_AUTH “<strong>*</strong>”</p>
</blockquote>
<p>For simplicity, we will write a simple code for turning on and off LED remotely</p>
<ol start="10">
<li>The positive of the LED should be connected to the D1 pin and negative pin to the ground pin of NodeMCU.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*lTdcYh-7O5uECpw8MczYow.png" alt="Image" width="666" height="495" loading="lazy"></p>
<ol start="11">
<li>Upload your code from Arduino IDE.</li>
</ol>
<blockquote>
<p>Sketch &gt; Upload</p>
</blockquote>
<ol start="12">
<li>Now try changing the database value to true and false. The led should now start turn on and off. Additionally, you can extend this project by creating a web app that will toggle the LED instead of manually changing the value in the database.</li>
</ol>
<p>So now that you understand the basics of how to go about connecting NodeMCU to the internet and controlling it remotely, start hacking some new projects with it.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
