Navigation

    M5Stack Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    1. Home
    2. mb
    M
    • Continue chat with mb
    • Start new chat with mb
    • Flag Profile
    • Profile
    • Following
    • Followers
    • Blocks
    • Topics
    • Posts
    • Best
    • Groups
    Save
    Saving

    mb

    @mb

    Entrepreneur & tech nerd

    3
    Reputation
    75
    Posts
    1710
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online
    Location Europe

    mb Follow

    Posts made by mb

    • RE: [MicroPython] Add urllib.parse to base firmware to enable web services

      Adding upip to the firmware image would make developer's live much easier.

      How to manually install the urllib.parse library.

      Create folder /upip and add files upip.py and upip_utarfile.py manually.

      Install the library with upip:

      %cd /flash/upip
      import upip
      upip.install("micropython-urllib.parse", "/flash/lib")
      

      To get it working, remove re.py and ffilib.py from lib. Hat-tip to Andreas.

      Finally you can encode URL parameters for GET requests:

      %cd /flash/lib
      import urllib.parse
      urllib.parse.urlencode({"a":1, "b": 2})
      
      => 'a=1&b=2'
      
      posted in Features Wish List
      M
      mb
    • [MicroPython] Add urllib.parse to base firmware to enable web services

      I am currently playing around with some web services and libraries, it mostly fails because most of those MicroPython programs require urllib.parse to be installed, mostly for urlencode().

      It would be great to get urllib.parse and its dependencies into the base firmware image.

      Cheers
      Mike

      posted in Features Wish List
      M
      mb
    • RE: How to install MicroPython libraries? (HTTP GET with query parameters)

      Well, and there is always the option to just strip it down to the basics.

      # urlencode.py
      
      _ALWAYS_SAFE = frozenset(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                               b'abcdefghijklmnopqrstuvwxyz'
                               b'0123456789'
                               b'_.-')
      
      _ALWAYS_SAFE_BYTES = bytes(_ALWAYS_SAFE)
      
      
      def quote(string, safe='/', encoding=None, errors=None):
          """quote('abc def') -> 'abc%20def'
      
          Each part of a URL, e.g. the path info, the query, etc., has a
          different set of reserved characters that must be quoted.
      
          RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists
          the following reserved characters.
      
          reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
                        "$" | ","
      
          Each of these characters is reserved in some component of a URL,
          but not necessarily in all of them.
      
          By default, the quote function is intended for quoting the path
          section of a URL.  Thus, it will not encode '/'.  This character
          is reserved, but in typical usage the quote function is being
          called on a path where the existing slash characters are used as
          reserved characters.
      
          string and safe may be either str or bytes objects. encoding must
          not be specified if string is a str.
      
          The optional encoding and errors parameters specify how to deal with
          non-ASCII characters, as accepted by the str.encode method.
          By default, encoding='utf-8' (characters are encoded with UTF-8), and
          errors='strict' (unsupported characters raise a UnicodeEncodeError).
          """
          if isinstance(string, str):
              if not string:
                  return string
              if encoding is None:
                  encoding = 'utf-8'
              if errors is None:
                  errors = 'strict'
              string = string.encode(encoding, errors)
          else:
              if encoding is not None:
                  raise TypeError("quote() doesn't support 'encoding' for bytes")
              if errors is not None:
                  raise TypeError("quote() doesn't support 'errors' for bytes")
          return quote_from_bytes(string, safe)
      
      
      def quote_plus(string, safe='', encoding=None, errors=None):
          """Like quote(), but also replace ' ' with '+', as required for quoting
          HTML form values. Plus signs in the original string are escaped unless
          they are included in safe. It also does not have safe default to '/'.
          """
          # Check if ' ' in string, where string may either be a str or bytes.  If
          # there are no spaces, the regular quote will produce the right answer.
          if ((isinstance(string, str) and ' ' not in string) or
              (isinstance(string, bytes) and b' ' not in string)):
              return quote(string, safe, encoding, errors)
          if isinstance(safe, str):
              space = ' '
          else:
              space = b' '
          string = quote(string, safe + space, encoding, errors)
          return string.replace(' ', '+')
      
      
      def quote_from_bytes(bs, safe='/'):
          """Like quote(), but accepts a bytes object rather than a str, and does
          not perform string-to-bytes encoding.  It always returns an ASCII string.
          quote_from_bytes(b'abc def\x3f') -> 'abc%20def%3f'
          """
          if not isinstance(bs, (bytes, bytearray)):
              raise TypeError("quote_from_bytes() expected bytes")
          if not bs:
              return ''
          if isinstance(safe, str):
              # Normalize 'safe' by converting to bytes and removing non-ASCII chars
              safe = safe.encode('ascii', 'ignore')
          else:
              safe = bytes([c for c in safe if c < 128])
          if not bs.rstrip(_ALWAYS_SAFE_BYTES + safe):
              return bs.decode()
          try:
              quoter = _safe_quoters[safe]
          except KeyError:
              _safe_quoters[safe] = quoter = Quoter(safe).__getitem__
          return ''.join([quoter(char) for char in bs])
      
      
      def urlencode(query, doseq=False, safe='', encoding=None, errors=None):
          """Encode a dict or sequence of two-element tuples into a URL query string.
      
          If any values in the query arg are sequences and doseq is true, each
          sequence element is converted to a separate parameter.
      
          If the query arg is a sequence of two-element tuples, the order of the
          parameters in the output will match the order of parameters in the
          input.
      
          The components of a query arg may each be either a string or a bytes type.
          When a component is a string, the safe, encoding and error parameters are
          sent to the quote_plus function for encoding.
          """
      
          if hasattr(query, "items"):
              query = query.items()
          else:
              # It's a bother at times that strings and string-like objects are
              # sequences.
              try:
                  # non-sequence items should not work with len()
                  # non-empty strings will fail this
                  if len(query) and not isinstance(query[0], tuple):
                      raise TypeError
                  # Zero-length sequences of all types will get here and succeed,
                  # but that's a minor nit.  Since the original implementation
                  # allowed empty dicts that type of behavior probably should be
                  # preserved for consistency
              except TypeError:
      #            ty, va, tb = sys.exc_info()
                  raise TypeError("not a valid non-string sequence "
                                  "or mapping object")#.with_traceback(tb)
      
          l = []
          if not doseq:
              for k, v in query:
                  if isinstance(k, bytes):
                      k = quote_plus(k, safe)
                  else:
                      k = quote_plus(str(k), safe, encoding, errors)
      
                  if isinstance(v, bytes):
                      v = quote_plus(v, safe)
                  else:
                      v = quote_plus(str(v), safe, encoding, errors)
                  l.append(k + '=' + v)
          else:
              for k, v in query:
                  if isinstance(k, bytes):
                      k = quote_plus(k, safe)
                  else:
                      k = quote_plus(str(k), safe, encoding, errors)
      
                  if isinstance(v, bytes):
                      v = quote_plus(v, safe)
                      l.append(k + '=' + v)
                  elif isinstance(v, str):
                      v = quote_plus(v, safe, encoding, errors)
                      l.append(k + '=' + v)
                  else:
                      try:
                          # Is this a sufficient test for sequence-ness?
                          x = len(v)
                      except TypeError:
                          # not a sequence
                          v = quote_plus(str(v), safe, encoding, errors)
                          l.append(k + '=' + v)
                      else:
                          # loop over the sequence
                          for elt in v:
                              if isinstance(elt, bytes):
                                  elt = quote_plus(elt, safe)
                              else:
                                  elt = quote_plus(str(elt), safe, encoding, errors)
                              l.append(k + '=' + elt)
          return '&'.join(l)
      

      Then we can finally do a nicer GET with parameters:

      import urequests
      from urlencode import urlencode
      
      url = 'http://server.tld/path/to'
      params = {'key1': 'value1', 'key2': 'value2'}
      if params:
              url = url.rstrip('?') + '?' + urlencode(params, doseq=True)
      print(url)
      response = urequests.get(url)
      
      posted in Micropython
      M
      mb
    • RE: How to install MicroPython libraries? (HTTP GET with query parameters)

      Thanks, @ksprayberry, I can manually transfer files. I just thought there was a upip or something on the device which can be used from the REPL.

      posted in Micropython
      M
      mb
    • How to install MicroPython libraries? (HTTP GET with query parameters)

      I would like to do a simple HTTP GET requests with key-value params.

      This seems not supported by urequests, I found a recommended work-around:

      import urequests
      from urllib.parse import urlencode
      
      def get(url, params=None, **kw):
          if params:
              url = url.rstrip('?') + '?' + urlencode(params, doseq=True)
          return urequests.get(url, **kw)
      
      payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
      res = get('http://httpbin.org/get', payload)
      print(res.json())
      

      Sadly urllib.parse from micropython-lib is not included in M5Stack MicroPython.

      How can I install a MicroPython library onto my Core2? I am currently using Thonny IDE.

      posted in Micropython
      M
      mb
    • [Core2] Touch event handlers in [MicroPython]?

      Does Core2 support touch event handlers in MicroPython?

      I would like to define my own touch interface:

      alt text

      So far I only found the M5Btn class, but I can not use it to define transparent touch tiles.

      from m5stack import *
      from m5stack_ui import *
      from uiflow import *
      
      screen = M5Screen()
      screen.clean_screen()
      screen.set_screen_bg_color(0xFFFFFF)
      
      touch_button0 = M5Btn(text=None, x=0, y=0, w=100, h=80, bg_c=None, text_c=None, font=None, parent=None)
      
      def touch_button0_pressed():
        # global params
        pass
      touch_button0.pressed(touch_button0_pressed)
      

      alt text

      I tried to overwrite the button with my touch tiles, but after press the button is shown.

      lcd.fillRect(   0,   0, 100, 80, 0xff0000 )
      lcd.fillRect( 100,   0, 120, 80, 0x00ff00 )
      lcd.fillRect( 220,   0, 100, 80, 0x0000ff )    
      lcd.fillRect(   0,  80, 100, 80, 0xaa0000 )
      lcd.fillRect( 100,  80, 120, 80, 0x00aa00 )
      lcd.fillRect( 220,  80, 100, 80, 0x0000aa )    
      lcd.fillRect(   0, 160, 100, 80, 0x550000 )
      lcd.fillRect( 100, 160, 120, 80, 0x005500 )
      lcd.fillRect( 220, 160, 100, 80, 0x000055 )    
      

      alt text

      Or do I need to do this manually in a loop?

      import time
      from m5stack import *
      
      
      def tile(x,y):
          qx = 0
          qy = 0
      
          if x>=0 and x<100: qx = 1
          if x>=100 and x<220: qx = 2
          if x>=220 and x<320: qx = 3
          
          if y>=0 and y<80: qy = 0
          if y>=80 and y<160: qy = 3
          if y>=160 and y<240: qy = 6
      
          return qx + qy
      
      
      def action(q):
          if q == 0: lcd.clear(0xFFFFFF)
          if q == 1: lcd.fillRect(   0,   0, 100, 80, 0xff0000 )
          if q == 2: lcd.fillRect( 100,   0, 120, 80, 0x00ff00 )
          if q == 3: lcd.fillRect( 220,   0, 100, 80, 0x0000ff )    
          if q == 4: lcd.fillRect(   0,  80, 100, 80, 0xaa0000 )
          if q == 5: lcd.fillRect( 100,  80, 120, 80, 0x00aa00 )
          if q == 6: lcd.fillRect( 220,  80, 100, 80, 0x0000aa )    
          if q == 7: lcd.fillRect(   0, 160, 100, 80, 0x550000 )
          if q == 8: lcd.fillRect( 100, 160, 120, 80, 0x005500 )
          if q == 9: lcd.fillRect( 220, 160, 100, 80, 0x000055 )    
      
      
      def loop():
          x = -1
          y = -1
          while True:
              if touch.status() == True:
                  t = touch.read()
                  tx = t[0]
                  ty = t[1]
                  if x != tx and y != ty:
                      x = tx
                      y = ty
                      q = tile(x, y)
                      action(q);
              else:
                  x = -1
                  y = -1
                  action(0)
      
              time.sleep(0.05)
      
      
      loop()
      
      posted in Core 2
      M
      mb
    • RE: [Bug] Core2 loads JPG from flash but crashes with image from micro SD card

      Here we go, easy work-around for the faulty lcd.image():

      from m5stack import *
      buffer = open("/sd/images/test.jpg").read()
      lcd.image_buff(lcd.CENTER, lcd.CENTER, buffer)
      
      posted in Micropython
      M
      mb
    • RE: [Core2] How to download JPG from web and display it on screen?

      Here we go, easy work-around the faulty lcd.image():

      from m5stack import *
      buffer = open("/sd/images/test.jpg").read()
      lcd.image_buff(lcd.CENTER, lcd.CENTER, buffer)
      
      posted in Core 2
      M
      mb
    • RE: Check your uPython version

      I would prefer to have a stable API for all devices. Current situation makes re-use of code complicated.

      Someone could write a wrapper API to cover the differences ;-)

      alt text

      xkcd comic

      posted in PROJECTS
      M
      mb
    • RE: Why is support not responding?

      Hi, I think this is mostly a community-driven forum, so it is other developers that can answer.

      I am not sure that any staff is speaking Russian and participating in the Russian-language forum.

      posted in General
      M
      mb