Skip to content

Instantly share code, notes, and snippets.

@ccooper21
Created November 19, 2019 05:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ccooper21/09c8c18f676b1e1a61dd77415e7b39a4 to your computer and use it in GitHub Desktop.
Save ccooper21/09c8c18f676b1e1a61dd77415e7b39a4 to your computer and use it in GitHub Desktop.
This is a Vagrant virtual machine definition and corresponding provisioning script for an ESP32 development environment using the ESP-IDF.
#!/usr/bin/env bash
set -o errexit
set -o pipefail
set -o nounset
[[ -v TRACE ]] && set -o xtrace
IFS=$'\n\t'
VAGRANT_USER=vagrant
VAGRANT_HOME_DIR=$(getent passwd ${VAGRANT_USER} | cut --delimiter=: --fields=6)
ESP_DIR=${VAGRANT_HOME_DIR}
# The following environment variables need to be updated as Espressif makes releases of the tool chain, IDF, and HomeKit
# SDK to refer to those releases.
# The URL for the most recent stable tool chain distribution can be found in the documentation at
# "https://esp-idf.readthedocs.io/en/stable/get-started/linux-setup.html". Starting with IDF v4.0, a standalone tool
# chain installation is unnecessary as the installation is handled by a script included with the IDF itself. In this
# case, the standalone tool chain installation can be skipped by leaving the tool chain URL variable unset.
TOOL_CHAIN_URL=https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
# These packages are the Ubuntu prerequisites for the most recent stable IDF documented at
# "https://esp-idf.readthedocs.io/en/stable/get-started/linux-setup.html". The required Python packages should not be
# included since it is preferable to install those using the Python "requirements.txt" file included with the IDF,
# instead of via "apt-get". The Python based installation will occur during the setup process.
IDF_APT_PACKAGE_DEPENDENCIES="bison flex gcc git gperf libncurses-dev make python python-pip wget"
# If a git tag for the IDF is not specified, the latest version of the IDF will be installed, which may be unstable.
# Documentation for and identification of the most recent stable release can be found at
# "https://docs.espressif.com/projects/esp-idf/en/stable/get-started/index.html".
IDF_GITHUB_PROJECT=espressif/esp-idf
IDF_GIT_TAG=v3.3
# The ESP32 HomeKit SDK is available from Espressif under NDA. More information is available at
# "https://www.espressif.com/en/products/software/esp-homekit-sdk". To prepare the SDK distribution file, clone the git
# repository containing the SDK, and create a compressed tar file from the root of the git repository as follows:
#
# tar cvzf ../esp-homekit-sdk-esp_homekit_release_2.3.r2.tar.gz *
#
# The name of the tar file must include a release/version number between the final underscore and the ".tar.gz" suffix
# (e.g., "2.3.r2"). If the SDK is unavailable, leave the HomeKit SDK file variable unset.
#HOMEKIT_SDK_FILE=esp-homekit-sdk-esp_homekit_release_2.3.r2.tar.gz
# *** Environment variables set after this point are not intended to be updated during typical script maintenance. ***
TOOL_CHAIN_URL=${TOOL_CHAIN_URL:=}
TOOL_CHAIN_FILE=$(echo ${TOOL_CHAIN_URL} | sed -E "s/^.*\///")
TOOL_CHAIN_TARGET_NAME=$(echo ${TOOL_CHAIN_FILE} | sed -E "s/-linux.*(\.tar\.gz|\.tgz)$//")
TOOL_CHAIN_TARGET_DIR=${ESP_DIR}/${TOOL_CHAIN_TARGET_NAME}
TOOL_CHAIN_TARGET_DIR_PARENT=$(realpath --canonicalize-missing ${TOOL_CHAIN_TARGET_DIR}/..)
IDF_GIT_TAG=${IDF_GIT_TAG:=}
IDF_TARGET_NAME=esp-idf-${IDF_GIT_TAG:-latest}
IDF_TARGET_NAME_ALIAS=esp-idf
IDF_TARGET_DIR=${ESP_DIR}/${IDF_TARGET_NAME}
IDF_TARGET_DIR_ALIAS=$(realpath --canonicalize-missing ${IDF_TARGET_DIR}/../${IDF_TARGET_NAME_ALIAS})
HOMEKIT_SDK_FILE=${HOMEKIT_SDK_FILE:=}
HOMEKIT_SDK_SOURCE_FILE_PATH=${VAGRANT_HOME_DIR}/${HOMEKIT_SDK_FILE}
HOMEKIT_SDK_TARGET_NAME=esp-homekit-sdk-v$(echo ${HOMEKIT_SDK_FILE} | sed -E "s/^.*_//" | sed -E "s/(\.tar\.gz|\.tgz)$//")
HOMEKIT_SDK_TARGET_NAME_ALIAS=esp-homekit-sdk
HOMEKIT_SDK_TARGET_DIR=${ESP_DIR}/${HOMEKIT_SDK_TARGET_NAME}
HOMEKIT_SDK_TARGET_DIR_ALIAS=$(realpath --canonicalize-missing ${HOMEKIT_SDK_TARGET_DIR}/../${HOMEKIT_SDK_TARGET_NAME_ALIAS})
apt-get update
apt-get install --yes ${IDF_APT_PACKAGE_DEPENDENCIES// /$'\t'}
sudo -u ${VAGRANT_USER} -H mkdir --parents ${ESP_DIR}
cd ${ESP_DIR}
IDF_GIT_BRANCH_OPTION=${IDF_GIT_TAG:+--branch$'\t'${IDF_GIT_TAG}}
sudo -u ${VAGRANT_USER} -H git clone ${IDF_GIT_BRANCH_OPTION} --recursive https://github.com/${IDF_GITHUB_PROJECT}.git ${IDF_TARGET_NAME}
sudo -u ${VAGRANT_USER} -H ln --symbolic ${IDF_TARGET_NAME} ${IDF_TARGET_NAME_ALIAS}
if [[ -f ${IDF_TARGET_DIR}/install.sh ]]; then
# The install commands invoked from the "install.sh" script are directly used so that the non-interactive flag can
# be set, as the script does not have a provision for this. Unfortunately, additional install commands may need to
# be added as the script evolves.
sudo -u ${VAGRANT_USER} -H ${IDF_TARGET_DIR}/tools/idf_tools.py --non-interactive --idf-path ${IDF_TARGET_DIR} install
sudo -u ${VAGRANT_USER} -H ${IDF_TARGET_DIR}/tools/idf_tools.py --non-interactive --idf-path ${IDF_TARGET_DIR} install-python-env
echo >> ${VAGRANT_HOME_DIR}/.profile
echo "source ${IDF_TARGET_DIR_ALIAS}/export.sh" >> ${VAGRANT_HOME_DIR}/.profile
elif [[ -n ${TOOL_CHAIN_URL} ]]; then
echo "Downloading the ESP32 tool chain (${TOOL_CHAIN_FILE})..."
cd ${ESP_DIR}
curl --silent --show-error --remote-name ${TOOL_CHAIN_URL}
echo "Unpacking the ESP32 tool chain (${TOOL_CHAIN_FILE})..."
sudo -u ${VAGRANT_USER} -H mkdir --parents ${TOOL_CHAIN_TARGET_DIR}
sudo -u ${VAGRANT_USER} -H tar --extract --gunzip --directory ${TOOL_CHAIN_TARGET_DIR_PARENT} --file ${TOOL_CHAIN_FILE}
rm ${TOOL_CHAIN_FILE}
sudo -u ${VAGRANT_USER} -H python -m pip install --user -r ${IDF_TARGET_DIR}/requirements.txt
echo >> ${VAGRANT_HOME_DIR}/.profile
echo "export PATH=\${PATH}:${TOOL_CHAIN_TARGET_DIR}/bin" >> ${VAGRANT_HOME_DIR}/.profile
echo "export IDF_PATH=${IDF_TARGET_DIR_ALIAS}" >> ${VAGRANT_HOME_DIR}/.profile
fi
if [[ -f ${HOMEKIT_SDK_SOURCE_FILE_PATH} ]]; then
echo "Unpacking the ESP32 HomeKit SDK (${HOMEKIT_SDK_FILE})..."
cd ${ESP_DIR}
if [[ ! -f ${HOMEKIT_SDK_FILE} ]]; then
mv ${HOMEKIT_SDK_SOURCE_FILE_PATH} .
fi
sudo -u ${VAGRANT_USER} -H mkdir --parents ${HOMEKIT_SDK_TARGET_DIR}
sudo -u ${VAGRANT_USER} -H tar --extract --gunzip --directory ${HOMEKIT_SDK_TARGET_DIR} --file ${HOMEKIT_SDK_FILE}
sudo -u ${VAGRANT_USER} -H ln --symbolic ${HOMEKIT_SDK_TARGET_NAME} ${HOMEKIT_SDK_TARGET_NAME_ALIAS}
echo "export HOMEKIT_PATH=${HOMEKIT_SDK_TARGET_DIR_ALIAS}" >> ${VAGRANT_HOME_DIR}/.profile
fi
usermod --append --groups dialout ${VAGRANT_USER}
# USB serial support is required to interact with the Espressif ESP32-DevKitC development board via its Silicon Labs
# CP210x USB-to-UART bridge. While another ESP32 development board may use a different USB-to-UART bridge, they all
# require USB serial support. USB serial support is provided by the "linux-modules-extra" package. After installing
# this package, a reboot is necessary for the changes to take effect.
apt-get install --yes linux-modules-extra-$(uname --kernel-release)
if [[ -f /var/run/reboot-required ]]; then
echo
echo "*************************************************************"
echo "Please reboot the virtual machine for changes to take effect."
echo "*************************************************************"
fi
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/bionic64"
config.vm.provider "virtualbox" do |vb|
vb.customize ["modifyvm", :id, "--usb", "on"]
vb.customize ["modifyvm", :id, "--usbehci", "on"]
vb.customize ["modifyvm", :id, "--usbxhci", "on"]
vb.customize ["usbfilter", "add", "0",
"--target", :id,
"--name", "Silicon Labs CP210x USB-to-UART Bridge",
"--vendorid","0x10c4",
"--productid","0xea60"
]
vb.customize ["usbfilter", "add", "0",
"--target", :id,
"--name", "WCH CH340 USB-to-UART Bridge",
"--vendorid","0x1a86",
"--productid","0x7523"
]
vb.customize ["usbfilter", "add", "0",
"--target", :id,
"--name", "FTDI FT2232x USB-to-UART Bridge",
"--vendorid","0x0403",
"--productid","0x6010"
]
end
config.vm.provision "file", source: "vagrant-setup", destination: "${HOME}"
config.vm.provision "shell", inline: "sudo -u vagrant -H rm vagrant-setup.sh"
config.vm.provision "shell", path: "vagrant-setup/vagrant-setup.sh"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment