|
1 | 1 | import time
|
2 | 2 | import random
|
| 3 | +import audioio |
3 | 4 | import board
|
4 | 5 | import busio
|
5 | 6 | from digitalio import DigitalInOut
|
| 7 | +import digitalio |
6 | 8 | import neopixel
|
7 | 9 | from adafruit_esp32spi import adafruit_esp32spi
|
8 | 10 | from adafruit_esp32spi import adafruit_esp32spi_wifimanager
|
9 | 11 | import adafruit_fancyled.adafruit_fancyled as fancy
|
10 | 12 |
|
11 | 13 | print("ESP32 Open Weather API demo")
|
12 | 14 |
|
13 |
| -# Use cityname, country code where countrycode is ISO3166 format. |
14 |
| -# E.g. "New York, US" or "London, GB" |
15 |
| -LOCATION = "Manhattan, US" |
| 15 | +button = digitalio.DigitalInOut(board.A1) |
| 16 | +button.switch_to_input(pull=digitalio.Pull.UP) |
| 17 | + |
| 18 | +wave_file = open("sound/Rain.wav", "rb") |
| 19 | +wave = audioio.WaveFile(wave_file) |
| 20 | +audio = audioio.AudioOut(board.A0) |
| 21 | + |
16 | 22 |
|
17 | 23 | # Get wifi details and more from a secrets.py file
|
18 | 24 | try:
|
|
21 | 27 | print("WiFi secrets are kept in secrets.py, please add them there!")
|
22 | 28 | raise
|
23 | 29 |
|
| 30 | +# Use cityname, country code where countrycode is ISO3166 format. |
| 31 | +# E.g. "New York, US" or "London, GB" |
| 32 | +LOCATION = secrets['timezone'] |
| 33 | + |
24 | 34 | # Set up where we'll be fetching data from
|
25 |
| -DATA_SOURCE = "http://api.openweathermap.org/data/2.5/weather?q="+LOCATION |
| 35 | +DATA_SOURCE = "http://api.openweathermap.org/data/2.5/weather?q="+secrets['timezone'] |
26 | 36 | DATA_SOURCE += "&appid="+secrets['openweather_token']
|
27 | 37 |
|
28 | 38 | # If you are using a board with pre-defined ESP32 Pins:
|
|
32 | 42 |
|
33 | 43 | spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
|
34 | 44 | esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
|
35 |
| -status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) # Uncomment for Most Boards |
| 45 | +status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) # Uncomment for Most Boards |
36 | 46 | wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
|
37 |
| -pixels = neopixel.NeoPixel(board.D2, 16, brightness=1.0, auto_write=False) |
| 47 | +pixels = neopixel.NeoPixel(board.D2, 150, brightness=1.0, auto_write=False) |
38 | 48 | pixels.fill(0x050505)
|
39 | 49 | pixels.show()
|
40 | 50 |
|
41 | 51 | # clouds palette
|
42 |
| -cloudy_palette = [fancy.CRGB(1.0, 1.0, 1.0), # White |
43 |
| - fancy.CRGB(0.5, 0.5, 0.5), # gray |
44 |
| - fancy.CRGB(0.5, 0.5, 1.0)] # blue-gray |
| 52 | +cloudy_palette = [fancy.CRGB(1.0, 1.0, 1.0), # White |
| 53 | + fancy.CRGB(0.5, 0.5, 0.5), # gray |
| 54 | + fancy.CRGB(0.5, 0.5, 1.0)] # blue-gray |
45 | 55 | # sunny palette
|
46 |
| -sunny_palette = [fancy.CRGB(1.0, 1.0, 1.0), # White |
47 |
| - fancy.CRGB(1.0, 1.0, 0.0),# Yellow |
48 |
| - fancy.CRGB(1.0, 0.5, 0.0),] # Orange |
| 56 | +sunny_palette = [fancy.CRGB(1.0, 1.0, 1.0), # White |
| 57 | + fancy.CRGB(1.0, 1.0, 0.0), # Yellow |
| 58 | + fancy.CRGB(1.0, 0.5, 0.0), ] # Orange |
49 | 59 | # thunderstorm palette
|
50 |
| -thunder_palette = [fancy.CRGB(0.0, 0.0, 1.0), # blue |
51 |
| - fancy.CRGB(0.5, 0.5, 0.5), # gray |
52 |
| - fancy.CRGB(0.5, 0.5, 1.0)] # blue-gray |
| 60 | +thunder_palette = [fancy.CRGB(0.0, 0.0, 1.0), # blue |
| 61 | + fancy.CRGB(0.5, 0.5, 0.5), # gray |
| 62 | + fancy.CRGB(0.5, 0.5, 1.0)] # blue-gray |
53 | 63 | last_thunder_bolt = None
|
54 | 64 |
|
55 | 65 | palette = None # current palette
|
56 | 66 | pal_offset = 0 # Positional offset into color palette to get it to 'spin'
|
57 | 67 | levels = (0.25, 0.3, 0.15) # Color balance / brightness for gamma function
|
58 | 68 | raining = False
|
| 69 | +snowing = False |
59 | 70 | thundering = False
|
| 71 | +has_sound = False |
60 | 72 |
|
61 | 73 | weather_refresh = None
|
62 | 74 | weather_type = None
|
| 75 | +button_mode = 4 |
| 76 | +button_select = False |
| 77 | + |
| 78 | +cloud_on = True |
| 79 | + |
63 | 80 | while True:
|
| 81 | + if not button.value: |
| 82 | + button_mode = button_mode + 1 |
| 83 | + print("Button Pressed") |
| 84 | + if button_mode > 4: |
| 85 | + button_mode = 0 |
| 86 | + print("Mode is:", button_mode) |
| 87 | + pressed_time = time.monotonic() |
| 88 | + button_select = True |
| 89 | + weather_refresh = None |
| 90 | + while not button.value: # Debounce |
| 91 | + audio.stop() |
| 92 | + if (time.monotonic() - pressed_time) > 4: |
| 93 | + print("Turning OFF") |
| 94 | + cloud_on = False |
| 95 | + pixels.fill(0x000000) # bright white! |
| 96 | + pixels.show() |
| 97 | + while not cloud_on: |
| 98 | + while not button.value: # Debounce |
| 99 | + pass |
| 100 | + if not button.value: |
| 101 | + pressed_time = time.monotonic() |
| 102 | + print("Button Pressed") |
| 103 | + cloud_on = True |
| 104 | + button_select = False |
| 105 | + weather_refresh = None |
| 106 | + |
| 107 | + if button_mode == 0: |
| 108 | + weather_type = 'Sunny' |
| 109 | + if button_mode == 1: |
| 110 | + weather_type = 'Clouds' |
| 111 | + if button_mode == 2: |
| 112 | + weather_type = 'Rain' |
| 113 | + if button_mode == 3: |
| 114 | + weather_type = 'Thunderstorm' |
| 115 | + if button_mode == 4: |
| 116 | + weather_type = 'Snow' |
| 117 | + |
64 | 118 | # only query the weather every 10 minutes (and on first run)
|
65 | 119 | if (not weather_refresh) or (time.monotonic() - weather_refresh) > 600:
|
66 | 120 | try:
|
67 |
| - response = wifi.get(DATA_SOURCE).json() |
68 |
| - print("Response is", response) |
69 |
| - weather_type = response['weather'][0]['main'] |
70 |
| - weather_type = 'Thunderstorm' # manually adjust weather type for testing! |
71 |
| - |
72 |
| - print(weather_type) # See https://openweathermap.org/weather-conditions |
| 121 | + if not button_select: |
| 122 | + response = wifi.get(DATA_SOURCE).json() |
| 123 | + print("Response is", response) |
| 124 | + weather_type = response['weather'][0]['main'] |
| 125 | + if weather_type == 'Clear': |
| 126 | + weather_type = 'Sunny' |
| 127 | + print(weather_type) # See https://openweathermap.org/weather-conditions |
73 | 128 | # default to no rain or thunder
|
74 |
| - raining = thundering = False |
| 129 | + raining = snowing = thundering = has_sound = False |
| 130 | + if weather_type == 'Sunny': |
| 131 | + palette = sunny_palette |
| 132 | + wave_file = open("sound/Clear.wav", "rb") |
| 133 | + wave = audioio.WaveFile(wave_file) |
| 134 | + has_sound = True |
75 | 135 | if weather_type == 'Clouds':
|
76 | 136 | palette = cloudy_palette
|
| 137 | + wave_file = open("sound/Clouds.wav", "rb") |
| 138 | + wave = audioio.WaveFile(wave_file) |
| 139 | + has_sound = True |
77 | 140 | if weather_type == 'Rain':
|
78 | 141 | palette = cloudy_palette
|
| 142 | + wave_file = open("sound/Rain.wav", "rb") |
| 143 | + wave = audioio.WaveFile(wave_file) |
79 | 144 | raining = True
|
80 |
| - if weather_type == 'Sunny': |
81 |
| - palette = sunny_palette |
| 145 | + has_sound = True |
82 | 146 | if weather_type == 'Thunderstorm':
|
83 | 147 | palette = thunder_palette
|
84 | 148 | raining = thundering = True
|
| 149 | + has_sound = True |
85 | 150 | # pick next thunderbolt time now
|
86 | 151 | next_bolt_time = time.monotonic() + random.randint(1, 5)
|
| 152 | + if weather_type == 'Snow': |
| 153 | + palette = cloudy_palette |
| 154 | + wave_file = open("sound/Snow.wav", "rb") |
| 155 | + wave = audioio.WaveFile(wave_file) |
| 156 | + snowing = True |
| 157 | + has_sound = True |
87 | 158 | weather_refresh = time.monotonic()
|
88 | 159 | except RuntimeError as e:
|
89 | 160 | print("Some error occured, retrying! -", e)
|
90 | 161 | time.sleep(5)
|
91 | 162 | continue
|
92 | 163 |
|
| 164 | + if not audio.playing and has_sound: |
| 165 | + if not thundering: |
| 166 | + audio.play(wave) |
| 167 | + |
93 | 168 | if palette:
|
94 | 169 | for i in range(len(pixels)):
|
95 | 170 | color = fancy.palette_lookup(palette, pal_offset + i / len(pixels))
|
|
100 | 175 |
|
101 | 176 | if raining:
|
102 | 177 | # don't have a droplet every time
|
103 |
| - if random.randint(0, 25) == 0: # 1 out of 25 times |
| 178 | + for i in range(random.randint(1, 5)): # up to 3 times... |
| 179 | + pixels[random.randint(0, len(pixels)-1)] = 0x0000FF # make a random pixel Blue |
| 180 | + pixels.show() |
| 181 | + |
| 182 | + if snowing: |
| 183 | + # don't have a droplet every time |
| 184 | + for i in range(random.randint(1, 5)): # up to 3 times... |
104 | 185 | pixels[random.randint(0, len(pixels)-1)] = 0xFFFFFF # make a random pixel white
|
105 |
| - pixels.show() |
| 186 | + pixels.show() |
106 | 187 |
|
107 | 188 | # if its time for a thunderbolt
|
108 | 189 | if thundering and (time.monotonic() > next_bolt_time):
|
109 | 190 | print("Ka Bam!")
|
110 | 191 | # fill pixels white, delay, a few times
|
111 | 192 | for i in range(random.randint(1, 3)): # up to 3 times...
|
112 |
| - pixels.fill(0xFFFFFF) # bright white! |
| 193 | + pixels.fill(0xFFFFFF) # bright white! |
113 | 194 | pixels.show()
|
114 |
| - time.sleep(random.uniform(0.01, 0.2)) # pause |
115 |
| - pixels.fill(0x0F0F0F) # gray |
| 195 | + time.sleep(random.uniform(0.01, 0.2)) # pause |
| 196 | + pixels.fill(0x0F0F0F) # gray |
116 | 197 | pixels.show()
|
117 |
| - time.sleep(random.uniform(0.01, 0.3)) # pause |
| 198 | + time.sleep(random.uniform(0.01, 0.3)) # pause |
118 | 199 | # pick next thunderbolt time now
|
119 |
| - next_bolt_time = time.monotonic() + random.randint(5, 15) # between 5 and 15 s |
| 200 | + Thunder = random.randint(0, 2) |
| 201 | + if Thunder == 0: |
| 202 | + wave_file = open("sound/Thunderstorm0.wav", "rb") |
| 203 | + elif Thunder == 1: |
| 204 | + wave_file = open("sound/Thunderstorm1.wav", "rb") |
| 205 | + elif Thunder == 2: |
| 206 | + wave_file = open("sound/Thunderstorm2.wav", "rb") |
| 207 | + wave = audioio.WaveFile(wave_file) |
| 208 | + audio.play(wave) |
| 209 | + next_bolt_time = time.monotonic() + random.randint(5, 15) # between 5 and 15 s |
0 commit comments