diff --git a/PyBasic/basicparser.py b/PyBasic/basicparser.py index 10b8f21..44d1bbf 100644 --- a/PyBasic/basicparser.py +++ b/PyBasic/basicparser.py @@ -680,11 +680,23 @@ def __openstmt(self): raise RuntimeError('File '+filename+' could not be opened in line ' + str(self.__line_number)) if accessMode == "r+": + if hasattr(self.__file_handles[filenum],'newlines'): + try: + self.__file_handles[filenum].readline() + except: + pass + newlines = self.__file_handles[filenum].newlines + else: + newlines = None self.__file_handles[filenum].seek(0) filelen = 0 for lines in self.__file_handles[filenum]: - filelen += (len(lines)+(0 if uname()[0].upper() == 'LINUX' or \ - implementation.name.upper() in ['MICROPYTHON','CIRCUITPYTHON'] else 1)) + filelen += len(lines) + if newlines != None: + filelen += len(newlines)-1 + else: + filelen += (0 if uname()[0].upper() == 'LINUX' or \ + implementation.name.upper() in ['MICROPYTHON','CIRCUITPYTHON'] else 1) self.__file_handles[filenum].seek(filelen) diff --git a/PyBasic/program.py b/PyBasic/program.py index 0b5806a..a7e22e3 100644 --- a/PyBasic/program.py +++ b/PyBasic/program.py @@ -146,13 +146,26 @@ def load(self, file, tmpfile): try: infile = open(file, 'r') + if hasattr(infile,'newlines'): + try: + infile.readline() + except: + pass + newlines = infile.newlines + infile.seek(0) + else: + newlines = None fIndex = 0 fOffset = 0 pgmLoad = False if file.split(".")[-1].upper() == "PGM": pgmLoad = True for fileLine in infile: - fOffset += (len(fileLine) + (0 if self.__imp == 'X' else 1)) + fOffset += len(fileLine) + if newlines != None: + fOffset += len(newlines)-1 + elif self.__imp != 'X': + fOffset += 1 if len(fileLine) >= 9 and fileLine[0:9] == "-999,-999": break @@ -173,8 +186,11 @@ def load(self, file, tmpfile): if fileLine.strip().upper()[fileLine.strip().find(' '):].strip()[:4] == "DATA": self.__data.addData(line_number,fIndex) #self.add_stmt(Lexer().tokenize((fileLine.replace("\n","")).replace("\r","")),fIndex+fOffset,tmpfile) - fIndex += (len(fileLine) + (0 if self.__imp == 'X' else 1)) - + fIndex += len(fileLine) + if newlines != None: + fIndex += len(newlines)-1 + elif self.__imp != 'X': + fIndex += 1 except OSError: print("Could not read file") @@ -204,10 +220,22 @@ def add_stmt(self, tokenlist, fIndex, tmpfile): if tokenlist[1].lexeme == "DATA": self.__data.addData(line_number,fIndex) else: + if hasattr(tmpfile,'newlines'): + try: + tmpfile.readline() + except: + pass + newlines = tmpfile.newlines + else: + newlines = None tmpfile.seek(0) filelen = 0 for lines in tmpfile: - filelen += (len(lines)+(0 if self.__imp == 'X' else 1)) + filelen += len(lines) + if newlines != None: + filelen += len(newlines) - 1 + elif self.__imp != 'X': + filelen += 1 self.__program[line_number] = -(filelen+1) if tokenlist[1].lexeme == "DATA": diff --git a/PyDOS.py b/PyDOS.py index 5433e10..8cdedc9 100644 --- a/PyDOS.py +++ b/PyDOS.py @@ -73,7 +73,7 @@ def PyDOS(): global envVars if "envVars" not in globals().keys(): envVars = {} - _VER = "1.43" + _VER = "1.49" prmpVals = ['>','(',')','&','|','\x1b','\b','<','=',' ',_VER,'\n','$',''] print("Starting Py-DOS...") diff --git a/README.md b/README.md index 4857417..f14caba 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,10 @@ down - the number of tiles connected down the matrix display If the parameters are omitted or not properly formatted, the program will prompt for each of the values. -**Playimage.py [filename]** - (Circuitpython only, requires the adafruit_imageload library installed in the /lib folder) program to display .bmp, .jpg, .gif or .png image files. If the program is loaded from PyDOS it attempts to determine the appropriate display configuration from the PyDOS environment, otherwise several display options are supported and selected depending on the existence of BOARD.Display or locally installed display libraries. +**Playimage.py [filename[,filename2,filename3,etc[],seconds_to_display]]]** - (Circuitpython only, requires the adafruit_imageload library installed in the /lib folder) program to display .bmp, .jpg, .gif (incl animated) or .png image files. If multiple comma +seperated files are entered a continous slide show is displayed with each image being +displayed for `seconds_to_display` seconds. Wildcard's in the format of *.xxx can be used +as an input filename. If the program is loaded from PyDOS it attempts to determine the appropriate display configuration from the PyDOS environment, otherwise several display options are supported and selected depending on the existence of BOARD.DISPLAY or locally installed display libraries. **reboot.py** - performs a soft reboot (Micropython requires a Ctrl-D to complete) diff --git a/bounce.py b/bounce.py index 2f06d3d..374d409 100644 --- a/bounce.py +++ b/bounce.py @@ -8,7 +8,8 @@ Pydos_ui = None x = 10; y = 10; d = 1; e = 1 -m='⬤' +#m='⬤' +m='O' try: width = int(envVars.get('_scrWidth',80)) height = int(envVars.get('_scrHeight',24)) diff --git a/cpython/matrix.py b/cpython/matrix.py index 4d22d19..a7926c0 100644 --- a/cpython/matrix.py +++ b/cpython/matrix.py @@ -6,13 +6,19 @@ import framebufferio import rgbmatrix import supervisor +from os import getenv try: type(passedIn) +except: + passedIn = getenv('PYDOS_MATRIX_CONFIG') + +try: args = passedIn.split(',') [base_width,base_height,bit_depth,chain_across,tile_down] = [int(p) for p in args] except: passedIn = "" + args = "" if len(args) != 5 or args[0] not in ['32','64'] or args[1] not in ['32','64'] or bit_depth < 1 or bit_depth > 8: try: diff --git a/cpython/playimage.py b/cpython/playimage.py index 8288f5c..19e6b99 100644 --- a/cpython/playimage.py +++ b/cpython/playimage.py @@ -3,13 +3,22 @@ import gifio except: pass +import adafruit_ticks import adafruit_imageload import bitmaptools import displayio -import time from os import getenv +from supervisor import runtime try: from pydos_ui import Pydos_ui + readkbd = Pydos_ui.read_keyboard + sba = Pydos_ui.serial_bytes_available +except: + Pydos_ui = [] + from sys import stdin + readkbd = stdin.read + sba = lambda : runtime.serial_bytes_available +try: from pydos_ui import input Pydos_display = ('display' in dir(Pydos_ui)) except: @@ -19,28 +28,32 @@ type(envVars) except: envVars = {} - + +display = None if '_display' in envVars.keys(): display = envVars['_display'] elif Pydos_display: display = Pydos_ui.display -elif 'DISPLAY' in dir(board): +elif bool(getattr(board,'DISPLAY',False)): display = board.DISPLAY +elif bool(getattr(runtime,'display',False)): + display = runtime.display else: try: - import matrix - display = matrix.envVars['_display'] + import framebufferio + import dotclockframebuffer except: try: - import framebufferio - import dotclockframebuffer + import adafruit_ili9341 except: try: - import adafruit_ili9341 - except: - import framebufferio + # import framebufferio import picodvi + except: + import matrix + display = matrix.envVars['_display'] + if display == None: displayio.release_displays() if 'TFT_PINS' in dir(board): @@ -79,88 +92,78 @@ def playimage(passedIn=""): if passedIn != "": - fname = passedIn + flist = passedIn else: - fname = "" + flist = "" - if fname == "": - fname = input("Enter filename: ") + if flist == "": + flist = input("Enter filename: ") try: while Pydos_ui.virt_touched(): pass except: pass - if fname==passedIn: + if flist==passedIn: print('Press "q" to quit') else: input('Press "Enter" to continue, press "q" to quit') - if fname[-4:].upper() in [".BMP",".PNG",".JPG",".RLE"]: - - bitmap, palette = adafruit_imageload.load( \ - fname, bitmap=displayio.Bitmap, palette=displayio.Palette) - - scalefactor = display.width / bitmap.width - if display.height/bitmap.height < scalefactor: - scalefactor = display.height/bitmap.height + files = flist.split(',') + try: + dispseconds = int(files[-1]) + files = files[:-1] + except: + dispseconds = 15 - if scalefactor < 1: - print(f'scalefactor: {scalefactor}') - bitframe = displayio.Bitmap(display.width,display.height,2**bitmap.bits_per_value) - bitmaptools.rotozoom(bitframe,bitmap,scale=scalefactor) - facecc = displayio.TileGrid(bitframe,pixel_shader=palette) - # pixel_shader=displayio.ColorConverter(input_colorspace=colorspace)) - pwidth = bitframe.width - pheight = bitframe.height - else: - facecc = displayio.TileGrid(bitmap,pixel_shader=palette) - # pixel_shader=displayio.ColorConverter(input_colorspace=colorspace)) - pwidth = bitmap.width - pheight = bitmap.height - - print("bitmap (w,h): ",bitmap.width,bitmap.height) - print("scaled bitmap (w,h): ",pwidth,pheight) - print("facecc (w,h): ",facecc.width,facecc.height) - - if pwidth < display.width: - facecc.x = (display.width-pwidth)//2 - if pheight < display.height: - facecc.y = (display.height-pheight)//2 - splash = displayio.Group() - splash.append(facecc) - display.root_group = splash + singleimage = False + if len(files) == 1 and files[0][0] != '*': + singleimage = True - input('Press Enter to close') + fileindx = 0 + wildindx = 0 + while True: + fname = files[fileindx] - elif fname[-4:].upper() in [".GIF"]: + if fname[0] == '*': + wildlist = [f for f in os.listdir() if f[fname.find('.')-len(fname):] == fname[fname.find('.')-len(fname):]] + fname = wildlist[wildindx] + wildindx = (wildindx +1) % len(wildlist) + if wildindx == 0: + fileindx = (fileindx + 1) % len(files) + else: + fileindx = (fileindx + 1) % len(files) - odgcc = gifio.OnDiskGif(fname) - with odgcc as odg: - if getenv('PYDOS_DISPLAYIO_COLORSPACE',"").upper() == 'BGR565_SWAPPED': - colorspace = displayio.Colorspace.BGR565_SWAPPED - else: - colorspace = displayio.Colorspace.RGB565_SWAPPED + if fname[-4:].upper() in [".BMP",".PNG",".JPG",".RLE"]: - scalefactor = display.width / odg.width - if display.height/odg.height < scalefactor: - scalefactor = display.height/odg.height + bitmap, palette = adafruit_imageload.load( \ + fname, bitmap=displayio.Bitmap, palette=displayio.Palette) + + scalefactor = display.width / bitmap.width + if display.height/bitmap.height < scalefactor: + scalefactor = display.height/bitmap.height if scalefactor < 1: - print(f'scalefactor: {scalefactor}') - bitframe = displayio.Bitmap(display.width,display.height,2**odg.bitmap.bits_per_value) - bitmaptools.rotozoom(bitframe,odg.bitmap,scale=scalefactor) - facecc = displayio.TileGrid(bitframe, \ - pixel_shader=displayio.ColorConverter(input_colorspace=colorspace)) + if singleimage: + print(f'scalefactor: {scalefactor}') + bitframe = displayio.Bitmap(display.width,display.height,2**bitmap.bits_per_value) + bitmaptools.rotozoom(bitframe,bitmap,scale=scalefactor) + facecc = displayio.TileGrid(bitframe,pixel_shader=palette) + # pixel_shader=displayio.ColorConverter(input_colorspace=colorspace)) pwidth = bitframe.width pheight = bitframe.height else: - facecc = displayio.TileGrid(odg.bitmap, \ - pixel_shader=displayio.ColorConverter(input_colorspace=colorspace)) - pwidth = odg.bitmap.width - pheight = odg.bitmap.height + facecc = displayio.TileGrid(bitmap,pixel_shader=palette) + # pixel_shader=displayio.ColorConverter(input_colorspace=colorspace)) + pwidth = bitmap.width + pheight = bitmap.height + if singleimage: + print("bitmap (w,h): ",bitmap.width,bitmap.height) + print("scaled bitmap (w,h): ",pwidth,pheight) + print("facecc (w,h): ",facecc.width,facecc.height) + if pwidth < display.width: facecc.x = (display.width-pwidth)//2 if pheight < display.height: @@ -169,27 +172,104 @@ def playimage(passedIn=""): splash.append(facecc) display.root_group = splash - start = 0 - next_delay = -1 - cmnd = "" - # Display repeatedly. - while cmnd.upper() != "Q": - - if Pydos_ui.serial_bytes_available(): - cmnd = Pydos_ui.read_keyboard(1) - print(cmnd, end="", sep="") - if cmnd in "qQ": - break - while time.monotonic() > start and next_delay > time.monotonic()-start: - pass - next_delay = odg.next_frame() - start = time.monotonic() - if next_delay > 0: - if scalefactor < 1: - bitmaptools.rotozoom(bitframe,odg.bitmap,scale=scalefactor) + if singleimage: + input('Press Enter to close') + break + else: + cmnd = "" + stop = adafruit_ticks.ticks_add(adafruit_ticks.ticks_ms(),int(dispseconds*1000)) + while adafruit_ticks.ticks_less(adafruit_ticks.ticks_ms(),stop): + if sba(): + cmnd = readkbd(1) + print(cmnd, end="", sep="") + if cmnd.upper() == "Q": + break + if cmnd.upper() == "Q": + break + + try: + splash.pop() + bitmap.deinit() + bitmap = None + facecc.bitmap.deinit() + facecc = None + if scalefactor < 1: + bitframe.deinit() + bitframe = None + except: + pass - else: - print('Unknown filetype') + elif fname[-4:].upper() in [".GIF"]: + + odgcc = gifio.OnDiskGif(fname) + with odgcc as odg: + + if getenv('PYDOS_DISPLAYIO_COLORSPACE',"").upper() == 'BGR565_SWAPPED': + colorspace = displayio.Colorspace.BGR565_SWAPPED + else: + colorspace = displayio.Colorspace.RGB565_SWAPPED + + scalefactor = display.width / odg.width + if display.height/odg.height < scalefactor: + scalefactor = display.height/odg.height + + if scalefactor < 1: + if singleimage: + print(f'scalefactor: {scalefactor}') + bitframe = displayio.Bitmap(display.width,display.height,2**odg.bitmap.bits_per_value) + bitmaptools.rotozoom(bitframe,odg.bitmap,scale=scalefactor) + facecc = displayio.TileGrid(bitframe, \ + pixel_shader=displayio.ColorConverter(input_colorspace=colorspace)) + pwidth = bitframe.width + pheight = bitframe.height + else: + facecc = displayio.TileGrid(odg.bitmap, \ + pixel_shader=displayio.ColorConverter(input_colorspace=colorspace)) + pwidth = odg.bitmap.width + pheight = odg.bitmap.height + + if pwidth < display.width: + facecc.x = (display.width-pwidth)//2 + if pheight < display.height: + facecc.y = (display.height-pheight)//2 + splash = displayio.Group() + splash.append(facecc) + display.root_group = splash + + cmnd = "" + # Display repeatedly. + stop = adafruit_ticks.ticks_add(adafruit_ticks.ticks_ms(),int(dispseconds*1000)) + while adafruit_ticks.ticks_less(adafruit_ticks.ticks_ms(),stop) or singleimage: + + if sba(): + cmnd = readkbd(1) + print(cmnd, end="", sep="") + if cmnd.upper() == "Q": + break + start = adafruit_ticks.ticks_ms() + next_delay = odg.next_frame() + start = adafruit_ticks.ticks_add(start,int(next_delay*1000)) + if next_delay > 0: + if scalefactor < 1: + bitmaptools.rotozoom(bitframe,odg.bitmap,scale=scalefactor) + while adafruit_ticks.ticks_less(adafruit_ticks.ticks_ms(),start): + pass + if cmnd.upper() == "Q": + break + + try: + splash.pop() + odgcc = None + facecc.bitmap.deinit() + facecc = None + if scalefactor < 1: + bitframe.deinit() + bitframe = None + except: + pass + + else: + print('Unknown filetype') try: splash.pop() diff --git a/fileview.py b/fileview.py index d51472c..9c23e39 100644 --- a/fileview.py +++ b/fileview.py @@ -1,12 +1,21 @@ import os -from pydos_ui import Pydos_ui +import supervisor +from sys import implementation +try: + from pydos_ui import Pydos_ui +except: + Pydos_ui = None + from sys import stdin try: from pydos_ui import input except: pass #import uselect -def viewFile(args): +def viewFile(args,scrsiz=()): + # scrsiz can be used if running program from REPL to specify the screen dimensions + # first import launches with defaults but subsequent launches can use: + # fileview.viewFile("filename.txt",(height,width)) def chkPath(tstPath): validPath = True @@ -60,19 +69,34 @@ def absolutePath(argPath,currDir): scrLines = int(envVars["_scrHeight"]) scrWidth = int(envVars["_scrWidth"]) + elif scrsiz: + (scrLines,scrWidth) = scrsiz elif 'get_screensize' in dir(Pydos_ui): (scrLines,scrWidth) = Pydos_ui.get_screensize() else: - scrLines = 24 - scrWidth = 80 + if 'height' in dir(supervisor.runtime.display): + scrLines = supervisor.runtime.display.height + scrWidth = supervisor.runtime.display.width + else: + scrLines = 24 + scrWidth = 80 + + try: + type(envVars) + except: + envVars={} if "_scrollable" in envVars.keys(): - scrollable = (envVars["_scrollable"] == True) + scrollable = (envVars["_scrollable"] == True) or (envVars["_scrollable"] == "True") else: try: scrollable = Pydos_ui.scrollable except: - scrollable = False + if implementation.name.upper() == 'CIRCUITPYTHON': + # Once CircuitPython 9.2.4 is stable this can be change to True + scrollable = False + else: + scrollable = False savDir = os.getcwd() args = absolutePath(args,savDir) @@ -108,7 +132,10 @@ def absolutePath(argPath,currDir): strtCol = 0 while cmnd.upper() != "Q": #cmnd = kbdInterrupt() - cmnd = Pydos_ui.read_keyboard(1) + if Pydos_ui: + cmnd = Pydos_ui.read_keyboard(1) + else: + cmnd = stdin.read(1) if ord(cmnd) == 27 and seqCnt == 0: seqCnt = 1 diff --git a/getdate.py b/getdate.py index 5f1b7a2..7e8a41a 100644 --- a/getdate.py +++ b/getdate.py @@ -28,32 +28,7 @@ def getdate(passedIn=""): print("Attempting to set Date/Time",end="") try: - print(" Using http worldtimeapi.org...",end="") - response = Pydos_wifi.get("http://worldtimeapi.org/api/ip",None,True) - time_data = Pydos_wifi.json() - - if passedIn == "": - tz_hour_offset = int(time_data['utc_offset'][0:3]) - tz_min_offset = int(time_data['utc_offset'][4:6]) - if (tz_hour_offset < 0): - tz_min_offset *= -1 - else: - tz_hour_offset = int(passedIn) - tz_min_offset = 0 - - unixtime = int(time_data['unixtime'] + (tz_hour_offset * 60 * 60)) + (tz_min_offset * 60) - ltime = time.localtime(unixtime) - - if sys.implementation.name.upper() == "MICROPYTHON": - machine.RTC().datetime(tuple([ltime[0]-(time.localtime(0)[0]-1970)]+[ltime[i] for i in [1,2,6,3,4,5,7]])) - else: - rtc.RTC().datetime = ltime - - print("\nTime and Date successfully set",end="") - envVars['errorlevel'] = '0' - - except: - print( " FAILED. Trying NTP...",end="") + print( "Trying NTP...",end="") if passedIn == "": tz_hour_offset = -4 @@ -116,6 +91,33 @@ def getdate(passedIn=""): print("\nTime and Date successfully set",end="") envVars['errorlevel'] = '0' + except: + + print("FAILED. Trying http worldtimeapi.org...",end="") + Pydos_wifi.timeout = 1000 + response = Pydos_wifi.get("http://worldtimeapi.org/api/ip",None,True) + time_data = Pydos_wifi.json() + + if passedIn == "": + tz_hour_offset = int(time_data['utc_offset'][0:3]) + tz_min_offset = int(time_data['utc_offset'][4:6]) + if (tz_hour_offset < 0): + tz_min_offset *= -1 + else: + tz_hour_offset = int(passedIn) + tz_min_offset = 0 + + unixtime = int(time_data['unixtime'] + (tz_hour_offset * 60 * 60)) + (tz_min_offset * 60) + ltime = time.localtime(unixtime) + + if sys.implementation.name.upper() == "MICROPYTHON": + machine.RTC().datetime(tuple([ltime[0]-(time.localtime(0)[0]-1970)]+[ltime[i] for i in [1,2,6,3,4,5,7]])) + else: + rtc.RTC().datetime = ltime + + print("\nTime and Date successfully set",end="") + envVars['errorlevel'] = '0' + print() Pydos_wifi.close() diff --git a/lib/pydos_bcfg.py b/lib/pydos_bcfg.py index 92ce74e..bf659c4 100644 --- a/lib/pydos_bcfg.py +++ b/lib/pydos_bcfg.py @@ -47,7 +47,7 @@ from machine import Pin try: led = "LED" - test = machine.Pin(led,Pin.OUT) + test = Pin(led,Pin.OUT) except: led = "D13" diff --git a/lib/pydos_ui.py b/lib/pydos_ui.py index 64e8211..638a1f0 100644 --- a/lib/pydos_ui.py +++ b/lib/pydos_ui.py @@ -6,6 +6,7 @@ import select if implementation.name.upper() == "CIRCUITPYTHON": import board + from supervisor import runtime try: from displayio import CIRCUITPYTHON_TERMINAL as TERM from terminalio import FONT @@ -15,8 +16,15 @@ class PyDOS_UI: def __init__(self): - if implementation.name.upper() == "CIRCUITPYTHON" and 'DISPLAY' in dir(board): + if implementation.name.upper() == "CIRCUITPYTHON": + self.scrollable = False + if bool(getattr(board,'DISPLAY',False)): + self.display = board.DISPLAY + elif bool(getattr(runtime,'display',False)): + self.display = runtime.display + else: + self.scrollable = True else: self.scrollable = True @@ -32,7 +40,6 @@ def serial_bytes_available(self,timeout=1): retval = 0 else: retval = 1 - retval = 1 if retval else 0 return retval @@ -46,8 +53,8 @@ def get_screensize(self,disp=None): dhigh = disp.height dwide = disp.width else: - dhigh = board.DISPLAY.height - dwide = board.DISPLAY.width + dhigh = self.display.height + dwide = self.display.width height = round(dhigh/(FONT.bitmap.height*TERM.scale))-1 width = round(dwide/((FONT.bitmap.width/95)*TERM.scale))-2 diff --git a/lib/pydos_wifi.py b/lib/pydos_wifi.py index 53a6f88..78db3c2 100644 --- a/lib/pydos_wifi.py +++ b/lib/pydos_wifi.py @@ -1,4 +1,4 @@ -PyDOS_wifi_VER = "1.40" +PyDOS_wifi_VER = "1.47" import os import time @@ -214,6 +214,10 @@ def get(self,text_url,headers=None,getJSON=False): return self.response + def post(self,text_url,data): + self.response = self._requests.post(text_url,data=data) + return self.response + def json(self): retVal = None if implementation.name.upper() == 'CIRCUITPYTHON': diff --git a/wifi_finance.py b/wifi_finance.py index e9b46f2..1e49cdd 100644 --- a/wifi_finance.py +++ b/wifi_finance.py @@ -4,6 +4,7 @@ from sys import implementation from os import uname from pydos_wifi import Pydos_wifi +import time def wifi_finance(symbol): try: @@ -12,11 +13,12 @@ def wifi_finance(symbol): _scrWidth = 80 if not symbol: - symbol = "IXIC" + symbol = ".IXIC:INDEXNASDAQ" else: symbol = symbol.upper() - prt_sym = symbol - srch_sym = symbol + prt_sym = symbol[:symbol.find(':')] + srch_sym = symbol[:symbol.find(':')] + search_attempts = 5000 # Get wifi details and more from a .env file if Pydos_wifi.getenv('CIRCUITPY_WIFI_SSID') is None: @@ -24,8 +26,16 @@ def wifi_finance(symbol): print("Connecting to %s" % Pydos_wifi.getenv('CIRCUITPY_WIFI_SSID')) - if not Pydos_wifi.connect(Pydos_wifi.getenv('CIRCUITPY_WIFI_SSID'), Pydos_wifi.getenv('CIRCUITPY_WIFI_PASSWORD')): - raise Exception("Unable to connect to WiFi!") + res = False + for i in range(2): + try: + res = Pydos_wifi.connect(Pydos_wifi.getenv('CIRCUITPY_WIFI_SSID'), Pydos_wifi.getenv('CIRCUITPY_WIFI_PASSWORD')) + break + except: + print('Retrying....') + if not res: + if not Pydos_wifi.connect(Pydos_wifi.getenv('CIRCUITPY_WIFI_SSID'), Pydos_wifi.getenv('CIRCUITPY_WIFI_PASSWORD')): + raise Exception("Unable to connect to WiFi!") print("My IP address is", Pydos_wifi.ipaddress) @@ -36,16 +46,24 @@ def wifi_finance(symbol): #search_string = 'data-symbol="^IXIC" data-field="regularMarketChangePercent"' #TEXT_URL = "https://www.moneycontrol.com/us-markets" #search_string = 'Nasdaq' + #TEXT_URL = f"https://www.google.com/search?q={symbol.replace('&','%26')}+stock+price" + #search_string = symbol + #Id_Symbol = True + #price_ident = '%)' + #window_depth=4 - TEXT_URL = f"https://www.google.com/search?q={symbol.replace('&','%26')}+stock+price" + TEXT_URL = f"https://www.google.com/finance/quote/%7Bsymbol.replace('&','%26')}" search_string = symbol + Id_Symbol = False + price_ident = 'data-last-price' + window_depth = 5 #headers = {"user-agent": "RetiredWizard@"+implementation.name.lower()+uname()[2]} print("Fetching text from %s" % TEXT_URL) response = Pydos_wifi.get(TEXT_URL) response_window = [] - for _ in range(4): + for _ in range(window_depth): response_window.append(Pydos_wifi.next(256)) if len(response_window[-1]) != 256: break @@ -61,58 +79,65 @@ def wifi_finance(symbol): print(pline) print("-" * _scrWidth) - print("Identifying symbol",end="") - name_loc = -1 iKount = 0 - while name_loc == -1 and iKount<800: - iKount +=1 - if iKount % 10 == 0: - print(".",end="") - - found_window = str(b''.join(response_window)) - - name_loc = found_window.find(' Inc. is') - if name_loc == -1: - name_loc = found_window.find(' Inc., commonly') - if name_loc == -1: - name_loc = found_window.find(' is a stock market ') - if name_loc != -1: - if found_window[:name_loc].rfind('or simply the ') != -1: - srch_sym = found_window[found_window[:name_loc].rfind('or simply the ')+14:name_loc] - elif found_window[:name_loc].rfind('>') != -1: - srch_sym = found_window[found_window[:name_loc].rfind('>')+1:name_loc] - srch_sym = srch_sym.replace(',','') - prt_sym = srch_sym.replace('&','&') - prt_sym = prt_sym.replace('amp;','') - if srch_sym[0:4].upper() == 'THE ': - srch_sym = srch_sym[4:] - print(f'* {search_string} * {srch_sym} * {prt_sym}',end="") - - if iKount<800: - for i in range(3): - response_window[i] = response_window[i+1] - try: - response_window[3] = Pydos_wifi.next(256) - if len(response_window[3]) != 256: - print('X',end="") - iKount=800 - except: - iKount=800 - print() - - print("Locating price data",end="") - response.close() - response = Pydos_wifi.get(TEXT_URL) - response_window = [] - iKount = 0 - for _ in range(4): - response_window.append(Pydos_wifi.next(256)) - if len(response_window[-1]) != 256: - iKount = 799 - break + if Id_Symbol: + print("Identifying symbol",end="") + name_loc = -1 + while name_loc == -1 and iKount') != -1: + srch_sym = found_window[found_window[:name_loc].rfind('>')+1:name_loc] + srch_sym = srch_sym.replace(',','') + prt_sym = srch_sym.replace('&','&') + prt_sym = prt_sym.replace('amp;','') + if srch_sym[0:4].upper() == 'THE ': + srch_sym = srch_sym[4:] + print(f'* {search_string} * {srch_sym} * {prt_sym}',end="") + + if iKount')+1 - pctend = pct + found_window[pct:].find('<') - #print("Debug: %s\n" % found_window[nasdaq:pctend]) - pricest = found_window[:pctst-2].rfind('>')+1 - priceend = pricest + found_window[pricest:].find('<') - if nasdaq != -1: - print(f'{prt_sym}: {found_window[pricest:priceend]} {found_window[pctst:pctend].replace("<","")}\n') +# Final scrape logic +# Google Search +# pct = found_window.find(price_ident) +# pctst = found_window[:pct].rfind('>')+1 +# pctend = pct + found_window[pct:].find('<') +# print("Debug: %s\n" % found_window[nasdaq:pctend]) +# pricest = found_window[:pctst-2].rfind('>')+1 +# priceend = pricest + found_window[pricest:].find('<') + +# Google finance + pricest = found_window.find(price_ident)+len(price_ident)+2 + priceend = pricest + found_window[pricest:].find('"') + pctst = -1 + + #print(f'Debug: start loc: {pricest} end loc: {priceend}\n{found_window[nasdaq:]}') + + print(f'{prt_sym}: {found_window[pricest:priceend]}',end="") + if pctst != -1: + print(f' {found_window[pctst:pctend].replace("<","")}\n') + else: + print('\n') else: print(f"{prt_sym} symbol not found\n") @@ -172,8 +210,23 @@ def wifi_finance(symbol): del response_window del found_window +print('\nDemonstration Web "scraping" program. The web sites being used in the') +print('demonstration will often change and break the algorithm used to locate a') +print('stock price. When that happens this program needs to be updated to work') +print('with the new web site or find a new one.\n') +print('The current web site being used is: https://www.google.com/finance\n') +print('With this site the symbol passed to wifi_finance must be formatted as') +print('follows: symbol:exchange. So for Apple Inc, you would enter AAPL:NASDAQ') +print('or for AT&T enter T:NYSE. To retrieve the price of an index format the') +print('symbol as follows: .indexsymbol:INDEXsymbol. For example Nasdaq:') +print('.IXIC:INDEXNASDAQ, Dow Jones: .DJI:INDEXDJX, S&P 500: .INX:INDEXSP. The') +print('index symbols can be retrieved by going to the www.google.com/finance page') +print("and selecting the index you're inerested in. The formatted symbol will be") +print('updated at the end of the URL (not the symbol displayed in the search box.') + if __name__ == "PyDOS": wifi_finance(passedIn) else: print('Enter "wifi_finance.wifi_finance("symbol")" in the REPL or PEXEC command to run.') - print(' A null symbol ("") will default to the Nasdaq Index') \ No newline at end of file + print(' A null symbol ("") will default to the Nasdaq Index') +