I'd re-evaluate the use of "printf / sprintf", and whether their convenience is worth allocating 12.5% of my memory to "buffer".
I'm guessing "__FlashStringHelper*" errors are why the F() macro isn't being used inside sprintf lines, which ties up another 55+ bytes for storing the templates for those sprintf calls.
"PingTime" is overflowing, it has room for "Reboot". Maybe you meant to use "buffer" instead?
It looks like the main issue comes down to output buffering being anticipated, but strayed away from. So that sizable "buffer" variable, combined with smaller redundant variables designed to improve readability, but eventually leading to variable confusion like what happened in "PingTime", ends up eating more memory than is needed.