Переписал автомат, выкинув проверку waitForReadyRead (из-за которой время от времени и непредсказуемо случалась ошибка SocketTimeoutError). Теперь вход в автомат возможен из двух разных функций: при получении сигнала от, например, кнопки -- когда пользователь хочет получить данные от устройства -- и от сокета (readyRead). Сначала автомат шлёт запрос в устройство, запоминает состояние и выходит. Потом срабатывает сокет и снова запускается автомат: он смотрит, в каком состоянии был, размышляет о том, что надо сделать дальше и либо выдаёт уже свой сигнал готовности данных чтения (или завершения операции записи, если мнеэто понадобится когда-нибудь), либо идёт по циклу состояний.
Получение данных из сокета теперь работает не с одиночными байтами, а с доступным объёмом. Не знаю, правда, как проверить работоспособность алгоритма, если данных пришло меньше, чем надо. Теоретически, пока не придёт "минимальный квант", функция приёма просто будет завершаться, ничего не делая. Тут уже зависит от того, как на самом деле генерится сигнал readyRead. Если он может выскакивать, даже если пришёл всего один байт,... а потом ещё один байт (и снова срабатывание сигнала)... и ещё один.. или два.. тогда должно работать норм. Если же это не так, то х.з.