MicroBlocks and Python Communication with Messages
MicroBlocks and Snap! Communication with Messages is really cool ! It is so easy and fun !
I want MicroBlocks to interoperate with more other ecologies. and I had some difficulties when I tried Python:
import serial # https://pyserial.readthedocs.io/
ser = serial.Serial('/dev/tty.usbmodem1402')
def microblocks_send(aString):
global ser
length = len(aString) + 1
rList = [251, 27, 0, length % 256, int(length/256)]
for i in aString:
rList.append(ord(i))
rList.append(254)
ser.write(bytearray(rList)) # https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.write
print(rList)
print(bytearray(rList))
microblocks_send('on')
#[251, 27, 0, 3, 0, 111, 110, 254]
# bytearray(b'\xfb\x1b\x00\x03\x00on\xfe')
The above code does not work, But it works fine in Snap! I referenced Microblocks Serial Protocol (version 2.09), but I still couldn't solve the problem
Comments (16)
-
repo owner -
reporter You are right! Thanks!
-
reporter - changed status to resolved
-
reporter - changed status to open
-
reporter When I read the message from MicroBlocks, the result is always the same(The problem seems to be the loop variable i):
import time from microblocks_messaging_library import MicroblocksMessage # See below m = MicroblocksMessage() m.connect('/dev/tty.usbmodem1402') # replace the string with micro:bit port # send message from Python to MicroBlocks m.send('happy') time.sleep(1) m.send('sad') # receive message from MicroBlocks while True: message = m.recv() print(message) # The output is always the same
here is the
MicroblocksMessage
classimport serial class MicroblocksMessage: def __init__(self, verbose=False): self._verbose = verbose # verbose: Print various debugging information self.ser = None self._buffer = bytearray() def connect(self, port, baudrate=115200): self.ser = serial.Serial(port, baudrate) def __anext__(self): self.close() def disconnect(self): self.ser.close() def send(self, aString): length = len(aString) + 1 rList = [251, 27, 0, length % 256, int(length / 256)] for i in aString: rList.append(ord(i)) rList.append(254) self.ser.write(bytearray(rList)) def _match(self, in_, filter="*"): msgLen = None end = None cmd = None result = [] length = len(in_) i = 1 # b2 = None while True: while not ((i > length) or (in_[(i - 1)] == 250) or (in_[(i - 1)] == 251)): i += 1 print(i) if length - i < 2: in_ = in_[(i - 1) :] return result cmd = in_[(i - 1) + 1] if in_[(i - 1)] == 250: if (not (type(filter) == int)) or cmd == filter: result.append(in_[(i - 1) + 1 : (i - 1) + 2]) i += 3 else: if in_[(i - 1)] == 251 and length - i > 3: msgLen = 256 * (in_[(i - 1) + 4]) + in_[(i - 1) + 3] end = i + 4 + msgLen # i-1? if end > length: in_ = in_[(i - 1) :] return result if (not (type(filter) == int)) or cmd == filter: result.append(in_[(i-1) + 1: (end-1)]) i = end + 1 else: in_ = in_[(i - 1) :] return result def recv(self): # todo callback msg = None msgType = None length = None # data = list(self.ser.read()) data = self.ser.read() if data: self._buffer = self._buffer + data for msgBytes in self._match(self._buffer, 27): length = len(msgBytes) if length > 4: msg = msgBytes[(5 - 1) :] msg = msg.decode("utf-8") return msg
The above code is translated from Snap!
-
repo owner Cool idea to make Python interact with MicroBlocks! I'll take a look when I get a chance. What's the MicroBlocks script you're using to test?
-
reporter here is the MicroBlocks script
If I solve the problem, I will publish the python library to pypi and github.
-
repo owner Here's a Python that sends and receives broadcast messages from MicroBlocks.
import serial import time class MicroblocksMessage: def __init__(self): self.ser = None self._buffer = bytearray() def connect(self, port): self.ser = serial.Serial(port, 115200) def disconnect(self): self.ser.close() def sendBroadcast(self, aString): utf8 = aString.encode('utf-8') length = len(utf8) + 1 bytes = bytearray([251, 27, 0, length % 256, int(length / 256)]) + utf8 + b'\xfe' self.ser.write(bytes) def receiveBroadcasts(self): result = [] data = self.ser.read() if data: self._buffer = self._buffer + data for msgBytes in self._match(27): result.append(msgBytes[4 :].decode("utf-8")) return result def _match(self, filter="*"): buf = self._buffer result = [] bytesRemaining = None cmd = None msgLen = None end = None length = len(buf) i = 0 while True: while not ((i >= length) or (buf[i] == 250) or (buf[i] == 251)): i += 1 # skip to start of next message bytesRemaining = length - i if (bytesRemaining < 1): # nothing to process self._buffer = buf[i :] return result cmd = buf[i] if (cmd == 250) and (bytesRemaining >= 3): # short message (3 bytes) if (filter == '*') or (filter == buf[i + 1]): result.append(buf[i : i + 3]) i += 3 elif (cmd == 251) and (bytesRemaining >= 5): # long message (>= 5 bytes) msgLen = (256 * buf[i + 4]) + buf[i + 3] end = i + 5 + msgLen if end > length: # long message is not yet complete self._buffer = buf[i :] return result if (filter == '*') or (filter == buf[i + 1]): result.append(buf[i : end]) i = end else: self._buffer = buf[i :] return result m = MicroblocksMessage() m.connect('/dev/tty.usbmodem2102') # replace the string with micro:bit port # broadcast messages from Python to MicroBlocks m.sendBroadcast('sad') time.sleep(1) m.sendBroadcast('happy') time.sleep(1) m.sendBroadcast('clear') # receive broadcasts from MicroBlocks while True: for msg in m.receiveBroadcasts(): print(msg)
And some MicroBlocks code for testing (you can save this PNG file, then drag it into MicroBlocks to load the scripts):
-
reporter -
repo owner Thanks for publishing it. I wonder how many people will use it? Do you have plans for using it in a project?
-
reporter I added the message flow diagram
I wonder how many people will use it?
It is currently being used at Elite. I recommended it to some users of CodeLab and they seemed to like it.
In China, Python is the most popular language for programming education , with a large number of elementary and middle schools using it, and I'm trying to get more people to migrate their Python legacy projects to MicroBlocks through the library.
Recently I may give a talk for Maker teachers on MicroBlocks . For interoperability between different programming platforms I may mention this library.
-
reporter I will email you if there is any further progress.
-
reporter Do you have plans for using it in a project?
I've had several requests for Python-MicroBlocks communication library before.
The Python community has many automation libraries that can take over the computer(such as pyautogui). If we can make Python and MicroBlocks communicate easily, We can then use MicroBlocks(boards) to interoperate with computers. This will unlock a lot of interesting possibilities. For example
Using a microbit A to communicate with Python(Python takes over the computer through pyautogui) while microbit A receives messages from microbit B through radio(so we can walk around), we can use microbit B as a Laser pointer with remote control for PPT.
When speaking, when it comes to how the Laser pointer with remote control is made(with MicroBlocks), people are usually very interested, and then naturally lead to the theme of the speech.
-
reporter - changed status to resolved
-
reporter Another interesting application is making wands 🪄 At CodeLab, we have observed that most children are particularly fascinated by wands. Programming and magic seem to have a natural connection
I etch a pattern of geometric shapes onto a stone. To the uninitiated, the shapes look mysterious and complex, but I know that when arranged correctly they will give the stone a special power, enabling it to respond to incantations in a language no human being has ever spoken. I will ask the stone questions in this language, and it will answer by showing me a vision: a world created by my spell, a world imagined within the pattern on the stone.
A few hundred years ago in my native New England, an accurate description of my occupation would have gotten me burned at the stake. Yet my work involves no witchcraft; I design and program computers. The stone is a wafer of silicon, and the incantations are software. -- Daniel Hillis《The Pattern on the Stone》
Python community has a lot of deep learning libraries(Tensorflow/PyTorch/...), in the previous microbitA-microbitB-Python architecture, we can use Python's deep learning library to compute microbitB's gesture in real time, thus making microbit B into a magic wand. Since Python controls the computer with pyautogui, the effective range of our magic will be very broad.
-
repo owner These are cool ideas! I agree, programming and magic have a very natural connection. In fact, programming feels like magic when you use it to make surprising and interesting things happen. Learning how to program is like learning how to cast spells. For me, programming and electronics have alway felt like "real" magic -- magic that actually works and the anyone can learn if they work at it.
I love the idea of using a pair of micro:bits to control your PPT slides, then show people the actual code so they can see that it's actually quite easy to understand.
- Log in to comment
I think you need to set the baud rate to 115200 using something like:
serial.Serial('/dev/tty.usbmodem1402', 115200)