Looks like your smtp server hangs if you try to connect to it using SSL.
Try this version.

-tk

On Sat, Jan 5, 2019 at 5:23 PM <[email protected]> wrote:

> As requested.
>
>
>
> Thanks for helping.
>
>
>
> Tom
>
>
>
> *From:* [email protected] <[email protected]> *On
> Behalf Of *Thomas Keffer
> *Sent:* Saturday, January 5, 2019 6:58 PM
> *To:* weewx-user <[email protected]>
> *Subject:* Re: [weewx-user] Re: Alarm.py Help
>
>
>
> Hmmm. Try this version. It has been heavily instrumented. Again, run with
> debug=1. Make sure you restart WeeWX.
>
>
>
> -tk
>
>
>
> On Sat, Jan 5, 2019 at 4:46 PM <[email protected]> wrote:
>
> I used the alarm.py version that you sent the link to.  I attached it
> along with the syslog.  I am not using an SSL connection.  Still nothing.
> I  did notice an error when I quit weewx this time.
>
>
> On Saturday, January 5, 2019 at 12:20:32 PM UTC-6, [email protected]
> wrote:
>
> I set up alarm.py per the instructions (I think).  I wanted to test an
> alarm so I set it for expression= "outTemp > 40".  When I run weewx I get
>
>
>
> alarm: Alarm set for expression: 'outTemp > 40.0'
>
>
>
> alarm: Alarm expression "outTemp > 40.0" evaluated True at 2019-01-05
> 11:15:00 CST (1546708500)
>
>
>
> This is what I would expect however nothing else happens.  I looked in the
> syslog file and there is no mention of the mail being sent or an smtp
> error.   Also there were no other entries stating the expression was true.
>
>
>
> I waited one hour and again got this but no other entries in syslog.
>
>
>
> Jan  5 12:16:16 raspberrypi weewx[5473]: alarm: Alarm expression "outTemp
> > 40.0" evaluated True at 2019-01-05 12:16:00 CST (1546712160)
>
>
>
>
>
> I am using a Raspberry Pi.
>
>
>
> Thanks,
>
>
>
> Tom
>
>
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "weewx-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout
> <https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgroups.google.com%2Fd%2Foptout&data=02%7C01%7C%7C851915cd0bf34e742e4b08d6737201e7%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636823330819558567&sdata=eMsVIQ0jZ4HNJLT2gzkmhUZgjeyoI0KlBSalpEOGTRI%3D&reserved=0>
> .
>
> --
> You received this message because you are subscribed to the Google Groups
> "weewx-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout
> <https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgroups.google.com%2Fd%2Foptout&data=02%7C01%7C%7C851915cd0bf34e742e4b08d6737201e7%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C636823330819558567&sdata=eMsVIQ0jZ4HNJLT2gzkmhUZgjeyoI0KlBSalpEOGTRI%3D&reserved=0>
> .
>
> --
> You received this message because you are subscribed to the Google Groups
> "weewx-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"weewx-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
#    Copyright (c) 2009-2019 Tom Keffer <[email protected]>
#    See the file LICENSE.txt for your rights.

"""Example of how to implement an alarm in weewx. 

*******************************************************************************

To use this alarm, add the following to the weewx configuration file:

[Alarm]
    expression = "outTemp < 40.0"
    time_wait = 3600
    smtp_host = smtp.example.com
    smtp_user = myusername
    smtp_password = mypassword
    from = [email protected]
    mailto = [email protected], [email protected]
    subject = "Alarm message from weewx!"
  
In this example, if the outside temperature falls below 40, it will send an
email to the users specified in the comma separated list specified in option
"mailto", in this case:

[email protected], [email protected]

The example assumes an SMTP email server at smtp.example.com that requires
login.  If the SMTP server does not require login, leave out the lines for
smtp_user and smtp_password.

Setting an email "from" is optional. If not supplied, one will be filled in,
but your SMTP server may or may not accept it.

Setting an email "subject" is optional. If not supplied, one will be filled in.

To avoid a flood of emails, one will only be sent every 3600 seconds (one
hour).

*******************************************************************************

To enable this service:

1) copy this file to the user directory

2) modify the weewx configuration file by adding this service to the option
"report_services", located in section [Engine][[Services]].

[Engine]
  [[Services]]
    ...
    report_services = weewx.engine.StdPrint, weewx.engine.StdReport, user.alarm.MyAlarm

*******************************************************************************

If you wish to use both this example and the lowBattery.py example, simply
merge the two configuration options together under [Alarm] and add both
services to report_services.

*******************************************************************************
"""

import time
import smtplib
from email.mime.text import MIMEText
import threading
import syslog
import socket

import weewx
from weewx.engine import StdService
from weeutil.weeutil import timestamp_to_string, option_as_list


# Inherit from the base class StdService:
class MyAlarm(StdService):
    """Service that sends email if an arbitrary expression evaluates true"""
    
    def __init__(self, engine, config_dict):
        # Pass the initialization information on to my superclass:
        super(MyAlarm, self).__init__(engine, config_dict)
        
        # This will hold the time when the last alarm message went out:
        self.last_msg_ts = 0
        
        try:
            # Dig the needed options out of the configuration dictionary.
            # If a critical option is missing, an exception will be raised and
            # the alarm will not be set.
            self.expression    = config_dict['Alarm']['expression']
            self.time_wait     = int(config_dict['Alarm'].get('time_wait', 3600))
            self.smtp_host     = config_dict['Alarm']['smtp_host']
            self.smtp_user     = config_dict['Alarm'].get('smtp_user')
            self.smtp_password = config_dict['Alarm'].get('smtp_password')
            self.SUBJECT       = config_dict['Alarm'].get('subject', "Alarm message from weewx")
            self.FROM          = config_dict['Alarm'].get('from', '[email protected]')
            self.TO            = option_as_list(config_dict['Alarm']['mailto'])
            self.timeout       = int(config_dict['Alarm'].get('timeout', 20))
            syslog.syslog(syslog.LOG_INFO, "alarm: Alarm set for expression: '%s'" % self.expression)
            
            # If we got this far, it's ok to start intercepting events:
            self.bind(weewx.NEW_ARCHIVE_RECORD, self.newArchiveRecord)    # NOTE 1
        except KeyError as e:
            syslog.syslog(syslog.LOG_INFO, "alarm: No alarm set.  Missing parameter: %s" % e)
            
    def newArchiveRecord(self, event):
        """Gets called on a new archive record event."""
        
        # To avoid a flood of nearly identical emails, this will do
        # the check only if we have never sent an email, or if we haven't
        # sent one in the last self.time_wait seconds:
        if not self.last_msg_ts or abs(time.time() - self.last_msg_ts) >= self.time_wait:
            # Get the new archive record:
            record = event.record
            
            # Be prepared to catch an exception in the case that the expression contains 
            # a variable that is not in the record:
            try:                                                              # NOTE 2
                # Evaluate the expression in the context of the event archive record.
                # Sound the alarm if it evaluates true:
                if eval(self.expression, None, record):                       # NOTE 3
                    # Sound the alarm!
                    # Launch in a separate thread so it doesn't block the main LOOP thread:
                    t  = threading.Thread(target=MyAlarm.soundTheAlarm, args=(self, record))
                    t.start()
                    # Record when the message went out:
                    self.last_msg_ts = time.time()
            except NameError as e:
                # The record was missing a named variable. Write a debug message, then keep going
                syslog.syslog(syslog.LOG_DEBUG, "alarm: %s" % e)

    def soundTheAlarm(self, rec):
        """This function is called when the given expression evaluates True."""
        
        # Get the time and convert to a string:
        t_str = timestamp_to_string(rec['dateTime'])

        # Log it
        syslog.syslog(syslog.LOG_INFO, 'alarm: Alarm expression "%s" evaluated True at %s' % (self.expression, t_str))

        # Form the message text:
        msg_text = 'Alarm expression "%s" evaluated True at %s\nRecord:\n%s' % (self.expression, t_str, str(rec))
        # Convert to MIME:
        msg = MIMEText(msg_text)
        
        # Fill in MIME headers:
        msg['Subject'] = self.SUBJECT
        msg['From']    = self.FROM
        msg['To']      = ','.join(self.TO)

        syslog.syslog(syslog.LOG_DEBUG, "alarm: Formed MIME msg")
        
        try:
            # First try end-to-end encryption
            syslog.syslog(syslog.LOG_DEBUG, "alarm: trying SMTP_SSL connection")
            s = smtplib.SMTP_SSL(self.smtp_host, timeout=self.timeout)
            syslog.syslog(syslog.LOG_DEBUG, "alarm: using SMTP_SSL")
        except (AttributeError, socket.timeout):
            syslog.syslog(syslog.LOG_DEBUG, "alarm: unable to use SMTP_SSL connection.")
            # If that doesn't work, try creating an insecure host, then upgrading
            s = smtplib.SMTP(self.smtp_host, timeout=self.timeout)
            try:
                syslog.syslog(syslog.LOG_DEBUG, "alarm: attempting upgrade.")
                # Be prepared to catch an exception if the server
                # does not support encrypted transport.
                s.ehlo()
                s.starttls()
                s.ehlo()
                syslog.syslog(syslog.LOG_DEBUG,
                              "alarm: using SMTP encrypted transport")
            except smtplib.SMTPException:
                syslog.syslog(syslog.LOG_DEBUG,
                              "alarm: using SMTP unencrypted transport")

        try:
            # If a username has been given, assume that login is required for this host:
            if self.smtp_user:
                syslog.syslog(syslog.LOG_DEBUG, "alarm: attempting login")
                s.login(self.smtp_user, self.smtp_password)
                syslog.syslog(syslog.LOG_DEBUG, "alarm: logged in with user name %s" % (self.smtp_user,))
            else:
                syslog.syslog(syslog.LOG_DEBUG, "alarm: no user given, so no login attempted")
            
            # Send the email:
            s.sendmail(msg['From'], self.TO,  msg.as_string())
            # Log out of the server:
            s.quit()
        except Exception as e:
            syslog.syslog(syslog.LOG_ERR, "alarm: SMTP mailer refused message with error %s" % (e,))
            raise
        
        # Log sending the email:
        syslog.syslog(syslog.LOG_INFO, "alarm: email sent to: %s" % self.TO)


if __name__ == '__main__':
    """This section is used for testing the code. """
    import sys
    import configobj
    from optparse import OptionParser

    usage_string = """Usage: 
    
    alarm.py config_path 
    
    Arguments:
    
      config_path: Path to weewx.conf"""
    parser = OptionParser(usage=usage_string)
    (options, args) = parser.parse_args()
    
    if len(args) < 1:
        sys.stderr.write("Missing argument(s).\n")
        sys.stderr.write(parser.parse_args(["--help"]))
        exit()
        
    config_path = args[0]
    
    weewx.debug = 1
    
    try:
        config_dict = configobj.ConfigObj(config_path, file_error=True)
    except IOError:
        print "Unable to open configuration file ", config_path
        exit()
        
    if 'Alarm' not in config_dict:
        print >>sys.stderr, "No [Alarm] section in the configuration file %s" % config_path
        exit(1)
    
    engine = None
    alarm = MyAlarm(engine, config_dict)
    
    rec = {'extraTemp1': 1.0,
           'outTemp'   : 38.2,
           'dateTime'  : int(time.time())}

    event = weewx.Event(weewx.NEW_ARCHIVE_RECORD, record=rec)
    alarm.newArchiveRecord(event)

Reply via email to