from machine import Pin, I2C, RTC, Timer
import ssd1306
import network
import socket
import ntptime
import urequests
import json
import neopixel
import utime
import time
import math
def neo_red():
for i in range(ring_size):
neo[i] = (255, 0, 0)
neo.write()
# new pixel ring yellow
def neo_yellow():
for i in range(ring_size):
neo[i] = (255, 255, 0)
neo.write()
def neo_off():
for i in range(ring_size):
neo[i] = (0,0,0)
neo.write()
def irq_handler(pin):
global isFlashing
if isFlashing:
timer1.deinit()
neo_off()
isFlashing = False
print("button pressed")
# degrees to radians
def rad(deg):
return deg*(math.pi/180)
obsTime = 0
refreshMetar = False
metar = None
global isFlashing
isFlashing = True
button = Pin(12, Pin.IN, Pin.PULL_UP)
button.irq(trigger=Pin.IRQ_RISING, handler=irq_handler)
# led pin assignment, turn them all on on boot for 500ms then off
# just to make sure they are working
redLed = Pin(26, Pin.OUT)
yellowLed = Pin(27, Pin.OUT)
greenLed = Pin(14, Pin.OUT)
redLed.on()
yellowLed.on()
greenLed.on()
time.sleep_ms(500)
redLed.off()
yellowLed.off()
greenLed.off()
# ESP32 Pin assignment for I2C
# and set up of SSD1306 Oled
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
# this is for debugging, can call this on python command line
def setWdir(dir):
global metar
if metar:
metar[0]['wdir'] = dir
def update_oled(wifi, ntp, met, clock):
oled.fill(0);
row1 = f"Wifi:{wifi} NTP:{ntp}"
oled.text(row1, 0, 0)
if met:
global obsTime
id = met[0]['icaoId']
obs = met[0]['obsTime']
obsTime = obs
reportTime = met[0]['reportTime']
wdir = met[0]['wdir']
wspd = met[0]['wspd']
temp = met[0]['temp']
wx = met[0]['wxString']
qnh = met[0]['altim']
t = time.gmtime(obs)
h = t[3]
m = t[4]
row2 = f"ID:{id} SA:{h:02d}{m:02d}"
oled.text(row2, 0, 8)
row3 = f"Wdir:{wdir:03d} Wspd:{wspd:02d}"
oled.text(row3, 0, 16)
row4 = f"Temp:{temp:02d} QNH:{qnh:04d}"
oled.text(row4, 0, 24)
row5 = f"Wx:{wx}"
oled.text(row5, 0, 32)
x = round(math.cos(rad(abs(runway-wdir))), 4)
hw = round(wspd*x, 0)
y = round(math.sin(rad(abs(runway-wdir))), 4)
xw = abs(round(wspd*y))
row6 = f"HW:{hw:03.0f} XW:{xw:02.0f}"
oled.text(row6, 0, 40)
if x < 0:
if not redLed.value():
activateFlash("red")
redLed.on()
yellowLed.off()
greenLed.off()
if x == 0:
if not yellowLed.value():
activateFlash("yellow")
yellowLed.on()
redLed.off()
greenLed.off()
if x > 0:
greenLed.on()
redLed.off()
yellowLed.off()
else:
oled.text("ID:**** SA:****", 0, 8)
oled.text("Wdir:*** Wspd:**", 0, 16)
oled.text("Temp:** QNH:****", 0, 24)
oled.text("Wx: ****", 0, 32)
oled.text("HW:*** XW:**", 0, 40)
oled.text("UTC:", 0, 48)
if clock:
h = clock[4]
m = clock[5]
s = clock[6]
t = f"UTC:{h:02d}:{m:02d}:{s:02d}"
oled.text(t, 0, 48)
oled.show()
def OnSec(t):
clock = rtc.datetime()
global metar
update_oled("ON", "SY", metar, clock)
m = clock[5]
s = clock[6]
if (m==55 and s==0) or (m==25 and s==0):
ntptime.settime()
print("time synced")
if (m==5 and s==0) or (m==35 and s==0):
global refreshMetar
refreshMetar = True
if refreshMetar and s==0:
print("udateing Metar")
r = urequests.get("https://aviationweather.gov/api/data/metar?ids=VABB&format=json&taf=false", timeout=15)
new_metar = json.loads(r.text)
if new_metar[0]['obsTime'] > obsTime:
print(f"metar now:{new_metar[0]['obsTime']} old time:{obsTime}")
update_oled("ON", "SY", new_metar, None)
global refreshMetar
refreshMetar = False
metar = new_metar
print("metar updated")
else:
print("same obs time of metar")
global toggle
global neo_color
neo_color = "black"
toggle = False
def onFlash(t):
global toggle
toggle = not toggle
if toggle:
if neo_color == "red":
neo_red()
if neo_color == "yellow":
neo_yellow()
else:
neo_off()
def activateFlash(color):
global isFlashing
global neo_color
neo_color = color
print(neo_color)
isFlashing = True
timer1.init(period=300, mode=Timer.PERIODIC, callback=onFlash)
update_oled("OF", "OF", None, None)
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('Wokwi-GUEST', '')
if not wlan.isconnected():
print('connecting to network...')
while not wlan.isconnected():
pass
update_oled("ON", "OF", None, None)
# set the clock to UTC via NTP
rtc = RTC()
ntptime.host = 'pool.ntp.org'
ntptime.timeout = 5
try:
ntptime.settime()
update_oled("ON", "SY", None, None)
except:
update_oled("ON", "OF", None, None)
print("ntp error")
print(rtc.datetime())
# get VABB Metar
runway = 270
r = urequests.get("https://aviationweather.gov/api/data/metar?ids=VABB&format=json&taf=false", timeout=15)
metar = json.loads(r.text)
if metar:
print(metar[0]['icaoId'])
print(metar[0]['temp'])
obsTime = metar[0]['obsTime']
update_oled("ON", "SY", metar, None)
# set up neopixel of 16 led ring
ring_size = 16
neo = neopixel.NeoPixel(Pin(19), ring_size)
# every 1 sec to update display, update clock via ntp, update metar every 30 min
timer0 = Timer(0)
timer0.init(period=1000, mode=Timer.PERIODIC, callback=OnSec)
# every 300 ms for running the neopixel if req
timer1 = Timer(1)