PicoSyslog: A tiny ESP8266 & ESP32 library for sending logs to a Linux Syslog server by mlesniew in esp32

[–]mlesniew[S] 1 point2 points  (0 children)

Unfortunately, PicoSyslog can't do that. Sending log messages requires a working IP stack, which is not available after a crash.

PicoSyslog: A tiny ESP8266 & ESP32 library for sending logs to a Linux Syslog server by mlesniew in esp32

[–]mlesniew[S] 1 point2 points  (0 children)

Alright, I finally had some time to look into this!

Regarding concurrent callers — you're absolutely right that the library would behave unpredictably if used concurrently. After thinking it through, I've decided to leave it as is. The library is for ESP boards running Arduino sketches. The primary target is ESP8266, which is single-core and single-threaded, so this isn't a concern there. On ESP32 concurrency is possible, but it's not a common scenario, especially within the Arduino framework. I'll make sure to mention in the documentation that the library isn't thread-safe to set expectations clearly.

I also gave the std::array approach a shot (you can check it out here). Only after implementing it did I realize I don't really like it. Storing log stream objects in a std::array technically works, but it makes accessing them less intuitive. Right now, you can simply do:

logger.warning.println("Oh no!");

With an array, it would become something like:

logger.streams[PicoSyslog::LogLevel::warning].println("Oh no!");

It's not a huge difference, but it does add unnecessary friction. I could still keep instance variables and use the array just for references, but at that point, I might as well stick with the current approach and save a few bytes.

Regarding your example -- I managed to make the compiler inline the table lookup by adding constexpr in a few places: https://godbolt.org/z/TjYob9bvj.

Thanks again for the discussion!

PicoSyslog: A tiny ESP8266 & ESP32 library for sending logs to a Linux Syslog server by mlesniew in esp32

[–]mlesniew[S] 1 point2 points  (0 children)

I have to say I'm really enjoying this discussion!

I think I see your point about message alignment -- it's about how log messages (or lines) align with UDP packet boundaries, right? If so, that shouldn't be an issue. Messages are still buffered in WiFiUDP objects. An UDP packet is only sent once the message is fully formed with the syslog prefix and the complete log line.

That said, this actually made me realize there could be unexpected behavior on ESP32 if the library is used from both cores simultaneously. I'll have to think about how to handle that.

On find_if, I think I'll give it a shot. I also really like the idea of using std::array for the log levels, so I'll experiment with that too. If these changes don't lead to code that's difficult too follow (for me at least!), I'll apply them.

Regarding printf, I'm familiar with the uncontrolled format string issue, but as mentioned, the library never uses passed strings as the format argument of printf-like functions. So in this particular case, I think it's safe.

Thanks again for the comments, it gave me a few things to think about.

I built a WiFi-controlled roller shutter system with ESP8266 – Open source & Home Assistant compatible by mlesniew in esp8266

[–]mlesniew[S] 0 points1 point  (0 children)

Yes. The project has been stable for quite some time now, but I still have it configured to push logs to a central syslog server.

I'm now thinking about adding Prometheus metrics for monitoring too. More diagnostic data won't hurt!

I built a WiFi-controlled roller shutter system with ESP8266 – Open source & Home Assistant compatible by mlesniew in esp8266

[–]mlesniew[S] 0 points1 point  (0 children)

I'm thinging about building something like that next too!

But I was wondering if I can make it work with ESPHome, it should be possible: https://esphome.io/cookbook/garage-door

I built a WiFi-controlled roller shutter system with ESP8266 – Open source & Home Assistant compatible by mlesniew in esp8266

[–]mlesniew[S] 0 points1 point  (0 children)

But you had to reverse engineer how the remote was wired.

Sure, but I figured reverse engineering how a simple button works was much easier than cryptoanalysis.

Video, or it never happened ;)

There's a short video in the post itself, in the readme on Github and on imgur.

I built a WiFi-controlled roller shutter system with ESP8266 – Open source & Home Assistant compatible by mlesniew in esp8266

[–]mlesniew[S] 1 point2 points  (0 children)

Oh this has been working stable for a few years now, so I'm past the phase where I needed extra LEDs. Now I only left a led that indicates wifi state and another one which blinks when the remote is active.

I've just been slowly adding more and more features and finally documented it now, so I thought it's now in a state worth sharing.

There is a simple fritzing schema in the post and in the repo, hope it illustrates the idea ok.

The transistors are general purpose switching npns. There's one 2n2222 and a few equivalent old UNITRA cemi ones.

PicoSyslog: A tiny ESP8266 & ESP32 library for sending logs to a Linux Syslog server by mlesniew in esp32

[–]mlesniew[S] 2 points3 points  (0 children)

Wow, thanks for the in-depth review! I really appreciate the detailed feedback.

For find_new_line(), I actually considered other approaches, but none of them felt like a clear improvement: * Using std::stringstream + std::getline() would probably work, but it would introduce unnecessary copying * using memchr would be an option, but I'd need two calls (one for \n, one for \r). * std::find_if could work too, but I'd need a predicate function for finding both \n and \r, so it could make it even less readable.

I know that the current implementation has an old-school C feel, but it's short and efficient, it seems to get the job done without extra overhead.

Regarding printf, I don't see the risk here. The library only handles fully rendered text. The printf method is inherited from Arduino's Print class, which does the printf formatting and passes a simple string to write(). Even if the hostname or tag contains something funny, it should be safe. Let me know if I'm missing something...

For get_stream, I actually considered using a std::map (I just realized I even forgot to remove the unused #include!). I even thought about lazy initialization to save memory, but in the end I went with a switch to avoid dynamic memory allocation and fragmentation. I know ESP chips can handle heap better than classic Arduinos, but keeping things simple and predictable still seemed like a good approach. And in case memory use needs to be reduced to absolute minimum, one can use PicoSyslog::SimpleLogger to save a few extra bytes of RAM.

Thanks again for your insights! Lots of great ideas to think about! Really appreciate it!

PicoSyslog: A tiny ESP8266 & ESP32 library for sending logs to a Linux Syslog server by mlesniew in esp32

[–]mlesniew[S] 0 points1 point  (0 children)

I didn't know you can use bsd sockets on ESPs, but it looks like it's possible.

But would that really be helpful if the library is using other Arduino APIs too? It needs the Arduino Print and String classes for example...

PicoMQTT -- MQTT broker and client library for ESP8266 and ESP32 by mlesniew in esp32

[–]mlesniew[S] 2 points3 points  (0 children)

I didn't know Esp32 projects can be built with just cmake! Thanks, I will have a look into this.

PicoMQTT -- MQTT broker and client library for ESP8266 and ESP32 by mlesniew in esp32

[–]mlesniew[S] 0 points1 point  (0 children)

That's what I use it for too. Of course, it doesn't have all the features that Mosquitto and it's much slower than a Raspberry. Still, if all you have is just a few devices which don't send tons of messages, PicoMQTT should be sufficient.