Skip to content

Commit

Permalink
Merge pull request #3338 from AllskyTeam/Add-uhubctl
Browse files Browse the repository at this point in the history
Add the uhubctl command
  • Loading branch information
EricClaeys authored Jan 22, 2024
2 parents 9471a3e + a93b348 commit 035a767
Show file tree
Hide file tree
Showing 9 changed files with 1,358 additions and 101 deletions.
130 changes: 67 additions & 63 deletions allsky.sh
Original file line number Diff line number Diff line change
Expand Up @@ -115,29 +115,46 @@ if [[ ${CAMERA_TYPE} == "RPi" ]]; then
elif [[ ${CAMERA_TYPE} == "ZWO" ]]; then
RPi_COMMAND_TO_USE=""
RESETTING_USB_LOG="${ALLSKY_TMP}/resetting_USB.txt"
ZWO_VENDOR="03c3"
TEMP="${ALLSKY_TMP}/${CAMERA_TYPE}_cameras.txt"
# Output will be: camera_model TAB ZWO_camera_ID for each camera found.
# The awk code assumes idProduct comes before iProduct.
CAMERAS="$( lsusb -d "${ZWO_VENDOR}:" -v 2>/dev/null |
awk '{
if ($1 == "idProduct") {
idProduct = substr($2, 3);
} else if ($1 == "iProduct") {
printf("%s\t%s\n", $3, idProduct);
exit(0);
}
}'
)"
NUM_CAMERAS=$( echo "${CAMERAS}" | wc -l )

reset_usb() # resets the USB bus
{
REASON="${1}" # why are we resetting the bus?
# Only reset a couple times, then exit with fatal error.
if [[ -f ${RESETTING_USB_LOG} ]]; then
NUM_USB_RESETS=$( < "${RESETTING_USB_LOG}" )
if [[ ${NUM_USB_RESETS} -eq 2 ]]; then
MSG="FATAL ERROR: Too many consecutive USB bus resets done (${NUM_USB_RESETS})."
echo -e "${RED}*** ${MSG} Stopping." >&2
if [[ ${NUM_USB_RESETS} -ge 2 ]]; then
MSG="Too many consecutive USB bus resets done (${NUM_USB_RESETS})."
echo -e "${RED}*** FATAL ERROR: ${MSG} Stopping Allsky.${NC}" >&2
rm -f "${RESETTING_USB_LOG}"
doExit "${EXIT_ERROR_STOP}" "Error" \
doExit "${EXIT_ERROR_STOP}" \
"Error" \
"${ERROR_MSG_PREFIX}\nToo many consecutive\nUSB bus resets done!\n${SEE_LOG_MSG}" \
"${NOT_STARTED_MSG}<br>${MSG}"
"${NOT_STARTED_MSG}: ${MSG}"
fi
else
NUM_USB_RESETS=0
fi

MSG="${YELLOW}WARNING: Resetting USB ports ${REASON/\\n/ }"
MSG="WARNING: Resetting USB ports ${REASON/\\n/ }"
if [[ ${ON_TTY} == "true" ]]; then
echo "${MSG}; restart ${ME} when done.${NC}" >&2
echo "${YELLOW}${MSG}; restart ${ME} when done.${NC}" >&2
else
echo "${MSG}, then restarting.${NC}" >&2
echo "${MSG}, then restarting." >&2
# The service will automatically restart this script.
fi

Expand All @@ -148,45 +165,41 @@ elif [[ ${CAMERA_TYPE} == "ZWO" ]]; then
"${ALLSKY_SCRIPTS}/generate_notification_images.sh" --directory "${ALLSKY_TMP}" "${FILENAME}" \
"yellow" "" "85" "" "" \
"" "5" "yellow" "${EXTENSION}" "" "WARNING:\n\nResetting USB bus\n${REASON}.\nAttempt ${NUM_USB_RESETS}."
sudo "${UHUBCTL_PATH}" -a cycle -l "${UHUBCTL_PORT}"
SEARCH="${ZWO_VENDOR}:${ZWO_CAMERA_ID}"
sudo "${ALLSKY_BIN}/uhubctl" --action cycle --exact --search "${SEARCH}"
sleep 3 # give it a few seconds, plus, allow the notification images to be seen
}

# "03c3" is the USB ID for ZWO devices.
ZWOdev=$( lsusb -d '03c3:' | awk '{ bus=$2; dev=$4; gsub(/[^0-9]/,"",dev); print "/dev/bus/usb/"bus"/"dev;}' )
# We have to run "lsusb -D" once for each device returned by "lsusb -d", and can't
# use "echo x | while read" because variables set inside the "while" loop don't get exposed
# to the calling code, so use a temp file.

TEMP="${ALLSKY_TMP}/${CAMERA_TYPE}_cameras.txt"
echo "${ZWOdev}" > "${TEMP}"
NUM=0
while read -r DEV
do
lsusb -D "${DEV}" 2>/dev/null | grep --silent 'iProduct .*ASI[0-9]' && ((NUM++))
done < "${TEMP}"

if [[ ${NUM} -eq 0 ]]; then
if [[ -n ${UHUBCTL_PATH} ]] ; then
reset_usb "looking for a\nZWO camera" # reset_usb exits if too many tries
exit 0 # exit with 0 so the service is restarted
else
MSG="FATAL ERROR: ZWO Camera not found"
echo -en "${RED}*** ${MSG}" >&2
if [[ ${ZWOdev} == "" ]]; then
echo " and no USB entry either.${NC}" >&2
USB_MSG=""
else
echo " but ${ZWOdev} found.${NC}" >&2
USB_MSG="\n${SEE_LOG_MSG}"
fi
if [[ ${NUM_CAMERAS} -eq 0 ]]; then
# reset_usb() exits if too many tries
reset_usb "looking for a\nZWO camera"
exit 0 # exit with 0 so the service is restarted
fi

echo " If you have the 'uhubctl' command installed, add it to config.sh." >&2
echo " In the meantime, try running it to reset the USB bus." >&2
doExit "${EXIT_NO_CAMERA}" "Error" \
"${ERROR_MSG_PREFIX}\nNo ZWO camera\nfound!${USB_MSG}" \
"${NOT_STARTED_MSG}<br>${MSG}<br>${SEE_LOG_MSG}."
fi
echo "${CAMERAS}" > "${TEMP}"

# See if the user changed camera models without telling Allsky.
# Get the ZWO ID for the camera model in the settings file and
# check if that camera is currently connected.
ZWO_CAMERA_ID="$( echo "${CAMERAS}" |
awk -v MODEL="${CAMERA_MODEL}" '
{
if ($1 == MODEL) {
print $2;
exit(0);
}
}'
)"
if [[ -z ${ZWO_CAMERA_ID} ]]; then
MSG="ZWO camera model '${CAMERA_MODEL}' not found."
MSG="${MSG}\nConnected cameras are:"
MSG="${MSG}\n$( echo "${CAMERAS}" | awk '{ printf(" * %s\n", $1); }' )"
MSG="${MSG}\nIf you changed cameras, select 'Refresh' for the"
MSG="${MSG} Camera Type on the Allsky Settings page."
doExit "${EXIT_ERROR_STOP}" \
"Error" \
"${NOT_STARTED_MSG}\nZWO camera\n${CAMERA_MODEL}\nnot found!" \
"${NOT_STARTED_MSG} ${MSG}"
fi

rm -f "${RESETTING_USB_LOG}" # We found the camera so don't need to reset.
Expand Down Expand Up @@ -306,34 +319,25 @@ if [[ ${RETCODE} -eq ${EXIT_RESTARTING} ]]; then
fi

if [[ ${RETCODE} -eq ${EXIT_RESET_USB} ]]; then
# Reset the USB bus if possible
if [[ ${UHUBCTL_PATH} != "" ]]; then
reset_usb " (ASI_ERROR_TIMEOUTs)"
if [[ ${ON_TTY} == "true" ]]; then
echo "*** USB bus was reset; You can restart allsky now. ***"
NOTIFICATION_TYPE="NotRunning"
else
NOTIFICATION_TYPE="Restarting"
fi
if [[ ${USE_NOTIFICATION_IMAGES} == "true" ]]; then
"${ALLSKY_SCRIPTS}/copy_notification_image.sh" "${NOTIFICATION_TYPE}"
fi
doExit 0 "" # use 0 so the service is restarted
# Reset the USB bus
reset_usb " (too many capture errors)"
if [[ ${ON_TTY} == "true" ]]; then
echo "*** USB bus was reset; You can restart allsky now. ***"
NOTIFICATION_TYPE="NotRunning"
else
# TODO: use ASI_ERROR_TIMEOUT message
MSG="Non-recoverable ERROR found"
[[ ${ON_TTY} == "true" ]] && echo "*** ${MSG} - ${SEE_LOG_MSG}. ***"
doExit "${EXIT_ERROR_STOP}" "Error" \
"${ERROR_MSG_PREFIX}Too many\nASI_ERROR_TIMEOUT\nerrors received!\n${SEE_LOG_MSG}" \
"${STOPPED_MSG}<br>${MSG}<br>${SEE_LOG_MSG}."
NOTIFICATION_TYPE="Restarting"
fi
if [[ ${USE_NOTIFICATION_IMAGES} == "true" ]]; then
"${ALLSKY_SCRIPTS}/copy_notification_image.sh" "${NOTIFICATION_TYPE}"
fi
doExit 0 "" # use 0 so the service is restarted
fi

# RETCODE -ge ${EXIT_ERROR_STOP} means we should not restart until the user fixes the error.
if [[ ${RETCODE} -ge ${EXIT_ERROR_STOP} ]]; then
echo "***"
if [[ ${ON_TTY} == "true" ]]; then
echo "*** After fixing, restart ${ME}.sh. ***"
echo "*** After fixing, restart ${ME}. ***"
else
echo "*** After fixing, restart the allsky service. ***"
fi
Expand Down
4 changes: 0 additions & 4 deletions config_repo/config.sh.repo
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,6 @@ WEB_DAYS_TO_KEEP=0
# See the documentation for a description of this setting.
WEBUI_DATA_FILES=""

# See the documentation for a description of these settings.
UHUBCTL_PATH=""
UHUBCTL_PORT=2


# ================ DO NOT CHANGE ANYTHING BELOW THIS LINE ================
ME2="$(basename "${BASH_SOURCE[0]}")"
Expand Down
13 changes: 0 additions & 13 deletions html/documentation/settings/allsky.html
Original file line number Diff line number Diff line change
Expand Up @@ -1241,19 +1241,6 @@ <h3>config.sh settings</h3>
See the <a allsky="true" href="/documentation/eplanations/SystemPageAdditions.html">WEBUI_DATA_FILES page</a>
for more information and an example of this setting.</td>
</tr>
<tr><td><span class="shSetting">UHUBCTL_PATH</span></td>
<td></td>
<td>If you have the <code>uhubctl</code> command installed enter its path name.
<code>uhubctl</code> resets the USB bus and can sometimes eliminate ASI_ERROR_TIMEOUTs
and/or "find" a camera that isn't showing up.
</td>
</tr>
<tr><td><span class="shSetting">UHUBCTL_PORT</span></td>
<td>2</td>
<td>Enter the USB port the camera is on.
Port 1 is USB 2.0 and port 2 is USB 3.0 on a Pi 4.
<br>Ignored if <span class="shSetting">UHUBCTL_PATH</span> is not set.</td>
</tr>

<tr><td class="note" colspan="3">Do not change anything lower in the file</td></tr>
</tbody>
Expand Down
1 change: 0 additions & 1 deletion scripts/check_allsky.sh
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,6 @@ fi
check_exists "WEB_VIDEOS_DIR"
check_exists "WEB_KEOGRAM_DIR"
check_exists "WEB_STARTRAILS_DIR"
check_exists "UHUBCTL_PATH"

##### Check for Allsky Website-related issues.
if [[ -f ${ALLSKY_REMOTE_WEBSITE_CONFIGURATION_FILE} && (${PROTOCOL} == "" || ${PROTOCOL} == "local") ]]; then
Expand Down
2 changes: 1 addition & 1 deletion scripts/functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function doExit()
if [[ -n ${WEBUI_MESSAGE} ]]; then
[[ ${TYPE} = "no-image" ]] && TYPE="success"
"${ALLSKY_SCRIPTS}/addMessage.sh" "${TYPE}" "${WEBUI_MESSAGE}"
echo "Stopping Allsky: ${WEBUI_MESSAGE}"
echo -e "Stopping Allsky: ${WEBUI_MESSAGE}" >&2
OUTPUT_A_MSG="true"
fi

Expand Down
19 changes: 15 additions & 4 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ endif

CFLAGS += $(DEFS) $(ZWOSDK)

all:check_deps capture_ZWO capture_RPi startrails keogram sunwait
all:check_deps capture_ZWO capture_RPi startrails keogram sunwait uhubctl
.PHONY : all

ifneq ($(shell id -u), 0)
deps:
echo This must be ran with root permissions.
echo This must be run with root permissions.
echo Please run 'sudo make deps'
else
deps:
Expand Down Expand Up @@ -154,19 +154,26 @@ startrails:startrails.cpp
@$(CC) $@.cpp -o $@ $(CFLAGS) $(OPENCV)
@echo `date +%F\ %R:%S` Done.

uhubctl:uhubctl.c
@echo `date +%F\ %R:%S` Building $@ program...
# This comes from the uhubctl Makefile:
@cc -g -O0 -Wall -Wextra -std=c99 -pedantic -DPROGRAM_VERSION=\"2.5.0\" -I/usr/include/libusb-1.0 [email protected] -o $@ -Wl,-zrelro,-znow -lusb-1.0
@echo `date +%F\ %R:%S` Done.

symlink: all
@echo `date +%F\ %R:%S` Symlinking binaries...
@ln -s $$PWD/capture_ZWO ../bin/
@ln -s $$PWD/capture_RPi ../bin/
@ln -s $$PWD/keogram ../bin/
@ln -s $$PWD/startrails ../bin/
@ln -s $$PWD/uhubctl ../bin/

.PHONY: symlink

ifneq ($(ROOTCHECK), 0)
install uninstall:
@echo This must be run with root permissions.
@echo Please run \'sudo make $@\'
@echo Please run 'sudo make $@'
else
install:
@echo `date +%F\ %R:%S` Copying binaries...
Expand All @@ -176,12 +183,14 @@ install:
install capture_RPi $(DESTDIR)$(bindir); \
install keogram $(DESTDIR)$(bindir); \
install startrails $(DESTDIR)$(bindir); \
install uhubctl $(DESTDIR)$(bindir); \
else \
[ ! -e ../bin ] && mkdir -p ../bin; \
install -o $(SUDO_USER) -g $(SUDO_USER) capture_ZWO ../bin/; \
install -o $(SUDO_USER) -g $(SUDO_USER) capture_RPi ../bin/; \
install -o $(SUDO_USER) -g $(SUDO_USER) keogram ../bin/; \
install -o $(SUDO_USER) -g $(SUDO_USER) startrails ../bin/; \
install -o $(SUDO_USER) -g $(SUDO_USER) uhubctl ../bin/; \
fi
@install sunwait $(DESTDIR)$(bindir)

Expand All @@ -193,18 +202,20 @@ uninstall:
rm -f $(DESTDIR)$(bindir)/keogram; \
rm -f $(DESTDIR)$(bindir)/startrails; \
rm -f $(DESTDIR)$(bindir)/sunwait; \
rm -f $(DESTDIR)$(bindir)/uhubctl; \
else \
rm -f ../bin/capture_ZWO; \
rm -f ../bin/capture_RPi; \
rm -f ../bin/keogram; \
rm -f ../bin/startrails; \
rm -f ../bin/uhubctl; \
fi

endif # sudo / root check
.PHONY : install uninstall

clean:
rm -f capture_ZWO capture_RPi startrails keogram sunwait *.o *.a
rm -f capture_ZWO capture_RPi startrails keogram sunwait uhubctl *.o *.a
.PHONY : clean

endif # Correct directory structure check
Expand Down
16 changes: 16 additions & 0 deletions src/UHUBCTL_LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
uhubctl � USB hub per-port power control.

Copyright (c) 2009-2023, Vadim Mikhailov

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Loading

0 comments on commit 035a767

Please sign in to comment.