What is the best serial protocol for bidirectional communication with NodeMCU? Except hardware UART. Main requirements are reliability and simplicity of use. Speed isn't as important.

Details:

I have an Arduino Pro Mini (ATmega328P 5V) controlled via UART.
I wish to connect an ESP8266 with stripped-down NodeMCU to offer a web interface for the same functionalities, sending &lt;=122 character strings to Arduino and possibly getting a short response.
I do not want to use Arduino for processing the interface (too little memory) or use the ESP only (need a stable clock and multiple analog inputs).

My research shows that:


ESP8266 has obvious timing issues, having been designed for a different purpose.
Controlling the ESP8266 from Arduino via hardware serial works fine, but I need it the other way around, too. Also, NodeMCU is rather chatty and I don't know how to suppress it, and I'd rather keep the hardware serial ports for programming.
The same via SoftwareSerial is unreliable
Personal experience shows OneWire works poorly on ESP8266 (though it may have been fixed)


I have no experience with I2C and SPI beyond polling a slave, and don't know about reliability on ESP8266.
The Arduino already works as an I2C master.
I'm assuming I2C is the way to go, but wanted to ask for opinions first.

[EDIT]
Seems I have once again neglected to set up the proper context. The reason I'm asking is that ESP8266 can't do very precise timing, leading to communication problems. Hardware UART to hardware UART is shown to be reliable. For most other protocols, at least one side does bit-banging. I have not done or found extensive reliability tests for those options, and hope instead that the community can offer some insights. Can you?
So you are asking how to use an Arduino Pro Mini as a smart peripheral connected to a NodeMCU master, without making use of the hardware serial port on the latter.

In general, this is either going to operate slowly enough that you can guarantee reception, or you will need to use some kind of flow control or acknowledgement.

One question is whether the APM can always receive at any time, or whether it has to do things which would cause it to not respond for some while and possibly lose data.

Hardware I2c or SPI, with a software flow control protocol using additional pins, are probably your best bets if you cannot use async serial.  For example the APM sets OK2SEND high when it's ready to receive (this is an APM output pin connected to a NodeMCU input pin).  When NodeMCU detects this high, it writes to I2C and then sets HAVESENT high.  When the APM detects &amp; processes incoming data as I2C slave, it sets OK2SEND low.  NodeMCU sees OK2SEND low (ack'ing the byte) and sets HAVESENT low.  APM detects HAVESENT low which completes the handshake.  When APM is ready for another byte, it sets OK2SEND high again.  etc.  Variants could send more than one byte per handshake, if performance needs that; APM asserting OK2SEND would be contracting to handle that number of bytes.

If you can guarantee that the APM will respond quickly enough to interrupts, you could use an interrupt driven I2C slave system on it, and simplify the above.  The APM could be like a dedicated I2C peripheral, albeit a slow one.