<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Mark&#39;s Project Blog</title>
    <link>https://blog.fixermark.com/</link>
    <description>Recent content on Mark&#39;s Project Blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <copyright>Mark Tomczak</copyright>
    <lastBuildDate>Fri, 08 May 2026 20:43:19 -0400</lastBuildDate>
    <atom:link href="https://blog.fixermark.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>DPS Bot</title>
      <link>https://blog.fixermark.com/posts/2026/dps-bot/</link>
      <pubDate>Fri, 08 May 2026 20:43:19 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2026/dps-bot/</guid>
      <description>&lt;p&gt;So I decided to build a &lt;a href=&#34;https://mastodon.fixermark.com/@dpsbot&#34;&gt;bot in Mastodon&lt;/a&gt; that reports the damage you&amp;rsquo;re taking hourly.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;dpsbot-content.png&#34; alt=&#34;A screenshot of the UI for DPS Bot, showing a summary of its information and &amp;ldquo;Take 7d12 likelihood damage&amp;rdquo;, &amp;ldquo;Take 2d20 possible damage&amp;rdquo;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;This was a fun exercise and mostly an excuse to play with Rust. I&amp;rsquo;ll talk about the process a bit: the core, setting up the scripts to execute it, and then a Docker wrapper.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Documenting Your Org&#39;s Files</title>
      <link>https://blog.fixermark.com/posts/2026/documenting-your-orgs-files/</link>
      <pubDate>Sat, 02 May 2026 12:34:45 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2026/documenting-your-orgs-files/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been thinking as of late about the things that desktop computer users get&#xA;that we&amp;rsquo;ve decided isn&amp;rsquo;t worth giving software engineers in their own&#xA;infrastructure.&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t think I&amp;rsquo;ve ever met anyone who works at a big tech company who is&#xA;&lt;em&gt;happy&lt;/em&gt; with the status quo. The closest we get is less sad. And a lot of the&#xA;pain points are fixable, but nobody fixes them because they aren&amp;rsquo;t key business&#xA;needs. Setting aside, for now, the conversation of what that means (happy&#xA;engineers are more often than not more productive engineers), I&amp;rsquo;m going to&#xA;document some basic quality-of-life improvements as they come to mind and&#xA;provide some easy and more complicated suggestions for improving them.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Screenshots into emacs org files in Windows</title>
      <link>https://blog.fixermark.com/posts/2025/screenshots-into-org-files-in-windows/</link>
      <pubDate>Sat, 02 Aug 2025 21:28:58 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2025/screenshots-into-org-files-in-windows/</guid>
      <description>&lt;p&gt;Related to &lt;a href=&#34;https://blog.fixermark.com/posts/2025/i-cannot-recommend-etherpad-on-sandstorm-at-this-time/&#34;&gt;my previous post&lt;/a&gt;, I needed to resolve the need to quickly take screenshots from Windows and put them in an org file in emacs. This proved a bit more difficult than I&amp;rsquo;d hoped; triggering a screenshot in Windows from emacs is non-obvious, and my attempts to use &lt;code&gt;yank-media&lt;/code&gt; suggested that screenshots didn&amp;rsquo;t end up on the clipboard in a way emacs could see them. Other options I could find in melpa knew how to screenshot from XWindows, but not Windows.&lt;/p&gt;</description>
    </item>
    <item>
      <title>I Cannot Recommend Etherpad on Sandstorm at This Time</title>
      <link>https://blog.fixermark.com/posts/2025/i-cannot-recommend-etherpad-on-sandstorm-at-this-time/</link>
      <pubDate>Sat, 02 Aug 2025 15:40:19 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2025/i-cannot-recommend-etherpad-on-sandstorm-at-this-time/</guid>
      <description>&lt;p&gt;Lately, I&amp;rsquo;ve been using &lt;a href=&#34;https://etherpad.org/&#34;&gt;Etherpad&lt;/a&gt; on &lt;a href=&#34;https://sandstorm.org/&#34;&gt;Sandstorm&lt;/a&gt; to track notes and clues in the game &lt;a href=&#34;https://www.blueprincegame.com/&#34;&gt;Blue Prince&lt;/a&gt;. While it started okay, I cannot recommend it at this time for this application. What follows is the specific issues that I&amp;rsquo;ve encountered.&lt;/p&gt;&#xA;&lt;p&gt;Note that this may not mean it&amp;rsquo;s not fit for &lt;em&gt;any&lt;/em&gt; purpose, or that these things cannot be fixed (I haven&amp;rsquo;t figured out how to fix them). But here are the issues I&amp;rsquo;ve encountered, and then I&amp;rsquo;ll talk about what I&amp;rsquo;m doing instead.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Monitoring Home Network With Grafana, Loki, Prometheus, and Alloy in Docker (part 2)</title>
      <link>https://blog.fixermark.com/posts/2025/monitoring-home-network-grafana-loki-prometheus-alloy-2/</link>
      <pubDate>Mon, 28 Jul 2025 22:47:25 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2025/monitoring-home-network-grafana-loki-prometheus-alloy-2/</guid>
      <description>&lt;p&gt;In &lt;a href=&#34;https://blog.fixermark.com/posts/2025/monitoring-home-network-grafana-loki-prometheus-alloy/&#34;&gt;part 1&lt;/a&gt;, we discussed setting up Grafana, Loki, and Alloy. Here, we&amp;rsquo;ll dive into Prometheus setup.&lt;/p&gt;&#xA;&lt;p&gt;Prometheus differs from Loki in that Loki stores individual log entries. Prometheus is a time-series database: it stores individual &lt;em&gt;events&lt;/em&gt; (each of which can be tagged with specific labels) and it is specialized for running analysis, bucketing, and summaries on events.&lt;/p&gt;&#xA;&lt;div class=&#34;callout&#34;&gt;&#xA;  &lt;div class=&#34;inner&#34;&gt;&#xA;    &lt;div class=&#34;exclaim&#34;&gt;!&lt;/div&gt;&#xA;    &lt;div class=&#34;contents&#34;&gt;&#xA;      It&amp;rsquo;s unfortunate that we can&amp;rsquo;t use one datastore for both types of data, but that&amp;rsquo;s the tradeoff of using a bit more scalable / extensible framework; we have two datastores because they are specialized to store two kinds of data (and if you have a large deployment, they may even have two different scaling concerns!).&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The steps here, relative to what we&amp;rsquo;ve built, are pretty straightforward:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Monitoring Home Network With Grafana, Loki, Prometheus, and Alloy in Docker (part 1)</title>
      <link>https://blog.fixermark.com/posts/2025/monitoring-home-network-grafana-loki-prometheus-alloy/</link>
      <pubDate>Wed, 25 Jun 2025 09:53:52 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2025/monitoring-home-network-grafana-loki-prometheus-alloy/</guid>
      <description>&lt;p&gt;Having gotten to three whole nodes in my home network, I&amp;rsquo;ve decided it&amp;rsquo;s about time to get some centralized monitoring going. To that end, I&amp;rsquo;ve gone with what I&amp;rsquo;m (vaguely) familiar with: the &lt;a href=&#34;https://grafana.com/&#34;&gt;Grafana&lt;/a&gt; open source logs display and its accompanying pieces. Here, I&amp;rsquo;ll lay out approximately how I got working home monitoring set up after a couple missteps.&lt;/p&gt;&#xA;&lt;p&gt;Part 1 will focus on everything except Prometheus and then we&amp;rsquo;ll come back to that one in part 2.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Running Sandstorm From a Raid 1 Drive Array</title>
      <link>https://blog.fixermark.com/posts/2025/running-sandstorm-from-a-raid-1/</link>
      <pubDate>Sat, 22 Feb 2025 11:06:49 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2025/running-sandstorm-from-a-raid-1/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;sandstorm-ui.png&#34; alt=&#34;The UI of my Sandstorm instance&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;In my quest to back slowly towards the exits from total reliance on Google&amp;rsquo;s infrastructure, I&amp;rsquo;ve managed to stand up an instance of &lt;a href=&#34;https://sandstorm.org/&#34;&gt;Sandstorm&lt;/a&gt; on a small ZimaBoard. This has been successful; one thing I was very concerned about was storage reliability because I know if I&amp;rsquo;m rotating away from someone else&amp;rsquo;s Cloud, it&amp;rsquo;s up to me whether I lose data if these drives break. To that end, I put both two Seagate 2TB drives in a CENMATE 2-drive SATA enclosure and went about setting up a RAID-1.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Unstick Terminals in Emacs</title>
      <link>https://blog.fixermark.com/posts/2025/unstick-terminals-in-emacs/</link>
      <pubDate>Sat, 15 Feb 2025 19:28:27 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2025/unstick-terminals-in-emacs/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve used &lt;a href=&#34;https://github.com/manateelazycat/multi-term&#34;&gt;multi-term&lt;/a&gt; for years in emacs as my primary terminal interface. It works great, but occasionally while ssh&amp;rsquo;ing to another machine and using the &lt;code&gt;emacsclient -t&lt;/code&gt; interface (my common approach), the terminal gets stuck to a too-small size. This happens most commonly when my ssh session crashes and I have to start a new one.&lt;/p&gt;&#xA;&lt;p&gt;It turns out the cause of this is that the terminal is taking its measurements from the other emacs window it&amp;rsquo;s bound to, and if you unbind it, it&amp;rsquo;ll be willing to take measurements from a new window.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Fireplace on a Raspberry Pi</title>
      <link>https://blog.fixermark.com/posts/2025/fireplace-on-a-raspberry-pi/</link>
      <pubDate>Sun, 26 Jan 2025 21:33:07 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2025/fireplace-on-a-raspberry-pi/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;fireplace.jpg&#34; alt=&#34;A fireplace display in a dark-wood decorated room&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;After not too much work, I was able to finish up the fireplace in our front room. This was a small hack involving a Raspberry Pi. I&amp;rsquo;ll summarize what worked and then share a few thoughts on what didn&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-worked&#34;&gt;What worked&lt;/h2&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s the quick summary:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Formatted a new Raspberry Pi 4B with a fresh OS install.&lt;/li&gt;&#xA;&lt;li&gt;In the Raspberry Pi settings, set &lt;a href=&#34;https://www.raspberrypi.com/documentation/computers/configuration.html#boot-options-nonint&#34;&gt;boot to console&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Set up a default &lt;code&gt;fireplace&lt;/code&gt; user, install a 5-minute loopable video of a fireplace, and write a tiny script to invoke it. This lives in the &lt;code&gt;/home/fireplace/kiosk/play-fireplace.sh&lt;/code&gt; directory.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/usr/bin/sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cvlc -Lf fireplace-5min.mp4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I can test this here and confirm it works.&lt;/p&gt;</description>
    </item>
    <item>
      <title>WebGL Fire Shader Based on Fractal Brownian Motion</title>
      <link>https://blog.fixermark.com/posts/2025/webgl-fire-shader-based-on-fbm/</link>
      <pubDate>Wed, 22 Jan 2025 19:27:32 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2025/webgl-fire-shader-based-on-fbm/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;fire.png&#34; alt=&#34;A screenshot of the shader in action. It&amp;rsquo;s brighter than the one based on Xflame, and richer&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;This is a followup to my &lt;a href=&#34;https://blog.fixermark.com/posts/2025/webgl-fire-shader-based-on-xflame/&#34;&gt;previous post&lt;/a&gt; on building a shader based on Xflame. I won&amp;rsquo;t be covering much of the details of building it since they&amp;rsquo;ll be similar.&lt;/p&gt;&#xA;&lt;p&gt;You can see the shader in action &lt;a href=&#34;fbm_fire.html&#34;&gt;here&lt;/a&gt;. Feel free to pop it open and inspect the code as we go.&lt;/p&gt;&#xA;&lt;p&gt;There are two primary pieces worth talking about in this one: the noise source and the Fractal Brownian Motion algorithm. As always, &lt;a href=&#34;https://thebookofshaders.com/&#34;&gt;The Book of Shaders&lt;/a&gt; does a much better job of deep-diving on these topics than I intend to, so if you start to feel lost, I&amp;rsquo;ll provide links that you can read up on and come back.&lt;/p&gt;</description>
    </item>
    <item>
      <title>WebGL Fire Shader Based on Xflame</title>
      <link>https://blog.fixermark.com/posts/2025/webgl-fire-shader-based-on-xflame/</link>
      <pubDate>Sat, 18 Jan 2025 10:18:44 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2025/webgl-fire-shader-based-on-xflame/</guid>
      <description>&lt;p&gt;Over the holiday, we had the fun idea to put a TV in front of the fireplace we never turn on so we can run fireplace images on it.&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;https://blog.fixermark.com/posts/2025/webgl-fire-shader-based-on-xflame/livingroom.jpg&#34;&#xA;    alt=&#34;A livingroom with a TV in front of the fireplace showing a video of a fire&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Really ties the room together.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s been a joy, but it got me thinking about what it would take to put a fire visualizer on there instead of videos of fireplaces. To that end, I&amp;rsquo;ve dusted off my old knowledge of GLSL and taken the opportunity to start experimenting with making a fire effect with webgl shaders. This took me down a couple of fun paths!&lt;/p&gt;</description>
    </item>
    <item>
      <title>Recreating the Cortex Theme Journal in Emacs Org Mode</title>
      <link>https://blog.fixermark.com/posts/2024/recreating-the-cortex-theme-journal-in-emacs-org-mode/</link>
      <pubDate>Sun, 29 Dec 2024 17:52:03 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2024/recreating-the-cortex-theme-journal-in-emacs-org-mode/</guid>
      <description>&lt;p&gt;It&amp;rsquo;s the New Years season again, and that means resolutions. Usually. This time around, I&amp;rsquo;m trying something a little new. Inspired by &lt;a href=&#34;https://www.youtube.com/watch?v=fSwpe8r50_o&#34;&gt;CGP Grey&amp;rsquo;s video on the topic&lt;/a&gt;, I&amp;rsquo;m trying &amp;ldquo;theme system journaling.&amp;rdquo; But since I&amp;rsquo;m not very good at keeping physical journals, I&amp;rsquo;ve recapitulated the system in emacs using org-mode, &lt;a href=&#34;https://github.com/joaotavora/yasnippet&#34;&gt;yasnippet&lt;/a&gt;, and some additional code. Here, I&amp;rsquo;ll go into detail on what I did and how it&amp;rsquo;s working so far. I learned some really neat org-mode features I wasn&amp;rsquo;t aware of; this has been a fun journey!&lt;/p&gt;</description>
    </item>
    <item>
      <title>Positioning Multiple Monitors From the Command Line</title>
      <link>https://blog.fixermark.com/posts/2024/positioning-multi-monitors-from-the-command-line/</link>
      <pubDate>Sat, 06 Jul 2024 21:49:12 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2024/positioning-multi-monitors-from-the-command-line/</guid>
      <description>&lt;p&gt;On rare occasions, I end up needing to plug a second monitor into my&#xA;laptop. This is a problem&#xA;&lt;a href=&#34;https://fixermark.blogspot.com/2021/11/setting-up-xmonad-on-lenovo-thinkpad-x1_01256514861.html&#34;&gt;I solved in the past&lt;/a&gt;&#xA;with a GUI, but it turns out there&amp;rsquo;s also a pretty easy-to-use command-line tool for this purpose: &lt;code&gt;xrandr&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;To use, first run it by itself&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;xrandr&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will list your current monitor configuration, which will look something like this:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Screen 0: minimum 320 x 200, current 5569 x 2520, maximum 16384 x 16384&#xA;eDP-1 connected primary 1920x1080+0+1440 (normal left inverted right x axis y axis) 309mm x 174mm&#xA;   2560x1440     60.00 +  60.00&#xA;   1920x1440     60.00&#xA;   1856x1392     60.00&#xA;   1792x1344     60.00&#xA;   2048x1152     60.00&#xA;   1920x1200     60.00&#xA;   1920x1080     60.00*&#xA;   1600x1200     60.00&#xA;. . . etc . . .&#xA;HDMI-1 disconnected (normal left inverted right x axis y axis)&#xA;DP-2 connected 3440x1440+2129+0 (normal left inverted right x axis y axis) 800mm x 335mm&#xA;   3440x1440     59.97*+  29.99&#xA;   2560x1440     59.95&#xA;   2560x1080     60.00    60.00    59.94&#xA;. . . etc . . .&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The starred rows are the configurations currently selected for the monitor.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Better Emacs Recipes With Yasnippet and Org-mode</title>
      <link>https://blog.fixermark.com/posts/2024/better-emacs-recipes-yasnippet-org-mode/</link>
      <pubDate>Thu, 11 Apr 2024 21:14:37 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2024/better-emacs-recipes-yasnippet-org-mode/</guid>
      <description>&lt;p&gt;While I&amp;rsquo;m pretty happy with my &lt;a href=&#34;https://blog.fixermark.com/posts/2024/emacs-recipes-with-yasnippet/&#34;&gt;recipe system&lt;/a&gt;, I recently learned about&#xA;&lt;a href=&#34;https://orgmode.org/worg/org-contrib/babel/&#34;&gt;org-babel&lt;/a&gt;, which is now&#xA;integreated into the core of org-mode. It turns out this does almost exactly&#xA;what I want; it&amp;rsquo;s designed to allow embedding and running code snippets inside&#xA;an org document in multiple languages. With just a few tweaks, I adapted my&#xA;previous approach to use org-babel.&lt;/p&gt;&#xA;&lt;p&gt;The major changes are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Using org-babel source blocks instead of elisp blocks&lt;/li&gt;&#xA;&lt;li&gt;Tweaking &lt;code&gt;recipe-do&lt;/code&gt; to fire the org-babel source blocks&lt;/li&gt;&#xA;&lt;li&gt;Substituting local variables at the end of the org file with named blocks at&#xA;the beginning of the file&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;using-org-babel-source-blocks&#34;&gt;Using org-babel source blocks&lt;/h2&gt;&#xA;&lt;p&gt;Org-babel introduces &amp;ldquo;source blocks,&amp;rdquo; which are blocks of code in various&#xA;languages that can be executed. They emit their results in a variety of ways,&#xA;including to a &amp;ldquo;result block&amp;rdquo; below the source block. This is more convenient&#xA;for tracking the results of running a block.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Emacs Recipes With Yasnippet</title>
      <link>https://blog.fixermark.com/posts/2024/emacs-recipes-with-yasnippet/</link>
      <pubDate>Sat, 16 Mar 2024 10:51:19 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2024/emacs-recipes-with-yasnippet/</guid>
      <description>&lt;p&gt;A common pattern while working on computer projects is running through a&#xA;sequence of &amp;ldquo;semi-automatic&amp;rdquo; operations, where you can&amp;rsquo;t &lt;em&gt;quite&lt;/em&gt; automate all&#xA;the steps fully, but the formula is basically the same every time. I call these&#xA;workflows &amp;ldquo;recipes,&amp;rdquo; and they have these shared properties:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;There&amp;rsquo;s a set of steps that&amp;rsquo;s almost always the same (but not always)&lt;/li&gt;&#xA;&lt;li&gt;Frequently, especially when they&amp;rsquo;re software development, they take hours /&#xA;days, long enough for interruptions to happen in the middle&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I&amp;rsquo;m easily distracted, so it&amp;rsquo;s common for me to lose track of where I am&#xA;following a recipe and burn some time picking myself back up.&lt;/p&gt;</description>
    </item>
    <item>
      <title>I created a simple flash card viewer</title>
      <link>https://blog.fixermark.com/posts/2024/flash-card-viewer/</link>
      <pubDate>Mon, 15 Jan 2024 15:45:43 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2024/flash-card-viewer/</guid>
      <description>&lt;figure&gt;&lt;img src=&#34;https://blog.fixermark.com/posts/2024/flash-card-viewer/viewer.png&#34;&#xA;    alt=&#34;Flash card viewer&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;The flash card viewer&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve created a simple&#xA;&lt;a href=&#34;https://fixermark.com/get-carded/index.html&#34;&gt;flash card viewer&lt;/a&gt; as a study&#xA;aid. It currently defaults to flash cards for the FIRST Robotics Competition&#xA;2024 game manual, but you can load your own into it by clicking the &amp;ldquo;Cards&amp;rdquo; dropdown&#xA;and pasting text like the following into the box:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Card front 1&#xA;&#xA;Card back 1&#xA;-&#xA;Card front 2&#xA;&#xA;Card back 2&#xA;-&#xA;Etc&#xA;&#xA;And so on&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Card state is stashed to local storage, so your edits will be preserved.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Challenges for Mastodon</title>
      <link>https://blog.fixermark.com/posts/2023/challenges-for-mastodon/</link>
      <pubDate>Wed, 25 Oct 2023 21:42:42 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/challenges-for-mastodon/</guid>
      <description>&lt;p&gt;In a &lt;a href=&#34;https://blog.fixermark.com/posts/2023/things-i-like-about-mastodon/&#34;&gt;previous post&lt;/a&gt;, I talked about things I really enjoy about Mastodon. This time around,&#xA;I&amp;rsquo;ll go over some challenges I see for the tool as a platform, product, and&#xA;ecosystem. Before reading too much into these, note that it&amp;rsquo;s possible not all&#xA;of these need to be fixed! Some can be interpreted as an improvement over the&#xA;status quo of Twitter / Reddit / Facebook (especially if you are&#xA;privacy-conscious). But these are things that will feel strange for people who&#xA;are used to those other systems. I&amp;rsquo;ll also try to offer some mitigation&#xA;suggestions, or at least expound on why I don&amp;rsquo;t think they can / should be&#xA;easily mitigated.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Things I Like About Mastodon</title>
      <link>https://blog.fixermark.com/posts/2023/things-i-like-about-mastodon/</link>
      <pubDate>Fri, 20 Oct 2023 19:40:23 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/things-i-like-about-mastodon/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been maintaining &lt;a href=&#34;http://mastodon.fixermark.com&#34;&gt;my own Mastodon node&lt;/a&gt; for&#xA;a few months now, enough to feel pretty moved-in, all things considered. To&#xA;nobody&amp;rsquo;s surprise, I&amp;rsquo;m really enjoying it!&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m going to do a back-to-back pair of posts about the pros and cons I&amp;rsquo;m seeing&#xA;in the ecosystem right now. Leading off with my favorite things. This is the&#xA;stuff that completely makes it worth my time to keep building and maintaining this server.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Debugging 502 errors in Mastodon</title>
      <link>https://blog.fixermark.com/posts/2023/mastodon-debugging-502/</link>
      <pubDate>Sun, 15 Oct 2023 20:25:30 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/mastodon-debugging-502/</guid>
      <description>&lt;p&gt;Recently after making some changes to my Mastodon server, I began suffering a&#xA;host of 502 and 500 errors. The root cause turned out to be something&#xA;unexpected, so I thought I&amp;rsquo;d document my debugging process to explain how I&#xA;tracked it down. This post will also serve as, I hope, an answer to someone&#xA;wrestling with their own server if they have the same problem.&lt;/p&gt;&#xA;&lt;p&gt;Spoiler: if you get a lot of &lt;code&gt;IPAddr::InvalidAddressError&lt;/code&gt; in your service logs,&#xA;make sure you haven&amp;rsquo;t set the &lt;code&gt;ALLOW_PRIVATE_ADDRESSES&lt;/code&gt; environment variable to&#xA;something invalid like &lt;code&gt;localhost&lt;/code&gt;. That&amp;rsquo;s a comma-separated list of &lt;em&gt;IP&lt;/em&gt;&#xA;addresses; it should be &lt;code&gt;127.0.0.1&lt;/code&gt; if it&amp;rsquo;s anything.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Cycling X-Clacks-Overhead output in Mastodon</title>
      <link>https://blog.fixermark.com/posts/2023/mastodon-x-clacks-overhead-cycler/</link>
      <pubDate>Sat, 14 Oct 2023 15:32:18 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/mastodon-x-clacks-overhead-cycler/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;“We keep that name moving in the Overhead,” he said, and it seemed to Princess that the wind in the shutter arrays above her blew more forlornly, and the everlasting clicking of the shutters grew more urgent. “He’d never have wanted to go home. He was a real linesman. His name is in the code, in the wind, in the rigging, and the shutters. Haven’t you ever heard the saying ‘Man’s not dead while his name is still spoken’?”&lt;/p&gt;</description>
    </item>
    <item>
      <title>Enabling Translations in your Mastodon Node with LibreTranslate</title>
      <link>https://blog.fixermark.com/posts/2023/mastodon-enable-translations/</link>
      <pubDate>Thu, 12 Oct 2023 20:00:49 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/mastodon-enable-translations/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;before.png&#34; alt=&#34;The translate button showing up in the Mastodon UI&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Out-of-the-box, Mastodon supports post translation using an external service. But to take advantage of&#xA;it, you have to set up the services and bind your Mastodon instance to them.&lt;/p&gt;&#xA;&lt;p&gt;It turns out this is a relatively simple process with only a few sharp edges. I&amp;rsquo;ve documented my&#xA;walk to a working configuration here. This process was supported by the Mastodon documentation and&#xA;&lt;a href=&#34;https://blog.gcn.sh/howtos/installing-libretranslate-using-docker-and-ubuntu&#34;&gt;this delightful tutorial for setting up LibreTranslate in Docker&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Showing Note as Suffix on Username</title>
      <link>https://blog.fixermark.com/posts/2023/showing-note-as-suffix-on-username/</link>
      <pubDate>Sat, 07 Oct 2023 11:00:00 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/showing-note-as-suffix-on-username/</guid>
      <description>&lt;p&gt;Having put all the pieces in place, we&amp;rsquo;re now ready to modify the UI to display&#xA;the attached note next to the user&amp;rsquo;s name. We&amp;rsquo;ll have to do a bit of plumbing to&#xA;account for our own sins (denormalizing the field into the post means we&amp;rsquo;ll need to&#xA;re-normalize it into accounts on the client-side). But then it&amp;rsquo;s just a few short&#xA;tweaks to the React components to display it.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Setting Up a Dev Environment for Mastodon</title>
      <link>https://blog.fixermark.com/posts/2023/setting-up-a-dev-environment/</link>
      <pubDate>Wed, 04 Oct 2023 23:00:00 +0000</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/setting-up-a-dev-environment/</guid>
      <description>&lt;p&gt;This post is part 2 of a 3-part series on adding the ability to show notes about&#xA;users on Mastodon next to their display names. Here, I talk a bit about setting&#xA;up a dev environment to make changes to the Mastodon UI.&lt;/p&gt;&#xA;&lt;p&gt;Parts of this series:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;../adding-a-field-to-the-mastodon-api&#34;&gt;Part 1: Adding a field to the Mastodon API&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;.&#34;&gt;Part 2: Setting up the UI dev environment&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;../showing-note-as-suffix-on-username&#34;&gt;Part 3: Surfacing a new field in the Mastodon UI&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;When you modify the Ruby files making up the Mastodon server, those changes&#xA;immediately impact the running server and no further manual intervention is&#xA;needed for testing. To complete Part 1, I actually changed and tested on my&#xA;production server; not best practice, but it worked.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Adding a field to the Mastodon API</title>
      <link>https://blog.fixermark.com/posts/2023/adding-a-field-to-the-mastodon-api/</link>
      <pubDate>Wed, 04 Oct 2023 01:30:00 +0000</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/adding-a-field-to-the-mastodon-api/</guid>
      <description>&lt;p&gt;When I was younger, I expected everyone in the future would have computer&#xA;handles we&amp;rsquo;d mostly go by, and names would be secondary. I gleefully memorized&#xA;hundreds of online handles for all the folks I knew in school and online.&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;https://blog.fixermark.com/posts/2023/adding-a-field-to-the-mastodon-api/hackers1.jpg&#34;&#xA;    alt=&#34;The character &amp;#39;Cereal Killer&amp;#39; from the movie &amp;#39;Hackers&amp;#39;&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Also, we&amp;rsquo;d all dress like this.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;It turned out, that didn&amp;rsquo;t exactly happen. People still keep their (usually)&#xA;parent-assigned names and use them often.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Backing Up Daily, Weekly, and Monthly with Cron</title>
      <link>https://blog.fixermark.com/posts/2023/cron-daily-weekly-monthly/</link>
      <pubDate>Fri, 25 Aug 2023 23:32:37 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/cron-daily-weekly-monthly/</guid>
      <description>&lt;p&gt;Now that my Mastodon server is&#xA;&lt;a href=&#34;https://blog.fixermark.com/posts/2023/backing-up-mastodon/#creating-backups&#34;&gt;making regular backups&lt;/a&gt;, I&#xA;want to preserve some of the backups on the off chance something goes&#xA;desparately wrong with my configuration and I have to do a very large rollback.&lt;/p&gt;&#xA;&lt;p&gt;It turns out, while &lt;code&gt;cron&lt;/code&gt; is maybe not the friendliest tool around, it makes&#xA;this task very easy. What I want to do is a three-tier backup: daily, weekly,&#xA;monthly. I only plan to keep one instance of each.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Backing Up Mastodon and expanding its storage</title>
      <link>https://blog.fixermark.com/posts/2023/backing-up-mastodon/</link>
      <pubDate>Tue, 08 Aug 2023 21:47:50 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/backing-up-mastodon/</guid>
      <description>&lt;p&gt;My Mastodon server has reached the point where it&amp;rsquo;s complex enough that backing&#xA;up would be prudent. I was a litle surprised to discover that a script to do&#xA;this for me is not provided in the default project. The project does have&#xA;&lt;a href=&#34;https://docs.joinmastodon.org/admin/backups/&#34;&gt;a comprehensive overview&lt;/a&gt; of the&#xA;steps to backup, so I set about making my own backup script. In the process, I&#xA;also discovered a need for way more storage, so I&amp;rsquo;ll talk a bit about how I did&#xA;that also.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Setting Up Mastodon on a Raspberry Pi 4</title>
      <link>https://blog.fixermark.com/posts/2023/setting-up-mastodon-raspberry-pi-4/</link>
      <pubDate>Mon, 17 Jul 2023 09:11:54 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/setting-up-mastodon-raspberry-pi-4/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;mastodon-mainpage.png&#34; alt=&#34;The About page of my Mastodon node&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;I recently set up a Mastodon node on a Raspberry Pi 4 in my home. By and large,&#xA;the process went smoothly, but I hit a couple of corner cases I wanted to&#xA;document (both for myself and anyone else following this path in the future).&lt;/p&gt;&#xA;&lt;p&gt;For the most part, I followed the&#xA;&lt;a href=&#34;https://docs.joinmastodon.org/admin/install/&#34;&gt;admin setup guide&lt;/a&gt; provided by the&#xA;Mastodon team. I had to deviate from it in terms of three pieces:&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Art of Computer Programming, I.B.Profin Edition: Chapter 1.1 -  Algorithms</title>
      <link>https://blog.fixermark.com/posts/2023/knuth-1-1/</link>
      <pubDate>Thu, 08 Jun 2023 17:58:26 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/knuth-1-1/</guid>
      <description>&lt;p&gt;About four years and one detour through some self-teaching in control system&#xA;theory later, I have returned to Donald Knuth&amp;rsquo;s famous tome, &lt;em&gt;The Art of Computer&#xA;Programming&lt;/em&gt; (volume 1). My previous attempt to read it was extremely&#xA;discouraging as I stumbled on the first part of the first chapter. Taking a&#xA;second read through, it made sense this time. When I first got stuck, I went&#xA;looking for discussion on the topic online and was unable to find it; I&amp;rsquo;m making&#xA;this post in the hopes that it&amp;rsquo;ll help some other reader in the future succeed&#xA;where I initially failed.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Beating Up React for Fun (and Profit?): Using React to Drive Another Component Tree</title>
      <link>https://blog.fixermark.com/posts/2023/beating-up-react-for-fun/</link>
      <pubDate>Sun, 23 Apr 2023 11:24:18 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/beating-up-react-for-fun/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://react.dev/&#34;&gt;React&lt;/a&gt; is a clever user interface library designed around a&#xA;very functional paradigm, where the input is some state (represented as&#xA;properties) and the output is a tree of renderable user interface components (represented as, usually, something that can be translated to another UI representation, such as an HTML element tree).&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s all well and good, but what if the render tree is already established,&#xA;but you want to use React to drive updates to it?&lt;/p&gt;</description>
    </item>
    <item>
      <title>A Python driver module for Brilliant Labs Monocle</title>
      <link>https://blog.fixermark.com/posts/2023/brilliant-monocle-driver-lib/</link>
      <pubDate>Sat, 01 Apr 2023 16:34:11 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/brilliant-monocle-driver-lib/</guid>
      <description>&lt;p&gt;I bundled up the things I learned about driving a Brilliant Labs Monocle into a&#xA;new &lt;a href=&#34;https://pypi.org/project/brilliant-monocle-driver/&#34;&gt;Python package&lt;/a&gt;. While doing the fine-tuning, I learned a bit more about driving the MicroPython UART interface.&lt;/p&gt;&#xA;&lt;p&gt;Worth noting: I only discovered it after I completed this project, but another&#xA;good example of using Python to drive Monocle actually comes from the&#xA;&lt;a href=&#34;https://github.com/brilliantlabsAR/monocle-micropython/blob/dev-streamlogic/tools/serial_console.py&#34;&gt;Monocle&amp;rsquo;s creators&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h1 id=&#34;fine-tuning-the-connection&#34;&gt;Fine-tuning the connection&lt;/h1&gt;&#xA;&lt;p&gt;The UART service has a maximum size of data it can consume in one &amp;ldquo;chunk;&amp;rdquo;&#xA;overflowing this limit can result in dropping bytes. As of right now, the count&#xA;is 128 bytes (- 3 bytes for overhead). For some reason I haven&amp;rsquo;t sussed out yet,&#xA;the BLE characteristic reports the size is only 20 bytes, so hard-coding it to&#xA;128 sped it up. The Bleak module will do chunking for you if you set the&#xA;mtu_size, but I implemented my own (mostly because I didn&amp;rsquo;t know Bleak would&#xA;handle it for me, but now that it&amp;rsquo;s implemented I like the logging so I&amp;rsquo;m&#xA;keeping it.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Controlling Monocle from a python script</title>
      <link>https://blog.fixermark.com/posts/2023/controlling-monocle-from-python-script/</link>
      <pubDate>Sat, 25 Mar 2023 08:07:50 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/controlling-monocle-from-python-script/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;monocle.jpg&#34; alt=&#34;A monocle on my chair&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;I recently got my hands on a&#xA;&lt;a href=&#34;https://www.brilliantmonocle.com/&#34;&gt;Brilliant Labs Monocle&lt;/a&gt;, which is a nifty&#xA;little tiny-screen device that connects to a host machine via Bluetooth&#xA;Low-Energy protocol and offers a simple API for controlling its content and&#xA;receiving input. The documentation is a little thin-on-the-ground on how to&#xA;interface it to a host, but after a little bit of hacking on it I pieced it&#xA;together.&lt;/p&gt;</description>
    </item>
    <item>
      <title>VSCode: connecting from Linux to Windows</title>
      <link>https://blog.fixermark.com/posts/2023/vscode-linux-to-windows/</link>
      <pubDate>Sun, 19 Feb 2023 08:00:00 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2023/vscode-linux-to-windows/</guid>
      <description>&lt;p&gt;Recently, while working on the&#xA;&lt;a href=&#34;https://github.com/wpilibsuite/allwpilib&#34;&gt;WPILib codebase&lt;/a&gt;, I found that my&#xA;poor Linux laptop was not upgraded enough to do the heavy-lifting, as the&#xA;codebase has pulled in a dependency on GLIBC 2.32 and I&amp;rsquo;m unwilling to risk my&#xA;laptop upgrading from Ubuntu 20 to 22. Rather than give up, I shifted my&#xA;development work to a Windows PC that I drive from my laptop.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve used the SSH plugin for VSCode in the past and it&amp;rsquo;s a solution I&amp;rsquo;m fond&#xA;of. Setting it up took just a few steps on the host machine and the client&#xA;machine.&lt;/p&gt;</description>
    </item>
    <item>
      <title>On AI Art</title>
      <link>https://blog.fixermark.com/posts/2022/on-ai-art/</link>
      <pubDate>Wed, 28 Dec 2022 11:52:46 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/on-ai-art/</guid>
      <description>&lt;p&gt;So I&amp;rsquo;m in Blender and I&amp;rsquo;m generating asteroids using the &lt;code&gt;Add Mesh -&amp;gt; Rock Generator&lt;/code&gt; tool (part of the &amp;ldquo;Add Mesh: Extra Objects&amp;rdquo; add-on) with an Asteroid template.&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;https://blog.fixermark.com/posts/2022/on-ai-art/asteroid1.png&#34;&#xA;    alt=&#34;A lumpy grey rock&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;&lt;em&gt;click&lt;/em&gt;&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;Each of these rocks is created using a few overlapped mathematical algorithms. The math is pure math, procedurally understood, with no hidden-node neural network in play.&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;https://blog.fixermark.com/posts/2022/on-ai-art/asteroid2.png&#34;&#xA;    alt=&#34;A lumpy grey rock&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;&lt;em&gt;click&lt;/em&gt;&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;The results are sufficient to serve the purpose of putting a rock in a game or image with maybe a little polish. The whole script is &lt;a href=&#34;https://svn.blender.org/svnroot/bf-extensions/contrib/py/scripts/addons/add_mesh_rocks/rockgen.py&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>LaTeX Content From Command Line</title>
      <link>https://blog.fixermark.com/posts/2022/latex-content-from-command-line/</link>
      <pubDate>Mon, 31 Oct 2022 13:11:50 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/latex-content-from-command-line/</guid>
      <description>&lt;p&gt;So I have found myself in the market for a new job recently. This isn&amp;rsquo;t the best&#xA;feeling in the world, but I&amp;rsquo;m not letting an opportunity go to waste. Today,&#xA;let&amp;rsquo;s talk about how to create a simple script that injects some content into a&#xA;LaTex document, in the context of creating a script that emits different&#xA;résumés with command-line-specified objectives.&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;https://blog.fixermark.com/posts/2022/latex-content-from-command-line/objective.png&#34;&#xA;    alt=&#34;An example of an objective in a résumé&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Let&amp;rsquo;s stop retyping this&lt;/p&gt;</description>
    </item>
    <item>
      <title>Playing with AprilTags: Python Recognizer</title>
      <link>https://blog.fixermark.com/posts/2022/april-tags-python-recognizer/</link>
      <pubDate>Mon, 19 Sep 2022 08:00:00 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/april-tags-python-recognizer/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;apriltag.png&#34; alt=&#34;An example AprilTag&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;An &lt;a href=&#34;https://www.firstinspires.org/robotics/frc/blog/2022-control-system-reporting-2023-updates-and-beta-testing&#34;&gt;announcement by FIRST Robotics&lt;/a&gt; earlier this year revealed an interesting bit of news: next year&amp;rsquo;s kit would include &lt;a href=&#34;https://april.eecs.umich.edu/software/apriltag&#34;&gt;AprilTags&lt;/a&gt; as vision targets. I&amp;rsquo;m completely unfamiliar with these, so I figured it&amp;rsquo;d be fun to dive in and see what they&amp;rsquo;re all about.&lt;/p&gt;&#xA;&lt;h1 id=&#34;generating-some-tags&#34;&gt;Generating some tags&lt;/h1&gt;&#xA;&lt;p&gt;AprilTags are a so-called &amp;ldquo;fiducial&amp;rdquo; system that identifies not only a position and orientation, but an identifier code as well via a block encoding scheme, conceptually similar to a barcode but with some design features useful to making them easy to comprehend from multiple angles. FRC is planning to use the &lt;a href=&#34;https://github.com/AprilRobotics/apriltag-imgs/tree/master/tag36h11&#34;&gt;36h11&lt;/a&gt;, so I grabbed a few samples from the repository. They&amp;rsquo;re stored in minimized &amp;ldquo;one pixel per block&amp;rdquo; format, so to make them tractable I blew them up and bordered them with ImageMagick (&lt;code&gt;convert tag36_11_00001.png -scale 10000% -bordercolor white -border 200 tag36_11_00001-large.png&lt;/code&gt;) and ran them out on the printer. I grabbed a few reference numbers to play with: 1, 42, and &lt;a href=&#34;https://www.facebook.com/frc422/&#34;&gt;422&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Create Custom Shuffleboard Plugin: Make It Play Sounds</title>
      <link>https://blog.fixermark.com/posts/2022/create-custom-shuffleboard-plugin-2/</link>
      <pubDate>Mon, 12 Sep 2022 08:00:00 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/create-custom-shuffleboard-plugin-2/</guid>
      <description>&lt;p&gt;Having created a new empty custom plugin in the&#xA;&lt;a href=&#34;https://blog.fixermark.com/posts/2022/create-custom-shuffleboard-plugin&#34;&gt;previous post&lt;/a&gt;, we are now ready&#xA;to change it to make it play sounds when the boolean value it monitors goes from&#xA;false to true. The plugin is available in &lt;a href=&#34;https://github.com/fixermark/shuffleboard/tree/sound-widget/example-plugins/sound-widget&#34;&gt;this GitHub repo&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h1 id=&#34;adding-some-visual-feedback&#34;&gt;Adding some visual feedback&lt;/h1&gt;&#xA;&lt;p&gt;Before we add the sound support, we&amp;rsquo;re going to add some visual feedback so we&#xA;can test the widget and assure it&amp;rsquo;s working. We&amp;rsquo;ll crib from the Boolean Box&#xA;built-in widget to display grey squares (but since the main goal is&#xA;sound, not visual, we won&amp;rsquo;t add the color customization options). Once that&amp;rsquo;s&#xA;in, we&amp;rsquo;ll make the changes we need to wire up sound.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Creating a custom Shuffleboard plugin</title>
      <link>https://blog.fixermark.com/posts/2022/create-custom-shuffleboard-plugin/</link>
      <pubDate>Mon, 05 Sep 2022 08:00:00 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/create-custom-shuffleboard-plugin/</guid>
      <description>&lt;p&gt;Well, it&amp;rsquo;s off-season for the FIRST Robotics competition, which is always a good time to try new things. This year, I became more interested in &lt;a href=&#34;https://docs.wpilib.org/en/stable/docs/software/dashboards/shuffleboard/getting-started/shuffleboard-tour.html&#34;&gt;Shuffleboard&lt;/a&gt;, which is one of the dashboard programs you can use to visualize telemetry from the robot on an attached laptop. Shuffleboard works by inspeting the shared &lt;a href=&#34;https://docs.wpilib.org/en/stable/docs/software/networktables/networktables-intro.html&#34;&gt;Network tables&lt;/a&gt; that the robot and its control computer keep updated and drawing various user-defined widgets based on the values in the table.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Simulating a flywheel part 2: friction and time-step updates</title>
      <link>https://blog.fixermark.com/posts/2022/simulating-a-flywheel-friction/</link>
      <pubDate>Sat, 23 Apr 2022 00:11:25 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/simulating-a-flywheel-friction/</guid>
      <description>&lt;p&gt;On a previous post, I discussed creating a simulator for a simple flywheel in&#xA;the FIRST Robotics WPILib framework in Java. We last discussed the high-level&#xA;framework and simulating a motor; here, we&amp;rsquo;ll go into simulating friction and&#xA;how we put it all together.&lt;/p&gt;&#xA;&lt;h1 id=&#34;friction-is-deceptively-complicated&#34;&gt;Friction is deceptively complicated&lt;/h1&gt;&#xA;&lt;p&gt;On the surface, friction is extremely simple. As is taught in high school&#xA;physics, it&amp;rsquo;s the force that resists motion proportional to the normal force of&#xA;the surface pushing against gravity. Which is to say, it&amp;rsquo;s just&#xA;&lt;code&gt;-K&amp;lt;sub&amp;gt;d&amp;lt;/sub&amp;gt; * m * g&lt;/code&gt;, for &lt;code&gt;g&lt;/code&gt; the gravitational constant (acceleration) and&#xA;&lt;code&gt;m&lt;/code&gt; the mass of the object, and &lt;code&gt;K&amp;lt;sub&amp;gt;d&amp;lt;/sub&amp;gt;&lt;/code&gt; the dynamic friction&#xA;coefficient.  Since the flywheel&amp;rsquo;s axle is pushed down by gravity on its socket,&#xA;the friction force becomes a counter-torque opposing spin.  So, no problem. We&#xA;calculate the counter-torque, subtract it from the motor&amp;rsquo;s forward torque, and&#xA;update every step. Punch that in and&amp;hellip; Oh dear.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Simulating a Flywheel part 1: overview and simulating a motor</title>
      <link>https://blog.fixermark.com/posts/2022/simulating-a-flywheel/</link>
      <pubDate>Mon, 18 Apr 2022 09:00:00 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/simulating-a-flywheel/</guid>
      <description>&lt;p&gt;Well, the off-season of FIRST Robotics is upon us. A time when young people&amp;rsquo;s&#xA;minds turn away from robots and towards other things. Like simulating robots!&lt;/p&gt;&#xA;&lt;p&gt;To give the team something to play with on the software side, I&amp;rsquo;m putting&#xA;together a couple of simulators of robot subsystems to experiment with. The&#xA;first one is a simple flywheel connected to one motor and encoder.&lt;/p&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;https://blog.fixermark.com/posts/2022/simulating-a-flywheel/interface.png&#34;&#xA;    alt=&#34;The interface for the simulator in Shuffleboard&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Interface for the simulator, showing the graph of flywheel RPM over time&lt;/p&gt;</description>
    </item>
    <item>
      <title>Piping Linux Audio to a file</title>
      <link>https://blog.fixermark.com/posts/2022/linux-pipe-audio-browser-file/</link>
      <pubDate>Mon, 14 Mar 2022 00:12:26 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/linux-pipe-audio-browser-file/</guid>
      <description>&lt;p&gt;I recently had to pipe some audio from my browser to a file. This may not be the most elegant way, but I found it works.&lt;/p&gt;&#xA;&lt;h1 id=&#34;using-simplescreenrecorder&#34;&gt;Using SimpleScreenRecorder&lt;/h1&gt;&#xA;&lt;p&gt;For capturing audio and video, I use &lt;a href=&#34;https://www.maartenbaert.be/simplescreenrecorder/&#34;&gt;SimpleScreenRecoder&lt;/a&gt;. It&amp;rsquo;s a pretty no-frills recording program that is intended for (among other things) streaming content from a machine. While it supports both audio and video, I only care about the audio portion for this project.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Resetting my monitor in Linux</title>
      <link>https://blog.fixermark.com/posts/2022/linux-reset-monitor/</link>
      <pubDate>Mon, 14 Mar 2022 00:01:48 -0400</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/linux-reset-monitor/</guid>
      <description>&lt;p&gt;Recently, I had an Ubuntu laptop I use regularly develop a weird quirk: sometimes when I plugged it into USB-C, neither the monitor nor power would connect. I discovered I could fix this by simply running &lt;code&gt;lspci&lt;/code&gt; on the laptop, which somehow forced both to come back.&lt;/p&gt;&#xA;&lt;p&gt;As this made no sense, I dug down a bit more. I can&amp;rsquo;t say I found an answer, but I did find some more things worth questioning.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Logs From The Server</title>
      <link>https://blog.fixermark.com/posts/2022/logs-from-hugo/</link>
      <pubDate>Sat, 26 Feb 2022 10:11:38 -0500</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/logs-from-hugo/</guid>
      <description>&lt;p&gt;One of the things I&amp;rsquo;ve missed, having moved my blog off of Blogger, is the metrics. I don&amp;rsquo;t use the metrics for much, but there&amp;rsquo;s a nonzero serotonin hit to knowing that my content is read by someone. It&amp;rsquo;d be nice to be able to restore at least that piece of the Blogger feature-set.&lt;/p&gt;&#xA;&lt;p&gt;Fortunately, I have access logs and a log analyzer.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve settled on &lt;a href=&#34;https://goaccess.io/&#34;&gt;goaccess&lt;/a&gt; for my log analysis; it&amp;rsquo;s pretty straightforward, takes HTTP access logs as input, and presents the data visually (including on the command line). It&amp;rsquo;s installable on my local machine via the package manager (&lt;code&gt;sudo apt-get install goaccess&lt;/code&gt;), so no problems there.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Self Hosted Hugo Comments: data rendered with partials</title>
      <link>https://blog.fixermark.com/posts/2022/self-hosted-hugo-comments-2/</link>
      <pubDate>Wed, 16 Feb 2022 10:05:27 +0100</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/self-hosted-hugo-comments-2/</guid>
      <description>&lt;p&gt;In an earlier post, I added self-hosted static comments via shortcodes in Hugo. This approach had some benefits, but I didn&amp;rsquo;t like how it required modifying every blog page to support comments, even if no comments were present.&lt;/p&gt;&#xA;&lt;p&gt;Hugo has a system of &lt;a href=&#34;https://gohugo.io/templates/partials/&#34;&gt;partials&lt;/a&gt; and &lt;a href=&#34;https://gohugo.io/templates/&#34;&gt;templates&lt;/a&gt; to allow for similar pages to have the same layout. We can take advantage of these to handle comments on every blog page. This will pull the comments out of the main flow of the blog posts; we could move them into the &lt;a href=&#34;https://gohugo.io/content-management/front-matter/&#34;&gt;front matter&lt;/a&gt; of the pages, but insted I&amp;rsquo;m going to knock out another con of the previous approach and consolidate all comments into one data file.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Self Hosted Hugo Comments: embedded in page</title>
      <link>https://blog.fixermark.com/posts/2022/self-hosted-hugo-comments-1/</link>
      <pubDate>Tue, 15 Feb 2022 11:39:35 +0100</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/self-hosted-hugo-comments-1/</guid>
      <description>&lt;p&gt;Having chosen to self-host my Hugo comments as part of the static page content, there are a couple of ways to do it. In this article, I explore embedding them in the page using shortcodes.&lt;/p&gt;&#xA;&lt;h1 id=&#34;the-method&#34;&gt;The method&lt;/h1&gt;&#xA;&lt;p&gt;Comments in my blog are represented by two shortcodes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;commenthtml&#34;&gt;comment.html&lt;/h2&gt;&#xA;&lt;p&gt;The first shortcode collects comment data in a semi-structured way and emits it as HTML. Here&amp;rsquo;s the whole thing.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/layouts/shortcodes/comment.html&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-hugo&#34; data-lang=&#34;hugo&#34;&gt;{{- $postid := default (.Get 0) (.Get &amp;#34;id&amp;#34;) -}}&#xA;{{- $username := default (.Get 1) (.Get &amp;#34;username&amp;#34;) -}}&#xA;{{- $usericon := default (.Get 2) (.Get &amp;#34;usericon&amp;#34;) -}}&#xA;{{- $postdate := default (.Get 3) (.Get &amp;#34;date&amp;#34;) -}}&#xA;&#xA;&amp;lt;div class=&amp;#34;comment&amp;#34;&amp;gt;&#xA;  &amp;lt;div class=&amp;#34;user-info&amp;#34;&amp;gt;&#xA;    {{ if $usericon }}&#xA;      &amp;lt;img src=&amp;#34;{{$usericon}}&amp;#34;&amp;gt;&#xA;    {{ end }}&#xA;    {{ $username }} {{ $postdate }}&#xA;  &amp;lt;/div&amp;gt;&#xA;  &amp;lt;div class=&amp;#34;comments-menu&amp;#34;&amp;gt;&amp;lt;a href=&amp;#34;mailto:blog+personal-comment@fixermark.com?body=Your Name:%0d%0aIcon:%0d%0aComment:&amp;amp;subject=Comment on {{ $.Page.Permalink }}?comment-id={{ $postid }}&amp;#34;&amp;gt;Reply&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;&#xA;  &amp;lt;div class=&amp;#34;comment-body&amp;#34;&amp;gt;&#xA;    {{ .Inner }}&#xA;  &amp;lt;/div&amp;gt;&#xA;&amp;lt;/div&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This code is triggered as, for example,&lt;/p&gt;</description>
    </item>
    <item>
      <title>I&#39;m switching my personal blog to Hugo</title>
      <link>https://blog.fixermark.com/posts/2022/switching-to-hugo/</link>
      <pubDate>Tue, 15 Feb 2022 10:57:53 +0100</pubDate>
      <guid>https://blog.fixermark.com/posts/2022/switching-to-hugo/</guid>
      <description>&lt;p&gt;After putting a bit of thought into it, I&amp;rsquo;ve decided to start the process of switching my &lt;a href=&#34;http://alsofixermark.blogspot.com&#34;&gt;personal blog&lt;/a&gt; to self-hosting on &lt;a href=&#34;http://gohugo.io&#34;&gt;Hugo&lt;/a&gt; instead of hosting through Blogger. This blog is staying where it is, but I&amp;rsquo;ve been playing with the Hugo framework for awhile and am finding I really enjoy it. Expect to see some posts about my experiences with it in here from time-to-time.&lt;/p&gt;&#xA;&lt;h1 id=&#34;why-switch&#34;&gt;Why switch?&lt;/h1&gt;&#xA;&lt;p&gt;Even with the benefit of &lt;a href=&#34;http://takeout.google.com&#34;&gt;Google Takeout&lt;/a&gt;, moving blog infrastructure is time-consuming. So why have I bothered? A few reasons, in no particular order:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Privacy Policy</title>
      <link>https://blog.fixermark.com/privacy-policy/</link>
      <pubDate>Sat, 12 Feb 2022 09:06:28 +0100</pubDate>
      <guid>https://blog.fixermark.com/privacy-policy/</guid>
      <description>&lt;h1 id=&#34;privacy-policy&#34;&gt;Privacy Policy&lt;/h1&gt;&#xA;&lt;p&gt;&lt;em&gt;last updated: 2025-08-02&lt;/em&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;change-history&#34;&gt;Change history&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;2025-08-02: Updated Comments policy to reflect new comment engine&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#general-principles&#34;&gt;General Principles&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#site-access&#34;&gt;Site Access&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#comments&#34;&gt;Comments&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#additional-concerns&#34;&gt;Additional Concerns&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;general-principles&#34;&gt;General Principles&lt;/h2&gt;&#xA;&lt;h3 id=&#34;balancing-personal-privacy-with-operational-needs&#34;&gt;Balancing personal privacy with operational needs&lt;/h3&gt;&#xA;&lt;p&gt;This policy attempts to find middle ground between the needs of the site owner and your needs as a user. &lt;strong&gt;I also attempt to adhere to the spirit of the GDPR, but it is a best-effort attempt.&lt;/strong&gt; In particular, &lt;strong&gt;this site will not ask you if you consent to cookies because it does not use cookies.&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title></title>
      <link>https://blog.fixermark.com/how-to-comment/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://blog.fixermark.com/how-to-comment/</guid>
      <description>&lt;h1 id=&#34;how-to-comment&#34;&gt;How to comment&lt;/h1&gt;&#xA;&lt;p&gt;To comment on this blog, send an email to &lt;a href=&#34;mailto:blog+comment@fixermark.com&#34;&gt;blog+comment@fixermark.com&lt;/a&gt; in the following format:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Subject: &amp;ldquo;Comment on &lt;code&gt;URL of page or ID of comment to reply to&lt;/code&gt;&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;Body:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The name by which you&amp;rsquo;d like to be known&lt;/li&gt;&#xA;&lt;li&gt;An icon (image or Gravatar icon URL); 128x128 pixels&lt;/li&gt;&#xA;&lt;li&gt;The text of the comment. Markdown formatting will be copied verbatim (unless it interferes with site behavior). Other formats will be matched best-effort.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Comments are updated by hand periodically. To remove a comment, see &lt;a href=&#34;https://blog.fixermark.com/privacy-policy&#34;&gt;the privacy policy&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
