Source code for automationshield.arduino

"""This module provides several functions to download the `arduino-cli`_ and install firmware on an Arduino board.

.. _arduino-cli: https://arduino.github.io/arduino-cli/
"""

import platform
import subprocess
import sys

from math import log
from pathlib import Path
from shutil import unpack_archive
from typing import Optional
from urllib.request import urlretrieve


LEONARDO: str = "arduino:avr:leonardo"
"""FQBN for Arduino Leonardo."""

UNO: str = "arduino:avr:uno"
"""FQBN for Arduino UNO."""

MEGA: str = "arduino:avr:mega"
"""FQBN for Arduino MEGA and MEGA 2560."""

src_dir: Path = Path(__file__).parent
"""Path to the automationshield src directory on the system.

:meta hide-value:
"""

script_dir: Path = src_dir / "arduino"
"""Path to the directory containing the Arduino script directories.

:meta hide-value:
"""

out_dir: Path = script_dir / "out"
"""Path to the directory containing the .hex files.

:meta hide-value:
"""

cli_dir: Path = script_dir / "arduino-cli"
"""Path to the directory containing the ``arduino-cli``.

:meta hide-value:
"""

cli_path: Path = cli_dir / "arduino-cli"
"""Path to the ``arduino-cli`` executable.

:meta hide-value:
"""


[docs] def download_cli(system:str): """Download the ``arduino-cli`` for the appropriate system. The executable is placed in :py:const:`cli_dir`. :param system: Name of operating system. Result of calling :py:meth:`platform.system`. """ base_url = "https://downloads.arduino.cc/arduino-cli/" system_bits = int(log(sys.maxsize + 1, 2) + 1) if system == "Windows": url = base_url + f"arduino-cli_latest_Windows_{system_bits}bit.zip" zip_name = "arduino-cli.zip" elif system == "Linux": if "ARM" in platform.machine().upper(): if system_bits == 64: url = base_url + f"arduino-cli_latest_Linux_ARM64.tar.gz" else: url = base_url + f"arduino-cli_latest_Linux_ARMv7.tar.gz" else: url = base_url + f"arduino-cli_latest_Linux_{system_bits}bit.tar.gz" zip_name = "arduino-cli.tar.gz" elif system == "Darwin": url = base_url + f"arduino-cli_latest_macOS_64bit.tar.gz" zip_name = "arduino-cli.tar.gz" zip_path = src_dir / zip_name urlretrieve(url, zip_path) unpack_archive(zip_path, cli_dir) zip_path.unlink()
[docs] def setup_cli(): """Run setup for ``arduino-cli``. This function calls the following methods of the ``arduino-cli``: .. code-block:: console :linenos: arduino-cli core update-index arduino-cli core install arduino:avr These respectively update the index of cores to the latest version and downloads the core for AVR boards, which includes a.o. the Arduino UNO, Mega (2560) and Leonardo. """ # update index subprocess.run( [cli_path, "core", "update-index"] ) # install core for AVR boards (includes Leonardo, UNO, Mega) subprocess.run( [cli_path, "core", "install", "arduino:avr"] )
[docs] def compile_script(device:str, script:str): """Compile an Arduino script for a specific Arduino board and Automationshield. .. code-block:: console :linenos: arduino-cli compile --fqbn {device} --clean --libraries {arduino.script_dir}/lib --export-binaries {arduino.script_dir}/{script} :param device: FQBN of Arduino board. :param script: Directory name of the Arduino code to be installed. Script directory are provided as a property of the shield classes, e.g.: :py:attr:`automationshield.AeroShield.script`. """ result = subprocess.run( [cli_path, "compile", "--fqbn", device, "--clean", "--libraries", script_dir / "lib", "--export-binaries", script_dir / script] ) result.check_returncode()
[docs] def upload_script(device:str, script:str, port:str, hex:Optional[str]=None): """Upload compiled script onto Arduino board. .. code-block:: console :linenos: arduino-cli upload --input-file {file} --fqbn {device} --port {port} {arduino.script_dir}/{script} In the command, the `file` argument points to the appropriate ``.hex`` file in :py:const:`arduino.out_dir`. This can be overridden by providing the ``hex`` argument. :param device: FQBN of Arduino board. :param script: Directory name of the Arduino code to be installed. Script directory are provided as a property of the shield classes, e.g.: :py:attr:`automationshield.AeroShield.script`. :param port: Port where the Arduino board is connected. Shield classes provide a :py:attr:`port` attribute that can be used. :param hex: ``.hex`` file to upload. Optional, defaults to the appropriate file in :py:const:`~automationshield.arduino.out_dir`. """ result = subprocess.run( [cli_path, "upload", "--input-file", (out_dir / f"{script}.ino.hex") if hex is None else hex, "--fqbn", device, "--port", port, script_dir / script] ) result.check_returncode()