diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 606246b1..863a677d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -39,7 +39,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -50,7 +50,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -64,4 +64,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 85bae44e..02a02ee0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,25 @@ # Changelog +## [2.7.0] Not Released +### Added +- Now compatible with Septentrio Mosaic-X5 firmware 4.15. Default login/password is `basegnss/basegnss!`. +- GUI -> Settings: Add display of network interface mac address. +- GUI -> Settings: Add Tcp host addr entry to open or block external access to the Gnss receiver. [#490](https://github.com/Stefal/rtkbase/issues/490) +- GUI ->: Add mount name in the web page title. Thanks to @sbonaime [#484](https://github.com/Stefal/rtkbase/issues/484) +- GUI -> Logs: .sbf files get a type in the type column. +- GUI -> Logs: .obs and .2?o files displayed as RINEX in type column. +### Changed +- RTKLib upgraded to release v2.5.0-EX. +- Add Galileo inside rinex preset for Nrcan. [#479](https://github.com/Stefal/rtkbase/issues/479) +- U-Blox ZED-F9P settings : Dynamic model sets to static during configuration. Thanks to @Jef239 [#488](https://github.com/Stefal/rtkbase/issues/488) +### Fixed +- GUI -> Logs: Fix wrong path when using custom data directory. [#471](https://github.com/Stefal/rtkbase/issues/471) +- GUI -> Settings: Better toggle buttons color behaviour. +### Deprecated +- Operating systems older than Debian 12 / Ubuntu 24.04 can't update RTKBase anymore. +- Python release < 3.11 deprecated +### Security +- Update various python module +- Update js library (leaflet, bootstrap-table) ## [2.6.4] - 2025-11-26 ### Fixed diff --git a/README.md b/README.md index f50f545a..5697e039 100644 --- a/README.md +++ b/README.md @@ -336,8 +336,8 @@ A gnss receiver with a timepulse output is a very accurate [stratum 0](https://e ``` ## Requirements: -Debian base distro >= 11 (Bullseye) -Python >= 3.8 +Debian base distro >= 12 (Bookworms) +Python >= 3.11 ## History: See the [changelog](./CHANGELOG.md) @@ -346,7 +346,7 @@ See the [changelog](./CHANGELOG.md) RTKBase is licensed under AGPL 3 (see [LICENSE](./LICENSE) file). RTKBase uses some parts of other software: -+ [RTKLIB](https://github.com/tomojitakasu/RTKLIB) (BSD-2-Clause) ++ [RTKLIB-EX](https://github.com/rtklibexplorer/RTKLIB) (BSD-2-Clause) + [ReachView](https://github.com/emlid/ReachView) (GPL v3) + [Flask](https://palletsprojects.com/p/flask/) [Jinja](https://palletsprojects.com/p/jinja/) [Werkzeug](https://palletsprojects.com/p/werkzeug/) (BSD-3-Clause) + [Flask SocketIO](https://github.com/miguelgrinberg/Flask-SocketIO) (MIT) diff --git a/archive_and_clean.sh b/archive_and_clean.sh index 3f5f094a..07b02f58 100755 --- a/archive_and_clean.sh +++ b/archive_and_clean.sh @@ -7,7 +7,7 @@ source <( grep '=' ${BASEDIR}/settings.conf ) cd ${datadir} check_space(){ - df -mP ${datadir} | grep -v '^Filesystem' | awk '{ print $4 }' + df -mP ${datadir} | tail -n1 | awk '{ print $4 }' } #Check if there is enough available space (default value is more than 500MB), and delete oldest archive if needed. diff --git a/drawing/um980_support.3mf b/drawing/um980_support.3mf new file mode 100644 index 00000000..755ec8ab Binary files /dev/null and b/drawing/um980_support.3mf differ diff --git a/drawing/um980_support.FCStd b/drawing/um980_support.FCStd new file mode 100644 index 00000000..e7d226a8 Binary files /dev/null and b/drawing/um980_support.FCStd differ diff --git a/drawing/um980_support3.3mf b/drawing/um980_support3.3mf new file mode 100644 index 00000000..9f20c88e Binary files /dev/null and b/drawing/um980_support3.3mf differ diff --git a/drawing/um980_support3.stl b/drawing/um980_support3.stl new file mode 100644 index 00000000..90d92993 Binary files /dev/null and b/drawing/um980_support3.stl differ diff --git a/receiver_cfg/Septentrio_Mosaic-X5.cfg b/receiver_cfg/Septentrio_Mosaic-X5.cfg index e7bd148a..83f48b83 100644 --- a/receiver_cfg/Septentrio_Mosaic-X5.cfg +++ b/receiver_cfg/Septentrio_Mosaic-X5.cfg @@ -9,9 +9,11 @@ setSBFOutput, Stream1, , +BDSRaw+BDSRawB1C+BDSRawB2a+BDSRawB2b setSBFOutput, Stream1, , +QZSRawL1CA+QZSRawL2C+QZSRawL5 setSBFOutput, Stream1, , +NAVICRaw setSBFOutput, Stream1, , +GEORawL1+GEORawL5 +setSatelliteTracking, -SBAS setSignalTracking, GPSL1CA+GPSL1PY+GPSL2PY+GPSL2C+GPSL5+GLOL1CA+GLOL2P+GLOL2CA+GLOL3+GALL1BC+GALE6BC+GALE5a+GALE5b+GALE5+GEOL1+GEOL5+BDSB1I+BDSB2I+BDSB3I+BDSB1C+BDSB2a+BDSB2b+QZSL1CA+QZSL2C+QZSL5+QZSL1CB+NAVICL5 setSBFOutput, Stream1, , +PVTGeodetic+ChannelStatus+ReceiverStatus+SatVisibility+ReceiverTime setPVTMode, Static setPPSParameters, sec1, Low2High, , UTC -setUSBInternetAccess, on -#END \ No newline at end of file +setUSBInternetAccess, off +setHttpsSettings, HTTP +#END diff --git a/receiver_cfg/Septentrio_Mosaic-X5_4.15.cfg b/receiver_cfg/Septentrio_Mosaic-X5_4.15.cfg new file mode 100644 index 00000000..ee170364 --- /dev/null +++ b/receiver_cfg/Septentrio_Mosaic-X5_4.15.cfg @@ -0,0 +1,20 @@ +# Config file for using a Septentrio Mosaic X5 with RTKBase +setSBFOutput, Stream1, USB1 +setSBFOutput, Stream1, , , sec1 +setSBFOutput, Stream1, , MeasEpoch+MeasExtra+EndOfMeas +setSBFOutput, Stream1, , +GPSRawCA+GPSRawL2C+GPSRawL5 +setSBFOutput, Stream1, , +GLORawCA +setSBFOutput, Stream1, , +GALRawFNAV+GALRawINAV+GALRawCNAV +setSBFOutput, Stream1, , +BDSRaw+BDSRawB1C+BDSRawB2a+BDSRawB2b +setSBFOutput, Stream1, , +QZSRawL1CA+QZSRawL2C+QZSRawL5 +setSBFOutput, Stream1, , +NAVICRaw +setSBFOutput, Stream1, , +GEORawL1+GEORawL5 +setSatelliteTracking, -SBAS +setSignalTracking, GPSL1CA+GPSL1PY+GPSL2PY+GPSL2C+GPSL5+GLOL1CA+GLOL2P+GLOL2CA+GLOL3+GALL1BC+GALE6BC+GALE5a+GALE5b+GALE5+GEOL1+GEOL5+BDSB1I+BDSB2I+BDSB3I+BDSB1C+BDSB2a+BDSB2b+QZSL1CA+QZSL2C+QZSL5+QZSL1CB+NAVICL5 +setSBFOutput, Stream1, , +PVTGeodetic+ChannelStatus+ReceiverStatus+SatVisibility+ReceiverTime +setPVTMode, Static +setPPSParameters, sec1, Low2High, , UTC +setUSBInternetAccess, off +setHttpsSettings, HTTP +login, basegnss, basegnss!, RxAdmin, S3pt3ntr10 +#END diff --git a/receiver_cfg/U-Blox_ZED-F9P_config_info.txt b/receiver_cfg/U-Blox_ZED-F9P_config_info.txt index 62b126af..5796f016 100644 --- a/receiver_cfg/U-Blox_ZED-F9P_config_info.txt +++ b/receiver_cfg/U-Blox_ZED-F9P_config_info.txt @@ -6,6 +6,7 @@ The U-Blox_ZED-F9P_rtkbase.txt config file is based on default settings with the - NAV-PVT enabled - NAV-SAT enabled - NAV-SIG enabled +- CFG-NAVSPG-DYNMODEL Dynamic model sets to static - NMEA on USB out disabled - NMEA on UART1 out disabled diff --git a/receiver_cfg/U-Blox_ZED-F9P_rtkbase.cfg b/receiver_cfg/U-Blox_ZED-F9P_rtkbase.cfg index e4709fdf..7d926e40 100644 --- a/receiver_cfg/U-Blox_ZED-F9P_rtkbase.cfg +++ b/receiver_cfg/U-Blox_ZED-F9P_rtkbase.cfg @@ -11,3 +11,4 @@ CFG-MSGOUT-UBX_NAV_SAT_USB,1 CFG-MSGOUT-UBX_NAV_SAT_UART1,1 CFG-MSGOUT-UBX_NAV_SIG_USB,1 CFG-MSGOUT-UBX_NAV_SIG_UART1,1 +CFG-NAVSPG-DYNMODEL,2 diff --git a/receiver_cfg/Unicore_UM980_rtcm3.cfg b/receiver_cfg/Unicore_UM980_rtcm3.cfg index cf8247c7..d6620ae1 100644 --- a/receiver_cfg/Unicore_UM980_rtcm3.cfg +++ b/receiver_cfg/Unicore_UM980_rtcm3.cfg @@ -14,4 +14,5 @@ rtcm1087 1 rtcm1097 1 rtcm1107 1 rtcm1117 1 -rtcm1127 1 \ No newline at end of file +rtcm1127 1 +MASK 0 diff --git a/receiver_cfg/Unicore_UM982_rtcm3.cfg b/receiver_cfg/Unicore_UM982_rtcm3.cfg index db5144e6..3a4d186a 100644 --- a/receiver_cfg/Unicore_UM982_rtcm3.cfg +++ b/receiver_cfg/Unicore_UM982_rtcm3.cfg @@ -14,4 +14,5 @@ rtcm1087 1 rtcm1097 1 rtcm1107 1 rtcm1117 1 -rtcm1127 1 \ No newline at end of file +rtcm1127 1 +MASK 0 diff --git a/run_cast.sh b/run_cast.sh index db7a656f..e8f6f2de 100755 --- a/run_cast.sh +++ b/run_cast.sh @@ -13,11 +13,11 @@ in_tcp="tcpcli://localhost:${tcp_port}#${receiver_format}" #in_ext_tcp is mainly for dev purpose to receive a raw stream from another base in_ext_tcp="tcpcli://${ext_tcp_source}:${ext_tcp_port}#${receiver_format}" -out_caster_A="ntrips://:${svr_pwd_a}@${svr_addr_a}:${svr_port_a}/${mnt_name_a}#rtcm3 -msg ${rtcm_msg_a} -p ${position}" +out_caster_A="-msg ${rtcm_msg_a} -out ntrips://:${svr_pwd_a}@${svr_addr_a}:${svr_port_a}/${mnt_name_a}#rtcm3 -p ${position}" #add receiver options if it exists [[ ! -z "${ntrip_a_receiver_options}" ]] && out_caster_A=""${out_caster_A}" -opt "${ntrip_a_receiver_options}"" -out_caster_B="ntrips://:${svr_pwd_b}@${svr_addr_b}:${svr_port_b}/${mnt_name_b}#rtcm3 -msg ${rtcm_msg_b} -p ${position}" +out_caster_B="-msg ${rtcm_msg_b} -out ntrips://:${svr_pwd_b}@${svr_addr_b}:${svr_port_b}/${mnt_name_b}#rtcm3 -p ${position}" #add receiver options if it exists [[ ! -z "${ntrip_b_receiver_options}" ]] && out_caster_B=""${out_caster_B}" -opt "${ntrip_b_receiver_options}"" @@ -29,26 +29,27 @@ if [[ ${local_ntripc_user} == '' ]] && [[ ${local_ntripc_pwd} == '' ]] local_ntripc_auth='B' #Basic authentification fi out_local_caster_source_table="${local_ntripc_mnt_name};rtcm3;${local_ntripc_msg};${receiver_frequency_count};GPS+GLO+GAL+BDS+QZS;NONE;NONE;${array_pos[0]};${array_pos[1]};0;0;RTKBase_${receiver},${version};NONE;${local_ntripc_auth};N;;" -out_local_caster="ntripc://${local_ntripc_user}:${local_ntripc_pwd}@:${local_ntripc_port}/${local_ntripc_mnt_name}:${out_local_caster_source_table}#rtcm3 -msg ${local_ntripc_msg} -p ${position}" +out_local_caster="-msg ${local_ntripc_msg} -out ntripc://${local_ntripc_user}:${local_ntripc_pwd}@:${local_ntripc_port}/${local_ntripc_mnt_name}:${out_local_caster_source_table}#rtcm3 -p ${position}" #add receiver options if it exists [[ ! -z "${local_ntripc_receiver_options}" ]] && out_local_caster="${out_local_caster} -opt ${local_ntripc_receiver_options}" -out_tcp="tcpsvr://:${tcp_port}" + +out_tcp="tcpsvr://${tcp_host_addr}:${tcp_port}" out_file="file://${datadir}/${file_name}.${receiver_format}::T::S=${file_rotate_time} -f ${file_overlap_time}" -out_rtcm_svr="tcpsvr://:${rtcm_svr_port}#rtcm3 -msg ${rtcm_svr_msg} -p ${position}" +out_rtcm_svr="-msg ${rtcm_svr_msg} -out tcpsvr://:${rtcm_svr_port}#rtcm3 -p ${position}" #add receiver options if it exists [[ ! -z "${rtcm_receiver_options}" ]] && out_rtcm_svr=""${out_rtcm_svr}" -opt "${rtcm_receiver_options}"" -out_rtcm_client="tcpcli://${rtcm_client_user}:${rtcm_client_pwd}@${rtcm_client_addr}:${rtcm_client_port}#rtcm3 -msg ${rtcm_client_msg} -p ${position}" +out_rtcm_client="-msg ${rtcm_client_msg} -out tcpcli://${rtcm_client_user}:${rtcm_client_pwd}@${rtcm_client_addr}:${rtcm_client_port}#rtcm3 -p ${position}" #add receiver options if it exists [[ ! -z "${rtcm_client_receiver_options}" ]] && out_rtcm_client=""${out_rtcm_client}" -opt "${rtcm_receiver_client_options}"" -out_rtcm_udp_svr="udpsvr://:${rtcm_udp_svr_port}#rtcm3 -msg ${rtcm_udp_svr_msg} -p ${position}" +out_rtcm_udp_svr="-msg ${rtcm_udp_svr_msg} -out udpsvr://:${rtcm_udp_svr_port}#rtcm3 -p ${position}" #add receiver options if it exists [[ ! -z "${rtcm_udp_svr_receiver_options}" ]] && out_rtcm_udp_svr=""${out_rtcm_udp_svr}" -opt "${rtcm_udp_svr_receiver_options}"" -out_rtcm_serial="serial://${out_com_port}:${out_com_port_settings}#rtcm3 -msg ${rtcm_serial_msg} -p ${position}" +out_rtcm_serial="-msg ${rtcm_serial_msg} -out serial://${out_com_port}:${out_com_port_settings}#rtcm3 -p ${position}" #add receiver options if it exists [[ ! -z "${rtcm_serial_receiver_options}" ]] && out_rtcm_serial=""${out_rtcm_serial}" -opt "${rtcm_serial_receiver_options}"" @@ -58,41 +59,41 @@ mkdir -p ${logdir} out_tcp) #echo ${cast} -in ${!1} -out $out_tcp # What is this ${!1} ? It's variable indirection - ${cast} -in ${!1} -out ${out_tcp} -b 1 -t ${level} -fl ${logdir}/str2str_tcp.log & + ${cast} -in ${!1} -out ${out_tcp} -b 1 -t ${level} -fl ${logdir}/str2str_tcp_$(date "+%F-%T").log ;; out_caster_A) #echo ${cast} -in ${!1} -out $out_caster - ${cast} -in ${!1} -out ${out_caster_A} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_ntrip_A.log & + ${cast} -in ${!1} ${out_caster_A} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_ntrip_A.log ;; out_caster_B) - ${cast} -in ${!1} -out ${out_caster_B} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_ntrip_B.log & + ${cast} -in ${!1} ${out_caster_B} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_ntrip_B.log ;; out_local_caster) #echo ${cast} -in ${!1} -out "${out_local_caster}" - ${cast} -in ${!1} -out ${out_local_caster} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_ntrip.log & + ${cast} -in ${!1} ${out_local_caster} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_ntrip.log ;; out_rtcm_svr) #echo ${cast} -in ${!1} -out $out_rtcm_svr - ${cast} -in ${!1} -out ${out_rtcm_svr} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_rtcm_svr.log & + ${cast} -in ${!1} ${out_rtcm_svr} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_rtcm_svr.log ;; out_rtcm_client) #echo ${cast} -in ${!1} -out $out_rtcm_client - ${cast} -in ${!1} -out ${out_rtcm_client} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_rtcm_client.log & + ${cast} -in ${!1} ${out_rtcm_client} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_rtcm_client.log ;; out_rtcm_udp_svr) #echo ${cast} -in ${!1} -out $out_rtcm_udp_svr - ${cast} -in ${!1} -out ${out_rtcm_udp_svr} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_rtcm_udp_svr.log & + ${cast} -in ${!1} ${out_rtcm_udp_svr} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_rtcm_udp_svr.log ;; out_rtcm_serial) #echo ${cast} -in ${!1} -out $out_rtcm_serial - ${cast} -in ${!1} -out ${out_rtcm_serial} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_rtcm_serial.log & + ${cast} -in ${!1} ${out_rtcm_serial} -i "${receiver_info}" -a "${antenna_info}" -t ${level} -fl ${logdir}/str2str_rtcm_serial.log ;; out_file) @@ -102,7 +103,7 @@ mkdir -p ${logdir} if [ ${ret} -eq 0 ] then mkdir -p ${datadir} - ${cast} -in ${!1} -out ${out_file} -t ${level} -fl ${logdir}/str2str_file.log & + ${cast} -in ${!1} -out ${out_file} -t ${level} -fl ${logdir}/str2str_file.log fi ;; diff --git a/settings.conf.default b/settings.conf.default index 007a1306..318184ca 100644 --- a/settings.conf.default +++ b/settings.conf.default @@ -2,9 +2,9 @@ [general] # Version -version=2.6.4 +version=2.7.0 # Rtkbase upgrade mandatory "checkpoint" -checkpoint_version=2.7.0 +checkpoint_version=2.8.0 # User who runs str2str_file service user= # NTRIP caster program @@ -44,6 +44,8 @@ receiver_firmware='' receiver_carrier='' #Antenna info, id, serial number. Without space inside the strings antenna_info='ADVNULLANTENNA' +#Tcp host address to bind the tcp stream +tcp_host_addr='127.0.0.1' #tcp port for RAW stream. If you change this value, edit gpsd conf file to reflect the port in DEVICES. tcp_port='5015' #ext_tcp_source is mainly for dev purpose to receive a raw stream from another base diff --git a/tools/bin/rtklib_b34j/aarch64/compiled_with_bookworm b/tools/bin/RTKLIB-2.5.0/aarch64/compiled_with_bookworm similarity index 100% rename from tools/bin/rtklib_b34j/aarch64/compiled_with_bookworm rename to tools/bin/RTKLIB-2.5.0/aarch64/compiled_with_bookworm diff --git a/tools/bin/RTKLIB-2.5.0/aarch64/convbin b/tools/bin/RTKLIB-2.5.0/aarch64/convbin new file mode 100755 index 00000000..1394a195 Binary files /dev/null and b/tools/bin/RTKLIB-2.5.0/aarch64/convbin differ diff --git a/tools/bin/RTKLIB-2.5.0/aarch64/rtkrcv b/tools/bin/RTKLIB-2.5.0/aarch64/rtkrcv new file mode 100755 index 00000000..57e8b626 Binary files /dev/null and b/tools/bin/RTKLIB-2.5.0/aarch64/rtkrcv differ diff --git a/tools/bin/RTKLIB-2.5.0/aarch64/str2str b/tools/bin/RTKLIB-2.5.0/aarch64/str2str new file mode 100755 index 00000000..d18a99f8 Binary files /dev/null and b/tools/bin/RTKLIB-2.5.0/aarch64/str2str differ diff --git a/tools/bin/rtklib_b34j/armv6l/compiled_with_buster b/tools/bin/RTKLIB-2.5.0/armv6l/compiled_with_bookworm similarity index 100% rename from tools/bin/rtklib_b34j/armv6l/compiled_with_buster rename to tools/bin/RTKLIB-2.5.0/armv6l/compiled_with_bookworm diff --git a/tools/bin/RTKLIB-2.5.0/armv6l/convbin b/tools/bin/RTKLIB-2.5.0/armv6l/convbin new file mode 100755 index 00000000..1fc92678 Binary files /dev/null and b/tools/bin/RTKLIB-2.5.0/armv6l/convbin differ diff --git a/tools/bin/RTKLIB-2.5.0/armv6l/rtkrcv b/tools/bin/RTKLIB-2.5.0/armv6l/rtkrcv new file mode 100755 index 00000000..f572a937 Binary files /dev/null and b/tools/bin/RTKLIB-2.5.0/armv6l/rtkrcv differ diff --git a/tools/bin/RTKLIB-2.5.0/armv6l/str2str b/tools/bin/RTKLIB-2.5.0/armv6l/str2str new file mode 100755 index 00000000..e07f432b Binary files /dev/null and b/tools/bin/RTKLIB-2.5.0/armv6l/str2str differ diff --git a/tools/bin/rtklib_b34j/armv7l/compiled_with_buster b/tools/bin/RTKLIB-2.5.0/armv7l/compiled_with_bookworm similarity index 100% rename from tools/bin/rtklib_b34j/armv7l/compiled_with_buster rename to tools/bin/RTKLIB-2.5.0/armv7l/compiled_with_bookworm diff --git a/tools/bin/RTKLIB-2.5.0/armv7l/convbin b/tools/bin/RTKLIB-2.5.0/armv7l/convbin new file mode 100755 index 00000000..97cae751 Binary files /dev/null and b/tools/bin/RTKLIB-2.5.0/armv7l/convbin differ diff --git a/tools/bin/RTKLIB-2.5.0/armv7l/rtkrcv b/tools/bin/RTKLIB-2.5.0/armv7l/rtkrcv new file mode 100755 index 00000000..f62213ec Binary files /dev/null and b/tools/bin/RTKLIB-2.5.0/armv7l/rtkrcv differ diff --git a/tools/bin/RTKLIB-2.5.0/armv7l/str2str b/tools/bin/RTKLIB-2.5.0/armv7l/str2str new file mode 100755 index 00000000..35cac826 Binary files /dev/null and b/tools/bin/RTKLIB-2.5.0/armv7l/str2str differ diff --git a/tools/bin/rtklib_b34j/aarch64/convbin b/tools/bin/rtklib_b34j/aarch64/convbin deleted file mode 100755 index 23b7f878..00000000 Binary files a/tools/bin/rtklib_b34j/aarch64/convbin and /dev/null differ diff --git a/tools/bin/rtklib_b34j/aarch64/rtkrcv b/tools/bin/rtklib_b34j/aarch64/rtkrcv deleted file mode 100755 index c66a69b2..00000000 Binary files a/tools/bin/rtklib_b34j/aarch64/rtkrcv and /dev/null differ diff --git a/tools/bin/rtklib_b34j/aarch64/str2str b/tools/bin/rtklib_b34j/aarch64/str2str deleted file mode 100755 index 5c83f2e1..00000000 Binary files a/tools/bin/rtklib_b34j/aarch64/str2str and /dev/null differ diff --git a/tools/bin/rtklib_b34j/armv6l/convbin b/tools/bin/rtklib_b34j/armv6l/convbin deleted file mode 100755 index 51302dc7..00000000 Binary files a/tools/bin/rtklib_b34j/armv6l/convbin and /dev/null differ diff --git a/tools/bin/rtklib_b34j/armv6l/rtkrcv b/tools/bin/rtklib_b34j/armv6l/rtkrcv deleted file mode 100755 index 493aba6e..00000000 Binary files a/tools/bin/rtklib_b34j/armv6l/rtkrcv and /dev/null differ diff --git a/tools/bin/rtklib_b34j/armv6l/str2str b/tools/bin/rtklib_b34j/armv6l/str2str deleted file mode 100755 index 26580694..00000000 Binary files a/tools/bin/rtklib_b34j/armv6l/str2str and /dev/null differ diff --git a/tools/bin/rtklib_b34j/armv7l/convbin b/tools/bin/rtklib_b34j/armv7l/convbin deleted file mode 100755 index 6cc2b1b2..00000000 Binary files a/tools/bin/rtklib_b34j/armv7l/convbin and /dev/null differ diff --git a/tools/bin/rtklib_b34j/armv7l/rtkrcv b/tools/bin/rtklib_b34j/armv7l/rtkrcv deleted file mode 100755 index ffd3673f..00000000 Binary files a/tools/bin/rtklib_b34j/armv7l/rtkrcv and /dev/null differ diff --git a/tools/bin/rtklib_b34j/armv7l/str2str b/tools/bin/rtklib_b34j/armv7l/str2str deleted file mode 100755 index d1a09b3d..00000000 Binary files a/tools/bin/rtklib_b34j/armv7l/str2str and /dev/null differ diff --git a/tools/convbin.sh b/tools/convbin.sh index 1da6b2f5..91a8020c 100755 --- a/tools/convbin.sh +++ b/tools/convbin.sh @@ -44,14 +44,14 @@ convert_to_rinex_ign_bis() { "${CONVBIN_PATH}" "${args}" return $? } -# Rinex v3.04 - 30s - GPS + GLONASS +# Rinex v3.04 - 30s - GPS + GLONASS + GALILEO convert_to_rinex_nrcan() { echo "- CREATING RINEX " "${RINEX_FILE}" "${CONVBIN_PATH}" "${raw_file}" -v 3.04 -r "${RAW_TYPE}" \ -hc "${RTKBASE_VERSION}" -hm "${MOUNT_NAME}" \ -hp "${ANT_POSITION}" -ha 0000/"${ANT_TYPE}" \ -hr 0000/"${RECEIVER}"/"${REC_VERSION}" \ - -f 2 -y E -y J -y S -y C -y I \ + -f 2 -y J -y S -y C -y I \ -od -os -oi -ot -ti 30 -tt 0 \ -ro "${REC_OPTION}" -o "${RINEX_FILE}" return $? diff --git a/tools/find_rtkbase/CHANGELOG.md b/tools/find_rtkbase/CHANGELOG.md index 96e13a19..ff5f4596 100644 --- a/tools/find_rtkbase/CHANGELOG.md +++ b/tools/find_rtkbase/CHANGELOG.md @@ -1,4 +1,10 @@ # Changelog -## [0.1] - not released +## [0.2] - Not released +### Added +- Shift+click on "open" button open the browser with the RTKBase ip address. +### Changed +- Switch from scapy to requests for http request. + +## [0.1] - 2025-02-16 - First release \ No newline at end of file diff --git a/tools/find_rtkbase/dist/find_rtkbase b/tools/find_rtkbase/dist/find_rtkbase index a559d671..77ba7e43 100755 Binary files a/tools/find_rtkbase/dist/find_rtkbase and b/tools/find_rtkbase/dist/find_rtkbase differ diff --git a/tools/find_rtkbase/dist/find_rtkbase.exe b/tools/find_rtkbase/dist/find_rtkbase.exe index e305a85c..30cf0d19 100644 Binary files a/tools/find_rtkbase/dist/find_rtkbase.exe and b/tools/find_rtkbase/dist/find_rtkbase.exe differ diff --git a/tools/find_rtkbase/find_rtkbase.py b/tools/find_rtkbase/find_rtkbase.py index 2f9756f3..a211d064 100644 --- a/tools/find_rtkbase/find_rtkbase.py +++ b/tools/find_rtkbase/find_rtkbase.py @@ -21,7 +21,7 @@ def __init__(self, master, ports=[80, 443], allscan=False): self.master = master self.ports = ports self.allscan = allscan - master.title("Find RTKBase v0.1") + master.title("Find RTKBase v0.2") master.geometry("400x200") master.columnconfigure(0, weight=1) master.rowconfigure(0, weight=1) @@ -123,12 +123,16 @@ def _after_scan_thread(self): self.base_buttons_list = ["base" + str(i) + "Button" for i, j in enumerate(self.available_base)] if len(self.available_base)>0: for i, base in enumerate(self.available_base): - def action(ip = (base.get('server') or base.get('ip')), port = base.get('port')): + def browser_fqdn(event, ip = (base.get('server') or base.get('ip')), port = base.get('port')): + self.launch_browser(ip, port) + def browser_ip(event, ip = (base.get('ip')), port = base.get('port')): self.launch_browser(ip, port) self.base_labels_list[i] = ttk.Label(self.top_frame, text=f"{base.get('server') or base.get('fqdn')} ({base.get('ip')})") self.base_labels_list[i].grid(column=0, row=i) - self.base_buttons_list[i] = ttk.Button(self.top_frame, text='Open', command=action) + self.base_buttons_list[i] = ttk.Button(self.top_frame, text='Open') + self.base_buttons_list[i].bind("", browser_fqdn) + self.base_buttons_list[i].bind("", browser_ip) self.base_buttons_list[i].grid(column=3, row=i) else: self.nobase_label.grid() diff --git a/tools/find_rtkbase/scan_network.py b/tools/find_rtkbase/scan_network.py index 3978ce50..dd69c9d1 100644 --- a/tools/find_rtkbase/scan_network.py +++ b/tools/find_rtkbase/scan_network.py @@ -1,8 +1,8 @@ #! /usr/bin/env python3 -import json import time import logging import argparse +import requests import scapy.all as scapy scapy.load_layer("http") from zeroconf import Zeroconf @@ -111,12 +111,12 @@ def get_rtkbase_infos(host_list): if address is None: continue log.debug(f"{address}:{port} Api request") - res = http_request(address, path="/api/v1/infos", port=port) + res = requests.get(f"http://{address}:{port}/api/v1/infos", timeout=10) log.debug(f"{address}:{port} Api response: {res}") - ans = json.loads(res.load.decode()) if res is not None else None + ans = res.json() if res is not None and res.status_code == 200 else None if ans: break - except (TimeoutError, TypeError, ConnectionRefusedError) as e: + except (TimeoutError, TypeError, requests.exceptions.ConnectionError) as e: log.debug(f"{address}:{port} - {e}") if ans and ans.get('app') == 'RTKBase': diff --git a/tools/install.sh b/tools/install.sh index cf97628a..5ebabb72 100755 --- a/tools/install.sh +++ b/tools/install.sh @@ -2,9 +2,11 @@ ### RTKBASE INSTALLATION SCRIPT ### declare -a detected_gnss +#detected_gnss content: port/device - brand - port speed - firmware - model declare RTKBASE_USER APT_TIMEOUT='-o dpkg::lock::timeout=3000' #Timeout on lock file (Could not get lock /var/lib/dpkg/lock-frontend) MODEM_AT_PORT=/dev/ttymodemAT +RTKLIB_RELEASE='RTKLIB-2.5.0' man_help(){ echo '################################' @@ -37,8 +39,8 @@ man_help(){ echo ' Install all dependencies like git build-essential python3-pip ...' echo '' echo ' -r | --rtklib' - echo ' Get RTKlib 2.4.3b34j from github and compile it.' - echo ' https://github.com/rtklibexplorer/RTKLIB/tree/b34j' + echo ' Get RTKlib 2.5-EX from github and compile it.' + echo ' https://github.com/rtklibexplorer/RTKLIB/tree/v2.5.0' echo '' echo ' -b | --rtkbase-release' echo ' Get last release of RTKBase:' @@ -103,13 +105,19 @@ _check_user() { fi } +_version() { + # Snippet from https://stackoverflow.com/a/37939589 + echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; +} + + install_dependencies() { echo '################################' echo 'INSTALLING DEPENDENCIES' echo '################################' apt-get "${APT_TIMEOUT}" update -y || exit 1 apt-get "${APT_TIMEOUT}" install -y git build-essential pps-tools python3-pip python3-venv python3-dev python3-setuptools python3-wheel python3-serial libsystemd-dev bc dos2unix socat zip unzip pkg-config psmisc proj-bin nftables || exit 1 - apt-get install -y libxml2-dev libxslt-dev || exit 1 # needed for lxml (for pystemd) + apt-get "${APT_TIMEOUT}" install -y libxml2-dev libxslt-dev || exit 1 # needed for lxml (for pystemd) #apt-get "${APT_TIMEOUT}" upgrade -y } @@ -119,9 +127,9 @@ install_gpsd_chrony() { echo '################################' apt-get "${APT_TIMEOUT}" install chrony gpsd -y || exit 1 #Disabling and masking systemd-timesyncd - systemctl stop systemd-timesyncd - systemctl disable systemd-timesyncd - systemctl mask systemd-timesyncd + systemctl stop systemd-timesyncd > /dev/null 2>&1 + systemctl disable systemd-timesyncd > /dev/null 2>&1 + systemctl mask systemd-timesyncd > /dev/null 2>&1 #Adding GPS as source for chrony grep -q 'set larger delay to allow the GPS' /etc/chrony/chrony.conf || echo '# set larger delay to allow the GPS source to overlap with the other sources and avoid the falseticker status ' >> /etc/chrony/chrony.conf @@ -170,14 +178,14 @@ install_rtklib() { sbc_array=('Xunlong Orange Pi Zero' 'Raspberry Pi' 'OrangePi Zero3') #test if computer_model in sbc_array (https://stackoverflow.com/questions/3685970/check-if-a-bash-array-contains-a-value) if printf '%s\0' "${sbc_array[@]}" | grep -Fxqz -- "${computer_model}" \ - && [[ -f "${rtkbase_path}"'/tools/bin/rtklib_b34j/'"${arch_package}"'/str2str' ]] \ - && lsb_release -c | grep -qE 'bullseye|bookworm' \ - && "${rtkbase_path}"'/tools/bin/rtklib_b34j/'"${arch_package}"/str2str --version > /dev/null 2>&1 + && [[ -f "${rtkbase_path}"'/tools/bin/'"${RTKLIB_RELEASE}"'/'"${arch_package}"'/str2str' ]] \ + && lsb_release -c | grep -qE 'bullseye|bookworm|trixie' \ + && "${rtkbase_path}"'/tools/bin/'"${RTKLIB_RELEASE}"'/'"${arch_package}"/str2str --version > /dev/null 2>&1 then echo 'Copying new rtklib binary for ' "${computer_model}" ' - ' "${arch_package}" - cp "${rtkbase_path}"'/tools/bin/rtklib_b34j/'"${arch_package}"/str2str /usr/local/bin/ - cp "${rtkbase_path}"'/tools/bin/rtklib_b34j/'"${arch_package}"/rtkrcv /usr/local/bin/ - cp "${rtkbase_path}"'/tools/bin/rtklib_b34j/'"${arch_package}"/convbin /usr/local/bin/ + cp "${rtkbase_path}"'/tools/bin/'"${RTKLIB_RELEASE}"'/'"${arch_package}"/str2str /usr/local/bin/ + cp "${rtkbase_path}"'/tools/bin/'"${RTKLIB_RELEASE}"'/'"${arch_package}"/rtkrcv /usr/local/bin/ + cp "${rtkbase_path}"'/tools/bin/'"${RTKLIB_RELEASE}"'/'"${arch_package}"/convbin /usr/local/bin/ else echo 'No binary available for ' "${computer_model}" ' - ' "${arch_package}" '. We will build it from source' _compil_rtklib @@ -186,20 +194,21 @@ install_rtklib() { _compil_rtklib() { echo '################################' - echo 'COMPILING RTKLIB 2.4.3 b34j' + echo 'COMPILING ' "${RTKLIB_RELEASE}" echo '################################' - #Get Rtklib 2.4.3 b34j release - sudo -u "${RTKBASE_USER}" wget -qO - https://github.com/rtklibexplorer/RTKLIB/archive/refs/tags/b34j.tar.gz | tar -xvz + TMPDIR=$(mktemp -dt RTKLIB.XXXXX) || return 1 + #Get Rtklib 2.5.0 release + sudo -u "${RTKBASE_USER}" wget -qO - https://github.com/rtklibexplorer/RTKLIB/archive/refs/tags/v2.5.0.tar.gz | tar -xvz --directory "${TMPDIR}" #Install Rtklib app #TODO add correct CTARGET in makefile? - make --directory=RTKLIB-b34j/app/consapp/str2str/gcc - make --directory=RTKLIB-b34j/app/consapp/str2str/gcc install - make --directory=RTKLIB-b34j/app/consapp/rtkrcv/gcc - make --directory=RTKLIB-b34j/app/consapp/rtkrcv/gcc install - make --directory=RTKLIB-b34j/app/consapp/convbin/gcc - make --directory=RTKLIB-b34j/app/consapp/convbin/gcc install + make --directory="${TMPDIR}"/"${RTKLIB_RELEASE}"/app/consapp/str2str/gcc + make --directory="${TMPDIR}"/"${RTKLIB_RELEASE}"/app/consapp/str2str/gcc install + make --directory="${TMPDIR}"/"${RTKLIB_RELEASE}"/app/consapp/rtkrcv/gcc + make --directory="${TMPDIR}"/"${RTKLIB_RELEASE}"/app/consapp/rtkrcv/gcc install + make --directory="${TMPDIR}"/"${RTKLIB_RELEASE}"/app/consapp/convbin/gcc + make --directory="${TMPDIR}"/"${RTKLIB_RELEASE}"/app/consapp/convbin/gcc install #deleting RTKLIB - rm -rf RTKLIB-b34j/ + rm -rf "${TMPDIR}"/"${RTKLIB_RELEASE}"/ } _rtkbase_repo(){ @@ -423,7 +432,7 @@ detect_gnss() { echo '################################' echo 'UART GNSS RECEIVER DETECTION' echo '################################' - systemctl is-active --quiet str2str_tcp.service && sudo systemctl stop str2str_tcp.service && echo 'Stopping str2str_tcp service' + systemctl is-active --quiet str2str_tcp.service && systemctl stop str2str_tcp.service && echo 'Stopping str2str_tcp service' # TODO remove port if not available in /dev/ for port in ttyS0 ttyUSB0 ttyUSB1 ttyUSB2 serial0 ttyS1 ttyS2 ttyS3 ttyS4 ttyS5; do for port_speed in 115200 57600 38400 19200 9600; do @@ -451,29 +460,38 @@ detect_gnss() { [[ ${#detected_gnss[*]} -eq 2 ]] && detected_gnss[2]='115200' # If /dev/ttyGNSS is a symlink of the detected serial port, switch to ttyGNSS [[ '/dev/ttyGNSS' -ef '/dev/'"${detected_gnss[0]}" ]] && detected_gnss[0]='ttyGNSS' - # Get firmware release + # Get model and firmware release if [[ "${detected_gnss[1]}" =~ 'u-blox' ]] then - #get F9P firmware release - detected_gnss[3]=$(python3 "${rtkbase_path}"/tools/ubxtool -f /dev/"${detected_gnss[0]}" -s ${detected_gnss[2]} -p MON-VER | grep 'FWVER' | awk '{print $NF}') - sudo -u "${RTKBASE_USER}" sed -i s/^receiver_firmware=.*/receiver_firmware=\'${firmware}\'/ "${rtkbase_path}"/settings.conf + detected_gnss[1]='u-blox' + #get U-Blox firmware release + ubx_monver="$(python3 "${rtkbase_path}"/tools/ubxtool -f /dev/"${detected_gnss[0]}" -s ${detected_gnss[2]} -p MON-VER | grep -e 'FWVER' -e 'MOD')" + detected_gnss[3]=$(grep 'FWVER' <<< "${ubx_monver}" | awk '{print $NF}') + [[ $(grep 'MOD' <<< "${ubx_monver}" | awk -F '=' '{print $NF}') == 'ZED-F9P' ]] && detected_gnss[4]='ZED-F9P' + elif [[ "${detected_gnss[1]}" =~ 'Septentrio' ]] then - #get mosaic-X5 firmware release - detected_gnss[3]="$(python3 "${rtkbase_path}"/tools/sept_tool.py --port /dev/ttyGNSS_CTRL --baudrate ${detected_gnss[2]} --command get_firmware --retry 5)" || firmware='?' + detected_gnss[1]='septentrio' + #get Septentrio model and firmware release + detected_gnss[3]="$( { python3 "${rtkbase_path}"/tools/sept_tool.py --port /dev/ttyGNSS_CTRL --baudrate ${detected_gnss[2]} --command get_firmware --retry 5 2>/dev/null || echo '?'; } | tail -n 1 )" + detected_gnss[4]="$( { python3 "${rtkbase_path}"/tools/sept_tool.py --port /dev/ttyGNSS_CTRL --baudrate ${detected_gnss[2]} --command get_model --retry 5 2>/dev/null || echo '?'; } | tail -n 1 )" + elif [[ "${detected_gnss[1]}" =~ 'unicore' ]] then - #get Unicore UM98X firmware release - detected_gnss[3]="$(python3 "${rtkbase_path}"/tools/unicore_tool.py --port /dev/"${detected_gnss[0]}" --baudrate ${detected_gnss[2]} --command get_firmware 2>/dev/null)" || firmware='?' + detected_gnss[1]='unicore' + #get Unicore model and firmware release + detected_gnss[3]="$( { python3 "${rtkbase_path}"/tools/unicore_tool.py --port /dev/"${detected_gnss[0]}" --baudrate ${detected_gnss[2]} --command get_firmware --retry 5 2>/dev/null || echo '?'; } | tail -n 1 )" + detected_gnss[4]="$( { python3 "${rtkbase_path}"/tools/unicore_tool.py --port /dev/"${detected_gnss[0]}" --baudrate ${detected_gnss[2]} --command get_model --retry 5 2>/dev/null || echo '?'; } | tail -n 1 )" + fi # "send" result - echo '/dev/'"${detected_gnss[0]}" ' - ' "${detected_gnss[1]}"' - ' "${detected_gnss[2]}"' - ' "${detected_gnss[3]}" + echo '/dev/'"${detected_gnss[0]}" ' - ' "${detected_gnss[1]}"' - ' "${detected_gnss[2]}"' - ' "${detected_gnss[3]}"' - ' "${detected_gnss[4]}" #Write Gnss receiver settings inside settings.conf #Optional argument --no-write-port (here as variable $1) will prevent settings.conf modifications. It will be just a detection without any modification. - if [[ ${#detected_gnss[*]} -eq 4 ]] && [[ "${1}" -eq 0 ]] + if [[ ${#detected_gnss[*]} -eq 5 ]] && [[ "${1}" -eq 0 ]] then - echo 'GNSS RECEIVER DETECTED: /dev/'"${detected_gnss[0]}" ' - ' "${detected_gnss[1]}" ' - ' "${detected_gnss[2]}" + echo 'GNSS RECEIVER DETECTED: /dev/'"${detected_gnss[0]}" ' - ' "${detected_gnss[1]}" ' - ' "${detected_gnss[2]}" ' - ' "${detected_gnss[3]}"' - ' "${detected_gnss[4]}" #if [[ ${detected_gnss[1]} =~ 'u-blox' ]] #then # gnss_format='ubx' @@ -483,12 +501,13 @@ detect_gnss() { #change the com port value/settings inside settings.conf sudo -u "${RTKBASE_USER}" sed -i s/^com_port=.*/com_port=\'${detected_gnss[0]}\'/ "${rtkbase_path}"/settings.conf sudo -u "${RTKBASE_USER}" sed -i s/^com_port_settings=.*/com_port_settings=\'${detected_gnss[2]}:8:n:1\'/ "${rtkbase_path}"/settings.conf - sudo -u "${RTKBASE_USER}" sed -i s/^receiver_firmware=.*/receiver_firmware=\'"${detected_gnss[3]}"\'/ "${rtkbase_path}"/settings.conf + sudo -u "${RTKBASE_USER}" sed -i s/^receiver_firmware=.*/receiver_firmware=\'"${detected_gnss[3]}"\'/ "${rtkbase_path}"/settings.conf + sudo -u "${RTKBASE_USER}" sed -i s/^receiver=.*/receiver=\'"${detected_gnss[1]}"_"${detected_gnss[4]}"\'/ "${rtkbase_path}"/settings.conf else echo 'settings.conf is missing' return 1 fi - elif [[ ${#detected_gnss[*]} -ne 4 ]] + elif [[ ${#detected_gnss[*]} -ne 5 ]] then return 1 fi @@ -513,7 +532,17 @@ configure_gnss(){ if [ -d "${rtkbase_path}" ] then source <( grep -v '^#' "${rtkbase_path}"/settings.conf | grep '=' ) - systemctl is-active --quiet str2str_tcp.service && sudo systemctl stop str2str_tcp.service + systemctl is-active --quiet str2str_tcp.service && systemctl stop str2str_tcp.service + #cleaning receiver options + sudo -u "${RTKBASE_USER}" sed -i s/^ntrip_a_receiver_options=.*/ntrip_a_receiver_options=/ "${rtkbase_path}"/settings.conf && \ + sudo -u "${RTKBASE_USER}" sed -i s/^ntrip_b_receiver_options=.*/ntrip_b_receiver_options=/ "${rtkbase_path}"/settings.conf && \ + sudo -u "${RTKBASE_USER}" sed -i s/^local_ntripc_receiver_options=.*/local_ntripc_receiver_options=/ "${rtkbase_path}"/settings.conf && \ + sudo -u "${RTKBASE_USER}" sed -i s/^rtcm_receiver_options=.*/rtcm_receiver_options=/ "${rtkbase_path}"/settings.conf && \ + sudo -u "${RTKBASE_USER}" sed -i s/^rtcm_client_receiver_options=.*/rtcm_client_receiver_options=/ "${rtkbase_path}"/settings.conf && \ + sudo -u "${RTKBASE_USER}" sed -i s/^rtcm_udp_svr_receiver_options=.*/rtcm_udp_svr_receiver_options=/ "${rtkbase_path}"/settings.conf && \ + sudo -u "${RTKBASE_USER}" sed -i s/^rtcm_udp_client_receiver_options=.*/rtcm_udp_client_receiver_options=/ "${rtkbase_path}"/settings.conf && \ + sudo -u "${RTKBASE_USER}" sed -i s/^rtcm_serial_receiver_options=.*/rtcm_serial_receiver_options=/ "${rtkbase_path}"/settings.conf + #if the receiver is a U-Blox F9P, launch the set_zed-f9p.sh. This script will reset the F9P and configure it with the corrects settings for rtkbase if [[ $(python3 "${rtkbase_path}"/tools/ubxtool -f /dev/"${com_port}" -s ${com_port_settings%%:*} -p MON-VER) =~ 'ZED-F9P' ]] then @@ -551,8 +580,14 @@ configure_gnss(){ echo 'Resetting the mosaic-X5 settings....' python3 "${rtkbase_path}"/tools/sept_tool.py --port /dev/ttyGNSS_CTRL --baudrate ${com_port_settings%%:*} --command reset --retry 5 sleep_time=30 ; echo 'Waiting '$sleep_time's for mosaic-X5 reboot' ; sleep $sleep_time - echo 'Sending settings....' - python3 "${rtkbase_path}"/tools/sept_tool.py --port /dev/ttyGNSS_CTRL --baudrate ${com_port_settings%%:*} --command send_config_file "${rtkbase_path}"/receiver_cfg/Septentrio_Mosaic-X5.cfg --store --retry 5 + if [ $(_version $firmware) -ge $(_version '4.15.0') ] + then + echo 'Sending settings....' + python3 "${rtkbase_path}"/tools/sept_tool.py --port /dev/ttyGNSS_CTRL --baudrate ${com_port_settings%%:*} --command send_config_file "${rtkbase_path}"/receiver_cfg/Septentrio_Mosaic-X5_4.15.cfg --store --retry 5 + else + echo 'Sending legacy settings....' + python3 "${rtkbase_path}"/tools/sept_tool.py --port /dev/ttyGNSS_CTRL --baudrate ${com_port_settings%%:*} --command send_config_file "${rtkbase_path}"/receiver_cfg/Septentrio_Mosaic-X5.cfg --store --retry 5 + fi if [[ $? -eq 0 ]] then echo 'Septentrio Mosaic-X5 successfuly configured' @@ -684,10 +719,11 @@ install_zeroconf_service() { echo 'INSTALLING ZEROCONF/AVAHI DEFINITION SERVICE' echo '################################' #Test is avahi is running and directory for services definition exists + type avahi-daemon >/dev/null 2>&1 || apt-get "${APT_TIMEOUT}" install -y avahi-daemon if systemctl is-active --quiet avahi-daemon.service && [[ -d /etc/avahi/services ]] then web_port=$(grep "^web_port=.*" "${rtkbase_path}"/settings.conf | cut -d "=" -f2) - sed -e 's|{port}|'$web_port'|' "${rtkbase_path}"/tools/zeroconf/rtkbase_web.service >> /etc/avahi/services/rtkbase_web.service + sed -e 's|{port}|'$web_port'|' "${rtkbase_path}"/tools/zeroconf/rtkbase_web.service > /etc/avahi/services/rtkbase_web.service else echo 'Can'\''t install avahi definition service, missing avahi service or /etc/avahi/services directory' fi diff --git a/tools/rtkbase_update.sh b/tools/rtkbase_update.sh index 0bd919c6..3f577e32 100755 --- a/tools/rtkbase_update.sh +++ b/tools/rtkbase_update.sh @@ -49,21 +49,21 @@ check_before_update() { case $ID in debian) - if (( $(echo "$VERSION_ID < 11" | bc -l) )) + if (( $(echo "$VERSION_ID < 12" | bc -l) )) then printf "${TOO_OLD}" >/dev/stderr exit 1 fi ;; raspbian) - if (( $(echo "$VERSION_ID < 11" | bc -l) )) + if (( $(echo "$VERSION_ID < 12" | bc -l) )) then printf "${TOO_OLD}" >/dev/stderr exit 1 fi ;; ubuntu) - if (( $(echo "$VERSION_ID < 22.04" | bc -l) )) + if (( $(echo "$VERSION_ID < 24.04" | bc -l) )) then printf "${TOO_OLD}" >/dev/stderr exit 1 @@ -73,24 +73,24 @@ check_before_update() { } update() { -echo 'remove existing rtkbase.old directory' -rm -rf /var/tmp/rtkbase.old -mkdir /var/tmp/rtkbase.old - -echo "copy rtkbase to rtkbase.old except /data directory" -cp -r ${destination_directory}/!(${data_dir}|venv) /var/tmp/rtkbase.old - -#Don't do that or it will stop the update process -#systemctl stop rtkbase_web.service - -echo "copy new release to destination" -if [[ -d ${source_directory} ]] && [[ -d ${destination_directory} ]] - then - cp -rfp ${source_directory}/. ${destination_directory} - else - echo 'can t copy' - exit 1 -fi + echo 'remove existing rtkbase.old directory' + rm -rf /var/tmp/rtkbase.old + mkdir /var/tmp/rtkbase.old + + echo "copy rtkbase to rtkbase.old except /data directory" + cp -r ${destination_directory}/!(${data_dir}|venv) /var/tmp/rtkbase.old + + #Don't do that or it will stop the update process + #systemctl stop rtkbase_web.service + + echo "copy new release to destination" + if [[ -d ${source_directory} ]] && [[ -d ${destination_directory} ]] + then + cp -rfp ${source_directory}/. ${destination_directory} + else + echo 'can t copy' + exit 1 + fi } insert_rtcm_msg() { @@ -257,15 +257,32 @@ upd_2.6.2() { upd_2.6.3() { echo '##########################' - echo 'Update from 2.6.3 to 2.6.x' + echo 'Update from 2.6.3 to 2.6.4' echo '##########################' # install updated service and new avahi service definition (forgot it on the previous update) "${destination_directory}"/tools/install.sh --user "${standard_user}" --unit-files --zeroconf + upd_2.6.4 "$@" +} +upd_2.6.4() { + echo '##########################' + echo 'Update from 2.6.4 to 2.7.0' + echo '##########################' + # install updated service and new avahi service definition (forgot it on the previous update) + "${destination_directory}"/tools/install.sh --user "${standard_user}" --unit-files --zeroconf + # upgrade dependencies + "${destination_directory}"/tools/install.sh --user "${standard_user}" --dependencies --rtkbase-requirements + #upgrade rtklib to RTKLib 2.5 + upgrade_rtklib + # restart str2str if it was active before upgrading rtklib + [ $str2str_active = 'active' ] && systemctl restart str2str_tcp + [ $str2str_file = 'active' ] && systemctl restart str2str_file + [ $rtkrcv_raw2nmea = 'active' ] && systemctl restart rtkbase_raw2nmea + echo 'Main service restarted' } #check if we can apply the update -#FOR THE OLDER ME -> Don't forget to modify the os detection if there is a 2.5.x release !!! +#FOR THE OLDER ME -> Don't forget to modify the os detection if there is a 2.7.x release !!! [[ $checking == '--checking' ]] && check_before_update && exit echo '################################' diff --git a/tools/sept_tool.py b/tools/sept_tool.py index ca9fd7d0..fb3955a7 100644 --- a/tools/sept_tool.py +++ b/tools/sept_tool.py @@ -10,7 +10,7 @@ logging.basicConfig(format='%(levelname)s: %(message)s') log = logging.getLogger(__name__) -log.setLevel('ERROR') +log.setLevel('WARNING') class CmdMapping(Enum): """Mapping human command to septentrio_cmd methods""" @@ -33,17 +33,16 @@ def arg_parse(): parser.add_argument("-r", "--retry", help="set a number of retry if the command fails", default=0, type=int) parser.add_argument("-d", "--debug", action='store_true') parser.add_argument("--version", action="version", version="%(prog)s 1.1") - args = parser.parse_args() - return args + return parser.parse_args() if __name__ == '__main__': args = arg_parse() if args.debug: log.setLevel('DEBUG') - log.debug(f"Arguments: {args}") + log.debug("Arguments: %s", args) command = args.command[0] retries = 0 - retry_delay = 2 + RETRY_DELAY = 2 while retries <= args.retry: try: with SeptGnss(args.port, baudrate=args.baudrate, timeout=30, debug=args.debug) as gnss: @@ -54,11 +53,11 @@ def arg_parse(): gnss.set_config_permanent() break except Exception as e: - log.debug("Exception: ",e) + log.debug("Exception: %s",e) retries += 1 if retries <= args.retry: - print("Failed...retrying in {}s".format(retry_delay)) - time.sleep(retry_delay) + log.warning("Failed...retrying in %ss", RETRY_DELAY) + time.sleep(RETRY_DELAY) if retries > args.retry: - print("Command failed!") + log.error("Command failed!") sys.exit(1) \ No newline at end of file diff --git a/tools/unicore_tool.py b/tools/unicore_tool.py index 680f1f32..a33f9f02 100644 --- a/tools/unicore_tool.py +++ b/tools/unicore_tool.py @@ -10,7 +10,7 @@ logging.basicConfig(format='%(levelname)s: %(message)s') log = logging.getLogger(__name__) -log.setLevel('ERROR') +log.setLevel('WARNING') class CmdMapping(Enum): """Mapping human command to unicore_cmd methods""" @@ -32,17 +32,16 @@ def arg_parse(): parser.add_argument("-r", "--retry", help="set a number of retry if the command fails", default=0, type=int) parser.add_argument("-d", "--debug", action='store_true') parser.add_argument("--version", action="version", version="%(prog)s 1.0") - args = parser.parse_args() - return args + return parser.parse_args() if __name__ == '__main__': args = arg_parse() if args.debug: log.setLevel('DEBUG') - log.debug(f"Arguments: {args}") + log.debug("Arguments: %s", args) command = args.command[0] retries = 0 - retry_delay = 2 + RETRY_DELAY = 2 while retries <= args.retry: try: with UnicoGnss(args.port, baudrate=args.baudrate, timeout=2, debug=args.debug) as gnss: @@ -53,11 +52,11 @@ def arg_parse(): gnss.set_config_permanent() break except Exception as e: - log.debug("Exception: ",e) + log.debug("Exception: %s",e) retries += 1 if retries <= args.retry: - log.warning("Failed...retrying in {}s".format(retry_delay)) - time.sleep(retry_delay) + log.warning("Failed...retrying in %ss", RETRY_DELAY) + time.sleep(RETRY_DELAY) if retries > args.retry: - print("Command failed!") + log.error("Command failed!") sys.exit(1) \ No newline at end of file diff --git a/unit/rtkbase_web.service b/unit/rtkbase_web.service index 09f0c6ac..8bbdc470 100644 --- a/unit/rtkbase_web.service +++ b/unit/rtkbase_web.service @@ -5,6 +5,7 @@ Description=RTKBase Web Server [Service] User=root +SyslogIdentifier=rtkbase_web ExecStart={python_path} {script_path}/web_app/server.py Restart=on-failure RestartSec=30 diff --git a/unit/str2str_file.service b/unit/str2str_file.service index fcf2e075..d58d66c3 100644 --- a/unit/str2str_file.service +++ b/unit/str2str_file.service @@ -4,7 +4,8 @@ Requires=str2str_tcp.service After=str2str_tcp.service [Service] -Type=forking +Type=simple +SyslogIdentifier=str2str_file User={user} ExecStart={script_path}/run_cast.sh in_tcp out_file Restart=on-failure diff --git a/unit/str2str_local_ntrip_caster.service b/unit/str2str_local_ntrip_caster.service index dbfa602a..9a5eafda 100644 --- a/unit/str2str_local_ntrip_caster.service +++ b/unit/str2str_local_ntrip_caster.service @@ -6,7 +6,8 @@ Requires=str2str_tcp.service After=str2str_tcp.service [Service] -Type=forking +Type=simple +SyslogIdentifier=str2str_local_ntrip_caster User={user} ExecStart={script_path}/run_cast.sh in_tcp out_local_caster Restart=on-failure diff --git a/unit/str2str_ntrip_A.service b/unit/str2str_ntrip_A.service index 58542e9d..43730b68 100644 --- a/unit/str2str_ntrip_A.service +++ b/unit/str2str_ntrip_A.service @@ -6,7 +6,8 @@ Requires=str2str_tcp.service After=str2str_tcp.service [Service] -Type=forking +Type=simple +SyslogIdentifier=str2str_ntrip_A User={user} ExecStart={script_path}/run_cast.sh in_tcp out_caster_A Restart=on-failure diff --git a/unit/str2str_ntrip_B.service b/unit/str2str_ntrip_B.service index 3a164ae6..170cc8dc 100644 --- a/unit/str2str_ntrip_B.service +++ b/unit/str2str_ntrip_B.service @@ -6,7 +6,8 @@ Requires=str2str_tcp.service After=str2str_tcp.service [Service] -Type=forking +Type=simple +SyslogIdentifier=str2str_ntrip_B User={user} ExecStart={script_path}/run_cast.sh in_tcp out_caster_B Restart=on-failure diff --git a/unit/str2str_rtcm_serial.service b/unit/str2str_rtcm_serial.service index 9f5c617f..b2581e65 100644 --- a/unit/str2str_rtcm_serial.service +++ b/unit/str2str_rtcm_serial.service @@ -6,7 +6,8 @@ Requires=str2str_tcp.service After=str2str_tcp.service [Service] -Type=forking +Type=simple +SyslogIdentifier=str2str_rtcm_serial User={user} ExecStart={script_path}/run_cast.sh in_tcp out_rtcm_serial Restart=on-failure diff --git a/unit/str2str_rtcm_svr.service b/unit/str2str_rtcm_svr.service index c78392dd..3d8630eb 100644 --- a/unit/str2str_rtcm_svr.service +++ b/unit/str2str_rtcm_svr.service @@ -6,7 +6,8 @@ Requires=str2str_tcp.service After=str2str_tcp.service [Service] -Type=forking +Type=simple +SyslogIdentifier=str2str_rtcm_svr User={user} ExecStart={script_path}/run_cast.sh in_tcp out_rtcm_svr Restart=on-failure diff --git a/unit/str2str_tcp.service b/unit/str2str_tcp.service index 5879fb09..d586de7f 100644 --- a/unit/str2str_tcp.service +++ b/unit/str2str_tcp.service @@ -5,7 +5,8 @@ Description=RTKBase Tcp #Requires=network-online.target [Service] -Type=forking +Type=simple +SyslogIdentifier=str2str_tcp User={user} ExecStart={script_path}/run_cast.sh in_serial out_tcp Restart=on-failure diff --git a/web_app/LogManager.py b/web_app/LogManager.py index 4597ff88..13711108 100644 --- a/web_app/LogManager.py +++ b/web_app/LogManager.py @@ -94,11 +94,15 @@ def getLogFormat(self, log_path): if os.path.isfile(potential_zip_path): return "RINEX" """ - if (extension in self.supported_solution_formats or - extension in self.convbin.supported_log_formats): - return extension.upper() - else: - return "" + log_format = "?" + if extension : + if (extension in self.supported_solution_formats or + extension in self.convbin.supported_log_formats): + log_format = extension.upper() + if extension in self.convbin.supported_output_formats: + log_format = "RINEX" + + return log_format def formTimeString(self, seconds): # form a x minutes y seconds string from seconds diff --git a/web_app/RTKBaseConfigManager.py b/web_app/RTKBaseConfigManager.py index eabd3032..cf1c7290 100644 --- a/web_app/RTKBaseConfigManager.py +++ b/web_app/RTKBaseConfigManager.py @@ -110,7 +110,7 @@ def get_main_settings(self): and remove the single quotes. """ ordered_main = [{"source_section" : "main"}] - for key in ("position", "com_port", "com_port_settings", "receiver", "receiver_firmware", "receiver_format", "antenna_info", "tcp_port", "gnss_rcv_web_ip", "gnss_rcv_web_proxy_port"): + for key in ("position", "com_port", "com_port_settings", "receiver", "receiver_firmware", "receiver_format", "antenna_info", "tcp_host_addr", "tcp_port", "gnss_rcv_web_ip", "gnss_rcv_web_proxy_port"): ordered_main.append({key : self.config.get('main', key).strip("'")}) return ordered_main diff --git a/web_app/ServiceController.py b/web_app/ServiceController.py index 250879f7..be31a62a 100644 --- a/web_app/ServiceController.py +++ b/web_app/ServiceController.py @@ -55,12 +55,26 @@ def status(self): return (self.unit.Unit.SubState).decode() def start(self): + """ + Start the unit. + It will reset the failed counter before starting the unit. + """ + try: + self.manager.Manager.ResetFailedUnit(self.unit.Unit.Names[0]) + except: + pass self.manager.Manager.EnableUnitFiles(self.unit.Unit.Names, False, True) return self.unit.Unit.Start(b'replace') def stop(self): + """ + Stop the unit. + """ self.manager.Manager.DisableUnitFiles(self.unit.Unit.Names, False) return self.unit.Unit.Stop(b'replace') def restart(self): + """ + Restart the unit. + """ return self.unit.Unit.Restart(b'replace') \ No newline at end of file diff --git a/web_app/gnss_rproxy_server.py b/web_app/gnss_rproxy_server.py index 7c08a6e8..14b658b4 100644 --- a/web_app/gnss_rproxy_server.py +++ b/web_app/gnss_rproxy_server.py @@ -125,7 +125,7 @@ def redirect_to_API_HOST(path): #NOTE var :path will be unused as all path we n return response -@app.route('/login', methods=['GET', 'POST']) +@app.route('/gnsslogin', methods=['GET', 'POST']) def login_page(): if current_user.is_authenticated: return redirect(url_for('index')) @@ -146,7 +146,7 @@ def login_page(): return render_template('proxy_login.html', title='Sign In', form=loginform) -@app.route('/logout') +@app.route('/gnsslogout') def logout(): logout_user() return redirect(url_for('login_page')) diff --git a/web_app/log_converter/convbin.py b/web_app/log_converter/convbin.py index ce273033..1a380949 100644 --- a/web_app/log_converter/convbin.py +++ b/web_app/log_converter/convbin.py @@ -26,7 +26,8 @@ class Convbin: - supported_log_formats = ["rtcm2", "rtcm3", "nov", "oem3", "ubx", "ss2", "hemis", "stq", "javad", "nvs", "binex", "rinex", "unicore"] + supported_log_formats = ["rtcm2", "rtcm3", "nov", "oem3", "ubx", "ss2", "hemis", "stq", "javad", "nvs", "binex", "rinex", "unicore", "sbf"] + supported_output_formats = ["obs", "20o", "21o", "22o", "23o", "24o", "25o", "26o", "27o", "28o", "29o", "30o", ] def __init__(self, rtklib_path): self.bin_path = rtklib_path diff --git a/web_app/network_infos.py b/web_app/network_infos.py index c2840da8..f71b92e3 100644 --- a/web_app/network_infos.py +++ b/web_app/network_infos.py @@ -51,9 +51,9 @@ def get_up_if(): def get_interfaces_infos(): """ Get all up network interfaces with their ip v4/v6 addresses - and the connection name. + the connection name and its mac address. It returns a list of dict - e.g. [{'device': 'end0', 'ipv4': ['192.168.1.135'], 'ipv6': [], 'conn_name': 'Wired connection 1'}] + e.g. [{'device': 'end0', 'ipv4': ['192.168.1.135'], 'ipv6': [], 'conn_name': 'Wired connection 1'}, 'hwaddr': '02:81:4E:7C:37:4F'] Return: list: all up network interfaces as dict @@ -86,6 +86,7 @@ def get_interfaces_infos(): conn_name = get_conn_name(k) if conn_name: device_info["conn_name"] = conn_name + device_info["hwaddr"] = nmcli.device.show(k).get('GENERAL.HWADDR') interfaces_infos.append(device_info) return interfaces_infos diff --git a/web_app/requirements.txt b/web_app/requirements.txt index ac559b3d..21c779f4 100644 --- a/web_app/requirements.txt +++ b/web_app/requirements.txt @@ -1,39 +1,41 @@ -bidict==0.22.1 -blinker==1.6.3 -Bootstrap-Flask==2.4.0 -certifi==2024.2.2 -cffi==1.16.0 -charset-normalizer==3.3.2 -click==8.1.7 -cryptography==42.0.7 -distro==1.8.0 -dnspython==2.6.1 -Flask==3.0.3 +bidict==0.23.1 +blinker==1.9.0 +Bootstrap-Flask==2.5.0 +certifi==2025.8.3 +charset-normalizer==3.4.3 +click==8.1.8 +distro==1.9.0 +Flask==3.1.2 Flask-Login==0.6.3 -Flask-SocketIO==5.3.6 -Flask-WTF==1.2.1 -gevent==24.2.1 -gunicorn==22.0.0 -h11==0.14.0 -idna==3.7 -itsdangerous==2.1.2 -Jinja2==3.1.4 -lxml==4.9.3 -MarkupSafe==2.1.3 -nmcli==1.3.0 -pexpect==4.8.0 -psutil==5.9.6 +Flask-SocketIO==5.5.1 +Flask-WTF==1.2.2 +future==1.0.0 +gevent==25.4.2 +greenlet==3.2.4 +gunicorn==23.0.0 +h11==0.16.0 +idna==3.10 +iso8601==2.1.0 +itsdangerous==2.2.0 +Jinja2==3.1.6 +lxml==6.0.1 +MarkupSafe==3.0.2 +nmcli==1.5.0 +packaging==25.0 +pexpect==4.9.0 +psutil==7.0.0 ptyprocess==0.7.0 -pycparser==2.21 -pyOpenSSL==24.1.0 -pyserial==3.5 -pystemd==0.13.2 -python-engineio==4.8.0 -python-socketio==5.10.0 -requests==2.32.3 -simple-websocket==1.0.0 -six==1.16.0 -urllib3==2.0.7 -Werkzeug==3.0.3 +pystemd==0.13.4 +python-engineio==4.12.2 +python-socketio==5.13.0 +PyYAML==6.0.2 +requests==2.32.5 +serial==0.0.97 +setuptools==80.9.0 +simple-websocket==1.1.0 +urllib3==2.5.0 +Werkzeug==3.1.3 wsproto==1.2.0 -WTForms==3.1.0 +WTForms==3.2.1 +zope.event==5.1.1 +zope.interface==7.2 \ No newline at end of file diff --git a/web_app/server.py b/web_app/server.py index 25049774..8e40a868 100755 --- a/web_app/server.py +++ b/web_app/server.py @@ -92,6 +92,7 @@ #Get settings from settings.conf.default and settings.conf rtkbaseconfig = RTKBaseConfigManager(os.path.join(rtkbase_path, "settings.conf.default"), os.path.join(rtkbase_path, "settings.conf")) +app.config["DOWNLOAD_FOLDER"] = rtkbaseconfig.get("local_storage", "datadir").strip("'") rtk = RTKLIB(socketio, rtklib_path=path_to_rtklib, @@ -210,25 +211,39 @@ def manager(): def repaint_services_button(services_list): """ - set service color on web app frontend depending on the service status: - status = running => green button + Sets service color on web app frontend depending on the service status: + status = running => green button status = auto-restart => orange button (alert) - result = exit-code => red button (danger) + result = exit-code or signal => red button (danger) """ for service in services_list: + """ if service.get("status") == "running": service["btn_color"] = "success" - #elif service.get("status") == "dead": - # service["btn_color"] = "danger" - elif service.get("result") == "exit-code": + service["btn_off_color"] = "outline-secondary" + elif service.get("result") == "exit-code" or service.get("result") == "signal": service["btn_color"] = "warning" + service["btn_off_color"] = "danger" elif service.get("status") == "auto-restart": service["btn_color"] = "warning" + if service.get("status") == "failed": + service["btn_off_color"] = "danger" + if service.get("state_ok") == False: service["btn_off_color"] = "outline-danger" elif service.get("state_ok") == True: + service["btn_off_color"] = "outline-secondary" + """ + + if service.get("status") == "running": + service["btn_color"] = "success" + elif service.get("status") == "auto-restart": + service["btn_color"] = "warning" + elif service.get("result") == "success": service["btn_off_color"] = "outline-secondary" + elif service.get("result") == "exit-code" or service.get("result") == "signal": + service["btn_off_color"] = "danger" return services_list @@ -393,11 +408,12 @@ def download_update(update_path): return update_archive @app.before_request -def inject_release(): +def inject_global_infos(): """ - Insert the RTKBase release number as a global variable for Flask/Jinja + Insert various informations as global variables for Flask/Jinja """ g.version = rtkbaseconfig.get("general", "version") + g.station_name = rtkbaseconfig.get_ntrip_A_settings()[4]['mnt_name_A'] g.sbc_model = get_sbc_model() @login.user_loader @@ -634,8 +650,13 @@ def detect_receiver(json_msg): #print("DEBUG ok stdout: ", answer.stdout) try: device_info = next(x for x in answer.stdout.splitlines() if x.startswith('/dev/')).split(' - ') - port, gnss_type, speed, firmware = [x.strip() for x in device_info] - result = {"result" : "success", "port" : port, "gnss_type" : gnss_type, "port_speed" : speed, "firmware" : firmware} + port, gnss_type, speed, firmware, model = [x.strip() for x in device_info] + result = {"result" : "success", + "port" : port, + "gnss_type" : gnss_type, + "port_speed" : speed, + "firmware" : firmware, + "model" : model} result.update(json_msg) except Exception: result = {"result" : "failed"} @@ -653,7 +674,7 @@ def apply_receiver_settings(json_msg): print(json_msg) rtkbaseconfig.update_setting("main", "com_port", json_msg.get("port").strip("/dev/"), write_file=False) rtkbaseconfig.update_setting("main", "com_port_settings", json_msg.get("port_speed") + ':8:n:1', write_file=False) - rtkbaseconfig.update_setting("main", "receiver", json_msg.get("gnss_type"), write_file=False) + rtkbaseconfig.update_setting("main", "receiver", json_msg.get("gnss_type") + '_' + json_msg.get("model"), write_file=False) rtkbaseconfig.update_setting("main", "receiver_firmware", json_msg.get("firmware"), write_file=True) socketio.emit("gnss_settings_saved", json.dumps(json_msg), namespace="/test") @@ -900,7 +921,6 @@ def getServicesStatus(emit_pingback=True): services_status.append({key:service[key] for key in service if key != 'unit'}) services_status = repaint_services_button(services_status) - #print(services_status) if emit_pingback: socketio.emit("services status", json.dumps(services_status), namespace="/test") return services_status @@ -924,6 +944,11 @@ def switchService(json_msg): print("Trying to stop service {}".format(service["name"])) service["unit"].stop() + # When the service is in failed state and we try to restart the service from the web UI during + # the StartLimitIntervalSec, the service status doesn't change (stay failed off), but the button switch to on + # I think I need to find another way to manage this case + #getServicesStatus(emit_pingback = True) + except Exception as e: print(e) # finally not needed anymore since the service status is refreshed continuously @@ -1009,8 +1034,6 @@ def arg_parse(): #check if authentification is required if not rtkbaseconfig.get_web_authentification(): app.config["LOGIN_DISABLED"] = True - #get data path - app.config["DOWNLOAD_FOLDER"] = rtkbaseconfig.get("local_storage", "datadir").strip("'") #load services status managed with systemd services_list = load_units(services_list) #Update standard user in settings.conf diff --git a/web_app/static/lib/bootstrap-table-1.21.1.min.css b/web_app/static/lib/bootstrap-table-1.21.1.min.css deleted file mode 100644 index 9f70dce8..00000000 --- a/web_app/static/lib/bootstrap-table-1.21.1.min.css +++ /dev/null @@ -1,10 +0,0 @@ -/** - * bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation) - * - * @version v1.21.1 - * @homepage https://bootstrap-table.com - * @author wenzhixin (http://wenzhixin.net.cn/) - * @license MIT - */ - -.bootstrap-table .fixed-table-toolbar::after{content:"";display:block;clear:both}.bootstrap-table .fixed-table-toolbar .bs-bars,.bootstrap-table .fixed-table-toolbar .columns,.bootstrap-table .fixed-table-toolbar .search{position:relative;margin-top:10px;margin-bottom:10px}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group{display:inline-block;margin-left:-1px!important}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group>.btn{border-radius:0}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group:first-child>.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group:last-child>.btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.bootstrap-table .fixed-table-toolbar .columns .dropdown-menu{text-align:left;max-height:300px;overflow:auto;-ms-overflow-style:scrollbar;z-index:1001}.bootstrap-table .fixed-table-toolbar .columns label{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.4286}.bootstrap-table .fixed-table-toolbar .columns-left{margin-right:5px}.bootstrap-table .fixed-table-toolbar .columns-right{margin-left:5px}.bootstrap-table .fixed-table-toolbar .pull-right .dropdown-menu{right:0;left:auto}.bootstrap-table .fixed-table-container{position:relative;clear:both}.bootstrap-table .fixed-table-container .table{width:100%;margin-bottom:0!important}.bootstrap-table .fixed-table-container .table td,.bootstrap-table .fixed-table-container .table th{vertical-align:middle;box-sizing:border-box}.bootstrap-table .fixed-table-container .table thead th{vertical-align:bottom;padding:0;margin:0}.bootstrap-table .fixed-table-container .table thead th:focus{outline:0 solid transparent}.bootstrap-table .fixed-table-container .table thead th.detail{width:30px}.bootstrap-table .fixed-table-container .table thead th .th-inner{padding:.75rem;vertical-align:bottom;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bootstrap-table .fixed-table-container .table thead th .sortable{cursor:pointer;background-position:right;background-repeat:no-repeat;padding-right:30px!important}.bootstrap-table .fixed-table-container .table thead th .sortable.sortable-center{padding-left:20px!important;padding-right:20px!important}.bootstrap-table .fixed-table-container .table thead th .both{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC")}.bootstrap-table .fixed-table-container .table thead th .asc{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==")}.bootstrap-table .fixed-table-container .table thead th .desc{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= ")}.bootstrap-table .fixed-table-container .table tbody tr.selected td{background-color:rgba(0,0,0,.075)}.bootstrap-table .fixed-table-container .table tbody tr.no-records-found td{text-align:center}.bootstrap-table .fixed-table-container .table tbody tr .card-view{display:flex}.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-title{font-weight:700;display:inline-block;min-width:30%;width:auto!important;text-align:left!important}.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-value{width:100%!important;text-align:left!important}.bootstrap-table .fixed-table-container .table .bs-checkbox{text-align:center}.bootstrap-table .fixed-table-container .table .bs-checkbox label{margin-bottom:0}.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type=checkbox],.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type=radio]{margin:0 auto!important}.bootstrap-table .fixed-table-container .table.table-sm .th-inner{padding:.3rem}.bootstrap-table .fixed-table-container.fixed-height:not(.has-footer){border-bottom:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height.has-card-view{border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height .fixed-table-border{border-left:1px solid #dee2e6;border-right:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height .table thead th{border-bottom:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height .table-dark thead th{border-bottom:1px solid #32383e}.bootstrap-table .fixed-table-container .fixed-table-header{overflow:hidden}.bootstrap-table .fixed-table-container .fixed-table-body{overflow-x:auto;overflow-y:auto;height:100%}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading{align-items:center;background:#fff;display:flex;justify-content:center;position:absolute;bottom:0;width:100%;max-width:100%;z-index:1000;transition:visibility 0s,opacity .15s ease-in-out;opacity:0;visibility:hidden}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.open{visibility:visible;opacity:1}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap{align-items:baseline;display:flex;justify-content:center}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .loading-text{margin-right:6px}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap{align-items:center;display:flex;justify-content:center}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::before{content:"";animation-duration:1.5s;animation-iteration-count:infinite;animation-name:loading;background:#212529;border-radius:50%;display:block;height:5px;margin:0 4px;opacity:0;width:5px}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot{animation-delay:.3s}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after{animation-delay:.6s}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark{background:#212529}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-dot,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::after,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::before{background:#fff}.bootstrap-table .fixed-table-container .fixed-table-footer{overflow:hidden}.bootstrap-table .fixed-table-pagination::after{content:"";display:block;clear:both}.bootstrap-table .fixed-table-pagination>.pagination,.bootstrap-table .fixed-table-pagination>.pagination-detail{margin-top:10px;margin-bottom:10px}.bootstrap-table .fixed-table-pagination>.pagination-detail .pagination-info{line-height:34px;margin-right:5px}.bootstrap-table .fixed-table-pagination>.pagination-detail .page-list{display:inline-block}.bootstrap-table .fixed-table-pagination>.pagination-detail .page-list .btn-group{position:relative;display:inline-block;vertical-align:middle}.bootstrap-table .fixed-table-pagination>.pagination-detail .page-list .btn-group .dropdown-menu{margin-bottom:0}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination{margin:0}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.page-intermediate a{color:#c8c8c8}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.page-intermediate a::before{content:"\2B05"}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.page-intermediate a::after{content:"\27A1"}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.disabled a{pointer-events:none;cursor:default}.bootstrap-table.fullscreen{position:fixed;top:0;left:0;z-index:1050;width:100%!important;background:#fff;height:calc(100vh);overflow-y:scroll}.bootstrap-table.bootstrap4 .pagination-lg .page-link,.bootstrap-table.bootstrap5 .pagination-lg .page-link{padding:.5rem 1rem}.bootstrap-table.bootstrap5 .float-left{float:left}.bootstrap-table.bootstrap5 .float-right{float:right}div.fixed-table-scroll-inner{width:100%;height:200px}div.fixed-table-scroll-outer{top:0;left:0;visibility:hidden;width:200px;height:150px;overflow:hidden}@keyframes loading{0%{opacity:0}50%{opacity:1}to{opacity:0}} \ No newline at end of file diff --git a/web_app/static/lib/bootstrap-table-1.21.1.min.js b/web_app/static/lib/bootstrap-table-1.21.1.min.js deleted file mode 100644 index bb53d31d..00000000 --- a/web_app/static/lib/bootstrap-table-1.21.1.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation) - * - * @version v1.21.1 - * @homepage https://bootstrap-table.com - * @author wenzhixin (http://wenzhixin.net.cn/) - * @license MIT - */ - -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).BootstrapTable=e(t.jQuery)}(this,(function(t){"use strict";function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var i=e(t);function n(t){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){for(var i=0;it.length)&&(e=t.length);for(var i=0,n=new Array(e);i=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,r=!0,s=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return r=t.done,t},e:function(t){s=!0,a=t},f:function(){try{r||null==i.return||i.return()}finally{if(s)throw a}}}}var d="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},f=function(t){return t&&t.Math==Math&&t},p=f("object"==typeof globalThis&&globalThis)||f("object"==typeof window&&window)||f("object"==typeof self&&self)||f("object"==typeof d&&d)||function(){return this}()||Function("return this")(),g={},v=function(t){try{return!!t()}catch(t){return!0}},b=!v((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),m=!v((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),y=m,w=Function.prototype.call,S=y?w.bind(w):function(){return w.apply(w,arguments)},x={},k={}.propertyIsEnumerable,O=Object.getOwnPropertyDescriptor,C=O&&!k.call({1:2},1);x.f=C?function(t){var e=O(this,t);return!!e&&e.enumerable}:k;var T,I,P=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},A=m,$=Function.prototype,R=$.bind,E=$.call,j=A&&R.bind(E,E),F=A?function(t){return t&&j(t)}:function(t){return t&&function(){return E.apply(t,arguments)}},_=F,N=_({}.toString),D=_("".slice),V=function(t){return D(N(t),8,-1)},B=v,L=V,H=Object,M=F("".split),U=B((function(){return!H("z").propertyIsEnumerable(0)}))?function(t){return"String"==L(t)?M(t,""):H(t)}:H,z=TypeError,q=function(t){if(null==t)throw z("Can't call method on "+t);return t},W=U,G=q,K=function(t){return W(G(t))},Y=function(t){return"function"==typeof t},J=Y,X=function(t){return"object"==typeof t?null!==t:J(t)},Q=p,Z=Y,tt=function(t){return Z(t)?t:void 0},et=function(t,e){return arguments.length<2?tt(Q[t]):Q[t]&&Q[t][e]},it=F({}.isPrototypeOf),nt=et("navigator","userAgent")||"",ot=p,at=nt,rt=ot.process,st=ot.Deno,lt=rt&&rt.versions||st&&st.version,ct=lt&<.v8;ct&&(I=(T=ct.split("."))[0]>0&&T[0]<4?1:+(T[0]+T[1])),!I&&at&&(!(T=at.match(/Edge\/(\d+)/))||T[1]>=74)&&(T=at.match(/Chrome\/(\d+)/))&&(I=+T[1]);var ht=I,ut=ht,dt=v,ft=!!Object.getOwnPropertySymbols&&!dt((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&ut&&ut<41})),pt=ft&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,gt=et,vt=Y,bt=it,mt=Object,yt=pt?function(t){return"symbol"==typeof t}:function(t){var e=gt("Symbol");return vt(e)&&bt(e.prototype,mt(t))},wt=String,St=function(t){try{return wt(t)}catch(t){return"Object"}},xt=Y,kt=St,Ot=TypeError,Ct=function(t){if(xt(t))return t;throw Ot(kt(t)+" is not a function")},Tt=Ct,It=function(t,e){var i=t[e];return null==i?void 0:Tt(i)},Pt=S,At=Y,$t=X,Rt=TypeError,Et={exports:{}},jt=p,Ft=Object.defineProperty,_t=function(t,e){try{Ft(jt,t,{value:e,configurable:!0,writable:!0})}catch(i){jt[t]=e}return e},Nt=_t,Dt="__core-js_shared__",Vt=p[Dt]||Nt(Dt,{}),Bt=Vt;(Et.exports=function(t,e){return Bt[t]||(Bt[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.22.8",mode:"global",copyright:"Š 2014-2022 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.22.8/LICENSE",source:"https://github.com/zloirock/core-js"});var Lt=q,Ht=Object,Mt=function(t){return Ht(Lt(t))},Ut=Mt,zt=F({}.hasOwnProperty),qt=Object.hasOwn||function(t,e){return zt(Ut(t),e)},Wt=F,Gt=0,Kt=Math.random(),Yt=Wt(1..toString),Jt=function(t){return"Symbol("+(void 0===t?"":t)+")_"+Yt(++Gt+Kt,36)},Xt=p,Qt=Et.exports,Zt=qt,te=Jt,ee=ft,ie=pt,ne=Qt("wks"),oe=Xt.Symbol,ae=oe&&oe.for,re=ie?oe:oe&&oe.withoutSetter||te,se=function(t){if(!Zt(ne,t)||!ee&&"string"!=typeof ne[t]){var e="Symbol."+t;ee&&Zt(oe,t)?ne[t]=oe[t]:ne[t]=ie&&ae?ae(e):re(e)}return ne[t]},le=S,ce=X,he=yt,ue=It,de=function(t,e){var i,n;if("string"===e&&At(i=t.toString)&&!$t(n=Pt(i,t)))return n;if(At(i=t.valueOf)&&!$t(n=Pt(i,t)))return n;if("string"!==e&&At(i=t.toString)&&!$t(n=Pt(i,t)))return n;throw Rt("Can't convert object to primitive value")},fe=TypeError,pe=se("toPrimitive"),ge=function(t,e){if(!ce(t)||he(t))return t;var i,n=ue(t,pe);if(n){if(void 0===e&&(e="default"),i=le(n,t,e),!ce(i)||he(i))return i;throw fe("Can't convert object to primitive value")}return void 0===e&&(e="number"),de(t,e)},ve=ge,be=yt,me=function(t){var e=ve(t,"string");return be(e)?e:e+""},ye=X,we=p.document,Se=ye(we)&&ye(we.createElement),xe=function(t){return Se?we.createElement(t):{}},ke=xe,Oe=!b&&!v((function(){return 7!=Object.defineProperty(ke("div"),"a",{get:function(){return 7}}).a})),Ce=b,Te=S,Ie=x,Pe=P,Ae=K,$e=me,Re=qt,Ee=Oe,je=Object.getOwnPropertyDescriptor;g.f=Ce?je:function(t,e){if(t=Ae(t),e=$e(e),Ee)try{return je(t,e)}catch(t){}if(Re(t,e))return Pe(!Te(Ie.f,t,e),t[e])};var Fe={},_e=b&&v((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),Ne=X,De=String,Ve=TypeError,Be=function(t){if(Ne(t))return t;throw Ve(De(t)+" is not an object")},Le=b,He=Oe,Me=_e,Ue=Be,ze=me,qe=TypeError,We=Object.defineProperty,Ge=Object.getOwnPropertyDescriptor,Ke="enumerable",Ye="configurable",Je="writable";Fe.f=Le?Me?function(t,e,i){if(Ue(t),e=ze(e),Ue(i),"function"==typeof t&&"prototype"===e&&"value"in i&&Je in i&&!i.writable){var n=Ge(t,e);n&&n.writable&&(t[e]=i.value,i={configurable:Ye in i?i.configurable:n.configurable,enumerable:Ke in i?i.enumerable:n.enumerable,writable:!1})}return We(t,e,i)}:We:function(t,e,i){if(Ue(t),e=ze(e),Ue(i),He)try{return We(t,e,i)}catch(t){}if("get"in i||"set"in i)throw qe("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var Xe=Fe,Qe=P,Ze=b?function(t,e,i){return Xe.f(t,e,Qe(1,i))}:function(t,e,i){return t[e]=i,t},ti={exports:{}},ei=b,ii=qt,ni=Function.prototype,oi=ei&&Object.getOwnPropertyDescriptor,ai=ii(ni,"name"),ri={EXISTS:ai,PROPER:ai&&"something"===function(){}.name,CONFIGURABLE:ai&&(!ei||ei&&oi(ni,"name").configurable)},si=Y,li=Vt,ci=F(Function.toString);si(li.inspectSource)||(li.inspectSource=function(t){return ci(t)});var hi,ui,di,fi=li.inspectSource,pi=Y,gi=fi,vi=p.WeakMap,bi=pi(vi)&&/native code/.test(gi(vi)),mi=Et.exports,yi=Jt,wi=mi("keys"),Si=function(t){return wi[t]||(wi[t]=yi(t))},xi={},ki=bi,Oi=p,Ci=F,Ti=X,Ii=Ze,Pi=qt,Ai=Vt,$i=Si,Ri=xi,Ei="Object already initialized",ji=Oi.TypeError,Fi=Oi.WeakMap;if(ki||Ai.state){var _i=Ai.state||(Ai.state=new Fi),Ni=Ci(_i.get),Di=Ci(_i.has),Vi=Ci(_i.set);hi=function(t,e){if(Di(_i,t))throw new ji(Ei);return e.facade=t,Vi(_i,t,e),e},ui=function(t){return Ni(_i,t)||{}},di=function(t){return Di(_i,t)}}else{var Bi=$i("state");Ri[Bi]=!0,hi=function(t,e){if(Pi(t,Bi))throw new ji(Ei);return e.facade=t,Ii(t,Bi,e),e},ui=function(t){return Pi(t,Bi)?t[Bi]:{}},di=function(t){return Pi(t,Bi)}}var Li={set:hi,get:ui,has:di,enforce:function(t){return di(t)?ui(t):hi(t,{})},getterFor:function(t){return function(e){var i;if(!Ti(e)||(i=ui(e)).type!==t)throw ji("Incompatible receiver, "+t+" required");return i}}},Hi=v,Mi=Y,Ui=qt,zi=b,qi=ri.CONFIGURABLE,Wi=fi,Gi=Li.enforce,Ki=Li.get,Yi=Object.defineProperty,Ji=zi&&!Hi((function(){return 8!==Yi((function(){}),"length",{value:8}).length})),Xi=String(String).split("String"),Qi=ti.exports=function(t,e,i){"Symbol("===String(e).slice(0,7)&&(e="["+String(e).replace(/^Symbol\(([^)]*)\)/,"$1")+"]"),i&&i.getter&&(e="get "+e),i&&i.setter&&(e="set "+e),(!Ui(t,"name")||qi&&t.name!==e)&&Yi(t,"name",{value:e,configurable:!0}),Ji&&i&&Ui(i,"arity")&&t.length!==i.arity&&Yi(t,"length",{value:i.arity});try{i&&Ui(i,"constructor")&&i.constructor?zi&&Yi(t,"prototype",{writable:!1}):t.prototype&&(t.prototype=void 0)}catch(t){}var n=Gi(t);return Ui(n,"source")||(n.source=Xi.join("string"==typeof e?e:"")),t};Function.prototype.toString=Qi((function(){return Mi(this)&&Ki(this).source||Wi(this)}),"toString");var Zi=Y,tn=Ze,en=ti.exports,nn=_t,on=function(t,e,i,n){n||(n={});var o=n.enumerable,a=void 0!==n.name?n.name:e;return Zi(i)&&en(i,a,n),n.global?o?t[e]=i:nn(e,i):(n.unsafe?t[e]&&(o=!0):delete t[e],o?t[e]=i:tn(t,e,i)),t},an={},rn=Math.ceil,sn=Math.floor,ln=Math.trunc||function(t){var e=+t;return(e>0?sn:rn)(e)},cn=function(t){var e=+t;return e!=e||0===e?0:ln(e)},hn=cn,un=Math.max,dn=Math.min,fn=function(t,e){var i=hn(t);return i<0?un(i+e,0):dn(i,e)},pn=cn,gn=Math.min,vn=function(t){return t>0?gn(pn(t),9007199254740991):0},bn=vn,mn=function(t){return bn(t.length)},yn=K,wn=fn,Sn=mn,xn=function(t){return function(e,i,n){var o,a=yn(e),r=Sn(a),s=wn(n,r);if(t&&i!=i){for(;r>s;)if((o=a[s++])!=o)return!0}else for(;r>s;s++)if((t||s in a)&&a[s]===i)return t||s||0;return!t&&-1}},kn={includes:xn(!0),indexOf:xn(!1)},On=qt,Cn=K,Tn=kn.indexOf,In=xi,Pn=F([].push),An=function(t,e){var i,n=Cn(t),o=0,a=[];for(i in n)!On(In,i)&&On(n,i)&&Pn(a,i);for(;e.length>o;)On(n,i=e[o++])&&(~Tn(a,i)||Pn(a,i));return a},$n=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Rn=An,En=$n.concat("length","prototype");an.f=Object.getOwnPropertyNames||function(t){return Rn(t,En)};var jn={};jn.f=Object.getOwnPropertySymbols;var Fn=et,_n=an,Nn=jn,Dn=Be,Vn=F([].concat),Bn=Fn("Reflect","ownKeys")||function(t){var e=_n.f(Dn(t)),i=Nn.f;return i?Vn(e,i(t)):e},Ln=qt,Hn=Bn,Mn=g,Un=Fe,zn=v,qn=Y,Wn=/#|\.prototype\./,Gn=function(t,e){var i=Yn[Kn(t)];return i==Xn||i!=Jn&&(qn(e)?zn(e):!!e)},Kn=Gn.normalize=function(t){return String(t).replace(Wn,".").toLowerCase()},Yn=Gn.data={},Jn=Gn.NATIVE="N",Xn=Gn.POLYFILL="P",Qn=Gn,Zn=p,to=g.f,eo=Ze,io=on,no=_t,oo=function(t,e,i){for(var n=Hn(e),o=Un.f,a=Mn.f,r=0;ro;)for(var s,l=yo(arguments[o++]),c=a?xo(go(l),a(l)):go(l),h=c.length,u=0;h>u;)s=c[u++],ho&&!fo(r,l,s)||(i[s]=l[s]);return i}:wo,Oo=ko;ro({target:"Object",stat:!0,arity:2,forced:Object.assign!==Oo},{assign:Oo});var Co={};Co[se("toStringTag")]="z";var To="[object z]"===String(Co),Io=To,Po=Y,Ao=V,$o=se("toStringTag"),Ro=Object,Eo="Arguments"==Ao(function(){return arguments}()),jo=Io?Ao:function(t){var e,i,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=function(t,e){try{return t[e]}catch(t){}}(e=Ro(t),$o))?i:Eo?Ao(e):"Object"==(n=Ao(e))&&Po(e.callee)?"Arguments":n},Fo=jo,_o=String,No=function(t){if("Symbol"===Fo(t))throw TypeError("Cannot convert a Symbol value to a string");return _o(t)},Do="\t\n\v\f\r                 \u2028\u2029\ufeff",Vo=q,Bo=No,Lo=F("".replace),Ho="[\t\n\v\f\r                 \u2028\u2029\ufeff]",Mo=RegExp("^"+Ho+Ho+"*"),Uo=RegExp(Ho+Ho+"*$"),zo=function(t){return function(e){var i=Bo(Vo(e));return 1&t&&(i=Lo(i,Mo,"")),2&t&&(i=Lo(i,Uo,"")),i}},qo={start:zo(1),end:zo(2),trim:zo(3)},Wo=ri.PROPER,Go=v,Ko=Do,Yo=qo.trim;ro({target:"String",proto:!0,forced:function(t){return Go((function(){return!!Ko[t]()||"​…᠎"!=="​…᠎"[t]()||Wo&&Ko[t].name!==t}))}("trim")},{trim:function(){return Yo(this)}});var Jo=v,Xo=function(t,e){var i=[][t];return!!i&&Jo((function(){i.call(null,e||function(){return 1},1)}))},Qo=ro,Zo=U,ta=K,ea=Xo,ia=F([].join),na=Zo!=Object,oa=ea("join",",");Qo({target:"Array",proto:!0,forced:na||!oa},{join:function(t){return ia(ta(this),void 0===t?",":t)}});var aa=Be,ra=function(){var t=aa(this),e="";return t.hasIndices&&(e+="d"),t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e},sa=v,la=p.RegExp,ca=sa((function(){var t=la("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),ha=ca||sa((function(){return!la("a","y").sticky})),ua={BROKEN_CARET:ca||sa((function(){var t=la("^r","gy");return t.lastIndex=2,null!=t.exec("str")})),MISSED_STICKY:ha,UNSUPPORTED_Y:ca},da={},fa=b,pa=_e,ga=Fe,va=Be,ba=K,ma=co;da.f=fa&&!pa?Object.defineProperties:function(t,e){va(t);for(var i,n=ba(e),o=ma(e),a=o.length,r=0;a>r;)ga.f(t,i=o[r++],n[i]);return t};var ya,wa=et("document","documentElement"),Sa=Be,xa=da,ka=$n,Oa=xi,Ca=wa,Ta=xe,Ia=Si("IE_PROTO"),Pa=function(){},Aa=function(t){return" - + {% endblock %} \ No newline at end of file diff --git a/web_app/templates/settings.html b/web_app/templates/settings.html index 3226d8de..9690796d 100644 --- a/web_app/templates/settings.html +++ b/web_app/templates/settings.html @@ -9,7 +9,7 @@ font-style: italic; } - + {% endblock %} @@ -92,11 +92,21 @@

Services:

+ +
+ + +
+ + Empty value enable external access to the Gnss receiver from another computer. Default is 127.0.0.1 (no external access) +
+
+
- + Local tcp port
@@ -529,7 +539,7 @@

System Settings:

{{ main_settings[3].receiver }} - {{ main_settings[4].receiver_firmware }} {% if 'septentrio' in main_settings[3].receiver.lower() %} - - + - {% endif %}
@@ -789,7 +799,7 @@ {% block scripts %} {{super()}} - + {% endblock %} \ No newline at end of file diff --git a/web_app/templates/status.html b/web_app/templates/status.html index 968e7038..80590a3f 100644 --- a/web_app/templates/status.html +++ b/web_app/templates/status.html @@ -2,7 +2,7 @@ {% block styles %} {{super()}} - + {% endblock %} {% block content %} @@ -68,7 +68,7 @@ {{super()}} - +