<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ashen Chathuranga</title>
    <description>The latest articles on DEV Community by Ashen Chathuranga (@ktauchathuranga).</description>
    <link>https://dev.to/ktauchathuranga</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1042951%2F990ce158-5843-4cff-8157-a8b10404784e.jpg</url>
      <title>DEV Community: Ashen Chathuranga</title>
      <link>https://dev.to/ktauchathuranga</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ktauchathuranga"/>
    <language>en</language>
    <item>
      <title>DevRank LK: Sri Lanka's GitHub Developer Leaderboard is Live – Join and Get Ranked! 🇱🇰</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Fri, 13 Mar 2026 18:37:41 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/devrank-lk-sri-lankas-github-developer-leaderboard-is-live-join-and-get-ranked-1g4o</link>
      <guid>https://dev.to/ktauchathuranga/devrank-lk-sri-lankas-github-developer-leaderboard-is-live-join-and-get-ranked-1g4o</guid>
      <description>&lt;p&gt;Hey Sri Lankan developers! 👋🇱🇰&lt;/p&gt;

&lt;p&gt;Our local tech scene is full of talent, but we rarely see a public ranking that actually celebrates our &lt;strong&gt;open-source contributions&lt;/strong&gt;. Until now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introducing DevRank LK&lt;/strong&gt; — a brand-new, fully automated weekly leaderboard that ranks Sri Lankan GitHub developers based on real activity over the past 12 months.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the Ranking Works
&lt;/h3&gt;

&lt;p&gt;Every Sunday a GitHub Action runs and calculates a score using this transparent formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commits&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PRs&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stars&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;followers&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No magic. Just pure GitHub data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live Leaderboard&lt;/strong&gt; → &lt;a href="https://ktauchathuranga.github.io/devrank-lk/" rel="noopener noreferrer"&gt;https://ktauchathuranga.github.io/devrank-lk/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Current Top 5 (as of today)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;@sameerasw&lt;/strong&gt; – 35,538 🔥
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/ktauchathuranga"&gt;@ktauchathuranga&lt;/a&gt;&lt;/strong&gt; – 5,056
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@Minokainduwara&lt;/strong&gt; – 1,691
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@Dineshs737&lt;/strong&gt; – 1,684
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@Pasindu-Jayasundara&lt;/strong&gt; – 1,618
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(Only &lt;strong&gt;20 developers&lt;/strong&gt; are listed right now — perfect time to get in early and climb the ranks!)&lt;/p&gt;

&lt;h3&gt;
  
  
  Why You Should Opt In Right Now
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Get public recognition for the work you already do
&lt;/li&gt;
&lt;li&gt;Friendly competition with fellow Lankan devs
&lt;/li&gt;
&lt;li&gt;Extra motivation to ship more open-source
&lt;/li&gt;
&lt;li&gt;Help put Sri Lanka on the global developer map
&lt;/li&gt;
&lt;li&gt;It’s completely free and open to any Sri Lankan developer&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to Join (Takes literally 2 minutes)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to the repo: &lt;a href="https://github.com/ktauchathuranga/devrank-lk" rel="noopener noreferrer"&gt;https://github.com/ktauchathuranga/devrank-lk&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Fork&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;data/users.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add your entry at the very end (before the closing &lt;code&gt;]&lt;/code&gt;), like this:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-github-username"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"note"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Optional short note (e.g. 'bl4ke.me' or 'Working at XYZ')"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Don’t forget the comma after the previous entry!
&lt;/li&gt;
&lt;li&gt;Commit → Create Pull Request&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it. Once your PR is merged you’ll appear in the next weekly update.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s Grow This Together
&lt;/h3&gt;

&lt;p&gt;If you’re a Sri Lankan developer (or Sri Lankan origin and active in the community), I strongly encourage you to opt in today. The more of us who join, the more meaningful and competitive this leaderboard becomes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After you join, drop your GitHub username in the comments below&lt;/strong&gt; — I’ll follow you and cheer you on! Tag your SL dev friends too.&lt;/p&gt;

&lt;p&gt;Let’s show the world what Sri Lankan developers can do! 💪&lt;/p&gt;

&lt;h1&gt;
  
  
  SriLanka #developers #opensource #GitHub #DevRankLK #srilankantech #coding #community
&lt;/h1&gt;

</description>
      <category>srilanka</category>
      <category>github</category>
      <category>rank</category>
      <category>leaderboard</category>
    </item>
    <item>
      <title>Reviving Tech: Building OpenPager</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Fri, 27 Feb 2026 23:43:32 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/reviving-tech-building-openpager-4257</link>
      <guid>https://dev.to/ktauchathuranga/reviving-tech-building-openpager-4257</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/mlh-built-with-google-gemini-02-25-26"&gt;Built with Google Gemini: Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built with Google Gemini
&lt;/h2&gt;

&lt;p&gt;Between organizing STEAM workshops and teaching my 4-month beginner Arduino course, I am constantly exploring new ways to push the boundaries of what microcontrollers can achieve. I wanted a project that moved beyond basic sensor reading and dove deep into the complexities of radio frequency communication and real-time processing.&lt;/p&gt;

&lt;p&gt;That drive led to OpenPager: a high-precision POCSAG (pager) transceiver library for Arduino-compatible microcontrollers (ESP8266, ESP32) and the TI CC1101 radio module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Auto-Baud Decoding: Automatically detects and receives 512, 1200, and 2400 baud messages simultaneously using parallel software decoders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;True Non-Blocking RX: A hardware timer ISR samples GDO0 at ~19.2 kHz. The main loop() just drains a ring buffer, ensuring it never busy-waits or bit-bangs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dual Radio Mode: Supports using two CC1101 modules on the same SPI bus, allowing for true simultaneous TX and RX operations without ever dropping a received packet.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Gemini's Role in the Build:&lt;/strong&gt;&lt;br&gt;
Implementing a protocol from the 1980s on modern IoT hardware requires a lot of bitwise gymnastics and register configuration. I leaned heavily on Google Gemini for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Register Configurations: Generating baseline hex values for CC1101 initialization, specifically calculating data rate multipliers for the different baud rates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BCH Error Correction: Translating the mathematical polynomials of POCSAG's BCH(31,21) error-correcting code into efficient, bitwise C++ functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alphanumeric Decoding: Helping write the logic to unpack 7-bit ASCII from 20-bit payload chunks, which requires reversing bits and shifting across arbitrary boundaries.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;You can view the full project, documentation, and source code on GitHub:&lt;br&gt;
&lt;a href="https://github.com/ktauchathuranga/openpager" rel="noopener noreferrer"&gt;https://github.com/ktauchathuranga/openpager&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a quick look at the non-blocking architecture in action. While the hardware timer samples the radio in the background, the main loop remains completely free to run other tasks—like a heartbeat LED, sensor reads, and uptime tracking—without stuttering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Pager processing (non-blocking)&lt;/span&gt;
    &lt;span class="n"&gt;pager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;millis&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;// Task 1: LED heartbeat&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;lastBlink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;ledOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lastBlink&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;HEARTBEAT_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;lastBlink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;ledOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ledOn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HEARTBEAT_LED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ledOn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Task 2: Analog sensor read&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;lastSensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lastSensor&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;SENSOR_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;lastSensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;analogRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SENSOR_PIN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[Sensor] A0 = %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cite&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;This project was a masterclass in hardware timers and interrupt safety.&lt;/p&gt;

&lt;p&gt;When building the non-blocking architecture, I had to ensure the ISR executed in sub-microseconds. I learned the hard way about what you can and cannot do inside an Interrupt Service Routine. Passing data from the ISR to the main loop using a volatile ring buffer taught me a ton about atomicity and race conditions. For example, on the ESP8266, using Timer1 for the ISR means standard functions like Servo and analogWrite (PWM) are entirely unavailable while receiving.&lt;/p&gt;

&lt;p&gt;Additionally, managing the ESP8266's software watchdog timer was an unexpected lesson. During transmission, clocking out bits blocks the processor. I had to strategically insert yield() calls on the ESP8266 to prevent watchdog resets, while carefully avoiding this on the ESP32 to prevent FreeRTOS from introducing multi-millisecond gaps that corrupt bit timing.&lt;/p&gt;

&lt;p&gt;Looking forward, I want to take this rock-solid asynchronous architecture and apply it to modern IoT projects. I'm currently conceptualizing a Smart Agro-Cloud Observer, and these lessons on keeping the main loop non-blocking while handling strict sensor timing will be invaluable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Gemini Feedback
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What worked well:&lt;/strong&gt;&lt;br&gt;
Gemini is phenomenal at explaining binary and bitwise operations. When staring at a hex dump of a pager transmission, I could paste the raw binary into Gemini, and it would perfectly break down the 32-bit codewords into the Address, Function bits, and BCH parity bits. It made debugging the decoder significantly less painful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where I ran into friction:&lt;/strong&gt;&lt;br&gt;
Where Gemini struggled was with the highly specific, hardware-dependent quirks of the ESP32 and ESP8266 SDKs.&lt;br&gt;
For instance, when setting up the SPI bus on the ESP32, Gemini suggested a standard SPI.begin(). However, the ESP32's default SPI implementation claims GPIO 5 as the SS pin. If you're using GPIO 5 for the CC1101's GDO0 interrupt pin (like I was), this creates bus contention. I had to manually debug this and pass -1 for the SS pin to prevent the conflict. AI is incredible for logic and algorithms, but it doesn't always have the "street smarts" of undocumented hardware quirks.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>geminireflections</category>
      <category>gemini</category>
      <category>arduino</category>
    </item>
    <item>
      <title>Introducing OpenPager: A POCSAG Transceiver Library for Arduino</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Sat, 07 Feb 2026 14:55:29 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/introducing-openpager-a-pocsag-transmitter-library-for-arduino-1lh1</link>
      <guid>https://dev.to/ktauchathuranga/introducing-openpager-a-pocsag-transmitter-library-for-arduino-1lh1</guid>
      <description>&lt;p&gt;I recently released &lt;strong&gt;OpenPager&lt;/strong&gt;, a library for Arduino-compatible microcontrollers that handles POCSAG (pager protocol) communication.&lt;/p&gt;

&lt;p&gt;It is designed specifically for the &lt;strong&gt;TI CC1101&lt;/strong&gt; radio transceiver paired with &lt;strong&gt;ESP8266&lt;/strong&gt; or &lt;strong&gt;ESP32&lt;/strong&gt; boards. While there are other radio libraries out there, OpenPager focuses specifically on robust POCSAG implementation with features like parallel auto-baud detection and software-based signal synchronization.&lt;/p&gt;

&lt;p&gt;It is available now in both the Arduino Library Registry and the PlatformIO Registry.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Hardware
&lt;/h3&gt;

&lt;p&gt;To use this, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCU:&lt;/strong&gt; ESP8266, ESP32, or similar Arduino-compatible board.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Radio:&lt;/strong&gt; TI CC1101 module (SPI interface).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The library is optimized for the ESP architecture, leveraging its speed for the software PLL required for accurate decoding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dual Mode:&lt;/strong&gt; Supports both transmitting and receiving (half-duplex).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-Baud Detection:&lt;/strong&gt; The receiver runs parallel decoders to detect and receive 512, 1200, and 2400 baud messages simultaneously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol Support:&lt;/strong&gt; Handles Alphanumeric (ASCII), Numeric (BCD), and Tone-only messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Correction:&lt;/strong&gt; Implements BCH error detection (SECDED).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signal Handling:&lt;/strong&gt; Automatic polarity detection for inverted signals and RSSI monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;PlatformIO&lt;/strong&gt;&lt;br&gt;
Add this to your &lt;code&gt;platformio.ini&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;lib_deps&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="err"&gt;ktauchathuranga/openpager&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Arduino IDE&lt;/strong&gt;&lt;br&gt;
Search for "OpenPager" in the Library Manager.&lt;/p&gt;
&lt;h3&gt;
  
  
  Usage: Receiving Messages
&lt;/h3&gt;

&lt;p&gt;The most complex part of pager protocols is usually handling different baud rates. OpenPager handles this by spawning three independent decoders internally. You just set it to "0" to enable auto-scanning for all rates.&lt;/p&gt;

&lt;p&gt;Here is a callback-based example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;OpenPager.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Initialize with CSN pin (15) and GDO0 pin (5)&lt;/span&gt;
&lt;span class="n"&gt;OpenPager&lt;/span&gt; &lt;span class="nf"&gt;pager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OpenPagerMessage&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[RIC: %lu] [Baud: %d] %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baudRate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;115200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize radio at 433.920 MHz&lt;/span&gt;
    &lt;span class="c1"&gt;// 0 = Auto-Baud mode (scans 512, 1200, 2400 simultaneously)&lt;/span&gt;
    &lt;span class="n"&gt;pager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;433.920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

    &lt;span class="n"&gt;pager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;pager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startReceive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The library handles decoding in the background; &lt;/span&gt;
    &lt;span class="c1"&gt;// messages appear via the callback.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Usage: Transmitting Messages
&lt;/h3&gt;

&lt;p&gt;Transmission is straightforward. You specify the RIC (Receiver ID), function code, message body, and baud rate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;OpenPager.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;OpenPager&lt;/span&gt; &lt;span class="nf"&gt;pager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Initialize at 433.920 MHz with a base rate of 1200&lt;/span&gt;
    &lt;span class="n"&gt;pager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;433.920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Send a message to RIC 1234567&lt;/span&gt;
    &lt;span class="c1"&gt;// Func: 3, Text: "Hello World", Baud: 1200, IsAlpha: true&lt;/span&gt;
    &lt;span class="n"&gt;pager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1234567&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Under the Hood
&lt;/h3&gt;

&lt;p&gt;The CC1101 operates in asynchronous mode, outputting raw demodulated data on the GDO0 pin. OpenPager processes this stream using a software PLL to maintain bit synchronization.&lt;/p&gt;

&lt;p&gt;The interesting part is the &lt;strong&gt;RX Architecture&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parallel Decoding:&lt;/strong&gt; The library runs three decoder instances (512, 1200, 2400) in parallel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sync Lock:&lt;/strong&gt; All decoders process the signal; when a valid sync word is detected, the appropriate decoder locks onto the stream.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jitter Handling:&lt;/strong&gt; On the ESP32, 2400 baud works reliably. On the ESP8266, interrupt jitter (~3-5µs) makes 2400 baud more challenging, but lower rates work perfectly.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repo:&lt;/strong&gt; &lt;a href="https://github.com/ktauchathuranga/openpager" rel="noopener noreferrer"&gt;https://github.com/ktauchathuranga/openpager&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are working with POCSAG or legacy paging hardware, give it a try and let me know if you run into any issues.&lt;/p&gt;

</description>
      <category>arduino</category>
      <category>esp32</category>
      <category>iot</category>
      <category>rf</category>
    </item>
    <item>
      <title>SSTV Encoder With 10+ Modes</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Sat, 24 Jan 2026 01:56:19 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/sstv-encoder-with-10-modes-66p</link>
      <guid>https://dev.to/ktauchathuranga/sstv-encoder-with-10-modes-66p</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;SSTV Encoder, built it using rust, you can input an image and it will create a .wav file according to your chosen mode. it support,&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;VIS Code&lt;/th&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Color Space&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;martin1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0xAC&lt;/td&gt;
&lt;td&gt;320×256&lt;/td&gt;
&lt;td&gt;114.3s&lt;/td&gt;
&lt;td&gt;RGB (GBR)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;martin2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0x28&lt;/td&gt;
&lt;td&gt;320×256&lt;/td&gt;
&lt;td&gt;58.1s&lt;/td&gt;
&lt;td&gt;RGB (GBR)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scottie1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0x3C&lt;/td&gt;
&lt;td&gt;320×256&lt;/td&gt;
&lt;td&gt;109.6s&lt;/td&gt;
&lt;td&gt;RGB (GBR)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scottie2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0xB8&lt;/td&gt;
&lt;td&gt;320×256&lt;/td&gt;
&lt;td&gt;71.1s&lt;/td&gt;
&lt;td&gt;RGB (GBR)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scottiedx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0xCC&lt;/td&gt;
&lt;td&gt;320×256&lt;/td&gt;
&lt;td&gt;268.9s&lt;/td&gt;
&lt;td&gt;RGB (GBR)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;robot36&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0x88&lt;/td&gt;
&lt;td&gt;320×240&lt;/td&gt;
&lt;td&gt;36.0s&lt;/td&gt;
&lt;td&gt;YUV&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;robot72&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0x0C&lt;/td&gt;
&lt;td&gt;320×240&lt;/td&gt;
&lt;td&gt;72.0s&lt;/td&gt;
&lt;td&gt;YUV&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pd120&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0x5F&lt;/td&gt;
&lt;td&gt;640×496&lt;/td&gt;
&lt;td&gt;126.1s&lt;/td&gt;
&lt;td&gt;YUV&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pd180&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0x60&lt;/td&gt;
&lt;td&gt;640×496&lt;/td&gt;
&lt;td&gt;187.1s&lt;/td&gt;
&lt;td&gt;YUV&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pd290&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0xDE&lt;/td&gt;
&lt;td&gt;800×616&lt;/td&gt;
&lt;td&gt;288.7s&lt;/td&gt;
&lt;td&gt;YUV&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bw8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0x82&lt;/td&gt;
&lt;td&gt;160×120&lt;/td&gt;
&lt;td&gt;8.0s&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bw12&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0x86&lt;/td&gt;
&lt;td&gt;160×120&lt;/td&gt;
&lt;td&gt;12.0s&lt;/td&gt;
&lt;td&gt;Grayscale&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once you generate the .wav files, you can decode them using any standerd SSTV decoder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7osfbwm1r3bpmfmk3dp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7osfbwm1r3bpmfmk3dp.png" alt="QSSTV Demo" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot CLI
&lt;/h2&gt;

&lt;p&gt;When it takes months to build a tool like this, With GitHub Copilot under my supervision built it in few days. this helps me to explore more areas otherwise i will miss. experience is actually good, everything in CLI making things convenient. and i like the way it asks clarifying questions before proceeding and giving me recommended  options to run kinda cool.&lt;/p&gt;

&lt;p&gt;Project link - &lt;a href="https://github.com/ktauchathuranga/sstv" rel="noopener noreferrer"&gt;https://github.com/ktauchathuranga/sstv&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>Complete ADS-B Decoder in Rust: Track Aircraft in Real-Time with RTL-SDR</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Mon, 19 Jan 2026 09:37:25 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/complete-ads-b-decoder-in-rust-track-aircraft-in-real-time-with-rtl-sdr-330k</link>
      <guid>https://dev.to/ktauchathuranga/complete-ads-b-decoder-in-rust-track-aircraft-in-real-time-with-rtl-sdr-330k</guid>
      <description>&lt;p&gt;Have you ever wondered how websites like FlightRadar24 track thousands of aircraft in real-time? The answer lies in &lt;strong&gt;ADS-B&lt;/strong&gt; (Automatic Dependent Surveillance-Broadcast) - a technology where aircraft continuously broadcast their position, altitude, speed, and identification. Best part? You can receive these signals yourself with a $20 USB dongle!&lt;/p&gt;

&lt;p&gt;I've built a complete ADS-B decoder in Rust that rivals the popular &lt;code&gt;dump1090&lt;/code&gt;, adding several improvements and comprehensive protocol documentation. Let me show you what makes this project special.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can You Track?
&lt;/h2&gt;

&lt;p&gt;With just an RTL-SDR dongle and a simple antenna, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Track aircraft up to 250+ nautical miles away&lt;/li&gt;
&lt;li&gt;See their callsigns (flight numbers)&lt;/li&gt;
&lt;li&gt;Monitor altitude, speed, and heading in real-time&lt;/li&gt;
&lt;li&gt;Calculate distance and bearing from your location&lt;/li&gt;
&lt;li&gt;Detect emergency squawk codes (7500/7600/7700)&lt;/li&gt;
&lt;li&gt;Access additional data like IAS, Mach number, and vertical rate from BDS registers
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hex     Flight   Alt    Speed  Lat      Lon       Msgs  Seen  Distance  Bearing
89645A  UAE80T   35000  465kt  5.8912   79.4521   142   0s    245.2km   312°
4D2023  AMC421   22000  385kt  37.074   13.799    87    1s    187.8km   158°
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Complete Mode S Decoding
&lt;/h3&gt;

&lt;p&gt;This isn't a minimal proof-of-concept - it's a full-featured decoder supporting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;All major Downlink Formats&lt;/strong&gt;: DF0, DF4, DF5, DF11, DF16, DF17, DF20, DF21&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPR Position Decoding&lt;/strong&gt;: Both global and local Compact Position Reporting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Correction&lt;/strong&gt;: Single-bit and optional two-bit error correction via CRC syndrome&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BDS Register Decoding&lt;/strong&gt;: Extract Comm-B data from DF20/DF21 messages&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Smart Aircraft Filtering
&lt;/h3&gt;

&lt;p&gt;Real-world RF environments are noisy. The decoder includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ghost aircraft filtering&lt;/strong&gt; with configurable message thresholds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent ICAO tracking&lt;/strong&gt; with TTL-based cleanup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ICAO address validation&lt;/strong&gt; and recovery from CRC&lt;/li&gt;
&lt;li&gt;Smart handling of position data across zone boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Emergency Detection
&lt;/h3&gt;

&lt;p&gt;Automatically highlights emergency situations with color-coded alerts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;7500&lt;/strong&gt; - Hijacking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7600&lt;/strong&gt; - Radio Failure
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7700&lt;/strong&gt; - General Emergency&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Multiple Output Formats
&lt;/h3&gt;

&lt;p&gt;Stream decoded data in various formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Raw TCP&lt;/strong&gt; (port 30002) - hex messages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SBS/BaseStation&lt;/strong&gt; (port 30003) - compatible with Virtual Radar Server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON API&lt;/strong&gt; (port 8080) - for web applications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive terminal&lt;/strong&gt; - with real-time updates&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Hardware You'll Need
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RTL-SDR dongle&lt;/strong&gt; ($20-30) or &lt;strong&gt;HackRF One&lt;/strong&gt; ($300+)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Antenna&lt;/strong&gt; - a simple 1090 MHz dipole works great (6.9cm elements)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Computer&lt;/strong&gt; - even a Raspberry Pi works!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install RTL-SDR libraries&lt;/span&gt;
&lt;span class="c"&gt;# Fedora/RHEL&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;rtl-sdr rtl-sdr-devel

&lt;span class="c"&gt;# Ubuntu/Debian  &lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;rtl-sdr librtlsdr-dev

&lt;span class="c"&gt;# Clone and build&lt;/span&gt;
git clone https://github.com/ktauchathuranga/adsb.git
&lt;span class="nb"&gt;cd &lt;/span&gt;adsb
cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running It
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Basic usage with RTL-SDR&lt;/span&gt;
./target/release/adsb &lt;span class="nt"&gt;--interactive&lt;/span&gt;

&lt;span class="c"&gt;# With HackRF One&lt;/span&gt;
./target/release/adsb &lt;span class="nt"&gt;--hackrf&lt;/span&gt; &lt;span class="nt"&gt;--interactive&lt;/span&gt;

&lt;span class="c"&gt;# Add your location for distance/bearing calculations&lt;/span&gt;
./target/release/adsb &lt;span class="nt"&gt;--interactive&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--lat&lt;/span&gt; 6.9271 &lt;span class="nt"&gt;--lon&lt;/span&gt; 79.8612

&lt;span class="c"&gt;# Enable networking for web access&lt;/span&gt;
./target/release/adsb &lt;span class="nt"&gt;--net&lt;/span&gt; &lt;span class="nt"&gt;--interactive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open &lt;code&gt;http://localhost:8080&lt;/code&gt; to see aircraft on a map!&lt;/p&gt;

&lt;h2&gt;
  
  
  How ADS-B Works
&lt;/h2&gt;

&lt;p&gt;One thing that sets this project apart is its &lt;strong&gt;comprehensive protocol documentation&lt;/strong&gt;. The README includes a complete deep-dive into:&lt;/p&gt;

&lt;h3&gt;
  
  
  Signal Characteristics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frequency&lt;/strong&gt;: 1090 MHz&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modulation&lt;/strong&gt;: PPM (Pulse Position Modulation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Rate&lt;/strong&gt;: 1 Mbit/s&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Types&lt;/strong&gt;: 56-bit (short) and 112-bit (long)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every message starts with a distinctive preamble:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Preamble (8 µs):
 ▲
1│    █   █         █   █
 │    █   █         █   █
0└──────────────────────────────────►
      0   1   2   3   4   5   6   7 µs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Position Encoding Magic
&lt;/h3&gt;

&lt;p&gt;Aircraft positions are encoded using &lt;strong&gt;CPR&lt;/strong&gt; (Compact Position Reporting) - an ingenious algorithm that represents global coordinates in just 17 bits each for latitude and longitude (vs. ~55 bits normally).&lt;/p&gt;

&lt;p&gt;The README includes the complete CPR decoding algorithm with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zone calculations&lt;/li&gt;
&lt;li&gt;Latitude/longitude recovery
&lt;/li&gt;
&lt;li&gt;NL (Number of Longitude zones) lookup tables&lt;/li&gt;
&lt;li&gt;Even/odd frame pairing logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Message Structure
&lt;/h3&gt;

&lt;p&gt;Detailed breakdowns of every message type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DF11&lt;/strong&gt;: All-Call Reply (ICAO address announcement)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DF17&lt;/strong&gt;: Extended Squitter (ADS-B position/velocity/ID)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DF4/DF5&lt;/strong&gt;: Altitude and Identity Replies
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DF20/DF21&lt;/strong&gt;: Comm-B messages with BDS data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CRC &amp;amp; Error Correction
&lt;/h3&gt;

&lt;p&gt;The decoder implements proper CRC-24 checking with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single-bit error correction (default)&lt;/li&gt;
&lt;li&gt;Two-bit error correction (aggressive mode)&lt;/li&gt;
&lt;li&gt;ICAO address recovery from XORed parity fields&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;The codebase is clean and modular:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   RTL-SDR   │────►│ Demodulator │────►│   Decoder   │────►│  Aircraft   │
│   Input     │     │             │     │             │     │   Tracker   │
│             │     │ • Preamble  │     │ • CRC Check │     │             │
│ • 2 MHz IQ  │     │ • PPM Decode│     │ • DF Parse  │     │ • Position  │
│ • 8-bit     │     │ • Magnitude │     │ • CPR Decode│     │ • History   │
└─────────────┘     └─────────────┘     └─────────────┘     └─────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;demodulator.rs&lt;/code&gt; - Preamble detection and PPM decoding&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;decoder.rs&lt;/code&gt; - Message parsing and field extraction
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;crc.rs&lt;/code&gt; - Error detection and correction&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aircraft.rs&lt;/code&gt; - Position tracking and CPR decoding&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;network.rs&lt;/code&gt; - TCP/HTTP servers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Educational Value
&lt;/h2&gt;

&lt;p&gt;While this is a production-ready tool, it's also an excellent learning resource:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Protocol Documentation&lt;/strong&gt;: 60KB+ of detailed explanations, diagrams, and examples&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Rust Code&lt;/strong&gt;: Idiomatic async Rust with tokio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-World DSP&lt;/strong&gt;: Signal processing, demodulation, error correction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Programming&lt;/strong&gt;: Concurrent TCP servers and HTTP APIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aviation Technology&lt;/strong&gt;: Deep dive into Mode S/ADS-B standards&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The README includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ASCII art diagrams of signal structures&lt;/li&gt;
&lt;li&gt;Bit-level message breakdowns&lt;/li&gt;
&lt;li&gt;Decoding algorithms with pseudocode&lt;/li&gt;
&lt;li&gt;Lookup tables and encoding schemes&lt;/li&gt;
&lt;li&gt;Examples with real messages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Future Enhancements
&lt;/h2&gt;

&lt;p&gt;Some ideas I'm exploring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mode A/C decoding (older transponders)&lt;/li&gt;
&lt;li&gt;MLAT (Multilateration) support&lt;/li&gt;
&lt;li&gt;Database integration for aircraft info&lt;/li&gt;
&lt;li&gt;Advanced filtering and alerting&lt;/li&gt;
&lt;li&gt;Performance optimizations for embedded systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;The project is open source and welcomes contributions! Whether it's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bug fixes&lt;/li&gt;
&lt;li&gt;Performance improvements
&lt;/li&gt;
&lt;li&gt;Additional message types&lt;/li&gt;
&lt;li&gt;Documentation enhancements&lt;/li&gt;
&lt;li&gt;Testing on new hardware&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the repo: &lt;a href="https://github.com/ktauchathuranga/adsb-rx" rel="noopener noreferrer"&gt;github.com/ktauchathuranga/adsb-rx&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;The implementation follows official specifications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ICAO Annex 10 (Aeronautical Telecommunications)&lt;/li&gt;
&lt;li&gt;DO-260B (MOPS for 1090 MHz ADS-B)&lt;/li&gt;
&lt;li&gt;Mode S specifications&lt;/li&gt;
&lt;li&gt;Various research papers on CPR decoding&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building this decoder taught me so much about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Radio protocols and signal processing&lt;/li&gt;
&lt;li&gt;The elegance of well-designed encoding schemes (CPR is brilliant!)&lt;/li&gt;
&lt;li&gt;Real-time systems and performance optimization&lt;/li&gt;
&lt;li&gt;The fascinating world of aviation technology&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're interested in SDR, aviation, or just want to see what's flying overhead, give it a try! The hardware is cheap, the software is free, and watching aircraft appear on your screen in real-time is genuinely exciting.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Have questions?&lt;/strong&gt; Drop them in the comments! I'd love to hear about your ADS-B setups or help troubleshoot any issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Like this?&lt;/strong&gt; Consider giving the repo a star on GitHub!&lt;/p&gt;

&lt;h1&gt;
  
  
  rust #sdr #aviation #opensource #flightracking
&lt;/h1&gt;

</description>
      <category>sdr</category>
      <category>raspberrypi</category>
      <category>dump1090</category>
    </item>
    <item>
      <title>Generate cloud-init files for Raspberry Pi OS without re-downloading images</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Wed, 24 Dec 2025 10:40:05 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/generate-cloud-init-files-for-raspberry-pi-os-without-re-downloading-images-51go</link>
      <guid>https://dev.to/ktauchathuranga/generate-cloud-init-files-for-raspberry-pi-os-without-re-downloading-images-51go</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Raspberry Pi recently introduced &lt;strong&gt;cloud-init&lt;/strong&gt; support in their official Raspberry Pi OS images. This is a big step forward because cloud-init allows users to preconfigure devices before first boot, including Wi-Fi credentials, users, SSH access, locale, and more.&lt;/p&gt;

&lt;p&gt;However, there is a practical problem with the current workflow provided by the official Raspberry Pi Imager. Advanced customization options are only available when you select &lt;strong&gt;Raspberry Pi OS&lt;/strong&gt; from the official OS list inside the imager. If you instead flash a locally downloaded image using the &lt;strong&gt;Custom Image&lt;/strong&gt; option, those configuration options disappear.&lt;/p&gt;

&lt;p&gt;For users with limited bandwidth, slow connections, or frequent cache cleanups, this becomes frustrating very quickly.&lt;/p&gt;

&lt;p&gt;This article explains the problem in detail and presents a simple, bandwidth-friendly solution using a cloud-init file generator.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem with Raspberry Pi Imager customization
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Customization only works with official OS downloads
&lt;/h3&gt;

&lt;p&gt;Raspberry Pi Imager allows you to configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wi-Fi (SSID, password, country)&lt;/li&gt;
&lt;li&gt;Username and password&lt;/li&gt;
&lt;li&gt;SSH access&lt;/li&gt;
&lt;li&gt;Locale, timezone, and keyboard layout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But these options are &lt;strong&gt;only enabled&lt;/strong&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You choose Raspberry Pi OS directly from the imager&lt;/li&gt;
&lt;li&gt;The image is downloaded by the imager itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the Raspberry Pi OS image manually&lt;/li&gt;
&lt;li&gt;Use the &lt;strong&gt;Custom Image&lt;/strong&gt; option to flash it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then all customization options are disabled.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Re-downloading wastes bandwidth
&lt;/h3&gt;

&lt;p&gt;This creates several issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Raspberry Pi OS images are large&lt;/li&gt;
&lt;li&gt;Clearing cache forces a full re-download&lt;/li&gt;
&lt;li&gt;Re-downloading the same image multiple times wastes data&lt;/li&gt;
&lt;li&gt;This is especially painful in regions with limited or expensive internet access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many users already have the image they want, but still need a way to configure Wi-Fi and users before first boot.&lt;/p&gt;




&lt;h2&gt;
  
  
  How cloud-init works on Raspberry Pi OS
&lt;/h2&gt;

&lt;p&gt;Recent Raspberry Pi OS images support &lt;strong&gt;cloud-init&lt;/strong&gt; by reading configuration files from the &lt;strong&gt;boot partition&lt;/strong&gt; during the first boot.&lt;/p&gt;

&lt;p&gt;The key files are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;meta-data&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;network-config&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;user-data&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If these files exist in the boot partition, Raspberry Pi OS will automatically apply the configuration on first boot.&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No need for Raspberry Pi Imager customization&lt;/li&gt;
&lt;li&gt;No need to re-download the OS image&lt;/li&gt;
&lt;li&gt;Works with any flashing tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You only need valid cloud-init files.&lt;/p&gt;




&lt;h2&gt;
  
  
  The solution: Raspberry Pi cloud-init generator
&lt;/h2&gt;

&lt;p&gt;To solve this problem, I created a simple web-based tool that generates cloud-init files for Raspberry Pi OS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project overview
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub repository&lt;/strong&gt;: &lt;a href="https://github.com/ktauchathuranga/rpi-cloud-init-generator" rel="noopener noreferrer"&gt;https://github.com/ktauchathuranga/rpi-cloud-init-generator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosted website&lt;/strong&gt;: &lt;a href="https://rpi-cloud-init-generator.onrender.com/" rel="noopener noreferrer"&gt;https://rpi-cloud-init-generator.onrender.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tool allows you to generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;meta-data&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;network-config&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;user-data&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ready to be copied directly to the Raspberry Pi boot partition.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the workflow looks now
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Old workflow (problematic)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open Raspberry Pi Imager&lt;/li&gt;
&lt;li&gt;Select Raspberry Pi OS from official list&lt;/li&gt;
&lt;li&gt;Download the image again&lt;/li&gt;
&lt;li&gt;Add customization&lt;/li&gt;
&lt;li&gt;Flash SD card&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeated downloads&lt;/li&gt;
&lt;li&gt;High data usage&lt;/li&gt;
&lt;li&gt;Custom image option unusable&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  New workflow (efficient)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download Raspberry Pi OS image once&lt;/li&gt;
&lt;li&gt;Flash it using &lt;strong&gt;Custom Image&lt;/strong&gt; in Raspberry Pi Imager or any other tool&lt;/li&gt;
&lt;li&gt;Open the cloud-init generator website&lt;/li&gt;
&lt;li&gt;Fill in Wi-Fi, user, and SSH details&lt;/li&gt;
&lt;li&gt;Generate &lt;code&gt;meta-data&lt;/code&gt;, &lt;code&gt;network-config&lt;/code&gt;, and &lt;code&gt;user-data&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy these files to the &lt;strong&gt;boot partition&lt;/strong&gt; of the SD card&lt;/li&gt;
&lt;li&gt;Boot the Raspberry Pi&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No re-downloads&lt;/li&gt;
&lt;li&gt;Full cloud-init customization&lt;/li&gt;
&lt;li&gt;Works offline after image download&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key benefits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Saves bandwidth&lt;/li&gt;
&lt;li&gt;Avoids unnecessary re-downloads&lt;/li&gt;
&lt;li&gt;Works with cached or archived images&lt;/li&gt;
&lt;li&gt;Uses official Raspberry Pi OS cloud-init support&lt;/li&gt;
&lt;li&gt;Simple and beginner-friendly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach is especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers flashing multiple Raspberry Pi boards&lt;/li&gt;
&lt;li&gt;Users with limited internet access&lt;/li&gt;
&lt;li&gt;Automated or repeatable Raspberry Pi setups&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Raspberry Pi OS cloud-init support is powerful, but the current Raspberry Pi Imager workflow unnecessarily forces users to re-download images to access basic customization features.&lt;/p&gt;

&lt;p&gt;By generating cloud-init files manually and placing them in the boot partition, you can fully configure Raspberry Pi OS without relying on the imager’s official OS download flow.&lt;/p&gt;

&lt;p&gt;The Raspberry Pi cloud-init generator makes this process simple, accessible, and bandwidth-efficient.&lt;/p&gt;

&lt;p&gt;If you regularly work with Raspberry Pi boards, this approach can save both time and data while giving you full control over your system configuration.&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>cloudinit</category>
      <category>fix</category>
      <category>programming</category>
    </item>
    <item>
      <title>Making Raspberry Pi Imager from AUR Work on Hyprland + Wofi</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Wed, 17 Dec 2025 10:02:17 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/making-raspberry-pi-imager-from-aur-work-on-hyprland-wofi-o1i</link>
      <guid>https://dev.to/ktauchathuranga/making-raspberry-pi-imager-from-aur-work-on-hyprland-wofi-o1i</guid>
      <description>&lt;p&gt;Raspberry Pi Imager is the official tool for writing Raspberry Pi OS images (and other images) to SD cards or USB drives. While it works smoothly on traditional desktop environments, running it on &lt;strong&gt;Hyprland&lt;/strong&gt; — a Wayland compositor — can be tricky, especially if installed via the &lt;strong&gt;AUR&lt;/strong&gt;. Here’s a deep dive into the issue and how to fix it.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;On Arch Linux, you have two main ways to install Raspberry Pi Imager:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pacman (official repo)&lt;/strong&gt;: &lt;code&gt;sudo pacman -S rpi-imager&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AUR (latest version)&lt;/strong&gt;: &lt;code&gt;yay -S rpi-imager-latest&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When using the &lt;strong&gt;AUR version&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launching the app from &lt;strong&gt;wofi&lt;/strong&gt; shows no response — the GUI doesn’t open.&lt;/li&gt;
&lt;li&gt;Running from terminal works only with &lt;code&gt;sudo -E rpi-imager&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meanwhile, the &lt;strong&gt;Pacman version&lt;/strong&gt; works normally from the menu.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Happens&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Root Privileges Needed&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Raspberry Pi Imager requires access to devices (SD cards/USB drives), which normal users cannot access.&lt;/li&gt;
&lt;li&gt;Therefore, it must run as root, usually via &lt;code&gt;pkexec&lt;/code&gt; or &lt;code&gt;sudo&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Wayland Environment&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;On Hyprland (Wayland), &lt;code&gt;pkexec&lt;/code&gt; often fails silently if the environment variables (&lt;code&gt;DISPLAY&lt;/code&gt;, &lt;code&gt;WAYLAND_DISPLAY&lt;/code&gt;, &lt;code&gt;XAUTHORITY&lt;/code&gt;) aren’t set properly.&lt;/li&gt;
&lt;li&gt;The desktop file provided by the AUR package typically uses:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;   &lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;pkexec --disable-internal-agent /usr/bin/rpi-imager %u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;On Wayland, this does not carry over the environment, so the GUI never appears.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Desktop File Difference&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The Pacman version (&lt;code&gt;/usr/share/applications/org.raspberrypi.rpi-imager.desktop&lt;/code&gt;) works because its environment and paths are standard.&lt;/li&gt;
&lt;li&gt;The AUR version may install to a slightly different path or not account for Wayland, causing the menu launcher to fail.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Solution&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The fix involves creating a &lt;strong&gt;wrapper script&lt;/strong&gt; that preserves the Wayland environment and modifying the desktop file to use it.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Create a Wayland-safe Wrapper&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Create a new script at &lt;code&gt;/usr/local/bin/rpi-imager-launch&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /usr/local/bin/rpi-imager-launch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Wayland-safe wrapper for Raspberry Pi Imager&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DISPLAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DISPLAY&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;WAYLAND_DISPLAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$WAYLAND_DISPLAY&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;XAUTHORITY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$XAUTHORITY&lt;/span&gt;

&lt;span class="c"&gt;# Launch Raspberry Pi Imager with pkexec&lt;/span&gt;
pkexec &lt;span class="nb"&gt;env &lt;/span&gt;&lt;span class="nv"&gt;DISPLAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DISPLAY&lt;/span&gt; &lt;span class="nv"&gt;WAYLAND_DISPLAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$WAYLAND_DISPLAY&lt;/span&gt; &lt;span class="nv"&gt;XAUTHORITY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$XAUTHORITY&lt;/span&gt; /usr/bin/rpi-imager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/rpi-imager-launch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Modify the Desktop File&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Edit the AUR-installed desktop file (likely &lt;code&gt;/usr/share/applications/com.raspberrypi.rpi-imager.desktop&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /usr/share/applications/com.raspberrypi.rpi-imager.desktop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the &lt;code&gt;Exec&lt;/code&gt; line to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/rpi-imager-launch %u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that when you click the app in &lt;strong&gt;wofi&lt;/strong&gt;, the wrapper script runs, preserving the environment variables necessary for Wayland.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Refresh the Menu&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If necessary, refresh your desktop database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;update-desktop-database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, launching Raspberry Pi Imager from &lt;strong&gt;wofi&lt;/strong&gt; works as expected — it will prompt for your password via GUI and open the application.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why This Works&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The wrapper ensures &lt;code&gt;DISPLAY&lt;/code&gt;, &lt;code&gt;WAYLAND_DISPLAY&lt;/code&gt;, and &lt;code&gt;XAUTHORITY&lt;/code&gt; are correctly passed to &lt;code&gt;pkexec&lt;/code&gt;, which is required on Wayland.&lt;/li&gt;
&lt;li&gt;Modifying the desktop file allows the menu launcher to call the wrapper instead of the original binary directly.&lt;/li&gt;
&lt;li&gt;This approach works for &lt;strong&gt;any root-required GUI application&lt;/strong&gt; on Wayland that fails to launch from a menu.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Optional Enhancements&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Passwordless Launch&lt;/strong&gt;: You can configure &lt;code&gt;sudoers&lt;/code&gt; to allow your user to run &lt;code&gt;/usr/bin/rpi-imager&lt;/code&gt; without a password. This makes one-click launching possible but slightly reduces security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Icon Customization&lt;/strong&gt;: If the AUR version lacks an icon, you can download a PNG and set &lt;code&gt;Icon=/path/to/icon.png&lt;/code&gt; in the desktop file.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Running AUR-installed Raspberry Pi Imager on Hyprland can fail silently due to Wayland environment issues with &lt;code&gt;pkexec&lt;/code&gt;. The solution is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a wrapper script that preserves environment variables.&lt;/li&gt;
&lt;li&gt;Edit the desktop file to point to the wrapper.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This ensures &lt;strong&gt;wofi&lt;/strong&gt; or any other menu launcher can start the app reliably, bridging the gap between Arch’s flexibility, Wayland, and applications requiring root access.&lt;/p&gt;

</description>
      <category>rpiimager</category>
      <category>archlinux</category>
    </item>
    <item>
      <title>Why Square Waves Create Many Frequencies</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Sat, 13 Dec 2025 16:58:45 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/why-square-waves-create-many-frequencies-2ekg</link>
      <guid>https://dev.to/ktauchathuranga/why-square-waves-create-many-frequencies-2ekg</guid>
      <description>&lt;h2&gt;
  
  
  Understanding Digital Noise Using the Water Wave Analogy
&lt;/h2&gt;




&lt;h2&gt;
  
  
  1. The Core Confusion
&lt;/h2&gt;

&lt;p&gt;A very common question in electronics is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“If a square wave has one frequency, how does it create many other frequencies?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first glance, this feels contradictory. But the confusion comes from mixing up &lt;strong&gt;repetition rate&lt;/strong&gt; with &lt;strong&gt;frequency content&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To make this intuitive, we’ll start with a &lt;strong&gt;water wave analogy&lt;/strong&gt;, then slowly connect it to the real technical explanation.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Water Wave Analogy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Calm Water
&lt;/h3&gt;

&lt;p&gt;Imagine a perfectly calm lake. The surface is flat. Nothing is moving.&lt;/p&gt;

&lt;p&gt;This is like &lt;strong&gt;DC voltage&lt;/strong&gt; — no frequency at all.&lt;/p&gt;




&lt;h3&gt;
  
  
  Smooth Hand Motion → Single Frequency
&lt;/h3&gt;

&lt;p&gt;Now gently move your hand &lt;strong&gt;up and down smoothly&lt;/strong&gt; in the water.&lt;/p&gt;

&lt;p&gt;What happens?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean, smooth waves&lt;/li&gt;
&lt;li&gt;One dominant wave size&lt;/li&gt;
&lt;li&gt;Predictable motion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is like a &lt;strong&gt;sine wave&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smooth voltage change&lt;/li&gt;
&lt;li&gt;One frequency&lt;/li&gt;
&lt;li&gt;Very little interference&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Sudden Slap → Many Frequencies
&lt;/h3&gt;

&lt;p&gt;Now instead of moving smoothly, &lt;strong&gt;slap the water once&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What do you see?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large slow waves&lt;/li&gt;
&lt;li&gt;Medium-sized ripples&lt;/li&gt;
&lt;li&gt;Tiny fast ripples&lt;/li&gt;
&lt;li&gt;Splashing in many directions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One single action created &lt;strong&gt;many wave sizes at the same time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the key idea.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Sudden changes create many waves&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Repeated Slaps → Square Wave
&lt;/h3&gt;

&lt;p&gt;A square wave is like &lt;strong&gt;slapping the water repeatedly at a fixed rate&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SLAP   SLAP   SLAP   SLAP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if the slaps happen at a steady rhythm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Each slap still creates&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;slow waves&lt;/li&gt;
&lt;li&gt;fast ripples&lt;/li&gt;
&lt;li&gt;very fast ripples&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;So although the &lt;em&gt;rate&lt;/em&gt; is fixed, the &lt;em&gt;wave content&lt;/em&gt; is broad.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Translating the Analogy to Electronics
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Repetition Rate vs Frequency Content
&lt;/h3&gt;

&lt;p&gt;When we say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"This is a 1 MHz square wave"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are only talking about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;How often the wave repeats&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not what frequencies it contains.&lt;/p&gt;




&lt;h3&gt;
  
  
  Sharp Edges = Fast Change
&lt;/h3&gt;

&lt;p&gt;A square wave looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_|‾|_|‾|_|‾|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;strong&gt;instant vertical edges&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In physics:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Faster voltage change → higher frequencies&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An instant edge means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infinite speed (theoretical)&lt;/li&gt;
&lt;li&gt;Infinite frequency components (theoretical)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In reality, edges are limited — but still very fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The Technical Explanation (Fourier Concept)
&lt;/h2&gt;

&lt;p&gt;Any repeating signal can be broken into sine waves.&lt;/p&gt;

&lt;p&gt;A square wave is equivalent to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fundamental frequency (f)&lt;/li&gt;
&lt;li&gt;3×f&lt;/li&gt;
&lt;li&gt;5×f&lt;/li&gt;
&lt;li&gt;7×f&lt;/li&gt;
&lt;li&gt;9×f&lt;/li&gt;
&lt;li&gt;… continuing upward&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;100 kHz square wave&lt;/strong&gt; contains energy at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100 kHz&lt;/li&gt;
&lt;li&gt;300 kHz&lt;/li&gt;
&lt;li&gt;500 kHz&lt;/li&gt;
&lt;li&gt;700 kHz&lt;/li&gt;
&lt;li&gt;900 kHz&lt;/li&gt;
&lt;li&gt;into the MHz range&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are called &lt;strong&gt;harmonics&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Why Digital Devices Create Radio Noise
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Raspberry Pi / Arduino Example
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GPIO pins switch very fast&lt;/li&gt;
&lt;li&gt;Output square waves&lt;/li&gt;
&lt;li&gt;No built-in RF filtering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The connecting wires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;act like antennas&lt;/li&gt;
&lt;li&gt;radiate the harmonics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is exactly like water ripples spreading outward.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why AM Radios Are Affected
&lt;/h3&gt;

&lt;p&gt;AM radios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detect amplitude changes&lt;/li&gt;
&lt;li&gt;are sensitive to wideband noise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Square-wave harmonics fall directly into AM bands, causing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;buzzing&lt;/li&gt;
&lt;li&gt;whining&lt;/li&gt;
&lt;li&gt;clicking sounds&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Why Sine Waves Are Clean
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal Type&lt;/th&gt;
&lt;th&gt;Edge Speed&lt;/th&gt;
&lt;th&gt;Harmonics&lt;/th&gt;
&lt;th&gt;RF Noise&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sine wave&lt;/td&gt;
&lt;td&gt;Smooth&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Very low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Triangle wave&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Some&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Square wave&lt;/td&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;Many&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  7. How Engineers “Calm the Water”
&lt;/h2&gt;

&lt;p&gt;To reduce noise, engineers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;slow down edges&lt;/li&gt;
&lt;li&gt;add RC filters&lt;/li&gt;
&lt;li&gt;add capacitors near power pins&lt;/li&gt;
&lt;li&gt;use ferrite beads&lt;/li&gt;
&lt;li&gt;use shielding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In water terms:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Filters turn slaps into smooth hand movements&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  8. One-Sentence Summary
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A square wave has one repetition rate, but its sharp edges force nature to include many frequencies — just like a water slap creates many ripples.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  9. Memory Trick
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Smooth motion → clean wave&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Sudden motion → many waves&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>beginners</category>
      <category>learning</category>
      <category>science</category>
    </item>
    <item>
      <title>What Really Happens When You Turn On Your Phone (IMEI, Tower &amp; Network Initialization Explained)</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Sat, 06 Dec 2025 14:13:11 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/what-really-happens-when-you-turn-on-your-phone-imei-tower-network-initialization-explained-270l</link>
      <guid>https://dev.to/ktauchathuranga/what-really-happens-when-you-turn-on-your-phone-imei-tower-network-initialization-explained-270l</guid>
      <description>&lt;p&gt;This article explains &lt;strong&gt;exactly what happens from the moment you power on your phone until it gets full network access&lt;/strong&gt;, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What data is sent to the tower&lt;/li&gt;
&lt;li&gt;When the &lt;strong&gt;IMEI&lt;/strong&gt; is transmitted&lt;/li&gt;
&lt;li&gt;How authentication works&lt;/li&gt;
&lt;li&gt;How telecom operators check &lt;strong&gt;millions of IMEI records instantly&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;How governments block unapproved devices (TRCSL / IMEI blacklisting)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Power-On: Baseband &amp;amp; RF Initialization
&lt;/h2&gt;

&lt;p&gt;When you press the power button:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;baseband modem&lt;/strong&gt; starts&lt;/li&gt;
&lt;li&gt;RF transceiver activates&lt;/li&gt;
&lt;li&gt;Precision clock (TCXO) starts&lt;/li&gt;
&lt;li&gt;SIM interface powers up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ No transmission&lt;/li&gt;
&lt;li&gt;✅ Phone only &lt;strong&gt;listens to radio signals&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Passive Cell Scanning (Silent Phase)
&lt;/h2&gt;

&lt;p&gt;The phone scans supported frequency bands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LTE Bands: 1, 3, 5, 8, etc.&lt;/li&gt;
&lt;li&gt;Searches for:

&lt;ul&gt;
&lt;li&gt;Synchronization Signals&lt;/li&gt;
&lt;li&gt;Broadcast channels (PBCH, BCCH)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;From the tower it learns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Operator name&lt;/li&gt;
&lt;li&gt;Cell ID&lt;/li&gt;
&lt;li&gt;Tracking Area Code (TAC)&lt;/li&gt;
&lt;li&gt;Network capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Still anonymous&lt;br&gt;&lt;br&gt;
✅ No IMSI&lt;br&gt;&lt;br&gt;
✅ No IMEI&lt;br&gt;&lt;br&gt;
✅ No transmission yet  &lt;/p&gt;


&lt;h2&gt;
  
  
  3. Cell Selection
&lt;/h2&gt;

&lt;p&gt;The phone selects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The strongest valid tower&lt;/li&gt;
&lt;li&gt;That supports:

&lt;ul&gt;
&lt;li&gt;Your SIM operator&lt;/li&gt;
&lt;li&gt;Your radio features&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now it decides:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This is the tower I will register to."&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  4. First Transmission: RACH (Random Access)
&lt;/h2&gt;

&lt;p&gt;Your phone sends its &lt;strong&gt;first uplink message&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Channel: &lt;strong&gt;RACH&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Contains:

&lt;ul&gt;
&lt;li&gt;Temporary timing&lt;/li&gt;
&lt;li&gt;Power parameters&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ No IMEI&lt;br&gt;&lt;br&gt;
❌ No IMSI&lt;br&gt;&lt;br&gt;
✅ Still anonymous  &lt;/p&gt;

&lt;p&gt;The tower replies with timing alignment.&lt;/p&gt;


&lt;h2&gt;
  
  
  5. Network Attach Request (SIM Identity Begins)
&lt;/h2&gt;

&lt;p&gt;Your phone sends an &lt;strong&gt;ATTACH REQUEST&lt;/strong&gt; containing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TMSI / IMSI&lt;/td&gt;
&lt;td&gt;SIM identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Device capabilities&lt;/td&gt;
&lt;td&gt;LTE/5G features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cipher algorithms&lt;/td&gt;
&lt;td&gt;Encryption support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;✅ IMSI involved&lt;br&gt;&lt;br&gt;
❌ IMEI still NOT sent  &lt;/p&gt;


&lt;h2&gt;
  
  
  6. SIM Authentication &amp;amp; Encryption
&lt;/h2&gt;

&lt;p&gt;Authentication challenge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Tower → Random Challenge
SIM → Cryptographic Response

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If verified:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encryption keys are created&lt;/li&gt;
&lt;li&gt;All traffic becomes encrypted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ SIM authenticated&lt;br&gt;&lt;br&gt;
✅ Secure channel established  &lt;/p&gt;


&lt;h2&gt;
  
  
  7. IMEI Is Requested (Important Step)
&lt;/h2&gt;

&lt;p&gt;Now the network sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
IDENTITY REQUEST → IMEI

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The phone replies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
IDENTITY RESPONSE → IMEI

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the network finally knows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your &lt;strong&gt;hardware identity&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Your &lt;strong&gt;exact device model&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Your &lt;strong&gt;legal status&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. IMEI Validation Using EIR (Equipment Identity Register)
&lt;/h2&gt;

&lt;p&gt;Network checks your IMEI against:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;List&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;✅ White List&lt;/td&gt;
&lt;td&gt;Approved devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚠️ Grey List&lt;/td&gt;
&lt;td&gt;Monitored devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;❌ Black List&lt;/td&gt;
&lt;td&gt;Blocked devices&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Allowed → Full network service&lt;/li&gt;
&lt;li&gt;❌ Blocked → "No Service / Emergency Only"&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9. Does the Network Search Through 23 Million IMEIs One-by-One?
&lt;/h2&gt;

&lt;p&gt;❌ &lt;strong&gt;Absolutely NOT.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Telecom operators use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hash tables&lt;/li&gt;
&lt;li&gt;B-Tree indexes&lt;/li&gt;
&lt;li&gt;In-memory caches&lt;/li&gt;
&lt;li&gt;Distributed databases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lookup process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
IMEI → Hash Index → Memory Lookup → Result in ~1–5 ms

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Records&lt;/th&gt;
&lt;th&gt;Lookup Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 million&lt;/td&gt;
&lt;td&gt;~1 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 million&lt;/td&gt;
&lt;td&gt;~2–4 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30 million&lt;/td&gt;
&lt;td&gt;~5 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;✅ No scanning&lt;br&gt;&lt;br&gt;
✅ No looping&lt;br&gt;&lt;br&gt;
✅ No delays  &lt;/p&gt;




&lt;h2&gt;
  
  
  10. Where the IMEI Database Exists
&lt;/h2&gt;

&lt;p&gt;IMEI records exist in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Central &lt;strong&gt;TRCSL EIR&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Mirrored operator EIRs (Dialog, Mobitel, Airtel, Hutch)&lt;/li&gt;
&lt;li&gt;Real-time synchronized systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your local operator checks &lt;strong&gt;its own cached EIR&lt;/strong&gt;, not a remote server every time.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Final Network Activation
&lt;/h2&gt;

&lt;p&gt;If everything is valid:&lt;/p&gt;

&lt;p&gt;✅ Calls&lt;br&gt;&lt;br&gt;
✅ SMS&lt;br&gt;&lt;br&gt;
✅ Mobile Data&lt;br&gt;&lt;br&gt;
✅ Encrypted Communication&lt;br&gt;&lt;br&gt;
✅ IP Address Assigned&lt;br&gt;&lt;br&gt;
✅ Tower-to-tower handover enabled  &lt;/p&gt;




&lt;h2&gt;
  
  
  12. Full Power-On Timeline
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RF Scan&lt;/td&gt;
&lt;td&gt;~0.5 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attach Request&lt;/td&gt;
&lt;td&gt;~0.2 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIM Auth&lt;/td&gt;
&lt;td&gt;~0.3 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IMEI Check&lt;/td&gt;
&lt;td&gt;~0.005 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IP Assignment&lt;/td&gt;
&lt;td&gt;~0.2 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;✅ Total: &lt;strong&gt;~1–1.5 seconds&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  13. Network Type vs IMEI Checking Node
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Network&lt;/th&gt;
&lt;th&gt;IMEI Checked By&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2G&lt;/td&gt;
&lt;td&gt;MSC + VLR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3G&lt;/td&gt;
&lt;td&gt;SGSN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4G LTE&lt;/td&gt;
&lt;td&gt;MME&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5G&lt;/td&gt;
&lt;td&gt;AMF&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  14. Security Reality
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In &lt;strong&gt;2G&lt;/strong&gt;, IMEI can be sniffed easily&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;4G/5G&lt;/strong&gt;, IMEI is transmitted &lt;strong&gt;after encryption&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;That makes modern interception extremely difficult&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  15. Final Summary Diagram
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Power On
↓
Scan Towers
↓
Attach with IMSI
↓
SIM Authentication
↓
Encrypted Channel
↓
IMEI Requested
↓
EIR Database Check (Milliseconds)
↓
Allowed ✅   or   Blocked ❌

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  16. Key Truth About Government Phone Blocking
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;❌ They do NOT hack your phone&lt;/li&gt;
&lt;li&gt;❌ They do NOT modify firmware&lt;/li&gt;
&lt;li&gt;❌ They do NOT disable WiFi&lt;/li&gt;
&lt;li&gt;✅ They simply &lt;strong&gt;deny service at the network level using IMEI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ Your phone becomes a &lt;strong&gt;WiFi-only device&lt;/strong&gt; if blocked&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  This article is ideal for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Telecom engineering students&lt;/li&gt;
&lt;li&gt;Cybersecurity researchers&lt;/li&gt;
&lt;li&gt;Mobile device hackers &amp;amp; reverse engineers&lt;/li&gt;
&lt;li&gt;RF &amp;amp; SDR learners&lt;/li&gt;
&lt;li&gt;IMEI tracking &amp;amp; blacklisting research&lt;/li&gt;
&lt;/ul&gt;




</description>
    </item>
    <item>
      <title>My Command Reference</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Sat, 06 Sep 2025 06:04:37 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/my-command-reference-56ne</link>
      <guid>https://dev.to/ktauchathuranga/my-command-reference-56ne</guid>
      <description>&lt;h2&gt;
  
  
  Docker Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Container Management
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all containers (running and stopped)&lt;/span&gt;
docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;

&lt;span class="c"&gt;# List only running containers&lt;/span&gt;
docker ps

&lt;span class="c"&gt;# Stop all running containers&lt;/span&gt;
docker stop &lt;span class="si"&gt;$(&lt;/span&gt;docker ps &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Remove all stopped containers&lt;/span&gt;
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker ps &lt;span class="nt"&gt;-aq&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Remove all containers (running and stopped)&lt;/span&gt;
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker ps &lt;span class="nt"&gt;-aq&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Stop and remove a specific container&lt;/span&gt;
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;lt;container_name_or_id&amp;gt;

&lt;span class="c"&gt;# Remove all unused containers, networks, images&lt;/span&gt;
docker system prune

&lt;span class="c"&gt;# Remove everything including volumes&lt;/span&gt;
docker system prune &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;--volumes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Image Management
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all images&lt;/span&gt;
docker images

&lt;span class="c"&gt;# Remove all unused images&lt;/span&gt;
docker image prune &lt;span class="nt"&gt;-a&lt;/span&gt;

&lt;span class="c"&gt;# Remove specific image&lt;/span&gt;
docker rmi &amp;lt;image_name_or_id&amp;gt;

&lt;span class="c"&gt;# Remove all images&lt;/span&gt;
docker rmi &lt;span class="si"&gt;$(&lt;/span&gt;docker images &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Build image from Dockerfile&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; &amp;lt;tag_name&amp;gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Pull image from registry&lt;/span&gt;
docker pull &amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running Containers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run container interactively&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;image_name&amp;gt; /bin/bash

&lt;span class="c"&gt;# Run container in background&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &amp;lt;image_name&amp;gt;

&lt;span class="c"&gt;# Run with port mapping&lt;/span&gt;
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; &amp;lt;host_port&amp;gt;:&amp;lt;container_port&amp;gt; &amp;lt;image_name&amp;gt;

&lt;span class="c"&gt;# Run with volume mount&lt;/span&gt;
docker run &lt;span class="nt"&gt;-v&lt;/span&gt; &amp;lt;host_path&amp;gt;:&amp;lt;container_path&amp;gt; &amp;lt;image_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Logs and Debugging
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# View container logs&lt;/span&gt;
docker logs &amp;lt;container_name_or_id&amp;gt;

&lt;span class="c"&gt;# Follow logs in real-time&lt;/span&gt;
docker logs &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;lt;container_name_or_id&amp;gt;

&lt;span class="c"&gt;# Execute command in running container&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;container_name_or_id&amp;gt; /bin/bash

&lt;span class="c"&gt;# Inspect container details&lt;/span&gt;
docker inspect &amp;lt;container_name_or_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Arduino CLI Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Board Management
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update board package index&lt;/span&gt;
arduino-cli core update-index

&lt;span class="c"&gt;# Install board package (e.g., ESP32)&lt;/span&gt;
arduino-cli core &lt;span class="nb"&gt;install &lt;/span&gt;esp32:esp32

&lt;span class="c"&gt;# List installed boards&lt;/span&gt;
arduino-cli core list

&lt;span class="c"&gt;# List available boards&lt;/span&gt;
arduino-cli board listall

&lt;span class="c"&gt;# Search for boards&lt;/span&gt;
arduino-cli core search &amp;lt;board_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Library Management
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update library index&lt;/span&gt;
arduino-cli lib update-index

&lt;span class="c"&gt;# Install library&lt;/span&gt;
arduino-cli lib &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;library_name&amp;gt;"&lt;/span&gt;

&lt;span class="c"&gt;# List installed libraries&lt;/span&gt;
arduino-cli lib list

&lt;span class="c"&gt;# Search for libraries&lt;/span&gt;
arduino-cli lib search &amp;lt;library_name&amp;gt;

&lt;span class="c"&gt;# Uninstall library&lt;/span&gt;
arduino-cli lib uninstall &lt;span class="s2"&gt;"&amp;lt;library_name&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compilation and Upload
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Compile sketch&lt;/span&gt;
arduino-cli compile &lt;span class="nt"&gt;--fqbn&lt;/span&gt; &amp;lt;board_fqbn&amp;gt; &amp;lt;sketch_path&amp;gt;

&lt;span class="c"&gt;# Upload to board&lt;/span&gt;
arduino-cli upload &lt;span class="nt"&gt;-p&lt;/span&gt; &amp;lt;port&amp;gt; &lt;span class="nt"&gt;--fqbn&lt;/span&gt; &amp;lt;board_fqbn&amp;gt; &amp;lt;sketch_path&amp;gt;

&lt;span class="c"&gt;# Compile and upload in one command&lt;/span&gt;
arduino-cli compile &lt;span class="nt"&gt;--upload&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &amp;lt;port&amp;gt; &lt;span class="nt"&gt;--fqbn&lt;/span&gt; &amp;lt;board_fqbn&amp;gt; &amp;lt;sketch_path&amp;gt;

&lt;span class="c"&gt;# Set upload speed (in sketch or command)&lt;/span&gt;
arduino-cli upload &lt;span class="nt"&gt;-p&lt;/span&gt; &amp;lt;port&amp;gt; &lt;span class="nt"&gt;--fqbn&lt;/span&gt; &amp;lt;board_fqbn&amp;gt; &amp;lt;sketch_path&amp;gt; &lt;span class="nt"&gt;--upload-field&lt;/span&gt; upload.speed&lt;span class="o"&gt;=&lt;/span&gt;921600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Board Detection and Port Management
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List connected boards&lt;/span&gt;
arduino-cli board list

&lt;span class="c"&gt;# Get board info&lt;/span&gt;
arduino-cli board details &lt;span class="nt"&gt;--fqbn&lt;/span&gt; &amp;lt;board_fqbn&amp;gt;

&lt;span class="c"&gt;# Common FQBNs:&lt;/span&gt;
&lt;span class="c"&gt;# Arduino Uno: arduino:avr:uno&lt;/span&gt;
&lt;span class="c"&gt;# ESP32: esp32:esp32:esp32&lt;/span&gt;
&lt;span class="c"&gt;# ESP8266: esp8266:esp8266:nodemcuv2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Serial Monitor with picocom
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Connect to serial port&lt;/span&gt;
picocom &lt;span class="nt"&gt;-b&lt;/span&gt; 115200 /dev/ttyUSB0

&lt;span class="c"&gt;# Connect with different baud rates&lt;/span&gt;
picocom &lt;span class="nt"&gt;-b&lt;/span&gt; 9600 /dev/ttyUSB0
picocom &lt;span class="nt"&gt;-b&lt;/span&gt; 57600 /dev/ttyUSB0
picocom &lt;span class="nt"&gt;-b&lt;/span&gt; 921600 /dev/ttyUSB0

&lt;span class="c"&gt;# Exit picocom: Ctrl+A then Ctrl+X&lt;/span&gt;

&lt;span class="c"&gt;# List available serial ports&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; /dev/tty&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="c"&gt;# or&lt;/span&gt;
dmesg | &lt;span class="nb"&gt;grep tty&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Arduino IDE Configuration Files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Preferences location (Linux)&lt;/span&gt;
~/.arduino15/

&lt;span class="c"&gt;# Sketches default location&lt;/span&gt;
~/Arduino/

&lt;span class="c"&gt;# Set upload speed in boards.txt or via IDE:&lt;/span&gt;
&lt;span class="c"&gt;# Tools -&amp;gt; Upload Speed -&amp;gt; Select desired speed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Useful Arduino Compile Flags
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verbose compilation output&lt;/span&gt;
arduino-cli compile &lt;span class="nt"&gt;--verbose&lt;/span&gt; &lt;span class="nt"&gt;--fqbn&lt;/span&gt; &amp;lt;board_fqbn&amp;gt; &amp;lt;sketch_path&amp;gt;

&lt;span class="c"&gt;# Enable warnings&lt;/span&gt;
arduino-cli compile &lt;span class="nt"&gt;--warnings&lt;/span&gt; all &lt;span class="nt"&gt;--fqbn&lt;/span&gt; &amp;lt;board_fqbn&amp;gt; &amp;lt;sketch_path&amp;gt;

&lt;span class="c"&gt;# Clean build&lt;/span&gt;
arduino-cli compile &lt;span class="nt"&gt;--clean&lt;/span&gt; &lt;span class="nt"&gt;--fqbn&lt;/span&gt; &amp;lt;board_fqbn&amp;gt; &amp;lt;sketch_path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Linux commands | search
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"tozed_param"&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./etc/tozed/config_update:42:tozed_param=enabled

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>CPU Stress Test on Arch Linux</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Wed, 20 Aug 2025 18:57:30 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/cpu-stress-test-on-arch-linux-5e80</link>
      <guid>https://dev.to/ktauchathuranga/cpu-stress-test-on-arch-linux-5e80</guid>
      <description>&lt;p&gt;This guide explains how to load your CPU to 100% to test cooling, thermal throttling, or stability.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ Warning
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This will heat up your CPU &lt;strong&gt;significantly&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Monitor temperatures with &lt;code&gt;lm_sensors&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Ensure your cooling system is working properly.&lt;/li&gt;
&lt;li&gt;Do &lt;strong&gt;not&lt;/strong&gt; leave unattended.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Install Required Tools
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-Syu&lt;/span&gt; stress-ng lm_sensors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;stress-ng&lt;/code&gt; → main stress-testing tool&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lm_sensors&lt;/code&gt; → CPU temperature monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Set up sensors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sensors-detect
sensors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Stress Test CPU
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option A: &lt;code&gt;stress-ng&lt;/code&gt; (recommended)
&lt;/h3&gt;

&lt;p&gt;Run all CPU cores at 100%:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;stress-ng &lt;span class="nt"&gt;--cpu&lt;/span&gt; 0 &lt;span class="nt"&gt;--cpu-method&lt;/span&gt; matrixprod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--cpu 0&lt;/code&gt; → use all cores&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--cpu-method matrixprod&lt;/code&gt; → heavy floating-point load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional: stop automatically after 5 minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;stress-ng &lt;span class="nt"&gt;--cpu&lt;/span&gt; 0 &lt;span class="nt"&gt;--cpu-method&lt;/span&gt; matrixprod &lt;span class="nt"&gt;--timeout&lt;/span&gt; 5m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Option B: &lt;code&gt;yes&lt;/code&gt; command (quick &amp;amp; dirty)
&lt;/h3&gt;

&lt;p&gt;Each &lt;code&gt;yes &amp;gt; /dev/null &amp;amp;&lt;/code&gt; consumes one core:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &amp;amp;
&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &amp;amp;
&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &amp;amp;
&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &amp;amp;
&lt;span class="c"&gt;# Add one per CPU core&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stop all processes with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;killall &lt;span class="nb"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Option C: Compile Test (optional)
&lt;/h3&gt;

&lt;p&gt;If you have source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-j$(nproc)&lt;/code&gt; → uses all CPU cores&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Monitor CPU Temperature
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;watch &lt;span class="nt"&gt;-n&lt;/span&gt; 1 sensors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Updates every second&lt;/li&gt;
&lt;li&gt;Check for thermal throttling warnings&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Stop Stress Test
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + C&lt;/code&gt; if running in terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;killall stress-ng&lt;/code&gt; or &lt;code&gt;killall yes&lt;/code&gt; for background processes&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>mDNS Setup on Arch Linux</title>
      <dc:creator>Ashen Chathuranga</dc:creator>
      <pubDate>Wed, 20 Aug 2025 14:06:13 +0000</pubDate>
      <link>https://dev.to/ktauchathuranga/mdns-setup-on-arch-linux-cj</link>
      <guid>https://dev.to/ktauchathuranga/mdns-setup-on-arch-linux-cj</guid>
      <description>&lt;p&gt;This will let other devices on your local network access your machine using a hostname like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://archlinux.local:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of remembering the IP (&lt;code&gt;192.168.x.x&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Install required packages
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; avahi nss-mdns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Enable and start Avahi
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; avahi-daemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Configure &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; with your favorite editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/nsswitch.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace its contents with this (copy and paste):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Name Service Switch configuration file.
# See nsswitch.conf(5) for details.

passwd: files systemd
group: files [SUCCESS=merge] systemd
shadow: files systemd
gshadow: files systemd

publickey: files

hosts: files mdns_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns myhostname
networks: files

protocols: files
services: files
ethers: files
rpc: files

netgroup: files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save and exit.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Restart name resolution
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart systemd-resolved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Test
&lt;/h2&gt;

&lt;p&gt;On your Arch machine, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping archlinux.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see it resolve to your LAN IP (e.g., &lt;code&gt;192.168.3.224&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;On another device (Linux/macOS/iOS), try opening:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://archlinux.local:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
