<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://scientiac.space/feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>scientiac::syntropy</title>
    <subtitle>A Computer Engineering student who loves FOSS and is learning about privacy, the Internet and languages writing about the things he does.</subtitle>
    <link href="https:&#x2F;&#x2F;scientiac.space"/>
    <link href="https://scientiac.space/atom.xml" rel="self" type="application/atom+xml"/>
    <updated>2026-04-30T00:00:00+00:00</updated>
    <id>https:&#x2F;&#x2F;scientiac.space</id>
    <entry>
        <title>Customizing the Operating System</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;cutomizing-the-os&#x2F;"/>
        <updated>2026-04-30T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;cutomizing-the-os&#x2F;</id>
        <content type="html"><![CDATA[
          <p><em>I just love tinkering with my devices, and have a design philosophy.</em></p>
<p><em>Sorry KDE</em>,<br />
<em><strong>"Nothing by default, just there when needed."</strong></em></p>
<p>Which I know is not a perfect system because sometimes things get lost. And I have to search them which isn't very efficient. Since I have started from the drawbacks and pain points lets just continue with it.</p>
<ol>
<li>Things get lost sometimes.</li>
<li>Moving the mouse can cause different panes to open.</li>
<li>There are only limited places to hide things.</li>
<li>Sometimes you just wish you could see things without having to do anything.</li>
</ol>
<p>Now that we've got that out of the way, lets start with everything that I have set up:</p>
<p><em>So, by now you might have already realized what the theme for today is.</em> <em>Yes!, it's <strong>Extreme Minimalism</strong>.</em></p>
<p>Let's start from the bottom up:</p>
<h2 id="pre-desktop">Pre-Desktop</h2>
<h3 id="bios">BIOS</h3>
<p>Fortunately my BIOS boot animation is very pretty, and I love that the logo of my vendor also somewhat resembles Arch Linux. It's the new ASUS Zenbook Logo, which is located at <code>/sys/firmware/acpi/bgrt/image</code> on my system.</p>
<p><em><strong>If you know how to extract the actual animation from the BIOS please tell me how, I want to make it into a <code>plymouth</code> boot animation.</strong></em></p>
<p><img src="https://scientiac.space/images/customizing-the-os/bios.png" alt="BIOS Logo" /></p>
<p>This is the end result image after the BIOS animation completes and before it hands over control to the <code>Bootloader</code>.</p>
<h3 id="bootloader">Bootloader</h3>
<p>I use <code>systemd-boot</code> which itself is super minimal. But, I have configured it to be invisible by setting the timeout to be 0.</p>
<p><img src="https://scientiac.space/images/customizing-the-os/systemd-boot.png" alt="Systemd Boot" /></p>
<p>It can be done by editing <code>/boot/loader/loader.conf</code> and setting <code>timeout 0</code>. Here comes the philosophy of keeping things hidden while still accessible. Because, holding <kbd>shift</kbd> while the system boots will let me see the Bootloader Entries if it is necessary.</p>
<p>I normally keep two kernels in case one breaks. Above image is only for reference to show how minimal the UI of <code>systemd-boot</code> is.</p>
<h3 id="initramfs">initramfs</h3>
<p>Since I use the <code>systemd</code> ecosystem including the <code>bootloader</code> and <code>init</code> system. I have used <code>mkinitcpio</code> to build a <code>systemd</code> dependent <code>initramfs</code>. Hence I use the the <a rel="external" href="https://wiki.archlinux.org/title/Mkinitcpio#Hook_list">Hook List</a> table to set up <code>mkinitcpio</code>.</p>
<p>I also add plymouth to the hook in <code>/etc/mkinitcpio.conf</code>:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"><span>HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block filesystems fsck plymouth)</span></span></code></pre><h3 id="unified-kernel-image-uki">Unified Kernel Image (UKI)</h3>
<p>The default Arch Linux UKI has it's own splash image. And I don't like different things flashing when the system boots. So, I change the splash image of the Arch Linux UKI my BIOS image mentioned above. For that I edit <code>/etc/mkinitcpio.d/linux.preset</code> to have:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"><span>default_options=&quot;--splash /sys/firmware/acpi/bgrt/image&quot;</span></span></code></pre><h3 id="kernel-cmdline">Kernel <code>cmdline</code></h3>
<p>In order to supress the messages in the boot process I put the following arguments to <code>/etc/kernel/cmdline</code>:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"><span>loglevel=3 quiet splash</span></span></code></pre>
<p>The log level and quiet arguments supress the messages while the splash enables the splash screen which will come into play when <code>plymouth</code> is installed.</p>
<h3 id="plymouth">Plymouth</h3>
<p>It is a system that uses Kernel Mode Setting (KMS) to set the native resolution of the display as early as possible, then provides a  splash screen leading all the way up to the login manager.</p>
<p>After installing <code>plymouth</code> through <code>pacman</code>, the default splash screen it uses is <code>BGRT</code> which stands for Boot Graphics Resource Table which also utilizes the <code>spinner</code> theme to put a spinner on the bottom of the splash screen.</p>
<p>The spinner theme the Arch Linux logo which I don't want there. So, I delete it from <code>/usr/share/plymouth/themes/spinner/</code> and delete all animation and throbber images too just to make everything clean. The Arch Linux and spinners will be gone on the next boot.</p>
<p>But, my device boots really fast, so after the kernel splash screen, there is a blank screen for a second then <code>plymouth</code> launches which lasts for not even a second. This causes me to see only a flicker of plymouth. So I have delayed the launch of it by 15 seconds.</p>
<p>In <code>/etc/plymouth/plymouthd.conf</code>:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"><span>[Daemon]</span></span>
<span class="giallo-l"><span>ShowDelay=15</span></span></code></pre>
<p>Well, you might ask why delay <code>plymouth</code> instead of just uninstalling the it entirely. It is because <code>plymouth</code> also appears during <code>poweroff</code> and <code>reboot</code> while the system is shutting down, which I want to have.</p>
<h3 id="gdm">GDM</h3>
<p>I use <a rel="external" href="https://github.com/niri-wm/niri">Niri</a> as my window manger of choice. But, have a fallback <a rel="external" href="https://www.gnome.org/">GNOME</a> session since <code>niri</code> plays well with GNOME's set of utilities.</p>
<p><img src="https://scientiac.space/images/customizing-the-os/gdm.png" alt="GDM" /></p>
<p>The default Arch Linux <code>GDM</code> has the Arch Linux logo there which I remove using the <a rel="external" href="https://github.com/gdm-settings/gdm-settings">GDM Settings</a> application. There might be a way to remove it via the command line but I am lazy and I just delete the application once I change this setting and it remains persistent. Tell me if you know the way. <code>;)</code></p>
<p><code>edit: 2026-05-03: start</code></p>
<h3 id="greetd">greetd</h3>
<p>I switched from <code>GDM</code> to <code>greetd</code> to have the same style on the login manager which I have for the lock screen. Which also meant sacrificing the lock screen of the GNOME session and using something new that I know nothing about. I starting tracking the setup for <code>greetd</code> in a <a rel="external" href="https://raw.githubusercontent.com/scientiac/einstein.chezmoi/refs/heads/main/dot_config/quickshell/scigreet/README.md">markdown</a> file.</p>
<p>For the greeter I use <code>niri</code> as it's compositor and <code>quickshell</code> for the UI.</p>
<p>The immediate issue was, the GNOME Keyring not being unlocked by default. Which was easily fixed by editing <code>/etc/pam.d/greetd</code> with the following PAM(Pluggable Authentication Modules) setup:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"><span>#%PAM-1.0</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>auth       required     pam_securetty.so</span></span>
<span class="giallo-l"><span>auth       requisite    pam_nologin.so</span></span>
<span class="giallo-l"><span>auth       include      system-local-login</span></span>
<span class="giallo-l"><span>auth       optional     pam_gnome_keyring.so</span></span>
<span class="giallo-l"><span>account    include      system-local-login</span></span>
<span class="giallo-l"><span>session    include      system-local-login</span></span>
<span class="giallo-l"><span>session    optional     pam_gnome_keyring.so auto_start</span></span></code></pre>
<p>Using <code>greetd</code> meant living with the logs when going from greeter to compositor. So, I went down a rabbit hole. I tried disabling systemd logs for user, for system, for greeter user and what not. I used google, duckduckgo, chatgpt, gemini, heck even grok to find a solution, but nothing helped.</p>
<p>Then, I found out about a side effect of the framebuffer console boot options from the <a rel="external" href="https://www.kernel.org/doc/html/latest/fb/fbcon.html">Linux Kernel Documentation</a> saying, "<em>One side effect that may be useful is using a map value that exceeds the number of loaded fb drivers. For example, if only one driver is available, fb0, adding fbcon=map:1 tells fbcon not to take over the console.</em>"</p>
<p>So, I appended fbcon=map:1 to <code>/etc/kernel/cmdline</code>.</p>
<p>This completely disabled the console, which meant no text will be printed during switch from greeter to the compositor. <strong>But</strong>, this also meant that there is now no way to go to <code>ttyX</code> if I had to debug the system in case it breaks. And since it's Arch Linux, noone can guarantee that it would not.</p>
<p>I then went down on another rabbit hole trying to enable the other framebuffers from userspace command line after system fully booted. Which I couldn't solve.</p>
<p>Looking for other console options, <strong>I found <code>kmscon</code></strong>, and out of sheer curosity I installed it and rebooted the system. And I can't state the joy I felt when I tried to switch to tty2 and it dropped me into a console. I also found out that it supported fonts and can use <code>pango</code> which I loved and immediately switched to a Nerd Font. I also themed it with the same colors that I theme my Terminal Emulator.</p>
<p>It was as easy as <code>sudo pacman -s kmscon</code> then reboot. By, default only <code>tty2</code> with <code>ctrl+alt+f2</code> works, but other sessions can be enabled with <code>systemd</code> too.</p>
<p>So, there it is, another minimal component, <code>greetd</code> added to the my system replacing GNOME's <code>GDM</code>. With the pretty-pretty <code>kmscon</code>, which is my love at first sight.</p>
<p><br />
<code>edit: 2026-05-03: end</code></p>
<h3 id="poweroff-and-reboot">Poweroff and Reboot</h3>
<p>I hate the annoying systemd wall messages when shutting down or rebooting the system:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"><span>Broadcast message from user@host (Thu 1970-01-01 00:00:00 UTC):</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>The system will power off now!</span></span></code></pre>
<p>So I use this one liner from <a rel="external" href="https://github.com/Kira-NT/disable-systemd-wall-messages">Kira-NT/disable-systemd-wall-messages</a> to disable the wall messages:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"><span style="color: #FABD2F;">curl</span><span style="color: #D3869B;"> -Ls</span><span style="color: #B8BB26;"> https://github.com/Kira-NT/disable-systemd-wall-messages/blob/HEAD/install.sh?raw=</span><span style="color: #D3869B;">true</span><span style="color: #8EC07C;"> |</span><span style="color: #FABD2F;"> sudo</span><span style="color: #B8BB26;"> sh</span><span style="color: #D3869B;"> -s</span></span></code></pre>
<p>And for the times I use terminal to reboot or power off I put the following shell alias for them:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"><span style="color: #FE8019;">alias</span><span style="color: #83A598;"> reboot</span><span style="color: #8EC07C;">=</span><span style="color: #A89984;">&quot;</span><span style="color: #B8BB26;">reboot --no-wall</span><span style="color: #A89984;">&quot;</span></span>
<span class="giallo-l"><span style="color: #FE8019;">alias</span><span style="color: #83A598;"> poweroff</span><span style="color: #8EC07C;">=</span><span style="color: #A89984;">&quot;</span><span style="color: #B8BB26;">poweroff --no-wall</span><span style="color: #A89984;">&quot;</span></span></code></pre><h2 id="desktop">Desktop</h2>
<p>All that for the 10 to 20 seconds it takes to get from hitting the power button into my desktop.</p>
<p>But, now we are finally at the desktop.</p>
<h3 id="niri">Niri</h3>
<p>As I have already mentioned, I use Niri as my desktop of choice. Lets start from then start then!</p>
<h4 id="wallpaper">Wallpaper</h4>
<p><code>awww</code> is what I use to set the wallpaper since it has the ability to set wallpapers to different layers in <code>niri</code>. I start the daemon as follows:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"><span style="color: #FABD2F;">awww-daemon</span><span style="color: #D3869B;"> -n</span><span style="color: #B8BB26;"> wp-front</span><span style="color: #A89984;"> &amp;</span></span>
<span class="giallo-l"><span style="color: #FABD2F;">awww-daemon</span><span style="color: #D3869B;"> -n</span><span style="color: #B8BB26;"> wp-back</span><span style="color: #A89984;"> &amp;</span></span></code></pre>
<p>The <code>wp-front</code> is the namespace for actual layer where <code>niri</code>'s wallpaper will be set.
The <code>wp-back</code> is the namespace for the layer behind the desktop where <code>niri</code>'s overview backdrop will be set.</p>
<p><img src="https://scientiac.space/images/customizing-the-os/wallpapers.png" alt="Wallpapers" /></p>
<p>I set my wallpaper on <code>wp-front</code> and a blurred version of the same wallpaper on <code>wp-back</code> to get the above results. With the following setting on the niri config:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="kdl"><span class="giallo-l"><span style="color: #8EC07C;">layer-rule</span><span> {</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    match</span><span style="color: #FABD2F;"> namespace</span><span style="color: #A89984;">=</span><span style="color: #B8BB26;">&quot;wp-back&quot;</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    place-within-backdrop</span><span style="color: #CC241D;"> true</span></span>
<span class="giallo-l"><span>}</span></span></code></pre>
<p>and the command to set:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"><span style="color: #FABD2F;">awww</span><span style="color: #B8BB26;"> img</span><span style="color: #A89984;"> &quot;</span><span style="color: #83A598;">$BLURRED_WALLPAPER</span><span style="color: #A89984;">&quot;</span><span style="color: #D3869B;"> -n</span><span style="color: #B8BB26;"> wp-back</span><span style="color: #A89984;"> &amp;</span></span>
<span class="giallo-l"><span style="color: #FABD2F;">awww</span><span style="color: #B8BB26;"> img</span><span style="color: #A89984;"> &quot;</span><span style="color: #83A598;">$SELECTED_WALLPAPER</span><span style="color: #A89984;">&quot;</span><span style="color: #D3869B;"> -n</span><span style="color: #B8BB26;"> wp-front</span><span style="color: #A89984;"> &amp;</span></span></code></pre><h4 id="launcher">Launcher</h4>
<p>In the past I used to use very minimal and customizable launchers like <code>rofi</code>, <code>wofi</code> and <code>tofi</code> but after watching enough number of ads for the Raycast launcher, I fell in love with <a rel="external" href="https://github.com/vicinaehq/vicinae">vicinae</a>.</p>
<p><img src="https://scientiac.space/images/customizing-the-os/launcher.png" alt="Launcher" /></p>
<p>It just works! The only thing I changed was the fonts to be <code>FantasqueSansM Nerd Font Propo</code>, the Icon theme to <code>Morewaita</code> and enabled blur.</p>
<h4 id="the-shell">The Shell</h4>
<p>I decided to write this blog post because of this shell. It gives me joy with a mix of pain and impostor syndrome to call it mine. I wrote it using AI in <code>quickshell</code>. One one hand, It'd had taken me weeks to completely write all this myself, but I did it in a single day, and it isn't system critical so I guess I get a pass for not doing it myself.</p>
<p><strong>Lockscreen:</strong> I decided to recreate the <code>swaylock-effects</code> lockscreen with a blurred screen setup using quickshell.</p>
<p><img src="https://scientiac.space/images/customizing-the-os/lockscreen.png" alt="Lockscreen" /></p>
<p>I want to make the same UI for <code>greetd</code> and use it for the Display Manager too but, I am afraid <code>GNOME</code> will not like it when I use something other than GDM. [ <strong><em>I did it!</em></strong> ]</p>
<p><strong>OSD:</strong> For OSD, I took design inspiration from the IOS dynamic island and decided to create an interactive bottom notch.</p>
<p><video src="https://scientiac.space/images/customizing-the-os/osd.mp4" autoplay loop></video></p>
<p><strong>Bar:</strong> For the Bar, I took inspiration from the OSD and made it top notch.</p>
<p><video src="https://scientiac.space/images/customizing-the-os/bar.mp4" autoplay loop></video></p>
<p><strong>Notifications:</strong> Similar to OSD and Bars I made the notifications with a corner swoop.</p>
<p><video src="https://scientiac.space/images/customizing-the-os/notification.mp4" autoplay loop></video></p>
<p>As a whole it looks like this:</p>
<p><video src="https://scientiac.space/images/customizing-the-os/desktop.mp4" controls></video></p>
<p><em>Sorry for the flashbang.</em></p>
<p>Almost everything in the shell is <code>quickshell</code> now, which replaced various applications like:</p>
<ul>
<li><code>way-edges</code> for bar</li>
<li><code>swayosd</code> for brightness and volume OSD</li>
<li><code>battery-osd</code> for battery notifications and OSD</li>
<li><code>swaylock</code> for lock screen</li>
<li><code>swaync</code> for notifications</li>
</ul>
<h2 id="this-is-fun">This is Fun</h2>
<p>Funny how describing the setup of the 10 second boot process took more words than describing the desktop. But, if we consider "<em>A picture is worth a thousand words.</em>" the desktop wins by a long shot!</p>
<p>If you see some lag, it's because of the screen record. I have applied this <em><strong>"Nothing by default, just there when needed."</strong></em> philosophy everywhere from <code>bootloader</code> to <code>shell (desktop)</code>,<code>browser</code>, <code>editor</code> and individual applications if possible. This is how I like it. Tell me if you like it.</p>
<p>Also please give me recommendations if you have any.</p>
<p><em>See you on the next one!</em></p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>OverlayFS for RedoxOS</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;redox-overlayfs&#x2F;"/>
        <updated>2026-03-31T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;redox-overlayfs&#x2F;</id>
        <content type="html"><![CDATA[
          <h2 id="along-with-the-importance-of-mentorship-and-respect-for-low-level-developers">Along with the Importance of Mentorship and Respect for Low Level Developers</h2>
<p>When we were searching for a project to do for our final year submission, I came across a feature request on RedoxOS asking for OverlayFS support. I had kept it as something "I wish I could do". When pitching our ideas for the project, I also said that I wish we could do something like this, to my teammate <a rel="external" href="https://github.com/faultypointer">faultypointer</a>. Since, he was interested in working on low level too while the whole world was doing AI projects we decided that we would do it. Afterall, when we take on the project we must complete it anyhow, otherwise we risk getting the degree.</p>
<img src="https://scientiac.space/images/redox_overlayfs/redoxos.png" style="padding:0.25rem;border-radius: 0.5rem;">
<center>
<p><em>RedoxOS GUI running Cosmic Applications</em></p>
</center>
<p>And, so it began. We proposed the idea to the faculty and they accepted, but they said that it must be a completely original work, without using any existing code written by RedoxOS contributors. We then started the research on how the OS was architectured and how we could implement something like OverlayFS.</p>
<blockquote class="note">
	<p class="alert-title">Note</p>
	<p>Overlay filesystems are pseudo-filesystems which combines multiple filesystems or
multiple directories from same filesystems into one, resulting in a single directory
structure that contains underlying files and sub-directories from all sources.</p>
<img src="https://scientiac.space/images/redox_overlayfs/overlayfs.png" style="padding:0.25rem;border-radius: 1rem;">
<center>
<p>High Level representation of OverlayFS</p>
</center>
</blockquote>
<h2 id="the-first-contact">The First Contact</h2>
<p>When we contacted the people making RedoxOS on their matrix server, we found out that someone had started the preliminary work for OverlayFS. We then contacted him and said that we wanted to help make the thing. He was positive about it and said that though he couldn't mentor us for it, he would leave <a rel="external" href="https://gitlab.redox-os.org/redox-os/redox/-/issues/1568">some notes</a> for us to better kickstart the project. We took the notes and started the preliminary work on the alien codebase of RedoxOS.</p>
<h2 id="the-struggle-begins">The Struggle Begins</h2>
<p>It was a completely new territory for us.
Though we had some theoretical knowledge on Operating System and their Architecture from our syllabus, our practical experience for OS development was closer to none.
Reading the <a rel="external" href="https://doc.redox-os.org/book/">RedoxOS Book</a> was fun though, I got to learn about the various components of RedoxOS and what their philosophy was.
Though I read about RedoxOS in detail, I hadn't made up my mind on where I would start developing the OverlayFS.</p>
<p>First few months, taking about the project and having in my mind that it's a low level project I wanted to do was like a dream.
I was excited and so was faultypointer. We talked about the architecture and discussed the plans and theory of how OverlayFS worked, we gathered resources and references. Those were exciting days.</p>
<h2 id="the-build-system">The Build System</h2>
<p>It had been very long since we have just studied the theory and we hadn't implemented anything. Until that time we managed to understand the build pipeline and how the source code of RedoxOS was structured. We were using NixOS at the time so, we had to jump to a more normal Linux distribution to make out life easier to work with building RedoxOS.
I don't even know how many times we built RedoxOS from scratch deleting containers and reinstalling them again and again and again.</p>
<p>Another thing we realized while building RedoxOS is that <strong>it wasn't self-hosted</strong> yet. Meaning, you couldn't build programs for RedoxOS from inside RedoxOS. We knew from <a rel="external" href="https://gitlab.redox-os.org/matlik">James Matlik's</a> Implementation Proposal that we had to make a delegate pattern in order to make it on Linux and then integrate it with RedoxOS. I wasn't familier to delegate patterns so, I was still learning about it.</p>
<h2 id="the-initial-implementation">The Initial Implementation</h2>
<p>While I was busy wasting time asking AI to guide me to start the project, faultypointer had already written the preliminary filesystem struct and made the delegate struct to prototype it on Linux.
While I hadn't done much, I was much relieved that actual work on the project was finally started. Finally we <em>(by we mean just faultypointer)</em> had started work on the project.</p>
<p>In the first implementation, a delegate <code>FileSystem</code> struct was written that would do the things the overlay scheme would do in the future. What it contained was:</p>
<ul>
<li>Functions for <code>open</code>, <code>read</code>, <code>write</code>, <code>close</code>, <code>unlink</code>, <code>readdir</code>.</li>
<li>Helper functions for copying up files from lower to upper layer, checking for whiteout files and creating whiteout files.</li>
<li>Some tests for those functions to verify that they were working as expected.</li>
</ul>
<h2 id="scheming-with-schememut-then-schemesync">Scheming with SchemeMut then SchemeSync</h2>
<p>After the <code>SchemeMut</code> for OverlayFS was implemented and the <code>main</code> scheme function was implemented we could test the workings of initial syscall implementations on RedoxOS as well as on Linux. But, <code>SchemeMut</code> was not what the RedoxOS team was using for other schemes. Later, the <code>SchemeMut</code> implementation was replaced with <code>SchemeSync</code> which finally brought the project to a fairly usable state.</p>
<h2 id="the-great-big-purge">The Great Big Purge</h2>
<p>After the verification that the implementation worked in practice, the initial structure of source code wasn't fit for a more involved implementation. The structure was reimplemented using rust's <code>struct</code> and <code>impl</code> syntax. All that was left was to implement each individual filesystem syscall that the scheme required to work with the OverlayFS implementation logic.</p>
<p>Starting to write syscalls, the <code>rust</code> libraries soon didn't cut it. Then <code>libc</code> had to be used.<code>open</code> was implemented. The most visual part of the whole project was done by the <code>getdents</code> syscall, which listed the directory entries that showed the logical merged/overlay layer of the OverlayFS, hence, that had to be implemented next.</p>
<blockquote class="important">
	<p class="alert-title">Important</p>
	<p>Due to RedoxOS being a microkernel based Operating System, it's own filesystem and our OverlayFS was outside the kernel space. The architecture of the OverlayFS can be visualized as follows:</p>
<img src="https://scientiac.space/images/redox_overlayfs/architecture.png" style="padding:0.25rem;border-radius: 1rem;">
<center>
<p>Architecture of the filesystem within RedoxOS</p>
</center>
</blockquote>
<h2 id="system-calls">System Calls</h2>
<p>After everything was set up, all that remained was implementing more and more syscalls untill each one was implemented. The implemented syscalls in order are as follows:</p>
<ol>
<li><code>open</code> - Resolves path checking upper then lower layer, respects whiteouts, and forwards UID/GID for permission checks.</li>
<li><code>getdents</code> - Merges directory entries from upper then lower layer, excluding shadowed names and honoring opaque directories; maintains opaque offsets.</li>
<li><code>read</code> - Reads from whichever layer the file was resolved from at open time.</li>
<li><code>write</code> - Performs copy-on-write: copies lower-layer file to upper layer on first write, then writes to the upper copy.</li>
<li><code>fpath</code> - Retrieves the path for a file descriptor via the scheme interface.</li>
<li><code>unlink</code> - Removes upper-layer files directly; for lower-layer files creates a whiteout in the upper layer.</li>
<li><code>rmdir</code> - Validates directory emptiness and removes directories, creating upper-layer markers if the directory originated from lower layer.</li>
<li><code>fchown</code> - Triggers copy-up for lower-layer files, then applies ownership change to the upper-layer copy.</li>
<li><code>fchmod</code> - Triggers copy-up for lower-layer files, then applies permission change to the upper-layer copy.</li>
<li><code>fsize</code> - Returns size metadata from the layer where the file resides (upper or lower).</li>
<li><code>fcntl</code> - Manipulates file descriptor flags through the scheme interface.</li>
<li><code>fvent</code> - Registers events for asynchronous I/O through the scheme interface.</li>
<li><code>flink</code> - Creates hard links only within the upper layer; linking to a lower-layer file triggers copy-up first.</li>
<li><code>ftruncate</code> - Performs copy-on-write if needed, then truncates the upper-layer copy.</li>
<li><code>statvfs</code> - Aggregates filesystem statistics across both layers to report combined capacity and inode usage.</li>
<li><code>futimens</code> - Performs copy-on-write if needed, then updates timestamps on the upper-layer copy.</li>
<li><code>dup</code> - Duplicates file descriptors, preserving the resolved-layer behavior of the underlying handle.</li>
</ol>
<h2 id="proof-that-syscalls-for-overlayfs-work-ed">Proof that Syscalls for OverlayFS Work(ed).</h2>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/redox_overlayfs/getdents.png" style="width: 19rem; padding:0.25rem;border-radius: 0.5rem;">
  <img src="https://scientiac.space/images/redox_overlayfs/copyup.png" style="width: 19rem; padding:0.25rem;border-radius: 0.5rem;">
</div>
<div style="text-align: center">
<p><em>Copy-Up in Terminal UI</em></p>
</div>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/redox_overlayfs/graphical-getdents.png" style="width: 19rem; padding:0.25rem;border-radius: 0.5rem;">
  <img src="https://scientiac.space/images/redox_overlayfs/graphical-copyup.png" style="width: 19rem; padding:0.25rem;border-radius: 0.5rem;">
</div>
<div style="text-align: center">
<p><em>Copy-Up in Graphical UI</em></p>
</div>
<h2 id="change-is-inevitable">Change is Inevitable</h2>
<p>Since RedoxOS is a very unstable operating system, which is heavily in development, during the development of the OverlayFS we repeatedly rewrote parts to keep up with upstream changes.
Near the project submission a fresh pull from RedoxOS introduced mismatches with our overlay code: path handling and validation required fixes, some Scheme APIs (<code>SchemeSync</code> and related types) had their methods changed so we needed to implement new functions.
Also, the way Scheme was started changed (we later found root-start resembled our old approach, but the new init-system startup only allowed a single overlay instance). During this we also came across a runtime freeze where a std library function appeared to hang with no error or panic which was unlikely in upstream CI, so we suspected a deadlock in our code.</p>
<p>So, we decided to limit the implementation on the older commit and settled to showing what already worked on our system in our final project demonstration. This means we won't able to contribute the implementation upstream, and to be very honest we are very insecure <em>(almost unsatisfied)</em> about <a rel="external" href="https://gitlab.com/carboxide/overlayfs">our current implementation</a> which is one more excuse for us to procrastinate now that the defence is over.</p>
<h2 id="mentors-and-developers">Mentors and Developers</h2>
<p>Though everything I contributed to the project was mentored to me by faultypointer, he didn't have anyone who mentored him.
I admire faultypointer for his dedication to the craft and his knowledge and flexibility to understand and work on an alien codebase.
I don't even know if I had taken up the project and faultypointer wasn't on our team that we could even make an implementation of OverlayFS that actually worked.</p>
<p>Near the final defence I saw exhaustion and burnout on faulty's face that I had never seen before, I wasn't knowledged/skilled enough to help him either.
That moment was the time I <em>(maybe we both)</em> realized the importance of mentor and mentorship. After all we are just students learning in this field.</p>
<p>Though I admire low level developers and I try to dabble on it, but, I also like visuals and graphics and something that looks presentable.
The amount of work that faultypointer has put on this project compared to me is stellar, and of that work the final result being something so simple that can be explained in 3 sentences is very underwhelming <em>(one might say anticlimactic)</em>.
This project has immensely increased my respect towards the low-level developers and most importantly faultypointer <code>(Sudesh)</code>.</p>
<h2 id="end-of-an-era">End of an Era</h2>
<p>This being a final year project of my bachelor degree also makes me very sentimental about it. Hopefully, we keep in touch even after we part ways to our respective future.</p>
<p>Love you brother! I'll find you from under the ocean and over the sky if you don't keep in touch. This is very much a warning as it is a request.</p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>E-reader First Android</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;e-reader-android&#x2F;"/>
        <updated>2025-11-18T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;e-reader-android&#x2F;</id>
        <content type="html"><![CDATA[
          <p><em>This time it is a really simple thing. But, I wanted to document it anyway.</em></p>
<h3 id="why">Why?</h3>
<p>I am constantly in a quest of making things better for the sake of reducing my media addiction.
The only social media with "status updates" that I use is <a rel="external" href="https://polymaths.social/@iac">polymaths.social</a> a <code>gotosocial</code>(Fediverse) instance.
I have stopped using Facebook and Instagram a while back and I block the shorts section of my YouTube.</p>
<p>Having done that, the addiction has shifted from a whole range of social media to just watching YouTube videos till the end of time.
So, I decided to make YouTube only show what I search with no home page or even the subscription page. <em>(Though, I can still access them with a toggle.)</em>
I also don't want to consume YouTube on my phone. And I want to read books instead of consuming visual media.</p>
<h3 id="so">So?</h3>
<p>For a while now my YouTube recommendations were full of e-readers, dumb phones and modding kindles.
I did like the idea and checked the price of those devices (Classic Consumerism).
Since, they are manufactured in small quantities, they are very expensive for the specs they offer.
And most of them are not available in my region.
But, my stubbornness, or maybe my addiction is so bad that I need to have what I want and if I don't I just can't do any other work properly.</p>
<p>Then I thought, I cannot convert something dumb to something advanced by itself but the reverse is possible.
I remembered a device called <a rel="external" href="https://shop.boox.com/products/palma">BOOX Palma</a> and since it is an android device I thought I could recreate it with my own phone that I already have.
From the <a rel="external" href="https://www.youtube.com/watch?v=Qtk7ERwlIAk">kindle modding video</a> I also realised that <code>KOReader</code> is not just an old, weirdly made e-book reader app.</p>
<p><em>So, I decided to base the entire personality of my phone to the <code>KOReader</code> app.</em></p>
<h3 id="preparing-android">Preparing Android</h3>
<p>Since I use a <code>custom ROM</code> it is much easier for me to customize my device to a greater potential than vanilla android that google offers. I use <a rel="external" href="https://projectinfinity-x.com/">Project Infinity X</a>.</p>
<ol>
<li>I wanted the <code>B&amp;W</code> monochromatic look of e-readers, so, the first thing I did is set a <a rel="external" href="https://wallpapercave.com/wp/wp6681156.jpg">white background</a> as my wallpaper.</li>
<li>The <code>Monet color</code> is set to be monochromatic.</li>
<li>In <code>Accessibility &gt; Color and motion &gt; Use color correction &gt; Grayscale</code> is turned on. (I just disable this via a quick setting toggle when I need colours.)</li>
<li>In <code>Accessibility &gt; Color and motion &gt; Remove animations</code> is turned on.</li>
<li>In <code>Display &gt; Color &gt; Night Light</code> is turned on.</li>
<li>Dark Theme is disabled.</li>
<li><code>Display &gt; Display cutout</code> is set to <code>notchbarkiller</code>. (<em>This setting is generally in <code>Developer Options</code> if not in <code>Display</code> but, the exact name: <code>notchbarkiller</code> may not be present.</em>)</li>
<li>Additionally, a <code>Reading Mode</code> can be made with the features like: disabling notifications and setting the screen as greyscale. But, I wanted to control those settings individually.</li>
</ol>
<h3 id="installing-the-launcher">Installing the Launcher</h3>
<ol>
<li>I decided to install <a rel="external" href="https://github.com/gezimos/inkOS/">InkOS</a> as my launcher because it adds on to the e-reader aesthetic.</li>
<li>I removed all the shortcuts of the home screen and set <code>Books</code> as the only shortcut there.</li>
<li>From the app drawer I changed the name of the apps to their generic names and hid most of the unused apps.</li>
<li>Configured <code>swipe left</code> gesture to <code>KOReader</code> and <code>swipe right</code> to <code>App Drawer</code>.</li>
<li>Finally I set <code>InkOs</code> as my default launcher.</li>
</ol>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/e-reader-android/homescreen.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/e-reader-android/lockscreen.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<div style="text-align: center">
<p><em><code>Home Screen</code> with a single books shortcut and <code>Lock Screen</code> with a big digital clock.</em></p>
</div>
<h3 id="setting-up-koreader">Setting Up <code>KOReader</code></h3>
<ol>
<li>Installed <code>KOReader</code> <a rel="external" href="https://github.com/koreader/koreader">from GitHub</a> and set it to <code>Start with: last file</code>.</li>
<li>Disabled <code>Cover Browser Plugin</code> and installed <a rel="external" href="https://github.com/joshuacant/ProjectTitle">Project: Title</a>.</li>
</ol>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/e-reader-android/koreader.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/e-reader-android/app-drawer.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<div style="text-align: center">
<p><em><code>KOReader</code> with <code>The Shape of Design</code> (Swiping Left) and the <code>App Drawer</code> (Swiping Right).</em></p>
</div>
<p><em>In <code>KOReader</code> individual books have their individual settings but once everything is set up, scaled and aligned properly for the book that you want to read, only reading it will be the remaining task.</em></p>
<h3 id="final-touches">Final Touches</h3>
<p>The phone is normally is in <code>DND</code> mode, but when it is not, I have disabled the notifications of almost every app except signal.
I have installed <a rel="external" href="https://ublockorigin.com/"><code>uBlock Origin</code></a> on <code>firefox</code> and have hidden different UI elements that I don't want to see e.g. YouTube Shorts.
The quick settings panel is now cleared and only the very essential settings like <code>WIFI</code>, modes and colour correction toggles are there.</p>
<p>All in all, I have made reading books the easiest task on the phone and added friction to everything else by locking the apps so I have some time to realise what I actually want to do.</p>
<p><em>I aim to read more books with this setup. Wish me luck!</em></p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>Almost splitting a Keyboard in Half</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;diy-split-keyboard&#x2F;"/>
        <updated>2025-09-30T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;diy-split-keyboard&#x2F;</id>
        <content type="html"><![CDATA[
          <p><em>Yeah! I keep doing stupid things.</em></p>
<p>The idea of remapping keys isn't new, be it for typing in a different language or to make the escape key more ergonomic for vim users.
I mapped my <kbd>escape</kbd> key to <kbd>`</kbd> and <kbd>caps-lock</kbd> key to <kbd>escape</kbd> when I bought my 65% keyboard.
It was because I had to use some weird function keybind just to type a <kbd>~</kbd>. Then I realised my laptop key got remapped too, but I
just went ahead with it. That is when I used this software called <a rel="external" href="https://github.com/rvaiya/keyd">keyd</a>.</p>
<p>Fast forward to today and rewind to a month back, I was bored out of my mind and was fidgeting with my keyboard when I popped one of the keys
out of it. And right then I looked at the keys and wondered if I could make a minimal split keyboard out of it using <code>keyd</code>.</p>
<p>I had watched many videos about split keyboards, and one was even in my <a rel="external" href="https://boardsource.xyz/products/unicorne-lp-aluminum-corne-case">wish</a>list for a long time. So, I wondered if I was gonna invest in a keyboard that is going to shape my typing muscle memory, I should at least give it a try beforehand.</p>
<p>Now that I started writing about it, I don't think it was that big a deal. It only took too much of my time to configure it. First I tried the <code>ferris sweep</code> layout which was too much of a sacrifice, then I tried <code>corne</code> and finally decided on the <code>5 column corne</code>.</p>
<h3 id="before-operation">Before Operation:</h3>
<p><img src="https://scientiac.space/images/diy-split-keyboard/before.png" alt="keyboard-before" /></p>
<h3 id="after-operation">After Operation:</h3>
<p><img src="https://scientiac.space/images/diy-split-keyboard/after.jpeg" alt="keyboard-after" /></p>
<details>
<summary>Here is the <code>keyd</code> configuration:</summary>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="yaml"><span class="giallo-l"><span style="color: #928374;font-style: italic;"># corne-36.conf</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># keyboard id to enable [wired, bluetooth and 2.4ghz]</span></span>
<span class="giallo-l"><span style="color: #A89984;">[</span><span style="color: #B8BB26;">ids</span><span style="color: #A89984;">]</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">5566:0008</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">3151:6001</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">1235:aa22</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #A89984;">[</span><span style="color: #B8BB26;">main</span><span style="color: #A89984;">]</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 1</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;q&quot; to write q</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">1 = q</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;w&quot; to write w</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">2 = w</span><span>  </span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;e&quot; to write e</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">3 = e</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;r&quot; to write r</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">4 = r</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;t&quot; to write t</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">5 = t</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 2</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;a&quot; to write a</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">q = a</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;s&quot; to write s</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">w = s</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;d&quot; to write d</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">e = d</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;f&quot; to write f</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">r = f</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;g&quot; to write g</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">t = g</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 3</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;z&quot; to write z</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">a = z</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;x&quot; to write x</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">s = x</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;c&quot; to write c</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">d = c</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;v&quot; to write v</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f = v</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;b&quot; to write b</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">g = b</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># BOTTOM ROW - Special keys</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;down-arrow&quot; for leftmeta, hold &quot;down-arrow&quot; for meta</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">x = overload(meta, leftmeta)</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;alt&quot; for space, hold &quot;alt&quot; for navigation</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">c = overload(navigation, space)</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;up-arrow&quot; for esc, hold &quot;up-arrow&quot; for control</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">v = overload(control, esc)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 1</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;y&quot; to write y</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">8 = y</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;u&quot; to write u</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">9 = u</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;i&quot; to write i</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">0 = i</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;o&quot; to write o</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">minus = o</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;p&quot; to write p</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">equal = p</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 2</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;h&quot; to write h</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">u = h</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;j&quot; to write j</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">i = j</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;k&quot; to write k</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">o = k</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;l&quot; to write l</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">p = l</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;;&quot; to write semicolon</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">leftbrace = semicolon</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 3</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;n&quot; to write n</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">j = n</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;m&quot; to write m</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">k = m</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;,&quot; to write comma</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">l = comma</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;.&quot; to write dot, hold &quot;.&quot; for control</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">semicolon = dot</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;/&quot; to write slash</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">apostrophe = slash</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># BOTTOM ROW - Special keys</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;-&gt;&quot; for enter, hold &quot;-&gt;&quot; for alt</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">m = overload(alt, enter)</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;del&quot; for backspace, hold &quot;del&quot; for symbols</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">comma = overload(symbols, backspace)</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Press &quot;&lt;-&quot; for tab, hold &quot;&lt;-&quot; for shift</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">dot = overload(shift, tab)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ALL UNUSED KEYS FROM THE KEYBOARD</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">tab = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">capslock = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">backspace = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">backslash = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">rightbrace = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">esc = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">enter = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">6 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">7 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">y = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">leftshift = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">z = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">b = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">h = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">slash = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">rightshift = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">leftcontrol = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">leftalt = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">space = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">rightalt = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">rightcontrol = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">leftmeta = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">rightmeta = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">grave = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f1 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f2 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f3 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f4 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f5 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f6 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f7 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f8 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f9 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f10 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f11 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f12 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">up = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">down = noop</span><span>  </span></span>
<span class="giallo-l"><span style="color: #B8BB26;">left = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">right = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">home = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">end = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">pageup = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">pagedown = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">insert = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">delete = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp0 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp1 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp2 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp3 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp4 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp5 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp6 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp7 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp8 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kp9 = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kpdot = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kpenter = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kpplus = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kpminus = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kpasterisk = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">kpslash = noop</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">#  [ 1:q ] [ 2:w ] [ 3:e ] [ 4:r ] [ 5:t ]                    [ 8:y ] [ 9:u ] [ 0:i ] [ -:o ] [ =:p ]</span></span>
<span class="giallo-l"><span>#   </span><span style="color: #A89984;">[</span><span style="color: #B8BB26;"> q:a</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> w:s</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> e:d</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> r:f</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> t:g</span><span style="color: #A89984;"> ]              	[</span><span style="color: #B8BB26;"> i:h</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> o:j</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> p:k</span><span style="color: #A89984;"> ] [ [</span><span style="color: #B8BB26;">:l</span><span style="color: #A89984;"> ] [ ]</span><span style="color: #B8BB26;">:;</span><span style="color: #A89984;"> ]</span></span>
<span class="giallo-l"><span>#    </span><span style="color: #A89984;">[</span><span style="color: #B8BB26;"> a:z</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> s:x</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> d:c</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> f:v</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> g:b</span><span style="color: #A89984;"> ]          	     [</span><span style="color: #B8BB26;"> j:n</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> k:m</span><span style="color: #A89984;"> ] [</span><span style="color: #B8BB26;"> l</span><span style="color: #A89984;">:, ] [</span><span style="color: #B8BB26;"> ;:.</span><span style="color: #A89984;"> ] [ &#39;</span><span style="color: #B8BB26;">:/ ]</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">#          [ x:meta ] [ c:nav/space ] [ v:ctrl/esc ]    	[ m:alt/return ] [ ,:sym/backspace ] [ .:shift/tab ]</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #B8BB26;"># ------------------------------------------ #</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># ------------------------------------------ #</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #B8BB26;">[symbols]</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #B8BB26;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># ROW 1</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;q&quot; for &quot;!&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">1 = S-1</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;w&quot; for &quot;@&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">2 = S-2</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;e&quot; for &quot;#&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">3 = S-3</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;r&quot; for &quot;$&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">4 = S-4</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;t&quot; for &quot;%&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">5 = S-5</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #B8BB26;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #B8BB26;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># ROW 2</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;a&quot; for &quot;1&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">q = 1</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;s&quot; for &quot;2&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">w = 2</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;d&quot; for &quot;3&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">e = 3</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;f&quot; for &quot;4&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">r = 4</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;g&quot; for &quot;5&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">t = 5</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #B8BB26;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #B8BB26;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># ROW 3</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">capslock = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;z&quot; for &quot;6&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">a = 6</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;x&quot; for &quot;7&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">s = 7</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;c&quot; for &quot;8&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">d = 8</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;v&quot; for &quot;9&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f = 9</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># Hold &quot;del&quot; and press &quot;b&quot; for &quot;0&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">g = 0</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #B8BB26;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #B8BB26;"># BOTTOM ROW - Special keys</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">x = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">c = backslash</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">v = </span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 1</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;y&quot; for &quot;^&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">8 = S-6</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;u&quot; for &quot;&amp;&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">9 = S-7</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;i&quot; for &quot;*&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">0 = S-8</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;o&quot; for &quot;(&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">minus = S-9</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;p&quot; for &quot;)&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">equal = S-0</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 2</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;h&quot; for &quot;_&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">u = minus</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;j&quot; for &quot;=&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">i = equal</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;k&quot; for &quot;`&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">o = grave</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;l&quot; for &quot;[&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">p = leftbrace</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;;&quot; for &quot;]&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">leftbrace = rightbrace</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 3</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;n&quot; for &quot;_&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">j = S-minus</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;m&quot; for &quot;+&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">k = S-equal</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;,&quot; for &quot;~&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">l = S-grave</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;.&quot; for &quot;{&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">semicolon = S-leftbrace</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;del&quot; and press &quot;/&quot; for &quot;}&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">apostrophe = S-rightbrace</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># BOTTOM ROW - Special keys</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">m = backspace</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">comma = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">dot = rightshift</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #A89984;">[</span><span style="color: #B8BB26;">navigation</span><span style="color: #A89984;">]</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 1</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;q&quot; for &quot;f1&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">1 = f1</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;w&quot; for &quot;f2&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">2 = f2</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;e&quot; for &quot;f3&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">3 = f3</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;r&quot; for &quot;f4&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">4 = f4</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;t&quot; for &quot;f5&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">5 = f5</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 2</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;a&quot; for &quot;f6&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">q = f6</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;s&quot; for &quot;f7&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">w = f7</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;d&quot; for &quot;f8&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">e = f8</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;f&quot; for &quot;f9&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">r = f9</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;g&quot; for &quot;f10&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">t = f10</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># LEFT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 3</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;z&quot; for &quot;f11&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">a = f11</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;x&quot; for &quot;f12&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">s = f12</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">d = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">f = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">g = noop</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 1</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">8 = noop</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;u&quot; for &quot;tab&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">9 = tab</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;i&quot; for &quot;pageup&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">0 = pageup</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;o&quot; for &quot;pagedown&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">minus = pagedown</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;p&quot; for &quot;print&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">equal = print</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 2</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;h&quot; for &quot;left&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">u = left</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;j&quot; for &quot;down&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">i = down</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;k&quot; for &quot;up&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">o = up</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;l&quot; for &quot;right&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">p = right</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">leftbrace = noop</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ROW 3</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;n&quot; for &quot;home&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">j = home</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># Hold &quot;alt&quot; and press &quot;m&quot; for &quot;end&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">k = end</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">l = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">semicolon = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">apostrophe = noop</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># ------------------------------------------ #</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># RIGHT HAND</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># BOTTOM ROW - Special keys</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">m = noop</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">comma = delete</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">dot = noop</span></span></code></pre></details>
<p>I even vibe coded a <a href="https://scientiac.space/images/diy-split-keyboard/corne-36.html">layout visualiser</a> to remember the keybinds.</p>
<h3 id="happy-ending">Happy Ending?</h3>
<p>Well, I could just lie and say that I have increased my productivity by 200% but, that is far from the reality. After I had fun changing the layout, I am just happy with the comfort of my laptop keyboard and have not used the split keyboard at all. I do use it sometimes but, I am so slow on it that I immidiately fall back to the laptop. It is obvious, it takes time to learn a split layout but, I am just not investing my time on it. Nevertheless, <strong>it was so damn fun while I configured it</strong>.</p>
<p>Projects like <code>keyd</code> just keep the spirit of Linux alive.</p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>Static Site Webmentions</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;webmentions&#x2F;"/>
        <updated>2025-08-31T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;webmentions&#x2F;</id>
        <content type="html"><![CDATA[
          <p>I had set up Webmentions on my static site <a href="https://scientiac.space/syndications/posse-2024-11-05/">a while back</a>. It was because I really like the concept of a completely custom yet static social media where it's not instant but it's regular communication. But, the drawback of any kind of unique and DIY technology is not having people that actually use it.</p>
<p>Ironically, after the setup, I only have received Webmentions from myself during testing (<em>I am not counting the mastodon likes that propagated through <a rel="external" href="https://fed.brid.gy/web/scientiac.space">Bridgy Fed</a>)</em>. I am still sceptical about Bridgy Fed because It isn't what I wanted Webmentions to be, I didn't want any connections to a social media but I wanted to test the workings so I connected it.</p>
<h2 id="how-i-do-it">How I Do It</h2>
<p>My blog is a static site and being static comes with the cost of not being able to continuously listen to incoming messages. So, Webmentions don't really work on a static site. At least that's what I thought at first, then I found out about <a rel="external" href="https://webmention.io/">webmention.io</a>.</p>
<p>It's sort of like a retrofitted static site to support Webmentions.</p>
<h3 id="components">Components</h3>
<ul>
<li>A Static Site Generator <a rel="external" href="https://www.getzola.org/">www.getzola.org</a></li>
<li>Indieweb Compatibility <a rel="external" href="https://indiewebify.me/">indiewebify.me</a></li>
<li>Send webmentions <a rel="external" href="https://webmention.app/">webmention.app</a></li>
<li>Receive Webmentions <a rel="external" href="https://webmention.io/">webmention.io</a></li>
<li>Render Webmentions <a rel="external" href="https://keats.github.io/tera/">keats.github.io/tera</a></li>
<li>Runner <a rel="external" href="https://docs.github.com/en/actions">GitHub actions</a></li>
</ul>
<h4 id="a-static-site-generator">A Static Site Generator</h4>
<p>I am using <code>zola</code> as my static site generator and I love it. The comfort of just writing in <code>markdown</code> and letting <code>zola</code> do the heavy lifting to generate feeds is awesome. Generating an Atom/RSS feed is a must. This is needed by webmention.app to send webmentions by reading all your posts.</p>
<h4 id="indieweb-compatibility">Indieweb Compatibility</h4>
<p>To make an Indieweb compatible static site you need to pass these tests from <a rel="external" href="https://indiewebify.me/">indiewebify.me</a>.</p>
<ol>
<li>Web Sign In - This helps you sign in to indieweb services with your domain. <em>You must have your own registered domain name.</em></li>
<li><code>h-card</code> and <code>h-entry</code> classes on homepage as well as on the "post" page.</li>
<li>Ability to send Webmentions.</li>
</ol>
<h4 id="sending-webmentions">Sending Webmentions</h4>
<p>I use my generated Atom feed and webmention.app <a rel="external" href="https://webmention.app/docs#using-the-command-line">CLI</a> to send Webmentions.
It is as simple as running:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"><span style="color: #FABD2F;">npx</span><span style="color: #B8BB26;"> webmention https://scientiac.space/atom.xml</span><span style="color: #D3869B;"> --limit=0 --send</span></span></code></pre><h4 id="receiving-webmentions">Receiving Webmentions</h4>
<p>To receive Webmentions you need a perpetual listening server and the service is provided by <a rel="external" href="https://webmention.io/">webmention.io</a>.</p>
<ol>
<li>Sign into webmention.io with your domain. It will use <a rel="external" href="https://indielogin.com/">indielogin.com</a>. This requires you to have at least an email address on your h-card.</li>
<li>Go to <code>sites</code> and in the table click on <code>Get Setup Code</code> which will give you a tag to put on your HTML template header.</li>
<li>Test that you actually can receive Webmentions by mentioning yourself in a site and running the above command. It should show up in the dashboard of <code>webmention.io</code>.</li>
</ol>
<h4 id="render-webmentions">Render Webmentions</h4>
<p>You can now fetch the json feed of the Webmentions you have received in webmention.io using the following command and replacing the <code>${WEBMENTION_TOKEN}</code> with your own token.</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"><span style="color: #FABD2F;">curl</span><span style="color: #D3869B;"> -s</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">https://webmention.io/api/mentions.json?token=</span><span style="color: #A89984;">${</span><span style="color: #83A598;">WEBMENTION_TOKEN</span><span style="color: #A89984;">}&quot;</span><span style="color: #D3869B;"> -o</span><span style="color: #B8BB26;"> webmentions.json</span></span></code></pre>
<p>This json file can be used to render the Webmentions on your website using your static site generator's feature to read json files.</p>
<p>I made and activity page in zola where all the webmention activities are listed.</p>
<details>
<summary>Zola Template HTML</summary>
<p>This is located at <code>templates/activity.html</code> and used at <code>content/activity/_index.md</code></p>
<p><code>templates/activity.html</code></p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="html"><span class="giallo-l"><span>{% extends &quot;base.html&quot; %}</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>{% block content %}</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #83A598;">&lt;</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #FABD2F;"> class</span><span style="color: #A89984;">=</span><span style="color: #B8BB26;">section</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>{% set data = load_data(path=&quot;webmentions.json&quot;, format=&quot;json&quot;) %}</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #83A598;">&lt;</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #FABD2F;"> class</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">activity-box</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span>{% for links in data.links %}</span></span>
<span class="giallo-l"><span>    {% set trimmed_path = links.target | trim_start_matches(pat=&quot;https://&quot; ~ config.extra.url ~ &quot;/&quot;) | trim_end_matches(pat=&quot;/&quot;) %}</span></span>
<span class="giallo-l"><span>    {% set relative_path = trimmed_path ~ &quot;.md&quot; %}</span></span>
<span class="giallo-l"><span>    {% set target_page = get_page(path=relative_path) %}</span></span>
<span class="giallo-l"><span>    {% if not links.source is starting_with(&quot;https://&quot; ~ config.extra.url) %}</span></span>
<span class="giallo-l"><span>        {% if links.activity.type == &quot;like&quot; %}</span></span>
<span class="giallo-l"><span style="color: #83A598;">            &lt;</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #FABD2F;"> class</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">mention-profile like</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span style="color: #83A598;">                &lt;</span><span style="color: #8EC07C;font-weight: bold;">code</span><span style="color: #83A598;">&gt;&lt;</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #FABD2F;"> href</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">{{ links.source }}</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span><span>{{ links.data.author.name }}</span><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #83A598;">&gt;</span><span> liked </span><span style="color: #83A598;">&lt;</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #FABD2F;"> href</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">{{ links.target }}</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span><span>{{ target_page.title }}</span><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #83A598;">&gt;&lt;/</span><span style="color: #8EC07C;font-weight: bold;">code</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span style="color: #83A598;">            &lt;/</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span>        {% endif %}</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>        {% if links.activity.type == &quot;link&quot; %}</span></span>
<span class="giallo-l"><span style="color: #83A598;">            &lt;</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #FABD2F;"> class</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">mention-profile link</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span style="color: #83A598;">                &lt;</span><span style="color: #8EC07C;font-weight: bold;">code</span><span style="color: #83A598;">&gt;&lt;</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #FABD2F;"> href</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">{{ links.source }}</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span><span>{{ links.data.author.name }}</span><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #83A598;">&gt;</span><span> mentioned </span><span style="color: #83A598;">&lt;</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #FABD2F;"> href</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">{{ links.target }}</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span><span>{{ target_page.title }}</span><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #83A598;">&gt;&lt;/</span><span style="color: #8EC07C;font-weight: bold;">code</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span style="color: #83A598;">            &lt;/</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span>        {% endif %}</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>        {% if links.activity.type == &quot;reply&quot; %}</span></span>
<span class="giallo-l"><span style="color: #83A598;">            &lt;</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #FABD2F;"> class</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">mention-profile reply</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span style="color: #83A598;">                &lt;</span><span style="color: #8EC07C;font-weight: bold;">code</span><span style="color: #83A598;">&gt;&lt;</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #FABD2F;"> href</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">{{ links.source }}</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span><span>{{ links.data.author.name }}</span><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #83A598;">&gt;</span><span> replied to </span><span style="color: #83A598;">&lt;</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #FABD2F;"> href</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">{{ links.target }}</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span><span>{{ target_page.title }}</span><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #83A598;">&gt;&lt;/</span><span style="color: #8EC07C;font-weight: bold;">code</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span style="color: #83A598;">            &lt;/</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"><span>        {% endif %}</span></span>
<span class="giallo-l"><span>    {% endif %}</span></span>
<span class="giallo-l"><span>{% endfor %}</span></span>
<span class="giallo-l"><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">div</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>{% endblock content %}</span></span></code></pre>
<p><code>content/activity/_index.md</code></p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="markdown"><span class="giallo-l"><span>+++</span></span>
<span class="giallo-l"><span>template = &quot;activity.html&quot;</span></span>
<span class="giallo-l"><span>+++</span></span></code></pre></details>
<p>Webmentions are rendered by zola utilizing the <code>load_data</code> function of tera templating engine. The fetched <code>webmention.json</code> file is parsed and formatted. [<em>Can be seen in <code>activity.html</code> in the above template.</em>]</p>
<h4 id="runner">Runner</h4>
<p>To rebuild the site by fetching new Webmentions we will need a runner that does the process repeatedly in said amount of time. This is where GitHub actions come in. I have three workflows <code>send-webmentions.yaml</code>, <code>zola.yml</code> and <code>fetch-webmentions.yaml</code> which as the name says, sends Webmentions from the site, builds the site using zola and fetches received Webmentions from <code>webmention.io</code>.</p>
<p>For fetching I have saved my webmention.app api key as a secret in GitHub and use that in the workflow file.</p>
<p>First put your token form webmention.io in <code>settings &gt; security &gt; secrets and variables &gt; actions &gt; new repository secret</code> of your GitHub repo with the name <code>WEBMENTION_TOKEN</code>.</p>
<p>Then, the workflow files should be put in place.</p>
<details>
<summary>Workflow Files</summary>
<p>This is located at <code>.github/workflows/</code> from the root of your repository.</p>
<p>First workflow fetches new mentions every 30 minutes.<br />
<code>fetch-webmentions.yml</code></p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="yaml"><span class="giallo-l"><span style="color: #8EC07C;">name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Fetch Webmentions</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #D3869B;">on</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">  push</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    branches</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #B8BB26;"> main</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">  schedule</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #A89984;">    -</span><span style="color: #8EC07C;"> cron</span><span style="color: #A89984;">: &#39;</span><span style="color: #B8BB26;">*/30 * * * *</span><span style="color: #A89984;">&#39;</span><span style="color: #928374;font-style: italic;">  # Runs every 30 minutes</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">  workflow_dispatch</span><span style="color: #A89984;">:</span><span style="color: #928374;font-style: italic;">  # Allows manual triggering of the workflow if needed</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #8EC07C;">jobs</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">  fetch_webmentions</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    runs-on</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> ubuntu-latest</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #8EC07C;">    steps</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Checkout Repository</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        uses</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> actions/checkout@v4</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Fetch Webmentions</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        env</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">          WEBMENTION_TOKEN</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> ${{ secrets.WEBMENTION_TOKEN }}</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        run</span><span style="color: #A89984;">:</span><span style="color: #FB4934;"> |</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          mkdir -p static/webmention</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          # Fetch webmentions and save (overwrite) to a single file</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          curl -s &quot;https://webmention.io/api/mentions.json?token=${WEBMENTION_TOKEN}&quot; -o static/webmentions.json</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Commit and Push Webmentions</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        run</span><span style="color: #A89984;">:</span><span style="color: #FB4934;"> |</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          git config --global user.name &quot;github-actions[bot]&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          git config --global user.email &quot;github-actions[bot]@users.noreply.github.com&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          git add static/webmentions.json</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          git commit -m &quot;Update webmentions&quot; || echo &quot;No changes to commit&quot;</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          # Pull latest changes from main with rebase to avoid conflicts</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          git pull --rebase origin main</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          # Now push the updated branch</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          git push</span></span></code></pre>
<p>Second workflow builds the site from the source after fetching the Webmentions.<br />
<code>zola.yml</code></p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="yaml"><span class="giallo-l"><span style="color: #8EC07C;">name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Zola on GitHub Pages</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #D3869B;">on</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">  workflow_run</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    workflows</span><span style="color: #A89984;">: [&quot;</span><span style="color: #B8BB26;">Fetch Webmentions</span><span style="color: #A89984;">&quot;]</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    types</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #B8BB26;"> completed</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #8EC07C;">jobs</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">  build</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Publish site</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    runs-on</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> ubuntu-latest</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    steps</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #A89984;">    -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Checkout main</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">      uses</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> actions/checkout@v4</span></span>
<span class="giallo-l"><span style="color: #A89984;">    -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Build and deploy</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">      uses</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> shalzz/zola-deploy-action@v0.19.2</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">      env</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        GITHUB_TOKEN</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> ${{ secrets.GITHUB_TOKEN }}</span></span></code></pre>
<p>Third workflow sends Webmentions from the detected links in the newly generated <code>atom.xml</code>.<br />
<code>send-webmentions.yml</code></p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="yaml"><span class="giallo-l"><span style="color: #8EC07C;">name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Send Webmentions</span></span>
<span class="giallo-l"><span style="color: #D3869B;">on</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">  workflow_run</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    workflows</span><span style="color: #A89984;">: [&quot;</span><span style="color: #B8BB26;">Zola on GitHub Pages</span><span style="color: #A89984;">&quot;]</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    types</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #B8BB26;"> completed</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">jobs</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">  send_webmentions</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Send Webmentions with Delay</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    runs-on</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> ubuntu-latest</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">    steps</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Checkout Repository</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        uses</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> actions/checkout@v4</span></span>
<span class="giallo-l"><span>        </span></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Wait for Delay</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        run</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> sleep 60</span><span style="color: #928374;font-style: italic;">  # Waits for 1 minute (60 seconds) before running the next steps</span></span>
<span class="giallo-l"><span>        </span></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Read Site URL from CNAME</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        id</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> get_url</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        run</span><span style="color: #A89984;">:</span><span style="color: #FB4934;"> |</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          SITE_URL=$(cat static/CNAME)</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">          echo &quot;site_url=$SITE_URL&quot; &gt;&gt; $GITHUB_OUTPUT</span></span>
<span class="giallo-l"><span style="color: #B8BB26;">        </span></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Install Webmention Package</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        run</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> npm install @remy/webmention</span></span>
<span class="giallo-l"><span>        </span></span>
<span class="giallo-l"><span style="color: #A89984;">      -</span><span style="color: #8EC07C;"> name</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> Send Webmentions</span></span>
<span class="giallo-l"><span style="color: #8EC07C;">        run</span><span style="color: #A89984;">:</span><span style="color: #B8BB26;"> npx webmention https://${{ steps.get_url.outputs.site_url }}/atom.xml --limit=0 --send</span></span></code></pre></details>
<h2 id="sending-webmentions-1">Sending Webmentions</h2>
<p>In order to send Webmentions, the content should be formatted accordingly. In general I like to utilize three activities to send Webmentions.
[<em>It is preferred to only use one activity for one mention.</em>]</p>
<h3 id="mention">Mention</h3>
<p>One can mention a site using webmention by simply putting the link to the page being mentioned.
The site will get the webmention if it supports it.</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="markdown"><span class="giallo-l"><span style="color: #A89984;">[</span><span style="color: #928374;text-decoration: underline;">Void Bed</span><span style="color: #A89984;">](</span><span style="color: #D3869B;text-decoration: underline;">https://flux.3o14.com/void-bed/</span><span style="color: #A89984;">)</span><span> by flux.</span></span>
<span class="giallo-l"><span>or</span></span>
<span class="giallo-l"><span style="color: #83A598;">&lt;</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #FABD2F;"> href</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">https://flux.3o14.com/void-bed/</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span><span>Void Bed</span><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #83A598;">&gt;</span><span> by flux</span></span></code></pre><h3 id="like">Like</h3>
<p>One can like a post using webmention by formatting the link as follows:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="markdown"><span class="giallo-l"><span>I like how flux talks about his bed in </span><span style="color: #83A598;">&lt;</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #FABD2F;"> class</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">u-like-of</span><span style="color: #A89984;">&quot;</span><span style="color: #FABD2F;"> href</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">https://flux.3o14.com/void-bed/</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span><span>Void Bed</span><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #83A598;">&gt;</span></span></code></pre>
<p>I like how flux talks about his bed in <a class="u-like-of" href="https://flux.3o14.com/void-bed/">Void Bed</a></p>
<h3 id="reply">Reply</h3>
<p>One can reply to a post by formatting the link and the text as follows:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="markdown"><span class="giallo-l"><span style="color: #83A598;">&lt;</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #FABD2F;"> class</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">u-in-reply-to</span><span style="color: #A89984;">&quot;</span><span style="color: #FABD2F;"> href</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">https://flux.3o14.com/void-bed/</span><span style="color: #A89984;">&quot;</span><span style="color: #83A598;">&gt;</span><span>Void Bed</span><span style="color: #83A598;">&lt;/</span><span style="color: #8EC07C;font-weight: bold;">a</span><span style="color: #83A598;">&gt;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>I feel the same about my bed. Nice writing flux!</span></span></code></pre><h3 id="bridges">Bridges</h3>
<p>Though I have connected this site to the fediverse with Bridgy Fed, it is opt in using a zola shortcode. Because, I want the articles to have a "blog interaction" from other peoples blog but not from the social media. But, I do use bridgy on my short posts sometimes. <a href="https://scientiac.space/syndications/posse-2024-11-05/">Webmentions</a> and <a href="https://scientiac.space/syndications/posse-2025-02-04/">Linux is/not Difficult</a> are some posts I have used bridgy with and they also work as example posts to see how different webmention activities look like in my website.</p>
<h2 id="lastly">Lastly</h2>
<p>I had forgotten about webmentions and interactions on my site, but I recently read a post from Joel titled <a rel="external" href="https://joelchrono.xyz/blog/webmentions-but-manual/">Webmentions but manual (for Jekyll)</a> and people giving names to the interactions really caught my attention. I haven't given it a name because mine are just Webmentions but I feel like Webmentions are still a good option to have <em>(with much less spam)</em> for interaction if it isn't connected to an actual social media.
Some other posts I read were:
[<em>At least for the sake of just pinging them.</em>]</p>
<p><a rel="external" href="https://notes.jeddacp.com/implementing-community-echoes/">Implementing Community Echoes</a><br />
<a rel="external" href="https://forkingmad.blog/blog-interactions/">Blog interactions</a><br />
<a rel="external" href="https://kevquirk.com/blog/what-others-said">What Others Said...</a></p>
<p>I hope webmention on blogging sites takes off. Or maybe it has already taken off. I want the future where everyone can express themselves with their own taste and creativity not having to compromise personality for protocols.</p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>Booting Arch Linux Smoothly</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;boot-arch-smoothly&#x2F;"/>
        <updated>2025-07-05T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;boot-arch-smoothly&#x2F;</id>
        <content type="html"><![CDATA[
          <h2 id="my-device">My Device</h2>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>                  -`                     scientiac@einstein</span></span>
<span class="giallo-l"><span>                 .o+`                    ------------------</span></span>
<span class="giallo-l"><span>                `ooo/                    OS: Arch Linux x86_64</span></span>
<span class="giallo-l"><span>               `+oooo:                   Host: ASUS Zenbook 14 UM3406HA_UM3406HA (1.0)</span></span>
<span class="giallo-l"><span>              `+oooooo:                  Kernel: Linux 6.15.4-arch2-1</span></span>
<span class="giallo-l"><span>              -+oooooo+:                 Uptime: 31 mins</span></span>
<span class="giallo-l"><span>            `/:-:++oooo+:                Packages: 997 (pacman)</span></span>
<span class="giallo-l"><span>           `/++++/+++++++:               Shell: zsh 5.9</span></span>
<span class="giallo-l"><span>          `/++++++++++++++:              Display (SDC419D): 2880x1800 @ 60 Hz (as 1440x900) in 14&quot; [Built-in]</span></span>
<span class="giallo-l"><span>         `/+++ooooooooooooo/`            WM: niri (Wayland)</span></span>
<span class="giallo-l"><span>        ./ooosssso++osssssso+`           Cursor: Adwaita (24px)</span></span>
<span class="giallo-l"><span>       .oossssso-````/ossssss+`          Terminal: ghostty 1.1.3-arch1</span></span>
<span class="giallo-l"><span>      -osssssso.      :ssssssso.         Terminal Font: FantasqueSansM Nerd Font Mono (11pt)</span></span>
<span class="giallo-l"><span>     :osssssss/        osssso+++.        CPU: AMD Ryzen 7 8840HS (16) @ 5.13 GHz</span></span>
<span class="giallo-l"><span>    /ossssssss/        +ssssooo/-        GPU: AMD Radeon 780M Graphics [Integrated]</span></span>
<span class="giallo-l"><span>  `/ossssso+/:-        -:/+osssso+-      Memory: 2.51 GiB / 14.91 GiB (17%)</span></span>
<span class="giallo-l"><span> `+sso+:-`                 `.-/+oso:     Swap: 0 B / 4.00 GiB (0%)</span></span>
<span class="giallo-l"><span>`++:.                           `-/+/    Disk (/): 20.95 GiB / 475.94 GiB (4%) - btrfs</span></span>
<span class="giallo-l"><span>.`                                 `/    Local IP (wlan0): 192.168.1.71/24</span></span>
<span class="giallo-l"><span>                                         Battery (ASUS Battery): 52% [Discharging]</span></span>
<span class="giallo-l"><span>                                         Locale: en_US.UTF-8</span></span>
<span class="giallo-l"></span></code></pre><h2 id="firstly">Firstly...</h2>
<p>My friend challenged me to achieve flicker free boot on my laptop like someone achieved it many-many years ago, and said if fedora can do it by default why can't we?</p>
<iframe
	class="youtube-embed"
	src="https://www.youtube-nocookie.com/embed/5DW2JgJmsuY"
	allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
	referrerpolicy="strict-origin-when-cross-origin" allowfullscreen>
</iframe>
<p>Technically he didn't challenge me, he only mentioned that it was possible. And, I took it as a challenge. Because I know that linux can be as smooth and polished looking as
other commercial OS offerings. And I want my laptop to be as smooth as possible and as clean looking as possible.</p>
<p>So, I tried.</p>
<h3 id="how-did-you-start">How did you start?</h3>
<p>The only thing I didn't really want to do was reinstall my OS again. But, I had to.
I had never used the Unified Kernel Image (UKI) and I was using <code>systemd-boot</code> as my bootloader.
So, the bootloader had to go and UKI had to be installed.</p>
<blockquote class="note">
	<p class="alert-title">Note</p>
	<p><strong>1.</strong> <em>When installing Arch Linux, use <code>UKI</code> Unified Kernel Image and instead of using a bootloader, use <code>EFIstub</code> (EFI Boot Stub)</em></p>

</blockquote>
<p>I used <code>archinstall</code> and it had both of these options. It was very easy. I picked all other configurations as I used to do and just installed the system.</p>
<h3 id="after-installation">After Installation</h3>
<p>I had to change the kernel parameters, to make all those text go away. So, I tried using <code>efibootmgr</code> and failed again and again.
I couldn't for science's sake use it properly. Once, I tried using the script recommended by the <code>arch-wiki</code>, the boot process flickered more than It had ever flickered.
Luckily it hadn't removed the original entry and <code>efibootmgr</code> had a way to remove the broken entries, so I brought everything back to normal and tried it a countless times, failing each time.</p>
<p>I gave up on <code>efibootmgr</code>, from previous experiences with booting with a splash screen, I knew <code>plymouth</code> was a thing. So, I installed it. And went searching for ways to put kernel-parameters during boot. Plymouth needed <code>quiet splash</code> to work.</p>
<p>Then, I found <code>/etc/kernel/cmdline</code>. I added <code>quiet splash</code> to the end of the line and then rebooted. It showed no changes.
I found out that I had to rebuild the initial ramdisk environment. In other words I had to run:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;"># To (re-)generate initramfs images based on all existing presets, the -P/--allpresets switch is used. </span></span>
<span class="giallo-l"><span style="color: #FABD2F;">sudo</span><span style="color: #B8BB26;"> mkinitcpio</span><span style="color: #D3869B;"> -P</span></span>
<span class="giallo-l"></span></code></pre><blockquote class="note">
	<p class="alert-title">Note</p>
	<p><strong>2.</strong> <em>To add kernel parameters, you need to append the text on <code>/etc/kernel/cmdline</code> and then, rebuild the initramfs image using <code>sudo mkinitcpio -P</code>.</em></p>

</blockquote>
<p>My <code>/etc/kernel/cmdline</code> looks like this:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>root=PARTUUID=4638cd24-77e4-4ed3-bb8a-9478d9c2d2db zswap.enabled=0 rw rootfstype=btrfs quiet loglevel=3 udev.log-priority=3 systemd.show_status=false splash</span></span>
<span class="giallo-l"></span></code></pre>
<p>The part until <code>rootfstyps=btrfs</code> was autogenerated during installation and I added the rest afterwards.</p>
<p>Now, <strong>It Worked!</strong> But, it was the same(somewhat). The splash animation for ASUS ran, then it showed me a big Arch Linux logo, then the screen went black and then the splash screen reappeared and it dropped me to my login manager. This was the behavior it used to show before I installed arch without doing anything I previously did. Basically, I was back to how it was before I reinstalled my OS. All that copying and configuring for nothing.</p>
<h3 id="why-you-should-not-give-up">Why you should not give up</h3>
<p>So, I started putting different kernel params to check if one of it worked and if any of it removed blackout before showing me the splash screen again. The wiki for <a rel="external" href="https://wiki.archlinux.org/title/Silent_boot">silent boot</a> suggested I put <code>loglevel=3 systemd.show_status=auto rd.udev.log_level=3</code> in the kernel parameters.</p>
<p>It also said:</p>
<blockquote>
<p><em>If you also want to stop systemd from printing its version number when booting, you should also append udev.log_level=3 to your kernel parameters. If systemd is used in an initramfs, append rd.udev.log_level=3 instead.</em></p>
</blockquote>
<p>Since, I wasn't using <code>systemd</code> in the initramfs, I used <code>udev.log_level=3</code> instead. Then I rebuilt the initramfs and rebooted. <strong>It was the same.</strong></p>
<blockquote class="note">
	<p class="alert-title">Note</p>
	<p><strong>3.</strong> <em>Append <code>quiet loglevel=3 udev.log-priority=3 systemd.show_status=false splash</code> in <code>/etc/kernel/cmdline</code> to enable splash and quiet out the logs.</em></p>

</blockquote>
<p>Then I became desperate and started looking everywhere; forums, wikis, even YouTube comment section. And, you know what? YouTube comments helped for once.</p>
<p><img src="https://scientiac.space/images/boot-arch-smoothly/comment.png" alt="Youtube Comment" />
This comment is from the YouTube video I have linked above.</p>
<p>I finally realised, <code>plymouth</code> was the culprit. The kernel had to hand over the process to plymouth and it caused the delay after the big Arch Linux logo.</p>
<p>I also found out that kernel itself can render the logo without plymouth, that was how the Arch Linux Logo was being rendered even before plymouth had started.
If only, I had read the silent boot wiki entry properly:</p>
<blockquote>
<p><em>To prevent the kernel from blanking the vendor logo, Linux 4.19 introduced a new configuration option <code>FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER</code> that retains the contents of the framebuffer until text needs to be printed on the framebuffer console. Since version 4.19.arch1, the official Arch Linux kernels are compiled with <code>CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y</code>.</em></p>
</blockquote>
<p>Thanks to arch I didn't have to recompile the kernel to get that.</p>
<blockquote class="tip">
	<p class="alert-title">Tip</p>
	<p><em>There is no need to use <code>plymouth</code> because the Linux kernel can show splash images by itself and enabling both only makes the process less smoother.</em></p>

</blockquote>
<h3 id="it-still-wasn-t-smooth">It still wasn't "smooth"</h3>
<p>I didn't want the Arch Linux logo, I wanted my vendor logo to be continued, like it was still booting until my login screen appeared.
If only I can replace the "Arch Linux" logo with <code>bgrt</code> (The vendor's splash logo). So, I went looking where I could change that.</p>
<blockquote>
<p><em>The Boot Graphics Record Table (BGRT) is an optional ACPI table which contains a pointer to the image that has been drawn during boot.</em></p>
</blockquote>
<p>I found <code>/etc/mkinitcpio.d/linux.preset</code> to be the exact thing I was looking for. And from the name itself I knew I needed to rebuild the initramfs again for the changes to be reflected.</p>
<p>I had to change the following line in <code>linux.preset</code>:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="ini"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">default_options</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">--splash /usr/share/systemd/bootctl/splash-arch.bmp</span><span style="color: #A89984;">&quot;</span></span>
<span class="giallo-l"></span></code></pre>
<p>My first instinct was to go to <code>/usr/share/systemd/bootctl/</code> and <code>rm splash-arch.bmp</code>. I did that and rebooted, Now, It showed black screen until the login manager showed up.
It was progress.</p>
<p>Then I found my <code>bgrt</code> image in <code>/sys/firmware/acpi/bgrt/</code> it was named <code>image</code> with no file extension.</p>
<p>So, I changed the above line to:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="ini"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;"> default_options</span><span style="color: #A89984;">=&quot;</span><span style="color: #B8BB26;">--splash /sys/firmware/acpi/bgrt/image</span><span style="color: #A89984;">&quot;</span></span>
<span class="giallo-l"></span></code></pre>
<p>Then I rebuilt the initramfs and rebooted. To be greeted with a smooth boot. Like I wanted it to be. Showing bgrt until the login manager showed up.</p>
<blockquote class="note">
	<p class="alert-title">Note</p>
	<p><strong>4.</strong> <em>Change the <code>default_options=</code> configuration to <code>/sys/firmware/acpi/bgrt/image</code> in <code>/etc/mkinitcpio.d/linux.preset</code> then rebuild the initramfs by doing <code>sudo mkinitcpio -P</code>.</em></p>

</blockquote>
<h3 id="it-was-not-as-smooth-as-plymouth">It was not as "smooth" as plymouth</h3>
<p>The booting process was good and how I wanted it to be, but when it came to rebooting it showed:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>[    54.796241] watchdog: watchdog0: watchdog did not stop!</span></span>
<span class="giallo-l"><span>[    54.918590] watchdog: watchdog0: watchdog did not stop!</span></span>
<span class="giallo-l"><span>[    55.597358] reboot: Restarting system</span></span>
<span class="giallo-l"></span></code></pre>
<p>I didn't want that to show up and with a bit of research, I came to a conclusion that disabling watchdog was fine so I did. I edited <code>/etc/modprobe.d/blacklist.conf</code> and added <code>blacklist sp5100_tco</code>. Intel users are supposed to <code>blacklist iTCO_wdt</code> or the watchdog that their system used.</p>
<p>Now my <code>/etc/modprobe.d/blacklist.conf</code> has:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span># Do not load the watchdog module on boot.</span></span>
<span class="giallo-l"><span>blacklist sp5100_tco</span></span>
<span class="giallo-l"></span></code></pre><blockquote class="note">
	<p class="alert-title">Note</p>
	<p><strong>5.</strong> <em>Blacklist your watchdog so you don't get watchdog messages when rebooting and powering off by editing <code>/etc/modprobe.d/blacklist.conf</code>.</em></p>

</blockquote>
<h3 id="i-don-t-like-having-nice-things">I don't like having nice things</h3>
<p>What I did above is enough to get flicker free boot/smooth boot or whatever you call it, but I wanted more, I want <code>plymouth</code> to work without flicker. Spoiler: I couldn't.</p>
<p>Anyway, I switched to <code>systemd</code> instead of <code>udev</code> so my <code>/etc/mkinitcpio.conf</code> has the following hooks now:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>HOOKS=(base systemd modconf autodetect kms keyboard sd-vconsole block filesystems fsck plymouth)</span></span>
<span class="giallo-l"></span></code></pre>
<p>I reinstalled plymouth, and I like it when it smoothly transitions to GDM instead of flashing me to GDM. It was a tradeoff between GDM flash or just flicker when loading spalash screen.</p>
<p>I added more kernel parameters to mitigate the flashing but I couldn't do it.</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>root=PARTUUID=4638cd24-77e4-4ed3-bb8a-9478d9c2d2db zswap.enabled=0 rw rootfstype=btrfs amdgpu.modeset=1 amdgpu.dc=1 video=efifb:keep plymouth.use-simpledrm quiet vt.global_cursor_default=0 loglevel=3 rd.udev.log_level=3 systemd.show_status=auto splash</span></span>
<span class="giallo-l"></span></code></pre>
<p><code>plymouth.use-simpledrm</code> does start plymouth immediately but when the <code>amdgpu</code> driver is ready it mode-switches to it and the black screen appears. I can technically use <code>nomodeset</code> and achieve true flicker free boot with plymouth and everything but then I lose out on my graphics driver setting dpi scaling and brightness and more for me on boot.</p>
<p>I even tried setting <code>/etc/plymouth/plymouthd.conf</code> to delay it's starting but it still doesn't stop flickering. It either flickers or it skips and I get the UKI splash screen until the login manager.</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="ini"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #A89984;">[</span><span style="color: #FABD2F;">Daemon</span><span style="color: #A89984;">]</span></span>
<span class="giallo-l"><span style="color: #FB4934;">ShowDelay</span><span style="color: #A89984;">=</span><span>0</span></span>
<span class="giallo-l"><span style="color: #FB4934;">DeviceTimeout</span><span style="color: #A89984;">=</span><span>30</span></span>
<span class="giallo-l"></span></code></pre>
<p>I think I will just remove the plymouth configuration since it isn't helping anything. Or maybe I'll just leave it there because it is not doing anything.</p>
<h3 id="removing-arch-linux-logo">Removing Arch Linux Logo</h3>
<p>To remove the logo from GDM I quickly installed <code>gdm-settings</code> and there was a toggle which I turned off.</p>
<p>I didn't like the logo shown by plymouth during boot either, so I just removed the image <code>watermark.png</code> from the spinner theme in <code>/usr/share/plymouth/themes/spinner/</code>. I also removed all animation and throbber images just to make everything clean.</p>
<h3 id="conclusion">Conclusion</h3>
<p>I did eventually come back to "not so smooth boot" but I am one <code>sudo pacman -R plymouth</code> away from it. Furthermore, I can boast about having 3 splash screens that look the same transitioning seamlessly*, even 4 if you count the UEFI animation.</p>
<p>It goes as follows:</p>
<ol>
<li><code>UEFI</code> animation starts and ends.</li>
<li><code>UKI Splash Screen</code> starts and ends.</li>
<li><code>simpledrm</code> backed <code>plymouth</code> bgrt theme starts and screen goes blank.</li>
<li><code>amdgpu</code> backed plymouth screen gradually appears and transitions to GDM.</li>
</ol>
<p>But, if I remove plymouth:</p>
<ol>
<li><code>UEFI</code> animation starts and ends.</li>
<li><code>UKI Splash Screen</code> starts and drops me to GDM.</li>
</ol>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>3o14 social</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;3o14-social&#x2F;"/>
        <updated>2025-02-28T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;3o14-social&#x2F;</id>
        <content type="html"><![CDATA[
          <img src="https://scientiac.space/images/3o14_com/makuro.png" alt="App Icon for 3o14" style="width: 25%;" />
<h2 id="preface">Preface</h2>
<p>When I started using Linux, I found out that I had to use cronjobs to run some scripts I wanted to run in repeat, that was how I was introduced about services/daemons. Then it was when trying to make a website, I needed a server to continuously see the live changes that I did to my HTML file. I gradually learned about more industry standard servers like Apache after playing with the python server module almost all the time when testing and making a website. Then I found out about self-hosting. [<em>That's what's like growing in a Linux environment.</em>] I hated subscriptions and was unable to use the "free" VPS services due to their credit card requirements. Almost everything I did was entirely on my laptop and on my phone with Termux. [<em>I used to use Termux even before I got a laptop.</em>] Then, being in the Linux communities I got interested in Privacy and Security, then I joined mastodon as a healthier alternative social media platform as an experiment.</p>
<p>I didn't know about decentralization and federation back then, I used the link from the YouTube channel I liked and that was my social media home, until that server (Instance) got shut down, and I had to move to a new instance, that is how I got to know about decentralization and federation. Now living in one of the servers, I found out about more services like mastodon that weren't mastodon but could communicate with my instance but had a completely different UI and features. I learned about single user instances and servers particularly for a single user. Since then, I wanted my own private island(instance) of my social media. I did somewhat treat this blogging site as my own island, but it is static and isn't like a "social" media at all. This is how I got interested in ActivityPub and wanted to build my own.</p>
<h2 id="introduction">Introduction</h2>
<p>3o14 (pi) is a single user ActivityPub based social media that also supports rendering mathematical typesetting as a way to scientifically communicate between people. It is a self-hostable social media for a single person that is Privacy respecting (obviously) and we (It's not my single effort.) built it to understand the underlying protocol ActivityPub and how it worked. (And as a minor project for our computer engineering degree.)</p>
<h3 id="how-the-fediverse-works">How the Fediverse works</h3>
<p>The Fediverse operates on a decentralized model, allowing various independent servers, or instances, to communicate with one another through open protocols like ActivityPub. Each instance hosts its own community and user base [<em>It could be a single user too</em>], enabling users to create accounts on different servers while still interacting seamlessly with users on other instances. When a user posts content, that activity is packaged in a standardized format and sent to other instances, allowing for real-time updates and interactions across the network. This federated approach ensures that no single entity controls the entire ecosystem, promoting user autonomy and privacy. Additionally, the use of open-source software means that anyone can set up their own instance, fostering a diverse range of platforms and experiences within the Fediverse. By leveraging these protocols, you can build applications that not only respect user privacy but also facilitate rich, interconnected social experiences across various platforms.</p>
<img src="https://scientiac.space/images/3o14_com/fediverse.png" alt="App Icon for 3o14" />
<h3 id="what-we-wanted-to-build-and-eventually-built">What we wanted to build (and eventually built)</h3>
<p>We wanted to build a single user social media platform using the protocol, that supported mathematical syntax for scientific communication. It had to be easy to deploy with minimal efforts and had to be federated with the network of Fediverse. It would be a platform for tech minded scientific people who want privacy in their social media and want to own their own data without having to rely on big tech and black box social media with constraints like Facebook, X, Instagram, etc. which do not have anything helpful for using mathematical symbols in the posts. [<em>This absolutely doesn't mean that it doesn't support regular posts, it should.</em>]</p>
<p>I want to start from the frontend, because that is the most amount of work I have put in.</p>
<h3 id="frontend">Frontend</h3>
<p>For the frontend, I used React Native because I was looking at the trends and saw a growing social media Bluesky writing its cross-platform frontend entirely in React Native and saw how they had all the features available in both their web and mobile platforms. It was fairly easy to use with a framework called 'Expo', which made building and testing the app in web and in android much easier. Learning about routes of expo and how it handled screens and modals was a bit difficult at first, but it got easier as the app grew. But working with multiple platform did bring multiple issues for different platforms.</p>
<p><img src="https://scientiac.space/images/3o14_com/login.png" alt="Instance Chooser" /></p>
<p>One of the issues was rendering mathematics, there was no library that could render math on web as well as in mobile. I had to work around by using two libraries with separate rendering logic for web and mobile, of which I still am not satisfied with how the mobile renderer is a bit slow and janky, but I made the two platforms act as closest as possible.</p>
<p>Learning about ActivityPub APIs was fun, I got to know how the requests were made and how things worked after the UI is clicked, how screens were loaded and so much. AI tools helped a lot to write logics and understand them when I was absolutely blank about what to do. [<em>It happened more often than you'd think.</em>]</p>
<h3 id="backend">Backend</h3>
<p>I did not do much work on the backend, <a rel="external" href="https://faulty.carboxi.de">faultypointer</a> did the work. But I do understand the technologies used in it. Hono was used for the server and fedify was used as the typescript library to eliminate the boilerplate for building Fediverse apps (I didn't just take that from the fedify site). The server too is written in typescript like the frontend. Fedify works as the middleware that processes the <code>activity/json</code> data that are requested to the server for federation. The database is Postgres and the schema and query is handled by the drizzle ORM.</p>
<h2 id="showcase">Showcase</h2>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/3o14_com/home_page.png" style="width: 19rem; padding:0.25rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/3o14_com/reply_page.png" style="width: 19rem; padding:0.25rem;border-radius: 1.75rem;">
</div>
<div style="text-align: center">
<p><strong>img:</strong> <em>homepage and replies page</em></p>
</div>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/3o14_com/light_compose.png" style="width: 19rem; padding:0.25rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/3o14_com/light_reply.png" style="width: 19rem; padding:0.25rem;border-radius: 1.75rem;">
</div>
<div style="text-align: center">
<p><strong>img:</strong> <em>post compose and reply compose page in light mode with post visibility menu toggled</em></p>
</div>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/3o14_com/light_mobile.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/3o14_com/dark_mobile.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<div style="text-align: center">
<p><strong>img:</strong> <em>homepage and profile page in mobile</em></p>
</div>
<h2 id="conclusion">Conclusion</h2>
<p>There isn't much to conclude here because we have achieved the basics of what we want, but the work is very incomplete and alpha. We have an android app that does work with all other servers, not just ours thanks to Fediverse, but everything is bare-bones and need many improvements. This piece of art is presentable, but I now need to host both the webui and backend on a Raspberry Pi to show that a simple device can handle your social media, and you don't have to rely on big tech for it.</p>
<p>Lastly, here is the source for what we are working on, <a rel="external" href="https://github.com/3o14-com">github/3o14-com</a>. Enjoy!</p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>Beautifying Firefox with &quot;chrome&quot;</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;firefox-userstyle&#x2F;"/>
        <updated>2024-08-20T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;firefox-userstyle&#x2F;</id>
        <content type="html"><![CDATA[
          <p>My mind goes hyperactive whenever exams are near, this semester is no different. I always find something very interesting to do every time an exam is around. This semester, I went into a rabbit hole of customizing Firefox to make it minimal (or immersive), I'd say.</p>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/firefox-userstyle/normal-home.png" style="width: 19rem; padding:0.25rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/firefox-userstyle/normal-tabs.png" style="width: 19rem; padding:0.25rem;border-radius: 1.75rem;">
</div>
<div style="text-align: center">
<p><strong>img:</strong> <em>homepage and tabs-expanded view</em></p>
</div>
<p><img src="https://scientiac.space/images/firefox-userstyle/normal-website.png" alt="normal-website" /></p>
<div style="text-align: center">
<p><strong>img:</strong> <em>webpage view</em></p>
</div>
<p>I am very much into customization, and I like to keep changing things around. When I was using gnome in arch Linux some years back I had come across <a rel="external" href="https://github.com/rafaelmardojai/firefox-gnome-theme">rafaelmardojai/firefox-gnome-theme</a> which I immediately installed to make my system consistent with the <em>libadwaita</em> style. That was the time when I realized the repo had almost 100% CSS in the GitHub language thingy bar. I knew what CSS was but never bothered to look into the Firefox theme, it simply worked.</p>
<p>Fast-forward to a few months ago, the arc browser had the internet going crazy about it. I did like the UI being minimal and focused on viewing websites, hiding the settings that would normally show up all the time. Since you had to make an account to just use the browser, I didn't use it. Then I went searching for themes that replicated the UI on Firefox itself. I found <a rel="external" href="https://github.com/KiKaraage/ArcWTF">KiKaraage/ArcWTF</a> which I used for a while. This time I modified the CSS and restarted Firefox and kept on updating the CSS and restarting Firefox until I got what I wanted. I hated that I had to restart Firefox to apply the small change in <code>userChrome.css</code> that I was going to repeat because I didn't know what I was doing.</p>
<p>I am currently using <code>nix</code>, so, eventually this was to come. I had to configure my Firefox with <code>home-manager</code>. This caused me to leave behind my arcWTF css because there was no easy way to simply put the chrome folder in its place with nix. But, there was a way to write <code>userChrome</code> within the nix configuration. This way of changing CSS was even more of a hassle because I had to first write it inside nix with no LSP for CSS, then I had to evaluate the nix file to put things into place and then restart Firefox.</p>
<p>Aaah! That was really clunky but, I then made single <code>userChrome.css</code> and <code>userContent.css</code> files and then just imported them with nix to read the file instead of writing the CSS inside the <code>.nix</code> file, and it was a little better. Now started my journey to make the most minimal and at the same time good Firefox userstyle in a single <code>.css</code> file. I then found <a rel="external" href="https://github.com/migueravila/SimpleFox">simplefox</a> a goldmine for minimal Firefox config, but there was a single issue, I was used to the tabs being tree style and on the left sidebar. So, I installed <a rel="external" href="https://addons.mozilla.org/en-US/firefox/addon/sidebery/">sidebery</a> and got some CSS from arcWTF to make the collapsed sidebar work.</p>
<p>Then I got a new laptop, which currently has windows, but It has a gorgeous screen which in comparison to the previous laptop is the difference of 70% more DCI-P3 with a 3k OLED screen. I copied my CSS from my NixOS machine, and it was working pretty well. Until I had an idea to improve it further. For days, I kept editing the CSS and restarting my Firefox to change the <code>.css</code> with hit and trial getting more failures than success in the style actually being like I intended it to be. And then yesterday I was fed up with doing that and actually searched if there was a way of doing that without restarting Firefox (live).</p>
<p>Surprise, surprise, it was not just possible but intentional. I wished I had known about this before. You just do the following things:</p>
<ol>
<li>Open the <code>hamburger menu</code>.</li>
<li>Go to <code>more tools</code>.</li>
<li>Click on <code>web developer tools</code>.
The web developer interface will open, now on the top right side of the toolbox,</li>
<li>Click on the <code>3 dot menu</code>.</li>
<li>Click on <code>settings</code>.</li>
<li>Enable two options:</li>
</ol>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>    enable remote debugging</span></span>
<span class="giallo-l"></span></code></pre><pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>    enable browser chrome and add-on debugging toolboxes.</span></span>
<span class="giallo-l"></span></code></pre>
<ol start="7">
<li>Then go to <code>hamburger menu &gt; more tools &gt; browser toolbox</code> or the shortcut <code>Ctrl+Shift+Alt-I</code>.</li>
<li>Then it'll ask for confirmation with the following prompt:</li>
</ol>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>    An incoming request to permit remote debugging connection was detected. A remote client can take complete control over your browser!</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>    Client Endpoint: 127.0.0.1:51146</span></span>
<span class="giallo-l"><span>    Server Endpoint: 127.0.0.1:51141</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>    Allow connection?</span></span>
<span class="giallo-l"></span></code></pre>
<ol start="9">
<li>Allow it and the toolbox opens. Go to the <code>style editior</code> from the menu.</li>
<li>Find <code>userChrome.css</code> and enjoy live tinkering. When you are done, just click on save or <code>Ctrl+S</code> and it is permanent.</li>
<li>For <code>userContent.css</code> just come to the Firefox homepage and hit <code>Ctrl+Shift+C</code>, go to the style editor and find the <code>userContent.css</code>.</li>
</ol>
<h2 id="finally">Finally</h2>
<p>I created this beautiful Firefox userstyle with a focus on minimalism and web content. It's called <a rel="external" href="https://github.com/scientiac/scifox">scifox</a> because duh! It's my Firefox I will call it whatever I want. I am also working on a version with hidden panels that show up on hover to make it even more minimalistic and immersive. If you want to check that out, it's on the <a rel="external" href="https://github.com/scientiac/scifox/tree/immersive">immersive</a> branch.</p>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/firefox-userstyle/immersive-home.png" style="width: 19rem; padding:0.25rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/firefox-userstyle/immersive-tabs.png" style="width: 19rem; padding:0.25rem;border-radius: 1.75rem;">
</div>
<div style="text-align: center">
<p><strong>img:</strong> <em>immersive homepage and tabs-expanded view</em></p>
</div>
<p><img src="https://scientiac.space/images/firefox-userstyle/website.png" alt="website" /></p>
<div style="text-align: center">
<p><strong>img:</strong> <em>immersive webpage view</em></p>
</div>
<p>I have grown to prefer this minimal UI, and I absolutely love <a rel="external" href="https://addons.mozilla.org/en-US/firefox/addon/adaptive-tab-bar-colour/">Adaptive Tab Bar Colour</a> for making the whole UI follow the style the creator of the website intended. And one more thing, I am in love with <a rel="external" href="https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/">uBlock Origin</a> and can't live without it. <strong>So, if you are not a Firefox user give Firefox a go, I know it'll not disappoint you and even if it does Firefox is like Linux, you can pick and plug features make it work the way you want.</strong></p>
<blockquote>
<p>Looking for the URL bar in webpage? Hover where it should be and you might just find it.</p>
</blockquote>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>Manoid: A Waste Management Robot</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;yantra-bot&#x2F;"/>
        <updated>2024-06-12T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;yantra-bot&#x2F;</id>
        <content type="html"><![CDATA[
          <p><strong>A Smart Waste Management Robot using Python and OpenCV</strong> that can detect the nearest waste(Determined by an <code>no 8</code> ArUco Marker in the video), navigate to it using the shortest path on the map, pick it(Denoted by a <code>5 second</code> stop in the video) and reach the destination(Determined By <code>no 5</code> Aruco Marker in the video) to dump it and again repeat the process if more waste is detected; with only sensor being an overhead camera tracking the ArUco Markers.</p>
<p><video src="https://scientiac.space/images/manoid/manoid.mp4" controls></video></p>
<blockquote>
<p><em>In the video, I am picking the robot up sometimes to keep it on a new position to show that it can track it's last position and go directly there instead of trying to calculate the route again.</em></p>
</blockquote>
<p>In today's world, efficient waste management is becoming increasingly crucial due to rapid urbanization and population growth. Traditional methods of waste collection and dumping are labor-intensive and often inefficient. By integrating robotics and advanced algorithms, we can streamline these processes, reduce human effort, and ensure a cleaner environment. This project, 'manoid', aims to demonstrate how a robot can autonomously detect, navigate, and manage waste using only a single overhead camera and advanced computer vision techniques.</p>
<blockquote>
<p>I have written another blog post related to this: <a rel="external" href="https://scientiac.space/blog/esp-mosquitto/">Manoid: Communication</a></p>
</blockquote>
<p><strong>Let's see how it was made.</strong></p>
<h3 id="requirements">Requirements:</h3>
<table><thead><tr><th><strong>Category</strong></th><th><strong>Component</strong></th></tr></thead><tbody>
<tr><td>Hardware</td><td>ESP32 Microcontroller</td></tr>
<tr><td>Hardware</td><td>L298N Motor Driver</td></tr>
<tr><td>Hardware</td><td>DC Motor and Wheels</td></tr>
<tr><td>Hardware</td><td>A 12V Battery</td></tr>
<tr><td>Hardware</td><td>A camera (I used my phone with an IP Camera app for video streaming)</td></tr>
<tr><td>Software</td><td>Python (for publishing)</td></tr>
<tr><td>Software</td><td>Arduino IDE (for ESP32 firmware)</td></tr>
<tr><td>Software</td><td>mosquitto (for serving)</td></tr>
</tbody></table>
<h2 id="basic-setup">Basic Setup</h2>
<h3 id="setting-up-arduino-ide">Setting Up Arduino IDE</h3>
<p><strong>To install the ESP32 board in your Arduino IDE, follow these instructions:</strong></p>
<ol>
<li>In your Arduino IDE, go to File &gt; Preferences.</li>
<li>Enter the following into the “Additional Board Manager URLs” field:</li>
</ol>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FABD2F;">  https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json</span></span>
<span class="giallo-l"></span></code></pre>
<ol start="3">
<li>Click the “OK” button.</li>
<li>Open the Boards Manager. Go to Tools &gt; Board &gt; Boards Manager.</li>
<li>Search for ESP32 and press the install button for the “ESP32 by Espressif Systems”.</li>
<li>Once installed, select your ESP32 board in Tools &gt; Board menu.</li>
<li>Select the appropriate Port in Tools &gt; Port menu (in my case it was the <code>DOIT ESP32 DEVKIT V1</code>).</li>
</ol>
<p>Now your Arduino IDE is set up to work with ESP32.</p>
<h3 id="setting-up-the-environment">Setting Up The Environment</h3>
<p>I've got my environment all sorted out with Nix and Nix Flake, and I've made it even easier with direnv activation. Mosquitto's up and running smoothly on its default port 1883. <code>python</code> and it's dependencies <code>opencv</code>,<code>numpy</code>,<code>paho-mqtt</code> and <code>flask</code> in a virtual environment are set up via nix flakes as well. You can look at the <a rel="external" href="https://nix.dev/">nix documentation</a> to know more about how it works.</p>
<p><strong>To set it up:</strong></p>
<ol>
<li>I assume that nix is installed with flakes enabled on your computer.</li>
<li>Clone the repo and enter the environment by running <code>nix develop</code> or allowing <code>direnv</code> to do it for you if you have it installed.</li>
</ol>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FABD2F;">  git</span><span style="color: #B8BB26;"> clone https://github.com/scientiac/manoid</span></span>
<span class="giallo-l"></span></code></pre>
<ol start="3">
<li>A MQTT server will be running as soon as you enter the environment on the default port of <code>1883</code> and you can check the logs using the <code>screen</code> command.</li>
<li>Change parameters to match your device and make sure everything in on point.</li>
<li>Run the <code>main.py</code> script and admire the magic.</li>
</ol>
<h3 id="changing-parameters">Changing Parameters</h3>
<p>When adjusting parameters due to dynamic changes in Wi-Fi or IP addresses, several key locations in the code need to be updated to ensure MQTT and IP camera is properly connected. Here's a breakdown of where to make these adjustments:</p>
<p>In the <code>esp32.ino</code> file:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="cpp"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FE8019;">  const char</span><span style="color: #8EC07C;">*</span><span> ssid </span><span style="color: #8EC07C;">=</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Your_WIFI_SSID</span><span style="color: #A89984;">&quot;;</span></span>
<span class="giallo-l"><span style="color: #FE8019;">  const char</span><span style="color: #8EC07C;">*</span><span> password </span><span style="color: #8EC07C;">=</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Your_WIFI_Password</span><span style="color: #A89984;">&quot;;</span></span>
<span class="giallo-l"><span style="color: #FE8019;">  const char</span><span style="color: #8EC07C;">*</span><span> mqtt_server </span><span style="color: #8EC07C;">=</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Your_MQTT_Server_IP</span><span style="color: #A89984;">&quot;;</span></span>
<span class="giallo-l"></span></code></pre>
<p>In the <code>main.py</code> file:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="python"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #D3869B;font-weight: bold;">  MQTT_BROKER</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Your_MQTT_Server_IP</span><span style="color: #A89984;">&quot;</span><span style="color: #928374;font-style: italic;"> # this is at the top of the document</span></span>
<span class="giallo-l"><span>  args</span><span style="color: #8EC07C;">=</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">http://Your_IP_Camera_feed_Address</span><span style="color: #A89984;">&quot;,)</span><span style="color: #928374;font-style: italic;"> # this is almost at the end of the document</span></span>
<span class="giallo-l"><span>  </span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">  # to use a usb camera </span></span>
<span class="giallo-l"><span>  args</span><span style="color: #8EC07C;">=</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">0</span><span style="color: #A89984;">,),</span><span style="color: #928374;font-style: italic;"> # this can be used and the camera may have ID other than `0` so make sure to check that</span></span>
<span class="giallo-l"></span></code></pre>
<p>Tuning the motors is essential because it directly impacts the robot's movement, responsiveness, and overall efficiency. Factors such as the size, power, and weight distribution of the robot, as well as the surface it operates on, can all influence how the motors should be configured.</p>
<p>In the <code>esp32.py</code> file:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="python"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">  # Tuning the motors</span></span>
<span class="giallo-l"><span style="color: #FABD2F;">  int</span><span> left_min_pwm_forward</span><span style="color: #8EC07C;"> =</span><span style="color: #D3869B;"> 110</span><span style="color: #B16286;">;</span></span>
<span class="giallo-l"><span style="color: #FABD2F;">  int</span><span> left_min_pwm_backward</span><span style="color: #8EC07C;"> =</span><span style="color: #D3869B;"> 115</span><span style="color: #B16286;">;</span></span>
<span class="giallo-l"><span style="color: #FABD2F;">  int</span><span> right_min_pwm_forward</span><span style="color: #8EC07C;"> =</span><span style="color: #D3869B;"> 110</span><span style="color: #B16286;">;</span></span>
<span class="giallo-l"><span style="color: #FABD2F;">  int</span><span> right_min_pwm_backward</span><span style="color: #8EC07C;"> =</span><span style="color: #D3869B;"> 115</span><span style="color: #B16286;">;</span></span>
<span class="giallo-l"></span></code></pre>
<p>In the <code>main.py</code> file (tuning PID settings):</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="python"><span class="giallo-l"></span>
<span class="giallo-l"><span>  robot_settings</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> {</span></span>
<span class="giallo-l"><span style="color: #D3869B;">      6</span><span style="color: #A89984;">: {</span><span>  </span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">          # Robot ID 6</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">P_left</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.8</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">P_right</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.8</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">P_center</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.4</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">I_left</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.01</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">I_right</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.01</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">I_center</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.01</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">D_left</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.001</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">D_right</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.001</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">D_center</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.001</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">backward_speed_left</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 10</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">backward_speed_right</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 10</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">left_prev_error</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">right_prev_error</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">center_prev_error</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">          &quot;</span><span style="color: #B8BB26;">dt</span><span style="color: #A89984;">&quot;:</span><span style="color: #D3869B;"> 0.3</span><span style="color: #A89984;">,</span></span>
<span class="giallo-l"><span style="color: #A89984;">      }</span></span>
<span class="giallo-l"><span style="color: #A89984;">  }</span></span>
<span class="giallo-l"></span></code></pre><h3 id="making-the-bot">Making the bot:</h3>
<ol>
<li>Assemble the bot following the diagram below:</li>
</ol>
<p><img src="https://scientiac.space/images/manoid/diagram.png" alt="PIN Diagram" /></p>
<ol start="2">
<li>Then open the file inside the project directory on <code>etc/esp32/esp32.ino</code> on your Arduino IDE set up to work with esp32 and change the parameters to fit your environment.</li>
<li>And finally flash it!</li>
</ol>
<p><img src="https://scientiac.space/images/manoid/bot.png" alt="Bot" /></p>
<blockquote>
<p><em>You can test the bot manually by connecting to the mqtt server using an application (<em>like MyMQTT on android</em>) and sending values from <code>0</code> to <code>255</code> to the topics :<br />
<code>/robot6_left_forward</code><br />
<code>/robot6_left_backward</code><br />
<code>/robot6_right_forward</code><br />
<code>/robot6_right_backard</code><br />
where <code>0</code> being the wheels at no speed and <code>255</code> being the max speed</em></p>
</blockquote>
<h2 id="what-is-in-the-code">What is in the code?</h2>
<h3 id="the-functions-duh">The Functions, duh!</h3>
<details>
<summary>Click to expand: The Functions</summary>
<p>This list contains the functions involved in the robot, with each function's purpose:</p>
<p><strong>1. <code>get_warped_frame(input_frame, marker_ids, PAD)</code></strong></p>
<ul>
<li>Detects ArUco markers in the input frame.</li>
<li>Extracts the corners of specified markers.</li>
<li>Warps the frame to correct perspective if all specified markers are detected.</li>
<li>Returns the warped frame and marker corners.</li>
</ul>
<p><strong>2. <code>calculate_scale(corners, marker_physical_size_cm)</code></strong></p>
<ul>
<li>Calculates the scale of the marker in pixels per centimeter.</li>
<li>Uses the distance between two corners of the marker.</li>
</ul>
<p><strong>3. <code>adjust_marker_corners(corners, offset_x_cm, offset_y_cm, adjust_width_cm, adjust_height_cm, marker_physical_size_cm)</code></strong></p>
<ul>
<li>Adjusts the marker corners based on given offsets and size adjustments in centimeters.</li>
</ul>
<p><strong>4. <code>detect_aruco_markers(frame, aruco_dict_type)</code></strong></p>
<ul>
<li>Detects ArUco markers in the frame.</li>
<li>Processes the detected markers and adjusts corners if necessary.</li>
<li>Returns the detected markers with their centers and corners.</li>
</ul>
<p><strong>5. <code>heuristic(a, b)</code></strong></p>
<ul>
<li>Calculates the Manhattan distance between two points.</li>
<li>Used in pathfinding algorithms.</li>
</ul>
<p><strong>6. <code>astar(start, goal, obstacles, grid_size)</code></strong></p>
<ul>
<li>Implements the A* algorithm to find the shortest path from start to goal.</li>
<li>Considers obstacles and returns the path if found.</li>
</ul>
<p><strong>7. <code>connect_mqtt()</code></strong></p>
<ul>
<li>Connects to the MQTT broker to enable robot communication.</li>
</ul>
<p><strong>8. <code>send_mqtt_command(topic, command)</code></strong></p>
<ul>
<li>Sends a command to the robot via MQTT.</li>
</ul>
<p><strong>9. <code>get_bot_position(bot_id, markers)</code></strong></p>
<ul>
<li>Retrieves the current position of a robot based on its marker ID.</li>
</ul>
<p><strong>10. <code>calculate_distances(robot_corners, next_position)</code></strong></p>
<ul>
<li>Calculates the distances from the robot's center and corners to the next position.</li>
</ul>
<p><strong>11. <code>move_towards_goal(robot_id, path, threshold)</code></strong></p>
<ul>
<li>Moves the robot towards the goal following the given path using PID control.</li>
</ul>
<p><strong>12. <code>draw_lines_to_goal(frame, robot_corners, goal_position, color, thickness)</code></strong></p>
<ul>
<li>Draws lines from the robot's corners and center to the goal position on the frame.</li>
</ul>
<p><strong>13. <code>draw_path(frame, path, color, thickness, grid_size)</code></strong></p>
<ul>
<li>Draws the planned path on the frame.</li>
</ul>
<p><strong>14. <code>get_head_position(robot_id, markers)</code></strong></p>
<ul>
<li>Returns the head position and corners of the robot based on its marker ID.</li>
</ul>
<p><strong>15. <code>get_waste_positions(markers, waste_id)</code></strong></p>
<ul>
<li>Filters and returns the positions of a specific type of waste.</li>
</ul>
<p><strong>16. <code>fill_grid_cells_from_corners(corners, grid_size)</code></strong></p>
<ul>
<li>Returns all grid cells covered by a rectangle defined by its corners.</li>
</ul>
<p><strong>17. <code>update_obstacles(markers, target_waste_ids, robot_head_pos)</code></strong></p>
<ul>
<li>Updates the list of obstacles and finds the nearest waste position.</li>
</ul>
<p><strong>18. <code>convert_to_grid_coordinates(position, cell_size)</code></strong></p>
<ul>
<li>Converts a position to grid coordinates based on the cell size.</li>
</ul>
<p><strong>19. <code>convert_obstacles_to_grid(obstacles, cell_size)</code></strong></p>
<ul>
<li>Converts a set of positions to grid coordinates.</li>
</ul>
<p><strong>20. <code>convert_grid_to_actual(path, cell_size)</code></strong></p>
<ul>
<li>Converts a path of grid coordinates back to actual coordinates.</li>
</ul>
<p><strong>21. <code>plan_path(start, goal, obstacles)</code></strong></p>
<ul>
<li>Plans a path using the A* algorithm and returns it in actual coordinates.</li>
</ul>
<p><strong>22. <code>find_nearest_edge_midpoint_to_robot(robot_pos, marker_id, markers)</code></strong></p>
<ul>
<li>Finds the nearest edge midpoint of a marker relative to the robot's position.</li>
</ul>
<p><strong>23. <code>pickup_waste(robot_id)</code></strong></p>
<ul>
<li>Sends a command to the robot to pick up the waste.</li>
</ul>
<p><strong>24. <code>drop_off_waste(robot_id, waste_id)</code></strong></p>
<ul>
<li>Sends a command to the robot to drop off the waste and marks it as processed.</li>
</ul>
<p><strong>25. <code>robot_control_loop(robot_id)</code></strong></p>
<ul>
<li>Main control loop for the robot:
<ul>
<li>Connects to MQTT.</li>
<li>Detects waste, navigates to it, picks it up, and drops it off.</li>
<li>Repeats the process continuously.</li>
</ul>
</li>
</ul>
<p><strong>26. <code>capture_and_update_shared_resources(url)</code></strong></p>
<ul>
<li>Continuously captures video frames.</li>
<li>Detects markers and updates shared resources with the frame and markers.</li>
</ul>
<p><strong>27. <code>visualize_robot_behavior()</code></strong></p>
<ul>
<li>Visualizes the robot's current behavior on the frame.</li>
<li>Draws the robot's position, planned path, obstacles, and goal on the frame.</li>
</ul>
</details>
<p><img src="https://scientiac.space/images/manoid/functions.svg" alt="functions" /></p>
<h2 id="finally">Finally</h2>
<h3 id="testing">Testing</h3>
<p>To test only the <code>main.py</code> file for it's pathfinding capabilities, you can run the <code>./pngstream.py</code> file in the <code>etc</code> directory and put <code>http://127.0.0.1:5000/video_feed</code> on the following placeholder in <code>main.py</code>:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="python"><span class="giallo-l"></span>
<span class="giallo-l"><span>    args</span><span style="color: #8EC07C;">=</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">http://Your_IP_Camera_feed_Address</span><span style="color: #A89984;">&quot;,)</span><span style="color: #928374;font-style: italic;"> # this is almost at the end of the document</span></span>
<span class="giallo-l"></span></code></pre>
<p>and then run <code>main.py</code>. This will open up a window with the png showing the detected path in the screen along with detecting all the ArUco markers. If only the markers are detected and the path doesn't show up, it can be assumed that the code isn't working corrctly.</p>
<blockquote>
<p><em>I suggest testing this way as soon as nix finishes setting the environment and keep testing the code like this to minimize the need to test it physically.</em></p>
</blockquote>
<h3 id="troubleshooting-common-issues">Troubleshooting Common Issues</h3>
<ul>
<li>Connection Problems: If the robot fails to connect to the MQTT broker, double-check your Wi-Fi credentials and ensure the broker's IP address is correct in both the ESP32 firmware and main.py. (The main.py script will print errors if something isn't properly connected.)</li>
<li>Movement Issues: If the robot's movements are erratic or it doesn't move as expected, recheck the motor connections and ensure the PWM values are correctly tuned in <code>main.py</code> and <code>esp32.ino</code>.</li>
<li>Marker Detection Failures: If the robot cannot detect ArUco markers, ensure the camera feed is clear and unobstructed. Adjust the camera's focus and lighting conditions to improve detection accuracy."</li>
</ul>
<h3 id="possible-improvements">Possible Improvements</h3>
<ol>
<li>In my pathfinding algorithm, I don't search for the diagonal paths which lengthens the "short path" as I wanted the robot to face <code>the waste</code> or <code>the destination</code> from either sides of the square and not the corners.</li>
<li>Making swarm robots instead of using only one.</li>
<li>Making the code object-oriented.</li>
<li>Adding grippers to grab the waste instead of the 5-second delay and drop the waste on its destination.</li>
</ol>
<blockquote>
<p><em>We had added the functionalities of gripping and swarm navigation when using this bot on a Robotics Competition in Nepal called <code>Yantra Swarmanoid</code> but decided to remove it on this showcase, though the code to grab and drop the waste is still in there in 'main.py'.</em></p>
</blockquote>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>Manoid: Communication</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;esp-mosquitto&#x2F;"/>
        <updated>2023-12-31T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;esp-mosquitto&#x2F;</id>
        <content type="html"><![CDATA[
          <p><img src="https://scientiac.space/images/manoid/led_esp.jpg" alt="Esp with Led" /></p>
<h2 id="introduction">Introduction</h2>
<p>Building a clueless robot isn't an easy task and I am only in the beginning of it. This report will discuss on how to setup the microcontroller boards and how the communication will work for project <code>manoid</code> (A waste management robot). Also, the much difficult image processing and mapping is on the way, which I should be working on instead of writing this but I'll leave that for next year. Communication seems like a simple topic to work on for now.</p>
<blockquote>
<p><strong>Note :</strong> <em>I wrote the code for the bot <a href="https://scientiac.space/blog/yantra-bot/">manoid</a> in arduino's '.ino' instead of using micropython's '.py' but micropython can be used to do the same as well.</em></p>
</blockquote>
<h3 id="requirements">Requirements:</h3>
<table><thead><tr><th><strong>Category</strong></th><th><strong>Component</strong></th></tr></thead><tbody>
<tr><td>Hardware</td><td>ESP8266 Microcontroller</td></tr>
<tr><td>Firmware</td><td>MicroPython (for receiving)</td></tr>
<tr><td>Software</td><td>Python (for publishing)</td></tr>
<tr><td>Software</td><td>esptool</td></tr>
<tr><td>Software</td><td>mosquitto (for serving)</td></tr>
<tr><td>Software</td><td>adafruit-ampy</td></tr>
</tbody></table>
<h2 id="basic-setup">Basic Setup</h2>
<h3 id="flashing-firmware">Flashing Firmware</h3>
<p>Micropython is an implementation of Python 3 that includes a small subset of the Python standard library and is optimised to run on microcontrollers and in constrained environments. The microcontroller I am using is the ESP8266 (NodeMCU). Flashing it with micropython was easy (for me), I've been flashing things since years. It goes like this:</p>
<ol>
<li>Install <code>esptool</code> and erase flash your ESP8266 first.</li>
</ol>
<blockquote>
<p>You should first confirm that /dev/ttyUSB0 is your device which you want to flash <code>micropython</code> on.</p>
</blockquote>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FABD2F;">    esptool.py</span><span style="color: #D3869B;"> --port</span><span style="color: #B8BB26;"> /dev/ttyUSB0 erase_flash</span></span>
<span class="giallo-l"></span></code></pre>
<ol start="2">
<li>Then flash the <a rel="external" href="https://micropython.org/download/ESP8266_GENERIC/">latest firmware</a> of ESP8266.</li>
</ol>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FABD2F;">    esptool.py</span><span style="color: #D3869B;"> --port</span><span style="color: #B8BB26;"> /dev/ttyUSB0</span><span style="color: #D3869B;"> --baud 460800</span><span style="color: #B8BB26;"> write_flash</span><span style="color: #D3869B;"> --flash_size=detect 0</span><span style="color: #8EC07C;"> &lt;</span><span style="color: #B8BB26;">path to the .bin file</span><span> (firmware)</span><span style="color: #8EC07C;">&gt;</span></span>
<span class="giallo-l"></span></code></pre>
<p>The default flashing mode worked on my first <code>ESP8266</code> but when I tried to flash it to another <code>ESP8266</code> it flashes successfully but didn't let me access the repl. So, I had to set the flashing mode to <code>dout</code>.</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FABD2F;">    esptool.py</span><span style="color: #D3869B;"> --port</span><span style="color: #B8BB26;"> /dev/ttyUSB0</span><span style="color: #D3869B;"> --baud 460800</span><span style="color: #B8BB26;"> write_flash</span><span style="color: #D3869B;"> --flash_size=detect --flash_mode</span><span style="color: #B8BB26;"> dout</span><span style="color: #D3869B;"> 0</span><span style="color: #8EC07C;"> &lt;</span><span style="color: #B8BB26;">path to the .bin file</span><span> (firmware)</span><span style="color: #8EC07C;">&gt;</span></span>
<span class="giallo-l"></span></code></pre>
<ol start="3">
<li>Check if everything is working by connecting to the <code>micropython repl</code>. You can use <code>screen</code> or <code>tmux</code> or your own solution to connect to the <code>repl</code>. Here is how you can use screen:</li>
</ol>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FABD2F;">    screen</span><span style="color: #B8BB26;"> /dev/ttyUSB0</span><span style="color: #D3869B;"> 115200</span></span>
<span class="giallo-l"></span></code></pre>
<p>The above command gives you a blank screen, when you hit enter you'll get the prompt, type <code>help</code> and hit enter. This should show up:</p>
<p><img src="https://scientiac.space/images/manoid/repl.png" alt="repl" /></p>
<h3 id="mqtt">MQTT</h3>
<p>I am sure you played with the <code>repl</code> and now it's time to push some scripts to run in it. For now we will focus on using <code>MQTT</code> protocol to transfer data from one machine to another.</p>
<h4 id="an-overview-of-how-mqtt-works">An overview of how MQTT works</h4>
<ol>
<li>A MQTT client establishes a connection with the MQTT broker.</li>
<li>Once connected, the client can either publish messages, subscribe to specific messages, or do both.</li>
<li>When the MQTT broker receives a message, it forwards it to subscribers who are interested.</li>
</ol>
<blockquote>
<p>Here, <strong>server</strong> will be <code>mosquitto</code> running on the computer <strong>publisher</strong> will be the <code>python script</code> on the computer and <strong>subscriber</strong> will be the <code>ESP8266</code> running micropython. [Message will be sent from python script through mosquitto server to ESP8266]</p>
</blockquote>
<h4 id="mosquitto">Mosquitto</h4>
<p>To set the mosquitto server first we should allow port <code>1883</code> on your firewall. I am using a custom configuration file for now. So, make a file named <code>mosquitto.conf</code> and put the following lines to allow all connections:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>    listener 1883</span></span>
<span class="giallo-l"><span>    allow_anonymous true</span></span>
<span class="giallo-l"></span></code></pre>
<p>then run the server by the following command:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FABD2F;">    mosquitto</span><span style="color: #D3869B;"> -c</span><span style="color: #B8BB26;"> ./mosquitto.conf</span></span>
<span class="giallo-l"></span></code></pre>
<p>This is how it'll look when a client named <code>tesseraclient</code> connects to the server:</p>
<p><img src="https://scientiac.space/images/manoid/mosquitto.png" alt="mosquitto" /></p>
<h3 id="pushing-scripts-to-the-microcontroller">Pushing Scripts to the Microcontroller</h3>
<p>There are two important files that MicroPython looks for in the root of its filesystem.  These files contain MicroPython code that will be executed whenever the board is powered up or reset (i.e. it 'boots').  These files are:</p>
<h4 id="boot-py">boot.py</h4>
<p>This file is run first on power up/reset and should contain low-level code that sets up the board to finish booting.</p>
<h4 id="main-py">main.py</h4>
<p>If this file exists it's run after boot.py and should contain any main script that you want to run when the board is powered up or reset.</p>
<p>To push the scripts I am using <code>adafruit-ampy</code> but the official way to push files is using their <a rel="external" href="https://learn.adafruit.com/micropython-basics-esp8266-webrepl/access-webrepl">webrepl</a>.</p>
<p>Using ampy you can push scripts with the following command:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="shellscript"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FABD2F;">    ampy</span><span style="color: #D3869B;"> -p</span><span style="color: #B8BB26;"> /dev/ttyUSB0 put</span><span style="color: #8EC07C;"> &lt;</span><span style="color: #B8BB26;">filename.p</span><span>y</span><span style="color: #8EC07C;">&gt;</span></span>
<span class="giallo-l"></span></code></pre><h2 id="programming">Programming</h2>
<h3 id="publisher">Publisher</h3>
<p>Firstly a python script on the computer to send messages, it sends <code>on</code> and <code>off</code> in the interval of 500ms with topic <code>led</code> to the mosquitto server:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="python"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> time</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> paho</span><span style="color: #A89984;">.</span><span>mqtt</span><span style="color: #A89984;">.</span><span>client</span><span style="color: #FB4934;"> as</span><span> mqtt</span></span>
<span class="giallo-l"><span style="color: #D3869B;font-weight: bold;">    BROKER_ADDRESS</span><span style="color: #A89984;">:</span><span style="color: #D3869B;"> 000.000</span><span style="color: #A89984;">.</span><span>00</span><span style="color: #A89984;">.</span><span>00</span><span style="color: #928374;font-style: italic;"> # IP address of the device running the mosquitto server</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    def</span><span style="color: #8EC07C;"> on_connect</span><span style="color: #A89984;">(</span><span style="color: #83A598;">client</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> userdata</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> flags</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> rc</span><span style="color: #A89984;">):</span></span>
<span class="giallo-l"><span style="color: #FB4934;">        if</span><span> rc</span><span style="color: #8EC07C;"> ==</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">            print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Connected to broker</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span style="color: #FB4934;">        else</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">            print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Connection failed with code</span><span style="color: #A89984;">&quot;,</span><span style="color: #D5C4A1;"> rc</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    def</span><span style="color: #8EC07C;"> on_disconnect</span><span style="color: #A89984;">(</span><span style="color: #83A598;">client</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> userdata</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> rc</span><span style="color: #A89984;">):</span></span>
<span class="giallo-l"><span style="color: #FE8019;">        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Disconnected from broker</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    def</span><span style="color: #8EC07C;"> establish_connection</span><span style="color: #A89984;">():</span></span>
<span class="giallo-l"><span>        client_id</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">tesserver</span><span style="color: #A89984;">&quot;</span></span>
<span class="giallo-l"><span>        client</span><span style="color: #8EC07C;"> =</span><span> mqtt</span><span style="color: #A89984;">.</span><span style="color: #83A598;">Client</span><span style="color: #A89984;">(</span><span style="color: #83A598;">client_id</span><span style="color: #8EC07C;">=</span><span style="color: #D5C4A1;">client_id</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>        client</span><span style="color: #A89984;">.</span><span>on_connect</span><span style="color: #8EC07C;"> =</span><span> on_connect</span></span>
<span class="giallo-l"><span>        client</span><span style="color: #A89984;">.</span><span>on_disconnect</span><span style="color: #8EC07C;"> =</span><span> on_disconnect</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>        client</span><span style="color: #A89984;">.</span><span style="color: #83A598;">connect</span><span style="color: #A89984;">(</span><span style="color: #D3869B;font-weight: bold;">BROKER_ADDRESS</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 1883</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 60</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">        return</span><span> client</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>    led_topic</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">led</span><span style="color: #A89984;">&quot;</span></span>
<span class="giallo-l"><span>    client</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> establish_connection</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>    client</span><span style="color: #A89984;">.</span><span style="color: #83A598;">publish</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">led_topic</span><span style="color: #A89984;">, &quot;</span><span style="color: #B8BB26;">off</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>    time</span><span style="color: #A89984;">.</span><span style="color: #83A598;">sleep</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">500</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>    client</span><span style="color: #A89984;">.</span><span style="color: #83A598;">publish</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">led_topic</span><span style="color: #A89984;">, &quot;</span><span style="color: #B8BB26;">off</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>    time</span><span style="color: #A89984;">.</span><span style="color: #83A598;">sleep</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">500</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span></code></pre><h3 id="subscriber">Subscriber</h3>
<h4 id="boot-py-1">boot.py</h4>
<p>This will start when I plug the esp to the power supply. No need to connect via <code>webrepl</code> and start manually. Generally it's not recommended to touch the <code>boot.py</code> file. <code>main.py</code> should be used instead but this is I who programming the microcontroller so <code>boot.py</code> it is.</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="python"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> esp</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> os</span><span style="color: #A89984;">,</span><span> machine</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> gc</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> webrepl</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>    webrepl</span><span style="color: #A89984;">.</span><span style="color: #83A598;">start</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"><span>    gc</span><span style="color: #A89984;">.</span><span style="color: #83A598;">collect</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> network</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> time</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> machine</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">    # Wi-Fi configuration</span></span>
<span class="giallo-l"><span>    ssid</span><span style="color: #8EC07C;"> =</span><span>  abcdef</span><span style="color: #928374;font-style: italic;"> #WIFI_SSID</span></span>
<span class="giallo-l"><span>    password</span><span style="color: #8EC07C;"> =</span><span style="color: #D3869B;"> 12345678</span><span style="color: #928374;font-style: italic;"> #WIFI_PASSWORD</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">    # Function to connect to Wi-Fi</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    def</span><span style="color: #8EC07C;"> connect_wifi</span><span style="color: #A89984;">():</span></span>
<span class="giallo-l"><span>        wlan</span><span style="color: #8EC07C;"> =</span><span> network</span><span style="color: #A89984;">.</span><span style="color: #83A598;">WLAN</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">network</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">STA_IF</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>        wlan</span><span style="color: #A89984;">.</span><span style="color: #83A598;">active</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">True</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">        if not</span><span> wlan</span><span style="color: #A89984;">.</span><span style="color: #83A598;">isconnected</span><span style="color: #A89984;">():</span></span>
<span class="giallo-l"><span style="color: #FE8019;">            print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Connecting to WiFi...</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>            wlan</span><span style="color: #A89984;">.</span><span style="color: #83A598;">connect</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">ssid</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> password</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">            # wlan.connect(ssid)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">            while not</span><span> wlan</span><span style="color: #A89984;">.</span><span style="color: #83A598;">isconnected</span><span style="color: #A89984;">():</span></span>
<span class="giallo-l"><span>                time</span><span style="color: #A89984;">.</span><span style="color: #83A598;">sleep</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">1</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FE8019;">        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Connected to WiFi</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">    # Connect to Wi-Fi</span></span>
<span class="giallo-l"><span style="color: #83A598;">    connect_wifi</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">    # Check if Wi-Fi connection is successful before executing mqtt.py</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span> network</span><span style="color: #A89984;">.</span><span style="color: #83A598;">WLAN</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">network</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">STA_IF</span><span style="color: #A89984;">).</span><span style="color: #83A598;">isconnected</span><span style="color: #A89984;">():</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">        # Execute mqtt.py</span></span>
<span class="giallo-l"><span style="color: #FB4934;">        try</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FB4934;">            import</span><span> mqtt</span><span style="color: #928374;font-style: italic;">  # Replace &#39;mqtt&#39; with the actual name of your Python script</span></span>
<span class="giallo-l"><span style="color: #FB4934;">        except</span><span style="color: #FABD2F;"> Exception</span><span style="color: #FB4934;"> as</span><span> e</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">            print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Error executing mqtt.py:</span><span style="color: #A89984;">&quot;,</span><span style="color: #D5C4A1;"> e</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span></code></pre><h4 id="mqtt-py">mqtt.py</h4>
<p>Upon connecting to the WIFI successfully the above script will import this file and things magically happen.</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="python"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> machine</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    from</span><span> umqtt</span><span style="color: #A89984;">.</span><span>simple</span><span style="color: #FB4934;"> import</span><span> MQTTClient</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    import</span><span> time</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    from</span><span> secrets</span><span style="color: #FB4934;"> import</span><span style="color: #D3869B;font-weight: bold;"> BROKER_ADDRESS</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">    # MQTT configuration</span></span>
<span class="giallo-l"><span>    client_id</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">teserraclient</span><span style="color: #A89984;">&quot;</span></span>
<span class="giallo-l"><span>    broker_address</span><span style="color: #8EC07C;"> =</span><span style="color: #D3869B;"> 000.000</span><span style="color: #A89984;">.</span><span>00</span><span style="color: #A89984;">.</span><span>00</span><span style="color: #928374;font-style: italic;"> # IP address of the device running the mosquitto server</span></span>
<span class="giallo-l"><span>    led_topic</span><span style="color: #8EC07C;"> =</span><span style="color: #FB4934;"> b</span><span style="color: #A89984;">&quot;</span><span style="color: #B8BB26;">led</span><span style="color: #A89984;">&quot;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">    # LED Pin</span></span>
<span class="giallo-l"><span>    led_pin</span><span style="color: #8EC07C;"> =</span><span> machine</span><span style="color: #A89984;">.</span><span style="color: #83A598;">Pin</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">15</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> machine</span><span style="color: #A89984;">.</span><span style="color: #D5C4A1;">Pin</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">OUT</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    def</span><span style="color: #8EC07C;"> connect_mqtt</span><span style="color: #A89984;">():</span></span>
<span class="giallo-l"><span>        c</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> MQTTClient</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">client_id</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> broker_address</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>        c</span><span style="color: #A89984;">.</span><span style="color: #83A598;">set_callback</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">callback</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">        while</span><span style="color: #D3869B;"> True</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FB4934;">            try</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span>                c</span><span style="color: #A89984;">.</span><span style="color: #83A598;">connect</span><span style="color: #A89984;">(</span><span style="color: #83A598;">clean_session</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">False</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Connected to MQTT broker.</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                c</span><span style="color: #A89984;">.</span><span style="color: #83A598;">subscribe</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">led_topic</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                return</span><span> c</span></span>
<span class="giallo-l"><span style="color: #FB4934;">            except</span><span style="color: #FABD2F;"> OSError</span><span style="color: #FB4934;"> as</span><span> e</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                print</span><span style="color: #A89984;">(</span><span style="color: #FB4934;">f</span><span style="color: #B8BB26;">&quot;Connection error: </span><span style="color: #D3869B;">{</span><span style="color: #D5C4A1;">e</span><span style="color: #D3869B;">}</span><span style="color: #B8BB26;">&quot;</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Retrying in 5 seconds...</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                time</span><span style="color: #A89984;">.</span><span style="color: #83A598;">sleep</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">5</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    def</span><span style="color: #8EC07C;"> callback</span><span style="color: #A89984;">(</span><span style="color: #83A598;">topic</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> msg</span><span style="color: #A89984;">):</span></span>
<span class="giallo-l"><span style="color: #FE8019;">        print</span><span style="color: #A89984;">(</span><span style="color: #FB4934;">f</span><span style="color: #B8BB26;">&quot;Received message on topic </span><span style="color: #D3869B;">{</span><span style="color: #D5C4A1;">topic</span><span style="color: #A89984;">.</span><span style="color: #83A598;">decode</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">utf-8</span><span style="color: #A89984;">&#39;)</span><span style="color: #D3869B;">}</span><span style="color: #B8BB26;">: </span><span style="color: #D3869B;">{</span><span style="color: #D5C4A1;">msg</span><span style="color: #A89984;">.</span><span style="color: #83A598;">decode</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">utf-8</span><span style="color: #A89984;">&#39;)</span><span style="color: #D3869B;">}</span><span style="color: #B8BB26;">&quot;</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">        if</span><span> topic</span><span style="color: #8EC07C;"> ==</span><span> led_topic</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FB4934;">            if</span><span> msg</span><span style="color: #8EC07C;"> ==</span><span style="color: #FB4934;"> b</span><span style="color: #A89984;">&quot;</span><span style="color: #B8BB26;">on</span><span style="color: #A89984;">&quot;:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Turning on the LED</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                led_pin</span><span style="color: #A89984;">.</span><span style="color: #83A598;">on</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"><span style="color: #FB4934;">            elif</span><span> msg</span><span style="color: #8EC07C;"> ==</span><span style="color: #FB4934;"> b</span><span style="color: #A89984;">&quot;</span><span style="color: #B8BB26;">off</span><span style="color: #A89984;">&quot;:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Turning off the LED</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                led_pin</span><span style="color: #A89984;">.</span><span style="color: #83A598;">off</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>    mqtt_client</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> connect_mqtt</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span> mqtt_client</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Waiting for messages...</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span style="color: #FB4934;">        while</span><span style="color: #D3869B;"> True</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FB4934;">            try</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span>                mqtt_client</span><span style="color: #A89984;">.</span><span style="color: #83A598;">wait_msg</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"><span style="color: #FB4934;">            except</span><span style="color: #FABD2F;"> OSError</span><span style="color: #FB4934;"> as</span><span> e</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                print</span><span style="color: #A89984;">(</span><span style="color: #FB4934;">f</span><span style="color: #B8BB26;">&quot;Error: </span><span style="color: #D3869B;">{</span><span style="color: #D5C4A1;">e</span><span style="color: #D3869B;">}</span><span style="color: #B8BB26;">&quot;</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Reconnecting...</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                mqtt_client</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> connect_mqtt</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                if not</span><span> mqtt_client</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                    break</span></span>
<span class="giallo-l"></span></code></pre><h3 id="finally">Finally</h3>
<p>If everything works after installing all the python dependencies you will see this if you are supplying power to your microcontroller using a computer that can accept serial in upon doing a soft reboot and running your python (publisher) script from your computer.</p>
<p><img src="https://scientiac.space/images/manoid/working.png" alt="final" /></p>
<p>This indicates that the publisher i.e. <code>python script</code> has connected to the server i.e. <code>mosquitto</code> and is now sending <code>on</code> and <code>off</code> messages to the server with topic <code>led</code> which then is sent to the subscriber i.e. <code>ESP8266</code> which is interpreted by the microcontroller as a command to enable and disable the set GPIO pin i.e. pin <code>15</code> if you look closely at the code.</p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>Droidian: Linux Smartphone Experience</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;droidian&#x2F;"/>
        <updated>2023-11-30T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;droidian&#x2F;</id>
        <content type="html"><![CDATA[
          <h2 id="my-device">My Device</h2>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>            #####           scientiac@mobius</span></span>
<span class="giallo-l"><span>           #######          ---------------</span></span>
<span class="giallo-l"><span>           ##O#O##          OS: Droidian trixie aarch64</span></span>
<span class="giallo-l"><span>           #######          Host: wcd937x Audio Codec AB IDP EXCALIBUR</span></span>
<span class="giallo-l"><span>         ###########        Kernel: 4.14-288-xiaomi-miatoll</span></span>
<span class="giallo-l"><span>        #############       Uptime: 1 hour, 40 mins</span></span>
<span class="giallo-l"><span>       ###############      Packages: 1945 (dpkg), 390 (nix-user), 47 (nix-default), 28 (flatpak)</span></span>
<span class="giallo-l"><span>       ################     Shell: bash 5.2.15</span></span>
<span class="giallo-l"><span>      #################     Resolution: 1080x2400x60x164823</span></span>
<span class="giallo-l"><span>    #####################   DE: GNOME (actually &#39;phosh&#39;)</span></span>
<span class="giallo-l"><span>    #####################   WM: weston (actually &#39;phoc&#39;)</span></span>
<span class="giallo-l"><span>      #################     Theme: adw-gtk3 [GTK2/3]</span></span>
<span class="giallo-l"><span>                            Icons: Papirus [GTK2/3]</span></span>
<span class="giallo-l"><span>                            Terminal: kgx</span></span>
<span class="giallo-l"><span>                            CPU: Qualcomm SM7125 (8) @ 1.804GHz</span></span>
<span class="giallo-l"><span>                            Memory: 2370MiB / 5587MiB</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>    * neofetch gathered some false data so i have manually edited this text blob.</span></span>
<span class="giallo-l"></span></code></pre><h2 id="firstly">Firstly...</h2>
<p>I have been playing around and testing Droidian on my <em>Xaomi Redmi Note 9 Pro Max (miatoll - excalibur)</em> as a daily driver since November 17th. Before this I had tried Droidian about a year ago on this very device.</p>
<blockquote>
<p>Note: The screenshots attached here are of my customized version of phosh and GTK colors, the default UI will look different.</p>
</blockquote>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/droidian/lockscreen.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/droidian/overview.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<h3 id="a-quick-then-v-s-now">A quick THEN v/s NOW</h3>
<p>Then, the UI was not tailored for the device I was using, it was vanilla phosh with clock in the center of the bar which was covered by the punch-hole of my device and the notification panel was also not aligned correctly to the device. Now, it's fine and the UI is just how it should be for the device.</p>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/droidian/old_tele.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/droidian/new_tele.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<p>Then, The Camera was not working at all. Now, the <code>droidian-camera</code> does work but it's laggy. Though it technically can capture videos the frame rate drops very randomly and the video comes out to be choppy. The file size of the choppy video is also very high.</p>
<p>Then, Apps like telegram and messenger from Firefox did not connect to calls at all. Now, microphone is generally supported by all apps and voice calling via other apps work fine.</p>
<p>Then, Waydroid used to work without much problems. Now, upon launching Waydroid and trying to video-call the entire shell crashes and the only way to bring back the UI is by a forced restart.</p>
<h2 id="experience">Experience</h2>
<p>Gnome Asia 2023 is starting Tomorrow, I travelled from Dharan to Kathmandu with Droidian on my phone and it feels like I am handicapped using this device coming from android.</p>
<h3 id="voice-calls">Voice Calls</h3>
<p>Since it is a phone it should be able to make calls and it does. Though my device supports two SIMs, droidian on my device only detects and uses one so, I had to let go of my secondary SIM.</p>
<img alt="Gnome Calls" src="https://scientiac.space/images/droidian/call_dialing.png" style="width: 15rem;"/>
<h3 id="notifications">Notifications</h3>
<p>Apps should be running in the background to be able to make notifications, and the other thing is I am not notified with sound or vibration of any of my texts messages be it from apps like <code>fractal</code>, <code>nheko</code>, <code>telegram-desktop</code> or even <code>gnome-messages</code> even if the app is running in the background when the screen is off.</p>
<p>The <code>gnome-calls</code> app is the only app I know which can make "noisy notifications" when my phone is locked and the screen is off. So, I only know if anyone is calling me on my number but nothing if they use any other platform.</p>
<img alt="Notification/ Quick Settings Panel" src="https://scientiac.space/images/droidian/notif_panel.png" style="width: 15rem;"/>
<h3 id="maps">Maps</h3>
<p>Yes, Gnome Maps works on this device but it does not show my real time location. And coming from using Google Maps, it isn't a very pleasant of an experience.</p>
<img alt="Gnome Maps" src="https://scientiac.space/images/droidian/gnome_maps.png" style="width: 15rem;"/>
<h3 id="waydroid">Waydroid</h3>
<p>The waydroid experience was buggy when used in the default condition but it worked fine under a nested <code>weston</code> session. But, <code>weston</code> comes with a drawback. The resolution when used in the default <code>phoc</code> is great everything looks crisp but when used in a nested <code>weston</code> session the resolution is low and it's only usable. At least waydroid doesn't crash the whole phoc session when used inside the nested <code>weston</code> session.</p>
<p>The first image below is with 400dpi (in default <code>phoc</code> session) whereas the second one is on 1700dpi (in <code>weston</code> session) set from android developer settings.</p>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/droidian/waydroid_phoc.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/droidian/waydroid_weston.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<p>Though <code>gnome-maps</code> do not show real time location, google maps from waydroid is able to do it. But, it requires some time to load everything.</p>
<h3 id="web-browsing">Web Browsing</h3>
<p>Web browsing is fine in droidian. Firefox with a mobile focused custom layout is the default browser. There are some glitches here and there on firefox caused by the inability to adapt to a mobile form but normal day to day browsing can be done nicely. Various websites, Facebook, Instagram, YouTube, everything works fine but not as smooth as using on desktop or android and it is expected because I am technically running a whole desktop application on a smartphone.</p>
<img alt="Youtube on Firefox" src="https://scientiac.space/images/droidian/firefox_yt.png" style="width: 15rem;"/>
<p>The desktop extensions work fine, but the UI to edit them from their window glitches on my device. So, the extensions which work by default work the best.</p>
<h3 id="social-media-and-messaging">Social Media and Messaging</h3>
<p>Well, mastodon is my favourite social media ever and <code>Tuba</code> is a dedicated app from flathub which works more than fine for it. YouTube, Facebook and Instagram can be used from the Firefox browser. For communication, <code>telegram-desktop</code> works fine, so does <code>Nheko</code> for matrix supporting voice calls as well, other matrix clients like <code>Fractal</code> work too. And there always are web based clients that work in responsive mode.</p>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/droidian/masto_pan.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/droidian/masto_home.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<p>It's not always gtk apps, qt apps are convergent too; <code>telegram-desktop</code> and <code>nheko</code> are two examples. They are the only "apps" which support voice calls natively and even video calls if it detects a camera (it doesn't in mine).</p>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/droidian/nheko.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/droidian/fractal.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<h3 id="file-sharing">File Sharing</h3>
<p>Sharing files is surprisingly important in our day-to-day life. Since it is a whole Linux system <code>ssh</code> can be used to transfer and receive files as well as modify it remotely. For a more GUI approach the best way to share files from any kind of device is the <code>magic-wormhole</code> protocol. And <code>warp</code> being the GTK convergent app for Droidian, it has made my life a lot easier.</p>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/droidian/warp_home.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/droidian/warp_send.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<p>I am writing this blog on my laptop while taking screenshots from my phone and sending them to my laptop using warp.</p>
<h2 id="customization">Customization</h2>
<p>The thing that introduced Linux to me and made it interesting was the customizability of it. I encountered Linux when YouTube recommended a video of KDE while I was searching for ways to customize windows. So, you can pretty much assume that I don't use things without giving some of my touch to it.</p>
<h3 id="colors-and-textures">Colors and Textures</h3>
<p>As I have mentioned before, the screenshots attached here are of my customized version of phosh and GTK colors. So, since it is basically a GTK environment, <code>gradience</code> works like a charm for changing the color palette of the apps. And for the phosh shell, some custom <code>gtk.css</code> on <code>~/.config/gtk-3.0/</code> will do the trick.</p>
<p>Here, I am using the <code>gruvbox</code> theme to customize my shell.</p>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/droidian/gradience.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/droidian/gradience_css.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="css"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #8EC07C;">    phosh-home</span><span style="color: #A89984;">, .</span><span style="color: #B8BB26;">phosh-overview</span><span style="color: #A89984;">,</span><span style="color: #8EC07C;"> phosh-app-grid</span><span style="color: #A89984;"> {</span></span>
<span class="giallo-l"><span style="color: #FE8019;">        background-color</span><span style="color: #A89984;">: #</span><span style="color: #D3869B;">282828</span><span style="color: #A89984;">;</span><span style="color: #928374;font-style: italic;"> /* gruvbox primary color */</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #8EC07C;">    phosh-top-panel</span><span style="color: #A89984;">,</span><span style="color: #8EC07C;"> phosh-lockscreen</span><span style="color: #A89984;">, .</span><span style="color: #B8BB26;">phosh-lockshield</span><span style="color: #A89984;"> {</span></span>
<span class="giallo-l"><span style="color: #FE8019;">        background-image</span><span style="color: #A89984;">:</span><span> url</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">file:///home/droidian/Desktop/image.png</span><span style="color: #A89984;">&#39;);</span><span style="color: #928374;font-style: italic;"> /* a blurred version of wallpaper or any preferred image */</span></span>
<span class="giallo-l"><span style="color: #FE8019;">        background-size</span><span style="color: #A89984;">:</span><span style="color: #D3869B;"> cover</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #FE8019;">        background-position</span><span style="color: #A89984;">:</span><span style="color: #D3869B;"> center</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span>    {</span></span>
<span class="giallo-l"></span></code></pre><h3 id="shell-tweaks">Shell Tweaks</h3>
<p>Changing icons, showing battery percentage in the bar, setting themes enabling Application filter, everything was done with an app called <code>postmarketos-tweaks</code> which I compiled from the source.</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>    https://gitlab.com/postmarketOS/postmarketos-tweaks</span></span>
<span class="giallo-l"></span></code></pre><div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/droidian/pmos.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/droidian/pmos_phosh.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<h3 id="scaling">Scaling</h3>
<p>The default scale is good for the eyes but for me it was a bit too big. I wanted more stuff on this small screen of my phone. For that I went to <code>/etc/phosh/phoc.ini</code> and set the following:</p>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="plain"><span class="giallo-l"></span>
<span class="giallo-l"><span>    [output:HWCOMPOSER-1]</span></span>
<span class="giallo-l"><span>    scale = 2.5</span></span>
<span class="giallo-l"></span></code></pre><h2 id="finally">Finally...</h2>
<p>The whole Linux ecosystem isn't convergent yet, and many apps go beyond the screen resulting in hidden buttons and texts. To tackle that problem, Droidian comes with <code>Mobile Settings</code> that helps to scale down particular apps so that they fit on the screen.</p>
<div class="gallery" style="display:flex; flex-wrap: wrap;">
  <img src="https://scientiac.space/images/droidian/mobile_settings.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
  <img src="https://scientiac.space/images/droidian/mobile_settings_comp.png" style="width: 15rem; padding:1rem;border-radius: 1.75rem;">
</div>
<h3 id="it-would-have-been-much-better-if-it-had">It would have been much better if it had...</h3>
<p>Some features like, the semi-automatic screen rotation that android has nowadays which would show a small prompt to rotate the screen upon rotating the device but without automatically rotating it. Also, gestures in apps like video players to scroll and double taps to skip, which would make the droidian experience much better. And, maybe a qr-code scanner to connect to wifi networks.</p>
<h3 id="lastly-some-mentions">Lastly, Some Mentions</h3>
<p>Waydroid has been a life saver for using essential video calling apps and surprisingly banking apps. But, the default waydroid experience is very buggy. It is not the fault of droidian devs though, waydroid is a completely different project.</p>
<p>Gnome Online Accounts made it very easy to sync my contacts saved on google contacts, calender events, emails on droidian. It also connected my google drive with <code>nautilus [Gnome Files]</code> making it easy to upload and access files from my drive.</p>
<h3 id="so">So,</h3>
<p>My experience with Linux on Mobile was interesting, though it has a lot to improve, I didn't expect it to be "functional enough" that I could use it for days without diving back to android. I will use this for some more days, maybe until the Gnome Asia 2023 event ends.</p>
<p>There is lot more to try but, I want to end this experiment for now.</p>
<p>Goodnight!</p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>Project Pieyes</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;gesture-controlled-arm&#x2F;"/>
        <updated>2023-06-01T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;gesture-controlled-arm&#x2F;</id>
        <content type="html"><![CDATA[
          <p><img src="https://scientiac.space/images/pieyes.gif" alt="Pieyes" /></p>
<h2 id="introduction">Introduction</h2>
<p>The purpose of this report is to document the process of building a CV robotic arm prototype using Arduino. The arm is designed to be controlled with natural hand gestures removing the need to look at the buttons on a screen or a controller to control it.</p>
<h3 id="materials-used">Materials Used:</h3>
<ol>
<li>Arduino Uno</li>
<li>16 Channel Servo driver</li>
<li>Buck Converter</li>
<li>Jumper Cables</li>
<li>3D Printed MK2 Chassis</li>
<li>4 Servos</li>
<li>A Portable Computer with Camera</li>
</ol>
<h3 id="software-used">Software Used:</h3>
<ol>
<li>Arduino IDE V2</li>
<li>Python 3</li>
</ol>
<h3 id="design">Design:</h3>
<p>The first step in building the CV controlled arm is to make a schematic of it. The arm is based on the MK2 Model, which is pretty easy to 3D-print and assemble. 4 servos are used for the base, the lower arm, the upper arm and the gripper. The servos are connected to the Servo Driver and the Servo Driver is connected to 5 volts DC power. The Arduino is used to control the Servo Driver to send PWM signals to servo.</p>
<p>The decisions for what signals to send for recognized gestures handled by a Python script which sends serial to Arduino via the USB. The Arduino receives the signal which is now converted to mechanical output.</p>
<h3 id="construction">Construction:</h3>
<p>The assembly of the base is a bit tricky with gears and servos to be attached to it, but the upper part is easily attached. The four servos are placed on the right place according to MK2 schematics and are connected to 16 Channel Servo Driver. (I connected 0,2,4 and 7 as base, lower arm, upper arm and gripper respectively on the Servo Driver.) While connecting the Servo Driver to Arduino; the VCC is connected to 5 volts and Grounds of Arduino and Servo Driver are connected. From Arduino the analogue 5 pin is connected to SCL and analogue 4 pin is connected to SDA respectively.(This connects the Servo Driver to the Arduino.)</p>
<p>The servo diver is connected to 5 volts DC converted from 12 volts power supply using a buck converter. USB connected to the Arduino supplies power to Arduino as well as the Servo Driver but not the Servos connected to the Driver. The USB also doubles as a data transmission device to send serial input to the Arduino from the laptop running the python script.</p>
<h3 id="programming">Programming</h3>
<h4 id="in-arduino">In Arduino:</h4>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="cpp"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #A89984;">#</span><span style="color: #8EC07C;">include</span><span style="color: #A89984;"> &lt;</span><span style="color: #B8BB26;">Wire.h</span><span style="color: #A89984;">&gt;</span></span>
<span class="giallo-l"><span style="color: #A89984;">#</span><span style="color: #8EC07C;">include</span><span style="color: #A89984;"> &lt;</span><span style="color: #B8BB26;">Adafruit_PWMServoDriver.h</span><span style="color: #A89984;">&gt;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">// called this way, it uses the default address 0x40</span></span>
<span class="giallo-l"><span>Adafruit_PWMServoDriver pwm </span><span style="color: #8EC07C;">=</span><span style="color: #FABD2F;"> Adafruit_PWMServoDriver</span><span style="color: #A89984;">(</span><span style="color: #B8BB26;">0x</span><span style="color: #D3869B;">40</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #A89984;">#</span><span style="color: #8EC07C;">define</span><span style="color: #FABD2F;"> SERVOMIN</span><span style="color: #D3869B;"> 100</span><span style="color: #928374;font-style: italic;">   // This is the &#39;minimum&#39; pulse length count (out of 4096)</span></span>
<span class="giallo-l"><span style="color: #A89984;">#</span><span style="color: #8EC07C;">define</span><span style="color: #FABD2F;"> SERVOMAX</span><span style="color: #D3869B;"> 450</span><span style="color: #928374;font-style: italic;">   // This is the &#39;maximum&#39; pulse length count (out of 4096)</span></span>
<span class="giallo-l"><span style="color: #A89984;">#</span><span style="color: #8EC07C;">define</span><span style="color: #FABD2F;"> SERVO_FREQ</span><span style="color: #D3869B;"> 50</span><span style="color: #928374;font-style: italic;">  // Analog servos run at ~50 Hz updates</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">// our servo # counter</span></span>
<span class="giallo-l"><span style="color: #FE8019;">uint8_t</span><span> servonum </span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #FE8019;">char</span><span> prevSerial </span><span style="color: #8EC07C;">=</span><span style="color: #A89984;"> &#39;</span><span style="color: #D3869B;">\0</span><span style="color: #A89984;">&#39;;</span></span>
<span class="giallo-l"><span style="color: #FE8019;">char</span><span> data</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">// Setting the default state of the arm.</span></span>
<span class="giallo-l"><span style="color: #FE8019;">int</span><span> val1 </span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;"> 312</span><span style="color: #A89984;">,</span><span> val2 </span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;"> 350</span><span style="color: #A89984;">,</span><span> val3 </span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;"> 174</span><span style="color: #A89984;">,</span><span> val4 </span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FE8019;">void</span><span style="color: #FABD2F;"> setup</span><span style="color: #A89984;">() {</span></span>
<span class="giallo-l"><span style="color: #83A598;">  Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">begin</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">9600</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">  Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Running...</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #83A598;">  pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">begin</span><span style="color: #A89984;">();</span></span>
<span class="giallo-l"><span style="color: #83A598;">  pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setOscillatorFrequency</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">27000000</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">  pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setPWMFreq</span><span style="color: #A89984;">(</span><span>SERVO_FREQ</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FABD2F;">  delay</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">10</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #A89984;">}</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FE8019;">void</span><span style="color: #FABD2F;"> loop</span><span style="color: #A89984;">() {</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">  // checking if serial is available or not and setting values to &quot;data&quot; as soon as the serial changes</span></span>
<span class="giallo-l"><span style="color: #FB4934;">  if</span><span style="color: #A89984;"> (</span><span style="color: #83A598;">Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">available</span><span style="color: #A89984;">()</span><span style="color: #8EC07C;"> &gt;</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">) {</span></span>
<span class="giallo-l"><span>    data </span><span style="color: #8EC07C;">=</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">read</span><span style="color: #A89984;">();</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span style="color: #A89984;"> (</span><span>data </span><span style="color: #8EC07C;">==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">W</span><span style="color: #A89984;">&#39;) {</span></span>
<span class="giallo-l"><span style="color: #FB4934;">      if</span><span style="color: #A89984;"> (</span><span>val4 </span><span style="color: #8EC07C;">&lt;</span><span> SERVOMAX</span><span style="color: #A89984;">) {</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Gripper IN</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(</span><span>val4</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setPWM</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">7</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span><span> val4</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span>        val4 </span><span style="color: #8EC07C;">+=</span><span style="color: #D3869B;"> 4</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #A89984;">      }</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span style="color: #A89984;"> (</span><span>data </span><span style="color: #8EC07C;">==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">A</span><span style="color: #A89984;">&#39;) {</span></span>
<span class="giallo-l"><span style="color: #FB4934;">      if</span><span style="color: #A89984;"> (</span><span>val4 </span><span style="color: #8EC07C;">&gt;</span><span> SERVOMIN</span><span style="color: #A89984;">) {</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Gripper OUT</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(</span><span>val4</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setPWM</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">7</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span><span> val4</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span>        val4 </span><span style="color: #8EC07C;">-=</span><span style="color: #D3869B;"> 4</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #A89984;">      }</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span style="color: #A89984;"> (</span><span>data </span><span style="color: #8EC07C;">==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">Y</span><span style="color: #A89984;">&#39;) {</span></span>
<span class="giallo-l"><span style="color: #FB4934;">      if</span><span style="color: #A89984;"> (</span><span>val2 </span><span style="color: #8EC07C;">&lt;</span><span> SERVOMAX</span><span style="color: #A89984;">) {</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Arm Base IN</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(</span><span>val2</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setPWM</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">2</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span><span> val2</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span>        val2 </span><span style="color: #8EC07C;">+=</span><span style="color: #D3869B;"> 4</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #A89984;">      }</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span style="color: #A89984;"> (</span><span>data </span><span style="color: #8EC07C;">==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">C</span><span style="color: #A89984;">&#39;) {</span></span>
<span class="giallo-l"><span style="color: #FB4934;">      if</span><span style="color: #A89984;"> (</span><span>val2 </span><span style="color: #8EC07C;">&gt;</span><span> SERVOMIN</span><span style="color: #A89984;">) {</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Arm Base OUT</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(</span><span>val2</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setPWM</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">2</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span><span> val2</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span>        val2 </span><span style="color: #8EC07C;">-=</span><span style="color: #D3869B;"> 4</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #A89984;">      }</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span style="color: #A89984;"> (</span><span>data </span><span style="color: #8EC07C;">==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">B</span><span style="color: #A89984;">&#39;) {</span></span>
<span class="giallo-l"><span style="color: #FB4934;">      if</span><span style="color: #A89984;"> (</span><span>val3 </span><span style="color: #8EC07C;">&lt;</span><span> SERVOMAX</span><span style="color: #A89984;">) {</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Arm Top IN</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(</span><span>val3</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setPWM</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">4</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span><span> val3</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span>        val3 </span><span style="color: #8EC07C;">+=</span><span style="color: #D3869B;"> 4</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #A89984;">      }</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span style="color: #A89984;"> (</span><span>data </span><span style="color: #8EC07C;">==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">X</span><span style="color: #A89984;">&#39;) {</span></span>
<span class="giallo-l"><span style="color: #FB4934;">      if</span><span style="color: #A89984;"> (</span><span>val3 </span><span style="color: #8EC07C;">&gt;</span><span> SERVOMIN</span><span style="color: #A89984;">) {</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Arm Top OUT</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(</span><span>val3</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setPWM</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">4</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span><span> val3</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span>        val3 </span><span style="color: #8EC07C;">-=</span><span style="color: #D3869B;"> 4</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #A89984;">      }</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span style="color: #A89984;"> (</span><span>data </span><span style="color: #8EC07C;">==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">D</span><span style="color: #A89984;">&#39;) {</span></span>
<span class="giallo-l"><span style="color: #FB4934;">      if</span><span style="color: #A89984;"> (</span><span>val1 </span><span style="color: #8EC07C;">&lt;</span><span> SERVOMAX</span><span style="color: #A89984;">) {</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Base IN</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(</span><span>val1</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setPWM</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">0</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span><span> val1</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span>        val1 </span><span style="color: #8EC07C;">+=</span><span style="color: #D3869B;"> 4</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #A89984;">      }</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span style="color: #A89984;"> (</span><span>data </span><span style="color: #8EC07C;">==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">Z</span><span style="color: #A89984;">&#39;) {</span></span>
<span class="giallo-l"><span style="color: #FB4934;">      if</span><span style="color: #A89984;"> (</span><span>val1 </span><span style="color: #8EC07C;">&gt;</span><span> SERVOMIN</span><span style="color: #A89984;">) {</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Base IN</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(</span><span>val1</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span style="color: #83A598;">        pwm</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">setPWM</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">0</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">,</span><span> val1</span><span style="color: #A89984;">);</span></span>
<span class="giallo-l"><span>        val1 </span><span style="color: #8EC07C;">-=</span><span style="color: #D3869B;"> 4</span><span style="color: #A89984;">;</span></span>
<span class="giallo-l"><span style="color: #A89984;">      }</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span style="color: #A89984;"> (</span><span>data </span><span style="color: #8EC07C;">==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">S</span><span style="color: #A89984;">&#39;) {</span></span>
<span class="giallo-l"><span style="color: #83A598;">      Serial</span><span style="color: #A89984;">.</span><span style="color: #FABD2F;">println</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">stop</span><span style="color: #A89984;">&quot;);</span></span>
<span class="giallo-l"><span style="color: #A89984;">    }</span></span>
<span class="giallo-l"><span style="color: #A89984;">  }</span></span>
<span class="giallo-l"><span style="color: #A89984;">}</span></span>
<span class="giallo-l"></span></code></pre><h4 id="in-laptop">In Laptop:</h4>
<pre class="giallo" style="color: #EBDBB2; background-color: #282828;"><code data-lang="python"><span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">#!/bin/python</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">import</span><span> cv2</span></span>
<span class="giallo-l"><span style="color: #FB4934;">import</span><span> mediapipe</span><span style="color: #FB4934;"> as</span><span> mp</span></span>
<span class="giallo-l"><span style="color: #FB4934;">import</span><span> math</span></span>
<span class="giallo-l"><span style="color: #FB4934;">from</span><span> serial</span><span style="color: #FB4934;"> import</span><span> Serial</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>mp_drawing</span><span style="color: #8EC07C;"> =</span><span> mp</span><span style="color: #A89984;">.</span><span>solutions</span><span style="color: #A89984;">.</span><span>drawing_utils</span></span>
<span class="giallo-l"><span>mp_hands</span><span style="color: #8EC07C;"> =</span><span> mp</span><span style="color: #A89984;">.</span><span>solutions</span><span style="color: #A89984;">.</span><span>hands</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">def</span><span style="color: #8EC07C;"> calculate_distance</span><span style="color: #A89984;">(</span><span style="color: #83A598;">x1</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> y1</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> x2</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> y2</span><span style="color: #A89984;">):</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    return</span><span> math</span><span style="color: #A89984;">.</span><span style="color: #83A598;">sqrt</span><span style="color: #A89984;">((</span><span style="color: #D5C4A1;">x2</span><span style="color: #8EC07C;"> -</span><span style="color: #D5C4A1;"> x1</span><span style="color: #A89984;">)</span><span style="color: #8EC07C;">**</span><span style="color: #D3869B;">2</span><span style="color: #8EC07C;"> +</span><span style="color: #A89984;"> (</span><span style="color: #D5C4A1;">y2</span><span style="color: #8EC07C;"> -</span><span style="color: #D5C4A1;"> y1</span><span style="color: #A89984;">)</span><span style="color: #8EC07C;">**</span><span style="color: #D3869B;">2</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">def</span><span style="color: #8EC07C;"> is_fist</span><span style="color: #A89984;">(</span><span style="color: #83A598;">landmarks</span><span style="color: #A89984;">):</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">    # Check if all finger tips are below their corresponding middle joints</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    return</span><span style="color: #A89984;"> (</span></span>
<span class="giallo-l"><span>        landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">THUMB_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">THUMB_IP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #FB4934;"> and</span></span>
<span class="giallo-l"><span>        landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">INDEX_FINGER_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">INDEX_FINGER_PIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #FB4934;"> and</span></span>
<span class="giallo-l"><span>        landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">MIDDLE_FINGER_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">MIDDLE_FINGER_PIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #FB4934;"> and</span></span>
<span class="giallo-l"><span>        landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">RING_FINGER_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">RING_FINGER_PIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #FB4934;"> and</span></span>
<span class="giallo-l"><span>        landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">PINKY_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">PINKY_PIP</span><span style="color: #A89984;">].</span><span>y</span></span>
<span class="giallo-l"><span style="color: #A89984;">    )</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">def</span><span style="color: #8EC07C;"> get_hand_side</span><span style="color: #A89984;">(</span><span style="color: #83A598;">landmarks</span><span style="color: #A89984;">):</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">    # Check if the wrist is to the left or right of the index finger tip</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    if</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">WRIST</span><span style="color: #A89984;">].</span><span>x</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">INDEX_FINGER_TIP</span><span style="color: #A89984;">].</span><span>x</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FB4934;">        return</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Left</span><span style="color: #A89984;">&quot;</span></span>
<span class="giallo-l"><span style="color: #FB4934;">    else</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FB4934;">        return</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Right</span><span style="color: #A89984;">&quot;</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">def</span><span style="color: #8EC07C;"> main</span><span style="color: #A89984;">():</span></span>
<span class="giallo-l"><span>    cap</span><span style="color: #8EC07C;"> =</span><span> cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">VideoCapture</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">0</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">    with</span><span> mp_hands</span><span style="color: #A89984;">.</span><span style="color: #83A598;">Hands</span><span style="color: #A89984;">(</span><span style="color: #83A598;">max_num_hands</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">1</span><span style="color: #A89984;">)</span><span style="color: #FB4934;"> as</span><span> hands</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FB4934;">        while</span><span> cap</span><span style="color: #A89984;">.</span><span style="color: #83A598;">isOpened</span><span style="color: #A89984;">():</span></span>
<span class="giallo-l"><span>            ret</span><span style="color: #A89984;">,</span><span> frame</span><span style="color: #8EC07C;"> =</span><span> cap</span><span style="color: #A89984;">.</span><span style="color: #83A598;">read</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">            if not</span><span> ret</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Unable to capture frame.</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                break</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">            # Flip the frame horizontally to mirror the image</span></span>
<span class="giallo-l"><span>            frame</span><span style="color: #8EC07C;"> =</span><span> cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">flip</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">frame</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 1</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">            # Convert the image from BGR to RGB</span></span>
<span class="giallo-l"><span>            image_rgb</span><span style="color: #8EC07C;"> =</span><span> cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">cvtColor</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">frame</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> cv2</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">COLOR_BGR2RGB</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">            # Process the image with MediaPipe Hands</span></span>
<span class="giallo-l"><span>            results</span><span style="color: #8EC07C;"> =</span><span> hands</span><span style="color: #A89984;">.</span><span style="color: #83A598;">process</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">image_rgb</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">            # Check for hand landmarks</span></span>
<span class="giallo-l"><span style="color: #FB4934;">            if</span><span> results</span><span style="color: #A89984;">.</span><span>multi_hand_landmarks</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                for</span><span> hand_landmarks</span><span style="color: #FB4934;"> in</span><span> results</span><span style="color: #A89984;">.</span><span>multi_hand_landmarks</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Draw hand landmarks on the image</span></span>
<span class="giallo-l"><span>                    mp_drawing</span><span style="color: #A89984;">.</span><span style="color: #83A598;">draw_landmarks</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">frame</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> hand_landmarks</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> mp_hands</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">HAND_CONNECTIONS</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Get the coordinates of the index finger and thumb landmarks</span></span>
<span class="giallo-l"><span>                    index_finger</span><span style="color: #8EC07C;"> =</span><span> hand_landmarks</span><span style="color: #A89984;">.</span><span>landmark</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">INDEX_FINGER_TIP</span><span style="color: #A89984;">]</span></span>
<span class="giallo-l"><span>                    thumb</span><span style="color: #8EC07C;"> =</span><span> hand_landmarks</span><span style="color: #A89984;">.</span><span>landmark</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">THUMB_TIP</span><span style="color: #A89984;">]</span></span>
<span class="giallo-l"><span>                    wrist</span><span style="color: #8EC07C;"> =</span><span> hand_landmarks</span><span style="color: #A89984;">.</span><span>landmark</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">WRIST</span><span style="color: #A89984;">]</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Convert landmark coordinates to pixel values</span></span>
<span class="giallo-l"><span>                    height</span><span style="color: #A89984;">,</span><span> width</span><span style="color: #A89984;">,</span><span> _</span><span style="color: #8EC07C;"> =</span><span> frame</span><span style="color: #A89984;">.</span><span>shape</span></span>
<span class="giallo-l"><span>                    x1</span><span style="color: #A89984;">,</span><span> y1</span><span style="color: #8EC07C;"> =</span><span style="color: #FABD2F;"> int</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">index_finger</span><span style="color: #A89984;">.</span><span style="color: #D5C4A1;">x</span><span style="color: #8EC07C;"> *</span><span style="color: #D5C4A1;"> width</span><span style="color: #A89984;">),</span><span style="color: #FABD2F;"> int</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">index_finger</span><span style="color: #A89984;">.</span><span style="color: #D5C4A1;">y</span><span style="color: #8EC07C;"> *</span><span style="color: #D5C4A1;"> height</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                    x2</span><span style="color: #A89984;">,</span><span> y2</span><span style="color: #8EC07C;"> =</span><span style="color: #FABD2F;"> int</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">thumb</span><span style="color: #A89984;">.</span><span style="color: #D5C4A1;">x</span><span style="color: #8EC07C;"> *</span><span style="color: #D5C4A1;"> width</span><span style="color: #A89984;">),</span><span style="color: #FABD2F;"> int</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">thumb</span><span style="color: #A89984;">.</span><span style="color: #D5C4A1;">y</span><span style="color: #8EC07C;"> *</span><span style="color: #D5C4A1;"> height</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Calculate the distance between the index finger and thumb</span></span>
<span class="giallo-l"><span>                    distance</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> calculate_distance</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">x1</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> y1</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> x2</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> y2</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Count the number of fingers that are up</span></span>
<span class="giallo-l"><span>                    fingers_up</span><span style="color: #8EC07C;"> =</span><span style="color: #D3869B;"> 0</span></span>
<span class="giallo-l"><span>                    landmarks</span><span style="color: #8EC07C;"> =</span><span> hand_landmarks</span><span style="color: #A89984;">.</span><span>landmark</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                    if</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">THUMB_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">THUMB_IP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span>                        fingers_up</span><span style="color: #8EC07C;"> +=</span><span style="color: #D3869B;"> 1</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                    if</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">INDEX_FINGER_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">INDEX_FINGER_PIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span>                        fingers_up</span><span style="color: #8EC07C;"> +=</span><span style="color: #D3869B;"> 1</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                    if</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">MIDDLE_FINGER_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">MIDDLE_FINGER_PIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span>                        fingers_up</span><span style="color: #8EC07C;"> +=</span><span style="color: #D3869B;"> 1</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                    if</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">RING_FINGER_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">RING_FINGER_PIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span>                        fingers_up</span><span style="color: #8EC07C;"> +=</span><span style="color: #D3869B;"> 1</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                    if</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">PINKY_TIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #8EC07C;"> &lt;</span><span> landmarks</span><span style="color: #A89984;">[</span><span>mp_hands</span><span style="color: #A89984;">.</span><span>HandLandmark</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">PINKY_PIP</span><span style="color: #A89984;">].</span><span>y</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span>                        fingers_up</span><span style="color: #8EC07C;"> +=</span><span style="color: #D3869B;"> 1</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Determine if the hand is right or left</span></span>
<span class="giallo-l"><span>                    hand_side</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> get_hand_side</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">hand_landmarks</span><span style="color: #A89984;">.</span><span style="color: #D5C4A1;">landmark</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Determine if there is a fist or not</span></span>
<span class="giallo-l"><span>                    is_hand_fist</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> is_fist</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">hand_landmarks</span><span style="color: #A89984;">.</span><span style="color: #D5C4A1;">landmark</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Display the number of fingers, distance, hand side, and fist status on the image</span></span>
<span class="giallo-l"><span>                    cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">putText</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">frame</span><span style="color: #A89984;">,</span><span style="color: #FABD2F;"> str</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">fingers_up</span><span style="color: #A89984;">), (</span><span style="color: #D3869B;">10</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 30</span><span style="color: #A89984;">),</span><span style="color: #D5C4A1;"> cv2</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">FONT_HERSHEY_SIMPLEX</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 1</span><span style="color: #A89984;">, (</span><span style="color: #D3869B;">0</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 255</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">),</span><span style="color: #D3869B;"> 2</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                    cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">putText</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">frame</span><span style="color: #A89984;">,</span><span style="color: #FABD2F;"> str</span><span style="color: #A89984;">(</span><span style="color: #FABD2F;">int</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">distance</span><span style="color: #A89984;">)), (</span><span style="color: #D3869B;">10</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 70</span><span style="color: #A89984;">),</span><span style="color: #D5C4A1;"> cv2</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">FONT_HERSHEY_SIMPLEX</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 1</span><span style="color: #A89984;">, (</span><span style="color: #D3869B;">0</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 255</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">),</span><span style="color: #D3869B;"> 2</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                    cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">putText</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">frame</span><span style="color: #A89984;">,</span><span style="color: #D5C4A1;"> hand_side</span><span style="color: #A89984;">, (</span><span style="color: #D3869B;">10</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 110</span><span style="color: #A89984;">),</span><span style="color: #D5C4A1;"> cv2</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">FONT_HERSHEY_SIMPLEX</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 1</span><span style="color: #A89984;">, (</span><span style="color: #D3869B;">0</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 255</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">),</span><span style="color: #D3869B;"> 2</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                    cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">putText</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">frame</span><span style="color: #A89984;">,</span><span style="color: #FABD2F;"> str</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">is_hand_fist</span><span style="color: #A89984;">), (</span><span style="color: #D3869B;">10</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 150</span><span style="color: #A89984;">),</span><span style="color: #D5C4A1;"> cv2</span><span style="color: #A89984;">.</span><span style="color: #D3869B;font-weight: bold;">FONT_HERSHEY_SIMPLEX</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 1</span><span style="color: #A89984;">, (</span><span style="color: #D3869B;">0</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 255</span><span style="color: #A89984;">,</span><span style="color: #D3869B;"> 0</span><span style="color: #A89984;">),</span><span style="color: #D3869B;"> 2</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Combine the values</span></span>
<span class="giallo-l"><span>                    combined_values</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> [</span><span>fingers_up</span><span style="color: #A89984;">,</span><span style="color: #FABD2F;"> int</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">distance</span><span style="color: #A89984;">),</span><span> hand_side</span><span style="color: #A89984;">,</span><span style="color: #FABD2F;"> str</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">is_hand_fist</span><span style="color: #A89984;">)]</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Print the combined values</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                    print</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">combined_values</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">                    # Print the corresponding letter based on the conditions</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                    if</span><span> fingers_up</span><span style="color: #8EC07C;"> ==</span><span style="color: #D3869B;"> 2</span><span style="color: #FB4934;"> and</span><span> distance</span><span style="color: #8EC07C;"> &lt;</span><span style="color: #D3869B;"> 60</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Gripper IN</span><span style="color: #A89984;">&quot;)</span><span>                    </span></span>
<span class="giallo-l"><span>                        input_value</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">A</span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">/dev/ttyUSB0</span><span style="color: #A89984;">&#39;,</span><span style="color: #D3869B;"> 9600</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> timeout</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">0.01</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #A89984;">.</span><span style="color: #83A598;">write</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">input_value</span><span style="color: #A89984;">.</span><span style="color: #83A598;">encode</span><span style="color: #A89984;">())</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">                    elif</span><span> fingers_up</span><span style="color: #8EC07C;"> ==</span><span style="color: #D3869B;"> 2</span><span style="color: #FB4934;"> and</span><span> distance</span><span style="color: #8EC07C;"> &gt;</span><span style="color: #D3869B;"> 60</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Gripper OUT</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                        input_value</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">W</span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">/dev/ttyUSB0</span><span style="color: #A89984;">&#39;,</span><span style="color: #D3869B;"> 9600</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> timeout</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">0.01</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #A89984;">.</span><span style="color: #83A598;">write</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">input_value</span><span style="color: #A89984;">.</span><span style="color: #83A598;">encode</span><span style="color: #A89984;">())</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">                    elif</span><span> fingers_up</span><span style="color: #8EC07C;"> ==</span><span style="color: #D3869B;"> 4</span><span style="color: #FB4934;"> and</span><span> hand_side</span><span style="color: #8EC07C;"> ==</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Right</span><span style="color: #A89984;">&quot;</span><span style="color: #FB4934;"> and not</span><span> is_hand_fist</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Arm Base IN</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                        input_value</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">C</span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">/dev/ttyUSB0</span><span style="color: #A89984;">&#39;,</span><span style="color: #D3869B;"> 9600</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> timeout</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">0.01</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #A89984;">.</span><span style="color: #83A598;">write</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">input_value</span><span style="color: #A89984;">.</span><span style="color: #83A598;">encode</span><span style="color: #A89984;">())</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">                    elif</span><span> fingers_up</span><span style="color: #8EC07C;"> ==</span><span style="color: #D3869B;"> 4</span><span style="color: #FB4934;"> and</span><span> hand_side</span><span style="color: #8EC07C;"> ==</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Left</span><span style="color: #A89984;">&quot;</span><span style="color: #FB4934;"> and not</span><span> is_hand_fist</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Arm Base OUT</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                        input_value</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">Y</span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">/dev/ttyUSB0</span><span style="color: #A89984;">&#39;,</span><span style="color: #D3869B;"> 9600</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> timeout</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">0.01</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #A89984;">.</span><span style="color: #83A598;">write</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">input_value</span><span style="color: #A89984;">.</span><span style="color: #83A598;">encode</span><span style="color: #A89984;">())</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">                    elif not</span><span> is_hand_fist</span><span style="color: #FB4934;"> and</span><span> hand_side</span><span style="color: #8EC07C;"> ==</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Right</span><span style="color: #A89984;">&quot;:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Arm Top IN</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                        input_value</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">B</span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">/dev/ttyUSB0</span><span style="color: #A89984;">&#39;,</span><span style="color: #D3869B;"> 9600</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> timeout</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">0.01</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #A89984;">.</span><span style="color: #83A598;">write</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">input_value</span><span style="color: #A89984;">.</span><span style="color: #83A598;">encode</span><span style="color: #A89984;">())</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">                    elif not</span><span> is_hand_fist</span><span style="color: #FB4934;"> and</span><span> hand_side</span><span style="color: #8EC07C;"> ==</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Left</span><span style="color: #A89984;">&quot;:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Arm Top OUT</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                        input_value</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">X</span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">/dev/ttyUSB0</span><span style="color: #A89984;">&#39;,</span><span style="color: #D3869B;"> 9600</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> timeout</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">0.01</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #A89984;">.</span><span style="color: #83A598;">write</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">input_value</span><span style="color: #A89984;">.</span><span style="color: #83A598;">encode</span><span style="color: #A89984;">())</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">                    elif</span><span> fingers_up</span><span style="color: #8EC07C;"> ==</span><span style="color: #D3869B;"> 5</span><span style="color: #FB4934;"> and</span><span> hand_side</span><span style="color: #8EC07C;"> ==</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Right</span><span style="color: #A89984;">&quot;:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Base IN</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                        input_value</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">D</span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">/dev/ttyUSB0</span><span style="color: #A89984;">&#39;,</span><span style="color: #D3869B;"> 9600</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> timeout</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">0.01</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #A89984;">.</span><span style="color: #83A598;">write</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">input_value</span><span style="color: #A89984;">.</span><span style="color: #83A598;">encode</span><span style="color: #A89984;">())</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">                    elif</span><span> fingers_up</span><span style="color: #8EC07C;"> ==</span><span style="color: #D3869B;"> 5</span><span style="color: #FB4934;"> and</span><span> hand_side</span><span style="color: #8EC07C;"> ==</span><span style="color: #A89984;"> &quot;</span><span style="color: #B8BB26;">Left</span><span style="color: #A89984;">&quot;:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">Base OUT</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                        input_value</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">Z</span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">/dev/ttyUSB0</span><span style="color: #A89984;">&#39;,</span><span style="color: #D3869B;"> 9600</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> timeout</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">0.01</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #A89984;">.</span><span style="color: #83A598;">write</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">input_value</span><span style="color: #A89984;">.</span><span style="color: #83A598;">encode</span><span style="color: #A89984;">())</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">                    else</span><span style="color: #A89984;">:</span></span>
<span class="giallo-l"><span style="color: #FE8019;">                        print</span><span style="color: #A89984;">(&quot;</span><span style="color: #B8BB26;">STOP</span><span style="color: #A89984;">&quot;)</span></span>
<span class="giallo-l"><span>                        input_value</span><span style="color: #8EC07C;"> =</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">S</span><span style="color: #A89984;">&#39;</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #8EC07C;"> =</span><span style="color: #83A598;"> Serial</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">/dev/ttyUSB0</span><span style="color: #A89984;">&#39;,</span><span style="color: #D3869B;"> 9600</span><span style="color: #A89984;">,</span><span style="color: #83A598;"> timeout</span><span style="color: #8EC07C;">=</span><span style="color: #D3869B;">0.01</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"><span>                        ardu</span><span style="color: #A89984;">.</span><span style="color: #83A598;">write</span><span style="color: #A89984;">(</span><span style="color: #D5C4A1;">input_value</span><span style="color: #A89984;">.</span><span style="color: #83A598;">encode</span><span style="color: #A89984;">())</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">            # Display the mirrored image with landmarks</span></span>
<span class="giallo-l"><span>            cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">imshow</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">Finger Tracking</span><span style="color: #A89984;">&#39;,</span><span style="color: #D5C4A1;"> frame</span><span style="color: #A89984;">)</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #928374;font-style: italic;">            # Exit loop when &#39;q&#39; is pressed</span></span>
<span class="giallo-l"><span style="color: #FB4934;">            if</span><span> cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">waitKey</span><span style="color: #A89984;">(</span><span style="color: #D3869B;">1</span><span style="color: #A89984;">)</span><span style="color: #8EC07C;"> &amp;</span><span style="color: #FE8019;"> 0x</span><span style="color: #D3869B;">FF</span><span style="color: #8EC07C;"> ==</span><span style="color: #FE8019;"> ord</span><span style="color: #A89984;">(&#39;</span><span style="color: #B8BB26;">q</span><span style="color: #A89984;">&#39;):</span></span>
<span class="giallo-l"><span style="color: #FB4934;">                break</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span>    cap</span><span style="color: #A89984;">.</span><span style="color: #83A598;">release</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"><span>    cv2</span><span style="color: #A89984;">.</span><span style="color: #83A598;">destroyAllWindows</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"></span>
<span class="giallo-l"><span style="color: #FB4934;">if</span><span style="color: #D3869B;"> __name__</span><span style="color: #8EC07C;"> ==</span><span style="color: #A89984;"> &#39;</span><span style="color: #B8BB26;">__main__</span><span style="color: #A89984;">&#39;:</span></span>
<span class="giallo-l"><span style="color: #83A598;">    main</span><span style="color: #A89984;">()</span></span>
<span class="giallo-l"></span></code></pre><h3 id="testing">Testing:</h3>
<p>The arm was completed, and it was time to test it. The servos were connected to power supply and the USB was connected to the Arduino. With the necessary code uploaded to the Arduino, the python script was run, and hand gestures were read from the computer which then converted to Serial signals and the code in Arduino interprets those Serial signals as per the uploaded code. Here, in the first trial reading the Front and Back side of the hand gave same results, I replaced the code for Left and Right aligned hand, which showed Right when I showed my right-hand palm to the Camera, and left when I showed my right-hand back to the camera, and vice-versa for the left hand. Which fixed the issue.</p>
<h3 id="challenges-and-solutions">Challenges and Solutions:</h3>
<p>There were not many challenges to make a working prototype which my arm is at the moment. But further improvement on the gestures are going to be challenging like; to read and interpret natural human arm movements in digital form and to match the movement of robot arm with an actual human arm.</p>
<h3 id="conclusion">Conclusion:</h3>
<p>In conclusion, the CV robotic arm is a working prototype for better control of devices requiring less time to adapt. It helps people to be familiar with using complex devices like robotic arm in a very short period of time.</p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
    <entry>
        <title>Project Firefly</title>
        <link href="https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;arduino-firefly&#x2F;"/>
        <updated>2023-04-28T00:00:00+00:00</updated>
        <author><name>scientiac</name></author>
        <id>https:&#x2F;&#x2F;scientiac.space&#x2F;blog&#x2F;arduino-firefly&#x2F;</id>
        <content type="html"><![CDATA[
          <p><img src="https://scientiac.space/images/firefly.jpg" alt="Firefly" /></p>
<h2 id="introduction">Introduction</h2>
<p>The purpose of this report is to document the process of building a fire extinguishing and gas sensing car using Arduino. The car is designed to detect fire using a flame IR sensor and go towards it to extinguish it if necessary. It also detects gas leaks and alerts the user via SMS. This report will detail the steps taken to design and build the car, as well as the challenges encountered and the solutions implemented.</p>
<h3 id="materials-used">Materials Used:</h3>
<ol>
<li>Arduino Uno</li>
<li>3 Flame IR Sensors</li>
<li>MQ-2 Gas Sensor</li>
<li>Motor Driver</li>
<li>2 DC Motor</li>
<li>Servo Motor</li>
<li>Water Pump</li>
<li>Fire Extinguisher (tested with water)</li>
<li>SIM800L GSM Module</li>
<li>Breadboard and Jumper Wires</li>
<li>Power Supply (Battery)</li>
</ol>
<h3 id="design">Design:</h3>
<p>The first step in building the fire extinguishing and gas sensing car was to design a schematic. The car is powered by an Arduino Uno microcontroller, which controls the sensors, motors, and other components. The 3 flame IR sensors are used to detect fire from three different directions, and the MQ-2 gas sensor is used to detect gas leaks. The motor driver is used to control the DC and servo motors, which drive the car and the water pump, respectively. The fire extinguisher reservoir is mounted on top of the car and the pump pushes the extinguisher from the pipe which is spread by the back-and-forth motion of the servo motor. The SIM800L GSM module is used to send SMS alerts to the user in case of a gas leak.</p>
<h3 id="construction">Construction:</h3>
<p>Once the schematic was finalized, the next step was to build the car. The components were connected to the Arduino Uno using a breadboard and jumper wires. The flame IR sensors were mounted on the front of the car on in the front and two facing either sides, and the MQ-2 gas sensor was mounted on top. The DC motors were connected to the motor driver and were used to drive the car. The servo motor was connected to the L298N motor driver and was connected to the fire extinguisher. The water pump was connected to the Arduino Uno and was used to pump water from the reservoir to the fire extinguisher which moved in a to and fro motion to spread the water coming out of it.</p>
<h3 id="testing">Testing:</h3>
<p>Once the car was built, it was time to test it. The car was placed in a test environment and was subjected to various scenarios. The flame IR sensor was able to detect fire and direct the car towards it. The MQ-2 gas sensor was able to detect gas leaks and activate the SMS alert system. The fire extinguisher was successfully activated by the servo motor, and the water pump was able to pump water to the fire extinguisher.</p>
<h3 id="challenges-and-solutions">Challenges and Solutions:</h3>
<p>One of the major challenges encountered during the construction of the car was the calibration of the flame IR sensor. The sensor needed to be calibrated to detect the flame accurately and direct the car towards it. The heater connected to our room was also detected as a fire source which made it harder to test the bot. This was solved by testing the sensor with different fire sources and adjusting the code accordingly. Our test subject for demonstration was a burning paper which was used for the calibration of flame sensor.</p>
<p>Another challenge was the activation of the fire extinguisher. The servo motor had to be calibrated to activate the extinguisher at the right time, and the water pump had to pump the water at the right pressure. This was solved by adjusting the code and the components until the system worked correctly.</p>
<h3 id="conclusion">Conclusion:</h3>
<p>In conclusion, the fire extinguishing and gas sensing car using Arduino is a useful device that can prevent fires and detect gas leaks. The car is powered by an Arduino Uno microcontroller and uses sensors, motors, and other components to perform its functions. The car was designed and built with the help of a schematic, and was tested successfully. The challenges encountered during the construction were solved by adjusting the code and the components. The car can be further improved by adding more sensors and refining the code as the SMS functionality was still flaky.</p>

          <hr/>
          <p><i>You might be wondering how I know that you're awesome!</i><br/> Because I know you read this via RSS.</p>
        ]]></content>
    </entry>
</feed>
