M5Stack is a great choice for this stuff, IMO. I absolutely love their devices, for the reasons that you list: multi-functional devices (lots of capability in a small / cheap unit), & compatibility / ease of flashing & using.
But especially, for the plug-and-play with no soldering, and having pre-packaged devices without needing to build hand-crafted enclosures.
And if you do want to do a bit more, they have a number of GPIO pins exposed on headers for simple plug-in of sensors etc. Generally though, it’s nice to stick with the plug-in Grove connector when possible.
M5Stack has several different “families” of ESP32 controller devices: Atom, Core, Stack, etc. Some of them seem suited for assembly into other things (like robotics), whereas I have stayed with the Atom series for Home Assistant / ESPHome usage. I’ve got Atom Lite (many of them), AtomU, Atom Speaker, Atom Echo, AtomS3 Lite, Atom S3, even Atom POE. But I’ve also been meaning to check out the M5Stick series.
One example of usage: I’ve deployed several ESPHome Bluetooth Proxy devices, that are very good looking and unobtrusive-- Just plug an AtomU (with USB-A connector) into a slimline USB wall adapter, and you can have a tiny BT Proxy which hugs the wall anywhere you’ve got an AC outlet.
You will also find that the Home Assistant team tends to build first for the M5Stack Atom devices when they come out with new HA features like Media Player, BT Proxy, Voice Assistant, etc. Typically just go to a web page & click a button to make your Atom device into an appliance for the new feature.
I would caution you about the Grove connectors on M5 systems, as they use the same connector in several different ways. They call it Port A, B, or C usage. Most typical use is hanging a bunch of I2C sensors onto a system, which uses “Port A” setup. “Port B” arrangement is typically used for DAC/ADC or other general GPIO analog or digital ports. And “Port C” is for UART.
But you can really use almost any type sensor or actuator on a Grove connector; you just have to pay attention to how you’re configuring the GPIO ports which the Atom unit has connected to the Grove connector.
If you’re using multiple I2C devices, you can fan-out with M5Stack 3-unit or 6-unit Grove “hubs”, since I2C allows multiple devices on same bus. I’ve even gotten creative with connecting two single-signal devices to the Atom with a “Y” Grove cable, connecting one device to the “data 1” Grove line & clipping “data 2” line (& opposite on the other device). Just configure the GPIO ports correspondingly in the ESPHome YAML code.
Besides M5Stack, I’ve also found another great source of things to hook into M5 Atom units: Grove-compatible connectors, sensors, different-length cables, etc. at Seeed Studio.
And you can find additional plug-and-play sensors and actuators at SparkFun. Although they use a different cable (known as QUIC or Stemma) --but you can buy Stemma-to-Grove adapter cables at Seeed Studio. Unfortunately, the SparkFun units typically don’t have enclosures (just little circuit boards with plug-in connectors).
And finally, for purchasing of devices, you can get M5 Atom units and sensors directly from M5Stack, But I like going with suppliers like DigiKey or Mouser; normally same price but 2-day delivery (vs shipping from China). You’ll find some differences in availability: occasionally DigiKey or Mouser or Amazon will have stock when the factory doesn’t, and vice versa. (And same for purchasing Seeed Studio parts via those suppliers.)
Let me know if any questions about the M5 ecosystem.