Ne kadar Claude'um kaldığını gösteren piksel saat
256 piksel kolay kısımdı. Zor kısımlar, sizi kendi hesabınızdan kilitleyebilen bir OAuth yenilemesi ve kuralları okunmak yerine ölçülmesi gereken bir firmware'di.
Masamda bir Ulanzi TC001 duruyor — AWTRIX 3 firmware'i çalışan, 32 × 8 RGB matrisli küçük bir piksel saat. Saati gösteriyor. Ben ayrıca Claude kullanım penceremden ne kaldığını da göstermesini istedim ki bakmak için terminal açmayı bırakayım.
İki yüz elli altı pikselin kolay kısım olduğu ortaya çıktı. Zor kısımlar, sizi kendi hesabınızdan kilitleyebilen bir OAuth yenileme akışı ve uygulama ömrü kurallarını bulabildiğim hiçbir yerde yazmayan bir firmware'di.
Panel ne diyor

Her şey 256 girdilik bir piksel tamponuna elle çiziliyor — 3 × 5'lik font dâhil, çünkü sekiz piksel yükseklikte başka bir şeye yer yok. Yerleşim şöyle: solda 7 piksellik ikon, sonra yüzde, sonra sıfırlanmaya kalan süre; en alt satırda da ilerleme çubuğu.
Renk, eşiklerde atlamak yerine sürekli bir gradyan olarak akıyor — 0-100 arasında yeşilden ambere, oradan kırmızıya. Eşikler ekranı ya "iyi" ya "alarm" hâline sokar; gradyan ise hiç irkilmeden, tek bakışta kaymayı fark etmenizi sağlar. %100'de sayının yerini kilit ikonu alıyor ve çubuk tam kırmızı doluyor.
Gerçekten uğraştıran tek şey, şeylerin sığmayı bırakması. Yirmi dört sütunun bir
yüzdeyi, bir yüzde işaretini ve 2:23 gibi bir geri sayımı taşıması gerekiyor.
Bu yüzden yerleşim sabit bir sırayla sadeleşiyor: önce tahmini değeri işaretleyen
~ gidiyor, sonra yüzde işareti, en son da geri sayım. Her hâlükârda bir şey
sığıyor.
Sizi kilitleyen yenileme jetonu
Yüzdeler, Claude Code'un kendi /usage ekranının kullandığı OAuth kullanım
endpoint'inden geliyor; bearer jetonu da yerel kimlik dosyasından okunuyor.
Yanıt, kind değeri session ya da weekly_all olan bir limits dizisi
taşıyor — ekranın ihtiyacı olan tam olarak bu.
Jetonun süresi doluyor, dolayısıyla script onu yeniliyor. İşte bir akşamıma mal olan tuzak: yenileme yanıtı yeni bir refresh token içeriyor ve eskisi anında ölüyor. Yanıtı kullanıp ekranı güncellerseniz ama yeni jetonu diske geri yazmayı unutursanız her şey kusursuz çalışır — bir kez. Sonraki çalıştırma iptal edilmiş bir jeton sunar ve kimlik doğrulayamaz; arka plan daemon'u olduğu için de sessizce başarısız olur.
Düzeltme tek satır. Düzeltmenin gerektiğini keşfetmek epey uzun sürdü, çünkü hata, siz bakmadığınız bir makinede, hatadan bir saat sonra ortaya çıkıyor.
Firmware'i ölçerek tersine mühendislik
Bu işi ilginç kılan gereksinim şuydu: script ölürse saat bunu fark edip saati göstermeye dönmeli. Üç saat önceden donmuş bir yüzde, hiç yüzde olmamasından kötüdür.
AWTRIX'te bunu yapıyormuş gibi duran duration ve lifetime parametreleri var.
Gerçekte ne yaptıkları yazılı olmadığı için ölçtüm:
| davranış | gerçekte olan |
|---|---|
lifetime dolması | yalnızca uygulamaya yeniden girilirken kontrol ediliyor, ekrandayken asla |
duration dolması | döngüyü normal şekilde ilerletiyor |
/api/switch | süre sayacını sıfırlıyor |
| uygulamayı güncelleme (push) | sayacı sıfırlamıyor |
Bu dört olgu tasarımı tamamen belirliyor. Yerleşik geçişi açıp geçiş hızını
sıfıra alın (böylece geçiş göze görünmez), uygulamaya 90 saniye duration ve
80 saniye lifetime verin ve her yoklama turunun başında ona geçiş yapın.
Script hayattayken, geçiş komutu uygulamaya lifetime kontrol edilemeden
yeniden giriyor; dolayısıyla firmware hiç ilerlemiyor ve panel olduğu yerde
kalıyor. Script ölürse hiçbir geçiş olmuyor, duration doluyor, döngü yerleşik
saate düşüyor ve bir sonraki yeniden girişte bayat uygulama siliniyor. Ölümden
doğru saate kadar ölçülen süre: 84 saniye.
Kodda olmayan hata
Bir süre boyunca düzenlemelerimin hiçbir etkisi olmadı. Yerleşimi değiştiriyordum, push ediyordum, cihaz eski tasarımı gösteriyordu.
Script, Başlangıç klasöründen pythonw altında arka plan daemon'u olarak
çalışıyor. Dosyayı düzenlemek, bellekte zaten çalışan sürece hiçbir şey yapmıyor;
o süreç de paneli her iki dakikada bir kodun önceki sürümüyle ezmeye devam
ediyor. Ekran bayat bir önbellek göstermiyordu; adı aynı olan başka bir program
gösteriyordu.
- Ekran
- 32 x 8
- Yoklama aralığı
- 180 sn
- Ölümden saate
- 84 sn
- Font
- 3 x 5, elle çizilmiş
Yoklama, hatadan sonra 30 saniyelik geri çekilmeyle 180 saniyede oturdu — daha önceki iki saniyelik yeniden deneme döngüsü bir dizi 429 yedi; düşmanca bir istemci yazdığınızı keşfetmenin kaba bir yolu. Canlı değerler diske önbellekleniyor ve endpoint kötü bir an geçirirse bir saate kadar oradan okunuyor; böylece geçici bir arıza paneli asla boş bırakmıyor.
Bunların neredeyse hiçbiri piksellerle ilgili değildi. Küçük ve sürekli açık bir şeyin, arkasındaki sistem ortadan kaybolduğunda ne yapması gerektiğiyle ilgiliydi — ve masada oturup saat numarası yapan bir cihaz için cevap, sessizce tekrar saat olmaya dönmek.