<link rel="self" type="application/atom+xml" hreflang="" href="gemini://benjaminja.com/tags/projects/feed.xml" />

<link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/tags/projects/" /><id>/</id>

2024-06-09T22:42:13Z

Hugo 0.129.0

<title><![CDATA[Planning Gemini Hosting Service]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2024/06/09-plan-gemini-host/" />

<id>gemini://benjaminja.com/log/2024/06/09-plan-gemini-host/</id>

<updated>2024-06-09T22:42:13Z</updated>

<summary type="gemini"><![CDATA[I have an idea for a project that I’m pretty excited about and I think it could be very helpful to the gemini community. I’ve started building it, but I realized that I should get peoples opinions before I go any further.

]]><![CDATA[I have an idea for a project that I’m pretty excited about and I think it could be very helpful to the gemini community. I’ve started building it, but I realized that I should get peoples opinions before I go any further. I would love to hear from you, whether that be through a post response, or a direct message.

Even though gemini is a very simple protocol and can be created with ease, you still need some technical expertise to set up a server. There are of course groups which allow you to have your own capsule directory such as [gemlog.blue], [bbs.geminispace.org]. [Or you could join a pubnix.]

=> gemlog.blue | bbs.geminispace.org | Or you could join a pubnix.

These are all great alternatives to having your own domain, but I haven’t seen any service that would provide simple hosting for your own domain. My project is to provide gemini hosting without needing to know all the technical things about hosting.

There will be two ways to manage your website. One way will be through the https portal which runs with htmx and fails safely if js is disabled. You will also be able to manage your capsule through gemini/titan.

I really want this to be a robust system, so I am building it in the cloud with AWS. Since AWS doesn’t know what gemini is, I will have to be using one of their EC2 VPS to host the gemini side of things. I’ve thought about going serverless for the web server, but that really does just over complicate everything; especially when I’m trying make a service that is server-side rendered. So instead, everything will live on the EC2 instance.

I’ve done some estimations about how much it will cost me to host this server, and it seems that right now, it will cost about $14/month. I think there are some cost saving measures that can be done to reduce cost of this. I’m using a t4g.nano instance which should cost $3/month. Most of the costs seem to be coming from the VPC at around $10/month with $3 for a public IP and $7 for endpoints to S3, and DynamoDb. There might be ways to reduce the cost of the VPC, but I don’t really know what would be needed to do.

One of the more controversial things that I expect to come from this service is pricing. I don’t want to make a profit on this project, but I also don’t want to be losing money. I feel like I could charge $1/month to host a gemini server for anyone, and scale up the service horizontally to provide lower latencies across countries as more people join. There are a few problems that I immediately see with charging people for hosting.

=> knuckle buster

¹ I’m realizing that this not possible because of how complex regulations are around credit card transactions.

I could also run the service off of donations. I think this would be the preferable option, however it does not scale well. I can’t imagine there would be enough donations to keep everything running when there are a million users (There will never be that many people or I’ll eat my hat).

Maybe there could be a compromise where everyone owes $1/month, but donations get distributed randomly between users Twitch Gift Sub style. Or donations could go directly to specific people. If there are enough donations to cover the costs of the servers, then it would be free for everyone.

I am interested to know how people feel about the idea of this service. Is it something you would want to use if you didn’t already have a place to host your capsule? Are you interested in it enough to transition from your existing service? Does the idea of paying for a gemini capsule sound bad? Do you have a suggestion for how this could be done?

I’ve mostly just put down my thoughts as they’ve come to me. So I hope that my thoughts aren’t too sporadic. I really want gemini to be more accessible to creators and I would like to know what people really want before I go further into the project than I already am.

Mentions

=> Comments on Mastodon

=> 📭 Message me | 📝Or mention this post

]]>

<category term="gemini" label="Gemini" scheme="gemini://benjaminja.com/tags/gemini/" />

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<category term="geminauts" label="Geminauts" scheme="gemini://benjaminja.com/tags/geminauts/" />

<published>2024-06-09T22:42:13Z</published></entry>

<title><![CDATA[Converting from teensy to arduino]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2024/05/21-station_conversion/" />

<id>gemini://benjaminja.com/log/2024/05/21-station_conversion/</id>

<updated>2024-05-21T22:13:26Z</updated>

<summary type="gemini"><![CDATA[For the past few days, I have been converting my weather station firmware to use an Arduino Atmega328P chip instead of a teensy Arm Cortex M7 chip. In my last post, I found that the teensy is significantly overpowered for the job and it could be contributing to why the temperature readings are consistently so high.

]]><![CDATA[For the past few days, I have been converting my weather station firmware to use an Arduino Atmega328P chip instead of a teensy Arm Cortex M7 chip. In my last post, I found that the teensy is significantly overpowered for the job and it could be contributing to why the temperature readings are consistently so high.

I want to discuss the logic that the station does and how it has become difficult to squeeze that same logic into a much smaller device.

On the teensy, the logic was split into a few parts:

  1. Interrupt when the rain sensor senses 0.01in of rain.

  1. Interrupt when the anemometer turns 180º.

  1. Keep a history of past hour of rainfall.

  1. Keep a history of the past 10 minutes of wind data (this includes average and gusts).

  1. Send all the information back to the base station when it needs it.

This is quite a bit of things for the station to do and is definitely way too much for the Arduino to handle. Instead of keeping a history of the data on the station, the base station will do most of the processing. I figured this would be a relatively easy process, but I have forgotten just how under powered the Arduino is.

The Arduino has 32kB of flash and 2kB of ram. 32kB is pretty small, but that isn’t really a big deal. You have to have a really big program to surpass 32kB. I don’t even think the program for the teensy was bigger than 32kB. The real problem is with the ram. 2048 bytes of ram is all you get. That’s including static variables, stack variables, and the heap.

When you compile for the arduino, it gives you a helpful graph saying how much ram and flash your program uses. For flash, it just doesn’t need to get bigger than 32kB. The ram is a different story though. The graph that is provided for ram shows only static variables that are pre-allocated. So if you used 1kB of ram in the graph, then you really only have 1kB of ram for the stack and heap. So you really need to be careful about memory at all times.

This is one of the reasons why I don’t particularly like C++ for embedded since when using classes you sometimes never really know how much memory you might end up using. Though the embedded community has made C++ feel a lot better than I think how modern C++ feels. I can’t wait for embedded Zig to mature, but it is still at the point where only like 5 boards are supported, and even then, only registers are available which make programming a nightmare. (I’ve really only tried to get into embedded Zig once, and probably missed a bunch of things. I would love to be proved wrong about embedded Zig)

With my adaption to Arduino, I have reduced the responsibilities significantly for the station.

  1. Interrupt when the rain sensor senses 0.01in of rain.

  1. Interrupt when the anemometer turns 180º.

  1. Store the number of rain ticks since the last update.

  1. Store the number of wind ticks and wind directions since the last update (up to 1 minute worth)

  1. Send all the information back to the base station when it requests it.

While the Arduino has the same basic responsibilities, it is now performing less calculations and storing less data in ram. The biggest changes are to the wind. Before, the teensy stored 600 floats/uint8 for the wind gust/directions at a rate of 1 sample per second for 10 minutes. That alone is 3000 bytes of data and 1.5 times the total ram capacity of the Arduino. And that is not including wind averages.

I’ve since realized that I could significantly save space by storing only the last minute of data (60 samples) and instead of calculating the speed on the chip, it just counts the number of ticks during the sample. I could store each sample as a uint8, and store the wind direction also as a uint8. This makes the cache only 128 bytes long.

You might be thinking to yourself “Self, how does one get 360º to fit in 255?” I’m glad you asked! My weather vane can only read 8 cardinal directions. “Great, so the direction can fit easily in a byte!” Not exactly, 10 times a second I take a reading from the weather vane. Convert it to x/y components and average it out for the sample. I then use an atan2 LUT to convert the x/y component back into an angle. The LUT is a 21x21 table ranging from [-1.0, 1.0].

=> 🖼 Image of the LUT—Colorized

Because the LUT is built with steps of 0.1, there are 441 possible outputs, but there are only 232 angles that are produced. So instead of outputting the angle I output the value for another LUT which converts from values [0,232) to [-174,180]. This way I can store a more accurate wind direction within a single byte. The base station will have to convert the angle index back into a real angle, but I feel like it is a pretty interesting way to get more detail out of the sensor.

Mentions

=> Comments on Mastodon

=> 📭 Message me | 📝Or mention this post

]]>

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<category term="weather-station" label="Weather-Station" scheme="gemini://benjaminja.com/tags/weather-station/" />

<published>2024-05-21T22:13:26Z</published></entry>

<title><![CDATA[Weatherstation Update]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2024/05/16-weatherstation-update/" />

<id>gemini://benjaminja.com/log/2024/05/16-weatherstation-update/</id>

<updated>2024-05-16T17:55:36Z</updated>

<summary type="gemini"><![CDATA[It has been a little while since I last wrote about my weather station–almost a whole year in fact. I wrote about how I would go about communicating between my raspberry pi and my micro controller.

]]><![CDATA[=> /log/2024/05/16-weatherstation-update/24-03-18_13-30-12_fly_.jpg 🖼 Photo of the weather station

It has been a little while since I last wrote about my weather station–almost a whole year in fact. I wrote about how I would go about communicating between my raspberry pi and my micro controller. I decided I would use CAN bus to do all the communicating. It turns out though that CAN is really difficult and designed to work well when you have multiple devices communicating over the same wire. Think long distance i2c. Since I’m just doing peer to peer, CAN ends up being a bit over complicated for my use case.

Shortly after writing my post, [Fripster] sent me a message saying that I might be better off using RS422. He was definitely right and I switched over to that right away.

=> Fripster

What is RS422

In my project, I’m specifically using differential TTL (transistor-transistor logic) where each UART is split into two twisted wires where one is + and the other is -. At the receiving end, the pair is combined back together into a single signal. These twisted pairs make it so that the signal can go for a significantly longer distance without signal degradation. There has been a ton of work done to figure out how and why it works, but it’s basically just magic to me.

S-Code

RS422 isn’t a protocol on its own. It is closer to a specification on how to physically connect two devices together. I’m not even sure if there is a standardized voltage designated for it, and if there is, I’m definitely not using it.

In order to actually communicate between the two devices, I came up with a binary extension to G-Code I called S-Code (I think it was short for Serial Code). Instead of commanding a CNC machine, I send custom codes to request codes be sent back or to save configurations.

The codes can be either in traditional g-code style, or in my own custom binary format. It supports 8, 16, 32, 64 bit integers, strings, and 32 or 64 bit floats. At the end of every binary code is an 8-bit crc.

You can learn more about it at [github.com/ttocsneb/scode].

=> github.com/ttocsneb/scode

Temperature Problems

I have been able to get the weather station up and running. It collects data, can display current conditions, and most importantly, is usable by non-technical people. Almost everything seems to be working with it. There is just one itsy bitsy problem. The temperature is readings are too high.

=> 🖼 Graph of the temperature readings from the airport, my station, and my station adjusted by a constant value

In the above graph, you can see that my station is higher than the airport temperatures by about 8ºF (~5ºC) on average. I ended up applying a constant adjustment to the temperature sensor to combat the issue. Just today, it was reading 72ºF (22ºC). There is absolutely no way it was 80ºF (27ºC) today. The constant adjustment isn’t a great solution though. You can see that the adjusted temperature can be higher than the airport during the day, and cooler during the night by a few degrees. Since the airport is by the lake, it is possible that the actual temperature differences between me and the airport are just a few degrees different, but I don’t know. I feel like there is something going on with the sensor or setup.

I have a few theories why the temperature could be wrong:

  1. The teensy is generating too much heat, affecting the readings.

  1. The Direct sunlight is increasing the temperature of the enclosure even though it is well ventilated.

  1. Waterproofing the chip could have caused problems with the sensor. (I did not waterproof the sensor itself, just around it, but I could have made a mistake)

  1. The sensor is faulty. I could just be unlucky and got a chip that wasn’t well calibrated.

I have a feeling that the issue is coming from the teensy being too hot. When developing the software, I noticed that the chip gets warm to the touch. It’s not really something that I have noticed on other MCUs, though seeing that the Cortex M-7 is clocked at 600MHz, it’s starting to make sense why it gets a little warm. If it is warm to my touch, then it would make sense why it could affect the temperature sensors readings.

The ground plane on the circuit board covers the whole thing, so the circuit board is acting like a heat sync and since the sensor is connected to ground, a larger thermal load could be pumping heat into the sensor.

This doesn’t really explain why the actual readings would at times be close to the real temperature. I would think that when the ambient temperature goes down, there would be a larger temperature differential making it so that heat from the teensy gets taken away faster than when it’s hotter outside. This makes sense in my head, but I’m sure there is something wrong with my reasoning. The name science may be in my degree, but that doesn’t mean I’m any good at it.

If the ground plane is part of the issue, then I could redesign the circuit board to isolate the ground from the sensor from the teensy as much as I can, or get rid of the ground plane altogether.

It’s possible that direct sunlight on the enclosure could be causing problems, radiating heat into the enclosure even though the sensor is in shade. This doesn’t make much sense to me since the same enclosure was used to house the original commercial weather station.

If you have any thoughts on why I might be experiencing temperature issues, I would love to hear from you!

Remotely flashing firmware

Another problem I have had is that it is impossible for me to flash the firmware to the teensy over serial. That means if I have a firmware update for the station, I will have to go up onto the roof, take down the machine, flash it, take it back up to the roof and hope that everything went smoothly.

I’ve looked into ways that I could reflash the teensy using different UARTs other than Serial0, but it seems that the bootloader is on another chip that is hardwired to the USB port.

I feel like the best option would be to use a different MCU altogether. I have a Arduino Pro Mini laying around which doesn’t have any onboard FTDI chip. I think that I would be able have the chip go into bootloader mode and flash it all through the existing RS422 interface.

――――――――――――――――――――――――――――――――――――――――

I’ve been thinking that with the temperature issue and inability to update the firmware, my next step in the weather station project would be to replace the Cortex M7 processor with an Atmel328P chip. It has a much slower clock speed of 16MHz and a much lower power consumption.

I’ve estimated that the teensy draws 90mA (0.3W) and the Arduino draws 6mA (0.02W). Some rudimentary calculations show that 0.02WH of power in a chip should yield about 5ºC of temperature change and 0.3WH of power in a chip should yield about 75ºC of temperature change. These are very rough calculations, but I think it shows that the teensy could very well be affecting the temperature readings and that an Arduino Pro Mini should have a much small impact on the temperature.

=> Site where I calculated temperature changes

I’ve already started working on transferring the logic from the teensy to the Arduino. It really shouldn’t be difficult. The most difficult thing will probably be converting from interrupts to PCINT.

Mentions

=> Comments on Mastodon

=> 📭 Message me | 📝Or mention this post

]]>

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<category term="weather-station" label="Weather-Station" scheme="gemini://benjaminja.com/tags/weather-station/" />

<published>2024-05-16T17:55:36Z</published></entry>

<title><![CDATA[If You Give a Hobbyist a Harddrive]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2024/01/16-upgrading_server/" />

<id>gemini://benjaminja.com/log/2024/01/16-upgrading_server/</id>

<updated>2024-01-16T07:31:00Z</updated>

<summary type="gemini"><![CDATA[I recently bought a 2TB hard drive for my home server. I use this server to host NextCloud and you can never have enough storage space. This server is an Inspiron 560s from 2008. It only has two hard drive bays and already has two hard drives.

]]><![CDATA[I recently bought a 2TB hard drive for my home server. I use this server to host NextCloud and you can never have enough storage space.

This server is an Inspiron 560s from 2008. It only has two hard drive bays and already has two hard drives. There is however a dvd bay and a SD-card bay. The new hard drive fits just perfectly in the SD-card bay, so that’s its new home.

=> 🖼 Hard Drive Door

The hobbyist will need to try out a new file system

A few months back, I watched a video about ZFS and was convinced to give it a try. The only problem is that it is pretty daunting to even think about trying out.

There must be so much extra stuff that needs to be learned just to access the file system. Since ZFS is designed to work with other drives, will every drive be required to use ZFS?

These fears are not founded though. It is true that there is some extra software that is required in order to manage ZFS, but it is honestly so much easier than having to deal with parted, or fstab. All I needed to do to format and setup the new disk under ZFS was

zpool create MyPool sda

For me, the strongest selling point of ZFS is that it makes storage work closer to RAM. When running a program, I don’t need to specify which ram stick I want to have my software run in. It just figures it out for me. ZFS has this idea of pools where each pool is made up of one or more hard drives. When I put a file in the file pool, I don’t know which hard drive the data is going into, just that it is being taken care of for me.

I migrated a second 1TB drive in the server to ZFS and added it to my main pool. So instead of having 3 drives to manage, I have the boot drive, and a 3TB storage space.

While they’re at it, the hobbyist might as well upgrade the OS

I haven’t updated the OS since I originally setup the machine in 2018. I’m running Ubuntu 18.04 and it has recently gone out of long term support. There are still 4 years left of security maintenance, but I figure since I’m working on the machine now, I might as well upgrade to a newer OS. I would like to try out Debian 12.

I backed up the main drive to my newly created pool and got ready to upgrade the OS. There’s nothing like some spring cleaning where you can get rid of the residue from all your weird decisions you made in the past 6 years and start fresh.

Creating the installation medium was my first hurdle. For whatever reason, I always have trouble creating an USB installer. I primarily use Mac as my daily driver and I’ve pretty much always relied on the Raspberry Pi Imager for Mac. With newer updates to the software, it feels like it is a lot harder to burn a USB stick with anything that isn’t Raspbian. So I switched over to my windows machine and I went through several programs trying to find one that will actually burn an ISO and make the drive bootable. I settled for Rufus.

I don’t know why, but no matter what I have tried I just can’t get the BIOS to recognize my USB. The machine is old enough that it doesn’t know what UEFI is, but the one time I was able to get the machine to recognize the drive was when it was formatted with GPT which should be UEFI only. I have spent hours making tweaks and re-imaging that poor USB stick to no avail.

The hobbyist is ready to sleep now

At this point, it might be better to just give up for now. It’s not necessary that I upgrade the OS (In fact I foresee that it would cause more heartache trying to get everything up and running again from a fresh start). There are still several years left of support for the current OS and I got everything done that I was originally intending to do.

I’m really happy with how ZFS has turned out and I should just see how it goes moving forward. The next thing to figure out is how to get docker volumes to live in my pool. But that’s a problem for another day.

=> 📭 Message me | 📝Or mention this post

]]>

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<published>2024-01-16T07:31:00Z</published></entry>

<title><![CDATA[Rewriting my Site Generator]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2024/01/13-rewriting_site_gen/" />

<id>gemini://benjaminja.com/log/2024/01/13-rewriting_site_gen/</id>

<updated>2024-01-13T21:30:00Z</updated>

<summary type="gemini"><![CDATA[It’s a new year and a new me. Now that I have finally graduated, I feel that I have more time to work on my side projects. One of the first big things I have done is rewriting my site generator once again.

]]><![CDATA[It’s a new year and a new me. Now that I have finally graduated, I feel that I have more time to work on my side projects. One of the first big things I have done is rewriting my site generator once again.

=> Simple Site Generator

Rather than creating my own templating engine, I decided to use [tera].

=> tera

Keeping similar vibes to my original site generator: any additional features is implemented through shell scripts. There are a few important features baked in with the generator and all of the very site specific features are python scripts I created.

It is inspired by [kiln]

=> kiln

~~but from all of my research it seems that the site has gone down as well as the repo that was holding it.~~
Update 2024-01-16:
It turns out that source hut was hit by a DDoS attack and kiln was part of the cross-fire. Everything seems to be back up now.

Configuration

Here is a copy of my configuration file for https.

# Specify file structure content = "content"scripts = "scripts"templates = "templates"output = "www/html"static = "static"# file types that will be rendered in content directorytemplate_types = ["md", "gmi", "html", "xml"]
# Where the output will live on the web  root = "/"# The base url name for the websiteurl = "https://benjaminja.info"# Any scripts to run before renderingpre = [
"proc/pretty-url.py",
"proc/tags.py", # tags script creates the tag system for my log"proc/pretty-url.py",
]
# Any scripts to run after renderingpost = [
"proc/proc_html.py",
]
# After rendering a file, convert it using the provided convert for each file # type[converters]
md  =  { ext = "html", cmd = ["gmi-conv", "-i", "md",  "-o", "html"] }
gmi =  { ext = "html", cmd = ["gmi-conv", "-i", "gmi", "-o", "html"] }

As an example of what a file might go through, I will show you how this file gets rendered.

Let’s say that I have the text

{% raw -%} 
> The site was rendered at {{ now | ftime(fmt="%B %e, %Y @ %r %:z") }}
{%- endraw %}

Here is the output:

The site was rendered at {{ now | ftime(fmt="%B %e, %Y @ %r %:z") }}

First, the pretty-url.py script will be run which renames this file from content/log/2024/01/13-rewriting_site_gen.md to content/log/2024/01/13-rewriting_site_gen/index.md. After that the tags.py script will be run which adds this file to the capsule and projects tags. The pretty-url.py script gets run again for any generated files, then the rendering starts.

Since this is an md file, it will get rendered. After being rendered it will be converted to html using gmi-conv -i md -o html. (There is another configuration rendering to gemini). After it is converted, the file will be passed through several templates. To be specific:

  1. templates/logs/2024/_root.html which adds the title, date, and mentions.

  1. templates/_root.html which adds the base html boilerplate.

We’re not done yet, finally the proc_html.py script gets run. This will use beautiful soup to find any code blocks and adds formatting to it as well as differentiates gemini links as gemini links.

――――――――――――――――――――――――――――――――――――――――

I have two configurations running. One for html and one for gemini. I only need to write my capsule once and it will be rendered to both endpoints which is pretty nice.

Making this Publicly Available

There are still a few oddities about the software that I’m not very happy with. I also want to add a bunch of documentation so that you can actually know how to use it. So I won’t be releasing my site generator until it is in better shape.

This software is probably a bit into the “You need to be a computer wiz to use this software” territory, but If I were to add some sane 3rd party scripts and some good tutorials, I think it might could be usable by an average person.

=> 📭 Message me | 📝Or mention this post

]]>

<category term="capsule" label="Capsule" scheme="gemini://benjaminja.com/tags/capsule/" />

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<published>2024-01-13T21:30:00Z</published></entry>

<title><![CDATA[Simple Site Generator]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2023/09/03-simple_site_gen/" />

<id>gemini://benjaminja.com/log/2023/09/03-simple_site_gen/</id>

<updated>2023-09-03T08:06:00Z</updated>

<summary type="gemini"><![CDATA[It’s been a while since I last posted. I have been busy working on my weatherstation. I’ll need to write about that soon, but for now I want to talk about the state of my capsule.

]]><![CDATA[It’s been a while since I last posted. I have been busy working on my weatherstation. I’ll need to write about that soon, but for now I want to talk about the state of my capsule.

During my breaks from the weatherstation, I have been working on my own site generator. I have finally got it to the point where I can start using it in production. There’s definitely a lot of work left to be done before I can publish it for others to use.

I have been calling it simple-site for now, though I’ll probably think of a better name when I actually release it. I have designed the generator to be as simple possible while allowing for complexity to come if desired.

The design starts out with templating. I designed my own simple templating engine that I found works surprisingly well. Each document will be rendered and passed to a chain of configured templates. To get added functionality, scripts can be created which will behave like functions in the templating engine. If you need more control, then generator scripts can be used to make alterations to the structure of the site.

Since I have migrated my capsule over to the new system, I have most likely missed a few things.

Example

Here is a pretty simple example of what my generator does. Hopefully it can help visualize what’s going on.

+- content
|  +- index.gmi
|  +- my-image.jpg
+- templates
|  +- base.gmi
+- site.toml
$ simple-site site.toml
Rendering "index.gmi"  with template "base.gmi"Copying "my-image.jpg"

Mentions

=> Rewriting my Site Generator

=> 📭 Message me | 📝Or mention this post

]]>

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<category term="capsule" label="Capsule" scheme="gemini://benjaminja.com/tags/capsule/" />

<category term="gemini" label="Gemini" scheme="gemini://benjaminja.com/tags/gemini/" />

<published>2023-09-03T08:06:00Z</published></entry>

<title><![CDATA[My weather vane is now better than new]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2023/04/30-repaired_weather_vane/" />

<id>gemini://benjaminja.com/log/2023/04/30-repaired_weather_vane/</id>

<updated>2023-04-30T17:12:00Z</updated>

<summary type="gemini"><![CDATA[Yesterday, I wrote about how I broke and repaird my weather-vane After it got repaired, I was able to get the sensor working in software. Everything worked, but there was one thing odd about the sensor.

]]><![CDATA[=> /log/2023/04/29-broke_weather_vane/ Yesterday, I wrote about how I broke and repaird my weather-vane

After it got repaired, I was able to get the sensor working in software. Everything worked, but there was one thing odd about the sensor.

To give some background, the sensor can tell the direction of the wind by triggering one of 8 magnetic reed switches each connected to a resistor. If I measure the resistance of the sensor, I can tell which direction the wind is blowing.

The east resistor measured infinite ohms. In hindsight this is obviously a problem, but I thought that everything was normal until after I did my repair. Why would there be a reed switch that connects to an infinite resistor? This is the same as having a switch connected to nothing.

I took apart the sensor once again to look for any damage. I was only hoping that I wouldn’t have a busted reed switch. After some continuity testing, I found this on the east sensor:

=> 🖼 A reed switch that has been pulled off the circuit board

This must be something that has been broken for over 6 years now. I was able to make the repair, luckily it was pretty simple. Just a jumper from the resistor to the reed switch.

=> 🖼 The repaired sensor

I can’t describe just how happy I am about this.

If the wind points between two of the sensors, then it will no longer think the wind has spontaneously pointed east.

=> 📭 Message me | 📝Or mention this post

]]>

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<category term="weather-station" label="Weather-Station" scheme="gemini://benjaminja.com/tags/weather-station/" />

<published>2023-04-30T17:12:00Z</published></entry>

<title><![CDATA[Whoops, I broke my weather vane]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2023/04/29-broke_weather_vane/" />

<id>gemini://benjaminja.com/log/2023/04/29-broke_weather_vane/</id>

<updated>2023-04-29T17:47:00Z</updated>

<summary type="gemini"><![CDATA[I am working on my weatherstation project now, and I’m going to finish it for real! Yesterday I was opening up the weather-vane to reverse-engineer the board it has and make sure what I already know is correct.

]]><![CDATA[I am working on my weatherstation project now, and I’m going to finish it for real! Yesterday I was opening up the weather-vane to reverse-engineer the board it has and make sure what I already know is correct.

I was able to get my picture and put it all back together; there was only one problem. The sensor no longer worked! It turns out that when I took the board out of the housing, I also pulled the cable a bit too hard and broke the connection to the board, whoops.

Fixing the board should be pretty easy, I just have to remove what’s left of the wires, and solder the wires back in. To make sure that the wires don’t fall apart again, I decided to use solid core wires and connect the cable to that.

Everything went pretty well until I accidentally ripped one of the pads off the circuit board, whoops. I am just lucky that the pad I pulled off had a simple connection that I could easily bypass.

I was able to fix the sensor just fine. It looks a little silly, but that’s ok. The one thing that I’m more annoyed at than anything else is that I didn’t need to take apart the sensor. I had already done that around 6 years ago, and uploaded it to my wordpress blog.

=> My blog where I analyzed the weather-vane.

=> 🖼 Back of the repaird weather-vane

=> 🖼 Front of the repaird weather-vane

Mentions

=> My weather vane is now better than new

=> 📭 Message me | 📝Or mention this post

]]>

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<category term="weather-station" label="Weather-Station" scheme="gemini://benjaminja.com/tags/weather-station/" />

<published>2023-04-29T17:47:00Z</published></entry>

<title><![CDATA[Planning PWS Hardware]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2023/04/16-planning_pws_hardware/" />

<id>gemini://benjaminja.com/log/2023/04/16-planning_pws_hardware/</id>

<updated>2023-04-16T17:26:00Z</updated>

<summary type="gemini"><![CDATA[It has been a dream of mine to create my own personal weather station (PWS). I’ve been working on this project for over 6 years now. Due to school and scope creep: I have not been able to complete this project.

]]><![CDATA[It has been a dream of mine to create my own personal weather station (PWS). I’ve been working on this project for over 6 years now. Due to school and scope creep: I have not been able to complete this project. This time will be different. I have a plan. This plan has been split up into two parts: hardware and software. In previous iterations, I have developed hardware and software at the same time without a clear plan, which I believe is part of the reason why it has taken me so long.

With this semester is almost over, I have done a bit of planning so I can hit the ground running with this project. I want to have the hardware installed as soon as reasonably possible so that I can start work on the software remotely.

The general idea for this project is to have a weather station that hosts a web-app. This would allow you to view the current weather conditions from anywhere in the building.

In order to do this, I will have a raspberry pi to host the server and communicate with the station hardware. The station hardware will include a weather vane, rain meter, temperature, humidity, pressure, and possibly a uv-index sensor. This will all be directly controlled by a teensy.

Hardware plan

The raspberry pi will sit on the roof in a shady spot. It will be connected to the internet via ethernet and get power over ethernet (PoE). The pi will interface with the teensy using CAN over an ethernet cable. It’s possible that the pi could be placed indoors, but I want to attach a camera as a little bonus thing. The teensy will be directly connected with all the sensors over i2c. The weather vane and rain meter don’t have any logic chips and so will need to be specially programmed.

Software plan

The teensy will generally act as a bridge between the sensors and the pi. The weather vane and rain meter will need special logic which I will go into later. The teensy will respond to requests from the pi. The pi will run OctoWeather (PWS software that I am developing). I haven’t made any plans yet of how this software will work, but I have general ideas of what it will do in my projects page.

The weather vane has two parts: wind direction and wind speed. Both of these use reed switches to detect what is happening. The wind speed closes the circuit on every rotation (maybe every 180º I can’t quite remember which). The wind direction has eight reed switches each connected to a different resistance to detect which cardinal direction the wind is blowing in. The rain meter has one reed switch that triggers every time 0.01 inches has fallen. The wind speed and rain meter will need to have special software to asynchronously determine how much rain has fallen and how fast the wind is blowing. This should be relatively easy by using pin change interrupts. The wind direction can be connected to a voltage divider to measure resistance on an analog pin.

What I’ve done so far

I have been able to install an ethernet cable that goes from the basement to the roof. I have also collected all of the hardware that I plan to use for this project.

=> 🖼 Ethernet Going to the roof

=> 🖼 Hardware I have so far

=> 📭 Message me | 📝Or mention this post

]]>

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<category term="weather-station" label="Weather-Station" scheme="gemini://benjaminja.com/tags/weather-station/" />

<published>2023-04-16T17:26:00Z</published></entry>

<title><![CDATA[How I deploy to my server]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2023/02/13-how_i_deploy/" />

<id>gemini://benjaminja.com/log/2023/02/13-how_i_deploy/</id>

<updated>2023-02-14T17:25:00Z</updated>

<summary type="gemini"><![CDATA[I don’t run this capsule on a server that I physically own. I rent out my server from digitalocean. Since my server doesn’t need to have lots of computing power or memory, I have opted to use the cheapest server possible that pennies can buy.

]]><![CDATA[I don’t run this capsule on a server that I physically own. I rent out my server from digitalocean. Since my server doesn’t need to have lots of computing power or memory, I have opted to use the cheapest server possible that pennies can buy. The only problem is that the server is so underpowered: it is nearly impossible to install software from source. In this log, I will explain how I go about deploying software to my server.

=> digitalocean.com

I’ve deployed my server as a droplet using a single shared CPU with 512 MB of memory. Because of these low specs, I have decided that all of my server/CGI software will run on native binaries to make using my capsule as smooth as possible.

The main server software that I use is made with Rust; a language known for its long and intensive compilations. I tried building it on my server and it took around 10 minutes before the build crashed from a lack of available memory. I would probably be better off cross compiling from my computer and uploading the binary than trying to find some workaround.

Uploading to the server

Compiling software for the server can vary widely from language to language, but it is almost always the same to upload your built binary to the server. The way I do it is by having a deploy.sh script in the root of a project that will build, upload, and install the software on the server.

BINARY=path/to/binary
REMOTE=root@my_server
BINAME="$(basename "$BINARY")"BINDIR=/usr/local/bin
TMPDIR=/var/tmp
# TODO Buildscp "$BINARY""$REMOTE:$TMPDIR/"ssh "$REMOTE""cd $TMPDIR && 
    install -Dm755 ./$BINAME$BINDIR/$BINAME &&
    rm ./$BINAME"

Of course depending on the type of software I’m deploying, the script may need to change to fit the project’s needs. I feel that it would be simpler to just scp the binary directly into the installed destination rather than installing it with a separate command, but I kind of like it.

Deploying Rust

Rust has become my goto language when it comes to compiled software. It supports a lot of language features that I like. It can feel like a high-level language while still allowing for low level control. My problem with Rust is with how difficult it is to cross compile. In theory, it is very easy to cross compile Rust, but when external libraries are used: the process becomes infinitely more complicated.

You will first need to install a target for your toolchain (This is fairly easy). If the program doesn’t use any external libraries, you should be good to go. Otherwise, you will need to install a C cross compiling toolchain (This can be tricky depending on your host system) and tell rust the linker you will be using in .cargo/config.toml. If your build still fails, a library might be compiling C from source, so you will need to tell rust that any C code should be built using your cross compiling toolchain in an environment variable. If you still can’t cross compile the software, then get ready for a never ending rabbit hole.

There is a tool that will help you do cross compiling that I wish I had known about before I spent a week learning how to do it manually. It is called “Cross”, and allows you to do cross compilations with very little hassle.

=> Cross

You will need to have Docker installed for Cross to work, but I think I have read that it might be possible to configure Cross to use Zig as a linker/compiler instead of building inside a Docker container.

Building with Cross is usually as simple as replacing cargo with cross. Depending on your needs, you may need to create a Cross.toml to customize your build, but that is still simpler than doing it manually.

TARGET=x86_64-unknown-linux-gnu
BINAME=
BINARY=target/release/$TARGET/$BINAME
cross build --release --target $TARGET

Deploying Go

In comparison to Rust, Go is a walk in the park. All that is needed to cross compile Go is two environment variables: GOOS and GOARCH. I don’t know if there are any edge cases that might show up when building. I really should learn Go.

BINAME=
BINARY=$BINAME
GOOS=linux GOARCH=amd64 go build

I haven’t needed to do anything else for Go to work, but I also don’t know the language. If it were possible to use external libraries, then I would imagine that cross compilation could get more complicated, but I just don’t know enough about the language to know if that’s even possible.

Deploying my capsule

This isn’t a language, but I figure it’s worth mentioning. When I deploy my capsule, I upload the project up to the server and then render it. This allows for semi-dynamic content that is stored exclusively on the server to be rendered into the capsule. The way I go about deploying the capsule is a little bit funky, but it works and that’s all that matters.

DIR="$(dirname -- "${BASH_SOURCE[0]}")"SERVER='gemini@my_server'DEST='/path/to/capsule/data/'SOURCE="$DIR/."GEMINI="/var/www/gemini/my.site/"COMMAND="${1:-upload}"# Upload to the serverif["$COMMAND"="upload"]; then# Synchronize the project with the server    rsync -rltp --delete-after -z --exclude='./git' --filter=':- .gitignore' -h "$SOURCE""$SERVER:$DEST"    echo "Uploaded capsule"# Run the build section of the deploy script on the server    ssh -t "$SERVER""cd $DEST ; ./deploy.sh build"elif["$COMMAND"="build"]; then# Render the capsule    cd "$DIR"    kiln build
    RES=$?
if[ $RES -ne 0]; then        exit $RES
fi# Copy the rendered files into the server folder    rsync -r "${DEST}public/""$GEMINI"    RES=$?
if[ $RES -ne 0]; then        exit $RES
fielse    echo "Invalid Command, should be one of [upload, build]"fi

I haven’t yet had the chance to deploy any other types of software, but I can imagine that some will be easier than others. Zig should be pretty simple, but C/C++ scares me. The thought of having to find or build libraries does not seem at all fun. Though C/C++ should still be easier than Rust.

=> 📭 Message me | 📝Or mention this post

]]>

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<category term="capsule" label="Capsule" scheme="gemini://benjaminja.com/tags/capsule/" />

<category term="gemini" label="Gemini" scheme="gemini://benjaminja.com/tags/gemini/" />

<published>2023-02-14T17:25:00Z</published></entry>

<title><![CDATA[MAC Attack!]]></title>

  <link rel="alternate" type="text/gemini" hreflang="" href="gemini://benjaminja.com/log/2023/02/06-macattack/" />

<id>gemini://benjaminja.com/log/2023/02/06-macattack/</id>

<updated>2023-02-07T05:43:00Z</updated>

<summary type="gemini"><![CDATA[I just finished the third project for my security class. This project has been simultaneously the most difficult and most easy lab that I have done. I wanted to describe my experience of the lab here.

]]><![CDATA[I just finished the third project for my security class. This project has been simultaneously the most difficult and most easy lab that I have done. I wanted to describe my experience of the lab here.

The Premise

The premise is that my TA has sent a message to my professor and I was able to intercept it. The message is as follows.

No one has completed lab 2 so give them all a 0

A MAC (Message Authenticated Code) was also in the message, which we know used a 128-bit key. The MAC is as follows in hex.

e384efadf26767a613162142b5ef0efbb9d7659a

I want to change the message to tell the professor that I should get full points, but I can’t because there is a MAC attached to the message. If I were to change the message, the attached MAC would be invalid and I could not generate a new MAC because I don’t have the secret key for the MAC.

=> MAC (Gemipedia) | MAC (Wikipedia)

How I went about the lab

This lab was one of those projects where you just have no idea where to start. I knew what I needed to do and vaguely how it should be done, but the specifics were beyond me. The project turned mostly into analyzing library code and trying to figure out how I could modify it to do what I need, which is to say the least, very stressful.

With this in mind, I was mostly working on creating unit tests that would help me fumble my way through the lab and took many breaks.

I would say the most frustrating thing about the lab was that a big part of it was on hashes, which changes wildly with even the smallest change, so it was very difficult to know whether I was getting close or not.

In the end, I was able to figure it out and I can’t describe how relieved I was.

Below is a more technical description of how the lab worked, so tread on if you dare.

Vulnerability in MAC

There is a vulnerability in MAC which took me a while to fully understand. In order to explain the vulnerability, I will have to explain how MAC works in the first place.

MAC is relatively simple. You start out with a key and a message. you concatenate them together and hash it:

Key = "0123456789abcdef"
Message = "Hello World!"
MAC = SHA("0123456789abcdefHello World!")
MAC = 36f141824e771ed3313815d82c996522d8191a99

The SHA algorithm will recursively calculate a digest from 512-bit blocks of data. Because of this, it is possible to continue calculating a hash by using the digest as the initialization vector for the SHA algorithm.

If we were to add to the end of the original message, hash that added bit with IV (initialization vector) being the original MAC, then we could pass this modified message and MAC to the professor and they would think the message was authentic.

The only problem is that SHA adds some information and padding to the end of the message internally to keep all blocks exactly 512 bits long. The solution is to simply add the padding to the end of the message, but before our added bit. One last thing to deal with is that SHA adds the length of the hashed string at the end of the last block, so we will need to know the length of the key for this to work.

The Attack

We are given pretty much everything we need for the attack. The most difficult thing will be figuring out how to modify the IV. According to my teacher, golang’s API for SHA allows setting the IV, but most languages don’t provide that functionality. I had to download a SHA-1 library and modify it myself to allow for setting an initialization vector. Analyzing the library and making it work for what I need was probably one of the most hair pulling things I have done.

Adding the padding to the message wasn’t too difficult, particularly with the aid of unit testing.

In the end I was able to generate this message to send to my teacher; posing as my TA with a valid MAC. The message itself looks a little corrupted, but that is a problem to deal with another day.

Message: No one has completed lab 2 so give them all a 0\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xf8P.S. Except for ttocsneb, Give him 100%
MAC: d338d12365cd75f5f13673991d9cd1359e355b2e

Prevention from this kind of attack

The best way to prevent this attack from being possible would be to use HMAC instead. It essentially performs two hashes with the key being manipulated in a way that I can not understand.

=> HMAC (Gemipedia) | HMAC (Wikipedia)

=> 📭 Message me | 📝Or mention this post

]]>

<category term="school" label="School" scheme="gemini://benjaminja.com/tags/school/" />

<category term="projects" label="Projects" scheme="gemini://benjaminja.com/tags/projects/" />

<published>2023-02-07T05:43:00Z</published></entry>

Proxy Information
Original URL
gemini://benjaminja.com/tags/projects/feed.xml
Status Code
Success (20)
Meta
text/xml
Capsule Response Time
1108.237585 milliseconds
Gemini-to-HTML Time
19.672705 milliseconds

This content has been proxied by September (ba2dc).