# Jonatan Miarecki > Welcome to my personal website where I write about my projects and other things. ## Bose Killed Your SoundTouch. Here's How to Fix It _You didn't break it. Bose did. Here's the fix — and why you shouldn't have to do this._ --- I have a SoundTouch 20. Solid hardware, years of daily use, and as of may 6th the preset buttons no longer work. This post explains what actually broke and why, then walks through how to bring the speaker back using [AfterTouch](https://github.com/gesellix/Bose-SoundTouch), a free open-source toolkit that replaces everything Bose's servers used to handle. No cloud, no Bose account, no app required. Tested on the SoundTouch 20; the process is the same or very similar across all SoundTouch models: 10, 30, Portable, and the home theater systems. ## The Architecture Problem Each of the six preset buttons on the device doesn't store a link to what it's supposed to play. Pressing one sends a request to Bose's servers asking what to stream. Without a server response, nothing plays. There was never a way to make it work locally. Bose knew this when they shipped the product and never disclosed it. For over a decade they sold a "press a button and listen" device with a hidden server dependency that customers had no way of knowing about. The [Consumer Rights Wiki](https://consumerrights.wiki) — which tracks anti-consumer practices in consumer tech — documented this as a clear example of undisclosed cloud dependency leading to functional loss of purchased hardware. In October 2025, Bose announced the servers would go dark. Under pressure from customers, they extended the deadline from February 18 to May 6, 2026. They also published the [SoundTouch Web API documentation](https://assets.bosecreative.com/m/496577402d128874/original/SoundTouch-Web-API.pdf) — though the community had largely documented this local device interface already, and Bose's release appears to have changed little beyond the version number. More to the point, it covers the port 8090 device API, not the cloud-side endpoints the preset buttons actually depend on. Those Bose never documented. The community had to [reverse-engineer them](https://www.gesellix.net/posts/aftertouch-bose-soundtouch/). Bose's official workaround is to save your stations as favourites inside individual music apps and stream from there. That's not really a replacement for preset buttons — it requires having your phone out, opening the right app, and navigating to the right place every time. ## What Still Works | Feature | Status | | -------------------------------- | -------------------- | | Bluetooth playback | ✅ Works | | AUX input | ✅ Works | | AirPlay / Spotify Connect / UPnP | ✅ Works | | Preset buttons (1–6) | ❌ No longer working | | TuneIn / Pandora / iHeartRadio | ❌ No longer working | | SoundTouch app music browsing | ❌ No longer working | You can still play audio, you just need your phone every time. The physical buttons, the thing that let you use the speaker without a phone, no longer work. ## The Fix: AfterTouch [AfterTouch](https://github.com/gesellix/Bose-SoundTouch) is an open-source toolkit by developer [Tobias Gesellchen](https://www.gesellix.net/posts/aftertouch-bose-soundtouch/) that emulates Bose's cloud services on your local network. Once your speaker is pointed at AfterTouch instead of Bose's servers, the preset buttons work again — along with TuneIn lookups and the internal account and device management the speaker expects. It ships as a single binary with no runtime to install, and the steps below only need a basic level of comfort with a terminal. AfterTouch needs to run on a machine that stays on. A Raspberry Pi, a NAS, or any always-on home server works. It doesn't require a lot of resources as it's mostly just serving a link to where the Speaker should play the music from. There are plans to eventually run AfterTouch directly on the SoundTouch hardware itself, which would make the whole setup self-contained, but that's out of scope for this post. AfterTouch builds on [SoundCork](https://github.com/deborahgu/soundcork), the Python-based server originally written by Deborah Gu that first cracked the Bose cloud protocol. AfterTouch extends it with a web UI, automatic device discovery, Docker support, and a migration wizard. Full documentation is at [gesellix.github.io/Bose-SoundTouch](https://gesellix.github.io/Bose-SoundTouch/). This guide will show you how to set up AfterTouch, migrate your speaker, and program the preset buttons with your own stations. **What you need:** - A Raspberry Pi, NAS, or any computer that stays on at home - Docker installed on that machine - Your SoundTouch speaker and home network ### Step 1: Run AfterTouch The easiest method is Docker. On your always-on machine: ```sh docker run -d \ --name soundtouch-service \ --network host \ --restart unless-stopped \ -v $(pwd)/AfterTouch-Data:/app/data \ ghcr.io/gesellix/bose-soundtouch:latest ``` > **Linux:** `--network host` lets AfterTouch discover your speaker automatically via multicast. On macOS or Windows, use `-p 8000:8000 -p 8443:8443` instead and add your speaker's IP manually in the UI. Or if you prefer Docker Compose: ```yaml services: soundtouch-service: image: ghcr.io/gesellix/bose-soundtouch:latest container_name: soundtouch-service network_mode: host volumes: - ./AfterTouch-Data:/app/data restart: unless-stopped ``` Once running, open `http://:8000` in a browser. AfterTouch will start scanning for SoundTouch devices on your network. Bluetooth and AUX playback work regardless of whether AfterTouch is running — they don't touch the network at all. {{< figure src="AfterTouch-page.jpg" alt="Screenshot of the AfterTouch web interface displaying a list of discovered Bose SoundTouch devices on the local network" caption="AfterTouch web UI showing discovered devices" >}} ### Step 2: Migrate Your Speaker Your speaker will appear in the Devices tab. Click **Migrate**. AfterTouch picks the best method for your model automatically. For most SoundTouch devices, including the SoundTouch 20, it uses the **telnet method**: the speaker has an internal diagnostic port (port 17000) that allows repointing the server URLs without opening the device or enabling SSH. There's also a USB SSH method for some models, but telnet works without touching the hardware at all. On the SoundTouch 20, I couldn't get SSH working anyway. AfterTouch will connect to the diagnostic port, repoint all server URLs to your local instance, and reboot the speaker. After rebooting, the speaker checks in with your server instead of Bose's. The preset buttons will respond, but the slots are empty after migration — you need to program them. The [AfterTouch migration guide](https://gesellix.github.io/Bose-SoundTouch/guides/MIGRATION-GUIDE.html) covers every model and edge case if you run into anything. {{< figure src="AfterTouch-migrate.jpg" alt="Screenshot of the AfterTouch device migration screen showing a successful migration for a SoundTouch 20" caption="AfterTouch migration success screen" >}} The speakers will not receive firmware or security updates going forward. Bose recommends keeping them on a private, firewalled network, which is reasonable advice regardless. If you're setting up a speaker that's been factory reset or has never been connected to Wi-Fi, you don't need the SoundTouch app for that part. The speaker broadcasts its own access point during setup; connecting to it brings up a webpage where you can enter your Wi-Fi credentials directly. #### How It Actually Works Your SoundTouch speaker has a configuration file listing the server URLs it calls for different functions — TuneIn lookups, account management (internally called "Marge"), software updates ("BMX"), and so on. Out of the factory they all point at `*.bose.com`. Migration rewrites those URLs to point at your AfterTouch instance. From that point on, when you press preset button 1, the speaker asks your server what to play. AfterTouch looks up what you configured for slot 1 and tells the speaker to stream it. The speaker fetches the audio directly from the radio station. Bose is out of the picture entirely. The only thing leaving your home network is the audio stream itself, going straight to the station's servers — the same as it always did. ### Step 3: Find Your Stream URLs After migration the preset slots are empty. You assign each button a stream URL. This is the genuinely liberating part: you're no longer limited to whatever Bose's curated service list included. Any publicly accessible audio stream works. **Option A: Direct stream URLs (recommended)** Most radio stations publish a raw stream URL on their own website — look for "Listen live" or "Stream", often buried in the footer — or via [radio-browser.info](https://www.radio-browser.info), a community-maintained directory covering tens of thousands of stations worldwide. Stream URLs usually end in `.mp3`, `.aac`, or `/stream`. These are the most durable option because nothing sits between you and the station. If the station keeps broadcasting, the URL keeps working. No Bose, no TuneIn, nothing in between. **Option B: TuneIn station IDs** AfterTouch includes a TuneIn emulation layer. In my testing both direct stream URLs and TuneIn station IDs worked reliably. To use a TuneIn station, pull the ID out of the station's URL: ``` https://tunein.com/radio/Example-FM-s112738/ ``` The `s112738` at the end is the station ID. Pass it with `--source TUNEIN` as shown in Step 4. That said, TuneIn is itself a service with its own longevity risks, so use direct stream URLs where you can find them. ### Step 4: Program the Preset Buttons AfterTouch ships with `soundtouch-cli` for local speaker control. You'll need [Go installed](https://go.dev/dl/) to get it, or grab a pre-built binary directly from the [releases page](https://github.com/gesellix/Bose-SoundTouch/releases) for Linux, macOS, or Windows. **Install with Go:** ```sh go install github.com/gesellix/bose-soundtouch/cmd/soundtouch-cli@latest ``` Find your speaker's IP in the AfterTouch web UI or your router's device list, then: **Discover your device:** ```sh soundtouch-cli discover devices ``` **Program a preset — direct stream URL:** ```sh soundtouch-cli --host 192.168.1.50 preset store \ --slot 1 \ --source LOCAL_INTERNET_RADIO \ --location "http://stream.example.com/live.mp3" \ --name "Example Radio" ``` **Program a preset — TuneIn station ID:** ```sh soundtouch-cli --host 192.168.1.50 preset store \ --slot 2 \ --source TUNEIN \ --location "/v1/playback/station/s112738" \ --name "Example FM" ``` **Verify everything saved:** ```sh soundtouch-cli --host 192.168.1.50 preset list ``` Press button 1 on the physical speaker. It should start playing within a few seconds. The full CLI reference — multiroom zones, scripting, home automation hooks — is at [gesellix.github.io/Bose-SoundTouch](https://gesellix.github.io/Bose-SoundTouch/). ## Home Assistant and Smart Home If you already have SoundTouch in Home Assistant and were using the UPnP integration, it should continue working without any changes. The UPnP was working locally the same as before. ## Other Options AfterTouch isn't the only project that came out of this. [ÜberBöse](https://github.com/julius-d/ueberboese-api) — German for "supremely evil", which is apt — offers native Spotify OAuth support and has an [Android app on F-Droid](https://f-droid.org/packages/io.github.juliusd.ueberboese.app/). Multiple working replacements existed before Bose flipped the switch. The community was ahead of the deadline. ## The Bigger Pattern The hardware works. The firmware works. What failed was an undisclosed, deliberate dependency on a remote server for something as basic as recalling a preset — a dependency that was never given a local fallback, never disclosed to buyers, and eventually terminated with a few months' notice. The right-to-repair conversation has traditionally focused on physical repairability: the right to open a device, replace a part, source components. But the same principle applies to software. If a device is functional hardware running functional firmware, consumers should have a meaningful right to keep using it even after the manufacturer decides the server costs aren't worth maintaining. What Bose did here — architect in a silent cloud dependency, sell the product for a decade, then kill the servers — is the software equivalent of building a car with a component that stops working the moment the dealer closes. The community fixed this one. A handful of developers reverse-engineered the cloud protocol in their own time and built working replacements before the deadline. That's a good outcome. It shouldn't have been necessary. If you want to follow more cases like this, [Consumer Rights Wiki](https://consumerrights.wiki) tracks this pattern across the industry — cloud-dependent hardware, planned obsolescence, and the companies behind it. ## About me Hi, I'm **Jonatan Miarecki**, a software engineer and AI researcher. I build things until they run, then figure out how to make them run better. Based in the EU and open to collaborating with anyone building something interesting. ## How I got here It started with Snap Circuits and Lego Mindstorms EV3, and the pattern has stayed consistent ever since: I want to see the thing work. Not in a simulator, not in theory, but actually running and doing something real. During secondary school I worked through Harvard's CS50x, and the German Physical Society awarded me the DPG-Abiturpreis in July 2025 for my physics results. Both helped, but honestly most of what I know came from breaking things and figuring out why. At some point I built a fully functional [8-bit CPU in Logisim](https://github.com/JonatanMGit/8-bit-cpu) from scratch: microcoded Harvard architecture, custom Python assembler. It started as an experiment and ended up teaching me more about memory management than most formal resources would have. ## What I work on My core languages are TypeScript, Python, C++, Rust, and C. I run Arch Linux (yes, I mention it) as my daily driver. For running things, I maintain a local cluster of Raspberry Pis and various devices on my home network, powered by solar panels. Everything runs in Docker containers, so when something breaks I can usually trace it, learn from it, and have it back up faster than a cloud provider would even acknowledge the ticket. No cloud lock-in, no subscription, full control over the data. I'm currently working on making parts of this infrastructure more autonomous, with self-managing services and automatic recovery. The ESP32 is still my favorite platform for anything that needs to interact with the physical world. Cheap, capable, and when something goes wrong you can experiment more! A lot of what I build starts because I run into an undocumented device, a missing driver, or a protocol nobody has bothered to tackle yet. That tends to be more interesting than having a spec to follow. I also maintain [wkd-checker](https://www.npmjs.com/package/wkd-checker), an npm package that verifies Web Key Directory endpoints against the IETF specification. It came out of building my own WKD setup and realising there was no easy way to validate it. ## Studies and research I started university early through the [Studieren ab 15](https://www.uni-bielefeld.de/einrichtungen/zll/junge-uni/studieren-ab-15/) program at Bielefeld University in October 2023, completing four semesters of computer science while still in secondary school. I'm currently pursuing a Bachelor's in Artificial Intelligence and Cognitive Informatics. My research focuses on how models of human cognition can inform the design of intelligent systems, specifically the gap between what AI can do in theory and how it behaves under real-time, constrained conditions. During the 2025 Bundeswettbewerb Informatik workshops at TU Dortmund, my team built autonomous agents for a Robocode tournament from scratch, no pre-built strategies. Watching something you wrote make decisions in real time, under pressure, is a different kind of feedback than unit tests. I also enjoy hackathons and programming competitions for the same reason: a hard deadline and an unfamiliar problem space tend to produce more interesting solutions than a comfortable sprint. ## Radio, signals, and community I'm a licensed amateur radio operator under the callsign **DN9AJ** (Class N, DARC DOK N43), currently studying for the CEPT license, and the youngest member of my local club. What draws me to amateur radio is the same thing that draws me to open-source software: the culture is genuinely open. Frequencies are unencrypted by rule, knowledge gets shared freely, and the infrastructure exists to serve people rather than extract value from them. In emergencies, amateur radio networks run independently of commercial infrastructure, and that independence is the whole point. On the technical side, I decoded SSTV image transmissions from the International Space Station and received a physical postcard from the crew back. That project turned into an open-source [SSTV encoder/decoder](https://github.com/JonatanMGit/sstv-js) and a browser-based [WebSDR frontend](https://github.com/JonatanMGit/websdr) with no server backend required. I also hold an A1/A3 drone operator license. For prototyping I use a Prusa i3 MK3S, with models made in OpenSCAD, Shapr3D, or Solid Edge depending on what I'm building. ## Not only computer languages I'm fluent in English, German, and Polish, a bit of French, and currently picking up Italian. Not only do I speak computer languages, but apparently several human ones too, though the compiler errors in Italian are considerably harder to interpret. Outside of screens: I swim regularly and hold the Deutsches Rettungsschwimmabzeichen Silber, recognized internationally as an ILS Lifesaver. Long-distance running and skiing when I get the chance (🇵🇱🇨🇭). ## Get in touch I'm open to collaboration on software engineering, applied research, or open-source infrastructure. Find my code on [GitHub](https://github.com/JonatanMGit) or my academic record on [ORCID](https://orcid.org/0009-0001-1771-4160). Reach me at jonatan@miarecki.eu or via Matrix at @jonatan:miarecki.eu. I prefer encrypted communication. My [S/MIME public key](/jonatan.crt) and [PGP public key](/jonatan.asc) are both available. The PGP key is auto-discoverable via my self-hosted WKD endpoint. If you want to understand how that works, I wrote a post on [Web Key Directory setup](/posts/web-key-directory-setup/). ### Identifiers - ORCID iD: [0009-0001-1771-4160](https://orcid.org/0009-0001-1771-4160) - GitHub: [JonatanMGit](https://github.com/JonatanMGit) - LinkedIn: [jonatan-miarecki](https://www.linkedin.com/in/jonatan-miarecki) - YouTube: [@Jonatan_M](https://www.youtube.com/@Jonatan_M) - ISNI: [0000000529684255](https://isni.org/isni/0000000529684255) - arXiv: [0009-0001-1771-4160](https://arxiv.org/a/0009-0001-1771-4160.html) - Google Scholar: [L85c0P0AAAAJ](https://scholar.google.com/citations?user=L85c0P0AAAAJ) - ResearchGate: [Jonatan-Miarecki](https://www.researchgate.net/profile/Jonatan-Miarecki) - Amateur radio callsign: DN9AJ [QRZCQ](https://www.qrzcq.com/call/DN9AJ) [QRZ](https://www.qrz.com/db/DN9AJ) - Google Knowledge Graph: [/g/11yzb1tsnz](https://www.google.com/search?kgmid=/g/11yzb1tsnz) ## Archives ## Legal / Impressum **Contents** [Impressum](#impressum) · [Privacy Policy](#privacy) · [Terms of Use](#terms) In summary this is a static website served via Cloudflare. Last updated April 2026. --- ## Impressum {#impressum} ``` Jonatan Miarecki c/o Online-Impressum #7707 Europaring 90 53757 Sankt Augustin Germany impressum@miarecki.eu +49 15678 306105 ``` **Responsible for editorial content (§ 18 para. 2 MStV):** Jonatan Miarecki, address as above. > This ladungsfähige address exists solely to satisfy German Impressum law - in keeping with the privacy-conscious nature of this blog. Please **do not send private letters, parcels, QSL cards, or other private content**. If you'd like to send me something personally, email me first and I'll give you the right details. Wir sind zur Teilnahme an einem Streitbeilegungsverfahren vor einer Verbraucherschlichtungsstelle weder verpflichtet noch bereit. --- ## Privacy Policy {#privacy} ### Controller Jonatan Miarecki - contact and address as above. JavaScript is not required for core content; optional features (search, theme switcher) may use it. ### Hosting - Cloudflare Static files are served via **Cloudflare, Inc.** (101 Townsend St, San Francisco, CA 94107, USA). **Legal basis:** Art. 6(1)(f) GDPR - legitimate interest in secure, functional delivery. **Third-country transfers:** Cloudflare operates under the EU–US Data Privacy Framework and Standard Contractual Clauses (Art. 46 GDPR), where applicable. → [Cloudflare Privacy Policy](https://www.cloudflare.com/privacypolicy/) When you access this website, technical data such as IP address, browser type, operating system, referrer URL, and timestamp may be processed. Cloudflare acts as a data processor pursuant to Art. 28 GDPR on the basis of a Data Processing Agreement. ### Cookies No tracking or advertising cookies are used. Cloudflare may set strictly necessary security cookies (e.g. `__cf_bm`) for bot/DDoS protection - consent not required under § 25 para. 2 no. 2 TDDDG. → [Cloudflare Cookie Policy](https://www.cloudflare.com/cookie-policy/) ### Interactive Tools & Forms Some tools on this site accept user input to perform a function you explicitly request. Input is sent to a Cloudflare Worker, used only to carry out that operation. **Legal basis:** Art. 6(1)(b) GDPR - strictly necessary to perform the service you requested. ### Contact Jonatan Miarecki Email: impressum@miarecki.eu Phone: +49 15678 306105 ### Your Rights Access (Art. 15) · Rectification (Art. 16) · Erasure (Art. 17) · Restriction (Art. 18) · Portability (Art. 20) · Object to legitimate-interest processing (Art. 21) · Withdraw consent at any time (Art. 7(3)). Contact impressum@miarecki.eu - I'll respond within one month (Art. 12(3) GDPR). For data processed by Cloudflare, you may also contact Cloudflare directly. You may also lodge a complaint with a supervisory authority, in particular the Landesbeauftragte für Datenschutz und Informationsfreiheit Nordrhein-Westfalen (LDI NRW). All connections are HTTPS-encrypted. --- ## Terms of Use {#terms} ### Content Licence - CC BY 4.0 Unless stated otherwise, all original written content on miarecki.eu is published under **[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)**. You may share and adapt it for any purpose, including commercially, if you credit **Jonatan Miarecki**, link to the original post, link to the licence, and indicate changes. > **Suggested attribution:** "[Post Title]" by Jonatan Miarecki (miarecki.eu) - [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) **Code is excluded.** Scripts, libraries, and software projects linked or embedded on this site are governed by their own licences (e.g. MIT, AGPL-3.0) - check the relevant repository. Due to the open nature of CC BY 4.0, content may be mirrored or indexed by third-party platforms - IPFS nodes, web archives, search aggregators, and similar services. I have no control over how those platforms display or present this content and am not responsible for their rendering, accuracy, or data practices. If you want to reuse code from this site, please check the specific licence in the relevant repository and follow its terms. Use of the content for machine learning or AI training is permitted under the terms of the CC BY 4.0 licence. ### No Warranty - Content, Code & Projects All content, tutorials, schematics, code snippets, and project write-ups are personal learning notes and experiments, provided **as is with no warranty of any kind** - express or implied - including accuracy, safety, completeness, or fitness for a particular purpose. They must be independently verified before any real-world, production, or safety-critical use. To the fullest extent permitted by applicable law, I accept no liability for damage, data loss, hardware failure, electrical hazards, safety incidents, or any other harm arising from following instructions or replicating projects on this site. The reader bears full responsibility for compliance with applicable safety codes, regulations, and their own technical competence. Nothing here constitutes professional, legal, medical, financial, or engineering advice. This limitation of liability does not apply in cases of intent or gross negligence or where liability is mandatory under applicable law. ### Sponsored or Affiliate Links Where a post or page contains sponsored content or affiliate links, this will be clearly labelled as **Advertisement** or **Sponsored**. I do not accept payment to disguise advertising as editorial content. ### External Links Links to third-party sites are for reference only. I inspected linked pages for obvious violations at the time of linking but do not continuously monitor them and accept no responsibility for their content. Any link found to be problematic will be removed promptly upon notification. ### Availability & Changes Continuous availability is not guaranteed. This document may be updated at any time; the date above reflects the current version. ### Applicable Law Governed by the laws of the **Federal Republic of Germany**, without prejudice to mandatory EU consumer protection provisions in your member state. --- *impressum@miarecki.eu* ## Site-Wide Search ## Receiving Images From the International Space Station Have you ever wanted to receive images directly from space? Recently, I found out that the International Space Station (ISS) occasionally transmits images down to Earth using radio waves, and with a surprisingly simple setup, you can receive them at home. I thought that was pretty cool, so I gave it a try. At the time of writing, the last ARISS SSTV event took place approximately a week ago. Here’s how I managed to receive images from the ISS and how you can do it too. The ISS doesn’t constantly send these images, so you’ll need to check the [ARISS SSTV event page](https://www.ariss.org/upcoming-sstv-events.html) for future transmissions. ## What Is SSTV? **SSTV (Slow Scan Television)** is a way to transmit images using audio over radio frequencies. The ISS uses a mode called **PD-120**, which transmits one image in about 126 seconds. The transmissions are usually sent on **145.800 MHz FM Wide** in the 2-meter amateur radio band. Between images, there's typically a 2-minute pause, so if you hear silence after receiving one image, that’s normal. The end result is a 640px x 496px image. ## My Setup ### Baofeng UV-5R The easiest way to receive SSTV images is to use a cheap handheld radio like the Baofeng UV-5R. I used this with an upgraded antenna - the Nagoya NA-771, which is tuned for 144 MHz (close enough to 145.800 MHz). This made a big difference in signal quality, especially when the ISS was low on the horizon. To set the frequency, you can use a tool like **Chirp** to program the radio. Set it to 145.800 MHz. By setting Duplex to Off, you disable transmitting anything accidentally. It would be beneficial to disable Squelch on the radio. You can do this by setting the squelch level to 0 (the lowest setting). This way, you can hear the beeps even when the signal is weak. A noisy signal is better than no signal at all. To record the audio, you can simply hold your phone up to the speaker and capture the beeping sound. But for better quality, I connected the Baofeng to my laptop using a 3.5mm AUX cable (Just make sure you use a 4-Pin cable, so that you can actually get the microphone input). This avoids speaker noise (like crackling on noisy signals) and gives you a cleaner signal to decode later. I recorded using Audacity. When you plug in an AUX cable, the Baofeng mutes its speaker. If you still want to hear what’s being received in real-time (for example, to check if it’s noisy), you can use a tool like **Helvum** (for Linux) or another audio patch software to route the mic input to your laptop speakers. Audacity also supports input monitoring, but it has a small delay. ### RTL-SDR I also tested an **RTL-SDR USB dongle** with a computer and software like **Gqrx**. While it worked, I had trouble getting a strong signal - probably because the antenna I used wasn’t tuned. The Baofeng gave better results overall. That said, the RTL-SDR does have one advantage: Gpredict can work with Gqrx to automatically adjust the tuning frequency for Doppler shift. I'm not sure this is absolutely necessary for SSTV, but it’s a cool feature. If you don't have any of these devices, you can look online for WebSDR receivers that provide this functionality online. ## Tracking the ISS You’ll need to know **when the ISS will be overhead** in your area. Some apps and tools I used for this: - **ISS Detector** (Android) - **Spot the Station** (official NASA app) - **Gpredict** (Linux) A typical ISS pass lasts about 10 minutes. When the ISS comes into range and if they are currently sending, you’ll hear a series of beeps and tones - that’s the SSTV signal. A PD-120 image takes a bit over 2 minutes to send. Depending on the timing and pass angle, you might receive one or even two images per pass. If you hear a lot of them over a week, you can even start to recognize each image by the sound they make. You may sometimes need to look in the App for settings to also show daytime passes as most are made for seeing the Station with your eyes, not for radio reception. During the pass, I kept my antenna pointed toward the ISS’s position using the app’s live tracking. If the signal started getting noisy, I adjusted the antenna’s orientation. If you hear a noise like this (SSTV Header), it means the SSTV transmission is starting: Try listening at different times of day to capture different slides. ## Decoding the Images Once you’ve recorded the audio, you can decode it into an image using SSTV software. These are the tools I used: - **Linux**: QSSTV - **Windows**: MMSSTV - **Android**: Robot36 Just keep the program open while recording or use them to decode the recording later. These programs usually auto-detect the PD-120 mode, but if not, you can select it manually. If you’re using **MMSSTV**, it needs the audio in a special `.mmv` format. You can convert your recording using `ffmpeg`: ```bash ffmpeg -i 'input.mp3' -ac 1 -ar 11025 -f s16le -c:a pcm_s16le -y "output.mmv" ``` Then in MMSSTV, go to **"File" → "Play Sound from the file..."** and load the `.mmv` file. I tested decoding using both phone microphone recordings and direct AUX recordings. The direct connection produced much better results: less background noise and clearer tones. If your image has green lines, try adjusting the slant setting in the software. ### Sharing Your Images Once you’ve decoded some images, you can share them with the community through the [ARISS SSTV Gallery](https://ariss-usa.org/ARISS_SSTV/). You can even receive a certificate of participation if you submit during an active event. It's a fun way to be part of a global amateur radio effort. ## Getting a QSL Card **Update:** I recently received a QSL card confirming my reception! If you want a physical memento of the event, you can request a **QSL card** — a written confirmation of a radio reception. I wanted to send my request directly (Direct) rather than through a bureau. To find out where to send your report, check [the ARISS QSL card page](https://www.ariss.org/qsl-cards.html) for your region. For Europe, the QSL manager is based in France. Typically, a direct international QSL request includes a self-addressed envelope (SAE) and either an International Reply Coupon (IRC) or "Green Stamps" (USD cash) to cover return postage. However, Deutsche Post no longer sells IRCs. Since I was sending to France, I found a workaround: I bought French stamps directly from the La Poste website, printed them out, and glued them onto my return envelope. I then placed the stamped return envelope inside the main envelope along with my reception report and sent it off. {{< figure src="iss_postcard.jpg" caption="The official QSL card I received. Top: The front of the card featuring the ISS and call signs. Bottom: The back of the card with the handwritten confirmation details." alt="A composite image showing both sides of an ARISS QSL card. The top half shows the front of the card: a photo of the International Space Station orbiting Earth against a blue ocean background, with the call signs NA1SS, RS0ISS, and OR4ISS in orange text. The bottom half shows the back of the card: it lists technical details about the station's modules and sponsors (Canada, Japan, Russia, USA, Europe). There is a handwritten table addressed to 'Jonatan Miarecki' (SWL) confirming the reception of SSTV signals on the 15th and 17th of July, 2025, at 145.800 MHz." >}} ## Image Gallery Here are some of the images I managed to receive during the July 2025 SSTV event. I included the sound files for each image so you can hear the SSTV tones that were transmitted. {{< figure src="ISS_20250717_215917.webp" alt="SSTV image from the ISS, Slide 1 of 12, celebrating the 40th anniversary of the STS-51F mission. The image displays two logos against a black, starry background. On the left is the circular Spacelab 2 mission patch showing the Space Shuttle over the Earth. On the right is the rectangular SAREX (Shuttle Amateur Radio Experiment) logo, also featuring the shuttle and Earth. Text below identifies them as the 'STS-51F Mission and SAREX Logos'." caption="Slide 1/12 - [Sound file](ISS_20250717_215917.mp3)" >}} {{< figure src="ISS_20250716_011150.webp" caption="Slide 2/12 - [Sound file](ISS_20250716_011150.mp3)" alt="SSTV image from the ISS, Slide 2 of 12. The image features the seven-member crew of the Space Shuttle Challenger mission, floating together in the microgravity environment of the Spacelab module. All the astronauts are wearing sunglasses and smiling for a group photo. The text at the bottom reads 'STS-51F Crew'" >}} {{< figure src="ISS_20250715_233553.webp" caption="Slide 3/12 - [Sound file](ISS_20250715_233553.mp3)" alt="SSTV image from the ISS, Slide 3 of 12 40th Anniversary. The image is a bust photot of astronaut Tony England, who is smiling and looking towards the camera. He is wearing a blue polo shirt with a mission patch on the chest. The background shows the interior of the shuttle. The text at the bottom identifies the image as 'SSTV Image of Tony England W0ORE'. The image has a slight blueish tint" >}} {{< figure src="ISS_20250719_002157.webp" caption="Slide 9/12 - [Sound file](ISS_20250719_002157.mp3)" alt="SSTV image from the ISS, Slide 9 of 12, celebrating the 50th anniversary of the Apollo-Soyuz mission. The image is a formal group portrait of the American astronauts and Soviet cosmonauts. The crew members are posed together in front of the American and Soviet flags, holding a model of the docked Apollo and Soyuz spacecraft. The text at the bottom reads 'Apollo Soyuz Crew'" >}} {{< figure src="ISS_20250718_224608.webp" caption="Slide 10/12" alt="SSTV image from the ISS, Slide 10 of 12, celebrating the 50th anniversary of the Apollo-Soyuz mission. The image is a side-by-side view of the two rocket launches. On the left, the Soyuz rocket is shown lifting off from its launchpad. On the right, the Apollo Saturn V rocket is shown on its launch tower. The caption below reads 'Soyuz (R) and Apollo (L) Launches'." >}} {{< figure src="ISS_20250718_225030.webp" caption="Slide 11/12" alt="SSTV image from the ISS, Slide 11 of 12, for the Apollo-Soyuz 50th Anniversary. The image shows an artist's depiction of the Apollo and Soyuz spacecraft docked together in orbit above the Earth. Below the spacecraft are portraits of the five crew members: astronauts Thomas Stafford, Vance Brand, and Deke Slayton, and cosmonauts Alexei Leonov and Valeri Kubasov. The text at the bottom reads 'Apollo Soyuz Artist Depiction'" >}} ## Web Key Directory Checker This tool verifies Web Key Directory (WKD) configuration for email addresses, checking both direct and advanced discovery methods. It validates policy files, CORS headers, key availability, and proper key association with the email address. At least one Method is required to be set up for the WKD to work. More Information on [how to set up WKD]({{< ref "/posts/WKD-setup/index.md" >}})

Direct Method Unknown

Key Location: Unknown
Key Available: Unknown
Key CORS Valid: Unknown
Key Type: Unknown
Fingerprint: Unknown
Email in Key: Unknown
Policy Available: Unknown
Policy Configuration Unknown
The WKD specification requires a policy file to be present (even if empty) to check for WKD support and advanced configuration properties.
Policy Location: Unknown
Policy CORS Valid: Unknown
Policy Compliant: Unknown

Advanced Method Unknown

Key Location: Unknown
Key Available: Unknown
Key CORS Valid: Unknown
Key Type: Unknown
Fingerprint: Unknown
Email in Key: Unknown
Policy Available: Unknown
Policy Configuration Unknown
The WKD specification requires a policy file to be present (even if empty) to check for WKD support and advanced configuration properties.
Policy Location: Unknown
Policy CORS Valid: Unknown
Policy Compliant: Unknown

Overall Status Unknown

Valid: Unknown
## NPM Library This tool is powered by the [wkd-checker](https://www.npmjs.com/package/wkd-checker) npm library. You can use it in your own projects or run it via CLI. The JSON output below is identical to the library output. ### CLI Usage ```bash npx wkd-checker test@example.com ``` ### Library Usage ```javascript const wkd = require('wkd-checker'); const email = 'test@example.com'; wkd.checkKey(email) .then(result => { console.log('WKD Result:', result); console.log('Advanced:', result.advanced.valid); console.log('Direct:', result.direct.valid); }) wkd.getKey(email) .then(key => { console.log('Retrieved Key:\n', key); }) .catch(err => { console.error('Error retrieving key:', err); }); ```

API Documentation

**Endpoint**: `POST https://miarecki.eu/api/wkd` **Method**: `POST` with `Content-Type`: `application/json` or `application/x-www-form-urlencoded` **Request Body**: - JSON Format: ```json { "email": "user@example.com" } ``` - x-www-form-urlencoded Format: ``` email=user@example.com ``` **Response**: - JSON Object with `advanced` and `direct` properties, each containing a `KeyCheckResult` object. - Example: ```json { "advanced": { "policy_location": "https://openpgpkey.miarecki.eu/.well-known/openpgpkey/miarecki.eu/policy", "policyAvailable": false, "policyCorsValid": false, "policy": null, "key_location": "https://openpgpkey.miarecki.eu/.well-known/openpgpkey/miarecki.eu/hu/u5u31zhdn1tyua7kdr4xmbd7k3h733b7?l=jonatan", "key_available": false, "keyCorsValid": false, "keyType": "Invalid", "keyTypeValid": false, "fingerprint": null, "emailInKey": false, "expired": false, "revoked": false, "policyCompliant": true, "valid": false }, "direct": { "policy_location": "https://miarecki.eu/.well-known/openpgpkey/policy", "policyAvailable": true, "policyCorsValid": true, "policy": { "mailboxOnly": false, "daneOnly": false, "authSubmit": false, "protocolVersion": null, "submissionAddress": null, "others": [] }, "key_location": "https://miarecki.eu/.well-known/openpgpkey/hu/u5u31zhdn1tyua7kdr4xmbd7k3h733b7?l=jonatan", "key_available": true, "keyCorsValid": true, "keyType": "BinaryKey", "keyTypeValid": true, "fingerprint": "18EECCF319422F31D717796880B1C14A34B7634A", "emailInKey": true, "expired": false, "revoked": false, "policyCompliant": true, "valid": true } } ``` ## Setting up Web Key Directory Getting a PGP Key is easy, but sharing it with others can be a hassle. ## Why use Web Key Directory Sharing your public key is important to secure your communication as it allows others to encrypt messages that only you with the corresponding private key can decrypt and to verify that messages are from you. This is especially important for E-Mail, as it is not encrypted by default and can be intercepted and read by the entity handling the E-Mail. However this requires the recipient to have your public key, which needs a way to be shared. ### Traditional ways to share your public key The traditional way to share your public key is to upload it to a keyserver, but this method has its drawbacks. Anyone can upload a key to a keyserver, and there is no way to verify that the key actually belongs to the person it claims to belong to. Another option would be to download the key from the person's website, but it would be much harder to find the key in the first place as everyone's site would be different and still requires manual work to get the key. Even sending the Key via E-Mail isn't great, as the first E-Mail would be unencrypted and the key could be intercepted and replaced with a malicious one and still require manual work to import the key. ### The solution This is where Web Key Directory comes in. WKD is a protocol that enables the discovery of OpenPGP public keys uploaded to people's own servers, bypassing the need for dedicated keyservers and allowing greater control over the keys. While using HTTPs to get the key, you can be a little more sure that the key used for the email address has been distributed by the owner of the domain, which might be the same person. WKD allows E-Mail clients, like Thunderbird, to automatically discover the public key of the recipient and directly use it on the first conversation. ## Setting up Web Key Directory WKD has two setups: the Direct setup and the Advanced setup. Despite their names, both require roughly the same steps. The Direct setup requires no additional DNS entries, while the Advanced setup requires a sub-domain with the fixed name `openpgpkey` to be created, which will be tested first before falling back to the Direct setup. ### Requirements 1. A domain: The domain is required to host the public key as otherwise you wouldn't be able to use WKD. For the basic setup, you just need to have the ability to place files in the `.well-known` directory of your domain. For the advanced setup, you need to be able to create a subdomain called `openpgpkey` and place files in the `.well-known` directory of that subdomain. 2. A public key that matches the email address host on the domain 3. A web server: The web server is required to host the public key. If you don't have web hosting or can't control the web server, you can use [Openpgp.org's WKD-as-a-service](https://keys.openpgp.org/about/usage#wkd-as-a-service). This service allows you to host your public key on their servers by utilizing the advanced setup. This approach comes with the downside of not having full control over the key and it including all the available keys for that identity. ### Getting the hash The basic mode expects the Key at this location: `https://{domain}/.well-known/openpgpkey/hu/{hash}?l={email-name}` where {domain} is the domain of the email address, {hash} is the WKD hash of the email address and {email-name} is the name part of the email address before the @ using proper percent escaping. The advanced mode is similar but uses the openpgpkey subdomain and includes the domain in lowercase in the path, like so: `https://openpgpkey.{domain}/.well-known/openpgpkey/{domain}/hu/{hash}?l={email-name}` The hash is calculated by taking the local-part of the email address (the part before the @), converting all ASCII characters to lowercase, and hashing it using the SHA-1 algorithm. The resulting 160-bit digest is encoded using the [Z-Base-32](https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt) method to create a 32-octet string. This string is then used as the hash in the URL. However you do not need to do this by hand as the gpg command line tool can do this for you. ```bash # A specific key: gpg --with-wkd-hash --fingerprint john@example.com # All stored keys: gpg --list-keys --with-wkd-hash ``` Outputs: ```{hl_lines=[4]} pub ed25519 2024-03-16 [SCA] [expires: 2026-03-17] 82BB 5FCA 5F46 ED3F 04A2 9A66 1973 3425 922A A05E uid [ultimate] John Doe wwq7w9d96wfsd4zkytndq84kpkjod3eb@example.com sub cv25519 2024-03-16 [E] [expires: 2026-03-17] ``` The hash is before the @ in the email address, which in this case is `wwq7w9d96wfsd4zkytndq84kpkjod3eb`. Now that you have the hash, you need to save a binary unarmored version of the public key to the location of the hash, which you can do with the following command: ```bash gpg --no-armor --export john@example.com > wwq7w9d96wfsd4zkytndq84kpkjod3eb ``` Be careful on Windows as it does not use the redirect operator `>` correctly and the binary data gets messed up. Consider using Git Bash or WSL to prevent this. ### DNS If you plan on using the advanced setup, you need to create a subdomain called `openpgpkey` and have the web server serve the keys from there. In case you use the Direct method, you need to make sure the openpgpkey subdomain does not respond. For example when you use wildcard DNS records, make sure that the openpgpkey subdomain is not subject to the wildcarding. This can be done by inserting an empty TXT RR for this sub-domain, which will prevent the wildcard DNS records from influencing the openpgp DNS record, as the Advanced method is tried first before falling back to the Direct method. ### Uploading the key The key needs to be uploaded to the web server at the location of the hash appropriate for the chosen setup. It should be served as `application/octet-stream` and allow access from anywhere using the `Access-Control-Allow-Origin: *` header. Example configurations for nginx could look like this: ```nginx location ^~ /.well-known/openpgpkey { default_type application/octet-stream; add_header Access-Control-Allow-Origin * always; } ``` or for Cloudflare pages by creating a \_headers file in the output directory: ```yaml /.well-known/openpgpkey/* Content-Type: application/octet-stream Access-Control-Allow-Origin: * ``` ### Adding the Policy file The specification requires that a Policy Flags file is served. This file is required even if the Web Key Directory Update Protocol is not supported, which is a protocol that allows for the automatic update of the public key. But this is not necessary as the keys will be statically hosted and served. The Policy Flags file can just be an empty file. For the Direct setup, it needs to be served at `/.well-known/openpgpkey/policy`, and for the Advanced setup at `/.well-known/openpgpkey/{domain}/policy`. ## Testing the setup Testing the setup requires WKD to be already set up and publicly accessible. ### Local check You can test your setup by the following GnuPG command, which will try to fetch the key from the server: ```bash gpg --auto-key-locate clear,nodefault,wkd --locate-keys john@example.com ``` ```bash gpg: key 19733425922AA05E: public key "john@example.com" imported gpg: Total number processed: 1 gpg: imported: 1 pub ed25519 2024-03-17 [SC] [expires: 2026-03-17] 82BB5FCA5F46ED3F04A29A6619733425922AA05E uid john@example.com ``` For daily use, you can just use the `--locate-keys` in gpg to automatically fetch the key from the server or look for the appropriate option in your E-Mail client. ### Online check Alternatively, you can use the following form to check if the WKD setup is working. It is a replacement for the [Metacode WKD Checker](https://metacode.biz/openpgp/web-key-directory) as it will be sunsetted on 1.05.2024. This tool has the benefit of showing which parts of the setup are working and which are not and tests both the Direct and Advanced setup.
## Conclusion Setting up Web Key Directory is a great way to share your public key with others. It allows for automatic discovery of the public key for example in E-Mail clients, and allows for greater control over the key as it is hosted on your own server and allows communication without manual key exchange. It also allows you to remove old or revoked keys from the server, which is not possible with traditional key servers, which will keep the key forever, cluttering the keyserver with old keys. Sources: - [OpenPGP Web Key Directory Internet-Draft](https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service/) ## Modding an IKEA Iskärna to use Zigbee The [IKEA Iskärna lamp](https://www.ikea.com/us/en/p/iskaerna-led-table-lamp-multicolor-90510403/) is a stylish addition to any home, but its original design limits functionality to manual control via a single button. This modding project aims to enhance the lamp's capabilities by replacing its original control board with a custom one, enabling Zigbee control, including integration with Home Assistant. This allows for automated control, custom effects, and remote operation of the lamp. ## Required materials - IKEA Iskärna lamp - 24V LED controller (Zigbee or other) - Soldering iron - Wires - Screwdriver - Glue - Optional Button ## Disassembly The first step is to disassemble the lamp. The lamp is held by a single screw at the back, which can be removed using a screwdriver. Once the screw is removed, the lamp can be opened by pulling the top part from the bottom part. {{< figure src="original_board.webp" title="The internal control board. Left: facing the button, right: back of the board" alt="The internal control board of the IKEA Iskärna lamp">}} ## Replacing the control board Next, to replace the original control board with a custom one, the original board must be removed. Do this by unsoldering the wires from the original board and removing the board from the lamp, while remembering which wire goes where (+, -, and the LEDs). Note that the original board is wired as RGB+, but at least they labeled the individual cables with shapes so you can tell them apart. The custom board can then be soldered in place of the original board, with the wires connected to the appropriate pins. By keeping the original power supply, no modifications are needed to the power supply and you can just hook up the new board to the original power receptacle inside the lamp. For the button to still work, you need a fitting board. However, this is very hard to find, so I just attached a new button to the new board and wired it to the original button location. This way, the original button still works. This allows you to still control the light manually and pair it in case you use a zigbee module. ## Reassembly {{< figure src="iskaerna_reasembly.webp" title="IKEA Iskärna lamp before reassembly" alt="IKEA Iskärna lamp disassembled">}} If you added a custom button to the new board, you need to glue it to the sliding piece inside the lamp, which originally held the button. Then you can also glue the new board to the bottom of the lamp. Once the new board is in place, the lamp can be reassembled by putting the top part back on the bottom part and screwing it back together. ## Conclusion {{< figure src="modified_iskaerna.webp" title="Modified IKEA Iskärna lamp" alt="Modified IKEA Iskärna lamp glowing red in a room">}} Uppon pairing the new board with your zigbee network, you can now control the light from home assistant, set it to turn on automatically, or use custom effects. This modding project allows for a more versatile use of the IKEA Iskärna lamp, enhancing its functionality and integration with smart home systems. Depending on which LED controller you use, the possibilities change. For example, with certain LED controllers, you could connect the lamp to Philips Hue or to IKEA's own smart home system (TRÅDFRI, DIRIGERA). Before the modification, this was not possible, as the lamp could only be controlled manually. Maybe you can set it up as an automatic night light or have simulate a sunrise in the morning. ## The Glorious Revolution and the resulting Bill of Rights ## Historical events In 1685, a pivotal moment in English history unfolded as James II succeeded his brother Charles II to the throne. James II, unlike his Protestant predecessor, was a devout Catholic. His ascent to power ignited a wave of hope among Catholics for greater religious freedom and tolerance. However, this hope was met with apprehension and resistance from the Protestant majority, particularly within Parliament. {{< figure src="James_II.jpg" alt="Portrait of James II" caption="Portrait of James II, Public Domain" width="40%">}} As James II began to assert his authority, tensions between the crown and Parliament escalated. Unlike his brother, James II sought to wield more centralized power, challenging the traditional balance between the monarchy and the legislative body. He amassed a standing army and appointed Catholics to key positions, raising concerns among the Protestant majority about the potential for religious persecution and the erosion of their rights. The friction between James II and Parliament reached a boiling point in November 1685 when the king made the controversial decision to dissolve a session of Parliament. This move was perceived as a direct challenge to the authority and independence of the legislative body. ## Ongoing call for change As the years passed, the skepticism among Parliament members regarding James II's policies and his consolidation of authority only deepened. The accumulation of power in the hands of the monarch and his decisions concerning religious matters fueled concerns about the erosion of fundamental freedoms. The increasing unease within Parliament about James II's actions spurred a call for decisive measures. In 1688, a coalition of English nobles extended an invitation to William of Orange, husband to James's Protestant daughter Mary, to intervene in English affairs. This invitation marked a pivotal moment in the quest for liberty and laid the foundation for the events that would unfold during the Glorious Revolution. Arriving in England in November 1688 with a formidable Dutch fleet and a combined force of Dutch and English troops, [William of Orange](https://en.wikipedia.org/wiki/William_III_of_England) represented the hopes of many Parliamentarians for a restoration of balance and the preservation of individual liberties. James II's army, which had been expected to defend the king, instead defected to William's side, and the king fled to France, effectively abdicating the throne, leading to a bloodless transition of power. {{< figure src="La_Reception_faite_au_Roy_d'Angleterre_par_le_Roy_à_St._Germain_en_Laye_le_VIIe_janvier_1689.jpg" alt="Louis XIV greeting the exiled James II in 1689" caption="Louis XIV greeting the exiled James II in 1689, Public Domain">}} ## Consequences and the English Bill of Rights Following the Glorious Revolution, England experienced profound political transformations that reshaped the relationship between the monarchy and Parliament. With the royal assent on December 16, 1689, Parliament's influence on the monarchs became more pronounced, marking a significant shift towards a system where consent was paramount. Central to these changes was the imposition of limits on the power of the monarchy. The establishment of free elections and the regular convening of Parliament became integral components of governance, ensuring that the voices of the people were heard and represented. Within this framework, members of Parliament were granted the freedom of speech, fostering an environment of open discourse and accountability. The abolition of excessive fines and cruel or unusual punishments, as well as the prohibition of the suspension of laws without parliamentary consent, were key provisions of the English Bill of Rights. These measures were designed to safeguard individual liberties and prevent the abuse of power by the monarchy. {{< figure src="English_Bill_of_Rights_of_1689.jpg" alt="English Bill of Rights" caption="The English Bill of Rights, Public Domain">}} As a result of these reforms, conflicts between monarchs and Parliament dwindled, paving the way for a more harmonious relationship based on mutual respect and cooperation. The principles outlined in the English Bill of Rights not only affected the political landscape of England but also influenced the development of other constitutional documents, including the United States Bill of Rights, shaping the course of modern governance and individual freedoms. Source: [UK-Parliament](https://www.parliament.uk/about/living-heritage/evolutionofparliament/parliamentaryauthority/revolution/) ## Valve publishes Steam Link App for Meta Quest Valve, the company behind the popular Steam gaming platform, has released a new app for the Meta Quest that allows you to stream PC VR games to Meta Quest VR headsets over a Wi-Fi connection. The app is called **Steam Link** and is available for free in the Meta Store. It can be downloaded via the [Meta Store](https://www.meta.com/en-us/experiences/5841245619310585/). This allows for direct streaming of SteamVR games, such as the popular "Half-Life: Alyx", to the Meta Quest VR headset. This move marks an expansion of Steam Link functionality, which has previously only been used to stream PC games to mobile devices such as smartphones and tablets. ## Comparison to existing solutions Compared to other solutions, such as Meta's built-in Air Link, Steam Link offers some advantages for users. First, you don't have to install the outdated Oculus PC software, which not only takes up storage space on your PC, but also affects the performance of your PC. With the Steam Link app, you also get to Steam Home much faster, as it loads directly in the app and skips the double menu of the Oculus Home. In my own test, the connection with the Steam Link app was also much faster than first starting the Oculus PC software and then establishing the connection. Here I also didn't have to restart to see my desktop, which was the case with Air Link. Quality-wise, there are also no major differences. Both have a very nice quality. No quality losses were found in either. ## Installation The setup is very easy. All you need is a PC that is already VR-ready and the [Steam Link VR app](https://www.meta.com/en-us/experiences/5841245619310585/) on your Meta Quest. An Ethernet connection between PC and router is recommended, but not mandatory. In my own test with Wi-Fi 6 it worked without problems and with a 120Hz refresh rate. With a wireless connection, there is a warning that the connection is not optimal, but this can be ignored. After installing the app, it should automatically find your PC on the network and you can connect it directly. It asks for a code that you have to enter on your headset from the PC the first time (you might even see it in passthrough). After that it should be connected directly and you can start your SteamVR games. ## Gaming experience After successful setup, you can play your SteamVR games directly on your Meta Quest. You start in the new [SteamVR 2.0](https://store.steampowered.com/news/app/250820/view/3739736044830869589), which has a new dashboard and a new user interface. These two innovations create a very nice gaming experience, as it is very easy to switch between games. {{< figure src="/img/SteamVR2.0.webp" title="The new SteamVR 2.0 Dashboard" alt="The image shows the new SteamVR 2.0 Dashboard. It has the old Steam Home background, but with the new dashboard. It contains games in large tiles and a bar with menus on the left." >}} Starting SteamVR is also much faster than with the Oculus PC software, as it starts directly in SteamVR Home and not first in Oculus Home and then in SteamVR. Instead of a few minutes, you can now get into the game in a few seconds. It is also possible to play non-VR games. These are displayed on a virtual screen located in the virtual environment. ## Conclusion The Steam Link app is a very good alternative to Air Link and offers some advantages. It is very easy to set up and offers a very nice gaming experience. It is also very good for people who don't want to install the Oculus PC software. Overall, getting started in the VR world is much faster and easier than before. ### Further information - [Steam Link VR App](https://www.meta.com/en-us/experiences/5841245619310585/) - [Steam Link VR Announcement](https://store.steampowered.com/news/app/593110/view/3823053915991825335) - [Steam Link VR FAQ](https://help.steampowered.com/en/faqs/view/0E2C-406B-9135-38A4) Images provided by Valve. ## Smart Message Language Reader for Home Automation The continuous development in the field of home automation opens up ever new possibilities to control the energy consumption in our homes efficiently. A crucial step in this direction is the reading of data from smart electricity meters using the Smart Message Language to gain detailed insights into energy consumption. That's exactly why I created "SML-Reader" to read out the Smart Message Language data and then send it to smart home systems, such as Home Assistant, via MQTT. ## Why this project? The idea for this project arose from the existing materials. With an already available W5500-EVB-Pico and the need for a reliable Ethernet connection in the basement, where the WLAN is weak, the motivation for implementing the Smart Message Language-Reader was born. The W5500-EVB-Pico, an inexpensive and easy-to-use microcontroller board with an Ethernet port, provides the perfect basis for this project. In addition, it has two hardware serials, which allow both the connection to the computer and to the infrared reading head. The difficulties in finding suitable software with Ethernet support for the RP2040 chip (used in the EVB-Pico) reinforced the desire to develop a tailor-made solution. For example, Tasmota is not yet available for the RP2040 chip with the W5500. Another obstacle was determining the OBIS codes, which vary depending on the smart meter and configuration. However, this can be easily found out by using the program. This project was made possible by the Smart Message Language, which is a standard for the transmission of energy consumption data. The SML is used in Germany for the communication between smart meters and the smart meter gateway. The SML is also used in other countries, such as Austria, Switzerland and the Netherlands. ## Project details ### Supported smart meters The SML-Reader is compatible with all smart meters that support the SML protocol. I successfully tested the system with the [Apator PICUS](https://www.apator.com/de/produkte/strom/strommessung/moderne-messeinrichtung/picus). The displayed data depends on the functions supported and configured in the smart meter. Under certain circumstances, certain settings may need to be made on the meter, such as disabling the PIN or enabling extended operating modes (InF). Some data also requires manual activation by the LMN interface by the network operator. Further OBIS codes can be added by editing the OBIS handler list. ### Hardware and software - [W5500-EVB-Pico microcontroller board](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico) - SML-compatible electricity meter - Ethernet cable and connection - Power connection - MQTT server - [PlatformIO](https://platformio.org/) IDE - [SML-Reader](https://github.com/JonatanMGit/SML-Reader) project ### Configuration of the SML-Reader Edit the `config.h` file in the SML-Reader project to enter the connection information for your MQTT server. Here you enter the MQTT login data. Further settings, such as a static IP address or other OBIS codes, can be made in main.cpp. After saving the configuration file, you can re-flash the SML-Reader to apply the changes. The configuration file is saved during flashing. A dynamic configuration via the web interface is in progress. The reading head must also be connected correctly. The connections are standard on the W5500-EVB-Pico board as follows: - TX: GPIO04 - RX: GPIO05 - GND: GND - VCC: 3V3 The setup should look like this: {{< figure src="SML-Reader-EN.svg" title="Diagram of the setup of the SML-Reader" alt="Diagram of the setup of the SML-Reader, showing the connection between the W5500-EVB-Pico and the IR reading head. The pins are the ones mentioned above." width="100%" >}} These connections come from the second hardware serial of the RP2040 chip. The first hardware serial is used for the connection to the computer. The second hardware serial is used for the connection to the reading head (UART0/UART1 and UART2) ### Flashing the SML-Reader with PlatformIO in VSCode 1. Install PlatformIO in VSCode 2. Clone the [SML-Reader](https://github.com/JonatanMGit/SML-Reader) project 3. Open the project in VSCode. There PlatformIO should see the option to build the project directly (upload) 4. After compiling and uploading the project, the SML-Reader should be ready to use. If there are problems with flashing, you can also manually copy the UF2 files to the device (hold Bootsel pressed while doing so). After successful flashing, the SML-Reader should receive the data from the electricity meter and then send it to the MQTT server. ## Reading the MQTT data in Home Assistant The device should now automatically send the data to the MQTT server. Using [MQTT Discovery](https://www.home-assistant.io/integrations/mqtt#discovery-options), the sensors are automatically created in Home Assistant. The sensors can then be used in Home Assistant. If this does not happen, you can always manually insert the measured values in Home Assistant via the config.yaml. The data is sent to `homeassistant/sensor/w5500-evb-pico//state`, if you want to integrate it into other systems. ## Web interface The project has a web interface that allows you to display the data read from the electricity meter. The interface is accessible via the IP address or the mDNS name of the SML-Reader. The displayed data depends on the functions supported and configured in the smart meter. ## Conclusion The project is an inexpensive and simple solution to read out the SML data from a smart meter and then send it to smart home systems, such as Home Assistant, via MQTT. The use of the W5500-EVB-Pico allows a reliable Ethernet connection, which is advantageous for local home automation. The web interface offers an easy way to display the data of the electricity meter. The use of PlatformIO allows an easy installation and configuration of the project. ### Further information Many thanks to the [SML Parser](https://github.com/olliiiver/sml_parser) library, which forms the basis for this project. More information is available on the German version of this page. ## The Michelson-Morley Experiment and the Aether Theory This blog Post has an alternative Video version if you prefer that. The video can be [accessed on YouTube](https://www.youtube.com/watch?v=F8t01xqgmCk). --- The Michelson-Morley experiment is an important physics experiment conducted in the late 19th century. It was already known in earlier times that light propagates in waves and was compared to water waves, which require a medium, namely water. Michelson and Morley thought that light must also have a medium, namely the aether, and they wanted to prove this through an experiment. ## What is the aether? The ether is the hypothetical medium through which light travels through the universe. This idea can be easily illustrated by everyday examples such as water waves or sound waves, which also require a medium to propagate. It was thought at the time that the aether medium existed throughout the universe to allow light to propagate. It also need not be dense, since planets are not affected by it. ### The behavior of the aether It was also assumed that the aether is at rest and does not move with the earth, much like the air around a car. When an object is moved through the aether, a kind of aether wind is created, similar to the wind created around a moving object. As the earth moves through the aether, an aether wind should also be created. The experiment of Michelson and Morley attempted to confirm the theory of the aether by means of the aether wind. Anything moving with the ether wind would have to move faster than against the ether wind, similar to the airplane. If you were to fly against the wind, it would be slower than with a tailwind. If you have a crosswind, i.e. the wind comes from the left or right side, this does not change the speed either. It was precisely this behavior that Michelson and Morley wanted to test with their experiment. If the aether were real, light would have to behave exactly like an airplane, flying faster when it has a tailwind and slower when it is flying against the wind. ## The experiment Michelson and Morley's experiment was designed to detect the aether wind. To do this, they used an interferometer, which consisted of a semi-transparent mirror, two perpendicular arms and a receiver. A laser beam was aimed at the semi-transparent mirror, which split the beam into two halves, each passing through one arm of the interferometer before hitting a mirror at the end of the arm and being reflected. The reflected beam returned to the semi-transparent mirror where it overlapped with the other beam and created interference patterns that could be observed on the receiver. ### The expectations The interesting thing about this experiment was that if the interferometer had moved with the aether wind, there should have been a shift in the interference pattern. This would arise due to the different speeds of the light rays, each traveling against and with the aether wind. If there were no aether, both light beams would travel at the same speed, regardless of the direction of the interferometer, and no difference in the interference pattern could be observed. ## Surprising results However, the result of the experiment surprised physicists because it showed no shift in the interference pattern. No matter which direction the interferometer was pointed, there was no measurable change. This result was a great surprise because it contradicted the assumption at the time that there must be an ether medium. The Michelson-Morley experiment was a significant step in the history of physics because it questioned the belief in the existence of the ether and thus in a fundamental property of the universe. The experiment showed that there is no aether wind and that light moves at the same speed in all directions, regardless of the observer's movement. This result was the starting point for Einstein's theory of special relativity, which revolutionized the understanding of spacetime and continues to play a central role in modern physics today. ## Protein Biosynthesis If you are more of a visual learner, you can also view my YouTube video for protein synthesis, which is embedded or [directly available on YouTube](https://www.youtube.com/watch?v=17GMVbstC3Q). --- Proteins are the workhorses of life and perform a variety of essential functions in our cells. But have you ever wondered how these complex molecules are actually made? The answer lies in the fascinating world of protein synthesis, a remarkable cellular process that we are in the process of unraveling. ## What is protein biosynthesis anyway? To understand this, we first need to examine a cell. ![Nucleus of a cell](/img/human_cell_nucleus.svg "A picture of a nucleus of a cell") This is where the DNA is stored. The genetic material must now reach the ribosomes outside the nucleus for protein formation to occur. To do this, the data must be processed and transported in such a way that these ribosomes can read it later. This processing and transport is called **protein biosynthesis**. ## The transcription The DNA is currently stored in a double helix and must now first be opened up. To process the data now, the DNA is transcribed into an mRNA. In this process, the DNA is divided into base pairs and the bases are then read individually. The bases are then translated into the matching bases of the mRNA. This is why the process is called **transcription.** This mRNA is now passed on. Unlike DNA, mRNA consists of only one strand and is now ready to leave the nucleus, while undergoing very little processing. First, the mRNA is shortened a bit more and then a few extra bases are added. These additional bases are important for translation. Now the mRNA is ready and can leave the nucleus. There it is read by the ribosomes. ## The translation The ribosomes are the factories of the cell and consist of two subunits. Now three bases are read at the same time and these are called codon. Each codon stands for an amino acid. After the entire mRNA has been read, the amino acid chains can now form complex 3D structures and thus form a protein. This process is called **translation** because the bases are translated into amino acids. The mRNA can then be broken down again and the ribosomes can dissolve again.