Luminescent Dreams

Weekly Ramblings for June 9th, 2022

Geese!, 2018-11

Been a while, y’all! No sooner did I make my website multilingual than I ran out of any energy to actually do any writing. Nevertheless, I am back and it’s time to ramble a bit.


Over the course of the last year and a few months, I’ve gotten vaguely on the Zettlekasten (or Second Brain) bandwagon. I’ve actually been sticking to it, though I’m pretty terrible at actually processing my backlog of information. Yet even with my backlog continuing to pile up, I’m finding it an invaluable tool for organizing information and making sure that I can actually find things afterwards.

Obsidian is my tool of choice, though for the most part I’m keeping it vanilla. I like the ease of flipping between raw Markdown mode and nicely rendered mode. Since I can trivially link a new file and trivially follow those links, I have become much more inclined to break my notes apart into smaller bits.

Over the next few months, I intend to draw the veil back with real information. Most of the videos and explanations that I find on the internet are pretty generalized and rarely ever talk about anything other than the philosophy of the Zettlekasten. So, I should actually reveal some concrete work.


I have a huge number of interests and gather new ones on a regular basis. I finally grabbed hold of the BlueR library for Rust and started trying to probe the knock-off fitness tracking watch that I bought a few years ago. In so doing, I also had to start learning about Bluetooth itself.

The core Bluetooth spec is over 3000 pages long. I find this mind-boggling. Actually, it seems vastly excessive to me. There is no way for any person, or even small group of people, to actually understand the whole document. And perhaps that is okay, since some hundreds of those pages specify the physical link layers, but damn. Basically, I haven’t figured out some of the basic concepts because this is a huge document for me to dig through.

But here are the basic components that I can see:

  • Device
  • Profile
  • Service
  • Service Class
  • Characteristic
  • Property
  • GATT

Then there are a lot of defined services which follow a set of standards. For instance, I grabbed the Battery Service document and read a bit of it. Just enough to be able to connect to my headset and read the battery level from it.

In any case, here’s the descriptor I can read from my fitness tracker watch:

device: Device { adapter_name: hci0, address: E3:09:3A:69:A9:9E }
    address_type:         LeRandom
    name:                 Some("ID115Pro")
    uuids:                Some({00001800-0000-1000-8000-00805f9b34fb, 00000af0-0000-1000-8000-00805f9b34fb, 00001801-0000-1000-8000-00805f9b34fb})
    paired:               false
    connected:            true
    trusted:              false
UUID processing
    Ok(GenericAttribute)    Ok(GenericAttrib)
    Err(00000af0-0000-1000-8000-00805f9b34fb)    Err(00000af0-0000-1000-8000-00805f9b34fb)
    Ok(GenericAccess)    Ok(GenericAccess)

It’s not entirely clear to me what all of this means. To some degree, I believe that the uuids on the device are supposed to indicate service UUIDs. It appears that some of the UUIDs aren’t registered and so aren’t known to anything else.

Long story short, I was unable to find anything comprehensible on the watch. I believe that all of the useful information I would want on the watch is actually stored in the GenericAccess attributes.

I’ve largely hit a roadblock here, but I have also found a Bluetooth sniffer application for Android, and so I may just install that and see if I can use it to record a transaction in progress when the knock-off software that can communicate with the watch actually pulls data from it. However, that is research for another time.

However, here is a similar output for my headset, which is itself a bit more interesting since I was able to grab the battery level from it:

device: Device { adapter_name: hci0, address: 00:1B:66:CD:B0:82 }
    address_type:         LePublic
    name:                 Some("LE-MOMENTUM 3")
    icon:                 Some("audio-headset")
    class:                Some(2360324)
    uuids:                Some({0000feed-0000-1000-8000-00805f9b34fb, 00001108-0000-1000-8000-00805f9b34fb, 00001200-0000-1000-8000-00805f9b34fb, 0000111e-0000-1000-8000-00805f9b34fb, 0000180a-0000-1000-8000-00805f9b34fb, 0000fdce-0000-1000-8000-00805f9b34fb, 0000110d-0000-1000-8000-00805f9b34fb, 931c7e8a-540f-4686-b798-e8df0a2ad9f7, 0000180f-0000-1000-8000-00805f9b34fb, 00001801-0000-1000-8000-00805f9b34fb, 0000110e-0000-1000-8000-00805f9b34fb, 00000000-deca-fade-deca-deafdecacaff, 0000110c-0000-1000-8000-00805f9b34fb, 1ddce62a-ecb1-4455-8153-0743c87aec9f, 0000110b-0000-1000-8000-00805f9b34fb, 0000fe03-0000-1000-8000-00805f9b34fb, 00001800-0000-1000-8000-00805f9b34fb})
    paired:               true
    connected:            true
    trusted:              true
UUID processing
    Ok(GenericAttribute)    Ok(GenericAttrib)
    Err(0000110c-0000-1000-8000-00805f9b34fb)    Ok(AvRemoteTarget)
    Err(0000110b-0000-1000-8000-00805f9b34fb)    Ok(AudioSink)
    Err(0000111e-0000-1000-8000-00805f9b34fb)    Ok(Handsfree)
    Err(00001200-0000-1000-8000-00805f9b34fb)    Ok(PnpInfo)
    Ok(DeviceInformation)    Err(0000180a-0000-1000-8000-00805f9b34fb)
    Ok(BatteryService)    Err(0000180f-0000-1000-8000-00805f9b34fb)
    Ok(GenericAccess)    Ok(GenericAccess)
    Err(0000110e-0000-1000-8000-00805f9b34fb)    Ok(AvRemote)
    Err(00001108-0000-1000-8000-00805f9b34fb)    Ok(Headset)
    Err(0000110d-0000-1000-8000-00805f9b34fb)    Ok(AdvancedAudio)

battery service detected: Service { adapter_name: hci0, device_address: 00:1B:66:CD:B0:82, id: 35 }
characteristic: Characteristic { adapter_name: hci0, device_address: 00:1B:66:CD:B0:82, service_id: 35, id: 36 }

Some are services, others are service classes. There are additional ones that I’ve deleted that don’t correspond to anything.

What I can do with this I don’t know. One thing interesting that it shows, though, is that an audio headset, which does not require any special software, implements a lot of standard services that get involved with hooking the headset into the Linux device drivers.

I purposely set myself a time limit on this post so that I could be sure to actually get it written, and I have run out of time. I have so much additional research to do and so much more to learn. I’ll be sure to share it as I learn to make sense of things.

Multilingual, Finally

Yesterday, I finally published a multilingual version of my website!

I have translated multiple articles, but my last program did not understand that multiple articles can be the same article but in different languages. The new program understands that, so I can easily create an article in multiple languages and the program will link them together.

My challenge: write a new article in Esperanto, and translate it to English!

I will post it Saturday!

(actually, I did that with this article, too!)

Weekly Ramblings for June 22nd, 2020

Hello, everyone, and welcome back after a long, unexpected hiatus!

COVID-19 has really done a number on my mental health and my activities, but I have managed to continuing to get outside to run, and nobody in my family has gotten sick. We’re continuing to largely self-isolate, with only occasional careful trips to the grocery store.

I have kept myself very busy with a combination of practicing Esperanto, trying to build a clock inside of Minecraft (harder than you might think), and building a real computer on a breadboard using real digital circuits.


This continues to be a multi-year-long project, however over the last few weeks I have participated in the Esperanto Version Fingtam Languages 30 Day Record Yourself Challenge. Turns out that this, more than anything else I have done, has helped me with my ability to speak. While I don’t participate every day, I actually have an active youtube channel. At the same time, many other people are participating in the challenge, and I believe I am starting to make friends.

Now that Evildea is also doing a series of direct method videos, I’m now immersing myself in Esperanto for a non-trivial amount of time every day, and I think that helps, too. I once watched a video talking about how language learning is mostly about input, and my biggest problem with Esperanto was the input side. There is very little media in the language and it is quite hard to find, even on Youtube. This challenge also has likely created many more Youtube streamers, which I feel is likely to be a bit self-perpetuating. I’ve been considering starting streams or videos for months, though at first I thought I would be streaming Slay the Spire or Go. However, I never did either of those and instead got myself into Minecraft.

Digital Logic Inside of Minecraft

In the early days of the pandemic, when I was really having trouble adapting to never being able to see my friends, I got a serious urge for a game that would let me just explore and build with little sense of an end of game or a particular goal. Thus, suddenly, I remembered Minecraft from long ago and decided to get back into the game. After a few weeks of playing alone, I set up a server and invited my friends to join. We had a couple of nights of mayham and fun and built out quite a lot of compound, plus I found out from some of the younger players about some higher-level automation that can be done within the game using basic components.

One of the quirks of the game is that on the first night, as we started putting up signs, I would put up signs in both English and Esperanto. In addition to Minecraft having a complete Esperanto translation, it was just fun to put up warning signs and direction signs in more than one language. And then other players started adding their own translations in French and German.

After they fell away, I moved away from the core base and started trying to decide what to build. At first, I thought a treehouse. Then I decided to revisit a long ago idea I had of building a clock that told world time within the game. Some of my inspiration comes from having read Anathem so many times, and I wanted to build a clock at the center of what could become a small compound. Or a large one. Maybe one day I’ll add a library and maybe even start writing things for books in the library, with maybe a little inspiration from certain activists who created an uncensored library in Minecraft.

But now, a month later, with many days of work into it, I continue to struggle to actually build the core clock circuit. While it’s easy to build a circuit that generates a rising pulse every second, the storage arrays tend to update much too slowly, plus I cannot figure out a design that will give me a reset line. So many things in the game might make the clock lose synchronization that I want a reset line that will force the entire clock to zero at sunrise.

My limiting factors are a combination of the size of basic logic gates (minimum of 12 cubic blocks for an AND gate, with the need to keep at least one clear block above all torches to avoid signal propogation), the propogation distance of a redstone signal (only 16 blocks), and mounting switching time. We only get 20 redstone ticks per second, and it is really surprising how quickly that can run out.

T flip-flops provide much simpler counter logic (requiring only a single AND gate between each bit) over the D flip-flop counter logic, which appears to require both an AND an an XOR gate between logic gates. At this time, I can build about a six-bit binary counter out of T flip-flops. This is enough for sixty seconds, though I still need to work out the logic for reseting these both at sunrise and at the 60-second mark. Plus, I need to send a signal to the next counter array to tell it to update, and it needs to persist until being read, because otherwise there is the chance that the signal will not last long enough to update the minute counter.

This may well be the hardest part of the whole project, even though I still have to figure out how to route the outputs into a binary decoder array, and then route those decoder outputs into a driver for a seven segment display. I know how to build both of these things, but again, signal propogation distance is really getting in the way, and the arrays themselves end up being really huge, and I need four of them for a four digit display.

This is hard enough that I keep considering giving up, especially given the next section…

Breadboard Computer

A long time ago, one of my friends told me about Ben Eater’s breadboard computer project. I pretty quickly watched the entire thing, but a month ago I finally ordered all of the parts necessary to do this project myself. Real world electronics, though they can be rather destroyed by failure to provide resistors in the right place, shorting lines, or applying current to what was supposed to be a ground line, are very small. The ones that we use in computers are impercetably small. The ones that I use in a breadboard computer are finger sized.

At this point, I have built the clock circuit, the two registers, the ALU, and assembled the memory board. So far, I have been able to understand everything, even the analog clock circuit and debouncers. As the project progresses, things are becoming a bit more abstract, where instead of laying out a bunch of 4-bit D-flip-flop chips to make memory cells, we’re actually just using two 64-bit chips that also accept address lines and do internal demuxing. Put together, I get a whole 16 bites of memory… which I will use for both program instructions and storage.

Elsewhere, we’re going to use an EEPROM to drive a trio of seven-segment displays. In one of his videos, Ben actually shows a basic logic gate layout that accomplishes the same thing, and it actually requires something like six breadboads with a lot of chips, so an EEPROM sounds like a pretty magnificent improvement over that. On the other hand, I think maybe I could do the same thing by building a binary decoder array and then feeding that into the ten lines of a matrix ROM.

This is quite fun, and I have yet to destroy anything. I have already done one video about my breadboard computer, but in Esperanto. I’m considering doing similar explanation videos with basic logic gates, and using this as fodder for additional Esperanto media to maybe inspire other people to learn the language as well!

And that is all for now! I’ll try to make these regularly again, targetting a Monday publication. Later!

FitnessTrax 0.1.0

The Streets at Night, 2019-09

Hello, and welcome back!

Today, I get to announce that I have release FitnessTrax 0.1!

FitnessTrax is a health and workout tracking program designed for individual users and following the privacy policy of keeping all of your data on your own computer. Data that lives there cannot be mined and exploited by third party companies that may not really have your privacy in mind.

This is the first version of the application that I feel is suitable for home users. While it is rather ugly, and limited at this time, it is also entirely usable. Over the next few releases, I plan to style the application nicely and to add many other pieces of information to the tracking system.

FitnessTrax is a GTK 3 application. It can currently only be installed from source. A NixOS derivation will be available soon. I am not currently working on installation from Crates.IO, on Ubuntu, or with Flatpack, but all three of these are on my roadmap.


This is the culmination of many years of work and learning.

I first started tracking my weight and my bike rides in 2003. I used nothing more than a couple of plain text files. For a long time, that worked, but graphs were impossible, and it was not possible for me to get a coherent view of any particular day in my history without reading information from many different places.

In 2013, I finally started trying to put all of the information into a single database of sorts. From the beginning, I had no desire to set up a separate database server. Aside from simply being overkill for an app that will only recieve a few writes every day, a separate server increases the effort necessary to install an application, and makes data backups significantly harder.

So, I started with a SQLite database and a Haskell web service. Over the years I migrated from SQLite to building an embedded time series database, then from Haskell to Haskell and Javascript, then to Rust and Javascript, Rust and Typescript, and finally to a Rust-only native GTK application.

Over the years I modified, updated, and tweaked the various data models into something that mostly fit the patterns that I could understand. I settled, at long last, on the Record data structure, then defined Weight, Steps, TimeDistance, Duration, and SetRep as records. Further, in my time at Cloud City I learned from several people who are very good at architecting user interfaces, and that has lead to the internal architecture of my application.

It may seem silly that an application that is little more than a glorified spreadsheet could take so long to build. But it should be known that I have developed this application mostly on my own, and have taken many false steps in the process. I have learned a lot, most of which I hope to one day apply to my career. I do not think that I could have ever done any better.

Honoring Amelia, two years later

In Memory of Amelia Perry

Two years ago today, I woke up to the news that my friend, Amelia, was gone.

Amelia was the victim of our country’s transphobia and inadequate response to mental health needs. She ended her life after six months intermittently in hospitals. Since then, I have participated in some of the same hospitalization programs as her. While I have been able to recover, her experiences continue to remind me htat these systems are inadequate, and that transgender inclusion cannot be assumed even in a state whose laws support transgender rights.

My feelings are complicated. I do not feel acute pain any more, but I believe that is because I remember her, and feel a bit of pain, every single day. Every day I think about the things she could be doing, and the things she already did to advance math and science. Things that I am unable to understand because she was beyond brilliant.

So, today, we remember the anniversary of Amelia’s death and we continue to fight for the inclusion and the dignity of transgender people, and destigmatization of mental illness until it is as unremarkable as any other illness.