From 4bc002091ed6debc7564d0dab8034def3577cc29 Mon Sep 17 00:00:00 2001 From: Gee Bartlett <122281230+ageeandakeyboard@users.noreply.github.com> Date: Wed, 22 Feb 2023 17:06:41 +0000 Subject: [PATCH 1/6] added in the wifi examples from another branch --- .../cosmic_unicorn/exchange_ticker.py | 148 ++ .../cosmic_unicorn/http_text/html_text.py | 209 +++ .../cosmic_unicorn/http_text/index.html | 102 ++ .../examples/cosmic_unicorn/weather/README.md | 0 .../cosmic_unicorn/weather/icons/cloud1.jpg | Bin 0 -> 1151 bytes .../cosmic_unicorn/weather/icons/cloud2.jpg | Bin 0 -> 1579 bytes .../cosmic_unicorn/weather/icons/cloud3.jpg | Bin 0 -> 1656 bytes .../cosmic_unicorn/weather/icons/cloud4.jpg | Bin 0 -> 1656 bytes .../cosmic_unicorn/weather/icons/rain1.jpg | Bin 0 -> 2053 bytes .../cosmic_unicorn/weather/icons/rain2.jpg | Bin 0 -> 2100 bytes .../cosmic_unicorn/weather/icons/rain3.jpg | Bin 0 -> 2091 bytes .../cosmic_unicorn/weather/icons/rain4.jpg | Bin 0 -> 2053 bytes .../cosmic_unicorn/weather/icons/snow1.jpg | Bin 0 -> 2128 bytes .../cosmic_unicorn/weather/icons/snow2.jpg | Bin 0 -> 2196 bytes .../cosmic_unicorn/weather/icons/snow3.jpg | Bin 0 -> 2223 bytes .../cosmic_unicorn/weather/icons/snow4.jpg | Bin 0 -> 2169 bytes .../cosmic_unicorn/weather/icons/storm1.jpg | Bin 0 -> 1360 bytes .../cosmic_unicorn/weather/icons/storm2.jpg | Bin 0 -> 1692 bytes .../cosmic_unicorn/weather/icons/storm3.jpg | Bin 0 -> 1835 bytes .../cosmic_unicorn/weather/icons/storm4.jpg | Bin 0 -> 1703 bytes .../cosmic_unicorn/weather/icons/sun1.jpg | Bin 0 -> 2273 bytes .../cosmic_unicorn/weather/icons/sun2.jpg | Bin 0 -> 2193 bytes .../cosmic_unicorn/weather/icons/sun3.jpg | Bin 0 -> 2269 bytes .../cosmic_unicorn/weather/icons/sun4.jpg | Bin 0 -> 2194 bytes ...icons_sourcefile(doesn't need copying).svg | 1577 +++++++++++++++++ .../cosmic_unicorn/weather/weather.py | 153 ++ 26 files changed, 2189 insertions(+) create mode 100644 micropython/examples/cosmic_unicorn/exchange_ticker.py create mode 100644 micropython/examples/cosmic_unicorn/http_text/html_text.py create mode 100644 micropython/examples/cosmic_unicorn/http_text/index.html create mode 100644 micropython/examples/cosmic_unicorn/weather/README.md create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/cloud1.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/cloud2.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/cloud3.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/cloud4.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/rain1.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/rain2.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/rain3.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/rain4.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/snow1.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/snow2.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/snow3.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/snow4.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/storm1.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/storm2.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/storm3.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/storm4.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/sun1.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/sun2.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/sun3.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons/sun4.jpg create mode 100644 micropython/examples/cosmic_unicorn/weather/icons_sourcefile(doesn't need copying).svg create mode 100644 micropython/examples/cosmic_unicorn/weather/weather.py diff --git a/micropython/examples/cosmic_unicorn/exchange_ticker.py b/micropython/examples/cosmic_unicorn/exchange_ticker.py new file mode 100644 index 000000000..6b910a42c --- /dev/null +++ b/micropython/examples/cosmic_unicorn/exchange_ticker.py @@ -0,0 +1,148 @@ +""" +This example uses the Coinbase open API to collect the current exchange rates. +Use Switch A to change to a different base exchange currency. +""" + +import WIFI_CONFIG +from network_manager import NetworkManager +import uasyncio +import urequests +import time +import math +from cosmic import CosmicUnicorn +from picographics import PicoGraphics, DISPLAY_COSMIC_UNICORN as DISPLAY +import gc + +URL = 'https://api.coinbase.com/v2/exchange-rates?currency={0}' + +currencies = {"Bitcoin": "BTC", "Ethereun": "ETH", "Pound": "GBP", "Dollar": "USD", "Dogecoin": "DOGE"} +currency_keys = list(currencies.keys()) + +ref_currency_name = "" +currency_name = "" +currency_symbol = "" +currency_rate = "" +rate_keys = [] + +# diplay options +line_1_line = -2 +line_2_line = 9 +line_3_line = 20 + +ref_currency_index = 0 + +cycles_per_sequence = 120 + +cu = CosmicUnicorn() +graphics = PicoGraphics(DISPLAY) + + +# for Handling the wifi connection +def status_handler(mode, status, ip): + # reports wifi connection status + print(mode, status, ip) + print('Connecting to wifi...') + if status is not None: + if status: + print('Wifi connection successful!') + else: + print('Wifi connection failed!') + + +try: + network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler) + uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)) +except Exception as e: + print(f'Wifi connection failed! {e}') + + +def get_data(currency_selected): + + graphics.set_pen(graphics.create_pen(20, 20, 20)) + graphics.clear() + graphics.set_pen(graphics.create_pen(100, 100, 100)) + graphics.text("Get", 0, 10, scale=1, spacing=1) + graphics.text("data", 8, 16, scale=1, spacing=1) + cu.update(graphics) + gc.collect() + # open the json file + print('Requesting URL:') + print(URL.format(currencies[currency_selected])) + r = urequests.get(URL.format(currencies[currency_selected])) + gc.collect() + # open the json data + data_obj = r.json() + print('Data obtained!') + r.close() + return data_obj + + +def calculate_xpos(length, cycle): + cycle_phase = math.cos(math.pi * cycle / (cycles_per_sequence / 2)) + pos_x = int((-(length / 2) * 10) - (length / 2) * 10 * cycle_phase) + return pos_x + + +def update_display(cycle): + + graphics.set_pen(graphics.create_pen(20, 20, 20)) + graphics.clear() + graphics.set_pen(graphics.create_pen(100, 0, 0)) + graphics.text(ref_currency_name, calculate_xpos((len(ref_currency_name)), cycle), line_1_line, scale=2, spacing=1) + graphics.set_pen(graphics.create_pen(100, 100, 0)) + if len(currency_symbol) > 3: + graphics.text(currency_symbol, calculate_xpos((len(currency_symbol)), cycle), line_2_line, scale=2, spacing=1) + else: + graphics.text(currency_symbol, 0, line_2_line, scale=2, spacing=1) + graphics.set_pen(graphics.create_pen(0, 100, 100)) + graphics.text(currency_rate, calculate_xpos((len(currency_rate)), cycle), line_3_line, scale=2, spacing=1) + + +def update_base_currency(index): + fetched_data = 0 + global rates, rate_keys, currency_symbol, currency_rate, ref_currency_name + fetched_data = get_data(currency_keys[index]) + rates = fetched_data['data']['rates'] + rate_keys = list(rates.keys()) + currency_symbol = rate_keys[index] + currency_rate = str(rates[rate_keys[index]]) + ref_currency_name = "{0}-{1}".format(currency_keys[index], currencies[currency_keys[index]]) + gc.collect() + + +update_base_currency(ref_currency_index) +update_display(0) +cu.update(graphics) +cycle_count = 0 +symbol_index = 0 +print("Display {0} {1}".format(currency_symbol, currency_rate)) + +while 1: + if cycle_count > 4 * cycles_per_sequence: + cycle_count = 0 + symbol_index += 1 + if symbol_index > len(currency_keys): + symbol_index = 0 + print("Display {0} {1}".format(currency_symbol, currency_rate)) + currency_symbol = rate_keys[symbol_index] + currency_rate = rates[rate_keys[symbol_index]] + + if (cu.is_pressed(CosmicUnicorn.SWITCH_A)): + ref_currency_index += 1 + if (ref_currency_index > len(currency_keys)): + ref_currency_index = 0 + update_base_currency(ref_currency_index) + + if (cu.is_pressed(CosmicUnicorn.SWITCH_B)): + cycle_count = 0 + symbol_index += 1 + + if symbol_index > len(rate_keys): + symbol_index = 0 + currency_symbol = rate_keys[symbol_index] + currency_rate = rates[rate_keys[symbol_index]] + + update_display(cycle_count) + cu.update(graphics) + cycle_count += 1 + time.sleep(0.1) diff --git a/micropython/examples/cosmic_unicorn/http_text/html_text.py b/micropython/examples/cosmic_unicorn/http_text/html_text.py new file mode 100644 index 000000000..a4316a2c2 --- /dev/null +++ b/micropython/examples/cosmic_unicorn/http_text/html_text.py @@ -0,0 +1,209 @@ +import time +from cosmic import CosmicUnicorn +from picographics import PicoGraphics, DISPLAY_COSMIC_UNICORN as DISPLAY +import WIFI_CONFIG +from network_manager import NetworkManager +import uasyncio as asyncio +import uasyncio.core + + +''' +Display scrolling wisdom, quotes or greetz. + +You can adjust the brightness with LUX + and -. +''' + +# Server Settings +host = "0.0.0.0" +port = 80 + + +def convert_colour(colour_str): + colour_str = colour_str.split(',') + print(colour_str) + return colour_str[0], colour_str[1], colour_str[2] + + +class text: + + def get(self, data): + global MESSAGE, MESSAGE_COLOUR, BACKGROUND_COLOUR + print(data) + if 'text' in data.keys(): + MESSAGE = data['text'] + if 'colourfg' in data.keys(): + MESSAGE_COLOUR = convert_colour(data['colourfg']) + if 'colourbg' in data.keys(): + BACKGROUND_COLOUR = convert_colour(data['colourbg']) + return {'message': 'text updated'}, 201 + + def post(self, data): + + return {'message': 'text updated'}, 201 + + +def status_handler(mode, status, ip): + global MESSAGE + print("Network: {}".format(WIFI_CONFIG.SSID)) + status_text = "Connecting..." + if status is not None: + if status: + status_text = "Connection successful!" + else: + status_text = "Connection failed!" + + print(status_text) + print("IP: {}".format(ip)) + MESSAGE = "{}".format(ip) + + +try: + from tinyweb.server import webserver + +except ImportError: + # WIFI settings + WIFI_COUNTRY = "GB" # Changeme! + network_manager = NetworkManager(WIFI_COUNTRY, status_handler=status_handler) + uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)) + # Install missing module + import upip + upip.install('logging') + from tinyweb.server import webserver + +# Create web server application +app = webserver() + + +# Static page +html_file = open('index.html', 'r') + +# WIFI settings +WIFI_COUNTRY = "GB" # Changeme! + + +# Index page +@app.route('/') +async def index(request, response): + # Start HTTP response with content-type text/html + await response.start_html() + # Send actual HTML page + await response.send(html_file.read()) + + +# HTTP redirection +@app.route('/redirect') +async def redirect(request, response): + # Start HTTP response with content-type text/html + await response.redirect('/') + +# constants for controlling scrolling text +PADDING = 5 +MESSAGE_COLOUR = (255, 255, 255) +OUTLINE_COLOUR = (0, 0, 0) +BACKGROUND_COLOUR = (10, 0, 96) +MESSAGE = "Connecting" +HOLD_TIME = 2.0 +STEP_TIME = 0.075 + +# create galactic object and graphics surface for drawing +cu = CosmicUnicorn() +graphics = PicoGraphics(DISPLAY) + +width = CosmicUnicorn.WIDTH +height = CosmicUnicorn.HEIGHT + + +# function for drawing outlined text +def outline_text(text, x, y): + graphics.set_pen(graphics.create_pen(int(OUTLINE_COLOUR[0]), int(OUTLINE_COLOUR[1]), int(OUTLINE_COLOUR[2]))) + graphics.text(text, x - 1, y - 1, -1, 1) + graphics.text(text, x, y - 1, -1, 1) + graphics.text(text, x + 1, y - 1, -1, 1) + graphics.text(text, x - 1, y, -1, 1) + graphics.text(text, x + 1, y, -1, 1) + graphics.text(text, x - 1, y + 1, -1, 1) + graphics.text(text, x, y + 1, -1, 1) + graphics.text(text, x + 1, y + 1, -1, 1) + + graphics.set_pen(graphics.create_pen(int(MESSAGE_COLOUR[0]), int(MESSAGE_COLOUR[1]), int(MESSAGE_COLOUR[2]))) + graphics.text(text, x, y, -1, 1) + + +def run(): + # Setup wifi + network_manager = NetworkManager(WIFI_COUNTRY, status_handler=status_handler) + + app.add_resource(text, '/update') + + # Connect to Wifi network + asyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)) + while (not network_manager.isconnected()): + time.sleep(0.1) + + +cu.set_brightness(0.5) + +# Start wifi connection +run() + + +async def message_update(): + global MESSAGE + last_time = time.ticks_ms() + STATE_PRE_SCROLL = 0 + STATE_SCROLLING = 1 + STATE_POST_SCROLL = 2 + + shift = 0 + state = STATE_PRE_SCROLL + + # set the font + graphics.set_font("bitmap8") + + # calculate the message width so scrolling can happen + msg_width = graphics.measure_text(MESSAGE, 1) + while 1: + + msg_width = graphics.measure_text(MESSAGE, 1) + time_ms = time.ticks_ms() + + if cu.is_pressed(CosmicUnicorn.SWITCH_BRIGHTNESS_UP): + cu.adjust_brightness(+0.01) + + if cu.is_pressed(CosmicUnicorn.SWITCH_BRIGHTNESS_DOWN): + cu.adjust_brightness(-0.01) + + if state == STATE_PRE_SCROLL and time_ms - last_time > HOLD_TIME * 1000: + if msg_width + PADDING * 2 >= width: + state = STATE_SCROLLING + last_time = time_ms + + if state == STATE_SCROLLING and time_ms - last_time > STEP_TIME * 1000: + shift += 1 + if shift >= (msg_width + PADDING * 2) - width - 1: + state = STATE_POST_SCROLL + last_time = time_ms + + if state == STATE_POST_SCROLL and time_ms - last_time > HOLD_TIME * 1000: + state = STATE_PRE_SCROLL + shift = 0 + last_time = time_ms + + graphics.set_pen(graphics.create_pen(int(BACKGROUND_COLOUR[0]), int(BACKGROUND_COLOUR[1]), int(BACKGROUND_COLOUR[2]))) + graphics.clear() + + outline_text(MESSAGE, x=PADDING - shift, y=11) + + # update the display + cu.update(graphics) + + # pause for a moment (important or the USB serial device will fail) + await asyncio.sleep(0.001) + + +# The folloing is required to run both the web server and the scrolling text coherantly +app._server_coro = app._tcp_server(host, port, app.backlog) +loop = asyncio.get_event_loop() +t1 = loop.create_task(message_update()) +t2 = loop.create_task(app._server_coro) +loop.run_forever() diff --git a/micropython/examples/cosmic_unicorn/http_text/index.html b/micropython/examples/cosmic_unicorn/http_text/index.html new file mode 100644 index 000000000..093d9f8eb --- /dev/null +++ b/micropython/examples/cosmic_unicorn/http_text/index.html @@ -0,0 +1,102 @@ + + + + + + +

Cosmic Unicorn Web Text

+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +

+ Please type in what you wish to be displayed on the Cosmic Unicorn and whe you are ready hit update to update the display +

+ +
+ +
\ No newline at end of file diff --git a/micropython/examples/cosmic_unicorn/weather/README.md b/micropython/examples/cosmic_unicorn/weather/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/micropython/examples/cosmic_unicorn/weather/icons/cloud1.jpg b/micropython/examples/cosmic_unicorn/weather/icons/cloud1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7c400e81f4e89910c388c9fa5cc751ed95ab3e0c GIT binary patch literal 1151 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 literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/rain2.jpg b/micropython/examples/cosmic_unicorn/weather/icons/rain2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5fe470c72d496ef8a7ce8d4dc7537932a3fe3cf2 GIT binary patch literal 2100 zcmbu-c{H2p9tZF@5=$&K5rlM6RW;U%W%Md?RLj^p)7k|o2DR0ihN)$$n4;yhjjaw^ zu~zN7$xum9rPHyLqL##{itSCSyols-=bpLe+`sO*^Lx(o$8(^9& z#?smnfWctEwSxf&rU8q?)!(YakiQjhcv$cPK#2h-fs=69DL@DXgQH*qCZGfWFyTM5 zfqxfF2#ydI5fwv;BX-XTv!-^IOvW)*ar|OVHstdxd{4-x9F(|S-sm2 zo{FhlXy}oec;MK_J*xT`mcau{r_QD^FAC^8YbGV;AZ+_X@hIV!jT`&Ot*OmPV`!5&j zz$Ju0z!9Q{E|?JcV8T%dVP%|%jQJH&?+ElMz1w247alxq=s~LJUj^lSB8SE0PaCjQ zxrelW$^JK3(*Gs<3-%w^6d(zQ9XuW!1>ga`@5(lYkBkxkhtE+$_``Gh=&f}dSxS+>5Wnq=S1Ytc} z3uQR(m3XL)EfvUV&y!~Z71Z(kQ{%}!c+u!?u{Q!h%&@C0wzMLhG>3f;r5Owu2CwO{ zCmi|o;We6Ol`T2Io9w5(w*MjL(M*BDhE`Z&ol;67((G6q3M3UX1VD-zdX$Eqe{HtT z-yLL3*?Ja85Na;7YBv^dhw0oXy*J}&k}Fg4QbphT^lgimi`_;1LcHB1L^`(7lPJmE z;oGzQ#Pg**_R@9R?NqhoZ7Ke-aZ$00J6^`EXIx({<S=_PD z3Ud-)imm40zRZyq5fgIWpH|7@W0~HPzo^%^H?J&k+wE+7tk4+@`okxmb`6((RaQ0F zPBw2pnvXFC#RWh-kDD+j06uGMY0c!6R4cwOnGEQJTs5k{AY~ zQvf8>Y%9#Gp{QQ0P8Dk=(YixVBGlpH_-eo?$z!k}5D@m8vkZ;A8 zJ-KsnY_+98Y`t`ZH_)7Bu;*#YA3tkm^igH=_aP_?*8>@{*U8K{`(8JG#9a?m?>UYE zZs7Y&f{CX`mgx|`N%FTAw+XtBhF{(*$S#D^AVX(2G}m+KeOVow$>3RJj(0G(U*wwJ zQ1#b?^^UXg6z?U6Bm2}|4c-1li0G%KrHmz2S;<`}3_?B&YQf4>t{4|nx*O}(Lb(}R z=b;QWW>_+|sNnec(~82Q%q}cfiZWH466Z$UStgw*t_|GUzKMx#?YyrOLXy(|ezb+4 zX!35Y?&0|Q?(E8Ttu&-9x~3LU$5R8J>{EE(6sd4A$vO#IG2M1Vnb$^Jb97m7FNQCT zjybY!e`9>ws^j24lBrOxbCHs)DKBYDLcymoHshT~BJQzaP0dzK`J@-e{l@(OQhab2 zsX7?9BC~89N^3f0f2*pWwU2k2_@SZo!pO{-ta2hJRJ^^hxxF3NH=Ccx{!W;a#x-(j z1@Vk5=|p;Hwd*n;4KguvaymMEIk$mY!pi8%?2(T4F_J0Xapc-)^CV5Vs%IgT$oz4E z5Ih)5z1|f{%N-}a_tK3&9(S7Sa5p?(0LVdM*-JY-Jx-oR$7a1^dX2h|X^{g(00h2$ z)n1Uw@y`n>QJ{GRx=1^p8?rZ%cf-1dB)Fu-`e`N3d!X52is7jQg3bU$#pL>p^jgv) z7t`pURBa26-rIeS%XhwBpB>RiwL*&5N2}X(X4TnQrgL>sv6FxK+=%BE)&>t@=spdvYnt#D?8PL*^e7(BR!8RPN;k^I_h3mMZOpEU0$pd7Z(Ae5jL&3OOa@|Q zE$C>dGagQ82l17G^aVE(1{s>izzT7SYN?38Z%w3)d1(%XInxwo7)Bz_+;Q YSxqSm)MYQa8C{=LePx#^00fi&1lYIJH2?qr literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/rain3.jpg b/micropython/examples/cosmic_unicorn/weather/icons/rain3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..91be10a9dc810584d65b3f337a5c77a81cd9891b GIT binary patch literal 2091 zcmbu+do-=@r+0VP)Ki>5`?{}@w`$|WpQ^0O_ z7dICG27>|TwiX~A2aax^{!(p+{H1{H%hEOgr2y;&_QGKXfD8%-N5P~#Ko0<5a(`q4 z|1OveTvl#}yaGZ|X=|WjToT!_3#jEajV{Y*|symBLznwEYuBQxh-?k{=y1@{Xdl|C+eQckaUT3h$LzM=6& zQ!|IlYwzfM)zv*PIP`XSWc1w_UoicTnUAw`pM>Db>gO+OU!nDlZ5IrH|M_Hp!2ZjH z+H%Rr%ED#kw_Pw9^45lmJf|pHL$v-u*doC!x}ci(Arz17IwK`QGK5c z-w52M{Y&=0!LI*bvOi(}ag71WaM;%8!BGGXkc7{FMN1HIQb4v^#9Sm!ZTd~;cOqkW z_GGRJKIJPn1SO(TpFJ4(LO=^K?m-Q8mBPZIwMJ$+bh$$?MLav)e91DZFt03z{xS-K zZzxs~zSk3@me&lSGvDxHcc_RdzL1toX5-}JTNQexfPyWnEb(!9CTSA$9?G!kvW;G} z5{&ptIQ@$)CKVp!$WU^`!NtvwdG|gPX)K$@P?&mD3c^u42_+)YxKe=Xs5;o9I`zhJ zNwU$y9rM5!DFrdS_|KMSuEm)B?eXmocx=APqgRI3Zu_nseKpfsA}PjszJo~G%WR4= zxGp&%h)}$b4E~mB@xs%{RNW)@LSj-};>>!8eZzPDuVxEc)J=@(U_lbg*P;L$agh%W zt!hjveWAHd!ozt3ZLuS2p(_hy#i2W)$}hiX1U{di248r3uw7MeaXC2;RyJ%ug&Qsy z3(mN|opT!E_9#k$WHFdBDFs9>I4TawLO?y!kqiBFi0L+zqB%#NFaZgFPx7eJLw&OE zO^x@*tn$zs>Sb{;x;0OtF=qF5CTdL4jm^b*<&hD#Wi4mXDZ%-AZ`3Gdb{W_sj}o}t zW+{-`;!*BY3B|Qz%qsXFC~i$wNwI34N zSazMd6NJSFXFI%>)G7a7A27lRGma?ehCDCj)~IjUHITo@(ETz_!vv}eS%uRo&`8=AAsE|HMdrv~eT zG_j+L%$(t+jfwfMgI-eLdcTMO~xDshOYqmrJK2%bpGXUuJk@SH-Y zTB#x&@8r$={7Ge&X0eM_G($!x5eV1jI|_ALxp*y4=xkw3hWIFjxbqr0c8{(m>&FGN zc=JUHhIL1RPN?7=!Y$BH#ERa1uZW4eC&A>uF0=&-Q8_U{VY0q z5tsr`Z_aS%Nu~6j&>rtBOnn^Y7vsSwHB0}Pai$7|O_EqcSKD-VgC{!MdS$qbgjrsR z$q?3|oWRUv#23-1g{FOTSG*c^pOow^@nBr}*51G}8i-Lbxwyax6D{OaDcfohRaf9^ z9h)tVhb7~Ik{fif&x^iz%1+2FMxKgAOwF6TIl{F+-tj=+W7GRIU5I&B@if}6dOXO< zK~hS8qm4S&Pt0qMN24v?OyM-JghvT4+p8&@{X{yEr6g)h#~z;QRrusLVFc=BhSd%x z;mX)ME3ZD8fM{K;+8U5>YpZcb&#ivoGt!EC3Ov3MkU(*9jn-(XeJS3zVGSMRcbJ<` zJ8FwM5Ac`FaxF)1n_2I!(P$Yl;C!s(*$0s9GGE7G&30L^XA%k`{KaPp-ad>20=_mr z_y>bv@%u;tQzzCz+spMn7-DDD<-;9dINvLCl`lBM?#L-I4(UNs83ZH&?e72DLEF=p PSnlF=+j!6mCw=!%5gW-L literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/rain4.jpg b/micropython/examples/cosmic_unicorn/weather/icons/rain4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9e676daf20e4affa57ba670afc9274356ec35947 GIT binary patch literal 2053 zcmbu+c{JPU8VB%SB$g;`V@sQA71h?#+OL^3$(^4|n4eC_g49B|msbeUzS&`8X?|R#5niUQ}H2yy^wBy5?nV z9h=kK(%RPE@usJ@uYZ8|esE}lKl!hzkJB@=bHbI?PiyNN;O5qz3j#p@e6l}a|KmdJ zx+GvQC`@|K1(6`{ZYTmKsctBxV0l@Z5UQwQ6epu}AuX@639f1EEKv5l(JiZT!el~A zxJUc9?Eiz^`Af1tVgGdv0di2t?&m=ffCV7(pWi@=;9+6_Rv}<42958yPiC~qhcu(f z99{hF4UP{&keg8cv}es1Ift^xRaceHW%aGsFzDcoR{nU9+d$nlLsC|HVMx&{5(;0P zqcHbDZ5y$?t_fcGjNi5gvl-g~lo)c8g>*PehAReSOdATL3h2oZW2g^cl1YbY@S+i) z=PF`%FV^c8W66O8GV#pf&d2nJBiVXtXI+1DH3KzH@F&PVu)8Kgng@r z#`dk{+Kxf}n|m5VdCG*91+r}4eS+L8?J}L;x-X0SJ0vn423;6~(*f|-v&|L&F?D}pWo*|Fw3Vr_>jr~;(F^lHL zhkKw_n~_^8g<&DbDxU?T&OSamTB(Pusmn>H2NF#S>)nvIy))Fhlw%9ck}&7;BRQNp zF%VymrCXMQVJ)b$#SBJ z!;VY$aTvUJ>iM^#D!Jd7o;4acmo76W( zZ%a>iR=AGFPzlp6`*&z9ItFc1pf6ERPaPFeY^!`BhXgMnF;NOd^XObE>p5fbx-ez^ z9GG&dIV2wSB>U(<9zEwsa|22!PaVoli1wsy&PE)|Ee~4XxQUFauDf^kT7Gi$_=wlp4Za5ddmU*!!4xz~-R2A0n~y!yk@(PH{=FnXlnm!X!{ z)WVBoIWJ1F)Xy1i`XycTAq+1xsN+@uk1IQTroWcz@FXp2^2FXOpi7IJ=RqvjqX#EL8MbO_a#kX(Fr#~m+mB&L56nBH1 z%(BguuD`^W#aOn8RKN8U0|#yO>2YN_{OkW@uqGz=%$uol;N+eprOTxIts$D6+Kv4DO)FT^yGXVuH(9vo;vpucK;s*c@pzFahiDlaYxcCQ%5S)Lcsin>%0*4;trb>T>)LD#BT z^BFg;vrx6V&aEnle@2>Y;DJ7q-LTvqj6+K*x&>Geofo7UQT zSxjkgO$d{D-D_*gfyo&dMa7`%_Y0Oy8ig4$U?6AnfFhf6(gV|@wCV+Zs5y{&CBK-U zp2Hm;H@w{FzD3bs^;LNOG;9A_&N-#j=NDRXz00KNB-_sjGo4(e$I+(Flz?_vX(x(K i`H{gIbWfx0AU_D>Xz{BHeQ|z*+K;9(I-IcL!QTOuyT7gg literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/snow1.jpg b/micropython/examples/cosmic_unicorn/weather/icons/snow1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..de769f956703ff6b8be4465b1e67b3676373c1c0 GIT binary patch literal 2128 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 RBfAN6M(dlIxhzpK{Vyb-`Op9W literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/snow3.jpg b/micropython/examples/cosmic_unicorn/weather/icons/snow3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b85dc3b2662348326d4ee724492ab1b30e9baf00 GIT binary patch literal 2223 zcmbu-do+~m8UXNb3=I)YF5}jWyLPrjE|ECh2uaAEkfuq+j3lDQbrxmDB{@ZeOo^e1 z5ke(TIa8`&VJtY{_(8$d7rg@@AJyXr%p#i5{T#H6E0jNB_>_EoJpZ(W#?QkD7;Zre6ytVZe~&@4>@3p=TNHdUydb^RUgPI0*G${w0B#EO=@47UflL`fYS0d$ z<}jcqdlZLG349=w0~3xi=Z7FUKa?%gY>i|#Z?xK7G%~|YQpyk>GLx_vv3M6@@dlx4 zHL*!?(0a~V4wTu9h4R?4SMCN~XL{19+oiP(a^j?I z1q&tl>8{STxDcV6@l$a5R&iV2>_iIr#2{VvvSlPD{_W1Nv&E7UNJFZF6&ZoQfyJWY z+!U-GiNkJl%AGse@4AD)3+g}Pz}Rxv*NH2bo{TwMwhOW-H@`JgD?YnuTt^TdFY@uA z%nx|U0fZ#&^VEJf<6yr`H1gc(~`i$R`?KYswXKB%v0;^wWev+KEmJg6MNSw&;y`4{f zSkw8WSq@};6}#;W=iPEsqk83Y-l;&o)pYVYQEkNZjvd@#d$Pv6NRIE2gO@#1jTGhi zm?DxS*KV4x%E3JAkv(-MV8qrMvmB>qF*>0s?%*SChaQQ_^UO>Mo5raSWai+$&zbF( zDWk3D#bp1X7VG4I$Gv~2FZOnFkG}L{C**nAMruaWOP=%L zBxOO^%=kXkSiU-`zymTMi1h2ekAMW0Q5brDR!rs=E#R$$ZU)0?y>)_qAAe<0RT2uO=30+CD#F+Y%eB z#Te{#?Jd@zcHt*o4&8-x)xwhGfGWQ$@LBWr`rrq^C-Ip+)iVF0h+ETkV{d4o1-wSh zs)iZWP*v|6%Kb03KI4R=jDXC8gdQTzByT%frwL40keZRfn^BUHbdlfM859d8>jIZq z9m_3zgV>m5>K$T7OGCu$DmBjPzB`rJ-818$yik{>PV%1tOfj#t5uD#RaAPKQCHoO zir>+WRbzsF)OHkq9pVu9p}2t*!84g!`SXnsIk){(btFa|+etG3W3pQE0@(wCrbtu> zz5A-vlNl^ zI?6??W}zLxbnj`ndAcF4e%OIpuI;0l&8`ayS=uz*jW^ADaOJL`r;u@+@1kXhcQv%c zZe@GWELtMAdtQTb!lIJu>C+f0%|e_FZJQ=@=n$Iz{z<|sjDKUQ1{;gIhMQp-6?Bf2 z_GK^iDNf*UUfT2RqSD+DuedjpLX>;tKR3s{+qyDd3O!sS!(lm!n{=3l20xBeB-e}6 zrZ^Wbu*{$KpQ(5Ct9&~i8Wkc8BeXd_F&C9r3tuI~Skw|?v}eYGOZEmeCYaF>gYiC7 zO45T-y?tmB#=jZrx-lIA9ZOHR6GGGcDx-O+5q_gKHPBvt>%wDJL)KfG zCoy{|Q~QP-zI8n9j~7JOZ<)0pkDjYvnE&i~{a3^Lx;a5$A;Smb%DSP(E`CH)U6)RJ znc(WH8xD=nqwC=|Ohb-A{#7fz^aq9bd#A)-c(&r6h8y~0Dy*YN8L!I|U*RjW%MaKu tmp;HEXSaT(JL4OEr0zcvyOl)Lz34$Pp*b=S9Naj_Idr*Dz(dN%{{>EY2KE2| literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/snow4.jpg b/micropython/examples/cosmic_unicorn/weather/icons/snow4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8ae9bd6af3d2affd9c44eb265b5ed77fc179d1f8 GIT binary patch literal 2169 zcmbu+e>Bto9tZHxY<^psF^uR-S$^eWzA9^ODatM@KSm>3Qi!yWeKkaE61l0!M0fcy znjiW4l^*=Kb%3p@=Q)q}TlrEs z4XpR}-0ulMAQ0fl>H?ILfX7<*r)n+aPX(-9Rz3g_8o)+iBNSo*s30Iv1VkwS%mDzR z`g=C;?}Dg6VXA8C8k$<#s{^g;0Tl=osse+ms={Ea)2XZH01Tn3_mkr;HRM5xx&>9= zDdP%T!*X|1uYuo)Y?JfRGntxNC_^J-^kyr}7Hb=<%g?Ucw(s!Rv)9vW-+piZfIw1E z@F8-`jE;O8%kOUqy7-@dQ8AOQ4_C;J`t zUoOO|O9cjl!qnGX5S8TB4Mo6Ie{xjQ+jUT#LPc6QWoYQ{zQS(m)wFc>lNlU6Gopps zgq3Ut*J!`V{x?|W|0Vka_8*rB(1Ai$KM#rk+<}#obbCp>9&JjH;*fkIdP#IQUe2iH$WzPw}mmla<6bdeH}`8sGR^ySXU zGvOk)X(r=T501tSAMIzyNng3~)3#mZi;-)BQuk@N0ra`B4Ui1~rG4scyO@ekjuGsh#EkS(nq8OP zW6P6rvZANCeB&^Det6aQZINP=BlxcV(8ybFXm(QdOTx$wQc!uo1Igzl1}zruUDB!< z!KRa(3~XQUF-)$(c@D;A@r~Vav(pNO63FB!fnJ=8IYaDzOUiryNp@z|SMHD`(P%Bm zMbMnaeTi_IxsW6(Te|ZGL9BzhyS48%J?O1<=d-E0o-1{ttp&EX-03)tj`;|YaAOD@bt4OKR9PNz&eocpN)18 zsp0xoYtcvV-pd*A^>(TCtB&q5Y2wKWa&bi0OWiJ2Q}W~kvRC=V7h2UvA6`@hp?Z?2 z$u+byZig)vyv{km;ZBC*rKHit+6tc#A2gkuRp?`izZ92HK}%RMxRt4(g0_dj#$KPJ zv-{+1sktiM8dPJej%O#;$5>Y)I^6RIwl|WX(3X-M>w4&SAIb@|v3`+MgPvk#pUwLpdfhxDOXiVwwbcbJ;Qn6qOT}JDU(;->4g-P@JhqS)n_h$AEeKs|nd&agI$=4Vx zN3!Uxn-7j%$MqL?2++ls%AbR(&t?(VJ^bk~O6MdM=Kv7~y$hla&R9~HZ%%e)R=ULf+?%h)3dVl*Ye zrEWoYqVf&SU(#j14#OZn6^hXy1=P*P4(Wwq7*oM#Wv$EXor}&iFM+%0yJsO%(CH`g z!rx{c8pTo#me|dspN#%_cL~kOjsV+p=?R9t4!Vjx;|hob?kq5KY;FVfNh!QsoU81M z7j4sv?p-tEvNzpi`5=uDrmm45M*@5R}iLT!~_3XEJcCjFZ5K!K1NCG8WNq6_8x zIE&PM^17%t58=>JksWH8D|rhVE@#MICu@kVr8vAS_Aeqx+%}wFE>aC+Grzh$J|T~ldGzM vbJ@|vK-JBApK7oyD#P_5&vShlX5|=7zc#~tfq7!R{Lr0lgUz*Mj&kB(gd)(H literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/storm1.jpg b/micropython/examples/cosmic_unicorn/weather/icons/storm1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d7ac6251071627f7786f880888b74fc460426512 GIT binary patch literal 1360 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 literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/storm3.jpg b/micropython/examples/cosmic_unicorn/weather/icons/storm3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6081f046654ef0891ff4a29e6c9958699875cbd1 GIT binary patch literal 1835 zcmbu+eKga190%~Bc8 zKp+rc|J(vp{eb&?_d_)w@0V4o_AiiY-e-{J_ zgCo?C>L?A(xq+&M02Bg)LE$h20uG;>J~wv`z%dA&m3Eud76pVOjbj$uCtkUwZnC+& zK{xOfXu3AyWD-h4Pk)I4*38^um8F$~qm#4Cy7lf`wt8&a?&%e@GdLu47k+o-frE#l zqKSu3#gb0Pk>k&tzd)lWGg4ABuU^Z#o}F`pSx{KSF6P|6Q&PdNtg5c5z5k%GsrgAu z>#tASI)z=`J+FKFL=vg&-O%vJ`wye?iOJ7XUw&8oF+J~s0I=^*_6_zg7iP`{g~MTR z>l2PEBW105Uvgk+FTE`r^%3Zk0EnOx6a1x)CQ|Y3P|cNX+E(w7+Ek z4VLu3WZz-`xJ1AL7-a7AU>IN{FdI2G~O1@)5!ixP^7e4>sLCyaI7pc&FBscy-RNBl<95siYm zMEs|5(b+=#=cbME*r+&#KPS60lA+WPzv0ts*C3f9n&@Xj~Cd*d3C)^cF& z&EV8$qY$Y;;8%?r7R zv@K+t30ZK>ef|UffpoI%E#|6sgvm$pk8Zlv@{UV3O4KP*yf`gEkDO|xHV~GA7);3$xNCX zG};K;FB@l&(gr_0-y@EDoWE4L13cd7?R2xMJ|)ad7~9_KPzX0^r;j&To;$u->GIq#5$$!kg-Ix{Wjab!1cPrCdVs)*gQE;ct zpRNKR6xUK}^TtYxPs_6NK_*$&Xy^i>n=XK~?7RtzCD_U!X)gEsDy?UTbKCV}6q!f- z6``|BGZ7Cegu7J$p)Svjt;=qqfp4ia3TmeCGdhWYs6VpNU@wts)J^}5nvQeV8-3>nn5*HbOeC+PM4>*`yGpHnnpIQwpJIUjvJoz2poO-$z;_4To4 T2TP)@9m0bHZdyAnRrUP|Es;5$ literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/storm4.jpg b/micropython/examples/cosmic_unicorn/weather/icons/storm4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..98cdc59c01e66aff906414d311da0631845bc5ec GIT binary patch literal 1703 zcmbu+cTm%37zglQ7GVe&ro>W|Eee)EKqTrR%HGpBhzx<)T1AKuWgI9Ff`S7?gF+>Q zAS*&xD#{cTWQJu>2#E|q$}b|CB9KDu*}MMLtIvDyAJ4td`@Q?TuXtF@12#I?*xLXQ z2n0C3wgB-6V7=abSFMM9SHSvZaRY#o1hxQMU=U3Jih{sU5OE8j0RRxh*KFYLfjMXEZ0+nFJiWYqd=KFd2L_!84hbcm z438k4i;ND1A{}uuejrU!P|++sp)q!!Ve1{7e9R#{js#}f&j2@Pxck|FBfXf1%<<5aOAoR z0*zeTFcciI)mTEo${pz+rl^UDmsHw+?Ou7Kl$MDHs2p&%S6W5ebX-TcPWwyt-(U&< zOZE-+kBbXzfI-$i4~7Ev0jq(ti>|9unPLDwS-JACs$2c%9CKk(Ij=skUhar3XAvK5 ztdg^8Ak?5>hv$t9BT9dq@~-MPeWE+!QeJW4ji=`m4%SRIyxlEV(h-{+5GL92rxktvQZ@juSi;Va^QGq)HW)tyq z^V|z`Os94e866TSa%E=q1yYu!d9T??wL6hC-mb^#XGB$*VWkF}h!b^|*4x`A(v6vp zvk}HhVfa>a7=>jm@9cTGVu|FR?m_aFJGM9dN9BpwEmOBjID1$ZTi(95^hs?EGP&zb zeK`{VidaQmv8{}4eGNS=o=lJYJG7Q|g=W*=W(cBpVjv+~3^bbWi1U9u4;2+R_!$o_ zhk$H8Vw9Q3HK)=!$<#V5-`QYvyMTEzi*_*QHe==!tvXkG==`aboXmn3itm;Z8E>vr z=8RZzdb2B=V=+;dys^vC2-Zk6sRxHFjmA~Urf&<7E0BU4s# zvu8(bx_mZ&!D6Da$Wh8x-X<+Piw9PMqT1a@MOSYo#`r7+xDTSa3a~=OJHy0@^pM9buTnj z13e;`r;t*|<~on?A{%lyFS~)Kn;gyVR@JBY>2M-ChE3^kt&XJmWc?Vo zuFv4O85*0EOO~MDcMJg+V;a98qK|;N?*+n0{7U{ZUc2Ucv<7ING6kAnGGsB>xqM_x zJ(}nnD+{(ImR)%)l?N`Hp=&5Ocm5u$fznf^W3qJ;mQQTHIB~G@v+}AFEpFgQYDkkw ztC3#XG33>8P)V@Ehe*Q(tNCNlr2O%fTsh6cL2F9aR-eS9H{@>(bWZbs8aU&|autqB zN39D~nTq5Gor(7T-U%8O=$F$u1-m=4XHKu3grf70GEl}!d2MNM`0JNRZd zeGrH3)m$(o@2%RL66^$3wuhHi%Xd;pbEgS8-Oe255H`l~P_}Dt37r#hL5*bjf)&K> ztDLr{Hal07U#gh7E2@_k9fYcvQ=hYXLm#$hT6i(g*b^=a#SSLkS}t^IctMeVqnBGI uzksf+osr>jj$n*cwkUM&lJ;=RPEF15Jc$YW^=O$xXY2gUPmf=VU;PQ#^YlRg literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons/sun1.jpg b/micropython/examples/cosmic_unicorn/weather/icons/sun1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b989b43259ddb2b4df2b6b3f4064e081146d76e4 GIT binary patch literal 2273 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 MFrZ=KSdDV}pF0fxb^rhX literal 0 HcmV?d00001 diff --git a/micropython/examples/cosmic_unicorn/weather/icons_sourcefile(doesn't need copying).svg b/micropython/examples/cosmic_unicorn/weather/icons_sourcefile(doesn't need copying).svg new file mode 100644 index 000000000..8eedbcb07 --- /dev/null +++ b/micropython/examples/cosmic_unicorn/weather/icons_sourcefile(doesn't need copying).svg @@ -0,0 +1,1577 @@ + + + + diff --git a/micropython/examples/cosmic_unicorn/weather/weather.py b/micropython/examples/cosmic_unicorn/weather/weather.py new file mode 100644 index 000000000..6f4a3e2e0 --- /dev/null +++ b/micropython/examples/cosmic_unicorn/weather/weather.py @@ -0,0 +1,153 @@ +import time +from cosmic import CosmicUnicorn +from picographics import PicoGraphics, DISPLAY_COSMIC_UNICORN as DISPLAY +import WIFI_CONFIG +from network_manager import NetworkManager +import uasyncio as asyncio +import urequests +import jpegdec + +# Set your latitude/longitude here (find yours by right clicking in Google Maps!) +LAT = 53.38609085276884 +LNG = -1.4239983439328177 +TIMEZONE = "auto" # determines time zone from lat/long + +URL = "http://api.open-meteo.com/v1/forecast?latitude=" + str(LAT) + "&longitude=" + str(LNG) + "¤t_weather=true&timezone=" + TIMEZONE +WEATHER_TEXT = '' +user_icon = None + + +def get_data(): + global WEATHER_TEXT, temperature, weathercode + print(f"Requesting URL: {URL}") + r = urequests.get(URL) + # open the json data + j = r.json() + print("Data obtained!") + print(j) + + # parse relevant data from JSON + current = j["current_weather"] + temperature = current["temperature"] + windspeed = current["windspeed"] + winddirection = calculate_bearing(current["winddirection"]) + weathercode = current["weathercode"] + date, now = current["time"].split("T") + WEATHER_TEXT = f"Temp: {temperature}°C Wind Speed: {windspeed}kmph Wind Direction: {winddirection} As of: {date}, {now}" + print(WEATHER_TEXT) + r.close() + + +def calculate_bearing(d): + # calculates a compass direction from the wind direction in degrees + dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'] + ix = round(d / (360. / len(dirs))) + return dirs[ix % len(dirs)] + + +def status_handler(mode, status, ip): + global MESSAGE + print("Network: {}".format(WIFI_CONFIG.SSID)) + + +# create galactic object and graphics surface for drawing +cu = CosmicUnicorn() +display = PicoGraphics(DISPLAY) + +WIDTH = CosmicUnicorn.WIDTH +HEIGHT = CosmicUnicorn.HEIGHT + +jpeg = jpegdec.JPEG(display) +TEXT_COLOUR = display.create_pen(200, 0, 200) +BLACK = display.create_pen(0, 0, 0) +WHITE = display.create_pen(255, 255, 255) + + +def run(): + # Setup wifi + network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler) + + # Connect to Wifi network + asyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)) + while (not network_manager.isconnected()): + time.sleep(0.1) + + +cu.set_brightness(1) +run() # Sets up Wifi connection + + +def outline_text(text, x, y): + display.set_pen(BLACK) + display.text(text, x - 1, y - 1, -1, 1) + display.text(text, x, y - 1, -1, 1) + display.text(text, x + 1, y - 1, -1, 1) + display.text(text, x - 1, y, -1, 1) + display.text(text, x + 1, y, -1, 1) + display.text(text, x - 1, y + 1, -1, 1) + display.text(text, x, y + 1, -1, 1) + display.text(text, x + 1, y + 1, -1, 1) + + display.set_pen(WHITE) + display.text(text, x, y, -1, 1) + + +def draw_page(cycle): + global user_icon + text_cycle = cycle % 1000 + cycle = cycle % 4 + # Clear the display + display.set_pen(15) + display.clear() + + # Draw the page header + display.set_font("bitmap6") + + if temperature is not None: + # Choose an appropriate icon based on the weather code + # Weather codes from https://open-meteo.com/en/docs + if user_icon is not None: + icons = ["icons/snow{0}.jpg".format(cycle + 1), "icons/rain{0}.jpg".format(cycle + 1), "icons/cloud{0}.jpg".format(cycle + 1), "icons/sun{0}.jpg".format(cycle + 1), "icons/storm{0}.jpg".format(cycle + 1)] + jpeg.open_file(icons[user_icon]) + else: + if weathercode in [71, 73, 75, 77, 85, 86]: # codes for snow + jpeg.open_file("icons/snow{0}.jpg".format(cycle + 1)) + elif weathercode in [51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82]: # codes for rain + jpeg.open_file("icons/rain{0}.jpg".format(cycle + 1)) + elif weathercode in [1, 2, 3, 45, 48]: # codes for cloud + jpeg.open_file("icons/cloud{0}.jpg".format(cycle + 1)) + elif weathercode in [0]: # codes for sun + jpeg.open_file("icons/sun{0}.jpg".format(cycle + 1)) + elif weathercode in [95, 96, 99]: # codes for storm + jpeg.open_file("icons/storm{0}.jpg".format(cycle + 1)) + jpeg.decode(0, 0, jpegdec.JPEG_SCALE_FULL) + display.set_pen(TEXT_COLOUR) + outline_text(WEATHER_TEXT, 32 - text_cycle, 0) + + else: + display.set_pen(0) + display.set_pen(15) + display.text("Unable to display weather! Check your network settings in WIFI_CONFIG.py", 5, 65, WIDTH, 1) + + cu.update(display) + + +while 1: + + get_data() + for count in range(500): + + if cu.is_pressed(CosmicUnicorn.SWITCH_A): + user_icon = 0 + if cu.is_pressed(CosmicUnicorn.SWITCH_B): + user_icon = 1 + if cu.is_pressed(CosmicUnicorn.SWITCH_C): + user_icon = 2 + if cu.is_pressed(CosmicUnicorn.SWITCH_D): + user_icon = 3 + if cu.is_pressed(CosmicUnicorn.SWITCH_BRIGHTNESS_UP): + user_icon = 4 + if cu.is_pressed(CosmicUnicorn.SWITCH_BRIGHTNESS_DOWN): + user_icon = None + draw_page(count) + time.sleep(0.2) From 9a613975d7324bdd048ce6482dc4456ed50e64ad Mon Sep 17 00:00:00 2001 From: Hel Gibbons Date: Fri, 24 Feb 2023 16:02:51 +0000 Subject: [PATCH 2/6] delete empty file --- micropython/examples/cosmic_unicorn/weather/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 micropython/examples/cosmic_unicorn/weather/README.md diff --git a/micropython/examples/cosmic_unicorn/weather/README.md b/micropython/examples/cosmic_unicorn/weather/README.md deleted file mode 100644 index e69de29bb..000000000 From 69ee5cff3ab3fb56a57215bd06a1f4bacea77d99 Mon Sep 17 00:00:00 2001 From: Hel Gibbons Date: Fri, 24 Feb 2023 16:20:16 +0000 Subject: [PATCH 3/6] remove out of date upip install code --- .../cosmic_unicorn/http_text/html_text.py | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/micropython/examples/cosmic_unicorn/http_text/html_text.py b/micropython/examples/cosmic_unicorn/http_text/html_text.py index a4316a2c2..88605b217 100644 --- a/micropython/examples/cosmic_unicorn/http_text/html_text.py +++ b/micropython/examples/cosmic_unicorn/http_text/html_text.py @@ -5,12 +5,15 @@ from network_manager import NetworkManager import uasyncio as asyncio import uasyncio.core - +from tinyweb.server import webserver ''' -Display scrolling wisdom, quotes or greetz. +Display scrolling wisdom, quotes or greetz... from the internetz! You can adjust the brightness with LUX + and -. + +Requires network_manager.py , WIFI_CONFIG.py, logging.mpy and tinyweb from micropython/examples/common +You'll also need index.html to be saved alongside this file. ''' # Server Settings @@ -56,24 +59,9 @@ def status_handler(mode, status, ip): print("IP: {}".format(ip)) MESSAGE = "{}".format(ip) - -try: - from tinyweb.server import webserver - -except ImportError: - # WIFI settings - WIFI_COUNTRY = "GB" # Changeme! - network_manager = NetworkManager(WIFI_COUNTRY, status_handler=status_handler) - uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK)) - # Install missing module - import upip - upip.install('logging') - from tinyweb.server import webserver - # Create web server application app = webserver() - # Static page html_file = open('index.html', 'r') @@ -201,9 +189,9 @@ async def message_update(): await asyncio.sleep(0.001) -# The folloing is required to run both the web server and the scrolling text coherantly +# The following is required to run both the web server and the scrolling text coherently app._server_coro = app._tcp_server(host, port, app.backlog) loop = asyncio.get_event_loop() t1 = loop.create_task(message_update()) t2 = loop.create_task(app._server_coro) -loop.run_forever() +loop.run_forever() \ No newline at end of file From 35cc345eb45333bb58e7b3fcfa806cc785bc4f19 Mon Sep 17 00:00:00 2001 From: Hel Gibbons Date: Fri, 24 Feb 2023 16:25:37 +0000 Subject: [PATCH 4/6] Hooray, linting! --- micropython/examples/cosmic_unicorn/http_text/html_text.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/micropython/examples/cosmic_unicorn/http_text/html_text.py b/micropython/examples/cosmic_unicorn/http_text/html_text.py index 88605b217..8ba4003ff 100644 --- a/micropython/examples/cosmic_unicorn/http_text/html_text.py +++ b/micropython/examples/cosmic_unicorn/http_text/html_text.py @@ -59,6 +59,7 @@ def status_handler(mode, status, ip): print("IP: {}".format(ip)) MESSAGE = "{}".format(ip) + # Create web server application app = webserver() @@ -194,4 +195,4 @@ async def message_update(): loop = asyncio.get_event_loop() t1 = loop.create_task(message_update()) t2 = loop.create_task(app._server_coro) -loop.run_forever() \ No newline at end of file +loop.run_forever() From ca9b9d6b6a0d6d4e27c7bcc4f83f668aa1703644 Mon Sep 17 00:00:00 2001 From: Gee Bartlett Date: Mon, 27 Feb 2023 12:22:19 +0000 Subject: [PATCH 5/6] checked and updated nostalga prompt example --- .../cosmic_unicorn/nostalgia_prompt.py | 106 ++++++++++++------ 1 file changed, 71 insertions(+), 35 deletions(-) diff --git a/micropython/examples/cosmic_unicorn/nostalgia_prompt.py b/micropython/examples/cosmic_unicorn/nostalgia_prompt.py index b114ce3f8..363d91383 100644 --- a/micropython/examples/cosmic_unicorn/nostalgia_prompt.py +++ b/micropython/examples/cosmic_unicorn/nostalgia_prompt.py @@ -6,58 +6,92 @@ A collection of copies of classic terminal styles including C64, MS-DOS, Spectrum, and more. Images and text are drawn pixel by pixel from a pattern of Os and Xs. - You can adjust the brightness with LUX + and -. ''' gu = CosmicUnicorn() graphics = PicoGraphics(DISPLAY) +prompt_x = 0 +prompt_y = 4 c64 = [ - " ", - " ", - " OOOOO OOOOOO OO OOOO OO OO XXXXXXX ", - " OO OO OO OOOO OO OO OO OO XXXXXXX ", - " OO OO OO OO OO OO OO OO OO XXXXXXX ", - " OOOOO OOOO OOOOOO OO OO OOOO XXXXXXX ", - " OOOO OO OO OO OO OO OO XXXXXXX ", - " OO OO OO OO OO OO OO OO OO XXXXXXX ", - " OO OO OOOOOO OO OO OOOO OO OO XXXXXXX ", - " XXXXXXX ", - " " + " ", + " ", + " OOOOO OOOOOO OO OOOO ", + " OO OO OO OOOO OO OO ", + " OO OO OO OO OO OO OO ", + " OOOOO OOOO OOOOOO OO OO ", + " OOOO OO OO OO OO OO ", + " OO OO OO OO OO OO OO ", + " OO OO OOOOOO OO OO OOOO ", + " ", + " ", + " ", + " ", + " OO OO XXXXXXX ", + " OO OO XXXXXXX ", + " OO OO XXXXXXX ", + " OOOO XXXXXXX ", + " OO XXXXXXX ", + " OO OO XXXXXXX ", + " OO OO XXXXXXX ", + " XXXXXXX ", + " " ] FOREGROUND_C64 = (230, 210, 250) BACKGROUND_C64 = (20, 20, 120) spectrum = [ - " ", - " ", - " O OOOO OOOO OOOOO O O O O XXXXXXXX ", - " O O O O O O O O O O O X XXXXXX ", - " O O O O O O O X XXXXXX ", - " O O O OOOOOO O O X XXXXXX ", - " O O O O O O O X XXXXXX ", - " OOOOOO OOOO O O OOOOO X XXXXXX ", - " X X ", - " XXXXXXXX ", - " " + " ", + " ", + " O OOOO OOOO OOOOO ", + " O O O O O O O ", + " O O O O O O O ", + " O O O OOOOOO O O ", + " O O O O O O O ", + " OOOOOO OOOO O O OOOOO ", + " ", + " ", + " ", + " ", + " ", + " O O O O XXXXXXXX ", + " O O O O X XXXXXX ", + " X XXXXXX ", + " X XXXXXX ", + " X XXXXXX ", + " X XXXXXX ", + " X X ", + " XXXXXXXX ", + " " ] FOREGROUND_SPECTRUM = (0, 0, 0) BACKGROUND_SPECTRUM = (180, 150, 150) bbc_micro = [ - " ", - " ", - " OOOOO OO OOOO OOO OOOO O ", - " O O O O O O O O O O ", - " O O O O O O O O ", - " OOOOO O O OOOO O O O ", - " O O OOOOOO O O O O ", - " O O O O O O O O O O ", - " OOOOO O O OOOO OOO OOOO O ", - " XXXXXXX ", - " " + " ", + " ", + " OOOOO OO OOOO OOO ", + " O O O O O O O ", + " O O O O O O ", + " OOOOO O O OOOO O ", + " O O OOOOOO O O ", + " O O O O O O O ", + " OOOOO O O OOOO OOO ", + " ", + " ", + " ", + " ", + " OOOO O ", + " O O O ", + " O O ", + " O O ", + " O O ", + " O O O ", + " OOOO O ", + " XXXXXXX ", + " " ] FOREGROUND_BBC_MICRO = (255, 255, 255) BACKGROUND_BBC_MICRO = (0, 0, 0) @@ -72,6 +106,8 @@ def draw(image, fg, bg, time_ms): fg_pen = graphics.create_pen(fg[0], fg[1], fg[2]) bg_pen = graphics.create_pen(bg[0], bg[1], bg[2]) + graphics.set_pen(bg_pen) + graphics.clear() for y in range(len(image)): row = image[y] for x in range(len(row)): @@ -87,7 +123,7 @@ def draw(image, fg, bg, time_ms): else: graphics.set_pen(bg_pen) - graphics.pixel(x, y) + graphics.pixel(x + prompt_x, y + prompt_y) gu.update(graphics) From d25b04c93f6b3f6f5e9e3e90e0f18645faca1f51 Mon Sep 17 00:00:00 2001 From: thirdr Date: Mon, 27 Feb 2023 13:44:30 +0000 Subject: [PATCH 6/6] standalone today example --- micropython/examples/cosmic_unicorn/today.py | 127 +++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 micropython/examples/cosmic_unicorn/today.py diff --git a/micropython/examples/cosmic_unicorn/today.py b/micropython/examples/cosmic_unicorn/today.py new file mode 100644 index 000000000..7b03aa5cd --- /dev/null +++ b/micropython/examples/cosmic_unicorn/today.py @@ -0,0 +1,127 @@ +import time +import network +import ntptime +import machine + +from cosmic import CosmicUnicorn +from picographics import PicoGraphics, DISPLAY_COSMIC_UNICORN as DISPLAY + +gu = CosmicUnicorn() +graphics = PicoGraphics(DISPLAY) + +# Default Brightness +gu.set_brightness(0.4) + +# You will need to create or update the file secrets.py with your network credentials using Thonny +# in order for the example to update using the NTP. + +# secrets.py should contain: +# WIFI_SSID = "" +# WIFI_PASSWORD = "" + +try: + from secrets import WIFI_SSID, WIFI_PASSWORD +except ImportError: + print("Create secrets.py with your WiFi credentials") + + +WIDTH = CosmicUnicorn.WIDTH +HEIGHT = CosmicUnicorn.HEIGHT + +rtc = machine.RTC() + +DAYS = ["Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"] + +# Enable the Wireless +wlan = network.WLAN(network.STA_IF) +wlan.active(True) + + +def network_connect(SSID, PSK): + + # Number of attempts to make before timeout + max_wait = 5 + + # Sets the Wireless LED pulsing and attempts to connect to your local network. + print("connecting...") + wlan.connect(SSID, PSK) + + while max_wait > 0: + if wlan.status() < 0 or wlan.status() >= 3: + break + max_wait -= 1 + print('waiting for connection...') + time.sleep(1) + + # Handle connection error. Switches the Warn LED on. + if wlan.status() != 3: + print("Unable to connect. Attempting connection again") + + +# Function to sync the Pico RTC using NTP +def sync_time(): + + try: + network_connect(WIFI_SSID, WIFI_PASSWORD) + except NameError: + print("Create secrets.py with your WiFi credentials") + + if wlan.status() < 0 or wlan.status() >= 3: + try: + ntptime.settime() + except OSError: + print("Unable to sync with NTP server. Check network and try again.") + + +def init(): + + sync_time() + + +def draw(): + + # Pens + RED = graphics.create_pen(120, 0, 0) + WHITE = graphics.create_pen(255, 255, 255) + + current_t = rtc.datetime() + + # Set the pen to Red and clear the screen. + graphics.set_pen(WHITE) + graphics.clear() + + # Measures the length of the text to help us with centring later. + day_length = graphics.measure_text(DAYS[current_t[3]], 1) + date_length = graphics.measure_text(str(current_t[2]), 3) + + graphics.set_font("bitmap6") + graphics.set_pen(RED) + graphics.rectangle(0, 0, WIDTH, 7) + graphics.set_pen(WHITE) + graphics.text(DAYS[current_t[3]], (WIDTH // 2) - (day_length // 2) - 1, 0, 32, 1) + + graphics.set_pen(RED) + graphics.set_font("bitmap8") + graphics.text(str(current_t[2]), (WIDTH // 2) - (date_length // 2) + 1, 9, 32, 3) + + graphics.set_pen(graphics.create_pen(0, 0, 0)) + + gu.update(graphics) + + +init() + +while 1: + + # Adjust Brightness +/- + if gu.is_pressed(CosmicUnicorn.SWITCH_BRIGHTNESS_UP): + gu.adjust_brightness(+0.01) + + if gu.is_pressed(CosmicUnicorn.SWITCH_BRIGHTNESS_DOWN): + gu.adjust_brightness(-0.01) + + # Connect to the network and sync with the NTP server + if gu.is_pressed(CosmicUnicorn.SWITCH_C): + sync_time() + + draw()