import micropython
from usocket import socket
from machine import Pin,WIZNET_PIO_SPI
import urequests
import network
import time
import json
import math
import time
from neopixel import Neopixel
from machine import Timer

# Our current location.
# This needs changing to your location before saving the firmware
mylat = 55.0
mylon = -1.5

# Create an interface for the addressable LEDs
numpix = 6
pixels = Neopixel(numpix, 0, 28, "GRB")
pixels.brightness(50)

# A global verable to store the curent "pulse" rate
speed = 0

# A function ti init the W5x00 chip
def w5x00_init():
    print("Connecting...", end='')
    spi = WIZNET_PIO_SPI(baudrate=31_250_000, mosi=Pin(23),miso=Pin(22),sck=Pin(21)) #W55RP20 PIO_SPI
    nic = network.WIZNET5K(spi,Pin(20),Pin(25)) #spi,cs,reset pin
    nic.active(True)
    
    # None DHCP
    # Comment out this section and change addresses if you are using DHCP
    # nic.ifconfig(('192.168.1.100','255.255.255.0','192.168.1.254','8.8.8.8'))
    
    # DHCP setup
    # Comment out this section if you are using fixed IP address
    nic.ifconfig('dhcp')
    print('IP address :', nic.ifconfig())
    
    # Wait for us to connect to the netowrk
    while not nic.isconnected():
        time.sleep(1)
        print('.', end='')
    print("Connected.")

# A function to calculate the distance (in Km) between two locations
def calcdist(lat1, lon1, lat2, lon2):
    radius = 6371 # km

    dlat = math.radians(lat2-lat1)
    dlon = math.radians(lon2-lon1)
    a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \
        * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
    d = radius * c

    return d

# A function to retrieve the ISS locarion from the wheretheiss API and return who far away it is
def request_wheretheiss(timer):
    r = urequests.get('https://api.wheretheiss.at/v1/satellites/25544')
    print(r.status_code)
    print(r.text)
    data = json.loads(r.text)
    dist = calcdist(mylat, mylon, float(data['latitude']), float(data['longitude']))
    print(dist)
    global speed
    if dist<=1000:
        speed = 1-(dist/1000)
    else:
        speed = 0

# A function to retrieve the ISS locarion from the open notify API and return who far away it is
def request_opennotify(timer):
    r = urequests.get('http://api.open-notify.org/iss-now.json')
    print(r.status_code)
    print(r.text)
    data = json.loads(r.text)
    location = data['iss_position']
    dist = calcdist(mylat, mylon, float(location['latitude']), float(location['longitude']))
    print(dist)
    global speed
    if dist<=1000:
        speed = 1-(dist/1000)
    else:
        speed = 0

# A function to chgange the colour of the LEDs to what it should be this moment in the animation cycle
def updateLEDs():
    if speed>=0.01:
        glow = (time.ticks_ms()*speed) % 512;
        if glow>=256:
            glow = 512-glow
        pixels.fill((glow, glow, 255))
    else:
        pixels.fill((0, 0, 32))

    pixels.show()
    
# A function to chedule the web request so it happens in the main thread    
def requestTimerCallback(timer):
    # Uncomment/comment the service you want to use/not use
    micropython.schedule(request_wheretheiss, timer)
    #micropython.schedule(request_opennotify, timer)

# The main function
def main():
    # Set the LEDs to read while we start up
    pixels.fill((32, 0, 0))
    pixels.show()

    # Init the netowrk stack
    w5x00_init()

    # Sreate a timer to make the web requtest every 20 seconds
    requestTimer = Timer()
    requestTimer.init(mode=Timer.PERIODIC, callback=requestTimerCallback, period=20000)
    
    # The main loop that updates the LED animation
    while True:
        updateLEDs()
        time.sleep_ms(40)

# If we are the main applicatin then start the main function
if __name__ == "__main__":
    main()

