Whilst I don't disagree with the urge to blame the control firmware for this problem, since firmware issues are indeed implicated, note that in any system where there are massive amounts of current and voltage flying about (relative to the minuscule voltages and currents in the microcontrollers, canbus transceivers, and other random electronic bits) the problems you lot are seeing could very well be caused by periodic software "upsets" due to induced transients in sensitive electronic circuits. Hardening circuitry against transients from battery chargers turning on (and off), high voltage AC-DC converters and other such things is not trivial. We have enough trouble as it is in IC powered cars from things like alternator load dumps and AC compressor clutch disengagements and other transients. Not having worked on EV's meeself I can only imagine the design nightmares in trying to make all this stuff reliable. Sometimes it's impossible to reliably defend against induced transients so the firmware has to be prepared to deal with such events. Then again automotive firmware isn't known for the highest quality...
It's a firmware bug. I specifically specialize in embedded message passing systems. To simply it : it doesn't matter if a message got dropped because of a glitch (transient, etc). Over a 5 hour period last night, 2 things were true:
STATE: TRACTION CHARGING
STATE: 12v CHARGING DISABLE
This combination of 2 states is invalid - it's a system design rule violation.
There are a number of designs where periodic resyncs of state, or comparing the coherency of current state, or resending messages if no reply received would have handled this issue. It's totally fine if this happens transiently. For example one simple design is that the firmware that handles the traction charging could periodically poll the system and get the state, and it's state machine will send a message to request the +12V charging enable if the present state shows the charging is off.
This kind of setup where a message will be resent over and over at the polling interval makes it immune to transient glitches, microcontroller reboots, etc.
You make the traction charging controller immune to reboots by having it derive what to do - "should it be charging" - by the
hardware. If it gets reset and it checks the pins and the charging connector is inserted and voltage is available, and it's
not charging, it should send the messages to begin charging by the same idea.