From 409ffa19a5d17d4e07a0fe93d6298c7a635a7252 Mon Sep 17 00:00:00 2001 From: Fischertechnik-OpenSource <fischertechnik-opensource@online.de> Date: Wed, 12 Feb 2025 11:47:30 +0100 Subject: [PATCH] Update to 3.1.8 --- bin/nightly_dev_installer | 35 +++++ bin/txt_compile | 38 +++++ bin/txt_compile_exec | 26 +++- bin/txt_debug_qtmenu | 2 + bin/txt_lan_setup | 147 +++++++++++++++++++ bin/txt_nodered | 61 +++++++- bin/txt_open_roberta | 98 +++++++++++++ bin/txt_open_roberta_service.template | 40 ++++++ bin/txt_run | 58 ++++++++ bin/txt_servo | 181 ++++++++++++++++++++--- bin/txt_servo_setpos | 38 +++++ bin/txt_update_avahi | 10 +- bin/txt_usb_gadget | 1 + bin/txt_wifi_setup | 198 ++++++++++++++++++++++---- src/txt_servo_setpos.cpp | 75 ++++++++++ 15 files changed, 952 insertions(+), 56 deletions(-) create mode 100644 bin/nightly_dev_installer create mode 100644 bin/txt_compile create mode 100644 bin/txt_debug_qtmenu create mode 100644 bin/txt_lan_setup create mode 100755 bin/txt_open_roberta create mode 100755 bin/txt_open_roberta_service.template create mode 100644 bin/txt_run create mode 100644 bin/txt_servo_setpos create mode 100644 src/txt_servo_setpos.cpp diff --git a/bin/nightly_dev_installer b/bin/nightly_dev_installer new file mode 100644 index 0000000..7056e30 --- /dev/null +++ b/bin/nightly_dev_installer @@ -0,0 +1,35 @@ +#!/bin/bash + +get_volume() +{ + for dev in mmcblk1p1 sda sdb sdc sdd + do + vol="$(mount | grep /dev/$dev | awk '{print $3}')" + if [ "$vol" ] + then + echo "$vol" + return 0 + fi + done + return 1 +} + +vol=$(get_volume) +if [ ! "$vol" ] +then + echo "Please insert USB-Stick or microSD card first..." + exit 1 +fi + +echo "entering $vol..." +cd $vol + +echo "Starting download & update..." +login="Wm1selkyaGxjblJsWTJodWFXczZSbFFoTWpOVVdGUTBNQW8K" +url="Wm5RdGRIaDBOREF0WkdWaWRXY3VjMmx0Y0d4bExYVnliQzVqYjIwdk15NHhMalV2Q2c9PQo=" +webcontent="$(curl -s "http://$(echo $login | base64 -d 2>/dev/null | base64 -d 2>/dev/null)@$(echo $url | base64 -d 2>/dev/null | base64 -d 2>/dev/null)")" +fw="$(echo "$webcontent" | grep -Eo "image-\S+raucb")" + +echo "Using $fw for update..." +rm image-*.raucb 2> /dev/null || true +curl http://$(echo $login | base64 -d 2>/dev/null | base64 -d 2>/dev/null)@$(echo $url | base64 -d 2>/dev/null | base64 -d 2>/dev/null)$fw -o $fw && rauc_install.sh -p $fw && reboot \ No newline at end of file diff --git a/bin/txt_compile b/bin/txt_compile new file mode 100644 index 0000000..bded920 --- /dev/null +++ b/bin/txt_compile @@ -0,0 +1,38 @@ +#!/bin/bash +# Script-helper to compile and execute cpp / c file +# +# Copyright (c) 2023 Accso. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +src_file_param="$1" +src_file=$(realpath "$src_file_param") +src_folder=$(dirname "$src_file") +src_filename=$(basename -- "$src_file") +extension="${src_filename##*.}" +shift +if [ "$extension" == "cpp" ] +then + COMPILER="/usr/bin/g++" +else + + COMPILER="/usr/bin/gcc" +fi + +binfile=$src_folder/"${src_filename%.*}" +FLAGS="-Wall -Wpedantic -Wextra -Wfatal-errors -I/usr/include/ft/ -lm -lcftlock -lTxtControlLib -L/usr/lib -o $binfile" + +$COMPILER $FLAGS $src_file_param +chmod +x $binfile \ No newline at end of file diff --git a/bin/txt_compile_exec b/bin/txt_compile_exec index 86f5bd3..0372bf4 100644 --- a/bin/txt_compile_exec +++ b/bin/txt_compile_exec @@ -1,8 +1,28 @@ #!/bin/bash -src_file=$(realpath "$1") +# Script-helper to compile and execute cpp / c file +# +# Copyright (c) 2023 Accso. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +src_file_param="$1" +src_file=$(realpath "$src_file_param") src_folder=$(dirname "$src_file") src_filename=$(basename -- "$src_file") extension="${src_filename##*.}" +shift if [ "$extension" == "cpp" ] then COMPILER="/usr/bin/g++" @@ -14,7 +34,7 @@ fi binfile=$src_folder/"${src_filename%.*}" FLAGS="-Wall -Wpedantic -Wextra -Wfatal-errors -I/usr/include/ft/ -lm -lcftlock -lTxtControlLib -L/usr/lib -o $binfile" -$COMPILER $FLAGS $1 +$COMPILER $FLAGS $src_file_param chmod +x $binfile -sudo -u ftgui $binfile \ No newline at end of file +sudo -u ftgui $binfile $@ \ No newline at end of file diff --git a/bin/txt_debug_qtmenu b/bin/txt_debug_qtmenu new file mode 100644 index 0000000..8c25493 --- /dev/null +++ b/bin/txt_debug_qtmenu @@ -0,0 +1,2 @@ +#!/bin/sh +journalctl --follow -u qtmenu \ No newline at end of file diff --git a/bin/txt_lan_setup b/bin/txt_lan_setup new file mode 100644 index 0000000..19b7f39 --- /dev/null +++ b/bin/txt_lan_setup @@ -0,0 +1,147 @@ +#!/bin/bash +# Main script to configure LAN settings +# +# Copyright (c) 2023 Accso. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Usage + +usage() +{ + echo "Usage: txt_lan_setup status" + echo " txt_lan_setup ping <host>" + echo " txt_lan_setup init" +} + +# Assigning arguments + +parse_args() +{ + action="${1}" + case "${action}" in + 'ping') + host="${2}" + ;; + esac +} + +iface_get_flags() +{ + iface="$1" + if [ -d "/sys/class/net/${iface}" ]; then + cat "/sys/class/net/${iface}/flags" + else + echo "0x1002" + fi +} + +iface_get_operstate() +{ + iface="$1" + if [ -d "/sys/class/net/${iface}" ]; then + cat "/sys/class/net/${iface}/operstate" + else + echo "down" + fi +} + +iface_client_lan=eth0 +flags_client_lan=$(iface_get_flags "${iface_client_lan}") +status_client_lan=$(iface_get_operstate "${iface_client_lan}") + +# Arguments verification + +. /usr/share/txt2-utils/txt_aux_functions + +check_args() +{ + case "${action}" in + 'status'|'init') + check_nargs "$#" 1 + ;; + 'ping') + check_nargs "$#" 2 + check_notempty "${host}" + ;; + *) + usage + echo "BUG: Unsupported action: ${action}" >&2 + exit 22 # EINVAL + ;; + esac +} + +do_status() +{ + if [ ! -L "/sys/class/net/${iface_client_lan}" ] + then + echo 'ERROR' + exit 0 + # exit 19 # ENODEV + fi + flags_client_lan=$(iface_get_flags "${iface_client_lan}") + status_client_lan=$(iface_get_operstate "${iface_client_lan}") + + if [ "${flags_client_lan}" = '0x1003' ] && [ "${status_client_lan}" = 'up' ]; then + # Interface fully configured, link ready + echo 'CLIENT_LAN:ON' + echo "CLIENT_IP:$(expr match "$(/sbin/ip -4 address show dev "${iface_client_lan}")" '.*inet \([0-9.]*/[0-9]*\)')" + return + fi + echo 'OFF' +} + +do_ping() +{ + if [ "${flags_client_lan}" = '0x1003' ] && [ "${status_client_lan}" = 'up' ]; then + if /bin/ping -I"${iface_client_lan}" -c1 -W2 "${host}" >&2 > /dev/null; then + echo 'PING:OK' + return + fi + fi + echo 'PING:FAILED' +} + +do_init() +{ + if [ ! -L "/sys/class/net/${iface_client_lan}" ] + then + echo 'INIT:ERROR' + exit 19 # ENODEV + fi + echo 'INIT:OK' +} + +# Main + +# - check arguments +parse_args "$@" +check_args "$@" + +# - do what is requested + +case "${action}" in + 'status') + do_status + ;; + 'ping') + do_ping + ;; + 'init') + do_init + ;; +esac +exit 0 diff --git a/bin/txt_nodered b/bin/txt_nodered index b311f6c..c23db75 100755 --- a/bin/txt_nodered +++ b/bin/txt_nodered @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Script-helper to control node-red server service # # Copyright (c) 2023 Manuel Schreiner, Accso. All rights reserved. @@ -36,12 +36,71 @@ nodered_service='node-red' . /usr/share/txt2-utils/txt_aux_functions + +settings="/opt/ft/workspaces/.node-red/settings.js" +username="ft" +password='$2b$08$F4amApJEf8Sa0InwzKMDV.wM89rQW1NfKP/otryBuHp8ifTK1mGr6' + +gen_admin_auth() +{ +cat << EOF >> "$settings".new + adminAuth: { + type: "credentials", + users: [{ + username: "$username", + password: "$password", + permissions: "*" + }] + }, +EOF +} + +gen_settings() +{ + if [ ! -f $settings ]; then + node-red & + pid_nodered=$! + sleep 30 + kill $pid_nodered + fi + + #password=$(echo "fischertechnik" | node-red admin hash-pw) + #password="${password:10}" + + if [ -f "$settings".new ]; then + rm "$settings".new + fi + + block_auth="" + while read p; do + if grep -q "adminAuth:" <<< "$p"; then + block_auth="start" + fi + if [ "$block_auth" == "start" ]; then + gen_admin_auth + block_auth="written" + fi + if [ ! "$block_auth" ]; then + echo "$p" >> "$settings".new + fi + + if grep -q "}," <<< "$p"; then + block_auth="" + fi + done <$settings + + if [ -f "$settings".new ]; then + mv "$settings".new "$settings" + fi +} + # Main check_nargs "$#" 1 case "${action}" in 'on') err=0 + gen_settings /bin/systemctl start "${nodered_service}" || err=$? ;; 'off') diff --git a/bin/txt_open_roberta b/bin/txt_open_roberta new file mode 100755 index 0000000..94f93d2 --- /dev/null +++ b/bin/txt_open_roberta @@ -0,0 +1,98 @@ +#!/bin/sh +# Script-helper to control openroberta server service +# +# Copyright (c) 2023 Manuel Schreiner, Accso. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Usage + +usage() +{ + echo "Usage: sudo txt_open_roberta <on|off|status>" +} + +# Assigning arguments + +action="${1}" + +# Setttings + +openroberta_service='openroberta' +openroberta_sessions='openroberta@*.service' +openroberta_config_template='/usr/share/openroberta/openrobertaconfig.json' +openroberta_config='/opt/ft/config/openrobertaconfig.json' + +# Arguments verification + +. /usr/share/txt2-utils/txt_aux_functions + +# Main + +if [ ! -f "${openroberta_config}" ]; +then + cp "${openroberta_config_template}" "${openroberta_config}" + chown ftgui:ftgui "${openroberta_config}" + chmod 640 "${openroberta_config}" +fi + +# make sure template is used to copy all new fields + +/usr/bin/jq -s 'reduce .[] as $item ({}; . *= $item)' "${openroberta_config_template}" "${openroberta_config}" > "${openroberta_config}.tmp" +cp "${openroberta_config}.tmp" "${openroberta_config}" +rm -Rf ${openroberta_config}.tmp + +check_nargs "$#" 1 +case "${action}" in + 'on') + err=0 + chown ftgui:ftgui "${openroberta_config}" + /bin/systemctl start "${openroberta_service}" || err=$? + ;; + 'off') + err=0 + /bin/systemctl kill "${openroberta_sessions}" || err=$? + /bin/systemctl stop "${openroberta_service}" || err=$? + ;; + 'restart') + err=0 + chown ftgui:ftgui "${openroberta_config}" + /bin/systemctl kill "${openroberta_sessions}" || true + /bin/systemctl stop "${openroberta_service}" || true + /bin/systemctl start "${openroberta_service}" || err=$? + ;; + 'status') + state1="$(/bin/systemctl is-active "${openroberta_service}")" + err=0 + if [ "${state1}" = 'active' ]; then + echo "OpenRoberta:ON" + elif [ "${state1}" = 'inactive' ]; then + echo "OpenRoberta:OFF" + else + echo "OpenRoberta:ERROR" + err=22 # EINVAL + fi + ;; + '--help') + usage + err=0 + ;; + *) + usage + echo "BUG: Unsupported action: ${action}" >&2 + err=22 # EINVAL + ;; +esac +exit ${err} diff --git a/bin/txt_open_roberta_service.template b/bin/txt_open_roberta_service.template new file mode 100755 index 0000000..456c57f --- /dev/null +++ b/bin/txt_open_roberta_service.template @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +########################################## +# +# Python template... +# +# (c) Manuel Schreiner, Accso +# + +########################################## +# Import section... +########################################## + +import time +import signal +import sys + +########################################## +# Functions section... +########################################## + +def _exit(sig, frame): + print("exit...") + appRunning = False + sys.exit(0) + +def heartBeat(): + print("Heart-Beat from Python...") + +########################################## +# Main script ... +########################################## + +appRunning = True + +signal.signal(signal.SIGINT, _exit) +signal.signal(signal.SIGTERM, _exit) + +while appRunning: + heartBeat() + time.sleep(1) diff --git a/bin/txt_run b/bin/txt_run new file mode 100644 index 0000000..43ea132 --- /dev/null +++ b/bin/txt_run @@ -0,0 +1,58 @@ +#!/bin/bash +# Script-helper to compile and execute cpp / c file +# +# Copyright (c) 2023 Accso. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +src_file_param="$1" +src_file=$(realpath "$src_file_param") +src_folder=$(dirname "$src_file") +src_filename=$(basename -- "$src_file") +filename="${src_filename%.*}" +extension="${src_filename##*.}" +extension=${extension,,} +username=$(whoami) +shift + +cd "$src_folder" + +case "${extension}" in + "ft") + echo "Running FT project..." + mkdir -p "$filename" + unzip "$src_filename" -d "$filename" + cd "$filename" + sudo -u ftgui python3 "${filename}.py" $@ + ;; + "py") + echo "Running python script..." + sudo -u ftgui python3 "$src_filename" $@ + ;; + "c") + echo "Compiling and running C program..." + txt_compile_exec "$src_filename" $@ + ;; + "cpp") + echo "Compiling and running C++ program..." + txt_compile_exec "$src_filename" $@ + ;; + *) + echo 'Please specify a file to run (*.ft, *.py, *.c, *.cpp)' + exit 1 + ;; +esac + +exit 0 diff --git a/bin/txt_servo b/bin/txt_servo index c3e3a94..3ec77ee 100644 --- a/bin/txt_servo +++ b/bin/txt_servo @@ -2,13 +2,31 @@ # Usage +# Disclaimer: Servo calibration can be stored within U-Boot with use_uboot_pre_config=1 +# to potential catch critical servo positions before boot +# This feature is not implemented in U-boot, so servo calibration values +# are moving into a config file in /opt/ft/config/servo.conf + servo_min_min=300 servo_min_max=1100 -servo_min_default=600 +servo_min_default=610 servo_max_min=1900 servo_max_max=2700 -servo_max_default=2400 +servo_max_default=2360 + +use_uboot_pre_config=0 + +debug=0 + +config_file="/opt/ft/config/servo.conf" + +debug_print() +{ + if [ "$debug" -eq "1" ]; then + echo $@ + fi +} usage() { @@ -23,61 +41,179 @@ usage() # Assigning arguments +while(true) +do + if [ "${1}" == "--uboot-env" ]; then + use_uboot_pre_config=1 + shift + elif [ "${1}" == "--file-env" ]; then + use_uboot_pre_config=0 + shift + elif [ "${1}" == "-d" ]; then + debug=1 + shift + else + break; + fi +done + operation="${1}" servo_num="${2}" +configFile_setEnv() +{ + env_key="$1" + env_value="$2" + + if ! grep -q "^${env_key}=" ${config_file}; then + echo "${env_key}=" >> ${config_file} + fi + sed -i "s/$env_key=.*/$env_key=$env_value/" "${config_file}" +} + +uboot_setEnv() +{ + env_key="$1" + env_value="$2" + + /sbin/fw_setenv "$env_key" "$env_value" 2>/dev/null +} + +setEnv() +{ + env_key="$1" + env_value="$2" + if [ "$use_uboot_pre_config" == "1" ]; then + /sbin/fw_setenv "$env_key" "$env_value" 2>/dev/null + else + configFile_setEnv "$env_key" "$env_value" + fi +} + +configFile_getEnv() +{ + env_key="$1" + env_value="$(cat "$config_file" | grep "^${env_key}=" | cut -f2- -d"=")" + #source ${config_file} + #eval env_value=\$\{${env_key}\} + echo $env_value +} + +uboot_getEnv() +{ + env_key=$1 + echo "$(/sbin/fw_printenv -n "${env_key}" 2>/dev/null)" +} + +getEnv() +{ + env_key="$1" + if [ "$use_uboot_pre_config" == "1" ]; then + uboot_getEnv "$env_key" + else + configFile_getEnv "$env_key" + fi +} + +copyEnvUbootToFile() +{ + debug_print "Copy u-boot to config-file..." + for i in 1 2 3 + do + err=0 + servo_min="$(uboot_getEnv "servo${i}_min")" + if [ ! $? -eq 0 ] || [ ! "$servo_min" ]; then + err=1 + fi + servo_max="$(uboot_getEnv "servo${i}_max")" + if [ ! $? -eq 0 ] || [ ! "$servo_max" ]; then + err=1 + fi + if [ $err -eq 0 ]; then + configFile_setEnv "servo${i}_min" "$servo_min" + configFile_setEnv "servo${i}_max" "$servo_max" + fi + done + +} + getServoValues() { - servo_num="${1}" - min_val="$(/sbin/fw_printenv -n "servo${servo_num}_min" 2>/dev/null)" + servo_num_index="${1}" + min_val="$(getEnv "servo${servo_num_index}_min" 2>/dev/null)" if [ ! $? -eq 0 ] then min_val=$servo_min_default - /sbin/fw_setenv "servo${servo_num}_min" "${min_val}" 2>/dev/null + setEnv "servo${servo_num_index}_min" "${min_val}" 2>/dev/null fi - max_val="$(/sbin/fw_printenv -n "servo${servo_num}_max" 2>/dev/null)" + max_val="$(getEnv "servo${servo_num_index}_max" 2>/dev/null)" if [ ! $? -eq 0 ] then max_val=$servo_max_default - /sbin/fw_setenv "servo${servo_num}_max" "${max_val}" 2>/dev/null + setEnv "servo${servo_num_index}_max" "${max_val}" 2>/dev/null fi if [ ! "$min_val" ] then min_val=$servo_min_default - /sbin/fw_setenv "servo${servo_num}_min" "${min_val}" 2>/dev/null + setEnv "servo${servo_num_index}_min" "${min_val}" 2>/dev/null fi if [ $min_val -gt $servo_min_max ] then min_val=$servo_min_max - /sbin/fw_setenv "servo${servo_num}_min" "${min_val}" 2>/dev/null + setEnv "servo${servo_num_index}_min" "${min_val}" 2>/dev/null fi if [ $min_val -lt $servo_min_min ] then min_val=$servo_min_min - /sbin/fw_setenv "servo${servo_num}_min" "${min_val}" 2>/dev/null + setEnv "servo${servo_num_index}_min" "${min_val}" 2>/dev/null fi if [ ! "$max_val" ] then max_val=$servo_max_default - /sbin/fw_setenv "servo${servo_num}_max" "${max_val}" 2>/dev/null + setEnv "servo${servo_num_index}_max" "${max_val}" 2>/dev/null fi if [ $max_val -lt $servo_max_min ] then max_val=$servo_max_min - /sbin/fw_setenv "servo${servo_num}_max" "${max_val}" 2>/dev/null + setEnv "servo${servo_num_index}_max" "${max_val}" 2>/dev/null fi if [ $max_val -gt $servo_max_max ] then max_val=$servo_max_max - /sbin/fw_setenv "servo${servo_num}_max" "${max_val}" 2>/dev/null + setEnv "servo${servo_num_index}_max" "${max_val}" 2>/dev/null fi - echo "{\"servo\":\"$servo_num\",\"min\":\"${min_val}\",\"max\":\"${max_val}\"}" 2>/dev/null || : + echo "{\"servo\":\"$servo_num_index\",\"min\":\"${min_val}\",\"max\":\"${max_val}\"}" 2>/dev/null || : } +if [ ! "$servo_num" ] || [ "$servo_num" -lt 1 ] || [ "$servo_num" -gt 3 ]; then + echo "ERROR: Only servo numbers from 1 to 3 are allowed..." + usage + exit 1 +fi + +if [ ! -e "${config_file}" ] ; then + touch $config_file + for i in 1 2 3 + do + echo "servo${i}_min=${servo_min_default}" >> $config_file + echo "servo${i}_max=${servo_max_default}" >> $config_file + done +fi + +uboot_ported=$(configFile_getEnv "ubootported") +if [ ! "$uboot_ported" ]; then + copyEnvUbootToFile + configFile_setEnv "ubootported" "1" +fi + +debug_print "Arguments: $@" +debug_print "Operation: ${operation}" +debug_print "Servo-Num: ${servo_num}" + case "${operation}" in "init") echo "{" @@ -89,18 +225,25 @@ case "${operation}" in "setcalibration") servo_min="${3}" servo_max="${4}" - /sbin/fw_setenv "servo${servo_num}_min" "${servo_min}" 2>/dev/null - /sbin/fw_setenv "servo${servo_num}_max" "${servo_max}" 2>/dev/null + debug_print "setcalibration" + debug_print "Min: ${servo_min}" + debug_print "Max: ${servo_max}" + setEnv "servo${servo_num}_min" "${servo_min}" 2>/dev/null + setEnv "servo${servo_num}_max" "${servo_max}" 2>/dev/null getServoValues "${servo_num}" ;; "setmin") servo_min="${3}" - /sbin/fw_setenv "servo${servo_num}_min" "${servo_min}" 2>/dev/null + debug_print "servo_min" + debug_print "Min: ${servo_min}" + setEnv "servo${servo_num}_min" "${servo_min}" 2>/dev/null getServoValues "${servo_num}" ;; "setmax") servo_max="${3}" - /sbin/fw_setenv "servo${servo_num}_max" "${servo_max}" 2>/dev/null + debug_print "setmax" + debug_print "Max: ${servo_max}" + setEnv "servo${servo_num}_max" "${servo_max}" 2>/dev/null getServoValues "${servo_num}" ;; "getmin") @@ -118,4 +261,4 @@ case "${operation}" in ;; esac -exit 0 +exit 0 \ No newline at end of file diff --git a/bin/txt_servo_setpos b/bin/txt_servo_setpos new file mode 100644 index 0000000..c783751 --- /dev/null +++ b/bin/txt_servo_setpos @@ -0,0 +1,38 @@ +#!/usr/bin/python3 +# Set Servo Position +# +# Copyright (c) 2023 Accso. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import ftlock +import sys +import time +import ft + +servoNum=int(sys.argv[1]) +servoPos=int(sys.argv[2]) + +if servoNum < 1 or servoNum > 3: + print("ERROR") + exit(1) +if servoPos < 300 or servoPos > 2700: + print("ERROR") + exit(1) + +txt2=ft.fttxt2() +s1=txt2.servo(servoNum) +txt2.update_config() +s1.pwm_set_us(servoPos) +print("OK") \ No newline at end of file diff --git a/bin/txt_update_avahi b/bin/txt_update_avahi index b1b6cf7..03b67d3 100644 --- a/bin/txt_update_avahi +++ b/bin/txt_update_avahi @@ -12,7 +12,6 @@ get_hostname() get_hostnames() { - echo "blablub.local" echo "$(get_hostname)" echo "$(get_hostname).local" if [ "$(get_domain_search)" ]; then @@ -40,7 +39,14 @@ get_ip_hostnames() get_txtapi_version() { - SW_VERS="$(cat /usr/lib/python3.5/site-packages/txtapi/VERSION | grep "^VERSION_NUM=" | awk -F'=' '{print $2}')" + PYTHON_PATH="" + if [ -d "/usr/lib/python3.5" ]; then + PYTHON_PATH="/usr/lib/python3.5" + elif [ -d "/usr/lib/python3.8" ]; then + PYTHON_PATH="/usr/lib/python3.8" + fi + + SW_VERS="$(cat $PYTHON_PATH/site-packages/txtapi/VERSION | grep "^VERSION_NUM=" | awk -F'=' '{print $2}')" if [ ! "$SW_VERS" ] then echo "unknown" diff --git a/bin/txt_usb_gadget b/bin/txt_usb_gadget index 5f3e908..f4ca7a5 100755 --- a/bin/txt_usb_gadget +++ b/bin/txt_usb_gadget @@ -103,6 +103,7 @@ check_udc() { do_start() { check_udc + /sbin/modprobe -a g_ether #/sbin/modprobe -a libcomposite if [ -d "${syspath_gadget}" ]; then read udc < "${syspath_gadget}/UDC" diff --git a/bin/txt_wifi_setup b/bin/txt_wifi_setup index c38dc80..f635e2a 100755 --- a/bin/txt_wifi_setup +++ b/bin/txt_wifi_setup @@ -77,34 +77,106 @@ parse_args() esac } +iface_get_flags() +{ + iface="$1" + if [ -d "/sys/class/net/${iface}" ]; then + cat "/sys/class/net/${iface}/flags" + else + echo "0x1002" + fi +} + +iface_get_operstate() +{ + iface="$1" + if [ -d "/sys/class/net/${iface}" ]; then + cat "/sys/class/net/${iface}/operstate" + else + echo "down" + fi +} + # Settings +kernel_version=$(uname -r) + +iface_client_lan=eth0 iface_client=mlan0 -if [ "$(lsusb | grep "RT5370")" ] +iface_apoint=uap0 +iface_com_mode=sdcard +if [ "$(lsusb 2>/dev/null | grep "RT5370")" ] || [ "$(lsusb -v 2>/dev/null | grep "802.11")" ] || [ -d "/sys/class/net/wlan0" ] || [ -d "/sys/class/net/wlanap0" ] then - flags=$(cat /sys/class/net/mlan0/flags) + flags=$(iface_get_flags "mlan0") if [ "${flags}" = "0x1003" ] then /usr/bin/sudo -n /sbin/ifconfig mlan0 down fi iface_client=wlan0 + iface_apoint=wlanap0 + iface_com_mode=usb fi + +flags_client=$(iface_get_flags "${iface_client}") +status_client=$(iface_get_operstate "${iface_client}") + +flags_client_lan=$(iface_get_flags "${iface_client_lan}") +status_client_lan=$(iface_get_operstate "${iface_client_lan}") + + iface_client_metric=1 iface_client_timeout=12 # 12 seconds to establish the link -iface_apoint=uap0 iface_apoint_timeout=12 # 12 seconds to establish the link temp_conf_dir=/tmp/txt2-utils hostap_conf_work="${temp_conf_dir}/hostapd.conf" wpasup_conf_work="${temp_conf_dir}/wpa_supplicant.conf" hostap_conf_template=/etc/hostapd.conf +if [ "${iface_com_mode}" == "usb" ]; then + hostap_conf_template=/etc/hostapd_rt.conf +fi wpasup_conf_template=/etc/wpa_supplicant.conf # Arguments verification . /usr/share/txt2-utils/txt_aux_functions +ensure_usb_wlan_station_iface() +{ + #echo "#### ensure_usb_wlan_station_iface ####" + #echo iface_com_mode: ${iface_com_mode} + #echo iface_client: ${iface_client} + #echo iface_apoint: ${iface_apoint} + if [ "${iface_com_mode}" == "usb" ]; then + if [ -d "/sys/class/net/${iface_client}" ] && [ ! -d "/sys/class/net/${iface_apoint}" ]; then + echo "${iface_client} -> ${iface_apoint}" + /usr/bin/sudo -n /sbin/ip link set dev ${iface_client} name ${iface_apoint} + sleep 2 + /usr/bin/sudo -n /bin/systemctl restart systemd-networkd + sleep 2 + fi + fi +} + +ensure_usb_wlan_client_iface() +{ + echo "#### ensure_usb_wlan_client_iface ####" + echo iface_com_mode: ${iface_com_mode} + echo iface_client: ${iface_client} + echo iface_apoint: ${iface_apoint} + + if [ "${iface_com_mode}" == "usb" ]; then + if [ ! -d "/sys/class/net/${iface_client}" ] && [ -d "/sys/class/net/${iface_apoint}" ]; then + echo "${iface_apoint} -> ${iface_client}" + /usr/bin/sudo -n /sbin/ip link set dev ${iface_apoint} name ${iface_client} + sleep 2 + /usr/bin/sudo -n /bin/systemctl restart systemd-networkd + sleep 2 + fi + fi +} + check_args() { case "${action}" in @@ -290,8 +362,11 @@ get_gateway() echo "$(netstat -r -n | grep "${iface_client}" | grep "UG" | awk '{print $2}')" } -wifi_recovery() +force_wifi_recovery() { + if [ ! "${iface_client}" == "mlan0" ]; then + return + fi /usr/bin/sudo -n /usr/bin/killall -q dhcpcd || true /usr/bin/sudo -n /usr/bin/killall -q wpa_supplicant || true /usr/bin/sudo -n /usr/bin/killall -q hostapd || true @@ -315,6 +390,15 @@ wifi_recovery() /usr/bin/sudo -n /usr/bin/killall -q hostapd || true } +wifi_recovery() +{ + if [ ${kernel_version:0:1} == "5" ]; then + echo "Recovery is not available for Kernel >= 5.x" + return + fi + force_wifi_recovery +} + check_client_iface() { if [ ! -L "/sys/class/net/${iface_client}" ] @@ -374,12 +458,12 @@ make_access_point_config() # Enable wpa and set wpa_psk script="s/^${spaces}wpa=.*$/wpa=2/;s/^${spaces}wpa_psk=.*$/wpa_psk=${psk}/;" fi - /bin/sed -e "s/^${spaces}channel=.*$/channel=${channel}/" \ - -e "s/^${spaces}ssid2\?=.*$/$(sed_escape "${ssid_expr}")/" \ - -e "s/^${spaces}wpa_passphrase=.*$/#wpa_passphrase=/" \ - -e "${script}" \ - "${hostap_conf_template}" + -e "s/^${spaces}ssid2\?=.*$/$(sed_escape "${ssid_expr}")/" \ + -e "s/^${spaces}wpa_passphrase=.*$/#wpa_passphrase=/" \ + -e "s/^${spaces}interface=.*$/interface=${iface_apoint}/" \ + -e "${script}" \ + "${hostap_conf_template}" } do_set_mmc_speed() @@ -399,6 +483,7 @@ do_get_gateway() do_start_client() { + ensure_usb_wlan_client_iface check_client_iface case "${ssid_type}" in 'raw') @@ -450,7 +535,7 @@ do_start_client() # Let system to establish the link before script exits while [ "${i:-0}" -lt "${iface_client_timeout}" ]; do - status_client=$(/bin/cat "/sys/class/net/${iface_client}/operstate") + status_client=$(iface_get_operstate "${iface_client}") if [ "${status_client}" = 'up' ]; then break fi @@ -479,6 +564,7 @@ do_stop_client() do_start_access_point() { + ensure_usb_wlan_station_iface check_point_iface case "${ssid_type}" in 'raw') @@ -514,13 +600,16 @@ do_start_access_point() # Let system to establish the link before script exits while [ "${i:-0}" -lt "${iface_apoint_timeout}" ]; do - status_apoint=$(/bin/cat "/sys/class/net/${iface_apoint}/operstate") + status_apoint=$(iface_get_operstate "${iface_apoint}") if [ "${status_apoint}" = 'up' ]; then break fi /bin/sleep 1 i=$((i+1)) done + #/usr/bin/sudo -n /usr/sbin/dhcpcd --allowinterfaces ${iface_apoint} + #/usr/bin/sudo -n /sbin/ifconfig ${iface_apoint} 192.168.8.2 + #/usr/bin/sudo -n /usr/sbin/dhcpcd --reconfigure } do_stop_access_point() @@ -536,12 +625,14 @@ do_stop_access_point() /bin/rm -f -- "${hostap_conf_work}" /bin/rmdir --ignore-fail-on-non-empty -- "${temp_conf_dir}" fi + ensure_usb_wlan_client_iface } do_stop_all() { do_stop_client do_stop_access_point + ensure_usb_wlan_client_iface } check_host_online() @@ -648,7 +739,7 @@ do_scan() fi fi - flags=$(/bin/cat "/sys/class/net/${iface_client}/flags") + flags=$(iface_get_flags "${iface_client}") if [ "${flags}" = "0x1002" ] then /usr/bin/sudo -n /sbin/ifconfig "${iface_client}" up 2> /dev/null > /dev/null @@ -657,6 +748,23 @@ do_scan() if [ -f "/usr/bin/mlanutl" ] && [ "${iface_client}" == "mlan0" ] then /usr/bin/sudo -n /usr/bin/mlanutl "${iface_client}" setuserscan + # advanced wifi recovery only available for kernel >= 5.x.x + if [ ${kernel_version:0:1} == "5" ] && [ $? -eq 0 ]; then + success=0 + for (( i = 0; i <= 10; i++ )) + do + /usr/bin/sudo -n /usr/bin/mlanutl "${iface_client}" setuserscan + if [ $? -eq 0 ]; then + success=1 + break; + fi + sleep 1 + done + if [ $success -eq 0 ]; then + force_wifi_recovery + /usr/bin/sudo -n /usr/bin/mlanutl "${iface_client}" setuserscan + fi + fi else # Fallback if mlanutl does not exist: WPA CLI requires a running wpa_supplicant, if not running use iw if [ "$(pidof wpa_supplicant)" ] @@ -675,9 +783,16 @@ do_scan() do_status_client() { - flags_client=$(/bin/cat "/sys/class/net/${iface_client}/flags") - status_client=$(/bin/cat "/sys/class/net/${iface_client}/operstate") - if [ "${flags_client}" = '0x1003' ]; then + flags_client=$(iface_get_flags "${iface_client}") + status_client=$(iface_get_operstate "${iface_client}") + flags_client_lan=$(iface_get_flags "${iface_client_lan}") + status_client_lan=$(iface_get_operstate "${iface_client_lan}") + if [ "${flags_client_lan}" = '0x1003' ] && [ "${status_client_lan}" = 'up' ]; then + # Interface fully configured, link ready + echo 'CLIENT:ON' + echo "CLIENT_IP:$(expr match "$(/sbin/ip -4 address show dev "${iface_client_lan}")" '.*inet \([0-9.]*/[0-9]*\)')" + return + elif [ "${flags_client}" = '0x1003' ]; then # Client interface is up if [ "${status_client}" = 'up' ] && /bin/pidof wpa_supplicant >/dev/null; then # Interface fully configured, link ready @@ -695,8 +810,8 @@ do_status_client() do_status_access_point() { if [ -L "/sys/class/net/${iface_apoint}" ]; then - flags_apoint=$(/bin/cat "/sys/class/net/${iface_apoint}/flags") - status_apoint=$(/bin/cat "/sys/class/net/${iface_apoint}/operstate") + flags_apoint=$(iface_get_flags "${iface_apoint}") + status_apoint=$(iface_get_operstate "${iface_apoint}") if [ "${flags_apoint}" = '0x1003' ]; then # Access point interface is up if [ "${status_apoint}" = 'up' ] && /bin/pidof hostapd >/dev/null; then @@ -715,15 +830,23 @@ do_status_access_point() do_status() { - if [ ! -L "/sys/class/net/${iface_client}" ] || [ ! -L "/sys/class/net/${iface_apoint}" ] - then - echo 'ERROR' - exit 19 # ENODEV + if [ ! "${iface_com_mode}" == "usb" ]; then + if [ ! -L "/sys/class/net/${iface_client}" ] || [ ! -L "/sys/class/net/${iface_apoint}" ] + then + echo 'ERROR' + exit 19 # ENODEV + fi fi - - flags_client=$(/bin/cat "/sys/class/net/${iface_client}/flags") - status_client=$(/bin/cat "/sys/class/net/${iface_client}/operstate") - if [ "${flags_client}" = '0x1003' ]; then + flags_client=$(iface_get_flags "${iface_client}") + status_client=$(iface_get_operstate "${iface_client}") + flags_client_lan=$(iface_get_flags "${iface_client_lan}") + status_client_lan=$(iface_get_operstate "${iface_client_lan}") + if [ "${flags_client_lan}" = '0x1003' ] && [ "${status_client_lan}" = 'up' ]; then + # Interface fully configured, link ready + echo 'CLIENT:ON' + echo "CLIENT_IP:$(expr match "$(/sbin/ip -4 address show dev "${iface_client_lan}")" '.*inet \([0-9.]*/[0-9]*\)')" + return + elif [ "${flags_client}" = '0x1003' ]; then # Client interface is up if [ "${status_client}" = 'up' ] && /bin/pidof wpa_supplicant >/dev/null; then # Interface fully configured, link ready @@ -735,8 +858,8 @@ do_status() fi return else - flags_apoint=$(/bin/cat "/sys/class/net/${iface_apoint}/flags") - status_apoint=$(/bin/cat "/sys/class/net/${iface_apoint}/operstate") + flags_apoint=$(iface_get_flags "${iface_apoint}") + status_apoint=$(iface_get_operstate "${iface_apoint}") if [ "${flags_apoint}" = '0x1003' ]; then # Access point interface is up if [ "${status_apoint}" = 'up' ] && /bin/pidof hostapd >/dev/null; then @@ -755,6 +878,12 @@ do_status() do_ping() { + if [ "${flags_client_lan}" = '0x1003' ] && [ "${status_client_lan}" = 'up' ]; then + if /bin/ping -I"${iface_client_lan}" -c1 -W2 "${host}" >&2 > /dev/null; then + echo 'PING:OK' + return + fi + fi if /bin/ping -I"${iface_client}" -c1 -W2 "${host}" >&2 > /dev/null; then echo 'PING:OK' else @@ -776,10 +905,17 @@ do_init() { # PAN9026 modules should already have been loaded #/usr/bin/sudo -n /sbin/modprobe -a mlan sd8xxx - if [ ! -L "/sys/class/net/${iface_client}" ] || [ ! -L "/sys/class/net/${iface_apoint}" ] - then - echo 'INIT:ERROR' - exit 19 # ENODEV + if [ "${iface_com_mode}" == "usb" ]; then + if [ ! -L "/sys/class/net/${iface_client}" ] && [ ! -L "/sys/class/net/${iface_apoint}" ]; then + echo 'INIT:ERROR' + exit 19 # ENODEV + fi + else + if [ ! -L "/sys/class/net/${iface_client}" ] || [ ! -L "/sys/class/net/${iface_apoint}" ] + then + echo 'INIT:ERROR' + exit 19 # ENODEV + fi fi do_stop_all echo 'INIT:OK' diff --git a/src/txt_servo_setpos.cpp b/src/txt_servo_setpos.cpp new file mode 100644 index 0000000..fbf1460 --- /dev/null +++ b/src/txt_servo_setpos.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 Accso. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <iostream> +#include <string> +#include <stdio.h> +#include <unistd.h> + +extern "C" { +#include "ftlock.h" +} +#include "ft.hpp" +#include "ftop.h" + +using namespace ft; + +#define SERVO_MIN 300UL +#define SERVO_MAX 2700UL + +int main(int argc, char **argv) +{ + int servoNum = 1; + int servoPos=1485; + if (argc < 2) + { + printf("ERROR\n"); + return 1; + } + + servoNum = atoi(argv[1]); + servoPos = atoi(argv[2]); + + if ((servoNum < 1) || (servoNum > 3)) + { + printf("ERROR\n"); + return 1; + } + + if ((servoPos < SERVO_MIN) || (servoPos > SERVO_MAX)) + { + printf("ERROR\n"); + return 1; + } + + if (ftlock_open() < 0) + { + printf("ERROR\n"); + return 1; + } + TXT txt2; + Servo s { txt2, servoNum }; + + txt2.update_config(); + s.setPwmUs(servoPos); + + ftlock_unlock(); // can be skipped in this case + ftlock_close(); // can be skipped in this case + printf("OK\n"); + return 0; +} -- GitLab