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

Code refactoring and typing #2

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ MOTOTRBO zone file generator from BrandMeister repeater list. It makes use of [B
## Installation

* `git clone https://github.com/yl3im/motobm.git`
* `pip install -r requirements.txt` as root or `pip install -r requirements.txt --user` as ordinary user.
* `python -m venv ./motobm-env`
* `source ./motobm-env/bin/activate`
* `python -m pip install -r requirements.txt`

## Usage

```
usage: ./zone.py [-h] [-f] -n NAME -b {vhf,uhf} -t {mcc,qth,gps} [-m MCC] [-q QTH] [-r RADIUS] [-lat LAT] [-lng LNG] [-p] [-6] [-zc ZONE_CAPACITY]
usage: python zone.py [-h] [-f] -n NAME -b {vhf,uhf} -t {mcc,qth,gps} [-m MCC] [-q QTH] [-r RADIUS] [-lat LAT] [-lng LNG] [-p] [-6] [-zc ZONE_CAPACITY]

Generate MOTOTRBO zone files from BrandMeister.

Expand All @@ -35,29 +37,29 @@ optional arguments:

## Examples

`./zone.py -n 'Germany' -b vhf -t mcc -m 262 -6 -zc 16`
`python zone.py -n 'Germany' -b vhf -t mcc -m 262 -6 -zc 16`

will create XML zone file(s) with all German repeaters for 2m band with 6 digit ID (real repeaters, not just hotspots), split to 16 channels per one zone.

`./zone.py -n 'Lithuania' -b uhf -t mcc -m LT -6`
`python zone.py -n 'Lithuania' -b uhf -t mcc -m LT -6`

will create XML zone file(s) with all Lithuanian repeaters for 70 band with 6 digit ID (real repeaters, not just hotspots).

`./zone.py -n 'Paris' -b uhf -t qth -q JN18EU -r 150 -6`
`python zone.py -n 'Paris' -b uhf -t qth -q JN18EU -r 150 -6`

will create XML zone file(s) with all repeaters for 70cm band with 6 digit ID (real repeaters, not just hotspots) 150 kilometers around Paris.

`./zone.py -n 'Stockholm' -b uhf -t gps -lat 59.225 -lon 18.250 -6`
`python zone.py -n 'Stockholm' -b uhf -t gps -lat 59.225 -lon 18.250 -6`

will create XML zone file(s) with all repeaters for 70cm band with 6 digit ID (real repeaters, not just hotspots) 100 kilometers around Stockholm.

In case your latitude and/or longitude have negative values, please refer them this way to avoid errors:

`./zone.py -n 'Minneapolis' -b uhf -t gps -lat 44.9570 -lon " -93.2780" -6`
`python zone.py -n 'Minneapolis' -b uhf -t gps -lat 44.9570 -lon " -93.2780" -6`

or

`./zone.py -n 'Minneapolis' -b uhf -t gps -lat 44.9570 -lon=-93.2780 -6`
`python zone.py -n 'Minneapolis' -b uhf -t gps -lat 44.9570 -lon=-93.2780 -6`

While creating zone file(s) the script will also output the list of found repeaters like this:

Expand Down
14 changes: 7 additions & 7 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
geographiclib
geopy
maidenhead
mobile-codes
requests
tabulate
urllib3
geographiclib~=2.0
geopy~=2.4.1
maidenhead~=1.7.0
mobile-codes~=0.7
requests~=2.32.3
tabulate~=0.9.0
urllib3~=2.2.2
75 changes: 75 additions & 0 deletions templatex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
ZONE = '''<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<config>
<category name="Zone">
<set name="Zone" alias="{zone_alias}" key="NORMAL">
<collection name="ZoneItems">
{channels}
</collection>
<field name="ZP_ZONEALIAS">{zone_alias}</field>
<field name="ZP_ZONETYPE" Name="Normal">NORMAL</field>
<field name="ZP_ZVFNLITEM" Name="None">NONE</field>
<field name="Comments"></field>
</set>
</category>
</config>
'''

CONVENTIONAL_PERSONALITY_RX_TX = '''
<set name="ConventionalPersonality" alias="{ch_alias}" key="DGTLCONV6PT25">
<field name="CP_PERSTYPE" Name="Digital">DGTLCONV6PT25</field>
<field name="CP_SLTASSGMNT" Name="2">SLOT2</field>
<field name="CP_COLORCODE">{ch_cc}</field>
<field name="CP_TXFREQ">{ch_rx}</field>
<field name="CP_RXFREQ">{ch_tx}</field>
<field name="CP_EMACKALERTEN">True</field>
<field name="CP_CNVPERSALIAS">{ch_alias}</field>
<field name="CP_TXINHXPLEN" Name="Color Code Free">MTCHCLRCD</field>
<field name="CP_MLTSTPSNLTIND">True</field>
<field name="CP_GPSRVRTPERSIT" Name="Selected">SELECTED</field>
<field name="CP_OVCMDECODEENABLE">True</field>
<field name="CP_TXCOMPUDPIPHEADEN" Name="DMR Standard">DMR_UDP_HEADER</field>
<field name="CP_LOCATIONDATADELIVERYMODE" Name="Follow Data Call Confirmed">FOLLOW_CALL_DATA_SETTING</field>
<field name="CP_MYCALLADCRTR" Name="Follow Admit Criteria">FOLLOW_ADMIT_CRITERIA</field>
<field name="CP_TEXTMESSAGETYPE" Name="Advantage">TMS</field>
<field name="CP_TRANSMITINTERRUPTTYPE" Name="Advantage">PROPRIETARY</field>
</set>
'''

CONVENTIONAL_PERSONALITY = '''
<set name="ConventionalPersonality" alias="{ch_alias} TS1" key="DGTLCONV6PT25">
<field name="CP_PERSTYPE" Name="Digital">DGTLCONV6PT25</field>
<field name="CP_SLTASSGMNT" Name="1">SLOT1</field>
<field name="CP_COLORCODE">{ch_cc}</field>
<field name="CP_TXFREQ">{ch_rx}</field>
<field name="CP_RXFREQ">{ch_tx}</field>
<field name="CP_EMACKALERTEN">True</field>
<field name="CP_CNVPERSALIAS">{ch_alias} TS1</field>
<field name="CP_TXINHXPLEN" Name="Color Code Free">MTCHCLRCD</field>
<field name="CP_MLTSTPSNLTIND">True</field>
<field name="CP_GPSRVRTPERSIT" Name="Selected">SELECTED</field>
<field name="CP_OVCMDECODEENABLE">True</field>
<field name="CP_TXCOMPUDPIPHEADEN" Name="DMR Standard">DMR_UDP_HEADER</field>
<field name="CP_LOCATIONDATADELIVERYMODE" Name="Follow Data Call Confirmed">FOLLOW_CALL_DATA_SETTING</field>
<field name="CP_MYCALLADCRTR" Name="Follow Admit Criteria">FOLLOW_ADMIT_CRITERIA</field>
<field name="CP_TEXTMESSAGETYPE" Name="Advantage">TMS</field>
<field name="CP_TRANSMITINTERRUPTTYPE" Name="Advantage">PROPRIETARY</field>
</set>
<set name="ConventionalPersonality" alias="{ch_alias} TS2" key="DGTLCONV6PT25">
<field name="CP_PERSTYPE" Name="Digital">DGTLCONV6PT25</field>
<field name="CP_SLTASSGMNT" Name="2">SLOT2</field>
<field name="CP_COLORCODE">{ch_cc}</field>
<field name="CP_TXFREQ">{ch_rx}</field>
<field name="CP_RXFREQ">{ch_tx}</field>
<field name="CP_EMACKALERTEN">True</field>
<field name="CP_CNVPERSALIAS">{ch_alias} TS2</field>
<field name="CP_TXINHXPLEN" Name="Color Code Free">MTCHCLRCD</field>
<field name="CP_MLTSTPSNLTIND">True</field>
<field name="CP_GPSRVRTPERSIT" Name="Selected">SELECTED</field>
<field name="CP_OVCMDECODEENABLE">True</field>
<field name="CP_TXCOMPUDPIPHEADEN" Name="DMR Standard">DMR_UDP_HEADER</field>
<field name="CP_LOCATIONDATADELIVERYMODE" Name="Follow Data Call Confirmed">FOLLOW_CALL_DATA_SETTING</field>
<field name="CP_MYCALLADCRTR" Name="Follow Admit Criteria">FOLLOW_ADMIT_CRITERIA</field>
<field name="CP_TEXTMESSAGETYPE" Name="Advantage">TMS</field>
<field name="CP_TRANSMITINTERRUPTTYPE" Name="Advantage">PROPRIETARY</field>
</set>
'''
30 changes: 30 additions & 0 deletions utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import typing
from os.path import exists

import geopy.distance
import requests
import urllib3


def download_file(f_path: str, url: str, overwrite: bool) -> bool:
if exists(f_path) and not overwrite:
return False

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

response = requests.get(url, verify=False)
response.raise_for_status()

with open(f_path, 'wb') as file:
file.write(response.content)

return True


def calc_distance(loc1: typing.Tuple[float, float], loc2: typing.Tuple[float, float]) -> float:
return geopy.distance.great_circle(loc1, loc2).km


def write_text_file(f_path: str, text: str) -> None:
with open(f_path, "wt") as f:
f.write(text)
Loading