raspi-blinka.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. """
  2. Adafruit Raspberry Pi Blinka Setup Script
  3. (C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
  4. Written by Melissa LeBlanc-Williams for Adafruit Industries
  5. """
  6. import os
  7. try:
  8. from adafruit_shell import Shell
  9. except ImportError:
  10. raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
  11. shell = Shell()
  12. shell.group="Blinka"
  13. default_python = 3
  14. blinka_minimum_python_version = 3.8
  15. def default_python_version(numeric=True):
  16. version = shell.run_command("python -c 'import platform; print(platform.python_version())'", suppress_message=True, return_output=True)
  17. if numeric:
  18. try:
  19. return float(version[0:version.rfind(".")])
  20. except ValueError:
  21. return None
  22. return version
  23. def get_python3_version(numeric=True):
  24. version = shell.run_command("python3 -c 'import platform; print(platform.python_version())'", suppress_message=True, return_output=True)
  25. if numeric:
  26. return float(version[0:version.rfind(".")])
  27. return version
  28. def check_blinka_python_version():
  29. """
  30. Check the Python 3 version for Blinka (which may be a later version than we're running this script with)
  31. """
  32. print("Making sure the required version of Python is installed")
  33. current = get_python3_version(False)
  34. current_major, current_minor = current.split(".")[0:2]
  35. required_major, required_minor = str(blinka_minimum_python_version).split(".")[0:2]
  36. if int(current_major) >= int(required_major) and int(current_minor) >= int(required_minor):
  37. return
  38. shell.bail("Blinka requires a minimum of Python version {} to install, current one is {}. Please update your OS!".format(blinka_minimum_python_version, current))
  39. def sys_update():
  40. print("Updating System Packages")
  41. if not shell.run_command("sudo apt-get update --allow-releaseinfo-change"):
  42. shell.bail("Apt failed to update indexes!")
  43. print("Upgrading packages...")
  44. if not shell.run_command("sudo apt-get -y upgrade"):
  45. shell.bail("Apt failed to install software!")
  46. def set_raspiconfig():
  47. """
  48. Enable various Raspberry Pi interfaces
  49. """
  50. print("Enabling I2C")
  51. shell.run_command("sudo raspi-config nonint do_i2c 0")
  52. print("Enabling SPI")
  53. shell.run_command("sudo raspi-config nonint do_spi 0")
  54. print("Enabling Serial")
  55. if not shell.run_command("sudo raspi-config nonint do_serial_hw 0", suppress_message=True):
  56. shell.run_command("sudo raspi-config nonint do_serial 0")
  57. print("Enabling SSH")
  58. shell.run_command("sudo raspi-config nonint do_ssh 0")
  59. print("Enabling Camera")
  60. shell.run_command("sudo raspi-config nonint do_camera 0")
  61. print("Disable raspi-config at Boot")
  62. shell.run_command("sudo raspi-config nonint disable_raspi_config_at_boot 0")
  63. def update_python():
  64. print("Making sure Python 3 is the default")
  65. if default_python < 3:
  66. shell.run_command("sudo apt-get install -y python3 git python3-pip")
  67. shell.run_command("sudo update-alternatives --install /usr/bin/python python $(which python2) 1")
  68. shell.run_command("sudo update-alternatives --install /usr/bin/python python $(which python3) 2")
  69. shell.run_command("sudo update-alternatives --skip-auto --config python")
  70. def update_pip():
  71. print("Making sure PIP and setuptools is installed")
  72. shell.run_command("sudo apt-get install --upgrade -y python3-pip python3-setuptools")
  73. def install_blinka(user=False):
  74. print("Installing latest version of Blinka locally")
  75. shell.run_command("sudo apt-get install -y i2c-tools libgpiod-dev python3-libgpiod")
  76. pip_command = "pip3 install --upgrade"
  77. username = None
  78. if user:
  79. username = os.environ["SUDO_USER"]
  80. shell.run_command(f"{pip_command} adafruit-blinka", run_as_user=username)
  81. # Custom function to run additional commands for Pi 5
  82. def check_and_install_for_pi5(pi_model, user=False):
  83. if shell.is_pi5_or_newer():
  84. username = None
  85. if user:
  86. username = os.environ["SUDO_USER"]
  87. print("Detected Raspberry Pi 5, applying additional fixes...")
  88. shell.run_command("sudo apt remove python3-rpi.gpio")
  89. shell.run_command("pip3 uninstall -y RPi.GPIO", run_as_user=username)
  90. shell.run_command("pip3 install --upgrade rpi-lgpio", run_as_user=username)
  91. else:
  92. print(f"Detected {pi_model}, no additional fixes needed.")
  93. def check_user_groups():
  94. # Check if the user has the groups i2c, spi, gpio, input, and video. If the user is not in a group, then they need to be added.
  95. groups = shell.run_command("groups", suppress_message=True, return_output=True).split()
  96. required_groups = ["i2c", "spi", "gpio", "input", "video"]
  97. for group in required_groups:
  98. if group not in groups:
  99. print(f"Adding user to the group: {group}.")
  100. shell.run_command(f"sudo usermod -aG {group} {os.environ['SUDO_USER']}")
  101. def main():
  102. global default_python
  103. shell.clear()
  104. # Check Raspberry Pi and Bail
  105. pi_model = shell.get_board_model()
  106. if not shell.is_raspberry_pi():
  107. shell.bail("This model of Raspberry Pi is not currently supported by Blinka")
  108. print("""This script configures your
  109. Raspberry Pi and installs Blinka
  110. """)
  111. print("{} detected.\n".format(pi_model))
  112. if not shell.is_raspberry_pi():
  113. shell.bail("Non-Raspberry Pi board detected. This must be run on a Raspberry Pi")
  114. os_identifier = shell.get_os()
  115. if os_identifier != "Raspbian":
  116. shell.bail("Sorry, the OS detected was {}. This script currently only runs on Raspberry Pi OS.".format(os_identifier))
  117. if not shell.is_python3():
  118. shell.bail("You must be running Python 3. Older versions have now been deprecated.")
  119. shell.check_kernel_update_reboot_required()
  120. python_version = default_python_version()
  121. if not python_version:
  122. shell.warn("WARNING No Default System python tied to the `python` command. It will be set to Version 3.")
  123. default_python = 0
  124. if not shell.prompt("Continue?"):
  125. shell.exit()
  126. elif int(default_python_version()) < 3:
  127. shell.warn("WARNING Default System python version is {}. It will be updated to Version 3.".format(default_python_version(False)))
  128. default_python = 2
  129. if not shell.prompt("Continue?"):
  130. shell.exit()
  131. sys_update()
  132. check_blinka_python_version()
  133. set_raspiconfig()
  134. update_python()
  135. update_pip()
  136. install_blinka(True)
  137. check_user_groups()
  138. # Check and install any Pi 5 fixes if detected
  139. check_and_install_for_pi5(pi_model, True)
  140. # Done
  141. print("""DONE.
  142. Settings take effect on next boot.
  143. """)
  144. shell.prompt_reboot()
  145. # Main function
  146. if __name__ == "__main__":
  147. shell.require_root()
  148. main()