Skip to content

Fix unneeded "Select port on upload" message #8194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Nov 14, 2018

Conversation

cmaglie
Copy link
Member

@cmaglie cmaglie commented Nov 12, 2018

This turned out to be really tricky: to reliably understand if the serial port is actually needed the only way is to check if the recipe contains the variable {serial.port} considering also the fact that the tag {serial.port} may be hidden inside another variable like extra_params or similar.

Some other cleanups in this PR:

  • the two duplicated "Upload" handlers DefaultExportAppHandler and DefaultExportHandler that are basically 99% the same are now merged and renamed to UploadHandler.
  • removed a lot of code duplication in SerialUploader, now it should be much more consistent when running upload (w/ or w/out programmer) and burn bootloader.
  • while Uploading (with or without programmer) there was already a nice dialog that asks to choose an upload port, I've reused that (and fixed the port selection...) whenever possible.
  • other small cleanups

@awatterott
Copy link

I have tested it under Win7 64bit and with boards without serial port it is working. But if a board with serial port is selected like Arduino Uno and no serial port is available then there is an error:

Sketch uses 930 bytes (2%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
processing.app.SerialNotFoundException: processing.app.helpers.PreferencesMapException: serial.port
	at cc.arduino.packages.uploaders.SerialUploader.runCommand(SerialUploader.java:393)
	at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:197)
	at cc.arduino.UploaderUtils.upload(UploaderUtils.java:77)
	at processing.app.SketchController.upload(SketchController.java:732)
	at processing.app.SketchController.exportApplet(SketchController.java:703)
	at processing.app.Editor$UploadHandler.run(Editor.java:2034)
	at java.lang.Thread.run(Thread.java:748)
Caused by: processing.app.helpers.PreferencesMapException: serial.port
	at processing.app.helpers.StringReplacer.checkIfRequiredKeyIsMissingOrExcept(StringReplacer.java:67)
	at cc.arduino.packages.uploaders.SerialUploader.runCommand(SerialUploader.java:386)
	... 6 more
processing.app.helpers.PreferencesMapException: serial.port
An error occurred while uploading the sketch
Exception in thread "Thread-39" java.util.ConcurrentModificationException
	at java.util.LinkedList$LLSpliterator.forEachRemaining(LinkedList.java:1239)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at cc.arduino.contributions.libraries.LibrariesIndexer.rescanLibraries(LibrariesIndexer.java:167)
	at cc.arduino.contributions.libraries.LibrariesIndexer.setLibrariesFolders(LibrariesIndexer.java:120)
	at processing.app.BaseNoGui.onBoardOrPortChange(BaseNoGui.java:678)
	at processing.app.Base.onBoardOrPortChange(Base.java:1327)
	at processing.app.Editor$UploadHandler.run(Editor.java:2064)
	at java.lang.Thread.run(Thread.java:748)

@facchinm facchinm added this to the Release 1.8.8 milestone Nov 13, 2018
@cmaglie
Copy link
Member Author

cmaglie commented Nov 13, 2018

thanks for testing! yes there is this small unhandled case:

        if (portMenu.getItemCount() == 0) statusError(e);   <---
        else if (serialPrompt()) run();
        else statusNotice(tr("Upload canceled."));

I'm changing it to:

        if (portMenu.getItemCount() == 0) {
          statusError(tr("Serial port not selected."));
        } else {
          if (serialPrompt()) {
            run();
          } else {
            statusNotice(tr("Upload canceled."));
          }
        }

so in case no ports are available "Serial port not selected." is printed.

@awatterott
Copy link

Yes, that is better and now everything is working.

@cmaglie cmaglie merged commit b5bfe08 into arduino:master Nov 14, 2018
@cmaglie cmaglie deleted the fix-no-upload-port branch November 14, 2018 16:41
@cmaglie cmaglie self-assigned this Nov 14, 2018
@cmaglie cmaglie added Type: Bug Component: IDE user interface The Arduino IDE's user interface Type: Regression Something that used to work and now doesn't labels Nov 14, 2018
Copy link
Collaborator

@matthijskooijman matthijskooijman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems I'm a bit late to the party. I meant to review this PR, but hadn't found the time. I did a review now anyway.

Great to see this refactoring, that improves a lot. Yay for killing the UploadAppHandler stuff that was not relevantly named anymore. Next up, renaming exportApplet?

I noticed a noUploadPort argument in UploaderUtils:

public Uploader getUploaderByPreferences(boolean noUploadPort) {

I wonder if that is something that should be set? Or perhaps it is no longer relevant? AFAICS, the argument is only set to true when passing --nouploadport on the commandline, but I haven't traced what it does exactly.

I haven't fully understood the core commit of this PR yet (haven't dug into the code deeply), but I did review all others. I left some remarks inline, of things that might be good to fix in the future (but nothing that actually breaks behaviour, I believe).

src = res;
}

// If the resulting string contains the tag, then the key is required
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not guaranteed: For example, of the string is "{foo}", a tag of "bar" is chosen (which is not in "{foo}"), but the "foo" variable contains "some string with bar", then this code will conclude that whatever key is passed is required, while it might not be.

Did you consider adding some instrumentation to replaceFromMapping to either check if a key is used, or more generically, let it return a list of keys it expanded?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can't happen because tag is guaranteed to be different from any key/value contained in the map and either from any part of the pattern recipe, see how it is choosen in the while loop just before this.

Copy link
Member Author

@cmaglie cmaglie Nov 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider adding some instrumentation to replaceFromMapping to either check if a key is used, or more generically, let it return a list of keys it expanded?

This is trickier than it looks :-)

  • returning the keys it expanded, won't help in detecting if a key is required, it could be that, for example, {serial.port} is required but it's not expanded because the key serial.port it's not present in the preferences map.
  • we could "detect" a list of keys that needs to be replaced using a regexp that looks at matching braces in the recipes, but there are some recipes where the braces are actually needed! see this openocd command for instance:
    tools.openocd.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.elf}} verify reset; shutdown"
    the part {{{build.path}/{build.project_name}.elf}} will translate to {{my/sketch.elf}} but this doesn't mean that my/sketch.elf is a required field.

else if (serialPrompt()) run();
else statusNotice(tr("Upload canceled."));
if (portMenu.getItemCount() == 0) {
statusError(tr("Serial port not selected."));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be "no serial ports available" or something?

private boolean runCommand(String patternKey, PreferencesMap prefs) throws Exception, RunnerException {
try {
String pattern = prefs.getOrExcept(patternKey);
StringReplacer.checkIfRequiredKeyIsMissingOrExcept("serial.port", pattern, prefs);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the only line that can throw a PreferencesMapException? If so, wouldn't it be better to have a smaller try block for that (or perhaps even let checkIfRequiredKeyIsMissingOrExcept return a boolean, if all it does is except or not except)?

Reading this, I wonder: Shouldn't StringReplacer.formatAndSplit (etc.) just throw when they find any unset variable? Or does that break for optional variables in some cases?

@rfscarlat
Copy link

404 Page not found
Do you still publish the fix? I have just installed 1.8.7 on a Windows 10 computer and hit the same issue.

@matthijskooijman
Copy link
Collaborator

@rscarlat - The fix is in git master, but not any released version yet. I believe it should be available in the hourly build version at https://www.arduino.cc/en/Main/Software (or perhaps in the beta build - I keep getting confused by the existance of both...).

@facchinm
Copy link
Member

Since this PR has been merged in master it has been automatically built and deployed as Hourly (and temporary PR urls have been deleted).
Beta builds are generated starting from 1.9-beta branch, which is manually rebased upon master every once in a while.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: IDE user interface The Arduino IDE's user interface Type: Bug Type: Regression Something that used to work and now doesn't
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants