Skip to content

Commit

Permalink
Release 0.7
Browse files Browse the repository at this point in the history
  • Loading branch information
ussserrr committed Nov 7, 2018
1 parent e81ab38 commit 2662bdc
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 58 deletions.
40 changes: 32 additions & 8 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Changelog:
stm32pio changelog:

ver. 0.1 (30.11.17):
- Initial version
Expand All @@ -15,24 +15,48 @@ Changelog:
ver. 0.4 (03-04.04.18):
- New: hide CubeMX and PlatformIO stdout output
- New: shebang
- New: choose your favourite editor with --start-editor option (replaced --with-atom)
- New: choose your favourite editor with '--start-editor' option (replaces '--with-atom')
- New: logging module
- New: more checks
- New: settings.py file
- New: 'settings.py' file
- New: cross-platform running
- New: debug output (verbose -v mode)
- New: readme.md and more comments
- New: debug output (verbose '-v' mode)
- New: 'README.md' and more comments
- Fixed: remove unnecessary imports
- Fixed: command to init pio project (removed double quotation marks)
- Fixed: command to initialize PlatformIO project (remove double quotation marks)
- Changed: many architectural improvements
- Changed: documentation improvements

ver. 0.45 (04-05.04.18):
- New: introducing unit-tests for the app
- New: clean-up mode
- New: clean-up feature

ver. 0.5 (07.04.18):
- New: more comments
- New: screenshots for the usage example
- Fixed: many small fixes and improvements
- Changed: test now more isolated and uses ./stm32pio-test/stm32pio-test.ioc file
- Changed: test now is more isolated and uses ./stm32pio-test/stm32pio-test.ioc file

ver. 0.7 (05-07.11.18):
- New: Windows support!
- New: new editors support (Sublime Text, gedit)
- New: more comments and docstrings
- New: more checks to improve robustness
- New: if __name__ == '__main__' block
- New: new test: build generated project
- New: new test: run editors
- New: new test: user's code preservation after the code regeneration
- New: clean run for test cases (implemented using decorator)
- Fixed: compatible with latest PlatformIO project structure (ver 3.6.1)
- Fixed: many small fixes and improvements
- Changed: 'java_cmd' parameter in 'settings.py' (simple 'java' by default)
- Changed: move to double-quoted strings
- Changed: remove '_getProjectNameByPath()' function (replaced by 'os.path.basename()')
- Changed: vast f-strings usage
- Changed: test '.ioc' file is updated to the latest STM32CubeMX version (4.27.0 at the moment)
- Changed: use 'os.path.join()' instead of manually composing of paths
- Changed: use 'with ... as ...' construction for opening files
- Changed: 120 chars line width
- Changed: PEP 8 conformity: variables and functions naming conventions
- Changed: PEP 8 conformity: multi-line imports
- Changed: 'miscs.py' module is renamed to 'util.py'
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# stm32pio
Small Python app that can create and update [PlatformIO](https://platformio.org) project from [STM32CubeMX](http://www.st.com/en/development-tools/stm32cubemx.html) `.ioc` file.
Small cross-platform Python app that can create and update [PlatformIO](https://platformio.org) projects from [STM32CubeMX](http://www.st.com/en/development-tools/stm32cubemx.html) `.ioc` files.

## Features
- Start the new project in a single directory using only `.ioc` file
Expand All @@ -9,15 +9,15 @@ Small Python app that can create and update [PlatformIO](https://platformio.org)

## Requirements:
- For this app:
- Python 3.5+
- Python 3.6+
- For usage:
- macOS or Linux OS
- macOS, Linux, Windows
- STM32CubeMX (all recent versions) with downloaded necessary frameworks (F0, F1, etc.). Try to generate code in ordinary way (through the GUI) at least once before running stm32pio
- Java CLI (JRE) (likely is already installed if STM32CubeMX works)
- PlatformIO CLI (from Atom you can run `Menubar -> PlatformIO -> Install Shell Commands`). Therefore, currently stm32pio doesn't support Windows due to the lack of the PlatformIO CLI.
- PlatformIO CLI.

## Usage
Check `settings.py` to make sure that all user-specific parameters (path to the STM32CubeMX executable) are valid. Run
Check `settings.py` to make sure that all user-specific parameters are valid. Run
```bash
$ python3 stm32pio.py --help
```
Expand All @@ -29,17 +29,22 @@ to see help.

![Code Generator tab](/screenshots/tab_CodeGenerator.png)

3. Back in the first tab (Project) copy the "Toolchain Folder Location" string. Click OK
3. Back in the first tab (Project) copy the "Toolchain Folder Location" string. Click OK, close CubeMX

![Project tab](/screenshots/tab_Project.png)

4. Use copied string as a `-d` argument for stm32pio
5. Run `pio boards` to list all supported devices. Pick one and use its ID as a `-b` argument (for example, `nucleo_f031k6`)
4. Use copied string as a `-d` argument for stm32pio. So it is assumed that the name of the project folder matches the name of `.ioc` file
5. Run `platformio boards` (`pio boards`) to list all supported devices. Pick one and use its ID as a `-b` argument (for example, `nucleo_f031k6`)
6. All done. You can now run
```bash
$ python3 stm32pio.py new -d /path/to/cubemx/project -b nucleo_f031k6 --start-editor=vscode
```
to complete generation and start the Visual Studio Code editor with opened folder (as example, not required).
to complete generation and start the Visual Studio Code editor with opened folder (as example, not required). Make sure you have all tools in PATH (`java` (or set in `settings.py`), editor, Python)
7. If you will be in need to update hardware configuration in the future, make all necessary stuff in CubeMX and run `generate` command in a similar way:
```bash
$ python3 stm32pio.py generate -d /path/to/cubemx/project
```
8. To clean-up the folder and keep only `.ioc` file run `clean` command

## Testing
Since ver. 0.45 there are some unit-tests in file `tests.py` (based on the unittest module). Run
Expand Down
14 changes: 7 additions & 7 deletions settings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import logging
import pathlib
import platform
import sys


my_os = platform.system()
Expand All @@ -10,19 +9,20 @@
logger = logging.getLogger('')


# We trying to guess STM32CubeMX path. You can just avoid this and hard-code it
# How you start Java from command line?
java_cmd = 'java'

# We trying to guess STM32CubeMX location. You can just avoid this and hard-code it. Note that STM32CubeMX will be
# called as 'java -jar'
# macOS default: 'Applications' folder
if my_os == 'Darwin':
cubemx_path = "/Applications/STMicroelectronics/STM32CubeMX.app/Contents/Resources/STM32CubeMX"
# not exactly default STM32CubeMX path on Linux but general convention on it
# Linux (Ubuntu) default:
elif my_os == 'Linux':
cubemx_path = "/usr/local/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX"
# Windows is not implemented yet
# Windows default:
elif my_os == 'Windows':
cubemx_path = "C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX.exe"
# logger.error("Windows is not supported!")
# sys.exit()
cubemx_path = "C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX.exe"

cubemx_script_filename = 'cubemx-script'

Expand Down
9 changes: 5 additions & 4 deletions stm32pio.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3


__version__ = 0.6
__version__ = 0.7


if __name__ == '__main__':
Expand All @@ -11,7 +11,7 @@
import sys

parser = argparse.ArgumentParser(description="Automation of creating and updating STM32CubeMX-PlatformIO projects. "
"Requirements: Python 3.5+, STM32CubeMX, PlatformIO CLI. Edit "
"Requirements: Python 3.6+, STM32CubeMX, Java, PlatformIO CLI. Edit "
"settings.py to set project path to the STM32CubeMX (if default "
"doesn't work)")
# global arguments (there is also automatically added '-h, --help' option)
Expand All @@ -21,11 +21,12 @@
subparsers = parser.add_subparsers(dest='subcommand', title='subcommands',
description="valid subcommands", help="modes of operation")

parser_new = subparsers.add_parser('new', help="generate CubeMX code, create PlatformIO project [and start editor]")
parser_new = subparsers.add_parser('new',
help="generate CubeMX code, create PlatformIO project [and start the editor]")
parser_new.add_argument('-d', '--directory', dest='project_path', help="path to the project", required=True)
parser_new.add_argument('-b', '--board', dest='board', help="PlatformIO name of the board", required=True)
parser_new.add_argument('--start-editor', dest='editor', help="use specified editor to open PlatformIO project",
choices=['atom', 'vscode', 'sublime'], required=False)
choices=['atom', 'vscode', 'sublime', 'gedit'], required=False)

parser_generate = subparsers.add_parser('generate', help="generate CubeMX code")
parser_generate.add_argument('-d', '--directory', dest='project_path', help="path to the project", required=True)
Expand Down
19 changes: 14 additions & 5 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ def test_patch_platformio_ini(self):

with open(os.path.join(project_path, 'platformio.ini'), mode='rb') as platformio_ini:
# '2' in seek() means that we count from the end of the file. This feature works only in binary file mode
# In Windows additional '\r' is appended to every '\n' so we need to count them for the correct calculation
# In Windows additional '\r' is appended to every '\n' (newline differences) so we need to count them
# for the correct calculation
if settings.my_os == 'Windows':
platformio_ini.seek(-(len(settings.platformio_ini_patch_text) +
settings.platformio_ini_patch_text.count('\n')), 2)
Expand Down Expand Up @@ -103,6 +104,7 @@ def test_run_editor(self):
util.start_editor(project_path, 'atom')
util.start_editor(project_path, 'vscode')
util.start_editor(project_path, 'sublime')
util.start_editor(project_path, 'gedit')
time.sleep(1) # wait a little bit for apps to start

if settings.my_os == 'Windows':
Expand All @@ -115,9 +117,16 @@ def test_run_editor(self):
result = subprocess.run(['ps', '-A'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8')
# Or, for Python 3.7 and above:
# result = subprocess.run(['ps', '-A'], capture_output=True, encoding='utf-8')
self.assertIn('Atom', result.stdout)
self.assertIn('Visual Studio Code', result.stdout)
self.assertIn('Sublime', result.stdout)
if settings.my_os == 'Darwin':
self.assertIn('Atom', result.stdout)
self.assertIn('Visual Studio Code', result.stdout)
self.assertIn('Sublime', result.stdout)
if settings.my_os == 'Linux':
self.assertIn('atom', result.stdout)
self.assertIn('code', result.stdout)
self.assertIn('sublime', result.stdout)
self.assertIn('gedit', result.stdout)



@clean_run
Expand All @@ -127,7 +136,7 @@ def test_regenerate_code(self):
and some new files)
"""

# Generate new project
# Generate a new project
util.generate_code(project_path)
util.pio_init(project_path, board)
util.patch_platformio_ini(project_path)
Expand Down
58 changes: 33 additions & 25 deletions util.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ def generate_code(project_path):

logger.info("starting to generate a code from the CubeMX .ioc file...")
if logger.level <= logging.DEBUG:
result = subprocess.run(['java', '-jar', settings.cubemx_path, '-q', cubemx_script_full_filename])
result = subprocess.run([settings.java_cmd, '-jar', settings.cubemx_path, '-q', cubemx_script_full_filename])
else:
result = subprocess.run(['java', '-jar', settings.cubemx_path, '-q', cubemx_script_full_filename],
result = subprocess.run([settings.java_cmd, '-jar', settings.cubemx_path, '-q', cubemx_script_full_filename],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Or, for Python 3.7 and above:
# result = subprocess.run(['java', '-jar', settings.cubemx_path, '-q', cubemx_script_full_filename],
# result = subprocess.run([settings.java_cmd, '-jar', settings.cubemx_path, '-q', cubemx_script_full_filename],
# capture_output=True)
if result.returncode != 0:
logger.error(f"code generation error (return code is {result.returncode}).\n"
Expand Down Expand Up @@ -116,14 +116,16 @@ def patch_platformio_ini(project_path):

logger.debug("patching 'platformio.ini' file...")

with open(os.path.join(project_path, 'platformio.ini'), mode='a') as platformio_ini_file:
platformio_ini_file.write(settings.platformio_ini_patch_text)
if os.path.isfile(os.path.join(project_path, 'platformio.ini')):
with open(os.path.join(project_path, 'platformio.ini'), mode='a') as platformio_ini_file:
platformio_ini_file.write(settings.platformio_ini_patch_text)
logger.info("'platformio.ini' patched")
else:
logger.warning("'platformio.ini' file not found")

shutil.rmtree(os.path.join(project_path, 'include'), ignore_errors=True)
shutil.rmtree(os.path.join(project_path, 'src'), ignore_errors=True)

logger.info("'platformio.ini' patched")



def start_editor(project_path, editor):
Expand All @@ -135,24 +137,28 @@ def start_editor(project_path, editor):
editor: editor keyword
"""

# TODO: handle errors if there is no editor

logger.info("starting an editor...")

if settings.my_os == 'Windows':
if editor == 'atom':
subprocess.run(['atom', project_path], shell=True)
elif editor == 'vscode':
subprocess.run(['code', project_path], shell=True)
elif editor == 'sublime':
subprocess.run(['subl', project_path], shell=True)
else:
if editor == 'atom':
subprocess.run(['atom', project_path])
elif editor == 'vscode':
subprocess.run(['code', project_path])
elif editor == 'sublime':
subprocess.run(['subl', project_path])
try:
if settings.my_os == 'Windows':
if editor == 'atom':
subprocess.run(['atom', project_path], check=True, shell=True)
elif editor == 'vscode':
subprocess.run(['code', project_path], check=True, shell=True)
elif editor == 'sublime':
subprocess.run(['subl', project_path], check=True, shell=True)
else:
if editor == 'atom':
subprocess.run(['atom', project_path], check=True)
elif editor == 'vscode':
subprocess.run(['code', project_path], check=True)
elif editor == 'sublime':
subprocess.run(['subl', project_path], check=True)
elif editor == 'gedit':
subprocess.run(['gedit', project_path], check=True)

except subprocess.CalledProcessError as e:
logger.error(f"Failed to start the editor {editor}: {e.stdout}")



Expand All @@ -164,16 +170,18 @@ def clean(project_path):
project_path: path to the project
"""

# Get folder content
folder_content = os.listdir(project_path)
# Keep the '.ioc' file
if (os.path.basename(project_path) + '.ioc') in folder_content:
folder_content.remove(os.path.basename(project_path) + '.ioc')

for item in folder_content:
if os.path.isdir(os.path.join(project_path, item)):
shutil.rmtree(os.path.join(project_path, item), ignore_errors=True)
logger.debug('del ./' + item)
logger.debug(f"del {item}/")
elif os.path.isfile(os.path.join(project_path, item)):
os.remove(os.path.join(project_path, item))
logger.debug('del ' + item)
logger.debug(f"del {item}")

logger.info("project has been cleaned")

0 comments on commit 2662bdc

Please sign in to comment.