Browse Source

Add basic implementation

Ian Adam Naval 3 years ago
parent
commit
c9b63ac33d
3 changed files with 136 additions and 0 deletions
  1. 0
    0
      laundry_notifier/__init__.py
  2. 119
    0
      laundry_notifier/run.py
  3. 17
    0
      setup.py

+ 0
- 0
laundry_notifier/__init__.py View File


+ 119
- 0
laundry_notifier/run.py View File

@@ -0,0 +1,119 @@
1
+import time
2
+import datetime
3
+import smtplib
4
+import math
5
+from email.mime.text import MIMEText
6
+from datetime import datetime
7
+
8
+from microstacknode.hardware.accelerometer.mma8452q import MMA8452Q
9
+
10
+
11
+EMAIL_USERNAME = 'noreply@ianonavy.com'
12
+EMAIL_PASSWORD = 'S2PENjQbO6=cHgchw@CXs.bJ'
13
+RECIPIENT_EMAILS = [
14
+    'ianonavy@gmail.com', 'dmurvihill@gmail.com',
15
+    '5038304363@tmomail.net'
16
+]
17
+ALERT_EMAIL_TEXT = """Hi,
18
+
19
+Your laundry is done. Or maybe your roomate's. I don't know.
20
+
21
+Regretfully,
22
+Ianonavy Bot
23
+"""
24
+G_RANGE = 2
25
+INTERVAL = 0.005  # seconds
26
+WINDOW_SIZE = 40  # intervals
27
+THRESHOLD = 0.003  # G's
28
+MAX_EMAIL_FREQUENCY = 60  # seconds
29
+
30
+
31
+def average(s):
32
+    return sum(s) * 1.0 / len(s)
33
+
34
+
35
+def stdev(s):
36
+    if not s:
37
+        return 0
38
+    avg = average(list(s))
39
+    variance = map(lambda x: (x - avg) ** 2, s)
40
+    return math.sqrt(average(list(variance)))
41
+
42
+
43
+def notify_user(recipient_email_address):
44
+    print("Alerting " + recipient_email_address)
45
+
46
+    msg = MIMEText(ALERT_EMAIL_TEXT)
47
+
48
+    # me == the sender's email address
49
+    # you == the recipient's email address
50
+    msg['Subject'] = 'Laundry Finished'
51
+    msg['From'] = 'pi@localhost'
52
+    msg['To'] = recipient_email_address
53
+
54
+    # Send the message via our own SMTP server.
55
+    username = EMAIL_USERNAME
56
+    password = EMAIL_PASSWORD
57
+    server = smtplib.SMTP('smtp.gmail.com:587')
58
+    server.starttls()
59
+    server.login(username, password)
60
+    server.send_message(msg)
61
+    server.quit()
62
+
63
+
64
+def enqueue(sliding_window, item):
65
+    if len(sliding_window) == WINDOW_SIZE:
66
+        sliding_window.pop(0)
67
+    sliding_window.append(item)
68
+
69
+
70
+def amplitude_stdev(sliding_window):
71
+    standard_deviations = {}
72
+    for key in ('x', 'y', 'z'):
73
+        values = [instance[key] for instance in sliding_window]
74
+        standard_deviations[key] = stdev(values)
75
+    return standard_deviations
76
+
77
+
78
+def send_emails(last_email_sent_at):
79
+    print((datetime.now() - last_email_sent_at).seconds)  # for debugging
80
+    # limit frequency of emails
81
+    if (datetime.now() - last_email_sent_at).seconds > MAX_EMAIL_FREQUENCY:
82
+        [notify_user(email) for email in RECIPIENT_EMAILS]
83
+        return datetime.now()
84
+    return last_email_sent_at
85
+
86
+
87
+def main():
88
+    with MMA8452Q() as accelerometer:
89
+        # Configure accelerometer
90
+        accelerometer.standby()
91
+        accelerometer.set_g_range(G_RANGE)
92
+        accelerometer.activate()
93
+
94
+        # Settle
95
+        time.sleep(INTERVAL)
96
+
97
+        sliding_window = []
98
+        dryer_state = 'off'
99
+        last_email_sent_at = datetime(1970, 1, 1, 0, 0, 0)
100
+
101
+        while True:
102
+            g_values = accelerometer.get_xyz()
103
+            enqueue(sliding_window, g_values)
104
+            sliding_stdev = amplitude_stdev(sliding_window)
105
+            print(sliding_stdev, dryer_state)  # for debugging
106
+            # don't send emails right at the beginning
107
+            if g_values:
108
+                if sliding_stdev['x'] < THRESHOLD:
109
+                    if dryer_state == 'on':
110
+                        last_email_sent_at = send_emails(last_email_sent_at)
111
+                    dryer_state = 'off'
112
+                else:
113
+                    dryer_state = 'on'
114
+
115
+            time.sleep(INTERVAL)
116
+
117
+
118
+if __name__ == '__main__':
119
+    main()

+ 17
- 0
setup.py View File

@@ -0,0 +1,17 @@
1
+from distutils.core import setup
2
+
3
+description = "Raspberry Pi-based laundry notification system."
4
+
5
+setup(
6
+    name='laundry-notifier',
7
+    version='0.0.1',
8
+    author='Ian Adam Naval',
9
+    author_email='ianonavy@gmail.com',
10
+    packages=['laundry_notifier'],
11
+    scripts=[],
12
+    url='https://git.ianonavy.com/ianonavy/laundry-notifier/',
13
+    license='MIT',
14
+    description=description,
15
+    long_description=description,
16
+    install_requires=['microstackcommon', 'microstacknode'],
17
+)

Loading…
Cancel
Save