Monday, August 3, 2026

Your Bluetooth is bad, August 2026 (Battery and Name)

 Your Bluetooth is bad, and you should feel bad

Alternate title: Your Bluetooth is OK, but it could be better

 Just two gripes this time!

Always include a name. 

I'm looking at you, Ruuvi. The Ruuvi sensors are interesting little devices. They started out back when the Eddystone protocol was an exciting new thing (fun fact: Copilot thinks there are still major Eddystone devices in the real world!), then made essentially the same sensors but with their own advertising format. And the Ruuvi company includes good documentation on their GitHub!

But ... why don't the tags advertise their names? Normally the way my app can tell one device from another is just from the name (and so far, without any overlaps) or for standard devices like Bike sensors, from the services exposed. Now I have to paw deep into every advertising packet just to see if an advert might be from a Ruuvi.

Use battery percentages, not voltages

Providing a battery voltage and not a percent, IMHO, is just weaseling your way out of a small bit of analysis. And it's an analysis that you, the maker, can do best.

There is no user out there who wants to know that the battery is at 2.45 volts. But everyone wants to know if the battery is running low. You can either do a conversion in your app, or you can just do the conversion on the device.

Not only that, but end users just expect a "ballpark" figure. This is confirmed by Microsoft, which expects devices to provide 11 steps (0..100% in 10% steps including the 0 and 100), and by the Bluetooth SIG which made the standardized battery levels.





Wednesday, July 8, 2026

API Rules for designers: use one encoding, not two

 

API Rules for designers: use one encoding, not two

 

"If you haven't tested your code, it's probably wrong"

 

Today's bad API example is from the Bluetooth Heart Rate system. Most of the protocol is fine: you get a notification every so often with updated heart rate information (e.g.,  heart rate in beats per minutes (BPM) plus optional stuff for overall energy and the "RR Interval" for fine-grained heart data).

 

Testing this protocol is extra expensive because the heart rate (BPM) can be sent in two ways. It might be a single byte, and it might be two bytes. There's a single bit in a flags structure to say which way it is. If the person's heart is 255 BPM or less, it's one byte. If it's 256 or more, it's two bytes. The app code (and device code) has to handle this.

 

For an app, the code is hard to test for two reasons. Most importantly, a human doesn't ever have a heart rate that high (according to Copilot, "255+ BPM is possible, but it’s always pathological"). The second is that even if I could find a person with a heart rate that high, I have no confidence that any specific consumer-grade device will ever produce this data. As just a person coding in their spare time, I can buy a couple of heart monitors. But imagine I still worked at Microsoft: what are the changes that a VP (that's the clearance it takes for approving purchases) would sign off on an unknown number of devices on the chance that one of them would produce this data?

 

In the end, I've got code in my new Bluetooth app (not on the Microsoft app store yet) to handle the special flag. But my confidence that it works isn't great.

 

The right API choice was to always send 2 bytes of data and not try to make something in the name of spurious efficiency.

 

For the nay-sayers: the awkward protocol doesn't support any interesting new scenarios, and doesn't have any appreciable amount of energy.

 

If they had kept the protocol as-is, developers would have the same abilities. The RR Interval data size would shrink from 9 entries to 8 -- but in typical use, there's only 3 or 4 entries. And if there's a case for needing more than 8 entries, the Bluetooth device could simply transmit more often.

 

Takeaway: Protocol designers should always include "how will a developer test their code" when considering complicated APIs.

 

Friday, April 3, 2026

IL2104 IL2026 TRIM and JSON with WinUI3 and newer C#

 JSON: why is C# TRIM so horrible for no reason 

Trim analysis warning IL2026: SerializeExtra.Demonstrate_Bug_Program.Demonstrate_Bug_Main(): Using member 'System.Text.Json.JsonSerializer.Serialize(!!0, JsonSerializerOptions)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.

In the old days, C# had a simple JSON story: always use the Newtonsoft JSON library, helpfully packaged up in NuGet, and never use anything else, ever. But then I tried making an app with WinUI3 and the more recent C# (like version 10?), and now it completely sucks, and it's ten times harder than it should be. And it's all Microsoft's fault

C# introduced a new concept: TRIM. This is a link time option. It's on by default for Release mode and off by default for Debug mode. What it does it go through your app and removes all of the "unneeded" code. The problem is that it means that the normal way Newtonsoft's JSON works doesn't work; it will just plain crash.

Note the horrific discovery mechanism for this, by the way: there you are, coding happily in a shiny new app, using shiny new features, and a switch you didn't set causes weird-ass warnings when you compile, and then your app crashes, but only when you're almost done and are now testing in Release mode.

The only solution is to switch to the System.Text.Json.JsonSerializer and Deserializer classes. But even these are completely broken with the new switch, and delightfully (sarcasm) the official Microsoft documentation guides you right into the absolute wrong way to use them.

Worse, the C# classes also guide you into the wrong way. Those shiny new templated classes? Those won't work at all.

Luckily, I've researched it so you can just jump right into the pit of success.

  • When you make your SourceGenerationContext from JsonSerializerContext, always add a TypeInfoPropertyName option 
  • When you call Serialize of Deserialize, you must use the non-templated versions. Pass in your object (or string, for deserialize), the typeof(yourclass) and your SourceGenerationContext.Default object. 
  • Never new up a SourceGenerationContext object. When you do, it won't have the JsonSourceGenerationOptions that the Microsoft docs tell you to use
  • Always specify a [JsonSourceGenerationOptions(WriteIndented = true)]. If you wanted a compressed serialization format, you'd have used Protocol Buffers, not JSON. When you use JSON, it's because your users want a human readable result, not some one-line nonsense.

See my complete project on Github for more details. The About file is particularly helpful. Look at the WeatherForecast_Fix1.cs file for full details. The bug is reported to Microsoft .NET team.


Thursday, March 19, 2026

Fixing the dreaded XAML parsing failed

Fixing my XAML Parsing Failed bug (subfolders)


This is a doozy, and is about the last possible bug one would imagine in the new WinUI3 that Microsoft is pushing for us to use when making apps for Windows.

The background when you make an app using C# (and really, why wouldn't you?), you will use the XAML mini-language for describing your layout. XAML has conceptually been around for years, but Microsoft being Microsoft, they can't help but radically change it and rename it every few years. The XAML for WPF isn't the XAML for SilverLight, which isn't the XAML for UWP, which isn't the XAML for the most recent WinUI3

And a problem that a ton of people have discovered is that somewhat randomly they will write some XAML and it will just fail. But it won't fail at compile time (they do compile-time work to make it run fast; the XAML is not interpreted at runtime). Instead, it fails when your XAML page or control is displayed! The exception generally just says "XAML Parsing Error".

Well, I've figured what's going on. Like any seasoned developer, I use folders to organize my controls. Guess what programming system from a major OS company can't handled "putting a control into a folder"? That's right, Microsoft's WinUI3!


And I've got a simple repro [on GitHub](https://github.com/pedasmith/bug_WinUI3_usercontrol_in_folder_xaml_parse)

Saturday, January 31, 2026

Weird EPUB bug: empty image files in the IRS i1040gi.epub file

This EPUB bug brought to you by the IRS and their i1040gi.epub file


Normally government EPUB files are pretty good about making usable EPUB files. But this year only, the IRS's "i1040gi.epub" file (the file with USA government tax information for filing out the very common 1040 tax form) has a subtly malformed epub file. The list of images (EPUB/img) has 28 GIF files which are all fine, and one JPG file (cover-instr-i1040.jpg) which is zero bytes long.

This file fails to load correctly which leads to a cascade of errors.

Solution is to catch the error and silently ignore it. (Technically, I first check for zero-byte files and ignore it, and also catch the exception and ignore it. Both branches were tested, of course)

Tuesday, December 9, 2025

Developing on ARM64: DEP0700 failures in Debug mode

Can you solve this error message? 

DEP0700: Registration of the app failed. [0x80073CF3] Windows cannot install package NAME because this package depends on a framework that could not be found. Provide the framework "Microsoft.VCLibs.140.00.Debug.UWPDesktop" published by "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", with neutral or ARM64 processor architecture and minimum version 14.0.33728.0, along with this package to install.


Background: building an existing UWP app on ARM machine

I have one of the ARM64 machines that Microsoft is big on, and of course I have a bunch of existing app (Store link). So what better thing to do than to enjoy a nice coffee in a fancy lodge here in the pacific northwest while updating the Bluetooth app to support a new device?

Except you can't deploy your debug-mode ARM64 app! It fails with the above error! 

What's do the might search engines say?

Search engines recommend the following three things:

<Dependencies>
<PackageDependency Name="Microsoft.VCLibs.140.00.UWPDesktop" MinVersion="14.0.24217.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />

</Dependencies>

Or this:

<RequiredBundles>$(RequiredBundles);Microsoft.VisualStudio.Component.UWP.VC.ARM64</RequiredBundles>

Or updating the user's .VSCODE profile. None of these work

Crappy solution found! Just run in x86 mode!

The crappy solution I eventually tried: just run in x86 mode instead of ARM64 mode. Sure, it's a waste of processor time and effort, and sure, it's a stunning indictment of Microsoft's absolute failure to actually support their own freaking devices, but it got me moving forward.


Tuesday, September 23, 2025

Github is both awesome and painful with VS 2026

 The old days of programming, before source control systems, was kind of dangerous. There was always the possibility of losing all your work, and there wasn't a good way to move files from one computer to another. Indeed, when I was a consultant, I paid good money for a "Jaz" drive and for a WinZip license just to be able to move files from one office to another.

GitHub integration is awesome for fixing all these problems. But it has its own particular point of view that makes it awkward for just a hobbyist programmer.

Today's problem: I added a big image to my new program that was larger than the 100 MB GitHub max. That's OK; GitHub isn't a blob storage. But correcting the problem!!!

First action: delete the large file and make a compressed copy (I don't want the compressed one to have the same name for other reasons). Result: now I can't upload my files from my computer to GitHub. Even though the file is deleted, it seems like Git really, really wants it to upload first so that it can delete it. And the upload will always fail.

Second action: read a bunch of suggestions on the internet. Result: this works, but I have to download a random python file that absolutely must not have an extension (!) and must be in a special path for Git integration. But integration isn't really needed. Result, B: it "works" but now my repo is broken. This is by design; the tool automatically unlinks my local files from the repo.

Third action: read more suggestions. And there's a completely different Git command to reset the remote (git remote add origin URL). And the first command helpfully told me the right URL to use. 

What would have helped: the Git integration in VS 2026 should include a "you added a giant new file and it's going to hurt".

TL/DR: Git is designed for Big Project and Very Knowledgeable Users. This causes problems.