├── .editorconfig ├── .flake8 ├── .github └── workflows │ ├── release.yml │ ├── test-release.yaml │ └── test.yml ├── .gitignore ├── .readthedocs.yaml ├── .yamllint ├── LICENSE ├── QUICKSTART.md ├── README.md ├── changelog.md ├── docs ├── CONTRIBUTING.md ├── DOCUMENTATION.md ├── EXAMPLES.md ├── changelog_link.rst ├── conf.py ├── index.rst ├── nextion.rst ├── readme_link.rst └── requirements.txt ├── examples ├── README.md ├── basic │ └── main.py ├── boot.py ├── boot_wifi.py ├── button │ └── main.py ├── checkbox │ └── main.py ├── dual_button │ └── main.py ├── everything.HMI ├── everything.tft ├── gauge │ └── main.py ├── gpio │ └── main.py ├── hardware │ └── main.py ├── number │ └── main.py ├── page │ └── main.py ├── progressbar │ └── main.py ├── radio │ └── main.py ├── rtc │ └── main.py ├── slider │ └── main.py ├── text │ └── main.py ├── upload │ └── main.py └── waveform │ └── main.py ├── nextion ├── __init__.py ├── common.py ├── const.py ├── nextion_button.py ├── nextion_checkbox.py ├── nextion_dual_state_button.py ├── nextion_gauge.py ├── nextion_gpio.py ├── nextion_hardware.py ├── nextion_number.py ├── nextion_page.py ├── nextion_progressbar.py ├── nextion_radio.py ├── nextion_rtc.py ├── nextion_slider.py ├── nextion_text.py ├── nextion_upload.py ├── nextion_variable.py ├── nextion_waveform.py ├── typing.py ├── ulogging.py └── version.py ├── package.json ├── requirements-deploy.txt ├── requirements-test.txt ├── requirements.txt ├── sdist_upip.py └── setup.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | indent_style = space 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | # 4 space indentation 15 | [*.py] 16 | indent_size = 4 17 | 18 | [*.yml] 19 | indent_size = 2 20 | 21 | [*.{md,rst}] 22 | indent_size = 4 23 | trim_trailing_whitespace = false 24 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | # Configuration for flake8 analysis 2 | [flake8] 3 | # Set the maximum length that any line (with some exceptions) may be. 4 | # max-line-length = 120 5 | 6 | # Set the maximum length that a comment or docstring line may be. 7 | # max-doc-length = 120 8 | 9 | # Set the maximum allowed McCabe complexity value for a block of code. 10 | # max-complexity = 15 11 | 12 | # Specify a list of codes to ignore. 13 | # D107: Missing docstring in __init__ 14 | # D400: First line should end with a period 15 | # W504: line break after binary operator -> Cannot break line with a long pathlib Path 16 | # D204: 1 blank line required after class docstring 17 | ignore = D107, D400, W504, D204 18 | 19 | # Specify a list of mappings of files and the codes that should be ignored for the entirety of the file. 20 | per-file-ignores = 21 | tests/*:D101,D102,D104 22 | 23 | # Provide a comma-separated list of glob patterns to exclude from checks. 24 | exclude = 25 | # No need to traverse our git directory 26 | .git, 27 | # Python virtual environments 28 | .venv, 29 | # tox virtual environments 30 | .tox, 31 | # There's no value in checking cache directories 32 | __pycache__, 33 | # The conf file is mostly autogenerated, ignore it 34 | docs/conf.py, 35 | # This contains our built documentation 36 | build, 37 | # This contains builds that we don't want to check 38 | dist, 39 | # We don't use __init__.py for scripts 40 | __init__.py 41 | # example testing folder before going live 42 | thinking 43 | .idea 44 | .bak 45 | # custom scripts, not being part of the distribution 46 | sdist_upip.py 47 | setup.py 48 | 49 | # Provide a comma-separated list of glob patterns to add to the list of excluded ones. 50 | # extend-exclude = 51 | # legacy/, 52 | # vendor/ 53 | 54 | # Provide a comma-separate list of glob patterns to include for checks. 55 | # filename = 56 | # example.py, 57 | # another-example*.py 58 | 59 | # Enable PyFlakes syntax checking of doctests in docstrings. 60 | doctests = False 61 | 62 | # Specify which files are checked by PyFlakes for doctest syntax. 63 | # include-in-doctest = 64 | # dir/subdir/file.py, 65 | # dir/other/file.py 66 | 67 | # Specify which files are not to be checked by PyFlakes for doctest syntax. 68 | # exclude-from-doctest = 69 | # tests/* 70 | 71 | # Enable off-by-default extensions. 72 | # enable-extensions = 73 | # H111, 74 | # G123 75 | 76 | # If True, report all errors, even if it is on the same line as a # NOQA comment. 77 | disable-noqa = False 78 | 79 | # Specify the number of subprocesses that Flake8 will use to run checks in parallel. 80 | jobs = auto 81 | 82 | # Also print output to stdout if output-file has been configured. 83 | tee = True 84 | 85 | # Count the number of occurrences of each error/warning code and print a report. 86 | statistics = True 87 | 88 | # Print the total number of errors. 89 | count = True 90 | 91 | # Print the source code generating the error/warning in question. 92 | show-source = True 93 | 94 | # Decrease the verbosity of Flake8's output. Each time you specify it, it will print less and less information. 95 | quiet = 0 96 | 97 | # Select the formatter used to display errors to the user. 98 | format = pylint 99 | 100 | [pydocstyle] 101 | # choose the basic list of checked errors by specifying an existing convention. Possible conventions: pep257, numpy, google. 102 | convention = pep257 103 | 104 | # check only files that exactly match regular expression 105 | # match = (?!test_).*\.py 106 | 107 | # search only dirs that exactly match regular expression 108 | # match_dir = [^\.].* 109 | 110 | # ignore any functions or methods that are decorated by a function with a name fitting the regular expression. 111 | # ignore_decorators = 112 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # this file is *not* meant to cover or endorse the use of GitHub Actions, but 4 | # rather to help make automated releases for this project 5 | 6 | name: Upload Python Package 7 | 8 | on: 9 | push: 10 | branches: 11 | - develop 12 | 13 | permissions: 14 | contents: write 15 | 16 | jobs: 17 | deploy: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v3 22 | - name: Set up Python 23 | uses: actions/setup-python@v3 24 | with: 25 | python-version: '3.9' 26 | - name: Install build dependencies 27 | run: | 28 | python -m pip install --upgrade pip 29 | if [ -f requirements-deploy.txt ]; then pip install -r requirements-deploy.txt; fi 30 | - name: Build package 31 | run: | 32 | changelog2version \ 33 | --changelog_file changelog.md \ 34 | --version_file nextion/version.py \ 35 | --version_file_type py \ 36 | --debug 37 | python setup.py sdist 38 | - name: Test built package 39 | # sdist call creates non twine conform "*.orig" files, remove them 40 | run: | 41 | rm dist/*.orig 42 | twine check dist/*.tar.gz 43 | - name: Publish package 44 | uses: pypa/gh-action-pypi-publish@release/v1.5 45 | with: 46 | password: ${{ secrets.PYPI_API_TOKEN }} 47 | skip_existing: true 48 | verbose: true 49 | print_hash: true 50 | - name: 'Create changelog based release' 51 | uses: brainelectronics/changelog-based-release@v1 52 | with: 53 | # note you'll typically need to create a personal access token 54 | # with permissions to create releases in the other repo 55 | # or you set the "contents" permissions to "write" as in this example 56 | changelog-path: changelog.md 57 | tag-name-prefix: '' 58 | tag-name-extension: '' 59 | release-name-prefix: '' 60 | release-name-extension: '' 61 | draft-release: true 62 | prerelease: false 63 | -------------------------------------------------------------------------------- /.github/workflows/test-release.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # this file is *not* meant to cover or endorse the use of GitHub Actions, but 4 | # rather to help make automated test releases for this project 5 | 6 | name: Upload Python Package to test.pypi.org 7 | 8 | on: [pull_request] 9 | 10 | permissions: 11 | contents: write 12 | 13 | jobs: 14 | test-deploy: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | - name: Set up Python 20 | uses: actions/setup-python@v3 21 | with: 22 | python-version: '3.9' 23 | - name: Install build dependencies 24 | run: | 25 | if [ -f requirements-deploy.txt ]; then pip install -r requirements-deploy.txt; fi 26 | - name: Build package 27 | run: | 28 | changelog2version \ 29 | --changelog_file changelog.md \ 30 | --version_file nextion/version.py \ 31 | --version_file_type py \ 32 | --additional_version_info="-rc${{ github.run_number }}.dev${{ github.event.number }}" \ 33 | --debug 34 | # micropython-nextion is owned by someone else on test.pypi.org 35 | # rename package only for this case 36 | sed -i \ 37 | "s/name\='micropython-nextion'/name\='be-micropython-nextion'/" \ 38 | setup.py 39 | python setup.py sdist 40 | - name: Test built package 41 | # sdist call creates non twine conform "*.orig" files, remove them 42 | run: | 43 | rm dist/*.orig 44 | twine check dist/*.tar.gz 45 | - name: Archive build package artifact 46 | uses: actions/upload-artifact@v3 47 | with: 48 | # https://docs.github.com/en/actions/learn-github-actions/contexts#github-context 49 | # ${{ github.repository }} and ${{ github.ref_name }} can't be used for artifact name due to unallowed '/' 50 | name: dist_repo.${{ github.event.repository.name }}_sha.${{ github.sha }}_build.${{ github.run_number }} 51 | path: dist/*.tar.gz 52 | retention-days: 14 53 | - name: Publish package 54 | uses: pypa/gh-action-pypi-publish@release/v1.5 55 | with: 56 | repository_url: https://test.pypi.org/legacy/ 57 | password: ${{ secrets.TEST_PYPI_API_TOKEN }} 58 | skip_existing: true 59 | verbose: true 60 | print_hash: true 61 | - name: 'Create changelog based prerelease' 62 | uses: brainelectronics/changelog-based-release@v1 63 | with: 64 | # note you'll typically need to create a personal access token 65 | # with permissions to create releases in the other repo 66 | # or you set the "contents" permissions to "write" as in this example 67 | changelog-path: changelog.md 68 | tag-name-prefix: '' 69 | tag-name-extension: '-rc${{ github.run_number }}.dev${{ github.event.number }}' 70 | release-name-prefix: '' 71 | release-name-extension: '-rc${{ github.run_number }}.dev${{ github.event.number }}' 72 | draft-release: true 73 | prerelease: true 74 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # This workflow will install Python dependencies, run tests and lint with a 4 | # specific Python version 5 | # For more information see: 6 | # https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 7 | 8 | name: Test Python package 9 | 10 | on: 11 | push: 12 | # branches: [ $default-branch ] 13 | branches-ignore: 14 | - 'main' 15 | - 'develop' 16 | 17 | permissions: 18 | contents: read 19 | 20 | jobs: 21 | build: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v3 26 | - name: Set up Python 27 | uses: actions/setup-python@v3 28 | with: 29 | python-version: '3.9' 30 | - name: Install test dependencies 31 | run: | 32 | pip install -r requirements-test.txt 33 | - name: Lint with flake8 34 | run: | 35 | flake8 . 36 | - name: Lint with yamllint 37 | run: | 38 | yamllint . 39 | # - name: Test with pytest 40 | # run: | 41 | # python -m pip install pytest 42 | # pytest 43 | # - name: Test with nose2 44 | # run: | 45 | # python -m pip install nose2 46 | # nose2 --config tests/unittest.cfg 47 | # coverage xml 48 | # coverage html 49 | # - name: Upload pytest test results 50 | # uses: actions/upload-artifact@v3 51 | # with: 52 | # name: pytest-results-${{ matrix.python-version }} 53 | # path: junit/test-results-${{ matrix.python-version }}.xml 54 | # # Use always() to always run this step to publish test results when there are test failures 55 | # if: ${{ always() }} 56 | - name: Install deploy dependencies 57 | run: | 58 | if [ -f requirements-deploy.txt ]; then pip install -r requirements-deploy.txt; fi 59 | - name: Build package 60 | run: | 61 | changelog2version \ 62 | --changelog_file changelog.md \ 63 | --version_file nextion/version.py \ 64 | --version_file_type py \ 65 | --debug 66 | python setup.py sdist 67 | rm dist/*.orig 68 | - name: Test build package 69 | run: | 70 | twine check dist/* 71 | - name: Validate mip package file 72 | run: | 73 | upy-package \ 74 | --setup_file setup.py \ 75 | --package_changelog_file changelog.md \ 76 | --package_file package.json \ 77 | --validate \ 78 | --ignore-version 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # custom, package specific ignores 2 | .DS_Store 3 | .DS_Store? 4 | pymakr.conf 5 | config/config*.py 6 | thinking/ 7 | *.bin 8 | .idea 9 | *.bak 10 | *.o 11 | .vagrant/ 12 | 13 | # Byte-compiled / optimized / DLL files 14 | __pycache__/ 15 | *.py[cod] 16 | *$py.class 17 | 18 | # C extensions 19 | *.so 20 | 21 | # Distribution / packaging 22 | .Python 23 | build/ 24 | develop-eggs/ 25 | dist/ 26 | downloads/ 27 | eggs/ 28 | .eggs/ 29 | # micropython libs are stored in lib/ 30 | # lib/ 31 | lib64/ 32 | parts/ 33 | sdist/ 34 | var/ 35 | wheels/ 36 | share/python-wheels/ 37 | *.egg-info/ 38 | .installed.cfg 39 | *.egg 40 | MANIFEST 41 | 42 | # PyInstaller 43 | # Usually these files are written by a python script from a template 44 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 45 | *.manifest 46 | *.spec 47 | 48 | # Installer logs 49 | pip-log.txt 50 | pip-delete-this-directory.txt 51 | 52 | # Unit test / coverage reports 53 | htmlcov/ 54 | .tox/ 55 | .nox/ 56 | .coverage 57 | .coverage.* 58 | .cache 59 | nosetests.xml 60 | coverage.xml 61 | *.cover 62 | *.py,cover 63 | .hypothesis/ 64 | .pytest_cache/ 65 | cover/ 66 | 67 | # Translations 68 | *.mo 69 | *.pot 70 | 71 | # Django stuff: 72 | *.log 73 | local_settings.py 74 | db.sqlite3 75 | db.sqlite3-journal 76 | *.sqlite3 77 | 78 | # Flask stuff: 79 | instance/ 80 | .webassets-cache 81 | 82 | # Scrapy stuff: 83 | .scrapy 84 | 85 | # Sphinx documentation 86 | docs/_build/ 87 | 88 | # PyBuilder 89 | .pybuilder/ 90 | target/ 91 | 92 | # Jupyter Notebook 93 | .ipynb_checkpoints 94 | 95 | # IPython 96 | profile_default/ 97 | ipython_config.py 98 | 99 | # pyenv 100 | # For a library or package, you might want to ignore these files since the code is 101 | # intended to run in multiple environments; otherwise, check them in: 102 | # .python-version 103 | 104 | # pipenv 105 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 106 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 107 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 108 | # install all needed dependencies. 109 | #Pipfile.lock 110 | 111 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 112 | __pypackages__/ 113 | 114 | # Celery stuff 115 | celerybeat-schedule 116 | celerybeat.pid 117 | 118 | # SageMath parsed files 119 | *.sage.py 120 | 121 | # Environments 122 | .env 123 | .venv 124 | env/ 125 | venv/ 126 | ENV/ 127 | env.bak/ 128 | venv.bak/ 129 | 130 | # Spyder project settings 131 | .spyderproject 132 | .spyproject 133 | 134 | # Rope project settings 135 | .ropeproject 136 | 137 | # mkdocs documentation 138 | /site 139 | 140 | # mypy 141 | .mypy_cache/ 142 | .dmypy.json 143 | dmypy.json 144 | 145 | # Pyre type checker 146 | .pyre/ 147 | 148 | # pytype static type analyzer 149 | .pytype/ 150 | 151 | # Cython debug symbols 152 | cython_debug/ 153 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Read the Docs configuration file 4 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 5 | 6 | # Required 7 | version: 2 8 | 9 | # Set the version of Python and other tools you might need 10 | build: 11 | os: ubuntu-22.04 12 | tools: 13 | python: "3.9" 14 | 15 | # Build documentation in the docs/ directory with Sphinx 16 | sphinx: 17 | configuration: docs/conf.py 18 | 19 | # Optionally declare the Python requirements required to build your docs 20 | python: 21 | install: 22 | - requirements: docs/requirements.txt 23 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | extends: default 4 | 5 | ignore: 6 | - .tox 7 | - .venv 8 | 9 | rules: 10 | line-length: 11 | level: warning 12 | ignore: 13 | - .github/workflows/* 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 brainelectronics and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /QUICKSTART.md: -------------------------------------------------------------------------------- 1 | # MicroPython Nextion library 2 | 3 | [![Downloads](https://pepy.tech/badge/micropython-nextion)](https://pepy.tech/project/micropython-nextion) 4 | ![Release](https://img.shields.io/github/v/release/brainelectronics/micropython-nextion?include_prereleases&color=success) 5 | ![MicroPython](https://img.shields.io/badge/micropython-Ok-green.svg) 6 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 7 | 8 | MicroPython Nextion library 9 | 10 | --------------- 11 | 12 | ## Get started 13 | 14 | This is a quickstart guide to flash the 15 | [MicroPython firmware][ref-upy-firmware-download], connect to a network and 16 | install the MicroPython Nextion library on the board 17 | 18 | ### Flash firmware 19 | 20 | ```bash 21 | esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART erase_flash 22 | esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART --baud 921600 write_flash -z 0x1000 esp32spiram-20220117-v1.18.bin 23 | ``` 24 | 25 | ### Install package 26 | 27 | Connect the MicroPython device to a network (if possible) 28 | 29 | ```python 30 | import network 31 | station = network.WLAN(network.STA_IF) 32 | station.active(True) 33 | station.connect('SSID', 'PASSWORD') 34 | station.isconnected() 35 | ``` 36 | 37 | Install the latest package version of this lib on the MicroPython device 38 | 39 | ```python 40 | import mip 41 | mip.install("github:brainelectronics/micropython-nextion") 42 | ``` 43 | 44 | For MicroPython versions below 1.19.1 use the `upip` package instead of `mip` 45 | 46 | ```python 47 | import upip 48 | upip.install('micropython-nextion') 49 | ``` 50 | 51 | ### Copy example file 52 | 53 | Copy one of the provided example `main.py` files to the MicroPython device. 54 | 55 | ```bash 56 | rshell --port /dev/tty.SLAB_USBtoUART --editor nano 57 | ``` 58 | 59 | Perform the following command inside the `rshell` to copy the Progressbar example to the MicroPython device. 60 | 61 | ```bash 62 | cp examples/progressbar/main.py /pyboard 63 | cp examples/boot.py /pyboard 64 | repl 65 | ``` 66 | 67 | 68 | [ref-upy-firmware-download]: https://micropython.org/download/ 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MicroPython Nextion library 2 | 3 | [![Downloads](https://pepy.tech/badge/micropython-nextion)](https://pepy.tech/project/micropython-nextion) 4 | ![Release](https://img.shields.io/github/v/release/brainelectronics/micropython-nextion?include_prereleases&color=success) 5 | ![MicroPython](https://img.shields.io/badge/micropython-Ok-green.svg) 6 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 7 | 8 | MicroPython Nextion library 9 | 10 | --------------- 11 | 12 | ## General 13 | 14 | Ported library to interact with [Nextion serial displays][ref-nextion-wiki], 15 | based on the [ITEAD Arduino Nextion][ref-itead-nextion-github] library. 16 | 17 | ## Installation 18 | 19 | ### Install required tools 20 | 21 | Python3 must be installed on your system. Check the current Python version 22 | with the following command 23 | 24 | ```bash 25 | python --version 26 | python3 --version 27 | ``` 28 | 29 | Depending on which command `Python 3.x.y` (with x.y as some numbers) is 30 | returned, use that command to proceed. 31 | 32 | ```bash 33 | python3 -m venv .venv 34 | source .venv/bin/activate 35 | 36 | pip install -r requirements.txt 37 | ``` 38 | 39 | ## Setup 40 | 41 | ### Install package 42 | 43 | Connect the MicroPython device to a network (if possible) 44 | 45 | ```python 46 | import network 47 | station = network.WLAN(network.STA_IF) 48 | station.active(True) 49 | station.connect('SSID', 'PASSWORD') 50 | station.isconnected() 51 | ``` 52 | 53 | #### General 54 | 55 | Install the latest package version of this lib on the MicroPython device 56 | 57 | ```python 58 | import mip 59 | mip.install("github:brainelectronics/micropython-nextion") 60 | ``` 61 | 62 | For MicroPython versions below 1.19.1 use the `upip` package instead of `mip` 63 | 64 | ```python 65 | import upip 66 | upip.install('micropython-nextion') 67 | ``` 68 | 69 | #### Specific version 70 | 71 | Install a specific, fixed package version of this lib on the MicroPython device 72 | 73 | ```python 74 | import mip 75 | # install a verions of a specific branch 76 | mip.install("github:brainelectronics/micropython-nextion", version="feature/add-mip-package-file") 77 | # install a tag version 78 | mip.install("github:brainelectronics/micropython-nextion", version="0.15.0") 79 | ``` 80 | 81 | For MicroPython versions below 1.19.1 use the `upip` package instead of `mip` 82 | 83 | ```python 84 | import upip 85 | upip.install('micropython-nextion') 86 | ``` 87 | 88 | #### Test version 89 | 90 | Install a specific release candidate version uploaded to 91 | [Test Python Package Index](https://test.pypi.org/) on every PR on the 92 | MicroPython device. If no specific version is set, the latest stable version 93 | will be used. 94 | 95 | ```python 96 | import mip 97 | mip.install("github:brainelectronics/micropython-nextion", version="0.15.0-rc1.dev29") 98 | ``` 99 | 100 | For MicroPython versions below 1.19.1 use the `upip` package instead of `mip` 101 | 102 | ```python 103 | import upip 104 | # overwrite index_urls to only take artifacts from test.pypi.org 105 | upip.index_urls = ['https://test.pypi.org/pypi'] 106 | upip.install('micropython-nextion') 107 | ``` 108 | 109 | See also [brainelectronics Test PyPi Server in Docker][ref-brainelectronics-test-pypiserver] 110 | for a test PyPi server running on Docker. 111 | 112 | ### Manually 113 | 114 | #### Upload files to board 115 | 116 | Copy the module to the MicroPython board and import them as shown below 117 | using [Remote MicroPython shell][ref-remote-upy-shell] 118 | 119 | Open the remote shell with the following command. Additionally use `-b 115200` 120 | in case no CP210x is used but a CH34x. 121 | 122 | ```bash 123 | rshell --port /dev/tty.SLAB_USBtoUART --editor nano 124 | ``` 125 | 126 | Perform the following command inside the `rshell` to copy all files and 127 | folders to the device 128 | 129 | ```bash 130 | mkdir /pyboard/lib 131 | mkdir /pyboard/lib/nextion 132 | 133 | cp nextion/* /pyboard/lib/nextion 134 | 135 | cp examples/basic/main.py /pyboard 136 | cp examples/boot.py /pyboard 137 | ``` 138 | 139 | ## Usage 140 | 141 | Use one of the [examples](examples/) to get started. Read also the 142 | [examples README](examples/README.md) to find all supported elements 143 | 144 | ## Credits 145 | 146 | Big thank you to [ITEAD Studio][ref-itead-github] for the implementation 147 | of the Arduino library. 148 | 149 | 150 | [ref-nextion-wiki]: https://wiki.iteadstudio.com/Nextion_HMI_Solution 151 | [ref-itead-nextion-github]: https://github.com/itead/ITEADLIB_Arduino_Nextion 152 | [ref-remote-upy-shell]: https://github.com/dhylands/rshell 153 | [ref-brainelectronics-test-pypiserver]: https://github.com/brainelectronics/test-pypiserver 154 | [ref-github-be-mircopython-modules]: https://github.com/brainelectronics/micropython-modules 155 | [ref-itead-github]: https://github.com/itead 156 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | 14 | 18 | 19 | ## Released 20 | ## [0.16.0] - 2023-06-12 21 | ### Added 22 | - Validate `package.json` file with every test workflow run but without version validation 23 | - Basic setup instructions added to docs examples file 24 | 25 | ### Changed 26 | - Update `nextion/ulogging.py` to [version 0.5 of micropython-lib](https://github.com/micropython/micropython-lib/blob/7128d423c2e7c0309ac17a1e6ba873b909b24fcc/python-stdlib/logging/logging.py) 27 | 28 | ### Removed 29 | - Outdated and unused `libs_external` folder with `ulogging.py` 30 | - `libs_external` and `nextion/ulogging.py` removed from `.flake8` exclude list 31 | 32 | ### Fixed 33 | - Installation instructions in Quickstart document are using `mip` 34 | 35 | ## [0.15.3] - 2023-05-17 36 | ### Fixed 37 | - Publish releases to PyPi again as `micropython-nextion`, see #35 38 | 39 | ## [0.15.2] - 2023-05-14 40 | ### Fixed 41 | - Logger import fixed, see #31 42 | - Examples README improved with MicroPython port specific UART pin usage example, see #30 43 | 44 | ## [0.15.1] - 2023-05-14 45 | ### Fixed 46 | - Remove yet unavailable files from `package.json`, see #33 47 | - Add `ulogging` module to package to remove all external dependencies 48 | 49 | ## [0.15.0] - 2023-05-13 50 | ### Added 51 | - `package.json` for `mip` installation with MicroPython v1.19.1 or newer, see #27 52 | - Instructions for installation with `mip` on MicroPython v1.19.1 or newer in `README`, see #27 53 | - UART ID can be specified in `NexHardware` with `uart_id`, see #29 54 | 55 | ## [0.14.0] - 2023-03-01 56 | ### Added 57 | - `.editorconfig` for common editor settings 58 | - `.yamllint` to lint all used YAML files 59 | - `requirements-test.txt` file 60 | - Run YAML linter on test workflow 61 | - `.readthedocs.yaml` definition file for ReadTheDocs 62 | - `docs` folder containing example files and configurations, see #24 63 | - `test-release` and `release` workflows create changelog based (pre-)releases 64 | - Documentation for changing a value on a non active page, see #20 65 | 66 | ### Changed 67 | - Removed unused files from `.gitignore` file 68 | - Fail workflow on flake8 violations, see #23 69 | 70 | ### Fixed 71 | - All workflows use checkout v3 instead of v2 72 | - Fixed uncovered YAML syntax issues in all workflow files 73 | 74 | ## [0.13.0] - 2022-10-23 75 | ### Added 76 | - `changelog2version` to [requirements file](requirements-deploy.txt) 77 | - [GitHub CI test release workflow](.github/workflows/test-release.yml) to 78 | deploy package as `be-micropython-nextion` to 79 | [Test Python Package Index](https://test.pypi.org/) on every PR 80 | - [Quickstart guide](QUICKSTART.md) 81 | 82 | ### Changed 83 | - Use [`changelog2version`][ref-changelog2version-package] to create package 84 | version file, see [#19][ref-issue-19], in: 85 | - [GitHub CI test workflow](.github/workflows/test.yml) 86 | - [GitHub CI release workflow](.github/workflows/release.yml) 87 | 88 | ### Removed 89 | - Script `update_version.py` to update version file 90 | 91 | ### Fixed 92 | - Flake8 warning in [`nextion_waveform`](nextion/nextion_waveform.py) and 93 | [`nextion_hardware`](nextion/nextion_hardware.py), see [#17][ref-issue-17] 94 | - Use `self._logger.*` instead of `self._nh._logger.*` in: 95 | - [`nextion_rtc`](nextion/nextion_rtc.py) 96 | - [`nextion_upload`](nextion/nextion_upload.py) 97 | - Path of `main.py` to copy manually to the MicroPython board described in 98 | [`README`](README.md) 99 | 100 | ## [0.12.0] - 2022-07-30 101 | ### Added 102 | - Support `NexRtc` usage with [`nextion_rtc`](nextion/nextion_rtc.py) 103 | 104 | ### Fixed 105 | - Add missing documentation for [upload example](examples/upload/main.py) to 106 | [examples README](examples/) 107 | 108 | ## [0.11.0] - 2022-07-30 109 | ### Added 110 | - Support `NexUpload` usage with [`nextion_upload`](nextion/nextion_upload.py) 111 | - [Compiled example TFT file](examples/everything.tft) for 112 | [upload example](examples/upload/main.py) 113 | 114 | ## [0.10.0] - 2022-07-30 115 | ### Added 116 | - Support `NexVariable` usage with 117 | [`nextion_variable`](nextion/nextion_variable.py) 118 | 119 | ### Fixed 120 | - Add full line comment between different section of all examples 121 | 122 | ## [0.9.0] - 2022-07-30 123 | ### Added 124 | - Support GPIO usage with [`nextion_gpio`](nextion/nextion_gpio.py) 125 | - [Usage example](examples/gpio/main.py) of GPIO 126 | 127 | ## [0.8.0] - 2022-07-30 128 | ### Added 129 | - Support all class specific functions of 130 | - Button 131 | - Dual state button 132 | - Number 133 | - Slider 134 | - Waveform 135 | 136 | ### Changed 137 | - Add full line comment between different section of examples 138 | 139 | ### Fixed 140 | - Flake8 warnings in several classes due to many imports and inheritance 141 | 142 | ## [0.7.1] - 2022-07-29 143 | ### Fixed 144 | - Add class `CommonPointerMixin` to [`common`](nextion/common.py) 145 | 146 | ## [0.7.0] - 2022-07-29 147 | ### Added 148 | - Support `Get_pointer_thickness_wid` and `Set_pointer_thickness_wid` by new 149 | class `CommonPointerMixin` in [`common`](nextion/common.py) 150 | 151 | ### Changed 152 | - Inherit from `CommonPointerMixin` in 153 | - Gauge 154 | - Slider 155 | 156 | ## [0.6.0] - 2022-07-29 157 | ### Added 158 | - Support `Get_place_xcen`, `Set_place_xcen`, `Get_place_ycen` and 159 | `Set_place_ycen` by new class `CommonPositionMixin` in 160 | [`common`](nextion/common.py) 161 | 162 | ### Changed 163 | - Inherit from `CommonPositionMixin` in 164 | - Button 165 | - Dual state button 166 | - Number 167 | - Text 168 | 169 | ### Fixed 170 | - Remove unused imports in nextion elements 171 | 172 | ## [0.5.0] - 2022-07-29 173 | ### Added 174 | - Support `Get_background_color_bco` and `Set_background_color_bco` by new 175 | class `CommonBackgroundColorMixin` in [`common`](nextion/common.py) 176 | - Support `Get_font_color_pco`, `Set_font_color_pco`, `getFont` and `setFont` 177 | by new class `CommonFontMixin` in [`common`](nextion/common.py) 178 | 179 | ### Changed 180 | - Inherit from `CommonFontMixin` and `CommonBackgroundColorMixin` in 181 | - Button 182 | - Checkbox 183 | - Dual state button 184 | - Gauge 185 | - Number 186 | - Progressbar 187 | - Radio 188 | - Slider 189 | - Text 190 | - Waveform 191 | 192 | ### Fixed 193 | - Remove unsupported `CommonValueMixin` from Button 194 | - Some typos in comments 195 | 196 | ## [0.4.0] - 2022-07-24 197 | ### Added 198 | - `clearChannel(channel)` in [`nextion_waveform`](nextion/nextion_waveform.py) 199 | to clear a waveform channel data 200 | - Script to [update version file](update_version.py) based on changelog entry 201 | - [Requirements file](requirements-deploy.txt) for GitHub CI python publish 202 | workflow 203 | - [GitHub CI python publish workflow](.github/workflows/python-publish.yml) 204 | 205 | ### Fixed 206 | - Replace undefined `__author__` in [`setup.py`](setup.py) 207 | - Add missing shebang header to [`version`](nextion/version.py) file 208 | 209 | ## [0.3.0] - 2022-07-22 210 | ### Added 211 | - Function `hide()` and `show()` for all supported Nextion elements to hide 212 | or show the element on the screen 213 | - Example how to hide and show an element in 214 | [hardware example](examples/hardware/main.py) 215 | 216 | ## [0.2.0] - 2022-07-21 217 | ### Added 218 | - `brightness(value)` to [`nextion_hardware`](nextion/nextion_hardware.py) to 219 | control the display brightness 220 | - `sleep(state)` to [`nextion_hardware`](nextion/nextion_hardware.py) to set 221 | display into sleep mode or wake it up 222 | - `reset()` to [`nextion_hardware`](nextion/nextion_hardware.py) to reset the 223 | display to its default view like after a power cycle 224 | - [Hardware example](examples/hardware) to show usage of new hardware functions 225 | 226 | ### Fixed 227 | - Invalid pin usage in [`boot_wifi.py`](examples/boot_wifi.py) file 228 | 229 | ## [0.1.0] - 2022-07-21 230 | ### Added 231 | - This changelog file 232 | - [`.gitignore`](.gitignore) file 233 | - [`.flake8`](.flake8) file 234 | - [`setup.py`](setup.py) and [`sdist_upip.py`](sdist_upip.py) files for PyPi 235 | package creation and deploy 236 | - [`LICENSE`](LICENSE) file 237 | - [`requirements.txt`](requirements.txt) file to setup tools for board 238 | interactions 239 | - [`README`](README.md) file with usage instructions 240 | - Initial [`nextion`](nextion) library with basic element function support 241 | - Example [`boot.py`](examples/boot.py) and 242 | [`boot_wifi.py`](examples/boot_wifi.py) files 243 | - [Examples](examples) for all [supported Nextion elements](examples/README.md) 244 | - [Example HMI file](examples/everything.HMI) to be used for all examples 245 | 246 | 247 | [Unreleased]: https://github.com/brainelectronics/micropython-nextion/compare/0.16.0...develop 248 | 249 | [0.16.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.16.0 250 | [0.15.3]: https://github.com/brainelectronics/micropython-nextion/tree/0.15.3 251 | [0.15.2]: https://github.com/brainelectronics/micropython-nextion/tree/0.15.2 252 | [0.15.1]: https://github.com/brainelectronics/micropython-nextion/tree/0.15.1 253 | [0.15.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.15.0 254 | [0.14.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.14.0 255 | [0.13.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.13.0 256 | [0.12.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.12.0 257 | [0.11.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.11.0 258 | [0.10.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.10.0 259 | [0.9.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.9.0 260 | [0.8.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.8.0 261 | [0.7.1]: https://github.com/brainelectronics/micropython-nextion/tree/0.7.1 262 | [0.7.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.7.0 263 | [0.6.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.6.0 264 | [0.5.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.5.0 265 | [0.4.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.4.0 266 | [0.3.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.3.0 267 | [0.2.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.2.0 268 | [0.1.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.1.0 269 | 270 | [ref-issue-17]: https://github.com/brainelectronics/micropython-nextion/issues/17 271 | [ref-issue-19]: https://github.com/brainelectronics/micropython-nextion/issues/19 272 | 273 | [ref-changelog2version-package]: https://pypi.org/project/changelog2version/ 274 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Guideline to contribute to this package 4 | 5 | --------------- 6 | 7 | ## TBD 8 | -------------------------------------------------------------------------------- /docs/DOCUMENTATION.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | Documentation is generated by using Sphinx and published on RTD 4 | 5 | --------------- 6 | 7 | ## Documentation 8 | 9 | Documentation is automatically created on each merge to the development 10 | branch, as well as with each pull request and available 11 | [📚 here at Read the Docs][ref-rtd-micropython-nextion] 12 | 13 | ### Install required packages 14 | 15 | ```bash 16 | # create and activate virtual environment 17 | python3 -m venv .venv 18 | source .venv/bin/activate 19 | 20 | # install and upgrade required packages 21 | pip install -U -r docs/requirements.txt 22 | ``` 23 | 24 | ### Create documentation 25 | 26 | Some usefull checks have been disabled in the `docs/conf.py` file. Please 27 | check the documentation build output locally before opening a PR. 28 | 29 | ```bash 30 | # perform link checks 31 | sphinx-build docs/ docs/build/linkcheck -d docs/build/docs_doctree/ --color -blinkcheck -j auto -W 32 | 33 | # create documentation 34 | sphinx-build docs/ docs/build/html/ -d docs/build/docs_doctree/ --color -bhtml -j auto -W 35 | ``` 36 | 37 | The created documentation can be found at [`docs/build/html`](docs/build/html). 38 | 39 | 40 | [ref-rtd-micropython-nextion]: https://micropython-nextion.readthedocs.io/en/latest/ 41 | -------------------------------------------------------------------------------- /docs/EXAMPLES.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Usage examples of this `micropython-nextion` library 4 | 5 | --------------- 6 | 7 | ## General 8 | 9 | An example of all implemented functionalities can be found at the 10 | [MicroPython Nextion examples folder][ref-micropython-nextion-examples] 11 | 12 | ## Setup Nextion 13 | 14 | ```python 15 | from nextion import NexHardware 16 | 17 | # define communication pins for Nextion display 18 | tx_pin = 21 19 | rx_pin = 22 20 | 21 | # create Nextion hardware interface 22 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 23 | 24 | # init nextion communication interface 25 | nh.nexInit() 26 | 27 | # modify text field "t0" showing "newtxt" by default 28 | cmd = 't0.txt="asdf"' 29 | nh.sendCommand(cmd) 30 | ``` 31 | 32 | ## Special hints 33 | 34 | ### Access object on a non active page 35 | 36 | In order to modify an object on another page than the currently displayed one, prepend the page name to the object/component name. 37 | 38 | The valid and working way could be 39 | 40 | ```python 41 | # default way of accessing a Nextion Number object "n0" on page "0" with the 42 | # component ID "1" 43 | n0 = NexNumber(nh, 0, 1, "n0") 44 | 45 | # assuming currently page3 is active 46 | # activate the page of the desired Nextion Number object and set its value 47 | page1.show() 48 | n0.setValue(35) 49 | 50 | # return to the previous page 51 | page3.show() 52 | ``` 53 | 54 | A more elegant way of achieving the same result, see 55 | [comment and solution of vahithosan][ref-modify-object-on-non-active-page] 56 | 57 | ```python 58 | # access the Nextion Number object "n0" on page "0" with the component ID "1" 59 | # from another page directly without showing the page first 60 | n0 = NexNumber(nh, 0, 1, "page0.n0") 61 | 62 | # assuming currently page3 is active 63 | # activate the page of the desired Nextion Number object and set its value 64 | n0.setValue(35) 65 | 66 | # show page with already updated value 67 | page1.show() 68 | ``` 69 | 70 | 71 | [ref-micropython-nextion-examples]: https://github.com/brainelectronics/micropython-nextion/tree/develop/examples 72 | [ref-modify-object-on-non-active-page]: https://github.com/brainelectronics/micropython-nextion/issues/20#issuecomment-1289640668 73 | -------------------------------------------------------------------------------- /docs/changelog_link.rst: -------------------------------------------------------------------------------- 1 | 2 | .. include:: ../changelog.md 3 | :parser: myst_parser.sphinx_ -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | 3 | import os 4 | import sys 5 | from pathlib import Path 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | sys.path.insert(0, os.path.abspath('../')) 14 | here = Path(__file__).parent.resolve() 15 | 16 | try: 17 | # Inject mock modules so that we can build the 18 | # documentation without having the real stuff available 19 | from mock import Mock 20 | 21 | to_be_mocked = [ 22 | 'micropython', 23 | 'machine', 24 | 'ulogging', 25 | 'time.ticks_diff', 'time.ticks_ms', 26 | ] 27 | for module in to_be_mocked: 28 | sys.modules[module] = Mock() 29 | print("Mocked '{}' module".format(module)) 30 | from nextion import common 31 | except ImportError: 32 | raise SystemExit("nextion has to be importable") 33 | else: 34 | pass 35 | 36 | # load elements of version.py 37 | exec(open(here / '..' / 'nextion' / 'version.py').read()) 38 | 39 | # -- Project information 40 | 41 | project = 'micropython-nextion' 42 | copyright = '2023, brainelectronics' 43 | author = 'brainelectronics' 44 | 45 | version = __version__ 46 | release = version 47 | 48 | # -- General configuration 49 | 50 | # Add any Sphinx extension module names here, as strings. They can be 51 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 52 | # ones. 53 | extensions = [ 54 | 'myst_parser', 55 | 'sphinx.ext.autodoc', 56 | 'sphinx.ext.autosectionlabel', 57 | 'sphinx.ext.autosummary', 58 | 'sphinx.ext.doctest', 59 | 'sphinx.ext.duration', 60 | 'sphinx.ext.intersphinx', 61 | 'sphinx.ext.viewcode', 62 | ] 63 | autosectionlabel_prefix_document = True 64 | 65 | # The suffix of source filenames. 66 | source_suffix = ['.rst', '.md'] 67 | 68 | intersphinx_mapping = { 69 | 'python': ('https://docs.python.org/3/', None), 70 | 'sphinx': ('https://www.sphinx-doc.org/en/master/', None), 71 | } 72 | intersphinx_disabled_domains = ['std'] 73 | suppress_warnings = [ 74 | # throws an error due to not found reference targets to files not in docs/ 75 | 'ref.myst', 76 | # throws an error due to multiple "Added" labels in "changelog.md" 77 | 'autosectionlabel.*' 78 | ] 79 | 80 | # A list of regular expressions that match URIs that should not be checked 81 | # when doing a linkcheck build. 82 | linkcheck_ignore = [ 83 | # tag 0.14.0 did not exist during docs introduction 84 | 'https://github.com/brainelectronics/micropython-nextion/tree/0.14.0', 85 | # RTD page did not exist during docs introduction 86 | 'https://micropython-nextion.readthedocs.io/en/latest/', 87 | ] 88 | 89 | templates_path = ['_templates'] 90 | 91 | # -- Options for HTML output 92 | 93 | # The theme to use for HTML and HTML Help pages. See the documentation for 94 | # a list of builtin themes. 95 | # 96 | html_theme = 'sphinx_rtd_theme' 97 | 98 | # -- Options for EPUB output 99 | epub_show_urls = 'footnote' 100 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | MicroPython Nextion 2 | =================================== 3 | 4 | Contents 5 | -------- 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | readme_link 11 | EXAMPLES 12 | DOCUMENTATION 13 | CONTRIBUTING 14 | nextion 15 | changelog_link 16 | 17 | Indices and tables 18 | ================== 19 | 20 | * :ref:`genindex` 21 | * :ref:`modindex` 22 | -------------------------------------------------------------------------------- /docs/nextion.rst: -------------------------------------------------------------------------------- 1 | API 2 | ======================= 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | Nextion Constants 8 | --------------------------------- 9 | 10 | .. automodule:: nextion.const 11 | :members: 12 | :private-members: 13 | :show-inheritance: 14 | 15 | Common module 16 | --------------------------------- 17 | 18 | .. automodule:: nextion.common 19 | :members: 20 | :private-members: 21 | :show-inheritance: 22 | 23 | Button 24 | --------------------------------- 25 | 26 | .. automodule:: nextion.nextion_button 27 | :members: 28 | :private-members: 29 | :show-inheritance: 30 | 31 | Checkbox 32 | --------------------------------- 33 | 34 | .. automodule:: nextion.nextion_checkbox 35 | :members: 36 | :private-members: 37 | :show-inheritance: 38 | 39 | Dual State Button 40 | --------------------------------- 41 | 42 | .. automodule:: nextion.nextion_dual_state_button 43 | :members: 44 | :private-members: 45 | :show-inheritance: 46 | 47 | Gauge 48 | --------------------------------- 49 | 50 | .. automodule:: nextion.nextion_gauge 51 | :members: 52 | :private-members: 53 | :show-inheritance: 54 | 55 | GPIO 56 | --------------------------------- 57 | 58 | .. automodule:: nextion.nextion_gpio 59 | :members: 60 | :private-members: 61 | :show-inheritance: 62 | 63 | Hardware 64 | --------------------------------- 65 | 66 | .. automodule:: nextion.nextion_hardware 67 | :members: 68 | :private-members: 69 | :show-inheritance: 70 | 71 | Number 72 | --------------------------------- 73 | 74 | .. automodule:: nextion.nextion_number 75 | :members: 76 | :private-members: 77 | :show-inheritance: 78 | 79 | Page 80 | --------------------------------- 81 | 82 | .. automodule:: nextion.nextion_page 83 | :members: 84 | :private-members: 85 | :show-inheritance: 86 | 87 | Progressbar 88 | --------------------------------- 89 | 90 | .. automodule:: nextion.nextion_progressbar 91 | :members: 92 | :private-members: 93 | :show-inheritance: 94 | 95 | Radio Button 96 | --------------------------------- 97 | 98 | .. automodule:: nextion.nextion_radio 99 | :members: 100 | :private-members: 101 | :show-inheritance: 102 | 103 | RTC 104 | --------------------------------- 105 | 106 | .. automodule:: nextion.nextion_rtc 107 | :members: 108 | :private-members: 109 | :show-inheritance: 110 | 111 | Scrolltext 112 | --------------------------------- 113 | 114 | .. automodule:: nextion.nextion_scrolltext 115 | :members: 116 | :private-members: 117 | :show-inheritance: 118 | 119 | Slider 120 | --------------------------------- 121 | 122 | .. automodule:: nextion.nextion_slider 123 | :members: 124 | :private-members: 125 | :show-inheritance: 126 | 127 | Text 128 | --------------------------------- 129 | 130 | .. automodule:: nextion.nextion_text 131 | :members: 132 | :private-members: 133 | :show-inheritance: 134 | 135 | Upload 136 | --------------------------------- 137 | 138 | .. automodule:: nextion.nextion_upload 139 | :members: 140 | :private-members: 141 | :show-inheritance: 142 | 143 | Variable 144 | --------------------------------- 145 | 146 | .. automodule:: nextion.nextion_variable 147 | :members: 148 | :private-members: 149 | :show-inheritance: 150 | 151 | Waveform 152 | --------------------------------- 153 | 154 | .. automodule:: nextion.nextion_waveform 155 | :members: 156 | :private-members: 157 | :show-inheritance: 158 | -------------------------------------------------------------------------------- /docs/readme_link.rst: -------------------------------------------------------------------------------- 1 | 2 | .. include:: ../README.md 3 | :parser: myst_parser.sphinx_ -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | # use fixed versions 2 | # 3 | # fix docutils to a version working for all 4 | docutils >=0.14,<0.18 5 | 6 | # sphinx 5.3.0 requires Jinja2 >=3.0 and docutils >=0.14,<0.20 7 | sphinx >=5.0.0,<6 8 | 9 | # sphinx-rtd-theme >=1.0.0 would require docutils <0.18 10 | sphinx-rtd-theme >=1.0.0,<2 11 | 12 | # replaces outdated and no longer maintained m2rr 13 | myst-parser >= 0.18.1,<1 14 | 15 | # mock imports of "micropython" 16 | mock >=4.0.3,<5 17 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | ## Examples Overview 2 | 3 | | Example | Nextion name | Supported | 4 | | ------------------------- | ------------- | ------------------ | 5 | | [Button](button) | NexButton | :heavy_check_mark: | 6 | | [Checkbox](checkbox) | NexCheckbox | :heavy_check_mark: | 7 | | [Crop](crop) | NexCrop | :x: | 8 | | [DualButton](dual_button) | NexDual | :heavy_check_mark: | 9 | | [Gauge](gauge) | NexGauge | :heavy_check_mark: | 10 | | [Gpio](gpio) | NexGpio | :heavy_check_mark: | 11 | | [Hardware](hardware) | NexHardware | :heavy_check_mark: | 12 | | [Hotspot](hotspot) | NexHotspot | :x: | 13 | | [Number](number) | NexNumber | :heavy_check_mark: | 14 | | [Page](page) | NexPage | :heavy_check_mark: | 15 | | [Picture](picture) | NexPicture | :x: | 16 | | [Progress](progress) | NexProgress | :heavy_check_mark: | 17 | | [Radio](radio) | NexRadio | :heavy_check_mark: | 18 | | [Rtc](rtc) | NexRtc | :heavy_check_mark: | 19 | | [Scrolltext](scrolltext) | NexScrolltext | :x: | 20 | | [Slider](slider) | NexSlider | :heavy_check_mark: | 21 | | [Text](text) | NexText | :heavy_check_mark: | 22 | | [Timer](timer) | NexTimer | :x: | 23 | | [Touch](touch) | NexTouch | :x: | 24 | | [Upload](upload) | NexUpload | :heavy_check_mark: | 25 | | [Variable](variable) | NexVariable | :heavy_check_mark: | 26 | | [waveform](waveform) | NexWaveform | :heavy_check_mark: | 27 | 28 | 29 | 30 | ## Basic example 31 | 32 | The [basic example](basic/main.py) shows the usage of all supported Nextion 33 | elements by simple UART command calls. 34 | 35 | The provided examples are designed for an **ESP32**. 36 | 37 | Check [MicroPython UART documentation](https://docs.micropython.org/en/latest/library/machine.UART.html) 38 | and the device/port specific setup for further details. 39 | 40 | On a RP2 the RX and TX pin needs to be defined as e.g. `tx_pin = Pin(4)`, 41 | `rx_pin = Pin(5)` and `uart_id = 1` whereas an ESP32 can use any pin with e.g. 42 | `tx_pin = 21` and `rx_pin = 22` and `uart_id = 1`. 43 | 44 | The following example code provides a universal RX/TX pin and UART ID setup. 45 | 46 | ```python 47 | tx_pin = 21 48 | rx_pin = 22 49 | uart_id = 1 50 | 51 | try: 52 | from machine import Pin 53 | import os 54 | from umodbus import version 55 | 56 | os_info = os.uname() 57 | print('MicroPython infos: {}'.format(os_info)) 58 | print('Used micropthon-modbus version: {}'.format(version.__version__)) 59 | 60 | if 'pyboard' in os_info: 61 | # NOT YET TESTED ! 62 | # https://docs.micropython.org/en/latest/library/pyb.UART.html#pyb-uart 63 | # (TX, RX) = (X9, X10) = (PB6, PB7) 64 | tx_pin = Pin(PB6) 65 | rx_pin = Pin(PB7) 66 | uart_id = 1 67 | elif 'esp8266' in os_info: 68 | # NOT YET TESTED ! 69 | # https://docs.micropython.org/en/latest/esp8266/quickref.html#uart-serial-bus 70 | raise Exception( 71 | 'UART0 of ESP8266 is used by REPL, UART1 can only be used for TX' 72 | ) 73 | elif 'esp32' in os_info: 74 | # https://docs.micropython.org/en/latest/esp32/quickref.html#uart-serial-bus 75 | tx_pin = 21 76 | rx_pin = 22 77 | uart_id = 1 78 | elif 'rp2' in os_info: 79 | # https://docs.micropython.org/en/latest/rp2/quickref.html#uart-serial-bus 80 | uart_id = 1 81 | tx_pin = Pin(4) 82 | rx_pin = Pin(5) 83 | except AttributeError: 84 | pass 85 | except Exception as e: 86 | raise e 87 | 88 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin, uart_id=uart_id) 89 | ``` 90 | 91 | ## Hardware example 92 | 93 | The [hardware example](hardware/main.py) shows the usage of the hardware 94 | functions `sleep`, `brightness` and `reset`. 95 | 96 | ## Upload example 97 | 98 | The [upload example](upload/main.py) shows how to update a Nextion display 99 | with a new TFT file. 100 | 101 | Copy the [example TFT file](everything.tft) to the MicroPython board with 102 | e.g. `rshell` 103 | 104 | ```bash 105 | rshell --port /dev/tty.SLAB_USBtoUART --editor nano 106 | ``` 107 | 108 | Copy the file to the device, this might take several minutes! 109 | 110 | ```bash 111 | cp everything.tft /pyboard 112 | ``` 113 | -------------------------------------------------------------------------------- /examples/basic/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to manipulate all elements of page 0 with basic command calls 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexHardware 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # ============================================================================ 29 | # ============================== Text examples =============================== 30 | # modify text field "t0" showing "newtxt" by default 31 | print('Set text field "t0" to "asdf"') 32 | cmd = 't0.txt="asdf"' 33 | nh.sendCommand(cmd) 34 | print() 35 | 36 | time.sleep(1) 37 | 38 | # ============================================================================ 39 | # ============================= Number examples ============================== 40 | # modify number field "n0" showing "0" by default 41 | print('Set number field "n0" to "93"') 42 | cmd = 'n0.val=93' 43 | nh.sendCommand(cmd) 44 | print() 45 | 46 | time.sleep(1) 47 | 48 | # modify float field "x0" showing "0.0" by default 49 | print('Set float field "x0" to "20.1"') 50 | cmd = 'x0.val=201' # last digit is value after "." 51 | nh.sendCommand(cmd) 52 | print() 53 | 54 | time.sleep(1) 55 | 56 | # ============================================================================ 57 | # ============================= Button examples ============================== 58 | # modify button "b0" showing "newtxt" by default 59 | print('Set button "b0" to "btn txt"') 60 | cmd = 'b0.txt="btn txt"' 61 | nh.sendCommand(cmd) 62 | print() 63 | 64 | time.sleep(1) 65 | 66 | # modify dual state button "bt0" showing "newtxt" by default 67 | print('Set dual state button "bt0" to "dsb txt"') 68 | cmd = 'bt0.txt="dsb txt"' 69 | nh.sendCommand(cmd) 70 | print() 71 | 72 | time.sleep(1) 73 | 74 | # ============================================================================ 75 | # =========================== Progressbar examples =========================== 76 | # modify progressbar "j0" showing "50%" by default 77 | print('Set progressbar "j0" to "20"') 78 | cmd = 'j0.val=20' 79 | nh.sendCommand(cmd) 80 | print() 81 | 82 | time.sleep(1) 83 | 84 | # ============================================================================ 85 | # ============================= Slider examples ============================== 86 | # modify slider "h0" showed in center position by default 87 | print('Set slider "h0" to "80"') 88 | cmd = 'h0.val=80' 89 | nh.sendCommand(cmd) 90 | print() 91 | 92 | time.sleep(1) 93 | 94 | # ============================================================================ 95 | # ============================ Checkbox examples ============================= 96 | # modify checkbox "c0" being checked by default 97 | print('Set checkbox "c0" to "unchecked"') 98 | cmd = 'c0.val=0' 99 | nh.sendCommand(cmd) 100 | print() 101 | 102 | time.sleep(1) 103 | 104 | # ============================================================================ 105 | # ============================== Radio examples ============================== 106 | # modify radio button "r0" being enabled by default 107 | print('Set radio butto "r0" to "disabled"') 108 | cmd = 'r0.val=0' 109 | nh.sendCommand(cmd) 110 | print() 111 | 112 | time.sleep(1) 113 | 114 | # ============================================================================ 115 | # ============================== Gauge examples ============================== 116 | # modify gauge "z0" pointing to the left by default 117 | print('Set gauge "z0" to "135" (degree)') 118 | cmd = 'z0.val=135' 119 | nh.sendCommand(cmd) 120 | print() 121 | 122 | time.sleep(1) 123 | 124 | # ============================================================================ 125 | # ============================ Waveform examples ============================= 126 | # add several datapoints to waveform "s0" 127 | print('Add several datapoints to waveform "s0"') 128 | for x in range(0, 50): 129 | cmd = 'add 14,0,{}'.format(x) 130 | nh.sendCommand(cmd) 131 | time.sleep(0.1) 132 | 133 | # ============================================================================ 134 | # ============================= End of example =============================== 135 | print('Returning to REPL in 5 seconds') 136 | 137 | # wait for 5 more seconds to safely finish the may still running threads 138 | time.sleep(5) 139 | -------------------------------------------------------------------------------- /examples/boot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Boot script 6 | 7 | Do initial stuff here, similar to the setup() function on Arduino 8 | """ 9 | 10 | # This file is executed on every boot (including wake-boot from deepsleep) 11 | # import esp 12 | # esp.osdebug(None) 13 | # import webrepl 14 | # webrepl.start() 15 | 16 | print('System booted successfully!') 17 | -------------------------------------------------------------------------------- /examples/boot_wifi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Boot script 6 | 7 | Do initial stuff here, similar to the setup() function on Arduino 8 | 9 | Connect to network, create an AccessPoint if connection failed otherwise 10 | """ 11 | 12 | # system packages 13 | import gc 14 | import machine 15 | import network 16 | import time 17 | 18 | # set clock speed to 240MHz instead of default 160MHz 19 | # import machine 20 | # machine.freq(240000000) 21 | 22 | station = network.WLAN(network.STA_IF) 23 | if station.active() and station.isconnected(): 24 | station.disconnect() 25 | time.sleep(1) 26 | station.active(False) 27 | time.sleep(1) 28 | station.active(True) 29 | 30 | station.connect('SSID', 'PASSWORD') 31 | time.sleep(1) 32 | 33 | connection_timeout = 10 * 1000 # WiFi connection timeout in milliseconds 34 | start_ms = time.ticks_ms() 35 | while (time.ticks_diff(time.ticks_ms(), start_ms) <= connection_timeout): 36 | print('Waiting for WiFi connection...') 37 | if station.isconnected(): 38 | print('Connected to WiFi') 39 | print(station.ifconfig()) 40 | break 41 | time.sleep(1) 42 | 43 | result = station.isconnected() 44 | # force an accesspoint creation 45 | # result = False 46 | 47 | if result is False: 48 | # disconnect as/from station and disable WiFi for it 49 | station.disconnect() 50 | station.active(False) 51 | time.sleep(1) 52 | 53 | # create a true AccessPoint without any active Station mode 54 | accesspoint = network.WLAN(network.AP_IF) 55 | 56 | # activate accesspoint if not yet enabled 57 | if not accesspoint.active(): 58 | accesspoint.active(True) 59 | 60 | accesspoint_name = "MicroPython AP" 61 | accesspoint.config(essid=accesspoint_name, 62 | authmode=network.AUTH_OPEN, 63 | password='', 64 | channel=11) 65 | 66 | print('Created Accesspoint: {}'.format(accesspoint_name)) 67 | 68 | print('Restart cause: {}'.format(machine.reset_cause())) 69 | 70 | # run garbage collector at the end to clean up 71 | gc.collect() 72 | 73 | print('System booted successfully!') 74 | -------------------------------------------------------------------------------- /examples/button/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a button element 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexButton, NexHardware 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # create a button instance 29 | b0 = NexButton(nh, 0, 1, "b0") 30 | 31 | # ============================================================================ 32 | # ============================== Example values ============================== 33 | # new values of button 34 | button_text = "btn txt" 35 | background_color_value = 63488 # red 36 | font_color_value = 31 # blue 37 | pressed_background_color_value = 64480 # orange 38 | pressed_font_color_value = 2047 # cyan 39 | x_offset = 20 40 | y_offset = 20 41 | 42 | # ============================================================================ 43 | # ============================== Text functions ============================== 44 | # request the text of button "b0" 45 | print('Requesting button "{}" text ...'.format(b0.name)) 46 | response = b0.getText() 47 | print('Button "{}" text is: "{}"'.format(b0.name, response)) 48 | print() 49 | 50 | time.sleep(1) 51 | 52 | # modify button "b0" showing "newtxt" by default 53 | print('Set button "{}" to "{}"'.format(b0.name, button_text)) 54 | b0.setText(button_text) 55 | print() 56 | 57 | time.sleep(1) 58 | 59 | # request the text of button "b0" again 60 | print('Requesting button "{}" text ...'.format(b0.name)) 61 | response = b0.getText() 62 | print('Button "{}" text is: "{}"'.format(b0.name, response)) 63 | print() 64 | 65 | # sanity check 66 | if response != button_text: 67 | print('WARNING: GET value did not match SET value') 68 | 69 | time.sleep(1) 70 | 71 | # ============================================================================ 72 | # =========================== Background functions =========================== 73 | # request the background color of button "b0" 74 | print('Requesting background color of button "{}" ...'.format(b0.name)) 75 | response = b0.Get_background_color_bco() 76 | print('Background color of button "{}" is: "{}"'.format(b0.name, response)) 77 | print() 78 | 79 | time.sleep(1) 80 | 81 | # modify the background color of button "b0" to "red" 82 | # search for RGB565 Colors. Red is "63488" at 65k colors 83 | print('Set background color of button "{}" to "{}"'. 84 | format(b0.name, background_color_value)) 85 | b0.Set_background_color_bco(background_color_value) 86 | print() 87 | 88 | time.sleep(1) 89 | 90 | # request the background color of button "b0" again 91 | print('Requesting background color of button "{}" ...'.format(b0.name)) 92 | response = b0.Get_background_color_bco() 93 | print('Background color of button "{}" is: "{}"'.format(b0.name, response)) 94 | print() 95 | 96 | # sanity check 97 | if response != background_color_value: 98 | print('WARNING: GET value did not match SET value') 99 | 100 | time.sleep(1) 101 | 102 | # ============================================================================ 103 | # ============================== Font functions ============================== 104 | # request the font color of button "b0" 105 | print('Requesting font color of button "{}" ...'.format(b0.name)) 106 | response = b0.Get_font_color_pco() 107 | print('Font color of button "{}" is: "{}"'.format(b0.name, response)) 108 | print() 109 | 110 | time.sleep(1) 111 | 112 | # modify the font color of button "b0" to "blue" 113 | # search for RGB565 Colors. Blue is "31" at 65k colors 114 | print('Set font color of button "{}" to "{}"'. 115 | format(b0.name, font_color_value)) 116 | b0.Set_font_color_pco(font_color_value) 117 | print() 118 | 119 | time.sleep(1) 120 | 121 | # request the font color of button "b0" again 122 | print('Requesting font color of button "{}" ...'.format(b0.name)) 123 | response = b0.Get_font_color_pco() 124 | print('Font color of button "{}" is: "{}"'.format(b0.name, response)) 125 | print() 126 | 127 | # sanity check 128 | if response != font_color_value: 129 | print('WARNING: GET value did not match SET value') 130 | 131 | time.sleep(1) 132 | 133 | # ============================================================================ 134 | # ============================ Position functions ============================ 135 | # request the x/y position of button "b0" again 136 | print('Requesting x/y position of button "{}" ...'.format(b0.name)) 137 | x_position = b0.Get_place_xcen() 138 | y_position = b0.Get_place_ycen() 139 | print('Position of button "{}" is: "x={}", "y={}"'. 140 | format(b0.name, x_position, y_position)) 141 | print() 142 | 143 | x_position += x_offset 144 | y_position += y_offset 145 | 146 | # modify the x/y position of button "b0" 147 | print('Set x/y position of button "{}" to "x={}", "y={}"'. 148 | format(b0.name, x_position, y_position)) 149 | b0.Set_place_xcen(x_position) 150 | b0.Set_place_ycen(y_position) 151 | print() 152 | 153 | time.sleep(1) 154 | 155 | # ============================================================================ 156 | # ============================ Special functions ============================= 157 | # request the pressed font color of button "b0" 158 | print('Requesting pressed font color of button "{}" ...'.format(b0.name)) 159 | response = b0.Get_press_font_color_pco2() 160 | print('Pressed font color of button "{}" is: "{}"'.format(b0.name, response)) 161 | print() 162 | 163 | time.sleep(1) 164 | 165 | # modify the pressed font color of button "b0" to "cyan" 166 | # search for RGB565 Colors. Cyan is "2047" at 65k colors 167 | print('Set font color of button "{}" to "{}"'. 168 | format(b0.name, pressed_font_color_value)) 169 | b0.Set_press_font_color_pco2(pressed_font_color_value) 170 | print() 171 | 172 | time.sleep(1) 173 | 174 | # request the pressed font color of button "b0" again 175 | print('Requesting pressed font color of button "{}" ...'.format(b0.name)) 176 | response = b0.Get_press_font_color_pco2() 177 | print('Pressed font color of button "{}" is: "{}"'.format(b0.name, response)) 178 | print() 179 | 180 | # sanity check 181 | if response != pressed_font_color_value: 182 | print('WARNING: GET value did not match SET value') 183 | 184 | time.sleep(1) 185 | 186 | # request the pressed background color of button "b0" 187 | print('Requesting pressed background color of button "{}" ...'.format(b0.name)) 188 | response = b0.Get_press_background_color_bco2() 189 | print('Pressed background color of button "{}" is: "{}"'. 190 | format(b0.name, response)) 191 | print() 192 | 193 | time.sleep(1) 194 | 195 | # modify the pressed background color of button "b0" to "orange" 196 | # search for RGB565 Colors. Red is "64480" at 65k colors 197 | print('Set pressed background color of button "{}" to "{}"'. 198 | format(b0.name, pressed_background_color_value)) 199 | b0.Set_press_background_color_bco2(pressed_background_color_value) 200 | print() 201 | 202 | time.sleep(1) 203 | 204 | # request the pressed background color of button "b0" again 205 | print('Requesting pressed background color of button "{}" ...'.format(b0.name)) 206 | response = b0.Get_press_background_color_bco2() 207 | print('Pressed background color of button "{}" is: "{}"'. 208 | format(b0.name, response)) 209 | print() 210 | 211 | # sanity check 212 | if response != pressed_background_color_value: 213 | print('WARNING: GET value did not match SET value') 214 | 215 | # ============================================================================ 216 | # ============================= End of example =============================== 217 | print('Returning to REPL in 5 seconds') 218 | 219 | # wait for 5 more seconds to safely finish the may still running threads 220 | time.sleep(5) 221 | -------------------------------------------------------------------------------- /examples/checkbox/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a checkbox element 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexCheckbox, NexHardware 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # create a checkbox instance 29 | c0 = NexCheckbox(nh, 0, 1, "c0") 30 | 31 | # ============================================================================ 32 | # ============================== Example values ============================== 33 | # new values of checkbox 34 | checkbox_value = 0 35 | background_color_value = 63488 # red 36 | font_color_value = 31 # blue 37 | 38 | # ============================================================================ 39 | # ============================== Value functions ============================= 40 | # request the value of checkbox "c0" 41 | print('Requesting checkbox "{}" value ...'.format(c0.name)) 42 | response = c0.getValue() 43 | print('Checkbox "{}" value is: "{}"'.format(c0.name, response)) 44 | print() 45 | 46 | time.sleep(1) 47 | 48 | # modify checkbox "c0" being checked by default 49 | print('Set checkbox "{}" to "{}"'.format(c0.name, checkbox_value)) 50 | c0.setValue(checkbox_value) 51 | print() 52 | 53 | time.sleep(1) 54 | 55 | # request the value of checkbox "c0" again 56 | print('Requesting checkbox "{}" value ...'.format(c0.name)) 57 | response = c0.getValue() 58 | print('Checkbox "{}" value is: "{}"'.format(c0.name, response)) 59 | print() 60 | 61 | # sanity check 62 | if response != checkbox_value: 63 | print('WARNING: GET value did not match SET value') 64 | 65 | time.sleep(1) 66 | 67 | # ============================================================================ 68 | # =========================== Background functions =========================== 69 | # request the background color of checkbox "c0" 70 | print('Requesting background color of checkbox "{}" ...'.format(c0.name)) 71 | response = c0.Get_background_color_bco() 72 | print('Background color of checkbox "{}" is: "{}"'.format(c0.name, response)) 73 | print() 74 | 75 | time.sleep(1) 76 | 77 | # modify the background color of checkbox "c0" to "red" 78 | # search for RGB565 Colors. Red is "63488" at 65k colors 79 | print('Set background color of checkbox "{}" to "{}"'. 80 | format(c0.name, background_color_value)) 81 | c0.Set_background_color_bco(background_color_value) 82 | print() 83 | 84 | time.sleep(1) 85 | 86 | # request the background color of checkbox "c0" again 87 | print('Requesting background color of checkbox "{}" ...'.format(c0.name)) 88 | response = c0.Get_background_color_bco() 89 | print('Background color of checkbox "{}" is: "{}"'.format(c0.name, response)) 90 | print() 91 | 92 | # sanity check 93 | if response != background_color_value: 94 | print('WARNING: GET value did not match SET value') 95 | 96 | time.sleep(1) 97 | 98 | # ============================================================================ 99 | # ============================== Font functions ============================== 100 | # request the font color of checkbox "c0" 101 | print('Requesting font color of checkbox "{}" ...'.format(c0.name)) 102 | response = c0.Get_font_color_pco() 103 | print('Font color of checkbox "{}" is: "{}"'.format(c0.name, response)) 104 | print() 105 | 106 | time.sleep(1) 107 | 108 | # enable checkbox "c0" again to make change in font color visible 109 | c0.setValue(1) 110 | 111 | # modify the font color of checkbox "c0" to "blue" 112 | # search for RGB565 Colors. Blue is "31" at 65k colors 113 | print('Set font color of checkbox "{}" to "{}"'. 114 | format(c0.name, font_color_value)) 115 | c0.Set_font_color_pco(font_color_value) 116 | print() 117 | 118 | time.sleep(1) 119 | 120 | # request the font color of checkbox "c0" again 121 | print('Requesting font color of checkbox "{}" ...'.format(c0.name)) 122 | response = c0.Get_font_color_pco() 123 | print('Font color of checkbox "{}" is: "{}"'.format(c0.name, response)) 124 | print() 125 | 126 | # sanity check 127 | if response != font_color_value: 128 | print('WARNING: GET value did not match SET value') 129 | 130 | # ============================================================================ 131 | # ============================= End of example =============================== 132 | print('Returning to REPL in 5 seconds') 133 | 134 | # wait for 5 more seconds to safely finish the may still running threads 135 | time.sleep(5) 136 | -------------------------------------------------------------------------------- /examples/dual_button/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a dual state button element 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexDSButton, NexHardware 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # create a dual state button instance 29 | bt0 = NexDSButton(nh, 0, 1, "bt0") 30 | 31 | # ============================================================================ 32 | # ============================== Example values ============================== 33 | # new values for dual state button 34 | button_text = "btn txt" 35 | button_value = 1 # 1 is active (green), 0 is inactive (grey) 36 | background_color_value = 63488 # red 37 | font_color_value = 31 # blue 38 | pressed_background_color_value = 64480 # orange 39 | x_offset = 20 40 | y_offset = 20 41 | 42 | # ============================================================================ 43 | # =========================== Text+Value functions =========================== 44 | # request the text of dual state button "bt0" 45 | print('Requesting dual state button "{}" text ...'.format(bt0.name)) 46 | response_text = bt0.getText() 47 | print('Dual state button "{}" text is: "{}"'.format(bt0.name, response_text)) 48 | print() 49 | 50 | # request the value of dual state button "bt0" 51 | print('Requesting dual state button "{}" value ...'.format(bt0.name)) 52 | response_value = bt0.getValue() 53 | print('Dual state button "{}" value is: "{}"'.format(bt0.name, response_value)) 54 | print() 55 | 56 | time.sleep(1) 57 | 58 | # modify dual state button "bt0" showing "newtxt" by default 59 | print('Set dual state button "{}" text to "{}"'.format(bt0.name, button_text)) 60 | bt0.setText(button_text) 61 | print() 62 | 63 | # modify dual state button "bt0" being released by default 64 | print('Set dual state button "{}" state to "{}"'. 65 | format(bt0.name, button_value)) 66 | bt0.setValue(button_value) 67 | print() 68 | 69 | time.sleep(1) 70 | 71 | # request the text of dual state button "bt0" again 72 | print('Requesting dual state button "{}" text ...'.format(bt0.name)) 73 | response_text = bt0.getText() 74 | print('Dual state button "{}" text is: "{}"'.format(bt0.name, response_text)) 75 | print() 76 | 77 | # request the value of dual state button "bt0" again 78 | print('Requesting dual state button "{}" value ...'.format(bt0.name)) 79 | response_value = bt0.getValue() 80 | print('Dual state button "{}" value is: "{}"'.format(bt0.name, response_value)) 81 | print() 82 | 83 | # sanity check 84 | if response_text != button_text: 85 | print('WARNING: GET text value did not match SET text value') 86 | if response_value != button_value: 87 | print('WARNING: GET state value did not match SET state value') 88 | 89 | time.sleep(1) 90 | 91 | # ============================================================================ 92 | # =========================== Background functions =========================== 93 | # request the background color of dual state button "bt0" 94 | print('Requesting background color of dual state button "{}" ...'. 95 | format(bt0.name)) 96 | response = bt0.Get_state0_color_bco0() 97 | print('Background color of dual state button "{}" is: "{}"'. 98 | format(bt0.name, response)) 99 | print() 100 | 101 | time.sleep(1) 102 | 103 | # modify the background color of dual state button "bt0" to "red" 104 | # search for RGB565 Colors. Red is "63488" at 65k colors 105 | print('Set background color of dual state button "{}" to "{}"'. 106 | format(bt0.name, background_color_value)) 107 | bt0.Set_state0_color_bco0(background_color_value) 108 | print() 109 | 110 | time.sleep(1) 111 | 112 | # request the background color of dual state button "bt0" again 113 | print('Requesting background color of dual state button "{}" ...'. 114 | format(bt0.name)) 115 | response = bt0.Get_state0_color_bco0() 116 | print('Background color of dual state button "{}" is: "{}"'. 117 | format(bt0.name, response)) 118 | print() 119 | 120 | # sanity check 121 | if response != background_color_value: 122 | print('WARNING: GET value did not match SET value') 123 | 124 | time.sleep(1) 125 | 126 | # ============================================================================ 127 | # ============================== Font functions ============================== 128 | # request the font color of dual state button "bt0" 129 | print('Requesting font color of dual state button "{}" ...'.format(bt0.name)) 130 | response = bt0.Get_font_color_pco() 131 | print('Font color of dual state button "{}" is: "{}"'. 132 | format(bt0.name, response)) 133 | print() 134 | 135 | time.sleep(1) 136 | 137 | # modify the font color of dual state button "bt0" to "blue" 138 | # search for RGB565 Colors. Blue is "31" at 65k colors 139 | print('Set font color of dual state button "{}" to "{}"'. 140 | format(bt0.name, font_color_value)) 141 | bt0.Set_font_color_pco(font_color_value) 142 | print() 143 | 144 | time.sleep(1) 145 | 146 | # request the font color of dual state button "bt0" again 147 | print('Requesting font color of dual state button "{}" ...'.format(bt0.name)) 148 | response = bt0.Get_font_color_pco() 149 | print('Font color of dual state button "{}" is: "{}"'. 150 | format(bt0.name, response)) 151 | print() 152 | 153 | # sanity check 154 | if response != font_color_value: 155 | print('WARNING: GET value did not match SET value') 156 | 157 | time.sleep(1) 158 | 159 | # ============================================================================ 160 | # ============================ Position functions ============================ 161 | # request the x/y position of dual state button "bt0" again 162 | print('Requesting x/y position of dual state button "{}" ...'.format(bt0.name)) 163 | x_position = bt0.Get_place_xcen() 164 | y_position = bt0.Get_place_ycen() 165 | print('Position of dual state button "{}" is: "x={}", "y={}"'. 166 | format(bt0.name, x_position, y_position)) 167 | print() 168 | 169 | x_position += x_offset 170 | y_position += y_offset 171 | 172 | # modify the x/y position of dual state button "bt0" 173 | print('Set x/y position of dual state button "{}" to "x={}", "y={}"'. 174 | format(bt0.name, x_position, y_position)) 175 | bt0.Set_place_xcen(x_position) 176 | bt0.Set_place_ycen(y_position) 177 | print() 178 | 179 | time.sleep(1) 180 | 181 | # ============================================================================ 182 | # ============================ Special functions ============================= 183 | # request the pressed background color of dual state button "bt0" 184 | print('Requesting pressed background color of dual state button "{}" ...'. 185 | format(bt0.name)) 186 | response = bt0.Get_state1_color_bco1() 187 | print('Pressed background color of dual state button "{}" is: "{}"'. 188 | format(bt0.name, response)) 189 | print() 190 | 191 | time.sleep(1) 192 | 193 | # modify the pressed background color of dual state button "bt0" to "red" 194 | # search for RGB565 Colors. Red is "63488" at 65k colors 195 | print('Set pressed background color of dual state button "{}" to "{}"'. 196 | format(bt0.name, pressed_background_color_value)) 197 | bt0.Set_state1_color_bco1(pressed_background_color_value) 198 | print() 199 | 200 | time.sleep(1) 201 | 202 | # request the pressed background color of dual state button "bt0" again 203 | print('Requesting pressed background color of dual state button "{}" ...'. 204 | format(bt0.name)) 205 | response = bt0.Get_state0_color_bco0() 206 | print('Pressed background color of dual state button "{}" is: "{}"'. 207 | format(bt0.name, response)) 208 | print() 209 | 210 | # sanity check 211 | if response != pressed_background_color_value: 212 | print('WARNING: GET value did not match SET value') 213 | 214 | # ============================================================================ 215 | # ============================= End of example =============================== 216 | print('Returning to REPL in 5 seconds') 217 | 218 | # wait for 5 more seconds to safely finish the may still running threads 219 | time.sleep(5) 220 | -------------------------------------------------------------------------------- /examples/everything.HMI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brainelectronics/micropython-nextion/e8c72ede7a193257a8f53104bb01d33a819e3b43/examples/everything.HMI -------------------------------------------------------------------------------- /examples/everything.tft: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brainelectronics/micropython-nextion/e8c72ede7a193257a8f53104bb01d33a819e3b43/examples/everything.tft -------------------------------------------------------------------------------- /examples/gauge/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a gauge element 10 | """ 11 | 12 | # system packages 13 | from random import randint 14 | import time 15 | 16 | # custom packages 17 | from nextion import NexGauge, NexHardware 18 | 19 | # define communication pins for Nextion display 20 | tx_pin = 21 21 | rx_pin = 22 22 | 23 | # create Nextion hardware interface 24 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 25 | 26 | # init nextion communication interface 27 | nh.nexInit() 28 | 29 | # create a gauge instance 30 | z0 = NexGauge(nh, 0, 1, "z0") 31 | 32 | # ============================================================================ 33 | # ============================== Example values ============================== 34 | # new values of gauge 35 | gauge_value = randint(10, 350) 36 | background_color_value = 63488 # red 37 | font_color_value = 31 # blue 38 | pointer_thickness = 5 39 | 40 | # ============================================================================ 41 | # ============================== Value functions ============================= 42 | # request the value of gauge "z0" 43 | print('Requesting gauge "{}" value ...'.format(z0.name)) 44 | response = z0.getValue() 45 | print('Gauge "{}" value is: "{}"'.format(z0.name, response)) 46 | print() 47 | 48 | time.sleep(1) 49 | 50 | # modify gauge "z0" being checked by default 51 | print('Set gauge "{}" to "{}"'.format(z0.name, gauge_value)) 52 | z0.setValue(gauge_value) 53 | print() 54 | 55 | time.sleep(1) 56 | 57 | # request the value of gauge "z0" again 58 | print('Requesting gauge "{}" value ...'.format(z0.name)) 59 | response = z0.getValue() 60 | print('Gauge "{}" value is: "{}"'.format(z0.name, response)) 61 | print() 62 | 63 | # sanity check 64 | if response != gauge_value: 65 | print('WARNING: GET value did not match SET value') 66 | 67 | # ============================================================================ 68 | # =========================== Background functions =========================== 69 | # request the background color of gauge "z0" 70 | print('Requesting background color of gauge "{}" ...'.format(z0.name)) 71 | response = z0.Get_background_color_bco() 72 | print('Background color of gauge "{}" is: "{}"'.format(z0.name, response)) 73 | print() 74 | 75 | time.sleep(1) 76 | 77 | # modify the background color of gauge "z0" to "red" 78 | # search for RGB565 Colors. Red is "63488" at 65k colors 79 | print('Set background color of gauge "{}" to "{}"'. 80 | format(z0.name, background_color_value)) 81 | z0.Set_background_color_bco(background_color_value) 82 | print() 83 | 84 | time.sleep(1) 85 | 86 | # request the background color of gauge "z0" again 87 | print('Requesting background color of gauge "{}" ...'.format(z0.name)) 88 | response = z0.Get_background_color_bco() 89 | print('Background color of gauge "{}" is: "{}"'.format(z0.name, response)) 90 | print() 91 | 92 | # sanity check 93 | if response != background_color_value: 94 | print('WARNING: GET value did not match SET value') 95 | 96 | time.sleep(1) 97 | 98 | # ============================================================================ 99 | # ============================== Font functions ============================== 100 | # request the font color of gauge "z0" 101 | print('Requesting font color of gauge "{}" ...'.format(z0.name)) 102 | response = z0.Get_font_color_pco() 103 | print('Font color of gauge "{}" is: "{}"'.format(z0.name, response)) 104 | print() 105 | 106 | time.sleep(1) 107 | 108 | # modify the font color of gauge "z0" to "blue" 109 | # search for RGB565 Colors. Blue is "31" at 65k colors 110 | print('Set font color of gauge "{}" to "{}"'.format(z0.name, font_color_value)) 111 | z0.Set_font_color_pco(font_color_value) 112 | print() 113 | 114 | time.sleep(1) 115 | 116 | # request the font color of gauge "z0" again 117 | print('Requesting font color of gauge "{}" ...'.format(z0.name)) 118 | response = z0.Get_font_color_pco() 119 | print('Font color of gauge "{}" is: "{}"'.format(z0.name, response)) 120 | print() 121 | 122 | # sanity check 123 | if response != font_color_value: 124 | print('WARNING: GET value did not match SET value') 125 | 126 | time.sleep(1) 127 | 128 | # ============================================================================ 129 | # ============================ Pointer functions ============================= 130 | # request the pointer thickness of gauge "z0" 131 | print('Requesting pointer thickness of gauge "{}" ...'.format(z0.name)) 132 | response = z0.Get_pointer_thickness_wid() 133 | print('Pointer thickness of gauge "{}" is: "{}"'.format(z0.name, response)) 134 | print() 135 | 136 | time.sleep(1) 137 | 138 | # modify the pointer thickness of gauge "z0" 139 | print('Set pointer thickness of gauge "{}" to "{}"'. 140 | format(z0.name, pointer_thickness)) 141 | z0.Set_pointer_thickness_wid(pointer_thickness) 142 | print() 143 | 144 | time.sleep(1) 145 | 146 | # request the pointer thickness of gauge "z0" again 147 | print('Requesting pointer thickness of gauge "{}" ...'.format(z0.name)) 148 | response = z0.Get_pointer_thickness_wid() 149 | print('Pointer thickness of gauge "{}" is: "{}"'.format(z0.name, response)) 150 | print() 151 | 152 | # sanity check 153 | if response != pointer_thickness: 154 | print('WARNING: GET value did not match SET value') 155 | 156 | # ============================================================================ 157 | # ============================= End of example =============================== 158 | print('Returning to REPL in 5 seconds') 159 | 160 | # wait for 5 more seconds to safely finish the may still running threads 161 | time.sleep(5) 162 | -------------------------------------------------------------------------------- /examples/gpio/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with the Nextion display GPIO pins 10 | """ 11 | 12 | # system packages 13 | from random import randint 14 | import time 15 | 16 | # custom packages 17 | from nextion import NexGpio, NexHardware 18 | 19 | # define communication pins for Nextion display 20 | tx_pin = 21 21 | rx_pin = 22 22 | 23 | # create Nextion hardware interface 24 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 25 | 26 | # init nextion communication interface 27 | nh.nexInit() 28 | 29 | # create a button instance 30 | gpio = NexGpio(nh) 31 | 32 | # ============================================================================ 33 | # ============================== Example values ============================== 34 | # new values of GPIOs 35 | pwm_pin = 7 # only GPIO4 and GPIO7 support PWM 36 | pwm_frequency = 500 # Hz, all PWM pins have same frequency 37 | pwm_value = randint(0, 100) # 0 is LOW (off), 100 is HIGH (on) 38 | 39 | # ============================================================================ 40 | # ============================= Pinmode functions ============================ 41 | # set all GPIOs as outputs 42 | print('Set all pins as digital output') 43 | for pin in range(0, 8): 44 | # outputs are HIGH by default 45 | gpio.pin_mode(pin, NexGpio.OUTPUT) 46 | print() 47 | 48 | time.sleep(1) 49 | 50 | # ============================================================================ 51 | # =========================== Digital IO functions =========================== 52 | # toggle all pins 5 times LOW/HIGH 53 | print('Toggle all pins 5 times LOW/HIGH with 0.5 sec delay between a change') 54 | for _ in range(0, 5): 55 | for pin in range(0, 8): 56 | # set pin LOW 57 | gpio.digital_write(pin, 0) 58 | time.sleep(0.5) 59 | # set pin HIGH 60 | gpio.digital_write(pin, 1) 61 | time.sleep(0.5) 62 | print() 63 | 64 | time.sleep(1) 65 | 66 | # set all GPIOs as inputs 67 | print('Set all pins as digital input') 68 | for pin in range(0, 8): 69 | gpio.pin_mode(pin, NexGpio.INPUT_PULL_UP) 70 | print() 71 | 72 | print('Read all pins state') 73 | for pin in range(0, 8): 74 | state = gpio.digital_read(pin) 75 | print('Pin "{}" value is: "{}"'.format(pin, state)) 76 | print() 77 | 78 | time.sleep(1) 79 | 80 | # ============================================================================ 81 | # =============================== PWM functions ============================== 82 | # only GPIO4 and GPIO7 support PWM 83 | print('Set GPIO7 pin as PWM output (Buzzer of Expansion Board)') 84 | gpio.pin_mode(pwm_pin, NexGpio.PWM) 85 | 86 | # request the PWM frequency 87 | print('Requesting PWM frequency ...') 88 | response = gpio.get_pwmfreq() 89 | print('PWM frequency is: "{}"'.format(response)) 90 | print() 91 | 92 | time.sleep(1) 93 | 94 | # modify PWM frequency to 500 Hz 95 | print('Set PWM frequency to "{}"'.format(pwm_frequency)) 96 | gpio.set_pwmfreq(pwm_frequency) 97 | print() 98 | 99 | time.sleep(1) 100 | 101 | # request the PWM frequency again 102 | print('Requesting PWM frequency ...') 103 | response = gpio.get_pwmfreq() 104 | print('PWM frequency is: "{}"'.format(response)) 105 | print() 106 | 107 | # sanity check 108 | if response != pwm_frequency: 109 | print('WARNING: GET value did not match SET value') 110 | 111 | time.sleep(1) 112 | 113 | # modify PWM value (0, 100)[%] 114 | print('Set PWM of "{}" to "{}"'.format(pwm_pin, pwm_value)) 115 | gpio.analog_write(pwm_pin, pwm_value) 116 | print() 117 | 118 | # ============================================================================ 119 | # ============================= End of example =============================== 120 | print('Returning to REPL in 5 seconds') 121 | 122 | # wait for 5 more seconds to safely finish the may still running threads 123 | time.sleep(5) 124 | -------------------------------------------------------------------------------- /examples/hardware/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with the display brightness, sleep mode and reset 10 | """ 11 | 12 | # system packages 13 | from random import randint 14 | import time 15 | 16 | # custom packages 17 | from nextion import NexCheckbox, NexButton, NexHardware, NexNumber 18 | 19 | # define communication pins for Nextion display 20 | tx_pin = 21 21 | rx_pin = 22 22 | 23 | # create Nextion hardware interface 24 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 25 | 26 | # init nextion communication interface 27 | nh.nexInit() 28 | 29 | # ============================================================================ 30 | # ============================ Brightness function =========================== 31 | # decrease display brightness to 50% 32 | display_brightness = 50 33 | print('Decreasing display brightness to {}%...'.format(display_brightness)) 34 | nh.brightness(display_brightness) 35 | print() 36 | 37 | time.sleep(1) 38 | 39 | # ============================================================================ 40 | # ============================== Sleep function ============================== 41 | # activate sleep mode of display 42 | print('Activating display sleep mode for 5 seconds') 43 | nh.sleep(True) 44 | time.sleep(5) 45 | print('Wakeup display again') 46 | nh.sleep(False) 47 | 48 | time.sleep(1) 49 | 50 | # ============================================================================ 51 | # ============================ Hide/show function ============================ 52 | # manipulate display content to demonstrate display reset afterwards 53 | print('Manipulating display content a little bit ...') 54 | b0 = NexButton(nh, 0, 1, "b0") 55 | b0.setText("something") 56 | n0 = NexNumber(nh, 0, 1, "n0") 57 | n0.setValue(randint(1, 100)) 58 | c0 = NexCheckbox(nh, 0, 1, "c0") 59 | c0.setValue(0) 60 | print('Reset display to default in 5 seconds') 61 | time.sleep(5) 62 | nh.reset() 63 | print('Fully brightness restored, all elements show the default value') 64 | print() 65 | 66 | time.sleep(1) 67 | 68 | # hide button "b0" on screen 69 | print('Hiding button "{}" ...'.format(b0.name)) 70 | b0.hide() 71 | print() 72 | 73 | time.sleep(5) 74 | 75 | # show button "b0" again on screen 76 | print('Showing button "{}" again ...'.format(b0.name)) 77 | b0.show() 78 | print() 79 | 80 | # ============================================================================ 81 | # ============================= End of example =============================== 82 | print('Returning to REPL in 5 seconds') 83 | 84 | # wait for 5 more seconds to safely finish the may still running threads 85 | time.sleep(5) 86 | -------------------------------------------------------------------------------- /examples/number/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a number element 10 | """ 11 | 12 | # system packages 13 | from random import randint 14 | import time 15 | 16 | # custom packages 17 | from nextion import NexNumber, NexHardware 18 | 19 | # define communication pins for Nextion display 20 | tx_pin = 21 21 | rx_pin = 22 22 | 23 | # create Nextion hardware interface 24 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 25 | 26 | # init nextion communication interface 27 | nh.nexInit() 28 | 29 | # create a number instance 30 | n0 = NexNumber(nh, 0, 1, "n0") 31 | 32 | # ============================================================================ 33 | # ============================== Example values ============================== 34 | # new values of number field 35 | number_value = randint(1, 100) 36 | background_color_value = 63488 # red 37 | font_color_value = 31 # blue 38 | x_offset = 20 39 | y_offset = 20 40 | number_length = 2 41 | # numer = 300, length = 0 -> "300" 42 | # length = 1 -> "3" 43 | # length = 2 -> "30" 44 | # length = 3 -> "300" 45 | # length = 4 -> "0300" 46 | 47 | # ============================================================================ 48 | # ============================== Value functions ============================= 49 | # request the value of number "n0" 50 | print('Requesting number "{}" value ...'.format(n0.name)) 51 | response = n0.getValue() 52 | print('Number field "{}" value is: "{}"'.format(n0.name, response)) 53 | print() 54 | 55 | time.sleep(1) 56 | 57 | # modify number field "n0" showing "0" by default 58 | print('Set number field "{}" to "{}"'.format(n0.name, number_value)) 59 | n0.setValue(number_value) 60 | print() 61 | 62 | time.sleep(1) 63 | 64 | # request the value of number "n0" again 65 | print('Requesting number "{}" value ...'.format(n0.name)) 66 | response = n0.getValue() 67 | print('Number field "{}" value is: "{}"'.format(n0.name, response)) 68 | print() 69 | 70 | # sanity check 71 | if response != number_value: 72 | print('WARNING: GET value did not match SET value') 73 | 74 | time.sleep(1) 75 | 76 | # ============================================================================ 77 | # =========================== Background functions =========================== 78 | # request the background color of number "n0" 79 | print('Requesting background color of number "{}" ...'.format(n0.name)) 80 | response = n0.Get_background_color_bco() 81 | print('Background color of number "{}" is: "{}"'.format(n0.name, response)) 82 | print() 83 | 84 | time.sleep(1) 85 | 86 | # modify the background color of number "n0" to "red" 87 | # search for RGB565 Colors. Red is "63488" at 65k colors 88 | print('Set background color of number "{}" to "{}"'. 89 | format(n0.name, background_color_value)) 90 | n0.Set_background_color_bco(background_color_value) 91 | print() 92 | 93 | time.sleep(1) 94 | 95 | # request the background color of number "n0" again 96 | print('Requesting background color of number "{}" ...'.format(n0.name)) 97 | response = n0.Get_background_color_bco() 98 | print('Background color of number "{}" is: "{}"'.format(n0.name, response)) 99 | print() 100 | 101 | # sanity check 102 | if response != background_color_value: 103 | print('WARNING: GET value did not match SET value') 104 | 105 | time.sleep(1) 106 | 107 | # ============================================================================ 108 | # ============================== Font functions ============================== 109 | # request the font color of number "n0" 110 | print('Requesting font color of number "{}" ...'.format(n0.name)) 111 | response = n0.Get_font_color_pco() 112 | print('Font color of number "{}" is: "{}"'.format(n0.name, response)) 113 | print() 114 | 115 | time.sleep(1) 116 | 117 | # modify the font color of number "n0" to "blue" 118 | # search for RGB565 Colors. Blue is "31" at 65k colors 119 | print('Set font color of number "{}" to "{}"'. 120 | format(n0.name, font_color_value)) 121 | n0.Set_font_color_pco(font_color_value) 122 | print() 123 | 124 | time.sleep(1) 125 | 126 | # request the font color of number "n0" again 127 | print('Requesting font color of number "{}" ...'.format(n0.name)) 128 | response = n0.Get_font_color_pco() 129 | print('Font color of number "{}" is: "{}"'.format(n0.name, response)) 130 | print() 131 | 132 | # sanity check 133 | if response != font_color_value: 134 | print('WARNING: GET value did not match SET value') 135 | 136 | time.sleep(1) 137 | 138 | # ============================================================================ 139 | # ============================ Position functions ============================ 140 | # request the x/y position of number "n0" again 141 | print('Requesting x/y position of number "{}" ...'.format(n0.name)) 142 | x_position = n0.Get_place_xcen() 143 | y_position = n0.Get_place_ycen() 144 | print('Position of number "{}" is: "x={}", "y={}"'. 145 | format(n0.name, x_position, y_position)) 146 | print() 147 | 148 | x_position += x_offset 149 | y_position += y_offset 150 | 151 | # modify the x/y position of number "n0" 152 | print('Set x/y position of number "{}" to "x={}", "y={}"'. 153 | format(n0.name, x_position, y_position)) 154 | n0.Set_place_xcen(x_position) 155 | n0.Set_place_ycen(y_position) 156 | print() 157 | 158 | # ============================================================================ 159 | # ============================ Special functions ============================= 160 | # request the number length of number "n0" 161 | print('Requesting number length of number "{}" ...'.format(n0.name)) 162 | response = n0.Get_number_length() 163 | print('Number length of number "{}" is: "{}"'.format(n0.name, response)) 164 | print() 165 | 166 | time.sleep(1) 167 | 168 | # modify the number length of number "n0" 169 | print('Set number length of number "{}" to "{}"'. 170 | format(n0.name, number_length)) 171 | n0.Set_number_length(number_length) 172 | print() 173 | 174 | time.sleep(1) 175 | 176 | # request the number length of number "n0" again 177 | print('Requesting number length of number "{}" ...'.format(n0.name)) 178 | response = n0.Get_number_length() 179 | print('Number length of number "{}" is: "{}"'.format(n0.name, response)) 180 | print() 181 | 182 | # sanity check 183 | if response != number_length: 184 | print('WARNING: GET value did not match SET value') 185 | 186 | time.sleep(1) 187 | 188 | # ============================================================================ 189 | # ============================= End of example =============================== 190 | print('Returning to REPL in 5 seconds') 191 | 192 | # wait for 5 more seconds to safely finish the may still running threads 193 | time.sleep(5) 194 | -------------------------------------------------------------------------------- /examples/page/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a page element 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexPage, NexHardware 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # create page instances 29 | page0 = NexPage(nh, 0, 0, "page0") 30 | page1 = NexPage(nh, 1, 0, "page1") 31 | page2 = NexPage(nh, 2, 0, "page2") 32 | 33 | # ============================================================================ 34 | # ============================== Page functions ============================== 35 | # show the default page 0 36 | print('Showing page "{}" ...'.format(page0.name)) 37 | page0.show() 38 | print() 39 | 40 | time.sleep(1) 41 | 42 | # show the page 1 43 | print('Showing page "{}" ...'.format(page1.name)) 44 | page1.show() 45 | print() 46 | 47 | time.sleep(1) 48 | 49 | # show the page 2 50 | print('Showing page "{}" ...'.format(page2.name)) 51 | page2.show() 52 | print() 53 | 54 | time.sleep(1) 55 | 56 | # show the page 0 again 57 | print('Showing page "{}" ...'.format(page0.name)) 58 | page0.show() 59 | print() 60 | 61 | # ============================================================================ 62 | # ============================= End of example =============================== 63 | print('Returning to REPL in 5 seconds') 64 | 65 | # wait for 5 more seconds to safely finish the may still running threads 66 | time.sleep(5) 67 | -------------------------------------------------------------------------------- /examples/progressbar/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a progressbar element 10 | """ 11 | 12 | # system packages 13 | from random import choice, randint 14 | import time 15 | 16 | # custom packages 17 | from nextion import NexHardware, NexProgressBar 18 | 19 | # define communication pins for Nextion display 20 | tx_pin = 21 21 | rx_pin = 22 22 | 23 | # create Nextion hardware interface 24 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 25 | 26 | # init nextion communication interface 27 | nh.nexInit() 28 | 29 | # create a progressbar instance 30 | j0 = NexProgressBar(nh, 0, 1, "j0") 31 | 32 | # ============================================================================ 33 | # ============================== Example values ============================== 34 | # new values of progressbar 35 | # avoid something close to zero or close to 50 36 | progressbar_value = choice([randint(5, 40), randint(60, 100)]) 37 | background_color_value = 63488 # red 38 | font_color_value = 31 # blue 39 | 40 | # ============================================================================ 41 | # ============================== Value functions ============================= 42 | # request the value of progressbar "j0" being 50 by default 43 | print('Requesting progressbar "{}" value ...'.format(j0.name)) 44 | response = j0.getValue() 45 | print('Progressbar "{}" value is: "{}"'.format(j0.name, response)) 46 | print() 47 | 48 | time.sleep(1) 49 | 50 | # modify progressbar "j0" being checked by default 51 | print('Set progressbar "{}" to "{}"'.format(j0.name, progressbar_value)) 52 | j0.setValue(progressbar_value) 53 | print() 54 | 55 | time.sleep(1) 56 | 57 | # request the value of progressbar "j0" again 58 | print('Requesting progressbar "{}" value ...'.format(j0.name)) 59 | response = j0.getValue() 60 | print('Progressbar "{}" value is: "{}"'.format(j0.name, response)) 61 | print() 62 | 63 | # sanity check 64 | if response != progressbar_value: 65 | print('WARNING: GET value did not match SET value') 66 | 67 | time.sleep(1) 68 | 69 | # ============================================================================ 70 | # =========================== Background functions =========================== 71 | # request the background color of progressbar "j0" 72 | print('Requesting background color of progressbar "{}" ...'.format(j0.name)) 73 | response = j0.Get_background_color_bco() 74 | print('Background color of progressbar "{}" is: "{}"'. 75 | format(j0.name, response)) 76 | print() 77 | 78 | time.sleep(1) 79 | 80 | # modify the background color of progressbar "j0" to "red" 81 | # search for RGB565 Colors. Red is "63488" at 65k colors 82 | print('Set background color of progressbar "{}" to "{}"'. 83 | format(j0.name, background_color_value)) 84 | j0.Set_background_color_bco(background_color_value) 85 | print() 86 | 87 | time.sleep(1) 88 | 89 | # request the background color of progressbar "j0" again 90 | print('Requesting background color of progressbar "{}" ...'.format(j0.name)) 91 | response = j0.Get_background_color_bco() 92 | print('Background color of progressbar "{}" is: "{}"'. 93 | format(j0.name, response)) 94 | print() 95 | 96 | # sanity check 97 | if response != background_color_value: 98 | print('WARNING: GET value did not match SET value') 99 | 100 | time.sleep(1) 101 | 102 | # ============================================================================ 103 | # ============================== Font functions ============================== 104 | # request the font color of progressbar "j0" 105 | print('Requesting font color of progressbar "{}" ...'.format(j0.name)) 106 | response = j0.Get_font_color_pco() 107 | print('Font color of progressbar "{}" is: "{}"'.format(j0.name, response)) 108 | print() 109 | 110 | time.sleep(1) 111 | 112 | # modify the font color of progressbar "j0" to "blue" 113 | # search for RGB565 Colors. Blue is "31" at 65k colors 114 | print('Set font color of progressbar "{}" to "{}"'. 115 | format(j0.name, font_color_value)) 116 | j0.Set_font_color_pco(font_color_value) 117 | print() 118 | 119 | time.sleep(1) 120 | 121 | # request the font color of progressbar "j0" again 122 | print('Requesting font color of progressbar "{}" ...'.format(j0.name)) 123 | response = j0.Get_font_color_pco() 124 | print('Font color of progressbar "{}" is: "{}"'.format(j0.name, response)) 125 | print() 126 | 127 | # sanity check 128 | if response != font_color_value: 129 | print('WARNING: GET value did not match SET value') 130 | 131 | # ============================================================================ 132 | # ============================= End of example =============================== 133 | print('Returning to REPL in 5 seconds') 134 | 135 | # wait for 5 more seconds to safely finish the may still running threads 136 | time.sleep(5) 137 | -------------------------------------------------------------------------------- /examples/radio/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a radio element 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexRadio, NexHardware 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # create a radio instance 29 | r0 = NexRadio(nh, 0, 1, "r0") 30 | 31 | # ============================================================================ 32 | # ============================== Example values ============================== 33 | # new values of radio 34 | radio_state = 0 35 | background_color_value = 63488 # red 36 | font_color_value = 31 # blue 37 | 38 | # ============================================================================ 39 | # ============================== Value functions ============================= 40 | # request the state of radio "r0" 41 | print('Requesting radio "{}" value ...'.format(r0.name)) 42 | response = r0.getValue() 43 | print('Radio "{}" value is: "{}"'.format(r0.name, response)) 44 | print() 45 | 46 | time.sleep(1) 47 | 48 | # modify radio "r0" being enabled by default 49 | print('Set radio "{}" to "{}"'.format(r0.name, radio_state)) 50 | r0.setValue(radio_state) 51 | print() 52 | 53 | time.sleep(1) 54 | 55 | # request the state of radio "r0" again 56 | print('Requesting radio "{}" value ...'.format(r0.name)) 57 | response = r0.getValue() 58 | print('Radio "{}" value is: "{}"'.format(r0.name, response)) 59 | print() 60 | 61 | # sanity check 62 | if response != radio_state: 63 | print('WARNING: GET value did not match SET value') 64 | 65 | time.sleep(1) 66 | 67 | # ============================================================================ 68 | # =========================== Background functions =========================== 69 | # request the background color of radio "r0" 70 | print('Requesting background color of radio "{}" ...'.format(r0.name)) 71 | response = r0.Get_background_color_bco() 72 | print('Background color of radio "{}" is: "{}"'.format(r0.name, response)) 73 | print() 74 | 75 | time.sleep(1) 76 | 77 | # modify the background color of radio "r0" to "red" 78 | # search for RGB565 Colors. Red is "63488" at 65k colors 79 | print('Set background color of radio "{}" to "{}"'. 80 | format(r0.name, background_color_value)) 81 | r0.Set_background_color_bco(background_color_value) 82 | print() 83 | 84 | time.sleep(1) 85 | 86 | # request the background color of radio "r0" again 87 | print('Requesting background color of radio "{}" ...'.format(r0.name)) 88 | response = r0.Get_background_color_bco() 89 | print('Background color of radio "{}" is: "{}"'.format(r0.name, response)) 90 | print() 91 | 92 | # sanity check 93 | if response != background_color_value: 94 | print('WARNING: GET value did not match SET value') 95 | 96 | time.sleep(1) 97 | 98 | # ============================================================================ 99 | # ============================== Font functions ============================== 100 | # request the font color of radio "r0" 101 | print('Requesting font color of radio "{}" ...'.format(r0.name)) 102 | response = r0.Get_font_color_pco() 103 | print('Font color of radio "{}" is: "{}"'.format(r0.name, response)) 104 | print() 105 | 106 | time.sleep(1) 107 | 108 | # enable radio "r0" again to make change in font color visible 109 | r0.setValue(1) 110 | 111 | # modify the font color of radio "r0" to "blue" 112 | # search for RGB565 Colors. Blue is "31" at 65k colors 113 | print('Set font color of radio "{}" to "{}"'. 114 | format(r0.name, font_color_value)) 115 | r0.Set_font_color_pco(font_color_value) 116 | print() 117 | 118 | time.sleep(1) 119 | 120 | # request the font color of radio "r0" again 121 | print('Requesting font color of radio "{}" ...'.format(r0.name)) 122 | response = r0.Get_font_color_pco() 123 | print('Font color of radio "{}" is: "{}"'.format(r0.name, response)) 124 | print() 125 | 126 | # sanity check 127 | if response != font_color_value: 128 | print('WARNING: GET value did not match SET value') 129 | 130 | # ============================================================================ 131 | # ============================= End of example =============================== 132 | print('Returning to REPL in 5 seconds') 133 | 134 | # wait for 5 more seconds to safely finish the may still running threads 135 | time.sleep(5) 136 | -------------------------------------------------------------------------------- /examples/rtc/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a RTC 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexHardware, NexRtc 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # create a RTC instance 29 | rtc = NexRtc(nh) 30 | 31 | # ============================================================================ 32 | # ============================ Sync time with NTP ============================ 33 | try: 34 | import network 35 | import ntptime 36 | 37 | station = network.WLAN(network.STA_IF) 38 | if station.isconnected(): 39 | ntptime.settime() 40 | else: 41 | print('Device not connected to the internet, using available time') 42 | except Exception as e: 43 | print('Unexpected exception {} occured, using available time'.format(e)) 44 | 45 | # cut off weekday and yearday, keep [year, month, mday, hour, minute, second] 46 | localtime = list(time.localtime())[0:6] 47 | 48 | # ============================================================================ 49 | # ============================ Set RTC functions ============================= 50 | # set RTC time to list of integers '[2022, 7, 30, 18, 21, 45]' 51 | print('Set RTC time to: {}'.format(localtime)) 52 | rtc.write_rtc_time(localtime) 53 | print() 54 | 55 | time.sleep(1) 56 | 57 | # set RTC time to time string '2022,07,30,18,21,45' 58 | localtime_str = ','.join('{:02d}'.format(x) for x in localtime) 59 | print('Set RTC time to: "{}"'.format(localtime_str)) 60 | rtc.write_rtc_time(localtime_str) 61 | print() 62 | 63 | time.sleep(1) 64 | 65 | # set only year of RTC 66 | print('Set only year of RTC to: "{}"'.format(localtime[0])) 67 | rtc.write_rtc_time('year', localtime[0]) 68 | print() 69 | 70 | time.sleep(1) 71 | 72 | # ============================================================================ 73 | # ============================ Get RTC functions ============================= 74 | # get RTC time as string 75 | response = rtc.read_rtc_time('str') 76 | print('Timestamp from RTC as string: "{}"'.format(response)) 77 | print() 78 | 79 | time.sleep(1) 80 | 81 | # get RTC time as list of integers 82 | response = rtc.read_rtc_time('int') 83 | print('Timestamp from RTC list of integers: "{}"'.format(response)) 84 | print() 85 | 86 | time.sleep(1) 87 | 88 | # get available time types from RTC one by one 89 | print('Get individual time types from RTC...') 90 | for time_type in rtc.time_types: 91 | response = rtc.read_rtc_time(time_type) 92 | print('{} by RTC: "{}"'.format(time_type, response)) 93 | print() 94 | 95 | # ============================================================================ 96 | # ============================= End of example =============================== 97 | print('Returning to REPL in 5 seconds') 98 | 99 | # wait for 5 more seconds to safely finish the may still running threads 100 | time.sleep(5) 101 | -------------------------------------------------------------------------------- /examples/slider/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a slider element 10 | """ 11 | 12 | # system packages 13 | from random import choice, randint 14 | import time 15 | 16 | # custom packages 17 | from nextion import NexSlider, NexHardware 18 | 19 | # define communication pins for Nextion display 20 | tx_pin = 21 21 | rx_pin = 22 22 | 23 | # create Nextion hardware interface 24 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 25 | 26 | # init nextion communication interface 27 | nh.nexInit() 28 | 29 | # create a slider instance 30 | h0 = NexSlider(nh, 0, 1, "h0") 31 | 32 | # ============================================================================ 33 | # ============================== Example values ============================== 34 | # new values of slider 35 | # avoid something close to zero or close to 50 36 | slider_value = choice([randint(5, 40), randint(60, 100)]) 37 | background_color_value = 63488 # red 38 | font_color_value = 31 # blue 39 | pointer_thickness = 5 40 | cursor_height = 5 41 | slider_max = 150 42 | slider_min = 10 43 | 44 | # ============================================================================ 45 | # ============================== Value functions ============================= 46 | # request the value of slider "h0" 47 | print('Requesting slider "{}" value ...'.format(h0.name)) 48 | response = h0.getValue() 49 | print('Slider "{}" value is: "{}"'.format(h0.name, response)) 50 | print() 51 | 52 | time.sleep(1) 53 | 54 | # modify slider "h0" showing "50" by default 55 | print('Set slider "{}" to "{}"'.format(h0.name, slider_value)) 56 | h0.setValue(slider_value) 57 | print() 58 | 59 | time.sleep(1) 60 | 61 | # request the value of slider "h0" again 62 | print('Requesting slider "{}" value ...'.format(h0.name)) 63 | response = h0.getValue() 64 | print('slider "{}" value is: "{}"'.format(h0.name, response)) 65 | print() 66 | 67 | # sanity check 68 | if response != slider_value: 69 | print('WARNING: GET value did not match SET value') 70 | 71 | time.sleep(1) 72 | 73 | # ============================================================================ 74 | # =========================== Background functions =========================== 75 | # request the background color of slider "h0" 76 | print('Requesting background color of slider "{}" ...'.format(h0.name)) 77 | response = h0.Get_background_color_bco() 78 | print('Background color of slider "{}" is: "{}"'.format(h0.name, response)) 79 | print() 80 | 81 | time.sleep(1) 82 | 83 | # modify the background color of slider "h0" to "red" 84 | # search for RGB565 Colors. Red is "63488" at 65k colors 85 | print('Set background color of slider "{}" to "{}"'. 86 | format(h0.name, background_color_value)) 87 | h0.Set_background_color_bco(background_color_value) 88 | print() 89 | 90 | time.sleep(1) 91 | 92 | # request the background color of slider "h0" again 93 | print('Requesting background color of slider "{}" ...'.format(h0.name)) 94 | response = h0.Get_background_color_bco() 95 | print('Background color of slider "{}" is: "{}"'.format(h0.name, response)) 96 | print() 97 | 98 | # sanity check 99 | if response != background_color_value: 100 | print('WARNING: GET value did not match SET value') 101 | 102 | time.sleep(1) 103 | 104 | # ============================================================================ 105 | # ============================== Font functions ============================== 106 | # request the font color of slider "h0" 107 | print('Requesting font color of slider "{}" ...'.format(h0.name)) 108 | response = h0.Get_font_color_pco() 109 | print('Font color of slider "{}" is: "{}"'.format(h0.name, response)) 110 | print() 111 | 112 | time.sleep(1) 113 | 114 | # modify the font color of slider "h0" to "blue" 115 | # search for RGB565 Colors. Blue is "31" at 65k colors 116 | print('Set font color of slider "{}" to "{}"'. 117 | format(h0.name, font_color_value)) 118 | h0.Set_font_color_pco(font_color_value) 119 | print() 120 | 121 | time.sleep(1) 122 | 123 | # request the font color of slider "h0" again 124 | print('Requesting font color of slider "{}" ...'.format(h0.name)) 125 | response = h0.Get_font_color_pco() 126 | print('Font color of slider "{}" is: "{}"'.format(h0.name, response)) 127 | print() 128 | 129 | # sanity check 130 | if response != font_color_value: 131 | print('WARNING: GET value did not match SET value') 132 | 133 | time.sleep(1) 134 | 135 | # ============================================================================ 136 | # ============================ Pointer functions ============================= 137 | # request the pointer thickness of slider "h0" 138 | print('Requesting pointer thickness of slider "{}" ...'.format(h0.name)) 139 | response = h0.Get_pointer_thickness_wid() 140 | print('Pointer thickness of slider "{}" is: "{}"'.format(h0.name, response)) 141 | print() 142 | 143 | time.sleep(1) 144 | 145 | # modify the pointer thickness of slider "h0" 146 | print('Set pointer thickness of slider "{}" to "{}"'. 147 | format(h0.name, pointer_thickness)) 148 | h0.Set_pointer_thickness_wid(pointer_thickness) 149 | print() 150 | 151 | time.sleep(1) 152 | 153 | # request the pointer thickness of slider "h0" again 154 | print('Requesting pointer thickness of slider "{}" ...'.format(h0.name)) 155 | response = h0.Get_pointer_thickness_wid() 156 | print('Pointer thickness of slider "{}" is: "{}"'.format(h0.name, response)) 157 | print() 158 | 159 | # sanity check 160 | if response != pointer_thickness: 161 | print('WARNING: GET value did not match SET value') 162 | 163 | time.sleep(1) 164 | 165 | # ============================================================================ 166 | # ============================ Special functions ============================= 167 | # ============================================================================ 168 | # ============================= Cursor functions ============================= 169 | # request the cursor height of slider "h0" 170 | print('Requesting cursor height of slider "{}" ...'.format(h0.name)) 171 | response = h0.Get_cursor_height_hig() 172 | print('Cursor height of slider "{}" is: "{}"'.format(h0.name, response)) 173 | print() 174 | 175 | time.sleep(1) 176 | 177 | # modify the cursor height of slider "h0" 178 | print('Set cursor height of slider "{}" to "{}"'. 179 | format(h0.name, cursor_height)) 180 | h0.Set_cursor_height_hig(cursor_height) 181 | print() 182 | 183 | time.sleep(1) 184 | 185 | # request the cursor height of slider "h0" again 186 | print('Requesting cursor height of slider "{}" ...'.format(h0.name)) 187 | response = h0.Get_cursor_height_hig() 188 | print('Cursor height of slider "{}" is: "{}"'.format(h0.name, response)) 189 | print() 190 | 191 | # sanity check 192 | if response != cursor_height: 193 | print('WARNING: GET value did not match SET value') 194 | 195 | time.sleep(1) 196 | 197 | # ============================================================================ 198 | # =========================== Value Limit functions ========================== 199 | # request the maximum value of slider "h0" 200 | print('Requesting maximum value of slider "{}" ...'.format(h0.name)) 201 | response = h0.getMaxval() 202 | print('Maximum value of slider "{}" is: "{}"'.format(h0.name, response)) 203 | print() 204 | 205 | time.sleep(1) 206 | 207 | # modify the maximum value of slider "h0" 208 | print('Set maximum value of slider "{}" to "{}"'. 209 | format(h0.name, slider_max)) 210 | h0.setMaxval(slider_max) 211 | print() 212 | 213 | time.sleep(1) 214 | 215 | # request the maximum value of slider "h0" again 216 | print('Requesting maximum value of slider "{}" ...'.format(h0.name)) 217 | response = h0.getMaxval() 218 | print('cursor height of slider "{}" is: "{}"'.format(h0.name, response)) 219 | print() 220 | 221 | # sanity check 222 | if response != slider_max: 223 | print('WARNING: GET value did not match SET value') 224 | 225 | time.sleep(1) 226 | 227 | # request the minimum value of slider "h0" 228 | print('Requesting minimum value of slider "{}" ...'.format(h0.name)) 229 | response = h0.getMinval() 230 | print('Minimum value of slider "{}" is: "{}"'.format(h0.name, response)) 231 | print() 232 | 233 | time.sleep(1) 234 | 235 | # modify the minimum value of slider "h0" 236 | print('Set minimum value of slider "{}" to "{}"'. 237 | format(h0.name, slider_min)) 238 | h0.setMinval(slider_min) 239 | print() 240 | 241 | time.sleep(1) 242 | 243 | # request the minimum value of slider "h0" again 244 | print('Requesting minimum value of slider "{}" ...'.format(h0.name)) 245 | response = h0.getMinval() 246 | print('cursor height of slider "{}" is: "{}"'.format(h0.name, response)) 247 | print() 248 | 249 | # sanity check 250 | if response != slider_min: 251 | print('WARNING: GET value did not match SET value') 252 | 253 | # ============================================================================ 254 | # ============================= End of example =============================== 255 | print('Returning to REPL in 5 seconds') 256 | 257 | # wait for 5 more seconds to safely finish the may still running threads 258 | time.sleep(5) 259 | -------------------------------------------------------------------------------- /examples/text/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a text element 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexText, NexHardware 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # create a textfield instance 29 | t0 = NexText(nh, 0, 1, "t0") 30 | 31 | # ============================================================================ 32 | # ============================== Example values ============================== 33 | # new values of text 34 | textfield_text = "other txt" 35 | background_color_value = 63488 # red 36 | font_color_value = 31 # blue 37 | x_offset = 20 38 | y_offset = 20 39 | 40 | # ============================================================================ 41 | # ============================== Text functions ============================== 42 | # request the text of textfield "t0" 43 | print('Requesting textfield "{}" text ...'.format(t0.name)) 44 | response = t0.getText() 45 | print('Textfield "{}" text is: "{}"'.format(t0.name, response)) 46 | print() 47 | 48 | time.sleep(1) 49 | 50 | # modify textfield "t0" showing "newtxt" by default 51 | print('Set textfield "{}" to "{}"'.format(t0.name, textfield_text)) 52 | t0.setText(textfield_text) 53 | print() 54 | 55 | time.sleep(1) 56 | 57 | # request the text of textfield "t0" again 58 | print('Requesting textfield "{}" text ...'.format(t0.name)) 59 | response = t0.getText() 60 | print('Textfield "{}" text is: "{}"'.format(t0.name, response)) 61 | print() 62 | 63 | # sanity check 64 | if response != textfield_text: 65 | print('WARNING: GET value did not match SET value') 66 | 67 | time.sleep(1) 68 | 69 | # ============================================================================ 70 | # =========================== Background functions =========================== 71 | # request the background color of textfield "t0" 72 | print('Requesting background color of textfield "{}" ...'.format(t0.name)) 73 | response = t0.Get_background_color_bco() 74 | print('Background color of textfield "{}" is: "{}"'.format(t0.name, response)) 75 | print() 76 | 77 | time.sleep(1) 78 | 79 | # modify the background color of textfield "t0" to "red" 80 | # search for RGB565 Colors. Red is "63488" at 65k colors 81 | print('Set background color of textfield "{}" to "{}"'. 82 | format(t0.name, background_color_value)) 83 | t0.Set_background_color_bco(background_color_value) 84 | print() 85 | 86 | time.sleep(1) 87 | 88 | # request the background color of textfield "t0" again 89 | print('Requesting background color of textfield "{}" ...'.format(t0.name)) 90 | response = t0.Get_background_color_bco() 91 | print('Background color of textfield "{}" is: "{}"'.format(t0.name, response)) 92 | print() 93 | 94 | # sanity check 95 | if response != background_color_value: 96 | print('WARNING: GET value did not match SET value') 97 | 98 | time.sleep(1) 99 | 100 | # ============================================================================ 101 | # ============================== Font functions ============================== 102 | # request the font color of textfield "t0" 103 | print('Requesting font color of textfield "{}" ...'.format(t0.name)) 104 | response = t0.Get_font_color_pco() 105 | print('Font color of textfield "{}" is: "{}"'.format(t0.name, response)) 106 | print() 107 | 108 | time.sleep(1) 109 | 110 | # modify the font color of textfield "t0" to "blue" 111 | # search for RGB565 Colors. Blue is "31" at 65k colors 112 | print('Set font color of textfield "{}" to "{}"'. 113 | format(t0.name, font_color_value)) 114 | t0.Set_font_color_pco(font_color_value) 115 | print() 116 | 117 | time.sleep(1) 118 | 119 | # request the font color of textfield "t0" again 120 | print('Requesting font color of textfield "{}" ...'.format(t0.name)) 121 | response = t0.Get_font_color_pco() 122 | print('Font color of textfield "{}" is: "{}"'.format(t0.name, response)) 123 | print() 124 | 125 | # sanity check 126 | if response != font_color_value: 127 | print('WARNING: GET value did not match SET value') 128 | 129 | time.sleep(1) 130 | 131 | # ============================================================================ 132 | # ============================ Position functions ============================ 133 | # request the x/y position of textfield "t0" again 134 | print('Requesting x/y position of textfield "{}" ...'.format(t0.name)) 135 | x_position = t0.Get_place_xcen() 136 | y_position = t0.Get_place_ycen() 137 | print('Position of textfield "{}" is: "x={}", "y={}"'. 138 | format(t0.name, x_position, y_position)) 139 | print() 140 | 141 | x_position += x_offset 142 | y_position += y_offset 143 | 144 | # modify the x/y position of textfield "t0" 145 | print('Set x/y position of textfield "{}" to "x={}", "y={}"'. 146 | format(t0.name, x_position, y_position)) 147 | t0.Set_place_xcen(x_position) 148 | t0.Set_place_ycen(y_position) 149 | print() 150 | 151 | # ============================================================================ 152 | # ============================= End of example =============================== 153 | print('Returning to REPL in 5 seconds') 154 | 155 | # wait for 5 more seconds to safely finish the may still running threads 156 | time.sleep(5) 157 | -------------------------------------------------------------------------------- /examples/upload/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to perform an update of the Nextion display content 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexHardware, NexUpload 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # create a upload instance 29 | nex_download = NexUpload(nh, "everything.tft", 115200) 30 | 31 | # ============================================================================ 32 | # ============================ Special functions ============================= 33 | # print file infos 34 | print('Update file name: "{}" with size of "{}" byte'. 35 | format(nex_download.file_name, nex_download.file_size)) 36 | 37 | # perform update 38 | print('Performing update, please wait ...') 39 | result = nex_download.upload() 40 | if result: 41 | print('Update done successfully') 42 | else: 43 | print('Update failed') 44 | print() 45 | 46 | # ============================================================================ 47 | # ============================= End of example =============================== 48 | print('Returning to REPL in 5 seconds') 49 | 50 | # wait for 5 more seconds to safely finish the may still running threads 51 | time.sleep(5) 52 | -------------------------------------------------------------------------------- /examples/waveform/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Main script 6 | 7 | Do your stuff here, this file is similar to the loop() function on Arduino 8 | 9 | Example on how to interact with a waveform element 10 | """ 11 | 12 | # system packages 13 | import time 14 | 15 | # custom packages 16 | from nextion import NexWaveform, NexHardware 17 | 18 | # define communication pins for Nextion display 19 | tx_pin = 21 20 | rx_pin = 22 21 | 22 | # create Nextion hardware interface 23 | nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin) 24 | 25 | # init nextion communication interface 26 | nh.nexInit() 27 | 28 | # create a waveform instance (CID is 14, see HMI file) 29 | s0 = NexWaveform(nh, 0, 14, "s0") 30 | 31 | # ============================================================================ 32 | # ============================== Example values ============================== 33 | # new values of waveform 34 | background_color_value = 63488 # red 35 | grid_color_value = 31 # blue 36 | grid_width = 20 37 | grid_height = 20 38 | channel_0_color = 64480 # orange 39 | 40 | # ============================================================================ 41 | # ============================ Datapoint functions =========================== 42 | # modify waveform "s0" 43 | print('Add datapoints to waveform "{}"'.format(s0.name)) 44 | for x in range(0, 100): 45 | channel_0_value = x 46 | channel_1_value = 100 - x 47 | channel_2_value = 20 48 | channel_3_value = int(x / 2) 49 | s0.addValue(0, channel_0_value) 50 | s0.addValue(1, channel_1_value) 51 | s0.addValue(2, channel_2_value) 52 | s0.addValue(3, channel_3_value) 53 | time.sleep(0.1) 54 | print() 55 | 56 | time.sleep(1) 57 | 58 | # remove channel 0 waveform 59 | print('Removing channel 0 waveform...') 60 | s0.clearChannel(0) 61 | print() 62 | 63 | time.sleep(1) 64 | 65 | # ============================================================================ 66 | # =========================== Background functions =========================== 67 | # request the background color of waveform "s0" 68 | print('Requesting background color of waveform "{}" ...'.format(s0.name)) 69 | response = s0.Get_background_color_bco() 70 | print('Background color of waveform "{}" is: "{}"'.format(s0.name, response)) 71 | print() 72 | 73 | time.sleep(1) 74 | 75 | # modify the background color of waveform "s0" to "red" 76 | # search for RGB565 Colors. Red is "63488" at 65k colors 77 | print('Set background color of waveform "{}" to "{}"'. 78 | format(s0.name, background_color_value)) 79 | s0.Set_background_color_bco(background_color_value) 80 | print() 81 | 82 | time.sleep(1) 83 | 84 | # request the background color of waveform "s0" again 85 | print('Requesting background color of waveform "{}" ...'.format(s0.name)) 86 | response = s0.Get_background_color_bco() 87 | print('Background color of waveform "{}" is: "{}"'.format(s0.name, response)) 88 | print() 89 | 90 | # sanity check 91 | if response != background_color_value: 92 | print('WARNING: GET value did not match SET value') 93 | 94 | time.sleep(1) 95 | 96 | # ============================================================================ 97 | # ============================ Special functions ============================= 98 | # ============================================================================ 99 | # =========================== Grid color functions =========================== 100 | # request the grid color of waveform "s0" 101 | print('Requesting grid color of waveform "{}" ...'.format(s0.name)) 102 | response = s0.Get_grid_color_gdc() 103 | print('Grid color color of waveform "{}" is: "{}"'.format(s0.name, response)) 104 | print() 105 | 106 | time.sleep(1) 107 | 108 | # modify the grid color of waveform "s0" to "blue" 109 | # search for RGB565 Colors. Blue is "31" at 65k colors 110 | print('Set grid color of waveform "{}" to "{}"'. 111 | format(s0.name, grid_color_value)) 112 | s0.Set_grid_color_gdc(grid_color_value) 113 | print() 114 | 115 | time.sleep(1) 116 | 117 | # request the grid color of waveform "s0" again 118 | print('Requesting grid color of waveform "{}" ...'.format(s0.name)) 119 | response = s0.Get_grid_color_gdc() 120 | print('Grid color of waveform "{}" is: "{}"'.format(s0.name, response)) 121 | print() 122 | 123 | # sanity check 124 | if response != grid_color_value: 125 | print('WARNING: GET value did not match SET value') 126 | 127 | time.sleep(1) 128 | 129 | # ============================================================================ 130 | # ========================= Channel color functions ========================== 131 | # request the channel 0 color of waveform "s0" 132 | print('Requesting channel 0 color of waveform "{}" ...'.format(s0.name)) 133 | response = s0.Get_channel_0_color_pco0() 134 | print('Channel 0 color of waveform "{}" is: "{}"'.format(s0.name, response)) 135 | print() 136 | 137 | time.sleep(1) 138 | 139 | # modify the channel 0 color of waveform "s0" to "orange" 140 | # search for RGB565 Colors. Orange is "64480" at 65k colors 141 | print('Set channel 0 color of waveform "{}" to "{}"'. 142 | format(s0.name, channel_0_color)) 143 | s0.Set_channel_0_color_pco0(channel_0_color) 144 | print() 145 | 146 | time.sleep(1) 147 | 148 | # request the channel 0 color of waveform "s0" again 149 | print('Requesting channel 0 color of waveform "{}" ...'.format(s0.name)) 150 | response = s0.Get_channel_0_color_pco0() 151 | print('Channel 0 color of waveform "{}" is: "{}"'.format(s0.name, response)) 152 | print() 153 | 154 | # sanity check 155 | if response != channel_0_color: 156 | print('WARNING: GET value did not match SET value') 157 | 158 | time.sleep(1) 159 | 160 | # ============================================================================ 161 | # ========================= Grid dimenstion functions ======================== 162 | # request the grid width of waveform "s0" 163 | print('Requesting grid width of waveform "{}" ...'.format(s0.name)) 164 | response = s0.Get_grid_width_gdw() 165 | print('Grid width of waveform "{}" is: "{}"'.format(s0.name, response)) 166 | print() 167 | 168 | time.sleep(1) 169 | 170 | # modify the grid width of waveform "s0" 171 | print('Set grid width of waveform "{}" to "{}"'.format(s0.name, grid_width)) 172 | s0.Set_grid_width_gdw(grid_width) 173 | print() 174 | 175 | time.sleep(1) 176 | 177 | # request the grid width of waveform "s0" again 178 | print('Requesting grid width of waveform "{}" ...'.format(s0.name)) 179 | response = s0.Get_grid_width_gdw() 180 | print('Grid width of waveform "{}" is: "{}"'.format(s0.name, response)) 181 | print() 182 | 183 | # sanity check 184 | if response != grid_width: 185 | print('WARNING: GET value did not match SET value') 186 | 187 | time.sleep(1) 188 | 189 | # request the grid height of waveform "s0" 190 | print('Requesting grid height of waveform "{}" ...'.format(s0.name)) 191 | response = s0.Get_grid_height_gdh() 192 | print('Grid height of waveform "{}" is: "{}"'.format(s0.name, response)) 193 | print() 194 | 195 | time.sleep(1) 196 | 197 | # modify the grid height of waveform "s0" 198 | print('Set grid height of waveform "{}" to "{}"'.format(s0.name, grid_height)) 199 | s0.Set_grid_height_gdh(grid_height) 200 | print() 201 | 202 | time.sleep(1) 203 | 204 | # request the grid height of waveform "s0" again 205 | print('Requesting grid height of waveform "{}" ...'.format(s0.name)) 206 | response = s0.Get_grid_height_gdh() 207 | print('Grid height of waveform "{}" is: "{}"'.format(s0.name, response)) 208 | print() 209 | 210 | # sanity check 211 | if response != grid_height: 212 | print('WARNING: GET value did not match SET value') 213 | 214 | # ============================================================================ 215 | # ============================= End of example =============================== 216 | print('Returning to REPL in 5 seconds') 217 | 218 | # wait for 5 more seconds to safely finish the may still running threads 219 | time.sleep(5) 220 | -------------------------------------------------------------------------------- /nextion/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | from .version import __version__ 5 | 6 | from .nextion_hardware import NexHardware, NexHardwareError 7 | from .nextion_button import NexButton 8 | from .nextion_checkbox import NexCheckbox 9 | from .nextion_dual_state_button import NexDSButton 10 | from .nextion_gauge import NexGauge 11 | from .nextion_gpio import NexGpio 12 | from .nextion_number import NexNumber 13 | from .nextion_page import NexPage 14 | from .nextion_progressbar import NexProgressBar 15 | from .nextion_radio import NexRadio 16 | from .nextion_rtc import NexRtc 17 | from .nextion_slider import NexSlider 18 | from .nextion_text import NexText 19 | from .nextion_upload import NexUpload 20 | from .nextion_variable import NexVariable 21 | from .nextion_waveform import NexWaveform 22 | -------------------------------------------------------------------------------- /nextion/common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Common 6 | 7 | Common functions shared accross all Nextion elements 8 | 9 | Check the description of Mixin 10 | https://realpython.com/lessons/multiple-inheritance-python/ 11 | """ 12 | 13 | # system packages 14 | from time import sleep 15 | 16 | 17 | class CommonError(Exception): 18 | """Base class for exceptions in this module.""" 19 | pass 20 | 21 | 22 | class Common(object): 23 | """docstring for Common""" 24 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 25 | """ 26 | Init gauge 27 | 28 | :param nh: The Nextion hardware interface object 29 | :type nh: NexHardware 30 | :param pid: The page ID 31 | :type pid: int 32 | :param cid: The component ID 33 | :type cid: int 34 | :param name: The component name 35 | :type name: str 36 | """ 37 | self._pid = pid 38 | self._cid = cid 39 | self._name = name 40 | self._nh = nh 41 | 42 | @property 43 | def pid(self) -> int: 44 | """ 45 | Get page ID of element 46 | 47 | :returns: Page ID 48 | :rtype: int 49 | """ 50 | return self._pid 51 | 52 | @property 53 | def cid(self) -> int: 54 | """ 55 | Get component ID of element 56 | 57 | :returns: Component ID 58 | :rtype: int 59 | """ 60 | return self._cid 61 | 62 | @property 63 | def name(self) -> str: 64 | """ 65 | Get name of element 66 | 67 | :returns: Name of element 68 | :rtype: str 69 | """ 70 | return self._name 71 | 72 | def hide(self) -> bool: 73 | """ 74 | Hide component on screen 75 | 76 | :returns: True on success, false otherwise 77 | :rtype: bool 78 | """ 79 | cmd = "vis {},0".format(self.name) 80 | self._nh.sendCommand(cmd) 81 | return self._nh.recvRetCommandFinished() 82 | 83 | def show(self) -> bool: 84 | """ 85 | Show component on screen 86 | 87 | :returns: True on success, false otherwise 88 | :rtype: bool 89 | """ 90 | cmd = "vis {},1".format(self.name) 91 | self._nh.sendCommand(cmd) 92 | return self._nh.recvRetCommandFinished() 93 | 94 | 95 | class CommonBackgroundColorMixin(object): 96 | """docstring for CommonBackgroundColorMixin""" 97 | def Get_background_color_bco(self) -> int: 98 | """ 99 | Get background color attribute of component 100 | 101 | :returns: The background color 102 | :rtype: int 103 | """ 104 | cmd = "get {}.bco".format(self.name) 105 | self._nh.sendCommand(cmd) 106 | sleep(0.1) # necessary, data might not be available otherwise 107 | return self._nh.recvRetNumber() 108 | 109 | def Set_background_color_bco(self, number: int) -> bool: 110 | """ 111 | Set background color attribute of component 112 | 113 | :param number: The background color number 114 | :type number: int 115 | 116 | :returns: True on success, false otherwise 117 | :rtype: bool 118 | """ 119 | cmd = "{}.bco={}".format(self.name, number) 120 | self._nh.sendCommand(cmd) 121 | cmd = "ref {}".format(self.name) 122 | self._nh.sendCommand(cmd) 123 | return self._nh.recvRetCommandFinished() 124 | 125 | 126 | class CommonFontMixin(object): 127 | """docstring for CommonFontMixin""" 128 | def Get_font_color_pco(self) -> int: 129 | """ 130 | Get font color attribute of component 131 | 132 | :returns: The font color 133 | :rtype: int 134 | """ 135 | cmd = "get {}.pco".format(self.name) 136 | self._nh.sendCommand(cmd) 137 | sleep(0.1) # necessary, data might not be available otherwise 138 | return self._nh.recvRetNumber() 139 | 140 | def Set_font_color_pco(self, number: int) -> bool: 141 | """ 142 | Set font color attribute of component 143 | 144 | :param number: The font color number 145 | :type number: int 146 | 147 | :returns: True on success, false otherwise 148 | :rtype: bool 149 | """ 150 | cmd = "{}.pco={}".format(self.name, number) 151 | self._nh.sendCommand(cmd) 152 | cmd = "ref {}".format(self.name) 153 | self._nh.sendCommand(cmd) 154 | return self._nh.recvRetCommandFinished() 155 | 156 | def getFont(self) -> int: 157 | """ 158 | Get font attribute of component 159 | 160 | :returns: The font color 161 | :rtype: int 162 | """ 163 | cmd = "get {}.font".format(self.name) 164 | self._nh.sendCommand(cmd) 165 | sleep(0.1) # necessary, data might not be available otherwise 166 | return self._nh.recvRetNumber() 167 | 168 | def setFont(self, number: int) -> bool: 169 | """ 170 | Set font attribute of component 171 | 172 | :param number: The font number 173 | :type number: int 174 | 175 | :returns: True on success, false otherwise 176 | :rtype: bool 177 | """ 178 | cmd = "{}.font={}".format(self.name, number) 179 | self._nh.sendCommand(cmd) 180 | cmd = "ref {}".format(self.name) 181 | self._nh.sendCommand(cmd) 182 | return self._nh.recvRetCommandFinished() 183 | 184 | 185 | class CommonPointerMixin(object): 186 | """docstring for CommonPointerMixin""" 187 | def Get_pointer_thickness_wid(self) -> int: 188 | """ 189 | Get pointer wid attribute of component 190 | 191 | :returns: The pointer thickness 192 | :rtype: int 193 | """ 194 | cmd = "get {}.wid".format(self.name) 195 | self._nh.sendCommand(cmd) 196 | sleep(0.1) # necessary, data might not be available otherwise 197 | return self._nh.recvRetNumber() 198 | 199 | def Set_pointer_thickness_wid(self, number: int) -> bool: 200 | """ 201 | Set pointer hig attribute of component 202 | 203 | :param number: The pointer thickness 204 | :type number: int 205 | 206 | :returns: True on success, false otherwise 207 | :rtype: bool 208 | """ 209 | cmd = "{}.wid={}".format(self.name, number) 210 | self._nh.sendCommand(cmd) 211 | cmd = "ref {}".format(self.name) 212 | self._nh.sendCommand(cmd) 213 | return self._nh.recvRetCommandFinished() 214 | 215 | 216 | class CommonPositionMixin(object): 217 | """docstring for CommonPositionMixin""" 218 | def Get_place_xcen(self) -> int: 219 | """ 220 | Get xcen attribute of component 221 | 222 | :returns: The x position 223 | :rtype: int 224 | """ 225 | cmd = "get {}.xcen".format(self.name) 226 | self._nh.sendCommand(cmd) 227 | sleep(0.1) # necessary, data might not be available otherwise 228 | return self._nh.recvRetNumber() 229 | 230 | def Set_place_xcen(self, number: int) -> bool: 231 | """ 232 | Get xcen attribute of component 233 | 234 | :param number: The new x position 235 | :type number: int 236 | 237 | :returns: True on success, false otherwise 238 | :rtype: bool 239 | """ 240 | cmd = "{}.xcen={}".format(self.name, number) 241 | self._nh.sendCommand(cmd) 242 | cmd = "ref {}".format(self.name) 243 | self._nh.sendCommand(cmd) 244 | return self._nh.recvRetCommandFinished() 245 | 246 | def Get_place_ycen(self) -> int: 247 | """ 248 | Get ycen attribute of component 249 | 250 | :returns: The y position 251 | :rtype: int 252 | """ 253 | cmd = "get {}.ycen".format(self.name) 254 | self._nh.sendCommand(cmd) 255 | sleep(0.1) # necessary, data might not be available otherwise 256 | return self._nh.recvRetNumber() 257 | 258 | def Set_place_ycen(self, number: int) -> bool: 259 | """ 260 | Get ycen attribute of component 261 | 262 | :param number: The new y position 263 | :type number: int 264 | 265 | :returns: True on success, false otherwise 266 | :rtype: bool 267 | """ 268 | cmd = "{}.ycen={}".format(self.name, number) 269 | self._nh.sendCommand(cmd) 270 | cmd = "ref {}".format(self.name) 271 | self._nh.sendCommand(cmd) 272 | return self._nh.recvRetCommandFinished() 273 | 274 | 275 | class CommonTextMixin(object): 276 | """docstring for CommonTextMixin""" 277 | def getText(self) -> str: 278 | """ 279 | Get text attribute of component 280 | 281 | :returns: The text. 282 | :rtype: str 283 | """ 284 | cmd = "get {}.txt".format(self.name) 285 | self._nh.sendCommand(cmd) 286 | sleep(0.1) # necessary, data might not be available otherwise 287 | return self._nh.recvRetString() 288 | 289 | def setText(self, text: str) -> bool: 290 | """ 291 | Set text attribute of component 292 | 293 | :param text: The text 294 | :type text: str 295 | 296 | :returns: True on success, false otherwise 297 | :rtype: bool 298 | """ 299 | cmd = '{}.txt="{}"'.format(self.name, text) 300 | self._nh.sendCommand(cmd) 301 | return self._nh.recvRetCommandFinished() 302 | 303 | 304 | class CommonValueMixin(object): 305 | """docstring for CommonValueMixin""" 306 | def getValue(self) -> int: 307 | """ 308 | Get value attribute of component 309 | 310 | :returns: The value. 311 | :rtype: int 312 | """ 313 | cmd = "get {}.val".format(self.name) 314 | self._nh.sendCommand(cmd) 315 | sleep(0.1) # necessary, data might not be available otherwise 316 | return self._nh.recvRetNumber() 317 | 318 | def setValue(self, value: int) -> bool: 319 | """ 320 | Set value attribute of component 321 | 322 | :param text: The value 323 | :type text: int 324 | 325 | :returns: True on success, false otherwise 326 | :rtype: bool 327 | """ 328 | cmd = "{}.val={}".format(self.name, value) 329 | self._nh.sendCommand(cmd) 330 | return self._nh.recvRetCommandFinished() 331 | -------------------------------------------------------------------------------- /nextion/const.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Const 6 | 7 | This file contains the constant definitions of all Nextion commands 8 | """ 9 | 10 | from micropython import const 11 | 12 | # function codes 13 | # defined as const(), see https://github.com/micropython/micropython/issues/573 14 | #: Command finished 15 | NEX_RET_CMD_FINISHED = const(0x01) 16 | #: Event launched 17 | NEX_RET_EVENT_LAUNCHED = const(0x88) 18 | #: Event upgraded 19 | NEX_RET_EVENT_UPGRADED = const(0x89) 20 | #: Event touch head 21 | NEX_RET_EVENT_TOUCH_HEAD = const(0x65) 22 | #: Event position head 23 | NEX_RET_EVENT_POSITION_HEAD = const(0x67) 24 | #: Event sleep position head 25 | NEX_RET_EVENT_SLEEP_POSITION_HEAD = const(0x68) 26 | #: Current page ID head 27 | NEX_RET_CURRENT_PAGE_ID_HEAD = const(0x66) 28 | #: String head 29 | NEX_RET_STRING_HEAD = const(0x70) 30 | #: Number head 31 | NEX_RET_NUMBER_HEAD = const(0x71) 32 | #: Invalid command 33 | NEX_RET_INVALID_CMD = const(0x00) 34 | #: Invalid component ID 35 | NEX_RET_INVALID_COMPONENT_ID = const(0x02) 36 | #: Invalid page ID 37 | NEX_RET_INVALID_PAGE_ID = const(0x03) 38 | #: Invalid picture ID 39 | NEX_RET_INVALID_PICTURE_ID = const(0x04) 40 | #: Invalid font ID 41 | NEX_RET_INVALID_FONT_ID = const(0x05) 42 | #: Invalid baudrate 43 | NEX_RET_INVALID_BAUD = const(0x11) 44 | #: Invalid variable 45 | NEX_RET_INVALID_VARIABLE = const(0x1A) 46 | #: Invalid operation 47 | NEX_RET_INVALID_OPERATION = const(0x1B) 48 | 49 | # non standard define, but helpful in any case 50 | #: End command 51 | NEX_END_CMD = b'\xFF\xFF\xFF' 52 | -------------------------------------------------------------------------------- /nextion/nextion_button.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexButton 6 | 7 | Functions to interact with a Nextion Button element 8 | """ 9 | 10 | # custom packages 11 | from .common import Common, CommonBackgroundColorMixin, CommonFontMixin, \ 12 | CommonPositionMixin, CommonTextMixin 13 | 14 | 15 | class NexButtonError(Exception): 16 | """Base class for exceptions in this module.""" 17 | pass 18 | 19 | 20 | class NexButton(Common, CommonBackgroundColorMixin, CommonFontMixin, 21 | CommonPositionMixin, CommonTextMixin): 22 | """docstring for NexButton""" 23 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 24 | """ 25 | Init button 26 | 27 | :param nh: The Nextion hardware interface object 28 | :type nh: NexHardware 29 | :param pid: The page ID 30 | :type pid: int 31 | :param cid: The component ID 32 | :type cid: int 33 | :param name: The component name 34 | :type name: str 35 | """ 36 | super().__init__(nh, pid, cid, name) 37 | 38 | def Get_press_background_color_bco2(self) -> int: 39 | """ 40 | Get the pressed background color 41 | 42 | :returns: The pressed background color bco2 43 | :rtype: int 44 | """ 45 | cmd = "get {}.bco2".format(self.name) 46 | self._nh.sendCommand(cmd) 47 | return self._nh.recvRetNumber() 48 | 49 | def Set_press_background_color_bco2(self, number: int) -> bool: 50 | """ 51 | Set the pressed background color 52 | 53 | :param number: The background color number 54 | :type number: int 55 | 56 | :returns: True on success, false otherwise 57 | :rtype: bool 58 | """ 59 | cmd = "{}.bco2={}".format(self.name, number) 60 | self._nh.sendCommand(cmd) 61 | cmd = "ref {}".format(self.name) 62 | self._nh.sendCommand(cmd) 63 | return self._nh.recvRetCommandFinished() 64 | 65 | def Get_press_font_color_pco2(self) -> int: 66 | """ 67 | Get the pressed font color 68 | 69 | :returns: The pressed font color pco2 70 | :rtype: int 71 | """ 72 | cmd = "get {}.pco2".format(self.name) 73 | self._nh.sendCommand(cmd) 74 | return self._nh.recvRetNumber() 75 | 76 | def Set_press_font_color_pco2(self, number: int) -> bool: 77 | """ 78 | Set the pressed font color 79 | 80 | :param number: The font color number 81 | :type number: int 82 | 83 | :returns: True on success, false otherwise 84 | :rtype: bool 85 | """ 86 | cmd = "{}.pco2={}".format(self.name, number) 87 | self._nh.sendCommand(cmd) 88 | cmd = "ref {}".format(self.name) 89 | self._nh.sendCommand(cmd) 90 | return self._nh.recvRetCommandFinished() 91 | -------------------------------------------------------------------------------- /nextion/nextion_checkbox.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexCheckbox 6 | 7 | Functions to interact with a Nextion Checkbox element 8 | """ 9 | 10 | # custom packages 11 | from .common import Common, CommonBackgroundColorMixin, CommonFontMixin, \ 12 | CommonValueMixin 13 | 14 | 15 | class NexCheckboxError(Exception): 16 | """Base class for exceptions in this module.""" 17 | pass 18 | 19 | 20 | class NexCheckbox(Common, CommonBackgroundColorMixin, CommonFontMixin, 21 | CommonValueMixin): 22 | """docstring for NexCheckbox""" 23 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 24 | """ 25 | Init checkbox 26 | 27 | :param nh: The Nextion hardware interface object 28 | :type nh: NexHardware 29 | :param pid: The page ID 30 | :type pid: int 31 | :param cid: The component ID 32 | :type cid: int 33 | :param name: The component name 34 | :type name: str 35 | """ 36 | super().__init__(nh, pid, cid, name) 37 | 38 | CommonFontMixin_unsupported_functions = [ 39 | "getFont", 40 | "setFont", 41 | ] 42 | for attr_name in CommonFontMixin_unsupported_functions: 43 | delattr(CommonFontMixin, attr_name) 44 | -------------------------------------------------------------------------------- /nextion/nextion_dual_state_button.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexDSButton 6 | 7 | Functions to interact with a Nextion dual state Button element 8 | """ 9 | 10 | # system packages 11 | from time import sleep 12 | 13 | # custom packages 14 | from .common import Common, CommonFontMixin, CommonPositionMixin, \ 15 | CommonTextMixin, CommonValueMixin 16 | 17 | 18 | class NexDSButtonError(Exception): 19 | """Base class for exceptions in this module.""" 20 | pass 21 | 22 | 23 | class NexDSButton(Common, CommonFontMixin, CommonPositionMixin, 24 | CommonTextMixin, CommonValueMixin): 25 | """docstring for NexDSButton""" 26 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 27 | """ 28 | Init dual state button 29 | 30 | :param nh: The Nextion hardware interface object 31 | :type nh: NexHardware 32 | :param pid: The page ID 33 | :type pid: int 34 | :param cid: The component ID 35 | :type cid: int 36 | :param name: The component name 37 | :type name: str 38 | """ 39 | super().__init__(nh, pid, cid, name) 40 | 41 | def Get_state0_color_bco0(self) -> int: 42 | """ 43 | Get bco0 attribute of component 44 | 45 | :returns: The background color 46 | :rtype: int 47 | """ 48 | cmd = "get {}.bco0".format(self.name) 49 | self._nh.sendCommand(cmd) 50 | sleep(0.1) # necessary, data might not be available otherwise 51 | return self._nh.recvRetNumber() 52 | 53 | def Set_state0_color_bco0(self, number: int) -> bool: 54 | """ 55 | Set bco0 attribute of component 56 | 57 | :param number: The background color number 58 | :type number: int 59 | 60 | :returns: True on success, false otherwise 61 | :rtype: bool 62 | """ 63 | cmd = "{}.bco0={}".format(self.name, number) 64 | self._nh.sendCommand(cmd) 65 | cmd = "ref {}".format(self.name) 66 | self._nh.sendCommand(cmd) 67 | return self._nh.recvRetCommandFinished() 68 | 69 | def Get_state1_color_bco1(self) -> int: 70 | """ 71 | Get bco1 attribute of component 72 | 73 | :returns: The background color 74 | :rtype: int 75 | """ 76 | cmd = "get {}.bco1".format(self.name) 77 | self._nh.sendCommand(cmd) 78 | sleep(0.1) # necessary, data might not be available otherwise 79 | return self._nh.recvRetNumber() 80 | 81 | def Set_state1_color_bco1(self, number: int) -> bool: 82 | """ 83 | Set bco1 attribute of component 84 | 85 | :param number: The background color number 86 | :type number: int 87 | 88 | :returns: True on success, false otherwise 89 | :rtype: bool 90 | """ 91 | cmd = "{}.bco1={}".format(self.name, number) 92 | self._nh.sendCommand(cmd) 93 | cmd = "ref {}".format(self.name) 94 | self._nh.sendCommand(cmd) 95 | return self._nh.recvRetCommandFinished() 96 | -------------------------------------------------------------------------------- /nextion/nextion_gauge.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexGauge 6 | 7 | Functions to interact with a Nextion Gauge element 8 | """ 9 | 10 | # custom packages 11 | from .common import Common, CommonBackgroundColorMixin, CommonFontMixin, \ 12 | CommonPointerMixin, CommonValueMixin 13 | 14 | 15 | class NexGaugeError(Exception): 16 | """Base class for exceptions in this module.""" 17 | pass 18 | 19 | 20 | class NexGauge(Common, CommonBackgroundColorMixin, CommonFontMixin, 21 | CommonPointerMixin, CommonValueMixin): 22 | """docstring for NexGauge""" 23 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 24 | """ 25 | Init gauge 26 | 27 | :param nh: The Nextion hardware interface object 28 | :type nh: NexHardware 29 | :param pid: The page ID 30 | :type pid: int 31 | :param cid: The component ID 32 | :type cid: int 33 | :param name: The component name 34 | :type name: str 35 | """ 36 | super().__init__(nh, pid, cid, name) 37 | 38 | CommonFontMixin_unsupported_functions = [ 39 | "getFont", 40 | "setFont", 41 | ] 42 | for attr_name in CommonFontMixin_unsupported_functions: 43 | delattr(CommonFontMixin, attr_name) 44 | -------------------------------------------------------------------------------- /nextion/nextion_gpio.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexGpio 6 | 7 | Functions to interact with Nextion GPIOs 8 | """ 9 | 10 | # system packages 11 | from time import sleep 12 | 13 | # custom packages 14 | from .common import Common 15 | 16 | 17 | class NexGpioError(Exception): 18 | """Base class for exceptions in this module.""" 19 | pass 20 | 21 | 22 | class NexGpio(Common): 23 | """docstring for NexGpio""" 24 | INPUT_PULL_UP = 0 # set pin as pull up input 25 | OUTPUT = 2 # set pin as push pull output 26 | INPUT_BINDING = 1 # bind Nextion element to falling edge of signal 27 | PWM = 3 # set pin as PWM output (only GPIO4 and GPIO7) 28 | 29 | def __init__(self, nh) -> None: 30 | """ 31 | Init GPIO 32 | 33 | :param nh: The Nextion hardware interface object 34 | :type nh: NexHardware 35 | """ 36 | super().__init__(nh, pid=-1, cid=-1, name="gpio") 37 | 38 | def pin_mode(self, port: int, mode: int, control_id: int = 0) -> bool: 39 | """ 40 | Set GPIO mode 41 | 42 | :param port: The GPIO port number 43 | :type port: int 44 | :param mode: The GPIO port mode 45 | 0 - Pull on the input 46 | 1 - the control input binding 47 | 2 - Push-pull output 48 | 3 - pwm output 49 | 4 - open mode leakage 50 | :type mode: int 51 | :param control_id: The bound CID of other nextion element 52 | :type control_id: int 53 | 54 | :returns: True on success, false otherwise 55 | :rtype: bool 56 | """ 57 | cmd = "cfgpio {},{},{}".format(port, mode, control_id) 58 | self._nh.sendCommand(cmd) 59 | return self._nh.recvRetCommandFinished() 60 | 61 | def digital_write(self, port: int, value: int) -> bool: 62 | """ 63 | Write a HIGH or LOW value to a digital pin 64 | 65 | :param port: The GPIO port number 66 | :type port: int 67 | :param value: The value (0 or 1) 68 | :type value: int 69 | 70 | :returns: True on success, false otherwise 71 | :rtype: bool 72 | """ 73 | cmd = "pio{}={}".format(port, value) 74 | self._nh.sendCommand(cmd) 75 | return self._nh.recvRetCommandFinished() 76 | 77 | def digital_read(self, port: int) -> int: 78 | """ 79 | Read a HIGH or a LOW value of a digital pin 80 | 81 | :param port: The GPIO port number 82 | :type port: int 83 | 84 | :returns: Value of specified digital pin, either 1 or 0 85 | :rtype: int 86 | """ 87 | cmd = "get pio{}".format(port) 88 | self._nh.sendCommand(cmd) 89 | sleep(0.1) # necessary, data might not be available otherwise 90 | return self._nh.recvRetNumber() 91 | 92 | def analog_write(self, port: int, value: int) -> bool: 93 | """ 94 | Set analog value (PWM wave) to a pin 95 | 96 | :param port: The GPIO port number 97 | :type port: int 98 | :param value: The duty cycle value (0-100) 99 | :type value: int 100 | 101 | :returns: True on success, false otherwise 102 | :rtype: bool 103 | """ 104 | cmd = "pwm{}={}".format(port, value) 105 | self._nh.sendCommand(cmd) 106 | return self._nh.recvRetCommandFinished() 107 | 108 | def set_pwmfreq(self, value: int) -> bool: 109 | """ 110 | Set the PWM output frequency for all pins 111 | 112 | :param value: The PWM frequency (1-65535) 113 | :type value: int 114 | 115 | :returns: True on success, false otherwise 116 | :rtype: bool 117 | """ 118 | cmd = "pwmf={}".format(value) 119 | self._nh.sendCommand(cmd) 120 | return self._nh.recvRetCommandFinished() 121 | 122 | def get_pwmfreq(self) -> int: 123 | """ 124 | Get the PWM output frequency 125 | 126 | :returns: The PWM frequency. 127 | :rtype: int 128 | """ 129 | cmd = "get pwmf" 130 | self._nh.sendCommand(cmd) 131 | sleep(0.1) # necessary, data might not be available otherwise 132 | return self._nh.recvRetNumber() 133 | -------------------------------------------------------------------------------- /nextion/nextion_number.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexNumber 6 | 7 | Functions to interact with a Nextion Number element 8 | """ 9 | 10 | # system packages 11 | from time import sleep 12 | 13 | # custom packages 14 | from .common import Common, CommonBackgroundColorMixin, CommonFontMixin, \ 15 | CommonPositionMixin, CommonValueMixin 16 | 17 | 18 | class NexNumberError(Exception): 19 | """Base class for exceptions in this module.""" 20 | pass 21 | 22 | 23 | class NexNumber(Common, CommonBackgroundColorMixin, CommonFontMixin, 24 | CommonPositionMixin, CommonValueMixin): 25 | """docstring for NexNumber""" 26 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 27 | """ 28 | Init number 29 | 30 | :param nh: The Nextion hardware interface object 31 | :type nh: NexHardware 32 | :param pid: The page ID 33 | :type pid: int 34 | :param cid: The component ID 35 | :type cid: int 36 | :param name: The component name 37 | :type name: str 38 | """ 39 | super().__init__(nh, pid, cid, name) 40 | 41 | def Get_number_length(self) -> int: 42 | """ 43 | Get length attribute of component 44 | 45 | :returns: The number length 46 | :rtype: int 47 | """ 48 | cmd = "get {}.lenth".format(self.name) 49 | self._nh.sendCommand(cmd) 50 | sleep(0.1) # necessary, data might not be available otherwise 51 | return self._nh.recvRetNumber() 52 | 53 | def Set_number_length(self, number: int) -> bool: 54 | """ 55 | Set length attribute of component 56 | 57 | :param number: The number length 58 | :type number: int 59 | 60 | :returns: True on success, false otherwise 61 | :rtype: bool 62 | """ 63 | cmd = "{}.lenth={}".format(self.name, number) 64 | self._nh.sendCommand(cmd) 65 | cmd = "ref {}".format(self.name) 66 | self._nh.sendCommand(cmd) 67 | return self._nh.recvRetCommandFinished() 68 | -------------------------------------------------------------------------------- /nextion/nextion_page.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexPage 6 | 7 | Functions to interact with a Nextion Page element 8 | """ 9 | 10 | # custom packages 11 | from .common import Common 12 | 13 | 14 | class NexPageError(Exception): 15 | """Base class for exceptions in this module.""" 16 | pass 17 | 18 | 19 | class NexPage(Common): 20 | """docstring for NexPage""" 21 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 22 | """ 23 | Init page 24 | 25 | :param nh: The Nextion hardware interface object 26 | :type nh: NexHardware 27 | :param pid: The page ID 28 | :type pid: int 29 | :param cid: The component ID 30 | :type cid: int 31 | :param name: The component name 32 | :type name: str 33 | """ 34 | super().__init__(nh, pid, cid, name) 35 | 36 | def show(self) -> bool: 37 | """ 38 | Show itself 39 | 40 | :returns: True on success, false otherwise 41 | :rtype: bool 42 | """ 43 | cmd = "page {}".format(self.name) 44 | self._nh.sendCommand(cmd) 45 | return self._nh.recvRetCommandFinished() 46 | -------------------------------------------------------------------------------- /nextion/nextion_progressbar.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexProgressBar 6 | 7 | Functions to interact with a Nextion Progressbar element 8 | """ 9 | 10 | # custom packages 11 | from .common import Common, CommonBackgroundColorMixin, CommonFontMixin, \ 12 | CommonValueMixin 13 | 14 | 15 | class NexProgressBarError(Exception): 16 | """Base class for exceptions in this module.""" 17 | pass 18 | 19 | 20 | class NexProgressBar(Common, CommonBackgroundColorMixin, CommonFontMixin, 21 | CommonValueMixin): 22 | """docstring for NexProgressBar""" 23 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 24 | """ 25 | Init progressbar 26 | 27 | :param nh: The Nextion hardware interface object 28 | :type nh: NexHardware 29 | :param pid: The page ID 30 | :type pid: int 31 | :param cid: The component ID 32 | :type cid: int 33 | :param name: The component name 34 | :type name: str 35 | """ 36 | super().__init__(nh, pid, cid, name) 37 | 38 | CommonFontMixin_unsupported_functions = [ 39 | "getFont", 40 | "setFont", 41 | ] 42 | for attr_name in CommonFontMixin_unsupported_functions: 43 | delattr(CommonFontMixin, attr_name) 44 | -------------------------------------------------------------------------------- /nextion/nextion_radio.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexRadio 6 | 7 | Functions to interact with a Nextion Radio element 8 | """ 9 | 10 | # custom packages 11 | from .common import Common, CommonBackgroundColorMixin, CommonFontMixin, \ 12 | CommonValueMixin 13 | 14 | 15 | class NexRadioError(Exception): 16 | """Base class for exceptions in this module.""" 17 | pass 18 | 19 | 20 | class NexRadio(Common, CommonBackgroundColorMixin, CommonFontMixin, 21 | CommonValueMixin): 22 | """docstring for NexRadio""" 23 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 24 | """ 25 | Init radio 26 | 27 | :param nh: The Nextion hardware interface object 28 | :type nh: NexHardware 29 | :param pid: The page ID 30 | :type pid: int 31 | :param cid: The component ID 32 | :type cid: int 33 | :param name: The component name 34 | :type name: str 35 | """ 36 | super().__init__(nh, pid, cid, name) 37 | 38 | CommonFontMixin_unsupported_functions = [ 39 | "getFont", 40 | "setFont", 41 | ] 42 | for attr_name in CommonFontMixin_unsupported_functions: 43 | delattr(CommonFontMixin, attr_name) 44 | -------------------------------------------------------------------------------- /nextion/nextion_rtc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexRtc 6 | 7 | Functions to interact with Nextion RTC 8 | """ 9 | 10 | # system packages 11 | from time import sleep 12 | 13 | # custom packages 14 | from .common import Common 15 | from .typing import List, Optional, Union 16 | 17 | 18 | class NexRtcError(Exception): 19 | """Base class for exceptions in this module.""" 20 | pass 21 | 22 | 23 | class NexRtc(Common): 24 | """docstring for NexRtc""" 25 | def __init__(self, nh) -> None: 26 | """ 27 | Init RTC 28 | 29 | :param nh: The Nextion hardware interface object 30 | :type nh: NexHardware 31 | """ 32 | super().__init__(nh, pid=-1, cid=-1, name="rtc") 33 | 34 | self._time_types = ["year", "mon", "day", "hour", "min", "sec", "week"] 35 | 36 | @property 37 | def time_types(self) -> List[str]: 38 | """ 39 | Get available time types 40 | 41 | :returns: Requestable time types from RTC 42 | :rtype: List[str] 43 | """ 44 | return self._time_types 45 | 46 | def write_rtc_time(self, *args, **kwargs) -> bool: 47 | """ 48 | Write time to RTC 49 | 50 | :param time: The time to set the RTC 51 | :type time: Union[str, List[int]] 52 | :param time_type: The type of time to change 53 | :type time_type: str 54 | 55 | :returns: True on success, False otherwise 56 | :rtype: bool 57 | """ 58 | if (len(args) + len(kwargs) == 1): 59 | # only a time is given 60 | if len(args): 61 | time = args[0] 62 | else: 63 | time = kwargs["time"] 64 | if isinstance(time, str) and len(time) >= 19: 65 | # "2016,11,25,12,34,50" 66 | year = time[0:4] 67 | month = time[5:7] 68 | day = time[8:10] 69 | hour = time[11:13] 70 | minute = time[14:16] 71 | second = time[17:19] 72 | elif (isinstance(time, list) and 73 | all(isinstance(x, int) for x in time)): 74 | # [2016, 11, 25, 12, 34, 50] 75 | year = time[0] 76 | month = time[1] 77 | day = time[2] 78 | hour = time[3] 79 | minute = time[4] 80 | second = time[5] 81 | else: 82 | raise NexRtcError("Time can either be given as '{}' or '{}'". 83 | format("2016,11,25,12,34,50", 84 | [2016, 11, 25, 12, 34, 50])) 85 | 86 | self._nh._logger.debug( 87 | "Timestamp (ISO8601): {}-{}-{}T{}:{}:{}".format( 88 | year, month, day, hour, minute, second)) 89 | 90 | cmd = "rtc0={}".format(year) 91 | self._nh.sendCommand(cmd) 92 | self._nh.recvRetCommandFinished() 93 | 94 | cmd = "rtc1={}".format(month) 95 | self._nh.sendCommand(cmd) 96 | self._nh.recvRetCommandFinished() 97 | 98 | cmd = "rtc2={}".format(day) 99 | self._nh.sendCommand(cmd) 100 | self._nh.recvRetCommandFinished() 101 | 102 | cmd = "rtc3={}".format(hour) 103 | self._nh.sendCommand(cmd) 104 | self._nh.recvRetCommandFinished() 105 | 106 | cmd = "rtc4={}".format(minute) 107 | self._nh.sendCommand(cmd) 108 | self._nh.recvRetCommandFinished() 109 | 110 | cmd = "rtc5={}".format(second) 111 | self._nh.sendCommand(cmd) 112 | return self._nh.recvRetCommandFinished() 113 | elif (len(args) + len(kwargs) == 2): 114 | # time_type is given as well 115 | if len(kwargs) == 2: 116 | time_type = kwargs['time_type'] 117 | time = kwargs['time'] 118 | else: 119 | if len(args) == 2: 120 | time_type = args[0] 121 | time = args[1] 122 | else: 123 | raise NexRtcError("Either use keyword or positional args") 124 | 125 | self._nh._logger.debug("Set '{}' to '{}'".format(time_type, time)) 126 | rtc_index = self.time_types.index(time_type.lower()) 127 | 128 | cmd = "rtc{}={}".format(rtc_index, time) 129 | self._nh.sendCommand(cmd) 130 | return self._nh.recvRetCommandFinished() 131 | else: 132 | raise NexRtcError("Only two args are allowed") 133 | 134 | def read_rtc_time(self, 135 | return_type: str, 136 | length: Optional[int] = 22) -> Union[str, List[int]]: 137 | """ 138 | Read RTC time 139 | 140 | :param return_type: The return type, choose "int", "str" or from 141 | ["year", "mon", "day", "hour", "min", "sec", 142 | "week"] 143 | :type return_type: str 144 | :param length: The length 145 | :type length: Optional[int] 146 | 147 | :returns: RTC time 148 | :rtype: Union[str, List[int]] 149 | """ 150 | return_type = return_type.lower() 151 | 152 | if return_type in ["str", "int"]: 153 | cmd = "get rtc0" 154 | self._nh.sendCommand(cmd) 155 | sleep(0.1) # necessary, data might not be available otherwise 156 | year = self._nh.recvRetNumber() 157 | 158 | cmd = "get rtc1" 159 | self._nh.sendCommand(cmd) 160 | sleep(0.1) # necessary, data might not be available otherwise 161 | month = self._nh.recvRetNumber() 162 | 163 | cmd = "get rtc2" 164 | self._nh.sendCommand(cmd) 165 | sleep(0.1) # necessary, data might not be available otherwise 166 | day = self._nh.recvRetNumber() 167 | 168 | cmd = "get rtc3" 169 | self._nh.sendCommand(cmd) 170 | sleep(0.1) # necessary, data might not be available otherwise 171 | hour = self._nh.recvRetNumber() 172 | 173 | cmd = "get rtc4" 174 | self._nh.sendCommand(cmd) 175 | sleep(0.1) # necessary, data might not be available otherwise 176 | minute = self._nh.recvRetNumber() 177 | 178 | cmd = "get rtc5" 179 | self._nh.sendCommand(cmd) 180 | sleep(0.1) # necessary, data might not be available otherwise 181 | second = self._nh.recvRetNumber() 182 | 183 | cmd = "get rtc6" 184 | self._nh.sendCommand(cmd) 185 | sleep(0.1) # necessary, data might not be available otherwise 186 | week = self._nh.recvRetNumber() 187 | 188 | time_buf = [year, month, day, hour, minute, second, week] 189 | 190 | if return_type == "str": 191 | time_string = ("{}/{}/{} {}:{}:{} {}". 192 | format(year, month, day, hour, minute, second, 193 | week)) 194 | if length >= 22: 195 | return time_string 196 | else: 197 | return time_string[0:length] 198 | elif return_type == "int": 199 | if length >= 7: 200 | return time_buf 201 | else: 202 | return time_buf[0:length] 203 | elif return_type in self.time_types: 204 | rtc_index = self.time_types.index(return_type) 205 | cmd = "get rtc{}".format(rtc_index) 206 | self._nh.sendCommand(cmd) 207 | sleep(0.1) # necessary, data might not be available otherwise 208 | return self._nh.recvRetNumber() 209 | else: 210 | raise NexRtcError("RTC time can only be returned as '{}' or '{}'" 211 | "or chosen from {}". 212 | format("str", "int", self.time_types)) 213 | -------------------------------------------------------------------------------- /nextion/nextion_slider.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexSlider 6 | 7 | Functions to interact with a Nextion Slider element 8 | """ 9 | 10 | # system packages 11 | from time import sleep 12 | 13 | # custom packages 14 | from .common import Common, CommonBackgroundColorMixin, CommonFontMixin, \ 15 | CommonPointerMixin, CommonValueMixin 16 | 17 | 18 | class NexSliderError(Exception): 19 | """Base class for exceptions in this module.""" 20 | pass 21 | 22 | 23 | class NexSlider(Common, CommonBackgroundColorMixin, CommonFontMixin, 24 | CommonPointerMixin, CommonValueMixin): 25 | """docstring for NexSlider""" 26 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 27 | """ 28 | Init slider 29 | 30 | :param nh: The Nextion hardware interface object 31 | :type nh: NexHardware 32 | :param pid: The page ID 33 | :type pid: int 34 | :param cid: The component ID 35 | :type cid: int 36 | :param name: The component name 37 | :type name: str 38 | """ 39 | super().__init__(nh, pid, cid, name) 40 | 41 | def Get_cursor_height_hig(self) -> int: 42 | """ 43 | Get cursor hig attribute of component 44 | 45 | :returns: The cursor height. 46 | :rtype: number 47 | """ 48 | cmd = "get {}.hig".format(self.name) 49 | self._nh.sendCommand(cmd) 50 | sleep(0.1) # necessary, data might not be available otherwise 51 | return self._nh.recvRetNumber() 52 | 53 | def Set_cursor_height_hig(self, number: int) -> bool: 54 | """ 55 | Set cursor hig attribute of component 56 | 57 | :param number: The number 58 | :type number: int 59 | 60 | :returns: True on success, false otherwise 61 | :rtype: bool 62 | """ 63 | cmd = "{}.hig={}".format(self.name, number) 64 | self._nh.sendCommand(cmd) 65 | cmd = "ref {}".format(self.name) 66 | self._nh.sendCommand(cmd) 67 | return self._nh.recvRetCommandFinished() 68 | 69 | def getMaxval(self) -> int: 70 | """ 71 | Get the maxval attribute of the component 72 | 73 | :returns: The maxval 74 | :rtype: int 75 | """ 76 | cmd = "get {}.maxval".format(self.name) 77 | self._nh.sendCommand(cmd) 78 | sleep(0.1) # necessary, data might not be available otherwise 79 | return self._nh.recvRetNumber() 80 | 81 | def setMaxval(self, number: int) -> bool: 82 | """ 83 | Set the maxval attribute of the component 84 | 85 | :param number: The new maxval 86 | :type number: int 87 | 88 | :returns: True on success, false otherwise 89 | :rtype: bool 90 | """ 91 | cmd = "{}.maxval={}".format(self.name, number) 92 | self._nh.sendCommand(cmd) 93 | cmd = "ref {}".format(self.name) 94 | self._nh.sendCommand(cmd) 95 | return self._nh.recvRetCommandFinished() 96 | 97 | def getMinval(self) -> int: 98 | """ 99 | Get the minval attribute of the component 100 | 101 | :returns: The minval 102 | :rtype: int 103 | """ 104 | cmd = "get {}.minval".format(self.name) 105 | self._nh.sendCommand(cmd) 106 | sleep(0.1) # necessary, data might not be available otherwise 107 | return self._nh.recvRetNumber() 108 | 109 | def setMinval(self, number: int) -> bool: 110 | """ 111 | Set the minval attribute of the component 112 | 113 | :param number: The new minval 114 | :type number: int 115 | 116 | :returns: True on success, false otherwise 117 | :rtype: bool 118 | """ 119 | cmd = "{}.minval={}".format(self.name, number) 120 | self._nh.sendCommand(cmd) 121 | cmd = "ref {}".format(self.name) 122 | self._nh.sendCommand(cmd) 123 | return self._nh.recvRetCommandFinished() 124 | -------------------------------------------------------------------------------- /nextion/nextion_text.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexText 6 | 7 | Functions to interact with a Nextion Text element 8 | """ 9 | 10 | # custom packages 11 | from .common import Common, CommonBackgroundColorMixin, CommonFontMixin, \ 12 | CommonPositionMixin, CommonTextMixin 13 | 14 | 15 | class NexTextError(Exception): 16 | """Base class for exceptions in this module.""" 17 | pass 18 | 19 | 20 | class NexText(Common, CommonBackgroundColorMixin, CommonFontMixin, 21 | CommonPositionMixin, CommonTextMixin): 22 | """docstring for NexText""" 23 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 24 | """ 25 | Init text 26 | 27 | :param nh: The Nextion hardware interface object 28 | :type nh: NexHardware 29 | :param pid: The page ID 30 | :type pid: int 31 | :param cid: The component ID 32 | :type cid: int 33 | :param name: The component name 34 | :type name: str 35 | """ 36 | super().__init__(nh, pid, cid, name) 37 | -------------------------------------------------------------------------------- /nextion/nextion_upload.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexUpload 6 | 7 | Functions to download TFT file to Nextion display 8 | """ 9 | 10 | # system packages 11 | from os import listdir, stat 12 | from time import sleep, ticks_diff, ticks_ms 13 | 14 | # custom packages 15 | from .common import Common 16 | 17 | 18 | class NexUploadError(Exception): 19 | """Base class for exceptions in this module.""" 20 | pass 21 | 22 | 23 | class NexUpload(Common): 24 | """docstring for NexUpload""" 25 | def __init__(self, nh, file_name: str, download_baudrate: int) -> None: 26 | """ 27 | Init upload 28 | 29 | :param nh: The Nextion hardware interface object 30 | :type nh: NexHardware 31 | :param file_name: The update filename 32 | :type file_name: str 33 | :param download_baudrate: The download baudrate 34 | :type download_baudrate: int 35 | """ 36 | super().__init__(nh, pid=-1, cid=-1, name="upload") 37 | 38 | self._file_name = file_name 39 | self._file_size = 0 40 | self._download_baudrate = download_baudrate 41 | 42 | if not self._checkFile(): 43 | raise NexUploadError("No such update file found: '{}'". 44 | format(file_name)) 45 | 46 | @property 47 | def file_name(self) -> str: 48 | """ 49 | Get the update filename 50 | 51 | :returns: Filename of update file 52 | :rtype: str 53 | """ 54 | return self._file_name 55 | 56 | @property 57 | def file_size(self) -> int: 58 | """ 59 | Get the update filesize 60 | 61 | :returns: Filesize of update file in bytes 62 | :rtype: int 63 | """ 64 | return self._file_size 65 | 66 | @file_size.setter 67 | def file_size(self, value: int) -> None: 68 | """ 69 | Filesize of update file 70 | 71 | :param value: The filesize 72 | :type value: int 73 | """ 74 | self._file_size = value 75 | 76 | @property 77 | def download_baudrate(self) -> int: 78 | """ 79 | Get the download baudrate 80 | 81 | :returns: Download baudrate for communication with Nextion display 82 | :rtype: int 83 | """ 84 | return self._download_baudrate 85 | 86 | @download_baudrate.setter 87 | def download_baudrate(self, value: int) -> None: 88 | """ 89 | Set download baudrate 90 | 91 | :param value: The baudrate value 92 | :type value: int 93 | """ 94 | self._download_baudrate = value 95 | 96 | def upload(self) -> bool: 97 | """ 98 | Perform update of Nextion display content 99 | 100 | :returns: True on success, raise NexUploadError otherwise 101 | :rtype: bool 102 | """ 103 | if not self._checkFile(): 104 | raise NexUploadError("File not found") 105 | 106 | if self._getBaudrate() == 0: 107 | raise NexUploadError("Get baudrate error") 108 | 109 | if not self._setDownloadBaudrate(self.download_baudrate): 110 | raise NexUploadError("Modify baudrate error") 111 | 112 | if not self._downloadTftFile(): 113 | raise NexUploadError("Download file error") 114 | 115 | self._nh._logger.debug("Download ok") 116 | return True 117 | 118 | def _checkFile(self) -> bool: 119 | """ 120 | Check existance of specified TFT file 121 | 122 | :returns: True on success, False otherwise 123 | :rtype: bool 124 | """ 125 | result = False 126 | if self._exists(self.file_name): 127 | # https://docs.python.org/3/library/os.html#os.stat 128 | info = stat(self.file_name) 129 | self.file_size = info[6] 130 | self._nh._logger.debug("TFT file size is '{}' bytes". 131 | format(self.file_size)) 132 | self._nh._logger.debug("File check ok") 133 | result = True 134 | else: 135 | self._nh._logger.debug("File '{}' does not exist". 136 | format(self.file_name)) 137 | return result 138 | 139 | def _getBaudrate(self) -> int: 140 | """ 141 | Get communication baudrate with Nextion display 142 | 143 | :returns: The baudrate 144 | :rtype: int 145 | """ 146 | baudrate_array = [115200, 19200, 9600, 57600, 38400, 4800, 2400] 147 | _baudrate = 0 148 | 149 | for baudrate in baudrate_array: 150 | self._nh._logger.debug("Checking connection with '{}' baud". 151 | format(baudrate)) 152 | 153 | if self._searchBaudrate(baudrate): 154 | _baudrate = baudrate 155 | self._nh._logger.debug("Success, baudrate set to '{}' baud". 156 | format(_baudrate)) 157 | return _baudrate 158 | 159 | return _baudrate 160 | 161 | def _searchBaudrate(self, baudrate: int) -> bool: 162 | """ 163 | Find suitable download baudrate 164 | 165 | :param baudrate: The baudrate 166 | :type baudrate: int 167 | 168 | :returns: True on success, False otherwise 169 | :rtype: bool 170 | """ 171 | self._nh._baudrate = baudrate 172 | self._nh._uart_init() 173 | self._nh.sendCommand("") 174 | self._nh.sendCommand("connect") 175 | sleep(0.1) # necessary, data might not be available otherwise 176 | response = self._recvRetString() 177 | self._nh._logger.debug("_searchBaudrate response for '{}' baud: {}". 178 | format(baudrate, response)) 179 | 180 | if "comok" in response: 181 | return True 182 | 183 | return False 184 | 185 | def _setDownloadBaudrate(self, baudrate: int) -> bool: 186 | """ 187 | Set the download baudrate 188 | 189 | :param baudrate: The baudrate 190 | :type baudrate: int 191 | 192 | :returns: True on success, False otherwise 193 | :rtype: bool 194 | """ 195 | cmd = "whmi-wri {},{},0".format(self.file_size, baudrate) 196 | self._nh._logger.debug("Set download baudrate cmd: '{}'".format(cmd)) 197 | 198 | self._nh.sendCommand("") 199 | self._nh.sendCommand(cmd) 200 | sleep(0.05) 201 | self._nh._baudrate = baudrate 202 | self._nh._uart_init() 203 | response = self._recvRetString(500) 204 | self._nh._logger.debug( 205 | "Set download baudrate response: '{}'".format(response)) 206 | if (0x05).to_bytes(1, 'little') in response: 207 | return True 208 | return False 209 | 210 | def _downloadTftFile(self) -> bool: 211 | """ 212 | Download TFT file to Nextion display 213 | 214 | :returns: True on success, False otherwise 215 | :rtype: bool 216 | """ 217 | # send chunks of 4096 218 | file_content = bytearray(4096) 219 | 220 | with open(self.file_name, 'rb') as update_file: 221 | while True: 222 | data_size = update_file.readinto(file_content) 223 | 224 | if not data_size: 225 | self._nh._logger.debug("Reached EOF, update finished") 226 | break 227 | 228 | self._nh._uart.write(file_content) 229 | 230 | response = self._recvRetString(500) 231 | # self._nh._logger.debug("File download response: '{}'". 232 | # format(response)) 233 | 234 | if (0x05).to_bytes(1, 'little') in response: 235 | # send next chunk 236 | pass 237 | else: 238 | return False 239 | 240 | return True 241 | 242 | def _recvRetString(self, timeout: int = 100) -> bytearray: 243 | """ 244 | Receive a string 245 | 246 | :param timeout: The communication timeout 247 | :type timeout: int 248 | 249 | :returns: Received response 250 | :rtype: bytearray 251 | """ 252 | buf = bytearray(70) 253 | start_ms = ticks_ms() 254 | 255 | # stay inside this while loop at least for the timeout time 256 | while (ticks_diff(ticks_ms(), start_ms) <= timeout): 257 | # check amount of available characters 258 | while self._nh._uart.any(): 259 | # can not decode received data here, as it might not be UTF-8 260 | self._nh._uart.readinto(buf) 261 | 262 | return buf 263 | 264 | def _exists(self, path: str) -> bool: 265 | """ 266 | Check existance of file at given path. 267 | 268 | :param path: The path to the file 269 | :type path: str 270 | 271 | :returns: Existance of file 272 | :rtype: bool 273 | """ 274 | result = False 275 | 276 | path_to_file_list = path.split('/') 277 | # ['path', 'to', 'some', 'file.txt'] 278 | 279 | root_path = '' 280 | this_path = root_path 281 | 282 | for ele in path_to_file_list[:-1]: 283 | files_in_dir = listdir(this_path) 284 | # print('Files in {}: {}'.format(this_path, files_in_dir)) 285 | 286 | if ele in files_in_dir: 287 | # print('"{}" found in "{}"'.format(ele, files_in_dir)) 288 | 289 | if this_path == '': 290 | this_path += '{}'.format(ele) 291 | else: 292 | this_path += '/{}'.format(ele) 293 | 294 | # print('Next folder to be checked is: {}'.format(this_path)) 295 | else: 296 | return result 297 | 298 | files_in_dir = listdir(this_path) 299 | if path_to_file_list[-1] in files_in_dir: 300 | # print('File "{}" found in "{}"'. 301 | # format(path_to_file_list[-1], this_path)) 302 | return True 303 | else: 304 | return False 305 | -------------------------------------------------------------------------------- /nextion/nextion_variable.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexVariable 6 | 7 | Functions to interact with a Nextion Variable element 8 | """ 9 | 10 | # custom packages 11 | from .common import Common, CommonTextMixin, CommonValueMixin 12 | 13 | 14 | class NexVariableError(Exception): 15 | """Base class for exceptions in this module.""" 16 | pass 17 | 18 | 19 | class NexVariable(Common, CommonTextMixin, CommonValueMixin): 20 | """docstring for NexVariable""" 21 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 22 | """ 23 | Init variable 24 | 25 | :param nh: The Nextion hardware interface object 26 | :type nh: NexHardware 27 | :param pid: The page ID 28 | :type pid: int 29 | :param cid: The component ID 30 | :type cid: int 31 | :param name: The component name 32 | :type name: str 33 | """ 34 | super().__init__(nh, pid, cid, name) 35 | -------------------------------------------------------------------------------- /nextion/nextion_waveform.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | NexWaveform 6 | 7 | Functions to interact with a Nextion Waveform element 8 | """ 9 | 10 | # system packages 11 | from time import sleep 12 | 13 | # custom packages 14 | from .common import Common, CommonBackgroundColorMixin, CommonFontMixin 15 | 16 | 17 | class NexWaveformError(Exception): 18 | """Base class for exceptions in this module.""" 19 | pass 20 | 21 | 22 | class NexWaveform(Common, CommonBackgroundColorMixin, CommonFontMixin): 23 | """docstring for NexWaveform""" 24 | def __init__(self, nh, pid: int, cid: int, name: str) -> None: 25 | """ 26 | Init waveform 27 | 28 | :param nh: The Nextion hardware interface object 29 | :type nh: NexHardware 30 | :param pid: The page ID 31 | :type pid: int 32 | :param cid: The component ID 33 | :type cid: int 34 | :param name: The component name 35 | :type name: str 36 | """ 37 | super().__init__(nh, pid, cid, name) 38 | 39 | def addValue(self, ch: int, number: int) -> bool: 40 | """ 41 | Add value to waveform 42 | 43 | :param ch: Channel of waveform (0-3) 44 | :type ch: int 45 | :param number: The value to add 46 | :type number: int 47 | 48 | :returns: True on success, false otherwise 49 | :rtype: bool 50 | """ 51 | if ch > 3: 52 | self._nh._logger.debug("Only channels (0-3) supported by waveform") 53 | return False 54 | 55 | cmd = "add {},{},{}".format(self.cid, ch, number) 56 | self._nh.sendCommand(cmd) 57 | return True 58 | 59 | def clearChannel(self, ch: int) -> bool: 60 | """ 61 | Clear a channel of the waveform 62 | 63 | :param ch: The channel to clear or 255 for all channels 64 | :type ch: int 65 | 66 | :returns: True on success, false otherwise 67 | :rtype: bool 68 | """ 69 | if (ch > 3) and (ch != 255): 70 | self._nh._logger.debug("Only the channels (0-3) or all channels " 71 | "at once (255) can be cleared") 72 | return False 73 | 74 | cmd = "cle {},{}".format(self.cid, ch) 75 | self._nh.sendCommand(cmd) 76 | return self._nh.recvRetCommandFinished() 77 | 78 | def Get_grid_color_gdc(self) -> int: 79 | """ 80 | Get grid color attribute of component 81 | 82 | :returns: The grid color 83 | :rtype: int 84 | """ 85 | cmd = "get {}.gdc".format(self.name) 86 | self._nh.sendCommand(cmd) 87 | sleep(0.1) # necessary, data might not be available otherwise 88 | return self._nh.recvRetNumber() 89 | 90 | def Set_grid_color_gdc(self, number: int) -> bool: 91 | """ 92 | Set grid color attribute of component 93 | 94 | :param number: The grid color number 95 | :type number: int 96 | 97 | :returns: True on success, false otherwise 98 | :rtype: bool 99 | """ 100 | cmd = "{}.gdc={}".format(self.name, number) 101 | self._nh.sendCommand(cmd) 102 | cmd = "ref {}".format(self.name) 103 | self._nh.sendCommand(cmd) 104 | return self._nh.recvRetCommandFinished() 105 | 106 | def Get_grid_width_gdw(self) -> int: 107 | """ 108 | Get grid width attribute of component 109 | 110 | :returns: The grid width 111 | :rtype: int 112 | """ 113 | cmd = "get {}.gdw".format(self.name) 114 | self._nh.sendCommand(cmd) 115 | sleep(0.1) # necessary, data might not be available otherwise 116 | return self._nh.recvRetNumber() 117 | 118 | def Set_grid_width_gdw(self, number: int) -> bool: 119 | """ 120 | Set grid width attribute of component 121 | 122 | :param number: The grid width 123 | :type number: int 124 | 125 | :returns: True on success, false otherwise 126 | :rtype: bool 127 | """ 128 | cmd = "{}.gdw={}".format(self.name, number) 129 | self._nh.sendCommand(cmd) 130 | cmd = "ref {}".format(self.name) 131 | self._nh.sendCommand(cmd) 132 | return self._nh.recvRetCommandFinished() 133 | 134 | def Get_grid_height_gdh(self) -> int: 135 | """ 136 | Get grid height attribute of component 137 | 138 | :returns: The grid height 139 | :rtype: int 140 | """ 141 | cmd = "get {}.gdh".format(self.name) 142 | self._nh.sendCommand(cmd) 143 | sleep(0.1) # necessary, data might not be available otherwise 144 | return self._nh.recvRetNumber() 145 | 146 | def Set_grid_height_gdh(self, number: int) -> bool: 147 | """ 148 | Set grid height attribute of component 149 | 150 | :param number: The grid height 151 | :type number: int 152 | 153 | :returns: True on success, false otherwise 154 | :rtype: bool 155 | """ 156 | cmd = "{}.gdh={}".format(self.name, number) 157 | self._nh.sendCommand(cmd) 158 | cmd = "ref {}".format(self.name) 159 | self._nh.sendCommand(cmd) 160 | return self._nh.recvRetCommandFinished() 161 | 162 | def Get_channel_0_color_pco0(self) -> int: 163 | """ 164 | Get channel0 pco0 attribute of component 165 | 166 | :returns: The channel0 pco0 167 | :rtype: int 168 | """ 169 | return self.Get_font_color_pco() 170 | 171 | def Set_channel_0_color_pco0(self, number: int) -> int: 172 | """ 173 | Set channel0 pco0 attribute of component 174 | 175 | :param number: The channel0 pco0 176 | :type number: int 177 | 178 | :returns: True on success, false otherwise 179 | :rtype: bool 180 | """ 181 | return self.Set_font_color_pco(number) 182 | -------------------------------------------------------------------------------- /nextion/typing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | Fake classes of typing module. 6 | 7 | https://github.com/micropython/micropython-lib/issues/190 8 | 9 | https://github.com/micropython/micropython-lib/blob/3d779b8ceab5b65b9f70accbcbb15ab3509eceb7/typing/typing.py 10 | """ 11 | 12 | 13 | class _Subscriptable(): 14 | def __getitem__(self, item): 15 | return None 16 | 17 | 18 | _subscriptable = _Subscriptable() 19 | 20 | 21 | class Any: 22 | pass 23 | 24 | 25 | class NoReturn: 26 | pass 27 | 28 | 29 | class ClassVar: 30 | pass 31 | 32 | 33 | Union = _subscriptable 34 | 35 | 36 | Optional = _subscriptable 37 | 38 | 39 | class Generic: 40 | pass 41 | 42 | 43 | class NamedTuple: 44 | pass 45 | 46 | 47 | class Hashable: 48 | pass 49 | 50 | 51 | class Awaitable: 52 | pass 53 | 54 | 55 | class Coroutine: 56 | pass 57 | 58 | 59 | class AsyncIterable: 60 | pass 61 | 62 | 63 | class AsyncIterator: 64 | pass 65 | 66 | 67 | class Iterable: 68 | pass 69 | 70 | 71 | class Iterator: 72 | pass 73 | 74 | 75 | class Reversible: 76 | pass 77 | 78 | 79 | class Sized: 80 | pass 81 | 82 | 83 | class Container: 84 | pass 85 | 86 | 87 | class Collection: 88 | pass 89 | 90 | 91 | # class Callable: 92 | # pass 93 | Callable = _subscriptable 94 | 95 | 96 | class AbstractSet: 97 | pass 98 | 99 | 100 | class MutableSet: 101 | pass 102 | 103 | 104 | class Mapping: 105 | pass 106 | 107 | 108 | class MutableMapping: 109 | pass 110 | 111 | 112 | class Sequence: 113 | pass 114 | 115 | 116 | class MutableSequence: 117 | pass 118 | 119 | 120 | class ByteString: 121 | pass 122 | 123 | 124 | Tuple = _subscriptable 125 | 126 | 127 | List = _subscriptable 128 | 129 | 130 | class Deque: 131 | pass 132 | 133 | 134 | class Set: 135 | pass 136 | 137 | 138 | class dict_keys: 139 | pass 140 | 141 | 142 | class FrozenSet: 143 | pass 144 | 145 | 146 | class MappingView: 147 | pass 148 | 149 | 150 | class KeysView: 151 | pass 152 | 153 | 154 | class ItemsView: 155 | pass 156 | 157 | 158 | class ValuesView: 159 | pass 160 | 161 | 162 | class ContextManager: 163 | pass 164 | 165 | 166 | class AsyncContextManager: 167 | pass 168 | 169 | 170 | Dict = _subscriptable 171 | 172 | 173 | class DefaultDict: 174 | pass 175 | 176 | 177 | class Counter: 178 | pass 179 | 180 | 181 | class ChainMap: 182 | pass 183 | 184 | 185 | class Generator: 186 | pass 187 | 188 | 189 | class AsyncGenerator: 190 | pass 191 | 192 | 193 | class Type: 194 | pass 195 | 196 | 197 | def cast(typ, val): 198 | return val 199 | 200 | 201 | def _overload_dummy(*args, **kwds): 202 | """Helper for @overload to raise when called.""" 203 | raise NotImplementedError( 204 | "You should not call an overloaded function. " 205 | "A series of @overload-decorated functions " 206 | "outside a stub module should always be followed " 207 | "by an implementation that is not @overload-ed." 208 | ) 209 | 210 | 211 | def overload(): 212 | return _overload_dummy 213 | -------------------------------------------------------------------------------- /nextion/ulogging.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | """ 5 | This file has been copied from micropython-lib 6 | 7 | https://github.com/micropython/micropython-lib/blob/7128d423c2e7c0309ac17a1e6ba873b909b24fcc/python-stdlib/logging/logging.py 8 | """ 9 | 10 | try: 11 | from micropython import const # noqa: F401 12 | except ImportError: 13 | 14 | def const(x): 15 | return x 16 | 17 | 18 | import sys 19 | import time 20 | 21 | CRITICAL = const(50) 22 | ERROR = const(40) 23 | WARNING = const(30) 24 | INFO = const(20) 25 | DEBUG = const(10) 26 | NOTSET = const(0) 27 | 28 | _DEFAULT_LEVEL = const(WARNING) 29 | 30 | _level_dict = { 31 | CRITICAL: "CRITICAL", 32 | ERROR: "ERROR", 33 | WARNING: "WARNING", 34 | INFO: "INFO", 35 | DEBUG: "DEBUG", 36 | NOTSET: "NOTSET", 37 | } 38 | 39 | _loggers = {} 40 | _stream = sys.stderr 41 | _default_fmt = "%(levelname)s:%(name)s:%(message)s" 42 | _default_datefmt = "%Y-%m-%d %H:%M:%S" 43 | 44 | 45 | class LogRecord: 46 | def set(self, name, level, message): 47 | self.name = name 48 | self.levelno = level 49 | self.levelname = _level_dict[level] 50 | self.message = message 51 | self.ct = time.time() 52 | self.msecs = int((self.ct - int(self.ct)) * 1000) 53 | self.asctime = None 54 | 55 | 56 | class Handler: 57 | def __init__(self, level=NOTSET): 58 | self.level = level 59 | self.formatter = None 60 | 61 | def close(self): 62 | pass 63 | 64 | def setLevel(self, level): 65 | self.level = level 66 | 67 | def setFormatter(self, formatter): 68 | self.formatter = formatter 69 | 70 | def format(self, record): 71 | return self.formatter.format(record) 72 | 73 | 74 | class StreamHandler(Handler): 75 | def __init__(self, stream=None): 76 | self.stream = _stream if stream is None else stream 77 | self.terminator = "\n" 78 | 79 | def close(self): 80 | if hasattr(self.stream, "flush"): 81 | self.stream.flush() 82 | 83 | def emit(self, record): 84 | if record.levelno >= self.level: 85 | self.stream.write(self.format(record) + self.terminator) 86 | 87 | 88 | class FileHandler(StreamHandler): 89 | def __init__(self, filename, mode="a", encoding="UTF-8"): 90 | super().__init__(stream=open(filename, mode=mode, encoding=encoding)) 91 | 92 | def close(self): 93 | super().close() 94 | self.stream.close() 95 | 96 | 97 | class Formatter: 98 | def __init__(self, fmt=None, datefmt=None): 99 | self.fmt = _default_fmt if fmt is None else fmt 100 | self.datefmt = _default_datefmt if datefmt is None else datefmt 101 | 102 | def usesTime(self): 103 | return "asctime" in self.fmt 104 | 105 | def formatTime(self, datefmt, record): 106 | if hasattr(time, "strftime"): 107 | return time.strftime(datefmt, time.localtime(record.ct)) 108 | return None 109 | 110 | def format(self, record): 111 | if self.usesTime(): 112 | record.asctime = self.formatTime(self.datefmt, record) 113 | return self.fmt % { 114 | "name": record.name, 115 | "message": record.message, 116 | "msecs": record.msecs, 117 | "asctime": record.asctime, 118 | "levelname": record.levelname, 119 | } 120 | 121 | 122 | class Logger: 123 | def __init__(self, name, level=NOTSET): 124 | self.name = name 125 | self.level = level 126 | self.handlers = [] 127 | self.record = LogRecord() 128 | 129 | def setLevel(self, level): 130 | self.level = level 131 | 132 | def isEnabledFor(self, level): 133 | return level >= self.getEffectiveLevel() 134 | 135 | def getEffectiveLevel(self): 136 | return self.level or getLogger().level or _DEFAULT_LEVEL 137 | 138 | def log(self, level, msg, *args): 139 | if self.isEnabledFor(level): 140 | if args: 141 | if isinstance(args[0], dict): 142 | args = args[0] 143 | msg = msg % args 144 | self.record.set(self.name, level, msg) 145 | handlers = self.handlers 146 | if not handlers: 147 | handlers = getLogger().handlers 148 | for h in handlers: 149 | h.emit(self.record) 150 | 151 | def debug(self, msg, *args): 152 | self.log(DEBUG, msg, *args) 153 | 154 | def info(self, msg, *args): 155 | self.log(INFO, msg, *args) 156 | 157 | def warning(self, msg, *args): 158 | self.log(WARNING, msg, *args) 159 | 160 | def error(self, msg, *args): 161 | self.log(ERROR, msg, *args) 162 | 163 | def critical(self, msg, *args): 164 | self.log(CRITICAL, msg, *args) 165 | 166 | def exception(self, msg, *args): 167 | self.log(ERROR, msg, *args) 168 | if hasattr(sys, "exc_info"): 169 | sys.print_exception(sys.exc_info()[1], _stream) 170 | 171 | def addHandler(self, handler): 172 | self.handlers.append(handler) 173 | 174 | def hasHandlers(self): 175 | return len(self.handlers) > 0 176 | 177 | 178 | def getLogger(name=None): 179 | if name is None: 180 | name = "root" 181 | if name not in _loggers: 182 | _loggers[name] = Logger(name) 183 | if name == "root": 184 | basicConfig() 185 | return _loggers[name] 186 | 187 | 188 | def log(level, msg, *args): 189 | getLogger().log(level, msg, *args) 190 | 191 | 192 | def debug(msg, *args): 193 | getLogger().debug(msg, *args) 194 | 195 | 196 | def info(msg, *args): 197 | getLogger().info(msg, *args) 198 | 199 | 200 | def warning(msg, *args): 201 | getLogger().warning(msg, *args) 202 | 203 | 204 | def error(msg, *args): 205 | getLogger().error(msg, *args) 206 | 207 | 208 | def critical(msg, *args): 209 | getLogger().critical(msg, *args) 210 | 211 | 212 | def exception(msg, *args): 213 | getLogger().exception(msg, *args) 214 | 215 | 216 | def shutdown(): 217 | for k, logger in _loggers.items(): 218 | for h in logger.handlers: 219 | h.close() 220 | _loggers.pop(logger, None) 221 | 222 | 223 | def addLevelName(level, name): 224 | _level_dict[level] = name 225 | 226 | 227 | def basicConfig( 228 | filename=None, 229 | filemode="a", 230 | format=None, 231 | datefmt=None, 232 | level=WARNING, 233 | stream=None, 234 | encoding="UTF-8", 235 | force=False, 236 | ): 237 | if "root" not in _loggers: 238 | _loggers["root"] = Logger("root") 239 | 240 | logger = _loggers["root"] 241 | 242 | if force or not logger.handlers: 243 | for h in logger.handlers: 244 | h.close() 245 | logger.handlers = [] 246 | 247 | if filename is None: 248 | handler = StreamHandler(stream) 249 | else: 250 | handler = FileHandler(filename, filemode, encoding) 251 | 252 | handler.setLevel(level) 253 | handler.setFormatter(Formatter(format, datefmt)) 254 | 255 | logger.setLevel(level) 256 | logger.addHandler(handler) 257 | 258 | 259 | if hasattr(sys, "atexit"): 260 | sys.atexit(shutdown) 261 | -------------------------------------------------------------------------------- /nextion/version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | __version_info__ = ('0', '4', '0') 5 | __version__ = '.'.join(__version_info__) 6 | __author__ = 'brainelectronics' 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "urls": [ 3 | [ 4 | "nextion/__init__.py", 5 | "github:brainelectronics/micropython-nextion/nextion/__init__.py" 6 | ], 7 | [ 8 | "nextion/common.py", 9 | "github:brainelectronics/micropython-nextion/nextion/common.py" 10 | ], 11 | [ 12 | "nextion/const.py", 13 | "github:brainelectronics/micropython-nextion/nextion/const.py" 14 | ], 15 | [ 16 | "nextion/nextion_button.py", 17 | "github:brainelectronics/micropython-nextion/nextion/nextion_button.py" 18 | ], 19 | [ 20 | "nextion/nextion_checkbox.py", 21 | "github:brainelectronics/micropython-nextion/nextion/nextion_checkbox.py" 22 | ], 23 | [ 24 | "nextion/nextion_dual_state_button.py", 25 | "github:brainelectronics/micropython-nextion/nextion/nextion_dual_state_button.py" 26 | ], 27 | [ 28 | "nextion/nextion_gauge.py", 29 | "github:brainelectronics/micropython-nextion/nextion/nextion_gauge.py" 30 | ], 31 | [ 32 | "nextion/nextion_gpio.py", 33 | "github:brainelectronics/micropython-nextion/nextion/nextion_gpio.py" 34 | ], 35 | [ 36 | "nextion/nextion_hardware.py", 37 | "github:brainelectronics/micropython-nextion/nextion/nextion_hardware.py" 38 | ], 39 | [ 40 | "nextion/nextion_number.py", 41 | "github:brainelectronics/micropython-nextion/nextion/nextion_number.py" 42 | ], 43 | [ 44 | "nextion/nextion_page.py", 45 | "github:brainelectronics/micropython-nextion/nextion/nextion_page.py" 46 | ], 47 | [ 48 | "nextion/nextion_progressbar.py", 49 | "github:brainelectronics/micropython-nextion/nextion/nextion_progressbar.py" 50 | ], 51 | [ 52 | "nextion/nextion_radio.py", 53 | "github:brainelectronics/micropython-nextion/nextion/nextion_radio.py" 54 | ], 55 | [ 56 | "nextion/nextion_rtc.py", 57 | "github:brainelectronics/micropython-nextion/nextion/nextion_rtc.py" 58 | ], 59 | [ 60 | "nextion/nextion_slider.py", 61 | "github:brainelectronics/micropython-nextion/nextion/nextion_slider.py" 62 | ], 63 | [ 64 | "nextion/nextion_text.py", 65 | "github:brainelectronics/micropython-nextion/nextion/nextion_text.py" 66 | ], 67 | [ 68 | "nextion/nextion_upload.py", 69 | "github:brainelectronics/micropython-nextion/nextion/nextion_upload.py" 70 | ], 71 | [ 72 | "nextion/nextion_variable.py", 73 | "github:brainelectronics/micropython-nextion/nextion/nextion_variable.py" 74 | ], 75 | [ 76 | "nextion/nextion_waveform.py", 77 | "github:brainelectronics/micropython-nextion/nextion/nextion_waveform.py" 78 | ], 79 | [ 80 | "nextion/typing.py", 81 | "github:brainelectronics/micropython-nextion/nextion/typing.py" 82 | ], 83 | [ 84 | "nextion/ulogging.py", 85 | "github:brainelectronics/micropython-nextion/nextion/ulogging.py" 86 | ], 87 | [ 88 | "nextion/version.py", 89 | "github:brainelectronics/micropython-nextion/nextion/version.py" 90 | ] 91 | ], 92 | "deps": [], 93 | "version": "0.15.1" 94 | } -------------------------------------------------------------------------------- /requirements-deploy.txt: -------------------------------------------------------------------------------- 1 | # List external packages here 2 | # Avoid fixed versions 3 | # # to upload package to PyPi or other package hosts 4 | twine>=4.0.1,<5 5 | changelog2version>=0.5.0,<1 6 | 7 | # # to convert markdown to reStructuredText 8 | # m2rr>=0.2.3,<1 9 | # # fix bug in m2rr dependecy definitions 10 | # # see https://github.com/qhua948/m2rr/pull/1 11 | # docutils<=0.18 12 | # mistune<=1 13 | -------------------------------------------------------------------------------- /requirements-test.txt: -------------------------------------------------------------------------------- 1 | # List external packages here 2 | # Avoid fixed versions 3 | flake8>=6.0.0,<7 4 | yamllint>=1.29,<2 5 | setup2upypackage>=0.2.0,<1 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # adafruit-ampy>=1.1.0,<2.0.0 2 | rshell>=0.0.30,<1.0.0 3 | -------------------------------------------------------------------------------- /sdist_upip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | # This module is part of Pycopy https://github.com/pfalcon/pycopy 4 | # and pycopy-lib https://github.com/pfalcon/pycopy-lib, projects to 5 | # create a (very) lightweight full-stack Python distribution. 6 | # 7 | # Copyright (c) 2016-2019 Paul Sokolovsky 8 | # Licence: MIT 9 | # 10 | # This module overrides distutils (also compatible with setuptools) "sdist" 11 | # command to perform pre- and post-processing as required for MicroPython's 12 | # upip package manager. 13 | # 14 | # Preprocessing steps: 15 | # * Creation of Python resource module (R.py) from each top-level package's 16 | # resources. 17 | # Postprocessing steps: 18 | # * Removing metadata files not used by upip (this includes setup.py) 19 | # * Recompressing gzip archive with 4K dictionary size so it can be 20 | # installed even on low-heap targets. 21 | # 22 | import sys 23 | import os 24 | import zlib 25 | import tarfile 26 | import re 27 | import io 28 | 29 | from distutils.filelist import FileList 30 | from setuptools.command.sdist import sdist as _sdist 31 | 32 | 33 | FILTERS = [ 34 | # include, exclude, repeat 35 | (r".+\.egg-info/(PKG-INFO|requires\.txt)", r"setup.py$"), 36 | (r".+\.py$", r"[^/]+$"), 37 | (None, r".+\.egg-info/.+"), 38 | ] 39 | outbuf = io.BytesIO() 40 | 41 | 42 | def gzip_4k(inf, fname): 43 | comp = zlib.compressobj(level=9, wbits=16 + 12) 44 | with open(fname + ".out", "wb") as outf: 45 | while 1: 46 | data = inf.read(1024) 47 | if not data: 48 | break 49 | outf.write(comp.compress(data)) 50 | outf.write(comp.flush()) 51 | os.rename(fname, fname + ".orig") 52 | os.rename(fname + ".out", fname) 53 | 54 | 55 | def filter_tar(name): 56 | fin = tarfile.open(name, "r:gz") 57 | fout = tarfile.open(fileobj=outbuf, mode="w") 58 | for info in fin: 59 | # print(info) 60 | if not "/" in info.name: 61 | continue 62 | fname = info.name.split("/", 1)[1] 63 | include = None 64 | 65 | for inc_re, exc_re in FILTERS: 66 | if include is None and inc_re: 67 | if re.match(inc_re, fname): 68 | include = True 69 | 70 | if include is None and exc_re: 71 | if re.match(exc_re, fname): 72 | include = False 73 | 74 | if include is None: 75 | include = True 76 | 77 | if include: 78 | print("including:", fname) 79 | else: 80 | print("excluding:", fname) 81 | continue 82 | 83 | farch = fin.extractfile(info) 84 | fout.addfile(info, farch) 85 | fout.close() 86 | fin.close() 87 | 88 | 89 | def make_resource_module(manifest_files): 90 | resources = [] 91 | # Any non-python file included in manifest is resource 92 | for fname in manifest_files: 93 | ext = fname.rsplit(".", 1)[1] 94 | if ext != "py": 95 | resources.append(fname) 96 | 97 | if resources: 98 | print("creating resource module R.py") 99 | resources.sort() 100 | last_pkg = None 101 | r_file = None 102 | for fname in resources: 103 | try: 104 | pkg, res_name = fname.split("/", 1) 105 | except ValueError: 106 | print("not treating %s as a resource" % fname) 107 | continue 108 | if last_pkg != pkg: 109 | last_pkg = pkg 110 | if r_file: 111 | r_file.write("}\n") 112 | r_file.close() 113 | r_file = open(pkg + "/R.py", "w") 114 | r_file.write("R = {\n") 115 | 116 | with open(fname, "rb") as f: 117 | r_file.write("%r: %r,\n" % (res_name, f.read())) 118 | 119 | if r_file: 120 | r_file.write("}\n") 121 | r_file.close() 122 | 123 | 124 | class sdist(_sdist): 125 | 126 | def run(self): 127 | self.filelist = FileList() 128 | self.get_file_list() 129 | make_resource_module(self.filelist.files) 130 | 131 | r = super().run() 132 | 133 | assert len(self.archive_files) == 1 134 | print("filtering files and recompressing with 4K dictionary") 135 | filter_tar(self.archive_files[0]) 136 | outbuf.seek(0) 137 | gzip_4k(outbuf, self.archive_files[0]) 138 | 139 | return r 140 | 141 | 142 | # For testing only 143 | if __name__ == "__main__": 144 | filter_tar(sys.argv[1]) 145 | outbuf.seek(0) 146 | gzip_4k(outbuf, sys.argv[1]) 147 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: UTF-8 -*- 3 | 4 | from setuptools import setup 5 | from pathlib import Path 6 | import sdist_upip 7 | 8 | here = Path(__file__).parent.resolve() 9 | 10 | # Get the long description from the README file 11 | long_description = (here / 'README.md').read_text(encoding='utf-8') 12 | 13 | # load elements of version.py 14 | exec(open(here / 'nextion' / 'version.py').read()) 15 | 16 | setup( 17 | name='micropython-nextion', 18 | version=__version__, 19 | description="MicroPython Nextion serial displays library", 20 | long_description=long_description, 21 | long_description_content_type='text/markdown', 22 | url='https://github.com/brainelectronics/micropython-nextion', 23 | author='brainelectronics', 24 | author_email='info@brainelectronics.de', 25 | classifiers=[ 26 | 'Development Status :: 4 - Beta', 27 | 'Intended Audience :: Developers', 28 | 'License :: OSI Approved :: MIT License', 29 | 'Programming Language :: Python :: Implementation :: MicroPython', 30 | ], 31 | keywords='micropython, nextion, display, nextion-display, nextion-communication, uart, library', 32 | project_urls={ 33 | 'Bug Reports': 'https://github.com/brainelectronics/micropython-nextion/issues', 34 | 'Source': 'https://github.com/brainelectronics/micropython-nextion', 35 | }, 36 | license='MIT', 37 | cmdclass={'sdist': sdist_upip.sdist}, 38 | packages=['nextion'], 39 | install_requires=[] 40 | ) 41 | --------------------------------------------------------------------------------