Coder Social home page Coder Social logo

pybricks-code's Introduction

CI test status codecov

pybricks-code

A Web App for programming LEGO® Powered Up smart hubs using Pybricks MicroPython.

Try it at https://code.pybricks.com or the latest updates https://beta.pybricks.com.

screenshot

Contributing

If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome.

For more details, see the file CONTRIBUTING.md.


LEGO® is a trademark of the LEGO Group of companies which does not sponsor, authorize or endorse this project.

pybricks-code's People

Contributors

bertlindeman avatar daphtdazz avatar dependabot-preview[bot] avatar dependabot[bot] avatar dlech avatar laurensvalk avatar littldr avatar scmmmh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

pybricks-code's Issues

[Bug] code.pybricks.com without Internet connection

Without Internet connection, the program is not loaded to the hub.

The BLE connection work well, and show the output of the hub (if you run the main.py built-in), but is not possible to load a new program.

better handling of disconnect during flash

Currently the behavior (error message) is different on each OS when a hub is disconnected while flashing. Linux works as expected. Windows will say that the connection timed out. Mac will say that there was an unknown GATT error.

Ideally all OSes should give the correct error that the hub was disconnected.

To reproduce, start flashing and pull the battery when the spinner in the toolbar button start spinning.

code completion TODO

  • fix offline usage - we are currently fetching pyodide from the pyodide cdn. webpack has issues with the current pyodide package. these need to get sorted.
  • install a specific version of pybricks-jedi package - this is needed if we make breaking changes to the Python package during development so we don't break regular users
  • sort order - it would be nice to have at least some basic sorting, like list items from __main__ first then items from pybricks modules, then everything else
  • fix active signature/prameter - should not be hard-coded to 0 - https://github.com/pybricks/pybricks-api/blob/a758eaa1db5969a0c64232ecad2c5523acb1acd7/jedi/src/pybricks_jedi/__init__.py#L320-L321
  • parameter docs - the editor can show per-parameter docs but jedi doesn't know how to parse these - we would have to make our own parser
  • additional features? - monaco and jedi have many features we aren't using - we can probably live without most of them - showing docs on hover might be a nice addition though
  • update to Pyodide 0.21 - this includes a fix to avoid spamming the browser console with warning messages when python code is interrupted
  • disable on mobile - monaco editor officially does not support mobile devices and this is unusable on mobile because it doesn't fit on the screen
  • Insert () for functions - it is a common beginner mistake to use function getters like properties.

Reduce import suggestions

I'm not sure what's a good alternative yet, but these seem quite intrusive. They come up for just about anything you type.

code-2021-07-07_09.00.17.mp4

Cannot flash City Hub firmware

The City Hub bootloader has several quirks that require the use of both writing with response and writing without response to the GATT characteristic. So the same fix for #53 is required to be able to use the City Hub at all.

Flashing firmware is slow (> 5 minutes)

Web Bluetooth does not support specifying write with response or write without response when writing to a GATT characteristic. For performance, we need to be able to write without response. The LEGO bootloader (on movehub, cityhub, cplushub) has set both PROPERTY_WRITE_NO_RESPONSE and PROPERTY_WRITE which causes Chrome on all platforms except Android to write with response. This results in an extra BLE packet being sent back from the hub to the host for every packet sent which really slows down the firmware flashing process.

App crashes/becomes unresponsive when checking for updates and server is down.

We aren't handling errors when checking for updates, so we can crash the redux sagas like this:

image

main.baec794c.js:2 TypeError: Failed to update a ServiceWorker for scope ('http://localhost:8000/') with script ('http://localhost:8000/service-worker.js'): An unknown error occurred when fetching the script.
y @ main.baec794c.js:2
main.baec794c.js:2 The above error occurred in task _p
    created by takeEvery(app.action.checkForUpdate, _p)
    created by kp
    created by Tg
    created by Tg
Tasks cancelled due to error:
takeEvery(app.action.checkForUpdate, _p)
kp
takeEvery(app.action.reload, xp)
Sp
Tp

editor hot reload issues

When developing Pybricks Code using the React dev server (yarn start), the editor sometimes disappears during hot reload.

Also more recent changes have cause syntax highlighting to stop working sometimes after hot reload.

Workaround is to just refresh the page.

This only affect development and not production builds.

Integrate DFU recovery in Pybricks Code

This should make it easier (and less scary) for new users to try it out because they can try recovery first. And it makes Pybricks Code usable standalone.

Could we use a variant of the same installation dialog, just with slightly different steps/text?

  • Step 1 could be the same. We can reword the "not listed" pop up text to be be applicable in both cases.
  • Skip step 2 & 3
  • Step 4 could be almost the same as well. But for Technic/Move/City Hub it would only offer instructions, no actual update.

image

[Issue] Top code rows and documentation bar gets hidden behind the top grey menu bar

At some point during editing the top lines of the code terminal, and the top bar of the documentation pane, got hidden behind the top grey 'menu' bar. See image below. This makes it impossible to open the help menu to navigate to items.

I only recall pressing 'Backspace' with the documentation window active.
Reloading the page does not fix the issue.
Hide/show documentation does not fix the issue.

image

Chrome: Versie 84.0.4147.135 (Officiële build) (64-bits)
Windows 10

Display hub status indicator

It may be useful to display:

  • Which hub we are connected to:
    • Name
    • Type
  • Battery level

Below is an example in a (very old) design exploration migrated from our previously internal issue tracker:

image

yarn start time

Since we were both getting the feeling that yarn start was taking longer, I thought I'd measure it.

I don't really mind that it takes long, but I was curious to see if there was a trend.


Latest listed first, time in seconds. All are measured once or twice with an external stopwatch. In all cases, yarn install was run first (not included in time).

4c09c54 - 32.5
0a47abe - 27.2
1d9dd82 - 30.5
0723580 - 46.9


df0e980 - 32.1

The last one listed is way back, before adding monaco editor.

So maybe it's just always been slow?

Keep installation dialog open at step 4 until user clicks "Connect".

It would be very useful to not close the installation dialog until the user clicks "Connect" in the pop-up, as shown in the mock-up screenshot below.

That way they don't have to remember all 6 steps by heart. If they miss a step and the device doesn't show, they can just repeat it to make it show up.

This will be useful even on small screens where it overlaps, as it still saves the user from having to go through the setup steps.

image

Clicking Bluetooth does nothing when using Chromium installed from Ubuntu snap

Ubuntu is transitioning the Chromium package to snap-only no more apt. This runs Chromium in a sandbox.

This caused a bug where clicking on the Bluetooth button did nothing in pybricks-code, not even an error message in the developer console.

Ubuntu has partially resolved the bug by allowing chromium to connect to bluez. However users currently have to manually connect them via the command line.

snap connect chromium:bluez

I have started the process of requesting that this be done automatically, however I currently lack sufficient privileges to write a proper request (my account was put on hold for trying to write too much).

Include software licenses for included assets

We have a display of the software licenses of Pybricks Code dependencies, but it seems that the firmware licenses are not included (aside from @pybricks/firmware top level license.)

They are included in the firmware ZIP archive, but I don't think we show those anywhere in the app.

Could we perhaps extract the required info and include them in the OSS license menu?

Template for new file (instead of hub selection)

When selecting a hub in the current version, I was thinking for a moment that this might do other things under the hood like restricting which hubs this program can run on.

So instead of choosing a hub, maybe we could call it "Choose a template"?

This can still include all the hubs, but also other things, like None (or maybe call it Empty).

I also added "Hub" to a few of the names here.

image

Essential Hub installation stuck at 64% erase

It remained stuck at 64% of erasing the flash and the light went back to blink purple.

It worked fine when trying again though. I did not need to reboot the hub.

This does not appear to be easily reproducable.

image

serializableStateInvariantMiddleware.ts:195 A non-serializable value was detected in an action, in the path: `payload`. Value: ArrayBuffer(14) 
Take a look at the logic that dispatched this action:  Object 
(See https://redux.js.org/faq/actions#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants) 
(To allow non-serializable values see: https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data)
(anonymous) @ serializableStateInvariantMiddleware.ts:195
serializableStateInvariantMiddleware.ts:195 A non-serializable value was detected in an action, in the path: `payload`. Value: ArrayBuffer(12) 
Take a look at the logic that dispatched this action:  Object 
(See https://redux.js.org/faq/actions#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants) 
(To allow non-serializable values see: https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data)
(anonymous) @ serializableStateInvariantMiddleware.ts:195
index.js:4 DFU GETSTATUS failed: Error: ControlTransferIn failed: NetworkError: A transfer error has occurred.

Device does not show up under Linux-Chrome

I see a rather odd issue. Using Chromium under Linux the City Hub in Bootloader mode is detected and can be flashed. But once flashed it simply does not show up. This only happens with chromium on Linux. Edge on Windows and Chrome on Android just work.

I see this with Chromium:
Version 98.0.4758.102 (Official Build) snap (64-bit)

Top button tooltips get stuck

The big blue buttons at the top can end up with their tooltips stuck open. This seems to happen because the keyboard focus and the mouse hover seem to be handled independently. If a button is selected (not activated) with the keyboard by pressing the tab key, the tooltip will pop up. Then if the focus is moved elsewhere by clicking the mouse, the tooltip will stay open.

This seems to particularly be an issue when using the settings menu. When the setting drawer closes, the settings button is focused. If focus is not redirected elsewhere quickly enough, the tooltip will open. Then when focus is redirected elsewhere with the mouse, the tooltip stays open.

add option for compiler optimizations

MicroPython defines 3 optimization levels. The default, O0; O1/O2 which does not compile assert statements; and O3 which does not include line numbers. These can make the compiled .mpy file smaller.

Not sure how useful this would be, but if we are looking for ways to squeeze every last byte of RAM out of the hubs, this could be a possibility.

Restore drag-and-drop firmare update.

Since we introduced the firmware install dialog, there is no longer a way to drag-and-drop firmware.zip files from CI in Pybricks code.

We still have pybricksdev to flash experimental builds, but it would be nice if we had drag-and-drop to make it easier for users to test the latest bug fix of an issue they are interested in.

Add left margin

The code is pressed against the lefthand bar.

image

A bit of space would be nice. Here's the spacing in VS Code, though a bt less should still be fine.

Screenshot from 2021-07-07 09-10-38

Show installation progress + success/failure in installation step 5

Motivation

The installation dialog disappears, so the actual installation feel a bit disconnected. I got the following (typical) messages with Move Hub, but it isn't super intuitive where they come from, or how to deal with them.

image

Suggestion

Something like shown below. The buttons at the bottom would be disabled at first.

  • "Install again" just takes you back to previous step.
  • "Done" closes the dialog

Since it would probably be hard to show the errors here as well, it's probably fine if they remain popups at the stop. If the dialog is open like this, they can easily click "install again" if errors occur.

image


start keeping changelog and include in app

Now that we are close to the initial release, we need to start keeping a proper changelog. We should also embed this in the app so that users can easily see what has changed when they receive an update.

Up to now, the changelog has been kept at pybricks/support#48

Errors loading small to medium-sized programs

Tested on 960a3163ed68e3fc46b15fb590b7e60c748979ad

image

Pybricks MicroPython v3.2.0b3-97-g2270df4e on 2022-10-15; SPIKE Prime Hub with STM32F413VG

1) Program crashes (bad mpy, but keeps running)

Some other variations with bad programs cause a watchdog timeout as well. This variant keeps the hub running, which may help with debugging.

from pybricks.hubs import InventorHub
from pybricks.pupdevices import Motor
from pybricks.parameters import Port, Direction
from pybricks.tools import wait, StopWatch
from pybricks.geometry import Axis

# MicroPython imports.
from umath import copysign
from usys import stdin
from uselect import poll

# Initialize motors.
left = Motor(Port.A, Direction.COUNTERCLOCKWISE)
right = Motor(Port.B)
left.reset_angle(0)
right.reset_angle(0)

# Initialize the hub.
hub = InventorHub()

# Control constants.
DUTY_FRICTION = 10
VOLTAGE_NOMINAL = 7400

# Drive speeds in motor degrees per second.
FORWARD = 350
STOPPED = 0
BACKWARD = -350

# Turn speed in motor degrees per second.
LEFT = -300
STRAIGHT = 0
RIGHT = 300

# Drive/turn command for each numpad key.
COMMANDS = {
    "1": (BACKWARD, LEFT),
    "2": (BACKWARD, STRAIGHT),
    "3": (BACKWARD, RIGHT),
    "4": (STOPPED, LEFT),
    "5": (STOPPED, STRAIGHT),
    "6": (STOPPED, RIGHT),
    "7": (FORWARD, LEFT),
    "8": (FORWARD, STRAIGHT),
    "9": (FORWARD, RIGHT),
}

# Register the standard input so we can read keyboard presses.
keyboard = poll()
keyboard.register(stdin)

# Initialize the loop timer.
timer = StopWatch()

# Initialize angle buffer for motor speed calculation.
LOOP_TIME = 0.015

# Motor speed is obtained as the motor position difference across
# a given time span. Time span must be multiple of loop time.
angle_filter_time = 0.150
angle_filter_size = round(angle_filter_time / LOOP_TIME)
angle_filter_buffer = [0] * angle_filter_size
angle_filter_index = 0

2) Fails before it runs

from pybricks.hubs import InventorHub
from pybricks.pupdevices import Motor
from pybricks.parameters import Port, Direction
from pybricks.tools import wait, StopWatch
from pybricks.geometry import Axis

# MicroPython imports.
from umath import copysign
from usys import stdin
from uselect import poll

# Initialize motors.
left = Motor(Port.A, Direction.COUNTERCLOCKWISE)
right = Motor(Port.B)
left.reset_angle(0)
right.reset_angle(0)

# Initialize the hub.
hub = InventorHub()

# Control constants.
DUTY_FRICTION = 10
VOLTAGE_NOMINAL = 7400

# Drive speeds in motor degrees per second.
FORWARD = 350
STOPPED = 0
BACKWARD = -350

# Turn speed in motor degrees per second.
LEFT = -300
STRAIGHT = 0
RIGHT = 300

# Drive/turn command for each numpad key.
COMMANDS = {
    "1": (BACKWARD, LEFT),
    "2": (BACKWARD, STRAIGHT),
    "3": (BACKWARD, RIGHT),
    "4": (STOPPED, LEFT),
    "5": (STOPPED, STRAIGHT),
    "6": (STOPPED, RIGHT),
    "7": (FORWARD, LEFT),
    "8": (FORWARD, STRAIGHT),
    "9": (FORWARD, RIGHT),
}

# Register the standard input so we can read keyboard presses.
keyboard = poll()
keyboard.register(stdin)

# Initialize the loop timer.
timer = StopWatch()

# Initialize angle buffer for motor speed calculation.
LOOP_TIME = 0.015

# Motor speed is obtained as the motor position difference across
# a given time span. Time span must be multiple of loop time.
angle_filter_time = 0.150
angle_filter_size = round(angle_filter_time / LOOP_TIME)
angle_filter_buffer = [0] * angle_filter_size
angle_filter_index = 0

# End-user controls for speed and steering.
user_drive_speed = 0
user_steering_speed = 0

# Initial state values.
target_motor_angle = 0
target_steering = 0
gyro_angle = 0
gyro_average = 0
gyro_filter = 0.01

while True:
    # Reset loop timer.
    timer.reset()

    # Filter the angular speed measurement.
    gyro_raw = -hub.imu.angular_velocity(Axis.Y)
    gyro_average = gyro_average * (1 - gyro_filter) + gyro_filter * gyro_raw
    gyro_filter = max(0.997 * gyro_filter, 0.0005)

    # Get angular gyro_speed and estimated angle.
    gyro_speed = gyro_raw - gyro_average
    gyro_angle += gyro_speed * LOOP_TIME

    # Get average motor angle.
    motor_angle = (left.angle() + right.angle()) / 2

    # Calculate average motor speed.
    motor_speed = (motor_angle - angle_filter_buffer[angle_filter_index]) / angle_filter_time
    angle_filter_buffer[angle_filter_index] = motor_angle
    angle_filter_index = (angle_filter_index + 1) % angle_filter_size

    # Update user controls if given.
    if keyboard.poll(0):
        try:
            user_drive_speed, user_steering_speed = COMMANDS[stdin.read(1)]
            print("Speed:", user_drive_speed, "steering:", user_steering_speed)
        except KeyError:
            user_drive_speed, user_steering_speed = 0, 0

    # Update target angle and steering based on user input.
    target_motor_angle += user_drive_speed * LOOP_TIME
    target_steering += user_steering_speed * LOOP_TIME
    motor_angle_error = motor_angle - target_motor_angle

    # Calculate balance control signal as weighed sum of all four states.
    # This has the effect of driving all of them to zero.
    duty_balance = (
        gyro_speed * 0.1 +
        gyro_angle * 15 +
        motor_speed * 0.15 +
        motor_angle_error * 0.1
    )

    # Calculate steering control signal
    duty_steering = (right.angle() - left.angle() + target_steering) * 0.2

    # Combine balance and steering for left motor.
    duty_left = duty_balance + duty_steering
    duty_left += copysign(DUTY_FRICTION, duty_left)
    duty_left *= VOLTAGE_NOMINAL / hub.battery.voltage()

    # Combine balance and steering for right motor.
    duty_right = duty_balance - duty_steering
    duty_right += copysign(DUTY_FRICTION, duty_right)
    duty_right *= VOLTAGE_NOMINAL / hub.battery.voltage()

    # Apply duty cycle for balancing and steering.
    left.dc(duty_left)
    right.dc(duty_right)

    # Wait for the loop time to complete.
    while timer.time() < LOOP_TIME * 1000:
        wait(1)

Install discoverability

Chromium lets you install web apps, which adds a program icon to your start menu (or OS equivalent) which launches the app without the usual address bar and other browser stuff so it looks more like a desktop app. This is really cool but the feature is not easily discoverable. By default, there is a small icon in the address bar and a menu item:

image
image

However, it is possible to add something to our settings menu to make this more discoverable. It is possible to trigger the install programatically, which pops up the install dialog:

image

So, we could add button for this to the settings menu if we wanted to.

Coding canvas can stay white in dark mode

This seems to happen on iOS Safari and its derivatives.

We don't support iOS right now because of the lack of Bluetooth support, but this might be a CSS issue we could fix one day.

This happens on both the stable and the beta release. On the beta release, the BETA text does not appear, so maybe it's an issue with the SVG?

E0D3335D-C582-4F7F-A98A-EE421D953F69

Better deployment strategy

We currently use the mirror feature of lftp for deploying the Pybricks Code website. This leaves the site in an inconsistent state for a few minutes while the upload happens. There are probably better deployment strategies out there that would reduce the window for causing problems for users, but I don't know what they are.

[Bug] Error "`wasm streaming compile failed" running a python program on a movehub / Control+ hub

Describe the bug
Trying to run a stripped sample python program using https://code.pybricks.com/

To reproduce

  1. On Windows 10 open Chrome version 85
  2. Flash firmware to the hub (take a minute but seems to end OKE)
  3. Click "Connect using bluetooth"
  4. The button "Download and run" goes from light blue to dark blue (So is available)
  5. Click button "Download and run"
  6. See error:
    wasm streaming compile failed: TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'.,falling back to ArrayBuffer instantiation,Traceback (most recent call last):, File "main.py", line 10, SyntaxError: invalid syntax

Expected behavior
Run the python program

Screenshots
image

Versions
Google Chrome | 85.0.4183.16 (Official Build) dev (64-bit) (cohort: Dev-nonPGO)
Revision | e5f41a80568bb5f51f3468c3fbb92aac2fceab70-refs/branch-heads/4183@{#226}
Windows 10 OS Version 1909 (Build 18363.900)

chrome://flags/#enable-experimental-web-platform-features
is enabled

Enable auto-indent

This doesn't seem to work yet in the new editor:

code-2021-07-07_08.57.13.mp4

Change (don't hide) Install as App button once installed

This may make the functionality a bit easier to understand.

Maybe we could change it to "open app", and perform the equivalent of this button browser button.

If that doesn't work, maybe we could just grey it out and change the text to: "Already installed as app".

Screenshot from 2022-09-26 13-37-52

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.