-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
224 lines (179 loc) · 8.84 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
import requests
import logging
from logging.handlers import RotatingFileHandler
import sys
from time import sleep
from datetime import datetime
from luma.led_matrix.device import max7219
from luma.core.interface.serial import spi, noop
from luma.core.render import canvas
from pont import get_ferry_ETD
from rain import get_rain
import RPi.GPIO as GPIO
# input lat & long from address here
LAT = 52.353681668987726
LNG = 4.92548286993842
UPDATE_INTERVAL = 60 * 2 # Refresh temp & ETD every 2 minutes
DISPLAY_INTERVAL = 1 # Update every second
CYCLE_TIME = 5 # show every cycle 5 seconds
HEAVY = 2.5
MOTION_SENSOR_PIN = 25 # GPIO pin number for the motion sensor
MOTION_INTERVAL = 2 * 60 # amount of time to activate the display after motion detected
# Initialize the LED matrix
def init_matrix():
serial = spi(port=0, device=0, gpio=noop())
device = max7219(serial, cascaded=4, block_orientation=-90, brightness=1)
device.contrast(0)
return device
def main():
logging.basicConfig(level=logging.INFO, format='%(asctime)s | %(levelname)s : %(message)s', handlers=[logging.handlers.RotatingFileHandler('/home/pi/python/led-it-rain/log/buien.log', maxBytes=2e6, backupCount=1), logging.StreamHandler(sys.stdout)])
logging.info('Started')
device = init_matrix()
GPIO.setmode(GPIO.BCM)
GPIO.setup(MOTION_SENSOR_PIN, GPIO.IN)
last_update_time = None
last_motion_time = datetime.now()
last_motion_state = True
try:
while True:
current_time = datetime.now()
# log only when motion state changes, always update time
current_motion_state = GPIO.input(MOTION_SENSOR_PIN)
if current_motion_state != last_motion_state:
last_motion_state = current_motion_state
if current_motion_state:
logging.info('Motion detected')
if current_motion_state:
last_motion_time = datetime.now()
if not last_motion_time or (current_time - last_motion_time).total_seconds() \
< MOTION_INTERVAL:
if not last_update_time or \
(current_time - last_update_time).total_seconds() \
> UPDATE_INTERVAL:
# get ferry ETD
if 7 <= current_time.hour <= 9 and current_time.weekday() < 5: # or True:
ETD = get_ferry_ETD()
else:
ETD = None
# get weather data
temp = get_temp(LAT, LNG)
rain = get_rain(LAT, LNG)
last_update_time = current_time
device.show()
update_display(device, temp, ETD, rain)
sleep(DISPLAY_INTERVAL)
else:
# Clear the display outside the specified time window
device.hide()
# check sensor again in 0.5 seconds
sleep(0.5)
except KeyboardInterrupt:
pass
finally:
# Clear the display when exiting the script
GPIO.cleanup()
with canvas(device) as draw:
device.hide()
logging.info('Stopped weatherdisplay')
def update_display(device, temp, ETD, rain):
with canvas(device) as draw:
if ETD is None or int(datetime.now().second / CYCLE_TIME) % 2 == 0:
#draw weather
if rain is not None:
for xpos, level in enumerate(rain):
draw.line((xpos, 8-level, xpos, 8), fill="white")
# draw temp
if temp is not None:
if len(temp) == 1:
draw_digit(temp, draw, 27)
elif len(temp) == 2:
draw_digit(temp[0], draw, 25)
draw_digit(temp[1], draw, 29)
else: # double digit freezing -- show min min
draw_digit('-', draw, 25)
draw_digit('-', draw, 29)
else:
if ETD is not None:
now = datetime.now()
diff = ETD - now
minutes, seconds = divmod(abs(diff.total_seconds()), 60)
time_remaining = "{:02d}:{:02d}".format(int(minutes), int(seconds))
offset = 7
draw_digit(time_remaining[0], draw, offset)
draw_digit(time_remaining[1], draw, offset+4)
draw_digit(time_remaining[2], draw, offset+8) # this is the colon, only 3 wide
draw_digit(time_remaining[3], draw, offset+10)
draw_digit(time_remaining[4], draw, offset+14)
def get_temp(lat, lng):
# pings openwheather API to get current temparature
# see also https://openweathermap.org/current
#return '-13'
key = '78efb78287a0d947d2bf4726b4bb6f60'
url = f'https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lng}&appid={key}&units=metric'
try:
r = requests.get(url)
except Exception as e:
logging.error(f'Could not connect to openwheather: {e}')
return None
temp = str(round(r.json()['main']['temp']))
logging.info(f'Retrieved temp data from openweather')
return temp
def draw_digit(digit, draw, offset=0):
# prints a digit of width 3 and height 8 with offset [offset] to [draw]
if digit == '0':
draw.line((offset, 0, offset+2, 0), fill=255) # links-rechts boven
draw.line((offset, 7, offset+2, 7), fill=255) # links-rechts onder
draw.line((offset, 0, offset, 7), fill=255) # links onder-boven
draw.line((offset+2, 0, offset+2, 7), fill=255) # rechts onder-boven
if digit == '1':
draw.line((offset+2, 0, offset+2, 7), fill=255) # rechts onder-boven
if digit == '2':
draw.line((offset, 0, offset+2, 0), fill=255) # links-rechts boven
draw.line((offset, 7, offset+2, 7), fill=255) # links-rechts onder
draw.line((offset, 3, offset+2, 3), fill=255) # links-rechts mid
draw.line((offset, 3, offset, 7), fill=255) # links mid-onder
draw.line((offset+2, 0, offset+2, 3), fill=255) # rechts mid-boven
if digit == '3':
draw.line((offset+2, 0, offset+2, 7), fill=255) # rechts onder-boven
draw.line((offset, 0, offset+2, 0), fill=255) # links-rechts boven
draw.line((offset, 7, offset+2, 7), fill=255) # links-rechts onder
draw.line((offset, 3, offset+2, 3), fill=255) # links-rechts mid
if digit == '4':
draw.line((offset, 3, offset+2, 3), fill=255) # links-rechts mid
draw.line((offset+2, 0, offset+2, 7), fill=255) # rechts onder-boven
draw.line((offset, 0, offset, 3), fill=255) # links mid-boven
if digit == '5':
draw.line((offset, 0, offset+2, 0), fill=255) # links-rechts boven
draw.line((offset, 7, offset+2, 7), fill=255) # links-rechts onder
draw.line((offset, 3, offset+2, 3), fill=255) # links-rechts mid
draw.line((offset, 0, offset, 3), fill=255) # links mid-boven
draw.line((offset+2, 3, offset+2, 7), fill=255) # rechts mid-onder
if digit == '6':
draw.line((offset, 0, offset+2, 0), fill=255) # links-rechts boven
draw.line((offset, 7, offset+2, 7), fill=255) # links-rechts onder
draw.line((offset, 3, offset+2, 3), fill=255) # links-rechts mid
draw.line((offset+2, 3, offset+2, 7), fill=255) # rechts mid-onder
draw.line((offset, 0, offset, 7), fill=255) # links onder-boven
if digit == '7':
draw.line((offset+2, 0, offset+2, 7), fill=255) # rechts onder-boven
draw.line((offset, 0, offset+2, 0), fill=255) # links-rechts boven
if digit == '8':
draw.line((offset, 0, offset+2, 0), fill=255) # links-rechts boven
draw.line((offset, 7, offset+2, 7), fill=255) # links-rechts onder
draw.line((offset, 0, offset, 7), fill=255) # links onder-boven
draw.line((offset+2, 0, offset+2, 7), fill=255) # rechts onder-boven
draw.line((offset, 3, offset+2, 3), fill=255) # links-rechts mid
if digit == '9':
draw.line((offset, 0, offset+2, 0), fill=255) # links-rechts boven
draw.line((offset, 7, offset+2, 7), fill=255) # links-rechts onder
draw.line((offset, 3, offset+2, 3), fill=255) # links-rechts mid
draw.line((offset+2, 0, offset+2, 7), fill=255) # rechts onder-boven
draw.line((offset, 0, offset, 3), fill=255) # links mid-boven
if digit == '-':
draw.line((offset+1, 3, offset+2, 3), fill=255) # links-rechts mid
if digit == ':':
draw.line((offset, 2, offset, 2), fill=255) # links-rechts mid
draw.line((offset, 4, offset, 4), fill=255) # links-rechts mid
return draw
if __name__ == "__main__":
main()