Skip to content

Commit

Permalink
Clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
TedSjoblom committed Oct 20, 2022
1 parent 0dc1e67 commit a473dec
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 88 deletions.
130 changes: 65 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
# crowsnest-connector-udp-nmea
# Crowsnest-connector-udp-nmea

A crowsnest microservice for connecting to NMEA UDP stream
A crowsnest microservice for connecting to NMEA UDP stream GNSS data.

### How it works
## How it works

For now, this microservice jsut does the basics.
For now, this microservice just does the basics.

- Connects to UPD
- Listens on the continuous stream
- Transform these 0183 or 2000 NMEA senteces
- Wraps into a brefv message and outputs over MQTT
- Connects to UPD/Multicast stream
- Transform 0183 NMEA sentences to JSON
- Wraps into a brefv message over MQTT the RAW NMEA and JSON parsed data

### Typical setup (docker-compose)

docker-compose.udp-nmea.yml
### Typical setup: docker-compose.nmea-anavs.yml

```yaml
version: "3"
Expand All @@ -33,58 +30,61 @@ services:
To setup the development environment:
```bash
python3 -m venv venv
source ven/bin/activate
```

Install everything thats needed for development:

```bash
pip install -r requirements_dev.txt
```

To run the linters:

```bash
black main.py tests
pylint main.py
```

To run the tests:

```bash
no automatic tests yet...
```

Add breaf as submodule:
```basch
Add brefv as submodule:

```bash
git submodule add <url>


# Once the project is added to your repo, you have to init and update it.

git submodule init
git submodule update

```

Kredit to https://github.com/Knio/pynmea2

Credit to https://github.com/Knio/pynmea2

## License

Apache 2.0, see [LICENSE](./LICENSE)



## NMEA parser to brefv
## Extra Notes NMEA parser to brefv

Messages types

```bash
(Not parsed to brefv)
$GNGSA,M,1,04,06,07,09,11,16,20,,,,,,1.53,1.09,1.07,1*0F
<GSA(
mode='M', (M= Manual, A=Automatic)
mode_fix_type='1', (Fix type: 1=Not available, 2=2D, 3=3D)

sv_id01='04', sv_id02='06', sv_id03='07', sv_id04='09'
sv_id05='11', sv_id06='16', sv_id07='20', sv_id08='', sv_id09=''
sv_id10='', sv_id11='', sv_id12='',
sv_id10='', sv_id11='', sv_id12='',

pdop='1.53', (PDOP 0.5 to 99.9)
hdop='1.09', (HDOP 0.5 to 99.9)
Expand All @@ -102,37 +102,37 @@ $GNGGA,114835.60,5742.5522736,N,01156.8392494,E,5,15,1.1,5.18,M,35.78,M,,*77
lat_dir='N', (hemisphere, N or S )
lon='01156.8392494', (Longitude, the format is dddmm.mmmmmmm)
lon_dir='E', (hemisphere, E or W)
gps_qual=5, (GPS quality indicator:
0: GNSS fix not available
gps_qual=5, (GPS quality indicator:
0: GNSS fix not available
1: GNSS fix valid
4: RTK fixed ambiguities
5: RTK float ambiguities
)
num_sats='15', (Number of satellites used, Fixed length 01 for single digits)

horizontal_dil='1.1', (HDOP, XX.X Variable/fixed length 1 digit after dot, variable before)
altitude=5.18, (Altitude geoid height)
altitude_units='M', (Unit of altitude)
geo_sep='35.78',
geo_sep_units='M',
age_gps_data='',
geo_sep='35.78',
geo_sep_units='M',
age_gps_data='',
ref_station_id='')>


--------
--------
(TODO)
PASHR – Attitude Data
$PASHR,114835.60,027.23,T,-75.83,,,3.158,,4.831,1,*22
<ASHRATT(
_r='R',
_r='R',
1) timestamp=datetime.time(11, 48, 35, 600000), (UTC)
2) true_heading=27.23, (Degrees)
3) is_true_heading='T',
3) is_true_heading='T',
4) roll=-75.83, (Degrees)
5) pitch=None, (Degrees)
6) heading=None,
6) heading=None,
7) roll_accuracy=3.158, (Degrees)
8) pitch_accuracy=None,
8) pitch_accuracy=None,
9) heading_accuracy=4.831, (Degrees, standard deviation)
aiding_status=Decimal('1'), (0: No position 1: RTK float position 2: RTK fixed position)
imu_status=None)>
Expand All @@ -151,62 +151,62 @@ $GNRMC,114835.60,A,5742.5522736,N,01156.8392494,E,,,191022,,W,D,V*61
spd_over_grnd=None,
true_course=None,
datestamp=datetime.date(2022, 10, 19),
mag_variation='',
mag_var_dir='W')
mag_variation='',
mag_var_dir='W')
data=['D', 'V']>

--------
VTG – Course over ground and ground speed
$GNVTG,,T,,M,,N,,K,A*3D
<VTG(
true_track=None,
true_track_sym='T',
mag_track=None,
mag_track_sym='M',
spd_over_grnd_kts=None,
spd_over_grnd_kts_sym='N',
spd_over_grnd_kmph=None,
spd_over_grnd_kmph_sym='K',
true_track=None,
true_track_sym='T',
mag_track=None,
mag_track_sym='M',
spd_over_grnd_kts=None,
spd_over_grnd_kts_sym='N',
spd_over_grnd_kmph=None,
spd_over_grnd_kmph_sym='K',
faa_mode='A')>


--------
PASHR – Attitude Data
$PASHR,114835.60,027.23,T,-75.83,,,3.158,,4.831,1,*22
<ASHRATT(
_r='R',
timestamp=datetime.time(11, 48, 35, 600000),
true_heading=27.23,
_r='R',
timestamp=datetime.time(11, 48, 35, 600000),
true_heading=27.23,
is_true_heading='T',
roll=-75.83, pitch=None,
heading=None,
roll_accuracy=3.158,
pitch_accuracy=None,
heading_accuracy=4.831,
aiding_status=Decimal('1'),
roll=-75.83, pitch=None,
heading=None,
roll_accuracy=3.158,
pitch_accuracy=None,
heading_accuracy=4.831,
aiding_status=Decimal('1'),
imu_status=None)>


--------
$GNZDA,114835.60,19,10,2022,,*7F
<ZDA(
timestamp=datetime.time(11, 48, 35, 600000),
day=19,
month=10,
year=2022,
local_zone=None,
timestamp=datetime.time(11, 48, 35, 600000),
day=19,
month=10,
year=2022,
local_zone=None,
local_zone_minutes=None)>

--------
$GNGST,114835.60,,,,,0.264,0.170,0.334*47
<GST(
timestamp=datetime.time(11, 48, 35, 600000),
rms=None,
std_dev_major=None,
std_dev_minor=None,
timestamp=datetime.time(11, 48, 35, 600000),
rms=None,
std_dev_major=None,
std_dev_minor=None,
orientation=None,
std_dev_latitude=0.264,
std_dev_longitude=0.17,
std_dev_latitude=0.264,
std_dev_longitude=0.17,
std_dev_altitude=0.334)>

--------
Expand All @@ -218,4 +218,4 @@ $GNTHS,27.23,V*3A
$GNROT,0.0,V*38
<ROT(rate_of_turn='0.0', status='V')>

```
```
29 changes: 14 additions & 15 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from paho.mqtt.client import Client as MQTT

from brefv_spec.envelope import Envelope
from brefv_spec.messages.position import Position

# Reading config from environment variables
env = Env()
Expand Down Expand Up @@ -43,10 +42,8 @@
# Create mqtt client and configure it according to configuration
mq = MQTT(client_id=MQTT_CLIENT_ID, transport=MQTT_TRANSPORT)
mq.username_pw_set(MQTT_USER, MQTT_PASSWORD)

if MQTT_TLS:
mq.tls_set()

mq.enable_logger(LOGGER)


Expand Down Expand Up @@ -76,17 +73,16 @@ def to_mqtt(payload: Any, topic: str):

def listen_multicast_nmea_0183(source):
"""Multicast input"""

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

sock.bind((MCAST_GRP, MCAST_PORT))
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)

sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

while True:
source.emit(sock.recv(10240))
# LOGGER.debug(sock.recv(10240))
LOGGER.debug(sock.recv(10240))


def pars_nmea(nmea_msg_bytes):
Expand All @@ -111,14 +107,15 @@ def pars_nmea(nmea_msg_bytes):
try:
nmea_type_msg = nmea_str.split(",")[0].replace("$", "")


if nmea_type_msg == "PASHR":
PASHR_items = nmea_str.split(",")

for idx, item in enumerate(PASHR_items):
try:
PASHR_items[idx] = float(PASHR_items[idx])
PASHR_items[idx] = float(item)
except:
pass
pass # Ignoring numbers

PASHR = {
"heading": PASHR_items[2],
Expand All @@ -131,19 +128,20 @@ def pars_nmea(nmea_msg_bytes):

msg = pynmea2.parse(nmea_str)


if msg.sentence_type == "GGA":

# Longitude +(North) or -(South)
longitude = float(msg.lon) / 100 # to dd.mmmmm
long_deg_min = ((longitude % 1)*100) /60 # Minute to degrees
long_deg_min = ((longitude % 1) * 100) / 60 # Minute to degrees
longitude = int(longitude) + long_deg_min

if msg.lon_dir == "S":
longitude = -longitude

# Latitude +(East) or -(West)
latitude = float(msg.lat) / 100 # to degrees
lat_deg_min = ((latitude % 1)*100) /60 # Minute to degrees
lat_deg_min = ((latitude % 1) * 100) / 60 # Minute to degrees
latitude = int(latitude) + lat_deg_min
if msg.lon_dir == "W":
latitude = -latitude
Expand All @@ -157,6 +155,7 @@ def pars_nmea(nmea_msg_bytes):
}
nmea_parameters.update(GGA)


elif msg.sentence_type == "RMC":

msg_UTC = msg.datestamp.isoformat() + " " + msg.timestamp.isoformat()
Expand All @@ -168,19 +167,22 @@ def pars_nmea(nmea_msg_bytes):
}
nmea_parameters.update(RMC)


elif msg.sentence_type == "VTG":
VTG = {
"sog": msg.spd_over_grnd_kts,
"cog": msg.true_track,
}
nmea_parameters.update(VTG)


elif msg.sentence_type == "ROT":
ROT = {
"rot": float(msg.rate_of_turn),
}
nmea_parameters.update(ROT)


elif msg.sentence_type == "GST":
GST = {
"std_dev_altitude": msg.std_dev_altitude,
Expand All @@ -193,14 +195,13 @@ def pars_nmea(nmea_msg_bytes):
LOGGER.error(e)

LOGGER.info(nmea_parameters)

return nmea_parameters


def to_brefv_nmea(GNSS_parameters):
"""NMEA in message to brefv envelope"""

# TODO: Create brefv format
# TODO: Modify to brefv format

envelope = Envelope(
sent_at=datetime.now(timezone.utc).isoformat(),
Expand All @@ -214,8 +215,6 @@ def to_brefv_nmea(GNSS_parameters):

# Build pipeline
LOGGER.info("Building pipeline...")
LOGGER.info("Connecting to multicast...")

source = Stream()

# RAW MQTT stream
Expand Down
8 changes: 0 additions & 8 deletions test.py

This file was deleted.

0 comments on commit a473dec

Please sign in to comment.