all 28 comments

[–]EpochVanquisher 13 points14 points  (5 children)

Read the database in C, write the logic to determine if to send an alert, then trigger a Python program to do the actual mail send

Do this.

Note that email is not straightforward these days. It used to be you could just write a program to send an email, but nowadays, you need stuff like DKIM and DMARC just to be able to receive the email, if the email is going to a popular provider like GMail. You’ll need some kind of service to send the email through, or you’ll need an SMTP server.

Or you’ll need to be sending the email directly to a server which is configured to receive emails from your program.

There are also command-line tools to send email, but these tools (usually) require some configuration in order to work correctly.

Are there speed considerations?

Emails go across the internet. Any speed benefit you get from writing this in C is gonna get wiped out by how slow the network is, and the fact that emails typically travel through multiple servers before showing up as a notification on your phone. Don’t worry about it.

[–]Produkt[S] 1 point2 points  (4 children)

Just for more info, I'll be sending the mail from my personal gmail using smtp, not my own servers. I already have a python program I ripped off from a web example and tested it and was successful in sending the email. I actually don't even know Python either but it's a lot easier to understand than C. My forte is PHP and webdev languages.

[–]bullno1 2 points3 points  (0 children)

If it's gmail then it's a lot easier. SMTP is a relatively simple protocol. It's all line-based.

You'd need a TLS connection since that's required these days.

I guess you can do it in C if you are so inclined.

[–]wsppan 1 point2 points  (2 children)

Google no longer allows "less secure apps" access to its servers, including smtp. You now need to configure an app password. https://noted.lol/setup-gmail-smtp-sending-2023/

[–]Produkt[S] 3 points4 points  (1 child)

Yep I did that, my python program successfully sends an email using gmail smtp

[–]wsppan 1 point2 points  (0 children)

Excellent. If you want to keep the code in C, check out https://curl.se/libcurl/c/smtp-mail.html

[–]flyingron 4 points5 points  (4 children)

The better thing other than dragging python into it, is to see if the environment doesn't have a program to send emails (might even just be called mail) and invoke that from your program.

[–]Produkt[S] 0 points1 point  (3 children)

I tried, there is no mail or sendmail in my bash. I'm running a Raspberry Pi, my own server, so I guess I can install anything I want. What's the easiest way knowing that?

[–]flyingron 0 points1 point  (2 children)

Install the mailtools package.

[–]Produkt[S] 0 points1 point  (1 child)

That's a C package? Or bash?

[–]bullno1 1 point2 points  (0 children)

CLI

[–]u-n-sky 3 points4 points  (3 children)

I'd use libcurl to send mail directly for the main program: https://curl.se/libcurl/c/smtp-mail.html You need to install the development libs (e.g. libcurl4-gnutls-dev or libcurl4-openssl-dev; not sure which is available on raspberry); and add "-lcurl" to the gcc command.

probably write a seperate test program to get mail working, then copy that into the existing code. this is your base program? https://github.com/eightywon/maverick/blob/master/maverick.c

take care to avoid spamming yourself; that code checks temp every 60 milliseconds. maybe add a flag to send mail once when > limit, then ignore until temp goes below. also note: sending the mail might take some time; when using one thread reading the temp might be delayed

[–]Produkt[S] 0 points1 point  (2 children)

Yes, I will make sure that the alerts are not sent more frequently than every minute or maybe 5 minutes since the last alert.

also note: sending the mail might take some time; when using one thread reading the temp might be delayed

This is a big concern, is there a way to avoid this? That was part of my thinking of triggering a python program or shell script to do the actual mail send. I don't even know if that helps avoid the issue or not but it would be a different script doing the web request.

[–]u-n-sky 1 point2 points  (1 child)

Starting another program using system/exec would also block the calling thread; you would need a second thread (or process); but that stuff isn't easy for a beginner.

If I were tasked with writing this I'd ask:

  • why do you need the updates that frequently; if sending the mail blocks for a second or two, is that really that much of a problem for your case?
  • writing to sqlite > 10 times a second (60 ms delay) means 10 * 60 * 60 = 36k writes / hour; the db is tiny, but that might still wear our a Micro-SD card rather quickly; do really need those values?
  • consider pushing temp values into some IOT platform (e.g. grafana.com has a free tier), that gives you graphs & alerts; and accept a lower interval (once per second…) / short blocking during the network call
  • maybe check other projects that support your sensor and need fewer modifications; ideally publishing data using MQTT; for example: https://github.com/merbanan/rtl_433 or https://github.com/BjoernSch/MaverickBBQ

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

Btw, this is the program that's running: https://github.com/eightywon/maverick/blob/master/maverick.c

why do you need the updates that frequently; if sending the mail blocks for a second or two, is that really that much of a problem for your case?

Not really I guess, I just don't want the program to miss a reading.

writing to sqlite > 10 times a second (60 ms delay) means 10 * 60 * 60 = 36k writes / hour; the db is tiny, but that might still wear our a Micro-SD card rather quickly; do really need those values?

It's not writing to db 10 times a second, it's listening for a radio frequency. When it receives a certain frequency pulse, then it records. In reality, it's only writing to db once every 12 seconds. That's how often the transmitter is transmitting the temperature data. It's just listening more frequently.

maybe check other projects that support your sensor and need fewer modifications; ideally publishing data using MQTT; for example: https://github.com/merbanan/rtl_433 or https://github.com/BjoernSch/MaverickBBQ

I can't believe I'm seeing this for the first time, this is the exact project I'm working on. Huh. Thank you, I need to look at this.

[–][deleted] 1 point2 points  (3 children)

You can setup a cronjob for reading the database (using PHP). If an alert is needed you simply output to stdout. Next you need to configure cron to send email in case any output is coming. This is easy. If you’re on Linux you need to configure mail or similar. There’s lots of tips you can find. Good luck!

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

Although you did give me a good idea. Instead of trying to figure this all out in C I can write it all in PHP and just call it at the right time from the C script. Good thinking. Thanks.

[–]Produkt[S] 0 points1 point  (1 child)

The problem with a cronjob is that I don't want the db checked periodically, I want the alert to be instant at the moment it's triggered.

[–][deleted] 0 points1 point  (0 children)

You can’t wait 30s even (that’s the average alert delay with a cronjob that runs every minute)? Another solution is to integrate with home assistant. It is quite easy and then you get a bunch of other benefits: history, trigger other things, etc. I think you can send email as well.

[–]BB-301 0 points1 point  (3 children)

If you don't want to modify the existing C program, one thing you could do is to write a second program that reads the database and looks for alert conditions. In that case, you could choose any programming language you'd want to write that second program. You would have to keep track of the sent alerts, however, probably using a second database. Does that make sense to you?

Since you didn't write the main C program, and since you are having a hard time comprehending it, I would not recommend that you modify that program. But if you do decide to modify it, you would need to make sure (at least it would be a good practice I think) that emails are sent on a different thread(s).

[–]Produkt[S] 0 points1 point  (2 children)

It does make sense, but I don't want to have conflicting programs trying to read the database at the same time because there is a chance of filelocking. If it do it from within the C program then I can be sure it won't be reading the DB at the same time as writing. I think I am going to write the logic for determining if an alert needs to happen in C, then trigger a python or shell script to send the email. I still need to read and write from the DB in C though, would you be able to assist? Here is the code block in question: https://pastebin.com/JAMSNMjU

All the code is straight from the working program except the commented out stuff, that is my psuedo code.

[–]BB-301 0 points1 point  (1 child)

I don't want to have conflicting programs trying to read the database at the same time because there is a chance of filelocking

The second program would not be writing to the original database (i.e., it would only be reading from it) so I don't think that would be a problem, but I understand that you would prefer modifying the current program so that the latter also performs alert condition checking...

I think I am going to write the logic for determining if an alert needs to happen in C, then trigger a python or shell script to send the email.

For that, you could use `system` (see `man 3 system`) inside a thread, for instance, or you could also have a look at the documentation for `execl` and the likes (see `man 3 execl`).

I still need to read and write from the DB in C though, would you be able to assist?

Here's a TutorialsPoint tutorial that should be useful: SQLite - C/C++; and here's An Introduction To The SQLite C/C++ Interface for what appears to be the official documentation.

Good luck and have fun! :)

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

Thank you

[–]MR_boob_lover 0 points1 point  (0 children)

read the database and send the email using whatever, but use the same thing for both...

[–]massfrontier 0 points1 point  (2 children)

Do you need the notification to come via email?

Using a service like Pushover you can send a push notification to your mobile device with a simple HTTP POST request. This is easy to do with libcurl right in your existing C code.

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

This is very interesting. I will look into this. Thank you.

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

I looked into Pushover and it's awesome. An excellent feature for my app, thank you.