Skip to content

Commit

Permalink
Added missing lxml dependency, updated README, fixed socket options, …
Browse files Browse the repository at this point in the history
…fixed multicast data filtering
  • Loading branch information
brian7704 committed Jun 19, 2024
1 parent c0c6411 commit 5576bca
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 31 deletions.
58 changes: 34 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,38 +30,36 @@ There is a bug in the takproto library which causes an exception in TAK Meshtast
There is a [PR](https://github.com/snstac/takproto/pull/16) that will fix the issue once it is merged. Until it is merged,
TAK Meshtastic Gateway will install takproto from the GitHub PR instead of PyPI.

On Windows, the `unishox2-py3` library fails to build from the source distribution with the command `pip install unishox2-py3`.
TAK Meshtastic Gateway will instead install [this wheel](https://github.com/brian7704/OpenTAKServer-Installer/blob/master/unishox2_py3-1.0.0-cp312-cp312-win_amd64.whl).
As a result, Python 3.12 is required when running TAK Meshtastic Gateway on Windows.

## Installation

### Linux
For installation you only need to create a Python virtual environment, activate the virtual environment, and install using pip.

Steps may differ slightly on some distros
### Linux/macOS

```bash
git clone https://github.com/brian7704/TAK_Meshtastic_Gateway.git
cd TAK_Meshtastic_Gateway
python3 -m venv venv
. ./venv/bin/activate
pip install bs4 meshtastic pubsub takproto colorlog unishox2-py3 netifaces2
The unishox2-py3 Python library requires C build tools. In Debian based distros (i.e. Ubuntu) they can be installed with
`apt install build-essential`.

```shell
python3 -m venv tak_meshtastic_gateway_venv
. ./tak_meshtastic_gateway_venv/bin/activate
pip install tak-meshtastic-gateway
```

### Windows

These instructions assume you already have git and Python installed. In a future release there will be a binary made
with PyInstaller which won't require git or Python to be installed.

```bash
git clone https://github.com/brian7704/TAK_Meshtastic_Gateway.git
cd TAK_Meshtastic_Gateway
python -m venv venv
.\venv\Scripts\activate.bat
pip install bs4 meshtastic pubsub takproto colorlog unishox2-py3 netifaces2
```powershell
python -m venv tak_meshtastic_gateway_venv
.\tak_meshtastic_gateway_venv\Scripts\activate
pip install tak-meshtastic-gateway
```

### MacOS
## Usage

TAK Meshtastic Gateway is untested on MacOS but should work fine. Try the Linux installation instructions and open
an issue to let us know if there are any problems.
When your virtual environment active, run the `tak-meshtastic-gateway` command

## Architecture

Expand All @@ -73,9 +71,21 @@ node over the LAN allows it to be mounted in a spot outside with good mesh recep

The Meshtastic node should be set to the TAK role. TAK Meshtastic Gateway will automatically change the node's long name
to the TAK client's callsign and the short name to the last four characters of the TAK client's UID. This ensures that
the callsign shows up correctly for mesh users who are only using the Meshtastic app and not a TAK client.
the callsign shows up correctly for mesh users who are only using the Meshtastic app as well as ATAK plugin users.
TAK Meshtastic Gateway will also update the Meshtastic node's location with the location of the EUD.

## ATAK Plugin Settings

For best results, use the following settings on devices using the [Meshtastic ATAK Plugin.](https://meshtastic.org/docs/software/integrations/integrations-atak-plugin/).
You can find the settings in ATAK by clicking the Settings tool -> Tool Preferences -> Specific Tool Preferences ->
Meshtastic Preferences.

- Show all Meshtastic devices: On
- Don't sshow Meshtastic devices without GPS: On
- Do not show your local Meshtastic device: On

The rest of the settings can be changed as needed.

## Usage

All arguments are optional. If an argument is not specified its default value will be used.
Expand Down Expand Up @@ -104,20 +114,20 @@ not require elevated permissions.
- WinTAK on a PC
- Meshtastic node connected to the PC via USB
- TAK Meshtastic Gateway running on the same PC
- Command: `python3 tak_meshtastic_gateway.py`
- Command: `tak_meshtastic_gateway`

### Scenario 2

- WinTAK on a PC
- Meshtastic node on the same LAN as the PC
- TAK Meshtastic Gateway running on the same PC as WinTAK
- Command: `python3 tak_meshtastic_gateway.py --mesh-ip MESHTASTIC_NODE_IP` Note: Substitute `MESHTASTIC_NODE_IP` with
- Command: `tak_meshtastic_gateway --mesh-ip MESHTASTIC_NODE_IP` Note: Substitute `MESHTASTIC_NODE_IP` with
the node's actual IP (i.e. `192.168.1.10`)

### Scenario 3

- ATAK or iTAK on a mobile device connected to a Wi-Fi network
- Meshtastic node connected to the same network
- TAK Meshtastic Gateway running on a computer or VM on the same network
- Command: `python3 tak_meshtastic_gateway.py --mesh-ip MESHTASTIC_NODE_IP --tak-client-ip TAK_CLIENT_IP` Note: Substitute
- Command: `tak_meshtastic_gateway --mesh-ip MESHTASTIC_NODE_IP --tak-client-ip TAK_CLIENT_IP` Note: Substitute
`MESHTASTIC_NODE_IP` and `TAK_CLIENT_IP` with their actual IPs (i.e. `192.168.1.10` and `192.168.1.11`)
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ python = [
{platform = "macos", version = "^3.8"}
]
beautifulsoup4 = "4.12.3"
lxml = "5.2.2"
meshtastic = "2.3.11"
pypubsub = "4.0.3"
colorlog = "6.8.2"
Expand Down
4 changes: 2 additions & 2 deletions tak_meshtastic_gateway/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# These version placeholders will be replaced later during substitution.
__version__ = "0.0.0-post.13+f653ee9"
__version_tuple__ = (0, 0, 0, "post", 13, "f653ee9")
__version__ = "0.0.0-post.14+c0c6411"
__version_tuple__ = (0, 0, 0, "post", 14, "c0c6411")
11 changes: 6 additions & 5 deletions tak_meshtastic_gateway/tak_meshtastic_gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def __init__(self, ip=None, serial_device=None, mesh_ip=None, tak_client_ip="loc
self.dm_port = dm_port
self.serial_device = serial_device
self.mesh_ip = mesh_ip
self.tak_client_ip = tak_client_ip
self.tx_interval = tx_interval
self.log_file = log_file
self.log_level = logging.DEBUG if debug else logging.INFO
Expand Down Expand Up @@ -411,23 +412,23 @@ def main(self):
if platform.system() == 'Windows':
self.chat_sock.bind((self.ip, chat_in[1]))
self.chat_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.ip))
self.chat_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(chat_in[0]) + socket.inet_aton(self.ip) + socket.inet_aton(self.ip))
self.chat_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(chat_in[0]) + socket.inet_aton(self.ip))
else:
self.chat_sock.bind(chat_in)
self.chat_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.ip))
self.chat_sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(chat_in[0]) + socket.inet_aton(self.ip) + socket.inet_aton(self.ip))
self.chat_sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(chat_in[0]) + socket.inet_aton(self.ip))

self.sa_multicast_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
self.sa_multicast_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)

if platform.system() == 'Windows':
self.sa_multicast_sock.bind((self.ip, sa_multicast_in[1]))
self.sa_multicast_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.ip))
self.sa_multicast_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(sa_multicast_in[0]) + socket.inet_aton(self.ip) + socket.inet_aton(self.ip))
self.sa_multicast_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(sa_multicast_in[0]) + socket.inet_aton(self.ip))
else:
self.sa_multicast_sock.bind(sa_multicast_in)
self.sa_multicast_sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.ip))
self.sa_multicast_sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(sa_multicast_in[0]) + socket.inet_aton(self.ip) + socket.inet_aton(self.ip))
self.sa_multicast_sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(sa_multicast_in[0]) + socket.inet_aton(self.ip))

self.dm_sock.start()

Expand All @@ -439,7 +440,7 @@ def main(self):
data, sender = s.recvfrom(4096)

# Only accept multicast data from one TAK client
if sender[0] != self.ip:
if sender[0] != self.ip and sender[0] != self.tak_client_ip:
self.logger.warning(f"Got data from {sender[0]}, ignoring")
continue
except KeyboardInterrupt:
Expand Down

0 comments on commit 5576bca

Please sign in to comment.