Finished reading: Stories of Your Life and Others by Ted Chiang š
Very interesting stories in this collection! I enjoyed it.
Finished reading: Stories of Your Life and Others by Ted Chiang š
Very interesting stories in this collection! I enjoyed it.
After much effort (and help from the forums), I was able to get a config working for my backyard weather station.
My station is custom built hardware, and returns a very simple JSON object with its current state when queried.
The json it returns looks like this:
{"timestamp":"2022-03-12 09:35:36 -0700",
"temperature_c":15.8720368908,
"temperature_f":60.56966640344,
"humidity":27.009330285,
"pressure":965.103717974,
"dewpoint_c":-3.0690760974329714,
"dewpoint_f":26.47566302462065}
And this is the Home Assistant configuration I needed to use to get the data into HASS:
rest:
- resource: http://weather.local
scan_interval: 60
sensor:
- name: Weather Station - Temperature
value_template: '{{ value_json.temperature_f | round(1) }}'
unit_of_measurement: '°F'
device_class: temperature
state_class: measurement
- name: Weather Station - Humidity
value_template: '{{ value_json.humidity | round(1) }}'
unit_of_measurement: '%'
device_class: humidity
state_class: measurement
- name: Weather Station - Pressure
value_template: '{{ value_json.pressure | round(1) }}'
unit_of_measurement: 'mbar'
device_class: atmospheric_pressure
state_class: measurement
- name: Weather Station - Dewpoint
value_template: '{{ value_json.dewpoint_f | round(1) }}'
unit_of_measurement: '°F'
device_class: temperature
state_class: measurement
Home Assistant is very powerful, but goodness is the learning curve steep. Documentation exists, but much of it is not helpful enough. I should probably contribute back some additional examples, at the least.
(Interesting side note: I asked ChatGPT to help me put together a configuration for this setup. It was able to do so, but the result was inefficient and used an older style of REST sensor setup. Human help in the forums led me to this solution.)
Thought experiment: a lossy compression algorithm that includes noise in the decompression phase. Every decompression is unique. š¤
I had to play around with the Home Assistant API to figure out how to set the brighness of a dimmable lamp. This is what ended up working.
My lamp was setup with brightness as a Number
.
curl -H "Authorization: Bearer your_token_goes_here" -H "Content-Type: application/json" -d '{"entity_id": "number.my_lamp", "value": 100}' http://homeassistant.local:8123/api/services/number/set_value
Currently reading: The Arctic Incident (Artemis Fowl, Book 2) by Eoin Colfer š
If the CEO of OpenAI thinks that you are a stochastic parrot, then that means that he doesn’t really recognize you as a person. We have a word for that kind of systemic lack of empathy and that word is “psychopath”.
Spent way too much time trying to get my ESP32 board to send data to my mqtt broker. Still havenāt got it working. Probably should have just stuck with REST. Too clever for my own good.
It turns out that if you set an environment variable named AWS_PROFILE, all AWS SDKs (including the CLI) will respect that value when looking for credentials for the current command.
Thanks to my brother, Ben, for pointing this out to me. It cleaned up a ton of boilerplate in some Ruby code I’ve been writing.
Currently reading: Stories of Your Life and Others by Ted Chiang š
Finished reading: Abandon by Blake Crouch š
Well written but too hopelessly dark for my taste.
ChatGPT and its ilk may well result in a better experience for searching than Google ā for a while. But if you don’t think the shitty incentives that led to Google’s quality dropping off aren’t going to affect these LLMs in the exact same ways, I’ve got a bridge to sell you.
Docker is just terrible. The default options always seem wrong. The error output is often inscrutible. Debugging is a nightmare. This is just poorly designed software.
This is enshittification: Surpluses are first directed to users; then, once they’re locked in, surpluses go to suppliers; then once they’re locked in, the surplus is handed to shareholders and the platform becomes a useless pile of shit. From mobile app stores to Steam, from Facebook to Twitter, this is the enshittification lifecycle.
This is it. The last 25 years in a nutshell.
There is no way that the people who work on docker actually ever use docker.
Currently reading: Abandon by Blake Crouch š
Finished Andor. What a show.
For months I haven’t been able to login to “My UPS” (which is now the only way to get detailed tracking info). Attempting to login would give me error LASSO_1010. Attempting to reset my password would return an “Application error” and never send a reset email.
The solution (via this Reddit thread) was to install the UPS mobile app, and initiate a password reset from the app. In that case I did receive the reset email, and was able to update my password, and I can now login.
Replaced a thumb stick in a VR controller tonight. Required a full tear down, but cost $15 instead of $75 for a new controller, and Iām not sending a good controller to the landfill because one part was bad.
Was fiddly and took a while, but very gratifying.
⦠the impulse to repair arises from and is sustained by love ā and that the particular form of love at work here is friendship. By repairing the things of this world we exhibit friendship towards them ā and they become friends to us in return.
Alan Jacobs, the friendliness of objects
If you buy something off the shelf, like an iPhone, which you can’t change, you’re less likely to care for it, and it’s going to end up in a drawer. Back then you could go to Radio Shack and get parts for your computer, it was possible to customize it (for example, the Altair), and then you could know it in its entirety. Devices that were customized, or built from near-scratch, are still loved, but as for your old iPhone6, you don’t know where it is, and even if you did it’s probably unusable. Devices like the iPhone6 can’t be repaired, they are designed to fail in ways that are inscrutable.
Hundred Rabbits , Weathering Software Winter
These sound like different notes in the same chord to me. I want computers, and computing, to be personal again.
Iāve working on adding some physical controls to my kitchen status display. The setup is very simple, and for a first-run all I wanted to be able to do was detect a button press, and run a script somewhere on the system.
I couldnāt find any existing code that does this (please point some out if you know of any), though thereās plenty of code out there for button handling in general.
Also, most of the code out there for doing GPIO work is either in C or Python, and I was hoping for a Ruby solution, or at least a solution that would be easy to wrap in Ruby.
In the end I learned about how to interface with the GPIO system on RPi via the filesystem.
From there, I found this code from Aaron Patterson using epoll
to monitor for changes in the level on the monitored pin. That seemed like it would work, but the epoll gem seems to be unmaintained at this point. Instead, I went with the Sleepy Penguin gem, which provides an interface to the same underlying Linux filesystem events.
Lastly, I wanted my pin pulled high by default, and thereās no way to do that via Sysfs, so I ended up using the gpio
utility to set the pin state and pull up resistor.
From there, I was able to run this little script, which will output the current state of the pin when it changes.
# install gpio command line tool
# gpio -g mode 16 up
require 'sleepy_penguin'
def watch pin, on:
puts "Setup Export"
File.binwrite "/sys/class/gpio/export", pin.to_s
puts "Setup Edge"
retries = 0
begin
File.binwrite "/sys/class/gpio/gpio#{pin}/edge", on
rescue
raise if retries > 3
sleep 0.1
retries += 1
retry
end
puts "Read Value"
fd = File.open "/sys/class/gpio/gpio#{pin}/value", 'r'
yield fd.read.chomp
puts "Setup epoll"
epoll = SleepyPenguin::Epoll.new
epoll.add fd, SleepyPenguin::Epoll::PRI
puts "Start loop wait"
loop do
fd.seek 0, IO::SEEK_SET
epoll.wait do
# yield fd.read.chomp
value = fd.read.chomp
p value
end
end
ensure
File.binwrite "/sys/class/gpio/unexport", pin.to_s
end
pin = 16
watch pin, on: 'both' do |value|
p value
end
Still to come: debouncing, better handling of a change event, and hopefully wrapping it all up into something much easier to work with.
For a long while now Iāve had a weather/calendar/status display on the wall in my kitchen. Powered by a Raspberry Pi, it updates every few minutes. Recently I started thinking about extending the interface, adding a few buttons to choose which āpageā might be active at any given time.
My hope was that I would be able to do a quick update to the display while the button āselectionā UI was being interacted with. The term for this in the eInk/ePaper world is āpartial update.ā
After spending a lot of time researching and experimenting, I havenāt yet been successful, though I learned a lot in the process. At this point I need to pause my project, but I thought it might be worthwhile to jot down my notes thus far, in case they might be helpful to anyone else trying to do the same sort of thing.
Last Updated January 2023
I have a 7.5ā ePaper display (Black/White, 800x480) and board from Waveshare. The Spec Doc (PDF) is available on their site.
Most of the displays that Waveshare sells seem to be manufactured by Good Displays, then Waveshare builds some boards and code, and sells/distributes.
Waveshare provides demo code and documentation for this display (and their other displays) on wiki on their website.
My status display uses some Ruby libraries to generate a BMP image, which is then transferred as-is to the display every few minutes.
This video by Applied Sciences on YouTube is a great place to start in understanding how these displays work, and how they can be manipulated.
The fundamental principle to understand is that the display uses pulses of AC power to create a charge differential that pulls the white/black capsules to different sides of the silos they float in. The pulses are necessary because applying a constant DC voltage would induce a charge in the structure of the display itself, and further refreshes would not be possible anymore. So these waveforms must be effective both in moving the ink capsules, as well as avoiding unnecessary charge inducement. To some extend these waveforms are a āsecret sauceā of good display drivers (and, from what I can tell at least, a good part of the reason that Kindle displays seem so far ahead of the rest of the eInk world ā theyāre using complicated, probably very high frequency updates, maybe driven by hardware of a higher complexity than these other hobbyist boards; Iād love to know more).
Most of these displays can be manipulated in such a way that you can update only a subsection of the display, at a higher rate than is possible when refreshing all the pixels at once. (See Waveshare sample code for some examples on some of their smaller displays).
When a screen refresh is performed, the display executes a series of AC pulses based on stored waveform data. The waveforms vary depending on the pixel transition. White -> White, White -> Black, Black -> White, etc. can all have different waveforms in use.
The Waveshare boards support overriding the waveforms with custom LookUp Tables (LUTs). The format is complicated, but you can find documentation in their spec docs; the Applied Sciences video is another good reference for these.
ZinggJM has some custom code supporting many, many panels; many of these have custom LUTs for doing fast/partial updates. Itās worth digging into those for examples of how LUTs work; or, if youāre satisfied, just use his code to drive your display(s).
This huge thread in the Arduino forums has a ton of little gems and tidbits about using these displays.
This is another fast-update project with code that might be helpful.
This is the code that Ben Krasnow (Applied Sciences) shared in his video.
Source: Katie Mansfield / @ tragicgirlsco.
I’m a sucker for stuff like this.
Currently reading: Breaking Bread with the Dead by Alan Jacobs š