diff --git a/common.sh b/common.sh index eaba123..ebb6f4b 100755 --- a/common.sh +++ b/common.sh @@ -5,75 +5,83 @@ AP_CONNECTED_ENDING="" FIRST_WIFI=$(nmcli device status | grep " wifi " | head -n1 | awk -F ' ' '{print $1}') if [ "${WIFI_ADAPTER}" == "" ]; then - WIFI_ADAPTER="${FIRST_WIFI}" + WIFI_ADAPTER="${FIRST_WIFI}" fi if [ "${WIFI_ADAPTER}" == "" ]; then - echo "[!] Unable to auto-detect wifi adapter. Please use the '-w' argument to pass in a wifi adapter." - echo "See '$0 -h' for more information." - exit 1 + echo "[!] Unable to auto-detect wifi adapter. Please use the '-w' argument to pass in a wifi adapter." + echo "See '$0 -h' for more information." + exit 1 fi SUPPORTS_AP=$(nmcli -f wifi-properties device show ${WIFI_ADAPTER} | grep WIFI-PROPERTIES.AP | awk -F ' ' '{print $2}') # We don't want to hard stop here because localization could lead to false positives, but warn if AP mode does not appear supported. if [ "${SUPPORTS_AP}" != "yes" ]; then - echo "[!] WARNING: Selected wifi AP support: ${SUPPORTS_AP}" - echo "AP support is manditory for tuya-cloudcutter to work. If this is blank or 'no' your adapter doesn't support this feature." - read -n 1 -s -r -p "Press any key to continue, or CTRL+C to exit" + echo "[!] WARNING: Selected wifi AP support: ${SUPPORTS_AP}" + echo "AP support is manditory for tuya-cloudcutter to work. If this is blank or 'no' your adapter doesn't support this feature." + read -n 1 -s -r -p "Press any key to continue, or CTRL+C to exit" fi -function run_helper_script () { +function run_helper_script() { if [ -f "scripts/${1}.sh" ]; then echo "Running helper script '${1}'" source "scripts/${1}.sh" fi } -reset_nm () { +reset_nm() { -if [ -z ${RESETNM+x} ]; then - return 0 -else - echo "Wiping NetworkManager configs" - rm -f /etc/NetworkManager/system-connections/*.nmconnection* - service NetworkManager restart - return 0 -fi + if [ -z ${RESETNM+x} ]; then + return 0 + else + echo "Wiping NetworkManager configs" + rm -f /etc/NetworkManager/system-connections/*.nmconnection* + service NetworkManager restart + return 0 + fi } -wifi_connect () { +wifi_connect() { FIRST_RUN=true - for i in {1..5} - do + for i in {1..5}; do AP_MATCHED_NAME="" # Turn on WiFi, and wait for SSID to show up reset_nm sleep 1 - service NetworkManager start; nmcli device set ${WIFI_ADAPTER} managed yes # Make sure we turn on managed mode again in case we didn't recover it in the trap below + service NetworkManager start + nmcli device set ${WIFI_ADAPTER} managed yes # Make sure we turn on managed mode again in case we didn't recover it in the trap below nmcli radio wifi off sleep 1 nmcli radio wifi on - while [ "${AP_MATCHED_NAME}" == "" ] - do + while [ "${AP_MATCHED_NAME}" == "" ]; do if [ ${FIRST_RUN} == true ]; then - echo "Scanning for open Tuya SmartLife AP" + SCAN_MESSAGE="Scanning for open Tuya SmartLife AP" + if [ "${OVERRIDE_SSID}" != "" ]; then + SCAN_MESSAGE="${SCAN_MESSAGE} ${OVERRIDE_SSID}" + fi + echo ${SCAN_MESSAGE} FIRST_RUN=false else echo -n "." fi - + RESCAN_ARG="--rescan yes" if [ "${DISABLE_RESCAN}" == "true" ]; then RESCAN_ARG="" fi - # Search for an AP ending with - and 4 hexidecimal characters that has no security mode, unless we've already connected to one, in which case we look for that specific one - SSID_REGEX="-[A-F0-9]{4}" + if [ "${OVERRIDE_SSID}" != "" ]; then + SSID_REGEX="${OVERRIDE_SSID}" + else + # Search for an AP ending with - and 4 hexidecimal characters that has no security mode, unless we've already connected to one, in which case we look for that specific one + SSID_REGEX="-[A-F0-9]{4}" + fi + if [ "${AP_CONNECTED_ENDING}" != "" ]; then SSID_REGEX="${AP_CONNECTED_ENDING}" fi @@ -109,7 +117,7 @@ wifi_connect () { return 0 } -build_docker () { +build_docker() { export NO_COLOR=1 docker build --network=host -t cloudcutter . if [ ! $? -eq 0 ]; then @@ -118,7 +126,7 @@ build_docker () { fi } -run_in_docker () { +run_in_docker() { docker rm cloudcutter >/dev/null 2>&1 docker run --rm --name cloudcutter --network=host -ti --privileged -v "$(pwd):/work" cloudcutter "${@}" } diff --git a/common_run.sh b/common_run.sh index 2c40e3b..ee4b908 100755 --- a/common_run.sh +++ b/common_run.sh @@ -2,17 +2,17 @@ # Select the right device if [ "${PROFILE}" == "" ]; then - if [ $METHOD_FLASH ]; then - run_in_docker pipenv run python3 get_input.py -w /work -o /work/profile.txt choose-profile -f - else - run_in_docker pipenv run python3 get_input.py -w /work -o /work/profile.txt choose-profile - fi + if [ $METHOD_FLASH ]; then + run_in_docker pipenv run python3 get_input.py -w /work -o /work/profile.txt choose-profile -f + else + run_in_docker pipenv run python3 get_input.py -w /work -o /work/profile.txt choose-profile + fi else - run_in_docker pipenv run python3 get_input.py -w /work -o /work/profile.txt write-profile $PROFILE + run_in_docker pipenv run python3 get_input.py -w /work -o /work/profile.txt write-profile $PROFILE fi if [ ! $? -eq 0 ]; then - echo "Failed to choose a profile, please run this script again" - exit 1 + echo "Failed to choose a profile, please run this script again" + exit 1 fi PROFILE=$(cat profile.txt) @@ -20,13 +20,13 @@ rm -f profile.txt LOCAL_PROFILE=$(echo "${PROFILE}" | sed 's/\/work\///g') SLUGS=($(cat ${LOCAL_PROFILE} | grep -oP '(?<="slug": ")[^"]*')) if ! [ -z "${SLUGS}" ]; then - DEVICESLUG="${SLUGS[0]}" - if [ "${#SLUGS[@]}" -eq 1 ]; then - PROFILES_GREP=($(cat ${LOCAL_PROFILE} | grep -A1 '"profiles": \[' | tr -d "\t" | tr -d "\"" | tr -d " " | tr -d "[")) - PROFILESLUG="${PROFILES_GREP[1]}" - else - PROFILESLUG="${SLUGS[1]}" - fi + DEVICESLUG="${SLUGS[0]}" + if [ "${#SLUGS[@]}" -eq 1 ]; then + PROFILES_GREP=($(cat ${LOCAL_PROFILE} | grep -A1 '"profiles": \[' | tr -d "\t" | tr -d "\"" | tr -d " " | tr -d "[")) + PROFILESLUG="${PROFILES_GREP[1]}" + else + PROFILESLUG="${SLUGS[1]}" + fi fi CHIP=$(cat "${LOCAL_PROFILE}" | grep -o '"chip": "[^"]*' | grep -o '[^"]*$') @@ -34,64 +34,64 @@ run_helper_script "pre-safety-checks" source safety_checks.sh if [ $METHOD_FLASH ]; then - # Select the right firmware - if [ "${FIRMWARE}" == "" ]; then - run_in_docker pipenv run python3 get_input.py -w /work -o /work/firmware.txt choose-firmware -c "${CHIP}" - else - run_in_docker pipenv run python3 get_input.py -w /work -o /work/firmware.txt validate-firmware-file "${FIRMWARE}" -c "${CHIP}" - fi - if [ ! $? -eq 0 ]; then - exit 1 - fi - FIRMWARE=$(cat firmware.txt) - rm -f firmware.txt + # Select the right firmware + if [ "${FIRMWARE}" == "" ]; then + run_in_docker pipenv run python3 get_input.py -w /work -o /work/firmware.txt choose-firmware -c "${CHIP}" + else + run_in_docker pipenv run python3 get_input.py -w /work -o /work/firmware.txt validate-firmware-file "${FIRMWARE}" -c "${CHIP}" + fi + if [ ! $? -eq 0 ]; then + exit 1 + fi + FIRMWARE=$(cat firmware.txt) + rm -f firmware.txt fi echo "Selected Device Slug: ${DEVICESLUG}" echo "Selected Profile: ${PROFILESLUG}" if ! [ -z "${FIRMWARE}" ]; then - echo "Selected Firmware: ${FIRMWARE}" + echo "Selected Firmware: ${FIRMWARE}" fi if ! [ -z "${AUTHKEY}" ] && ! [ -z "${UUID}" ] && ! [ -z "${PSKKEY}" ]; then - echo "Using AuthKey ${AUTHKEY} , UUID ${UUID} , and PSKKey ${PSKKEY}" - if ! [ -z "${DEVICEID}" ] && ! [ -z "${LOCALKEY}" ]; then - echo "Using DeviceId ${DEVICEID} and LocalKey ${LOCALKEY}" - fi - echo "Writing deviceconfig file..." - OUTPUT=$(run_in_docker pipenv run python3 -m cloudcutter write_deviceconfig "${PROFILE}" "${VERBOSE_OUTPUT}" --deviceid "${DEVICEID}" --localkey "${LOCALKEY}" --authkey "${AUTHKEY}" --uuid "${UUID}" --pskkey "${PSKKEY}") + echo "Using AuthKey ${AUTHKEY} , UUID ${UUID} , and PSKKey ${PSKKEY}" + if ! [ -z "${DEVICEID}" ] && ! [ -z "${LOCALKEY}" ]; then + echo "Using DeviceId ${DEVICEID} and LocalKey ${LOCALKEY}" + fi + echo "Writing deviceconfig file..." + OUTPUT=$(run_in_docker pipenv run python3 -m cloudcutter write_deviceconfig "${PROFILE}" "${VERBOSE_OUTPUT}" --deviceid "${DEVICEID}" --localkey "${LOCALKEY}" --authkey "${AUTHKEY}" --uuid "${UUID}" --pskkey "${PSKKEY}") else - # Connect to Tuya device's WiFi - echo "" - echo "================================================================================" - echo "Place your device in AP (slow blink) mode. This can usually be accomplished by either:" - echo "Power cycling off/on - 3 times and wait for the device to fast-blink, then repeat 3 more times. Some devices need 4 or 5 times on each side of the pause" - echo "Long press the power/reset button on the device until it starts fast-blinking, then releasing, and then holding the power/reset button again until the device starts slow-blinking." - echo "See https://support.tuya.com/en/help/_detail/K9hut3w10nby8 for more information." - echo "================================================================================" - echo "" - run_helper_script "pre-wifi-exploit" - wifi_connect - if [ ! $? -eq 0 ]; then - echo "Failed to connect, please run this script again" - exit 1 - fi + # Connect to Tuya device's WiFi + echo "" + echo "================================================================================" + echo "Place your device in AP (slow blink) mode. This can usually be accomplished by either:" + echo "Power cycling off/on - 3 times and wait for the device to fast-blink, then repeat 3 more times. Some devices need 4 or 5 times on each side of the pause" + echo "Long press the power/reset button on the device until it starts fast-blinking, then releasing, and then holding the power/reset button again until the device starts slow-blinking." + echo "See https://support.tuya.com/en/help/_detail/K9hut3w10nby8 for more information." + echo "================================================================================" + echo "" + run_helper_script "pre-wifi-exploit" + wifi_connect + if [ ! $? -eq 0 ]; then + echo "Failed to connect, please run this script again" + exit 1 + fi - # Exploit chain - echo "Waiting 1 sec to allow device to set itself up..." - sleep 1 - echo "Running initial exploit toolchain..." - if ! [ -z "${DEVICEID}" ] && ! [ -z "${LOCALKEY}" ]; then - echo "Using DeviceId ${DEVICEID} and LocalKey ${LOCALKEY}" - fi - OUTPUT=$(run_in_docker pipenv run python3 -m cloudcutter exploit_device "${PROFILE}" "${VERBOSE_OUTPUT}" --deviceid "${DEVICEID}" --localkey "${LOCALKEY}") + # Exploit chain + echo "Waiting 1 sec to allow device to set itself up..." + sleep 1 + echo "Running initial exploit toolchain..." + if ! [ -z "${DEVICEID}" ] && ! [ -z "${LOCALKEY}" ]; then + echo "Using DeviceId ${DEVICEID} and LocalKey ${LOCALKEY}" + fi + OUTPUT=$(run_in_docker pipenv run python3 -m cloudcutter exploit_device "${PROFILE}" "${VERBOSE_OUTPUT}" --deviceid "${DEVICEID}" --localkey "${LOCALKEY}") fi RESULT=$? echo "${OUTPUT}" if [ ! $RESULT -eq 0 ]; then - echo "Oh no, something went wrong with running the exploit! Try again I guess..." - exit 1 + echo "Oh no, something went wrong with running the exploit! Try again I guess..." + exit 1 fi CONFIG_DIR=$(echo "${OUTPUT}" | grep "output=" | awk -F '=' '{print $2}' | sed -e 's/\r//') echo "Saved device config in ${CONFIG_DIR}" @@ -109,17 +109,17 @@ sleep 5 run_helper_script "pre-wifi-config" wifi_connect if [ ! $? -eq 0 ]; then - echo "Failed to connect, please run this script again" - exit 1 + echo "Failed to connect, please run this script again" + exit 1 fi # If the AP prefix did not change, the exploit was not successful # End the process now to end further confusion if [[ $AP_MATCHED_NAME != A-* ]] && [ -z "${AUTHKEY}" ]; then - echo "================================================================================" - echo "[!] The profile you selected did not result in a successful exploit." - echo "================================================================================" - exit 1 + echo "================================================================================" + echo "[!] The profile you selected did not result in a successful exploit." + echo "================================================================================" + exit 1 fi # Add a minor delay to stabilize after connection @@ -128,7 +128,7 @@ OUTPUT=$(run_in_docker pipenv run python3 -m cloudcutter configure_wifi "cloudcu RESULT=$? echo "${OUTPUT}" if [ ! $RESULT -eq 0 ]; then - echo "Oh no, something went wrong with making the device connect to our hostapd AP! Try again I guess..." - exit 1 + echo "Oh no, something went wrong with making the device connect to our hostapd AP! Try again I guess..." + exit 1 fi echo "Device is connecting to 'cloudcutterflash' access point. Passphrase for the AP is 'abcdabcd' (without ')" diff --git a/safety_checks.sh b/safety_checks.sh index 26d236b..c38e65d 100755 --- a/safety_checks.sh +++ b/safety_checks.sh @@ -1,67 +1,67 @@ #!/bin/bash check_port () { - protocol="$1" - port="$2" - reason="$3" - echo -n "Checking ${protocol^^} port $port... " - process_pid=$(sudo ss -lnp -A "$protocol" "sport = :$port" | grep -Po "(?<=pid=)(\d+)" | head -n1) - if [ -n "$process_pid" ]; then - process_name=$(ps -p "$process_pid" -o comm=) - echo "Occupied by $process_name with PID $process_pid." - echo "Port $port is needed to $reason" - read -p "Do you wish to terminate $process_name? [y/N] " -n 1 -r - echo - if [[ "$REPLY" =~ ^[Ss]$ ]]; then - echo "Skipping..." - return - fi - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Aborting due to occupied port" - exit 1 - else - service=$(ps -p "$process_pid" -o unit= | grep .service | grep -Ev ^user) - if [ -n "$service" ]; then - echo "Attempting to stop $service" - sudo systemctl stop "$service" - else - echo "Attempting to terminate $process_name" - sudo kill "$process_pid" - if ! sudo timeout 10 tail --pid="$process_pid" -f /dev/null; then - echo "$process_name is still running after 10 seconds, sending SIGKILL" - sudo kill -9 "$process_pid" - sudo tail --pid="$process_pid" -f /dev/null - fi - fi - sleep 1 - fi - else - echo "Available." - fi + protocol="$1" + port="$2" + reason="$3" + echo -n "Checking ${protocol^^} port $port... " + process_pid=$(sudo ss -lnp -A "$protocol" "sport = :$port" | grep -Po "(?<=pid=)(\d+)" | head -n1) + if [ -n "$process_pid" ]; then + process_name=$(ps -p "$process_pid" -o comm=) + echo "Occupied by $process_name with PID $process_pid." + echo "Port $port is needed to $reason" + read -p "Do you wish to terminate $process_name? [y/N] " -n 1 -r + echo + if [[ "$REPLY" =~ ^[Ss]$ ]]; then + echo "Skipping..." + return + fi + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Aborting due to occupied port" + exit 1 + else + service=$(ps -p "$process_pid" -o unit= | grep .service | grep -Ev ^user) + if [ -n "$service" ]; then + echo "Attempting to stop $service" + sudo systemctl stop "$service" + else + echo "Attempting to terminate $process_name" + sudo kill "$process_pid" + if ! sudo timeout 10 tail --pid="$process_pid" -f /dev/null; then + echo "$process_name is still running after 10 seconds, sending SIGKILL" + sudo kill -9 "$process_pid" + sudo tail --pid="$process_pid" -f /dev/null + fi + fi + sleep 1 + fi + else + echo "Available." + fi } check_firewall () { - if sudo systemctl stop firewalld.service &>/dev/null; then - echo "Attempting to stop firewalld.service" - echo "When done, enable with: ${bold}sudo systemctl start firewalld.service${normal}" - fi - if command -v ufw >/dev/null && sudo ufw status | grep -qw active; then - sudo ufw disable - echo "When done, enable with: ${bold}sudo ufw enable${normal}" - fi + if sudo systemctl stop firewalld.service &>/dev/null; then + echo "Attempting to stop firewalld.service" + echo "When done, enable with: ${bold}sudo systemctl start firewalld.service${normal}" + fi + if command -v ufw >/dev/null && sudo ufw status | grep -qw active; then + sudo ufw disable + echo "When done, enable with: ${bold}sudo ufw enable${normal}" + fi } check_blacklist () { - if [ -e /etc/modprobe.d/blacklist-rtl8192cu.conf ]; then - echo "Detected /etc/modprobe.d/blacklist-rtl8192cu.conf" - echo "This has been known to cause kernel panic in hostapd" - echo "See https://github.com/ct-Open-Source/tuya-convert/issues/373" - read -p "Do you wish to remove this file? [y/N] " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - sudo rm /etc/modprobe.d/blacklist-rtl8192cu.conf - fi - fi + if [ -e /etc/modprobe.d/blacklist-rtl8192cu.conf ]; then + echo "Detected /etc/modprobe.d/blacklist-rtl8192cu.conf" + echo "This has been known to cause kernel panic in hostapd" + echo "See https://github.com/ct-Open-Source/tuya-convert/issues/373" + read -p "Do you wish to remove this file? [y/N] " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + sudo rm /etc/modprobe.d/blacklist-rtl8192cu.conf + fi + fi } echo "" @@ -77,4 +77,4 @@ check_port tcp 8886 "run MQTTS" check_firewall check_blacklist echo "Safety checks complete." -echo "" \ No newline at end of file +echo "" diff --git a/tuya-cloudcutter.sh b/tuya-cloudcutter.sh index 44138bd..add06e1 100755 --- a/tuya-cloudcutter.sh +++ b/tuya-cloudcutter.sh @@ -12,52 +12,54 @@ function getopts-extra () { done } -while getopts "hrntvw:p:f:d:l:s::a:k:u:" flag; do - case "$flag" in - r) RESETNM="true";; - n) DISABLE_RESCAN="true";; - v) VERBOSE_OUTPUT="true";; - w) WIFI_ADAPTER=${OPTARG};; - p) PROFILE=${OPTARG};; - f) FIRMWARE=${OPTARG} +while getopts "hrntvw:p:f:d:l:s::a:k:u:o:" flag; do + case "$flag" in + r) RESETNM="true";; + n) DISABLE_RESCAN="true";; + v) VERBOSE_OUTPUT="true";; + w) WIFI_ADAPTER=${OPTARG};; + p) PROFILE=${OPTARG};; + f) FIRMWARE=${OPTARG} METHOD_FLASH="true" - ;; - t) FLASH_TIMEOUT=${OPTARG};; - d) DEVICEID=${OPTARG};; - l) LOCALKEY=${OPTARG};; - a) AUTHKEY=${OPTARG};; - k) PSKKEY=${OPTARG};; - u) UUID=${OPTARG};; - s) getopts-extra "$@" + ;; + t) FLASH_TIMEOUT=${OPTARG};; + d) DEVICEID=${OPTARG};; + l) LOCALKEY=${OPTARG};; + a) AUTHKEY=${OPTARG};; + k) PSKKEY=${OPTARG};; + u) UUID=${OPTARG};; + o) OVERRIDE_SSID=${OPTARG};; + s) getopts-extra "$@" METHOD_DETACH="true" - HAVE_SSID="true" - SSID_ARGS=( "${OPTARG[@]}" ) - SSID=${SSID_ARGS[0]} - SSID_PASS=${SSID_ARGS[1]} - ;; - h) - echo "usage: $0 [OPTION]..." + HAVE_SSID="true" + SSID_ARGS=( "${OPTARG[@]}" ) + SSID=${SSID_ARGS[0]} + SSID_PASS=${SSID_ARGS[1]} + ;; + h) + echo "usage: $0 [OPTION]..." echo " -h Show this message" echo " -r Reset NetworkManager" - echo " -n No Rescan (for older versions of nmcli that don't support it)" - echo " -v Verbose log output" + echo " -n No Rescan (for older versions of nmcli that don't support it)" + echo " -o TEXT Override specific device AP name to connect to" + echo " -v Verbose log output" echo " -w TEXT WiFi adapter name (optional, auto-selected if not supplied)" echo " -p TEXT Device profile name, AKA Device Slug (optional)" - echo " -a TEXT AuthKey of the device (optional, requires UUID and PSKKey accompanied with it)" - echo " -k TEXT PSKKey of the device (optinal, requires AuthKey and UUID accompanied with it)" - echo " -u TEXT UUID of the device (optional, requires AuthKey and PSKKey accompanied with it)" - echo "" + echo " -a TEXT AuthKey of the device (optional, requires UUID and PSKKey accompanied with it)" + echo " -k TEXT PSKKey of the device (optinal, requires AuthKey and UUID accompanied with it)" + echo " -u TEXT UUID of the device (optional, requires AuthKey and PSKKey accompanied with it)" + echo "" echo "==== Detaching Only: ====" echo " -s SSID PASSWORD Wifi SSID and Password to use for detaching. Use quotes if either value contains spaces. Certain special characters may need to be escaped with '\\'" echo " -d TEXT New device id (optional)" - echo " -l TEXT New local key (optional)" - echo "" + echo " -l TEXT New local key (optional)" + echo "" echo "==== 3rd Party Firmware Flashing Only: ====" echo " -f TEXT Firmware file name without path as it exists in /custom-firmware/ (optional)" - echo " -t SECONDS Timeout in seconds for how long to wait before exiting after receiving firmware update information. Default is 15" - - exit 0 - esac + echo " -t SECONDS Timeout in seconds for how long to wait before exiting after receiving firmware update information. Default is 15" + + exit 0 + esac done if [ $METHOD_DETACH ] && [ $METHOD_FLASH ]; then @@ -75,20 +77,20 @@ if [ ! $METHOD_DETACH ] && [ ! $METHOD_FLASH ]; then select method in "Detach from the cloud and run Tuya firmware locally" "Flash 3rd Party Firmware"; do case $REPLY in 1) METHOD_DETACH="true" - break - ;; + break + ;; 2) METHOD_FLASH="true" - break - ;; + break + ;; esac done fi if [ $METHOD_DETACH ] && [ ! $HAVE_SSID ]; then echo "Detaching requires an SSID and Password, please enter each at the following prompt" - echo "In order to provide secure logging, the values you type for your password will not show on screen" - echo "If you make a mistake, you can run the detach process again" - echo "You can also pass credentials via the -s command line option, see '${0} -h' for more information'" + echo "In order to provide secure logging, the values you type for your password will not show on screen" + echo "If you make a mistake, you can run the detach process again" + echo "You can also pass credentials via the -s command line option, see '${0} -h' for more information'" read -p "Please enter your SSID: " SSID read -p "Please enter your Password: "$'\n' -s SSID_PASS fi @@ -98,55 +100,55 @@ echo "Loading options, please wait..." source common_run.sh if [ $METHOD_DETACH ]; then - # Cutting device from cloud, allowing local-tuya access still - echo "Cutting device off from cloud..." - echo "" - echo "================================================================================" - echo "Wait for up to 10-120 seconds for the device to connect to 'cloudcutterflash'. This script will then show the activation requests sent by the device, and tell you whether local activation was successful." - echo "================================================================================" - echo "" + # Cutting device from cloud, allowing local-tuya access still + echo "Cutting device off from cloud..." + echo "" + echo "================================================================================" + echo "Wait for up to 10-120 seconds for the device to connect to 'cloudcutterflash'. This script will then show the activation requests sent by the device, and tell you whether local activation was successful." + echo "================================================================================" + echo "" - nmcli device set ${WIFI_ADAPTER} managed no; service NetworkManager stop; - trap "service NetworkManager start; nmcli device set ${WIFI_ADAPTER} managed yes" EXIT # Set WiFi adapter back to managed when the script exits - INNER_SCRIPT=$(xargs -0 <<- EOF - # This janky looking string substitution is because of double evaluation. - # Once in the parent shell script, and once in this heredoc used as a shell script. - # First evaluate the value from the parent shell script while escaping ' chars - # with this janky substitutions so that it doesn't break this heredoc script. - SSID='${SSID/\'/\'\"\'\"\'}' - SSID_PASS='${SSID_PASS/\'/\'\"\'\"\'}' - bash /src/setup_apmode.sh ${WIFI_ADAPTER} ${VERBOSE_OUTPUT} - pipenv run python3 -m cloudcutter configure_local_device --ssid "\${SSID}" --password "\${SSID_PASS}" "${PROFILE}" "/work/device-profiles/schema" "${CONFIG_DIR}" ${FLASH_TIMEOUT} "${VERBOSE_OUTPUT}" - EOF - ) - run_in_docker bash -c "$INNER_SCRIPT" - if [ ! $? -eq 0 ]; then - echo "Oh no, something went wrong with detaching from the cloud! Try again I guess..." - if [ ! $VERBOSE_OUTPUT ]; then - echo "If you need to report an issue, please run with the -v flag and supply the full log of that attempt." - fi - exit 1 - fi + nmcli device set ${WIFI_ADAPTER} managed no; service NetworkManager stop; + trap "service NetworkManager start; nmcli device set ${WIFI_ADAPTER} managed yes" EXIT # Set WiFi adapter back to managed when the script exits + INNER_SCRIPT=$(xargs -0 <<- EOF + # This janky looking string substitution is because of double evaluation. + # Once in the parent shell script, and once in this heredoc used as a shell script. + # First evaluate the value from the parent shell script while escaping ' chars + # with this janky substitutions so that it doesn't break this heredoc script. + SSID='${SSID/\'/\'\"\'\"\'}' + SSID_PASS='${SSID_PASS/\'/\'\"\'\"\'}' + bash /src/setup_apmode.sh ${WIFI_ADAPTER} ${VERBOSE_OUTPUT} + pipenv run python3 -m cloudcutter configure_local_device --ssid "\${SSID}" --password "\${SSID_PASS}" "${PROFILE}" "/work/device-profiles/schema" "${CONFIG_DIR}" ${FLASH_TIMEOUT} "${VERBOSE_OUTPUT}" +EOF + ) + run_in_docker bash -c "$INNER_SCRIPT" + if [ ! $? -eq 0 ]; then + echo "Oh no, something went wrong with detaching from the cloud! Try again I guess..." + if [ ! $VERBOSE_OUTPUT ]; then + echo "If you need to report an issue, please run with the -v flag and supply the full log of that attempt." + fi + exit 1 + fi fi if [ $METHOD_FLASH ]; then - # Flash custom firmware to device - echo "Flashing custom firmware..." - echo "" - echo "================================================================================" - echo "Wait for up to 10-120 seconds for the device to connect to 'cloudcutterflash'. This script will then show the firmware upgrade requests sent by the device." - echo "================================================================================" - echo "" - nmcli device set "${WIFI_ADAPTER}" managed no - trap "nmcli device set ${WIFI_ADAPTER} managed yes" EXIT # Set WiFi adapter back to managed when the script exits - run_in_docker bash -c "bash /src/setup_apmode.sh ${WIFI_ADAPTER} ${VERBOSE_OUTPUT} && pipenv run python3 -m cloudcutter update_firmware \"${PROFILE}\" \"/work/device-profiles/schema\" \"${CONFIG_DIR}\" \"/work/custom-firmware/\" \"${FIRMWARE}\" \"${FLASH_TIMEOUT}\" \"${VERBOSE_OUTPUT}\"" - if [ ! $? -eq 0 ]; then - echo "Oh no, something went wrong with updating firmware! Try again I guess..." - if [ ! $VERBOSE_OUTPUT ]; then - echo "If you need to report an issue, please run with the -v flag and supply the full log of that attempt." - fi - exit 1 - fi + # Flash custom firmware to device + echo "Flashing custom firmware..." + echo "" + echo "================================================================================" + echo "Wait for up to 10-120 seconds for the device to connect to 'cloudcutterflash'. This script will then show the firmware upgrade requests sent by the device." + echo "================================================================================" + echo "" + nmcli device set "${WIFI_ADAPTER}" managed no + trap "nmcli device set ${WIFI_ADAPTER} managed yes" EXIT # Set WiFi adapter back to managed when the script exits + run_in_docker bash -c "bash /src/setup_apmode.sh ${WIFI_ADAPTER} ${VERBOSE_OUTPUT} && pipenv run python3 -m cloudcutter update_firmware \"${PROFILE}\" \"/work/device-profiles/schema\" \"${CONFIG_DIR}\" \"/work/custom-firmware/\" \"${FIRMWARE}\" \"${FLASH_TIMEOUT}\" \"${VERBOSE_OUTPUT}\"" + if [ ! $? -eq 0 ]; then + echo "Oh no, something went wrong with updating firmware! Try again I guess..." + if [ ! $VERBOSE_OUTPUT ]; then + echo "If you need to report an issue, please run with the -v flag and supply the full log of that attempt." + fi + exit 1 + fi fi run_helper_script "post-flash" \ No newline at end of file