Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect rtkbase tool #456

Merged
merged 8 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ settings.conf
test.sh
test.conf
*.FCStd1
/venv*/*
**/venv*/*
**/build/
4 changes: 4 additions & 0 deletions tools/find_rtkbase/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Changelog

## [0.1] - not released
- First release
Binary file added tools/find_rtkbase/dist/find_rtkbase
Binary file not shown.
Binary file added tools/find_rtkbase/dist/find_rtkbase.exe
Binary file not shown.
163 changes: 163 additions & 0 deletions tools/find_rtkbase/find_rtkbase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#! /usr/bin/env python3

import tkinter as tk
import tkinter.font
import tkinter.ttk as ttk
import webbrowser
import threading
import scan_network
import tkinter as tk
from tkinter import ttk
import logging
import argparse
import os
logging.basicConfig(format='%(levelname)s: %(message)s')
log = logging.getLogger(__name__)
log.setLevel('ERROR')


class MyApp:
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.geometry("400x200")
master.columnconfigure(0, weight=1)
master.rowconfigure(0, weight=1)
default_font = tkinter.font.nametofont("TkDefaultFont")
default_font.configure(size=12)
self._create_gui()
self.available_base = None
if os.name == 'nt':
log.debug('"False" scan to pop up the windows firewall window')
scan_network.zeroconf_scan('RTKBase Web Server', '_http._tcp.local.', timeout=0)

def _create_gui(self):

#Scanning and results frame
self.top_frame = ttk.Frame(self.master, padding="10")
self.top_frame.grid(row=0, column=0, sticky="nsew")
self.top_frame.columnconfigure(0, weight=1)
self.top_frame.rowconfigure(97, weight=1)
self.intro_label = ttk.Label(self.top_frame, text="Click 'Find' to search for RTKBase")
self.intro_label.grid(column=0, row=0, pady=10)
self.scanninglabel = ttk.Label(self.top_frame, text="Searching....")
self.scanninglabel.grid(column=0, row=0, pady=10)
self.scanninglabel.grid_remove()
self.progress_bar = ttk.Progressbar(self.top_frame,mode='indeterminate')
self.progress_bar.grid(column=2, columnspan=2, row=0, pady=10)
self.progress_bar.grid_remove()
self.nobase_label = ttk.Label(self.top_frame, text="No base station detected")
self.nobase_label.grid(column=0, row=0, columnspan=2, pady=10)
self.nobase_label.grid_remove()
self.error_label = ttk.Label(self.top_frame, text="Error")
self.error_label.grid(column=0, row=0, columnspan=2, pady=10)
self.error_label.grid_remove()


# Scan/Quit Frame
self.bottom_frame = ttk.Frame(self.top_frame)
self.bottom_frame.grid(column=0, row=99, columnspan=4, sticky="ew")
self.bottom_frame.columnconfigure(0, weight=1)
self.bottom_frame.columnconfigure(1, weight=1)
self.scanButton = ttk.Button(self.bottom_frame, text="Find", command=self.scan_network)
self.scanButton.grid(column=0, row=0, padx=(0, 5), sticky="e")
self.quitButton = ttk.Button(self.bottom_frame, text="Quit", command=self.master.quit)
self.quitButton.grid(column=1, row=0, padx=(5, 0), sticky="w")

# info Frame
""" self.info_frame = ttk.Frame(self.top_frame)
self.info_frame.grid(column=3, row=99, sticky="ew")
self.version_label = ttk.Label(self.info_frame, text="v0.1")
self.version_label.grid(sticky="e") """

def scan_network(self):

#Cleaning GUI
try:
self.intro_label.grid_remove()
self.error_label.grid_remove()
for label in self.base_labels_list:
label.destroy()
for button in self.base_buttons_list:
button.destroy()
except AttributeError:
pass
self.nobase_label.grid_remove()
self.scanButton.config(state=tk.DISABLED)
self.scanninglabel.grid()
self.progress_bar.grid()
self.progress_bar.start()

#Launch scan
thread = threading.Thread(target=self._scan_thread)
thread.start()

def _scan_thread(self):
log.debug(f"Start Scanning (ports {self.ports})")
try:
self.available_base = scan_network.main(self.ports, self.allscan)
#self.available_base = [{'ip': '192.168.1.23', 'port' : 80, 'fqdn' : 'rtkbase.home'},
# {'ip': '192.168.1.124', 'port' : 80, 'fqdn' : 'localhost'},
# {'ip': '192.168.1.199', 'port' : 443, 'fqdn' : 'basegnss'} ]
#self.available_base = [{'ip': '192.168.1.123', 'port' : 80, 'fqdn' : 'localhost'},]
except Exception as e:
log.debug(f"Error during network scan: {e}")
self.progress_bar.stop()
self.progress_bar.grid_remove()
self.scanninglabel.grid_remove()
self.error_label.grid()
self.scanButton.config(state=tk.NORMAL)
return

log.debug("Scan terminated")
self._after_scan_thread()

def _after_scan_thread(self):
log.debug(f"available_base: {self.available_base}")
self.scanninglabel.grid_remove()
self.progress_bar.stop()
self.progress_bar.grid_remove()
self.base_labels_list = ["base" + str(i) + "Label" for i, j in enumerate(self.available_base)]
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')):
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].grid(column=3, row=i)
else:
self.nobase_label.grid()
self.scanButton.config(state=tk.NORMAL)

def launch_browser(self, ip, port):
print('{} port {}'.format(ip, port))
webbrowser.open(f"http://{ip}:{port}")

def arg_parse():
""" Parse the command line you use to launch the script """

parser= argparse.ArgumentParser(prog='Scan for RTKBase', description="A tool to scan network and find Rtkbase Gnss base station")
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("-p", "--ports", nargs='+', help="Port(s) used to find the web server. Default value is 80 and 443", default=[80, 443], type=int)
parser.add_argument("-a", "--allscan", help="force scan with mDns AND ip range", action='store_true')
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

if __name__ == "__main__":
args = arg_parse()
if args.debug:
log.setLevel('DEBUG')
log.debug(f"Arguments: {args}")
root = tk.Tk()
iconpath = os.path.join(os.path.dirname(__file__), 'rtkbase_icon.png')
icon = tk.PhotoImage(file=iconpath)
root.wm_iconphoto(False, icon)
app = MyApp(root, args.ports, args.allscan)
root.mainloop()
47 changes: 47 additions & 0 deletions tools/find_rtkbase/find_rtkbase_console.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# -*- mode: python ; coding: utf-8 -*-


block_cipher = None


a = Analysis(
['find_rtkbase.py'],
pathex=[],
binaries=[],
datas=[('rtkbase_icon.png', '.') ],
hiddenimports=[
'zeroconf._utils.ipaddress', # and potentially others in .venv\Lib\site-packages\zeroconf\_utils, but that seems to pull in every pyd file
'zeroconf._handlers.answers', # and potentially others in .venv\Lib\site-packages\zeroconf\_handlers, but that seems to pull in every pyd file
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=["IPython"],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='find_rtkbase',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
47 changes: 47 additions & 0 deletions tools/find_rtkbase/find_rtkbase_noconsole.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# -*- mode: python ; coding: utf-8 -*-


block_cipher = None


a = Analysis(
['find_rtkbase.py'],
pathex=[],
binaries=[],
datas=[('rtkbase_icon.png', '.') ],
hiddenimports=[
'zeroconf._utils.ipaddress', # and potentially others in .venv\Lib\site-packages\zeroconf\_utils, but that seems to pull in every pyd file
'zeroconf._handlers.answers', # and potentially others in .venv\Lib\site-packages\zeroconf\_handlers, but that seems to pull in every pyd file
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=["IPython"],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='find_rtkbase',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
Binary file added tools/find_rtkbase/find_rtkbase_screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions tools/find_rtkbase/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# find_rtkbase

This is a gui app to find RTKBase base station on the local network.
Executable files are available in the /dist directory for Windows x64 and Gnu/Linux x86_64.

![find_rtkbase gui screenshot](find_rtkbase_screenshot.png)
## building binary/executable from source:

- without console option:

```pyinstaller find_rtkbase_noconsole.spec```

- with console option (find_rtkbase --help):

```pyinstaller find_rtkbase_console.spec```

Binary file added tools/find_rtkbase/rtkbase_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading