Lots of changes.

master
Tanner Collin 2 years ago
parent 1fce747278
commit 163ef3aad3
  1. 29
      content/.obsidian/workspace
  2. 4
      content/Acoustic Panels.md
  3. 7
      content/Backup Strategy.md
  4. 28
      content/Fake Dog.md
  5. 2
      content/Painting.md
  6. 2
      content/Plant Waterer.md
  7. 2
      content/Solar Car.md
  8. 41
      content/Things I Recommend.md
  9. 2
      content/Wine Crate Coffee Table.md
  10. BIN
      content/media/Pasted image 20220701212211.png
  11. BIN
      content/media/fake-dog.jpg
  12. BIN
      content/media/fake-dog2.png
  13. BIN
      content/media/fake-dog3.jpg
  14. BIN
      content/media/recommend1.png
  15. BIN
      content/media/recommend2.png
  16. BIN
      content/media/recommend3.png
  17. 4
      content/t0 Services.md
  18. 11
      content/t0txt.md
  19. 127
      themes/lite/templates/article.html
  20. 2
      themes/lite/templates/index.html
  21. 2
      themes/theme/templates/index.html

@ -4,12 +4,12 @@
"type": "split",
"children": [
{
"id": "e466de4f93356253",
"id": "25a79872dfa9b9bf",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "t0 Services.md",
"file": "Fake Dog.md",
"mode": "source",
"source": false
}
@ -69,7 +69,7 @@
"state": {
"type": "backlink",
"state": {
"file": "t0 Services.md",
"file": "Fake Dog.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
@ -86,7 +86,7 @@
"state": {
"type": "outline",
"state": {
"file": "t0 Services.md"
"file": "Fake Dog.md"
}
}
}
@ -95,19 +95,20 @@
}
],
"direction": "horizontal",
"width": 300
"width": 300,
"collapsed": true
},
"active": "e466de4f93356253",
"active": "25a79872dfa9b9bf",
"lastOpenFiles": [
"t0 Services.md",
"Linux Flavour.md",
"t0txt.md",
"Fake Dog.md",
"Protospace.md",
"Light Switch.md",
"Notica.md",
"Plant Waterer.md",
"fake-dog.png.md",
"media/fake-dog.png",
"QotNews.md",
"Sensors.md",
"Solar Car.md"
"Notica.md",
"Bypassing Ports.md",
"Backup Strategy.md",
"Acoustic Panels.md",
"Hand of Ozymandias.md"
]
}

@ -12,11 +12,11 @@ Acoustic panels are placed geometrically where the sound from the speakers would
![[ panel1.jpg | twelve L-shaped corners of the panels stacked together leaning on a table saw in a wood shop]]
I made six frames in the wood shop of my local makerspace, Protospace. After cutting the 1x4" pine boards to length, I made a jig so I could quickly join them together with screws.
I made six frames in the wood shop of my local makerspace, [[Protospace]]. After cutting the 1x4" pine boards to length, I made a jig so I could quickly join them together with screws.
![[ panel2.jpg | a panel with insulation inside on the ground about to be wrapped with black fabric]]
I added 4" batts of Rockwool insulation into each frame after it was assembled. I then wrapped the frame with black speaker fabric and stabled it in place while trying to pull it taut.
I added 4" batts of Rockwool insulation into each frame after it was assembled. I then wrapped the frame with black speaker fabric and stapled it in place while trying to pull it taut.
I sat in my theatre while a friend slid a handheld mirror along the wall until I could see the middle of the speaker in its reflection. This told me the centre point of where to mount each panel because the reflected sound would take the same path to my ear.

@ -3,7 +3,7 @@ Date: 2021-04-08
Category: Writing
Summary: Details about the backup system for all of my data.
Wide: true
Short: 1
Short: backup
[TOC]
@ -20,6 +20,7 @@ Backups need to be tested to ensure they are correct and happening regularly. M
Backups should also be incremental when possible (rather than mirror copies) so an accidental deletion isn't propagated into the backups, making the file irrecoverable.
## Strategy
The key is to have one central location that all your files, projects, and data are cloned to and then back that directory up to multiple locations.
I have one backup folder `/mnt/backup` on my media server at home that serves as the destination for all my backup sources. All scheduled automatic backups write to their own subfolder inside of it.
@ -142,7 +143,7 @@ All the files will be included in the 1 TB hard drive backup rotations.
### Web Services
Web services that I run like [txt.t0.vc](https://txt.t0.vc) and [QotNews](https://news.t0.vc) are backed up daily, weekly, and monthly depending on how frequently the data changes.
Web services that I run like [[t0 Services]] and [[QotNews]] are backed up daily, weekly, and monthly depending on how frequently the data changes.
I run `rdiff-backup` on the remote server with cron:
@ -163,7 +164,7 @@ The `tbotbak` user has write access to the `/mnt/backup/remote/tbotbak` director
### Protospace
I run a lot of services for [Protospace](https://protospace.ca/), my city's makerspace.
I run a lot of services for [[Protospace]], my city's makerspace.
The member portal I wrote called [[Spaceport]] creates an archive I download daily:

@ -0,0 +1,28 @@
Title: Fake Dog for Home Security
Date: 2022-06-27
Category: Creations
Summary: Fake dog barking for home security while on vacation.
Short: 7
I set up a fake dog that barks if my surveillance cameras are triggered while I'm out of town on vacation. It's a pair of computer speakers plugged into a Raspberry Pi, which is an inexpensive single-board computer. One speaker faces the front door and the other faces the side door.
When the front door camera is triggered my surveillance camera system sends a message to the Raspberry Pi. A simple program plays an audio clip of a big dog barking through the side speaker and then the front speaker. The change in speakers simulates a dog moving towards the front door. The opposite happens if the side door camera is triggered.
You can find the [source code](https://git.tannercollin.com/tanner/woof) on my Gitea.
![[fake-dog.jpg]]
## Technical Details
My surveillance cameras sit on a separate network without internet access and their RTSP streams are consumed by the Blue Iris NVR software running on a dedicated Windows box. When an object is detected moving through a defined area for certain cameras, Blue Iris is configured to send an MQTT message to the `iot/cameras` topic via the Mosquitto broker running on my media server.
A Python script kept alive by Supervisor runs on the Raspberry Pi and listens to the topic using the `asyncio-mqtt` module. It receives and tries to decode a json message like `{"serial": "SE-N-ZoneB"}`. If the camera's serial is found in a dict at the top of the script, the corresponding audio file is played using Pygame. Controlling which speaker barks is done by muting the left or right channel in the stereo audio file.
![[fake-dog2.png]]
## Efficacy
So is it worth it? According to [former burglars](https://news.t0.vc/TRMA), barking dogs and security cameras are some of the best deterrents to home invasions. The dog sounds kind of fake to me, but I know it isn't real. I'm hoping that a rushing burglar won't spend time pondering if the barking is from an elaborate speaker setup and will just move on to a different house.
Is it needed in my neighbourhood? I think so. I already caught a prowler who went in my backyard and checked my garage door handle to see if it was locked. He then broke into my neighbour's truck and garage after. If you know this guy, shoot me an email:
![[fake-dog3.jpg]]
The extra peace of mind while I'm away is worth the evening it took to set up. It was very easy to make because I reused the code I wrote for [[Protospace]]'s PA system doorbell that you can find on [GitHub](https://github.com/protospace/doorbell). It operates similarly by playing an audio file based on which 433 MHz doorbell is pressed.

@ -2,7 +2,7 @@ Title: Man's Reach Exceeds His Grasp
Date: 2012-04-11
Category: Creations
Summary: My first attempt at painting with acrylic.
Short: 7
Short: painting
The painting is called “Man’s Reach Exceeds His Grasp”. I've always wanted to try painting and thought I had a good idea, so after a couple of drawings I attempted to paint it. I eventually got it framed at Michaels. Many thanks to my friend Laura for the opportunity to do this, I couldn't have done it without her help.

@ -2,7 +2,7 @@ Title: Automatic Plant Waterer
Date: 2014-06-05
Category: Creations
Summary: A device that automatically waters plants.
short: 8
short: waterer
One day I decided watering my one plant was too much work, so I automated it. It's also great for when I'm on vacation. The plant is a year old now and doesn't look as good as it used to (kinda like you). So this machine is like its life support.

@ -2,7 +2,7 @@ Title: Solar Car
Date: 2013-04-27
Category: Creations
Summary: About my time volunteering with the University of Calgary Solar Car Team, where I designed a maximum power point tracker.
Short: 9
Short: car
I joined the University of Calgary Solar Car Team in my first semester for a chance to learn things, gain practical experience, and meet people that share my interests. The car was the top Canadian team in a 3000 km race from Darwin to Adelaide, Australia in 2011. We met up at a shop on campus every Saturday morning to work on the new Generation IV of the solar car.

@ -0,0 +1,41 @@
Title: Things I Recommend
Date: 2022-06-24
Category: Writing
Summary: Software and products that I recommend you use.
Wide: true
Short: 1
This outlines some software and devices I recommend you use: uBlock Origin, Sponsorblock, ThruNite T1 flashlights, Logitech G Pro Wireless mice, and ThinkPad Laptops. Nothing here was sponsored.
[TOC]
## Software
### uBlock Origin
uBlock Origin is an open source ad blocker and something I install immediately on all my devices. Running an ad blocker makes browsing the web way better. It removes distracting ads (even from YouTube), invasive tracking, and makes you safer by removing potentially fake links. It's the best piece of software I use even though it mostly remains unseen. And it even works on your phone.
You can install it on [Firefox Desktop](https://addons.mozilla.org/en-CA/firefox/addon/ublock-origin/), [Firefox Android](https://addons.mozilla.org/en-CA/android/addon/ublock-origin/), and [Chrome Desktop](https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm?hl=en). Make sure you install the correct "Origin" version and avoid "ublock.org".
### SponsorBlock
SponsorBlock automatically skips over sponsored segments in YouTube videos. Not YouTube ads (that's what uBlock Origin is for), but the actual parts of the video sponsored by companies to advertise their products. It uses a crowd-sourced database of timestamps to seamlessly jump over those parts. It also allows you to skip to the highlight of some videos by pressing "enter" so you aren't wasting time watching exposition.
You can install it on [Firefox Desktop](https://addons.mozilla.org/en-CA/firefox/addon/sponsorblock/) and [Chrome Desktop](https://chrome.google.com/webstore/detail/sponsorblock-for-youtube/mnjggcdmjocbbbhaepdhchncahnbgone?hl=en).
![[recommend1.png]]
![[recommend2.png]]
## Devices
### ThruNite T1 Flashlight
This is a tiny rechargeable flashlight that can output 1500 lumens, enough to hurt your eyes if you look directly into it. It has a magnet on the back to stick to things and an optional pocket-hat clip. I liked it so much I've bought three of them and gave one to a friend who then bought himself a couple more.
![[recommend3.png]]
### Logitech G Pro Wireless Mice
I've used a lot of wireless mice, and this one is by far my favourite. It has a USB dongle which I prefer because Bluetooh pairing annoys me. If you disable the LEDs the battery lasts for a few weeks of solid usage.
I like it so much that I own five of them: one for my office desk, nook desk, laptop bag, home theatre, and surveillance cameras NVR. I leave the last one plugged in so that when a mouse battery dies, I can swap it with a fully charged mouse that's ready to go. It also ensures they wear at a somewhat even rate.
### ThinkPad Laptops
I've had several different laptops over the years and have settled on buying ThinkPads going forward. I hate Lenovo as company because of their [Superfish scandal](https://en.wikipedia.org/wiki/Superfish#Lenovo_security_incident), but I can't deny that ThinkPads are absolutely solid. I currently own a ThinkPad X1 Carbon 6th Gen.
A lot of Linux developers use ThinkPads which means Linux is well supported on them and the drivers just work. The laptops are easy to pop open and service. Many parts are user-replaceable. My laptop charges off a small USB-C phone charger that I carry around. In a state of sickness-induced exhaustion, I spilled an entire glass of Gatorade on it and then drenched it in water to try and flush it away. I took the back off, drained it, and then pointed a fan at it for 24 hours. The laptop was working fine the next day.

@ -6,7 +6,7 @@ Short: 0
My close friend Odai saw a simple coffee table design online that was built out of four wooden wine crates. They are quite cheap and available at any hardware store. We each wanted to make one so went and bought eight crates and some plywood to use as a base.
We went to my local makerspace, Protospace, to build them in the wood shop. We thought it would be a quick job only taking a few hours, but it turned out to be a twelve hour job over a couple of days. At least we were in good company!
We went to my local makerspace, [[Protospace]], to build them in the wood shop. We thought it would be a quick job only taking a few hours, but it turned out to be a twelve hour job over a couple of days. At least we were in good company!
![[wine1.jpg | the table before staining. four box-like wine crates are on their sides and joined together in a spiral. a messy wood shop is in the background]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

@ -19,7 +19,7 @@ The second t-zero I wrote was [[t0txt]], a pastebin that is compatible with the
I figured that since I have a pastebin, I might as well make an image host since Imgur now sucks. It supports web and command line upload and pasting directly into the web page. I don't advertise it because public image hosts usually end up abused. However, you can easily find it if you follow the naming pattern.
## t0url
Next I created a URL shortener called [t0url](https://url.t0.vc) because I wanted to transfer links between devices quickly. Other shorteners use longer IDs but since this is my own, I can get away with only four capital letters which makes them easy to type and remember.
Next I created a URL shortener called t0url because I wanted to transfer links between devices quickly. Other shorteners use longer IDs but since this is my own, I can get away with only four capital letters which makes them easy to type and remember. I also don't advertise it because URL shorteners end up abused by scammers.
## t0reg
I then built a key-value store called [t0reg](https://reg.t0.vc). With "reg" meaning registers, it acts exactly like the t0txt pastebin but you can specify the destination ID where the data is stored. This is the most esoteric service, but the most used one because I have bots and scripts that periodically push and pull data to it. I also have bash curl aliases set up to help move data between servers with `foo | push` and `pull > foo.txt`.
@ -28,4 +28,4 @@ I then built a key-value store called [t0reg](https://reg.t0.vc). With "reg" mea
My site's [guestbook](https://t0.vc/g/) is powered by t0sig. When a guestbook entry is submitted, it's held in memory and assigned an ID. A bot then sends me the message over Telegram and I can choose to approve it by clicking a command. After approval, the message is simply appended to the end of the guestbook page. You can read the source code [here](https://git.tannercollin.com/tanner/t0sig/src/branch/master/t0sig.py).
## t0dns
I wrote the Telegram bot [t0dns](https://t.me/t0dns_bot) to quickly manage DNS records for `dns.t0.vc`. I got tired of logging into my domain registrar every time I wanted to add a subdomain for whatever random project I was working on. Now I only have to send a command to the bot like `/add_cname sensors ms.tannercollin.com.` and it will add the `sensors.dns.t0.vc` record to a zone file that it resolves. Anyone can use it, but I routinely prune the records so don't rely on it.
I wrote the Telegram bot [t0dns](https://t.me/t0dns_bot) to quickly manage DNS records for `dns.t0.vc`. I got tired of logging into my domain registrar every time I wanted to add a subdomain for whatever random project I was working on. Now I only have to send a command to the bot like `/add_cname sensors ms.tannercollin.com.` and it will add the `sensors.dns.t0.vc` record to a zone file that it resolves. Anyone can use it, but I routinely prune the records so don't rely on it.

@ -20,3 +20,14 @@ $ curl https://txt.t0.vc/IMLV
hello world!
```
## Spam Issue
After running t0txt for a while, I noticed there were a large number of pastes only containing random links. The service was being hit by backlink spam bots who try to submit any web form they find hoping they can spread links around. They do this to try and improve the search ranking of their client's websites. I added a simple CAPTCHA with the question "Who owns this site?" that checks for a substring of "tanner". This seems to have eliminated most spam.
I found a lot of txt.t0.vc links around the internet with pastes containing all sorts of spam. Cheap pharmaceuticals, blogs, online casinos, porn, and surprisingly lots of essay writing services. I wanted to clean these up because I didn't want the URL to be tarnished. I wrote a simple [script](https://github.com/tannercollin/t0txt/blob/master/misc/clean.py) that deletes pastes based on spam-words. It deleted 22,500 pastes out of the total 33,000 in the database.
The spam cleaning script iterates over all pastes. If the paste contains a word from the whitelist, it continues because it's probably related to one of my projects. If it contains a banned word from a list, it's marked for deletion. If it contains at least two words commonly associated with spam, it's also marked for deletion. A large percentage of the spam was in different languages I can't read, so I randomly chose words hoping to not get many false positives. Finally it counts the number of occurrences of "http" and compares it to the number of lines. If the count and ratio is above a threshold, it's marked for deletion.
## Don't Advertise your Pastebin
Pastebins are one of those projects not worth advertising. You should keep it within your circle of friends and grow by word-of-mouth and people seeing the links to your pastes. Additional users don't really get you anything except a larger database you have to back up. Advertising it will just bring spam which tarnishes the reputation of your domain and any subdomains on it.
I regret advertising t0txt, but the cat is already out of the bag so it doesn't really matter going forward. It would be interesting to make a pastebin where the paste's domain is different than the submission domain if you want to keep it somewhat hidden.

@ -1,57 +1,80 @@
{% extends "base.html" %}
{% block meta %}
<meta charset=UTF-8>
{% endblock %}
{% block style %}
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ article.title|striptags }} - t0.vc</title>
<meta charset=UTF-8>
<meta name="viewport" content="width=device-width, initial-scale=1">
{% if article.date %}
<meta name="date" content="{{article.date}}" />
{% endif %}
{% if article.summary %}
<meta name="description" content="{{article.summary|striptags}}" />
<meta name="summary" content="{{article.summary|striptags}}" />
{% endif %}
{% if article.category %}
<meta name="category" content="{{article.category}}" />
{% endif %}
{% for tag in article.tags %}
<meta name="tags" content="{{tag}}" />
{% endfor %}
{% endblock %}
<style>
a.external {
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath fill='%23fff' stroke='%23000' d='M1.5 4.518h5.982V10.5H1.5z'/%3E%3Cpath fill='%23000' d='M5.765 1H11v5.39L9.427 7.937l-1.31-1.31L5.393 9.35l-2.69-2.688 2.81-2.808L4.2 2.544z'/%3E%3Cpath fill='%23fff' d='m9.995 2.004.022 4.885L8.2 5.07 5.32 7.95 4.09 6.723l2.882-2.88-1.85-1.852z'/%3E%3C/svg%3E%0A");
background-position: center right;
background-repeat: no-repeat;
padding-right: 15px;
}
.toclink:not(:hover) {
text-decoration: none;
outline: none;
}
.content {
max-width: 600px;
}
.toclink {
color: black;
}
.highlight > pre {
margin: 0;
padding: 0.5rem;
overflow-x: auto;
background-color: #eee;
}
:not(pre)>code {
padding: 0 2px;
font-size: 0.8rem;
background-color: #eee;
}
.aside {
display: none;
}
.toc {
display: none;
}
img {
width: 600px;
height: auto;
}
</style>
{% endblock %}
{% block style %}
<style>
a.external {
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath fill='%23fff' stroke='%23000' d='M1.5 4.518h5.982V10.5H1.5z'/%3E%3Cpath fill='%23000' d='M5.765 1H11v5.39L9.427 7.937l-1.31-1.31L5.393 9.35l-2.69-2.688 2.81-2.808L4.2 2.544z'/%3E%3Cpath fill='%23fff' d='m9.995 2.004.022 4.885L8.2 5.07 5.32 7.95 4.09 6.723l2.882-2.88-1.85-1.852z'/%3E%3C/svg%3E%0A");
background-position: center right;
background-repeat: no-repeat;
padding-right: 15px;
}
.toclink:not(:hover) {
text-decoration: none;
outline: none;
}
.content {
max-width: 600px;
}
.toclink {
color: black;
}
.highlight > pre {
margin: 0;
padding: 0.5rem;
overflow-x: auto;
background-color: #eee;
}
:not(pre)>code {
padding: 0 2px;
font-size: 0.8rem;
background-color: #eee;
}
.aside {
display: none;
}
.toc {
display: none;
}
img {
width: 600px;
max-width: 100%;
height: auto;
}
</style>
</head>
{% endblock %}
{% block content %}
<div class="content">
<h1>{{ article.title }}</h1>
{{ article.summary }}
{{ article.locale_date }}
<hr />
{{ article.content }}
</div>
{% block content %}
<body>
<div class="content">
<p><a href="/">Return Home</a></p>
<h1>{{ article.title }}</h1>
{{ article.summary }}
{{ article.locale_date }}
<hr />
{{ article.content }}
</div>
</body>
</html>
{% endblock %}

@ -37,7 +37,9 @@ Creations
Writing
{% for article in articles_page.object_list if article.category.name == 'Writing' %}
{% if loop.index <= 4 %}
<a href={{ article.url }}>{{ article.title }}
{% endif %}
{% endfor %}
<a href=x>[more]
{% endblock %}

@ -27,7 +27,7 @@
{% block content %}
<div class="content index">
<p>
Hi, I'm Tanner! I do firmware and web development in Calgary.
Hi, I'm Tanner! I like home automation, <a href="/sensors">sensors</a>, privacy, bots, Python, Debian, coffee, and makerspaces.
</p>
<h2>Contact Info</h2>

Loading…
Cancel
Save