add web server, rtsp server, other fixes
This commit is contained in:
parent
1ec4b47da6
commit
7169c6ce31
80
Makefile
80
Makefile
|
@ -7,10 +7,11 @@ DRY_RUN=false
|
|||
|
||||
# Define dependencies
|
||||
DEPENDENCIES := nano htop nload sshpass python3-pip git ninja-build pkg-config gcc g++ systemd dkms python3-all python3-all-dev libpcap-dev libsodium-dev libevent-dev python3-pip python3-pyroute2 python3-msgpack \
|
||||
python3-future python3-twisted python3-serial python3-jinja2 iw virtualenv debhelper dh-python fakeroot build-essential python3-autobahn
|
||||
python3-future python3-twisted python3-serial python3-jinja2 iw virtualenv debhelper dh-python fakeroot build-essential python3-autobahn python3-websockets node gstreamer1.0-tools gstreamer1.0-plugins-base \
|
||||
gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-rtsp libgstrtspserver-1.0-0 python3-gi
|
||||
|
||||
# Define installation targets and options
|
||||
.PHONY: enable install interactive dependencies uninstall default full-install spirilink-driver spirilink-software setup-webapp-service configure-spirilink
|
||||
.PHONY: enable install interactive dependencies uninstall default full-install spirilink-driver spirilink-software setup-webapp-service configure-spirilink install-key setup-rtsp-service
|
||||
|
||||
default: interactive install
|
||||
|
||||
|
@ -43,6 +44,8 @@ full-install:
|
|||
$(MAKE) spirilink-software
|
||||
$(MAKE) configure-spirilink
|
||||
$(MAKE) setup-webapp-service
|
||||
$(MAKE) install-key
|
||||
$(MAKE) setup-rtsp-service
|
||||
@echo "Full installation complete."
|
||||
|
||||
manual-select:
|
||||
|
@ -55,7 +58,9 @@ manual-select:
|
|||
@echo "[5] SpiriLink Software"
|
||||
@echo "[6] Configure SpiriLink"
|
||||
@echo "[7] Setup WebApp Service"
|
||||
@echo "[8] Exit"
|
||||
@echo "[8] Install gs.key"
|
||||
@echo "[9] Setup RTSP Service"
|
||||
@echo "[0] Exit"
|
||||
@read -p "Enter your choices separated by spaces (e.g., 1 2 3): " choices; \
|
||||
selected="$$choices"; \
|
||||
for choice in $$selected; do \
|
||||
|
@ -66,13 +71,25 @@ manual-select:
|
|||
if [ "$$choice" = "5" ]; then $(MAKE) spirilink-software; fi; \
|
||||
if [ "$$choice" = "6" ]; then $(MAKE) configure-spirilink; fi; \
|
||||
if [ "$$choice" = "7" ]; then $(MAKE) setup-webapp-service; fi; \
|
||||
if [ "$$choice" = "8" ]; then exit 0; fi; \
|
||||
if [ "$$choice" = "8" ]; then $(MAKE) install-key; fi; \
|
||||
if [ "$$choice" = "9" ]; then $(MAKE) setup-rtsp-service; fi; \
|
||||
if [ "$$choice" = "0" ]; then exit 0; fi; \
|
||||
done;
|
||||
|
||||
install:
|
||||
@echo "Starting installation..."
|
||||
@echo "Installation complete."
|
||||
|
||||
# Install gs.key
|
||||
.PHONY: install-key
|
||||
install-key:
|
||||
@echo "Installing gs.key"
|
||||
@if [ -f $(CURDIR)/gs.key ]; then \
|
||||
$(SUDO) cp $(CURDIR)/gs.key /etc/; \
|
||||
else \
|
||||
echo "Error: gs.key not found in deployment folder."; \
|
||||
fi;
|
||||
|
||||
# Install dependencies from the array
|
||||
.PHONY: dependencies
|
||||
dependencies:
|
||||
|
@ -127,46 +144,42 @@ configure-spirilink:
|
|||
echo "unmanaged-devices=interface-name:spir0" | $(SUDO) tee -a /etc/NetworkManager/NetworkManager.conf > /dev/null; \
|
||||
fi
|
||||
@$(SUDO) systemctl restart NetworkManager
|
||||
@echo "Configuring wifibroadcast default interface..."
|
||||
@$(SUDO) bash -c 'echo "WFB_NICS=\"spir0\"" > /etc/default/wifibroadcast'
|
||||
@echo "SpiriLink configuration complete."
|
||||
|
||||
|
||||
# Install SpiriLink software
|
||||
.PHONY: spirilink-software
|
||||
spirilink-software:
|
||||
@echo "\nInstalling SpiriLink software..."
|
||||
@if [ -d ~/tmp/spirilink ]; then \
|
||||
@echo "Installing SpiriLink software..."
|
||||
@if [ -d ~/home/spiri/spirilink ]; then \
|
||||
read -p "SpiriLink software source already exists. Reinstall? (Y/N): " reinstall; \
|
||||
if [ "$$reinstall" = "Y" ] || [ "$$reinstall" = "y" ]; then \
|
||||
cd ~/tmp/spirilink && git pull && \
|
||||
$(SUDO) make deb && $(SUDO) dpkg -i ~/tmp/spirilink/deb_dist/wfb*.deb; \
|
||||
cd ~/home/spiri/spirilink && git pull && \
|
||||
$(SUDO) ./scripts/install_gs.sh spir0; \
|
||||
$(SUDO) bash -c 'echo "WFB_NICS=\"spir0\"" > /etc/default/wifibroadcast'; \
|
||||
$(SUDO) cp ~/home/spiri/spirilink/wifibroadcast.cfg /etc/; \
|
||||
else \
|
||||
echo "Skipping SpiriLink software installation."; \
|
||||
fi; \
|
||||
else \
|
||||
git clone https://git.spirirobotics.com/aepko/SpiriLink.git ~/tmp/spirilink && \
|
||||
cd ~/tmp/spirilink && \
|
||||
$(SUDO) make deb && $(SUDO) dpkg -i ~/tmp/spirilink/deb_dist/wfb*.deb; \
|
||||
git clone https://git.spirirobotics.com/aepko/SpiriLink.git ~/home/spiri/spirilink && \
|
||||
cd ~/home/spiri/spirilink && \
|
||||
$(SUDO) ./scripts/install_gs.sh spir0; \
|
||||
$(SUDO) bash -c 'echo "WFB_NICS=\"spir0\"" > /etc/default/wifibroadcast'; \
|
||||
$(SUDO) cp ~/home/spiri/spirilink/wifibroadcast.cfg /etc/; \
|
||||
fi;
|
||||
@echo "\nSpiriLink software installed."
|
||||
@echo "SpiriLink software installed."
|
||||
|
||||
|
||||
# Set up web app service
|
||||
.PHONY: setup-webapp-service
|
||||
setup-webapp-service:
|
||||
@echo "Setting up web app service..."
|
||||
@if [ -d ~/spiri-base ]; then \
|
||||
cd ~/spiri-base && git pull || (echo "Error updating repository. Check network and repository access." && exit 1); \
|
||||
@if [ -d ~/Spiri-Base ]; then \
|
||||
cd ~/Spiri-Base && git pull || (echo "Error updating repository. Check network and repository access." && exit 1); \
|
||||
else \
|
||||
git clone https://git.spirirobotics.com/aepko/Spiri-Base.git ~/spiri-base || (echo "Error cloning repository. Check network and repository access." && exit 1); \
|
||||
cd ~/spiri-base && git sparse-checkout init --cone && git sparse-checkout set .output; \
|
||||
fi;
|
||||
@if [ -d ~/spiri-base/.output ]; then \
|
||||
$(SUDO) mkdir -p /var/www/webapp; \
|
||||
$(SUDO) cp -r ~/spiri-base/.output/* /var/www/webapp/; \
|
||||
else \
|
||||
echo "Error: .output folder not found. Ensure the repository contains the necessary files."; \
|
||||
exit 1; \
|
||||
git clone https://git.spirirobotics.com/aepko/Spiri-Base.git ~/Spiri-Base || (echo "Error cloning repository. Check network and repository access." && exit 1); \
|
||||
cd ~/Spiri-Base && git sparse-checkout init --cone && git sparse-checkout set .output; \
|
||||
fi;
|
||||
@if [ -f $(CURDIR)/webapp.service ]; then \
|
||||
$(SUDO) cp $(CURDIR)/webapp.service /etc/systemd/system/webapp.service; \
|
||||
|
@ -175,7 +188,22 @@ setup-webapp-service:
|
|||
else \
|
||||
echo "Error: webapp.service not found in deployment folder."; \
|
||||
fi;
|
||||
@echo "\nWeb app service set up and running."
|
||||
@echo "Web app service set up and running."
|
||||
|
||||
# Set up RTSP service
|
||||
.PHONY: setup-rtsp-service
|
||||
setup-rtsp-service:
|
||||
@echo "Setting up RTSP server..."
|
||||
$(SUDO) mkdir -p ~/rtsp
|
||||
$(SUDO) cp $(CURDIR)/scripts/rtsp_server.py ~/rtsp/
|
||||
@if [ -f $(CURDIR)/scripts/rtsp-server.service ]; then \
|
||||
$(SUDO) cp $(CURDIR)/scripts/rtsp-server.service /etc/systemd/system/rtsp-server.service; \
|
||||
$(SUDO) systemctl enable rtsp-server.service; \
|
||||
$(SUDO) systemctl start rtsp-server.service; \
|
||||
else \
|
||||
echo "Error: rtsp-server.service not found in scripts folder."; \
|
||||
fi;
|
||||
@echo "RTSP server set up and running."
|
||||
|
||||
# Uninstall all installed components
|
||||
.PHONY: uninstall
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ЛЗэn<EFBFBD>Єj<EFBFBD><EFBFBD><EFBFBD> љ<C2A0>Ю+м<><D0BC>И GВ_Ђ<5F>Ќ{FФ<>a<EFBFBD>ћp<D19B>tzfш<ц@НkОЕВQSz<53>ЂtЂc
|
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=RTSP Server for FPV Video
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/python3 /home/spiri/rtsp/rtsp_server.py
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
Type=simple
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env python3
|
||||
import gi
|
||||
gi.require_version('Gst', '1.0')
|
||||
gi.require_version('GstRtspServer', '1.0')
|
||||
from gi.repository import Gst, GstRtspServer, GLib
|
||||
|
||||
class CustomRTSPMediaFactory(GstRtspServer.RTSPMediaFactory):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.set_shared(True)
|
||||
|
||||
def do_create_element(self, url):
|
||||
pipeline = (
|
||||
"udpsrc port=5600 caps=\"application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H265\" ! "
|
||||
"rtph265depay ! h265parse ! rtph265pay name=pay0 pt=96"
|
||||
)
|
||||
return Gst.parse_launch(pipeline)
|
||||
|
||||
class CustomRTSPServer(GstRtspServer.RTSPServer):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
factory = CustomRTSPMediaFactory()
|
||||
mount_points = self.get_mount_points()
|
||||
mount_points.add_factory("/video", factory)
|
||||
self.attach(None)
|
||||
|
||||
def main():
|
||||
Gst.init(None)
|
||||
server = CustomRTSPServer()
|
||||
loop = GLib.MainLoop() # Updated to GLib
|
||||
print("RTSP Server running at rtsp://127.0.0.1:8554/video")
|
||||
loop.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,15 +1,15 @@
|
|||
[Unit]
|
||||
Description=SpiriBase WebApp Service
|
||||
Description=Spiri Base Node.js Application
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/var/www/webapp
|
||||
ExecStart=/usr/bin/node /var/www/webapp/.output/server/index.mjs
|
||||
Restart=on-failure
|
||||
ExecStart=/usr/bin/node /home/spiri/Spiri-Base/.output/server/index.mjs
|
||||
WorkingDirectory=/home/spiri/Spiri-Base
|
||||
Restart=always
|
||||
User=spiri
|
||||
Group=spiri
|
||||
Environment=NODE_ENV=production
|
||||
User=www-data
|
||||
Group=www-data
|
||||
Environment=PORT=80
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,135 @@
|
|||
[common]
|
||||
primary = True # Set to False if you use several wfb instances on one card. Only primary instance will set radio channel.
|
||||
log_file = None # Set to "wifibroadcast.log" to disable log to stdout
|
||||
binary_log_file = None # Machine readable log for post-processing
|
||||
# File name should have '%%s' inside for profile mapping.
|
||||
# For example: 'binlog_%%s.log'
|
||||
|
||||
set_nm_unmanaged = True # Set radio interface in 'unmanaged state' in NetworkManager
|
||||
radio_mtu = 1445 # Used for mavlink aggregation and for tunnel packets - should be less or equal to MAX_PAYLOAD_SIZE, don't change if doubt
|
||||
tunnel_agg_timeout= 0.005 # aggragate tuntap packets if less than radio_mtu but no longer than 5ms
|
||||
mavlink_agg_timeout = 0.1 # aggragate mavlink packets if less than radio_mtu but no longer than 100ms
|
||||
mavlink_err_rate = True # If true then inject RX error rate else absolute values
|
||||
|
||||
log_interval = 1000 # [ms] Default interval which wfb_rx/tx use for statistics reporting
|
||||
tx_sel_rssi_delta = 3 # [dB] hysteresis for antenna selection by RSSI
|
||||
tx_sel_counter_abs_delta = 3 # [pkt] hysteresis for antenna selection by RX packet counter
|
||||
tx_sel_counter_rel_delta = 0.1 # default is max(3 packets or 10% of packets from the best antenna)
|
||||
|
||||
tx_rcv_buf_size = 2097152 # UDP SO_RCVBUF. Set 0 to use net.core.rmem_default. Increase in case of non-cbr data stream
|
||||
# This should not be greater than net.core.rmem_max
|
||||
|
||||
wifi_channel = 161 # radio channel @5825 MHz, range: 5815-5835 MHz, width 20MHz
|
||||
# Also you can set own frequency channel for each wifi card, for example:
|
||||
# {'wlan0': 161, 'wlan1': 165}
|
||||
|
||||
wifi_region = 'BO' # Set CRDA region
|
||||
wifi_txpower = None # Leave None to use default power settings from driver.
|
||||
# There is a special value 'off' for RX only cards.
|
||||
# For 8812au set to -dBm * 100. I.e for 30dBm set to -3000
|
||||
# For 8812eu set to dBm * 100. I.e for 30dBm set to 3000
|
||||
# Also you can set own txpower for each wifi card, for example:
|
||||
# {'wlan0': -100, 'wlan1': 100, 'wlan2': 'off'}
|
||||
|
||||
|
||||
temp_measurement_interval = 10 # [s] (8812eu only) Internal RF path temp measurement.
|
||||
temp_overheat_warning = 60 # [*C] (8812eu only) Overheat warning threshold.
|
||||
|
||||
[gs]
|
||||
streams = [{'name': 'video', 'stream_rx': 0x00, 'stream_tx': None, 'service_type': 'udp_direct_rx', 'profiles': ['base', 'gs_base', 'video', 'gs_video']},
|
||||
{'name': 'mavlink', 'stream_rx': 0x10, 'stream_tx': 0x90, 'service_type': 'mavlink', 'profiles': ['base', 'gs_base', 'mavlink', 'gs_mavlink']},
|
||||
{'name': 'tunnel', 'stream_rx': 0x20, 'stream_tx': 0xa0, 'service_type': 'tunnel', 'profiles': ['base', 'gs_base', 'tunnel', 'gs_tunnel']}
|
||||
]
|
||||
|
||||
stats_port = 8003 # used by wfb-cli
|
||||
api_port = 8103 # public JSON API
|
||||
link_domain = "default"
|
||||
|
||||
###########################################################################################################################
|
||||
# Low level profiles can be used to build top level profiles via inheritance #
|
||||
# You can define any number of them and split options between them as you want - only resulting set of options has matter #
|
||||
###########################################################################################################################
|
||||
|
||||
## Low level profiles have protocol-dependant fields
|
||||
|
||||
[base]
|
||||
stream_rx = None
|
||||
stream_tx = None
|
||||
keypair = None
|
||||
mirror = False # Set to true if you want to mirror packet via all cards for redundancy. Not recommended if cards are on one frequency channel.
|
||||
|
||||
# Radio settings for TX and RX
|
||||
bandwidth = 20 # bandwidth 20 or 40 MHz
|
||||
force_vht = False # Use VHT for 20 and 40 MHz bandwidth
|
||||
|
||||
# Radiotap flags for TX:
|
||||
short_gi = False # use short GI or not
|
||||
stbc = 1 # stbc streams: 1, 2, 3 or 0 if unused
|
||||
ldpc = 1 # use LDPC FEC. Currently available only for 8812au and must be supported both on TX and RX.
|
||||
mcs_index = 1 # mcs index
|
||||
|
||||
# Packet queueing control
|
||||
use_qdisc = False # Use or bypass kernel qdisc. Set to True if you want to use traffic shaper
|
||||
fwmark = 0 # If use qdisc then set fwmark to this value for data packets and to fwmark + 1 for FEC packets
|
||||
control_port = 0 # Override in tx sections if you want to manually control wfb_tx processes via wfb_tx_cmd utility
|
||||
|
||||
[gs_base]
|
||||
keypair = 'gs.key'
|
||||
|
||||
[radio_base]
|
||||
frame_type = 'data' # Use data or rts frames
|
||||
fec_k = 1 # FEC K (For tx side. Rx will get FEC settings from session packet)
|
||||
fec_n = 2 # FEC N (For tx side. Rx will get FEC settings from session packet)
|
||||
fec_timeout = 0 # [ms], 0 to disable. If no new packets during timeout, emit one empty packet if FEC block is open
|
||||
fec_delay = 0 # [us], 0 to disable. Issue FEC packets with delay between them.
|
||||
|
||||
[video]
|
||||
frame_type = 'data' # Use data or rts frames
|
||||
fec_k = 8 # FEC K (For tx side. Rx will get FEC settings from session packet)
|
||||
fec_n = 12 # FEC N (For tx side. Rx will get FEC settings from session packet)
|
||||
fec_timeout = 0 # [ms], 0 to disable. If no new packets during timeout, emit one empty packet if FEC block is open
|
||||
fec_delay = 0 # [us], 0 to disable. Issue FEC packets with delay between them.
|
||||
|
||||
peer = None
|
||||
|
||||
[mavlink]
|
||||
log_messages = False # Log all messages to binary log for post processing
|
||||
frame_type = 'data' # Use data or rts frames
|
||||
fec_k = 1 # FEC K (For tx side. Rx will get FEC settings from session packet)
|
||||
fec_n = 2 # FEC N (For tx side. Rx will get FEC settings from session packet)
|
||||
fec_timeout = 0 # [ms], 0 to disable. If no new packets during timeout, emit one empty packet if FEC block is open
|
||||
fec_delay = 0 # [us], 0 to disable. Issue FEC packets with delay between them.
|
||||
|
||||
peer = None
|
||||
osd = None
|
||||
|
||||
inject_rssi = True # inject RADIO_STATUS packets
|
||||
mavlink_sys_id = 3 # for injected rssi packets
|
||||
mavlink_comp_id = 68 # MAV_COMP_ID_TELEMETRY_RADIO
|
||||
|
||||
call_on_arm = None # call program on arm
|
||||
call_on_disarm = None # call program on disarm
|
||||
mavlink_tcp_port = None # listen for connections from QGC or from onboard computer
|
||||
|
||||
[tunnel]
|
||||
frame_type = 'data' # Use data or rts frames
|
||||
fec_k = 1 # FEC K (For tx side. Rx will get FEC settings from session packet)
|
||||
fec_n = 2 # FEC N (For tx side. Rx will get FEC settings from session packet)
|
||||
fec_timeout = 0 # [ms], 0 to disable. If no new packets during timeout, emit one empty packet if FEC block is open
|
||||
fec_delay = 0 # [us], 0 to disable. Issue FEC packets with delay between them.
|
||||
|
||||
[gs_video]
|
||||
fwmark = 20 # traffic shaper label
|
||||
peer = 'connect://127.0.0.1:5600' # outgoing connection for video sink (GS)
|
||||
|
||||
[gs_mavlink]
|
||||
fwmark = 10 # traffic shaper label
|
||||
peer = 'connect://127.0.0.1:14550' # outgoing connection
|
||||
# peer = 'listen://0.0.0.0:14550' # incoming connection
|
||||
# osd = 'connect://127.0.0.1:14551' # mirroring mavlink packets to OSD
|
||||
|
||||
[gs_tunnel]
|
||||
fwmark = 30 # traffic shaper label
|
||||
ifname = 'gs-wfb'
|
||||
ifaddr = '10.5.0.1/24'
|
||||
default_route = False
|
Loading…
Reference in New Issue