code format
This commit is contained in:
parent
8d47259f78
commit
98f1545fca
38
owrx/aprs.py
38
owrx/aprs.py
@ -14,9 +14,12 @@ knotsToKilometers = 1.852
|
|||||||
feetToMeters = 0.3048
|
feetToMeters = 0.3048
|
||||||
milesToKilometers = 1.609344
|
milesToKilometers = 1.609344
|
||||||
inchesToMilimeters = 25.4
|
inchesToMilimeters = 25.4
|
||||||
|
|
||||||
|
|
||||||
def fahrenheitToCelsius(f):
|
def fahrenheitToCelsius(f):
|
||||||
return (f - 32) * 5 / 9
|
return (f - 32) * 5 / 9
|
||||||
|
|
||||||
|
|
||||||
# not sure what the correct encoding is. it seems TAPR has set utf-8 as a standard, but not everybody is following it.
|
# not sure what the correct encoding is. it seems TAPR has set utf-8 as a standard, but not everybody is following it.
|
||||||
encoding = "utf-8"
|
encoding = "utf-8"
|
||||||
|
|
||||||
@ -63,7 +66,7 @@ class Ax25Parser(object):
|
|||||||
|
|
||||||
|
|
||||||
class WeatherMapping(object):
|
class WeatherMapping(object):
|
||||||
def __init__(self, char, key, length, scale = None):
|
def __init__(self, char, key, length, scale=None):
|
||||||
self.char = char
|
self.char = char
|
||||||
self.key = key
|
self.key = key
|
||||||
self.length = length
|
self.length = length
|
||||||
@ -81,14 +84,15 @@ class WeatherMapping(object):
|
|||||||
deepApply(obj[keys[0]], ".".join(keys[1:]), v)
|
deepApply(obj[keys[0]], ".".join(keys[1:]), v)
|
||||||
else:
|
else:
|
||||||
obj[key] = v
|
obj[key] = v
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = int(input[1:1 + self.length])
|
value = int(input[1 : 1 + self.length])
|
||||||
if self.scale:
|
if self.scale:
|
||||||
value = self.scale(value)
|
value = self.scale(value)
|
||||||
deepApply(weather, self.key, value)
|
deepApply(weather, self.key, value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
remain = input[1 + self.length:]
|
remain = input[1 + self.length :]
|
||||||
return weather, remain
|
return weather, remain
|
||||||
|
|
||||||
|
|
||||||
@ -102,7 +106,7 @@ class WeatherParser(object):
|
|||||||
WeatherMapping("p", "rain.day", 3, lambda x: x / 100 * inchesToMilimeters),
|
WeatherMapping("p", "rain.day", 3, lambda x: x / 100 * inchesToMilimeters),
|
||||||
WeatherMapping("P", "rain.sincemidnight", 3, lambda x: x / 100 * inchesToMilimeters),
|
WeatherMapping("P", "rain.sincemidnight", 3, lambda x: x / 100 * inchesToMilimeters),
|
||||||
WeatherMapping("h", "humidity", 2),
|
WeatherMapping("h", "humidity", 2),
|
||||||
WeatherMapping("b", "barometricpressure", 5, lambda x: x/10),
|
WeatherMapping("b", "barometricpressure", 5, lambda x: x / 10),
|
||||||
WeatherMapping("s", "snowfall", 3, lambda x: x * 25.4),
|
WeatherMapping("s", "snowfall", 3, lambda x: x * 25.4),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -172,9 +176,7 @@ class AprsParser(object):
|
|||||||
if "type" in mapData and mapData["type"] == "thirdparty" and "data" in mapData:
|
if "type" in mapData and mapData["type"] == "thirdparty" and "data" in mapData:
|
||||||
mapData = mapData["data"]
|
mapData = mapData["data"]
|
||||||
if "lat" in mapData and "lon" in mapData:
|
if "lat" in mapData and "lon" in mapData:
|
||||||
loc = LatLngLocation(
|
loc = LatLngLocation(mapData["lat"], mapData["lon"], mapData["comment"] if "comment" in mapData else None)
|
||||||
mapData["lat"], mapData["lon"], mapData["comment"] if "comment" in mapData else None
|
|
||||||
)
|
|
||||||
source = mapData["source"]
|
source = mapData["source"]
|
||||||
if "type" in mapData:
|
if "type" in mapData:
|
||||||
if mapData["type"] == "item":
|
if mapData["type"] == "item":
|
||||||
@ -290,7 +292,7 @@ class AprsParser(object):
|
|||||||
index = filtered[0]
|
index = filtered[0]
|
||||||
result["item"] = information[0:index]
|
result["item"] = information[0:index]
|
||||||
result["live"] = information[index] == "!"
|
result["live"] = information[index] == "!"
|
||||||
result.update(self.parseRegularAprsData(information[index + 1:]))
|
result.update(self.parseRegularAprsData(information[index + 1 :]))
|
||||||
# override type, losing information about compression
|
# override type, losing information about compression
|
||||||
result["type"] = "item"
|
result["type"] = "item"
|
||||||
return result
|
return result
|
||||||
@ -320,20 +322,17 @@ class AprsParser(object):
|
|||||||
logger.debug(matches)
|
logger.debug(matches)
|
||||||
path = matches.group(2).split(",")
|
path = matches.group(2).split(",")
|
||||||
destination = next((c.strip("*").upper() for c in path if c.endswith("*")), None)
|
destination = next((c.strip("*").upper() for c in path if c.endswith("*")), None)
|
||||||
data = self.parseAprsData({
|
data = self.parseAprsData(
|
||||||
|
{
|
||||||
"source": matches.group(1).upper(),
|
"source": matches.group(1).upper(),
|
||||||
"destination": destination,
|
"destination": destination,
|
||||||
"path": path,
|
"path": path,
|
||||||
"data": matches.group(6).encode(encoding)
|
"data": matches.group(6).encode(encoding),
|
||||||
})
|
|
||||||
return {
|
|
||||||
"type": "thirdparty",
|
|
||||||
"data": data,
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
return {"type": "thirdparty", "data": data}
|
||||||
|
|
||||||
return {
|
return {"type": "thirdparty"}
|
||||||
"type": "thirdparty",
|
|
||||||
}
|
|
||||||
|
|
||||||
def parseRegularAprsData(self, information):
|
def parseRegularAprsData(self, information):
|
||||||
if self.hasCompressedCoordinates(information):
|
if self.hasCompressedCoordinates(information):
|
||||||
@ -384,10 +383,7 @@ class AprsParser(object):
|
|||||||
weather = {}
|
weather = {}
|
||||||
if len(comment) > 6 and comment[3] == "/":
|
if len(comment) > 6 and comment[3] == "/":
|
||||||
try:
|
try:
|
||||||
weather["wind"] = {
|
weather["wind"] = {"direction": int(comment[0:3]), "speed": int(comment[4:7]) * milesToKilometers}
|
||||||
"direction": int(comment[0:3]),
|
|
||||||
"speed": int(comment[4:7]) * milesToKilometers,
|
|
||||||
}
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
comment = comment[7:]
|
comment = comment[7:]
|
||||||
|
@ -11,9 +11,7 @@ class CounterMetric(Metric):
|
|||||||
self.counter += increment
|
self.counter += increment
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
return {
|
return {"count": self.counter}
|
||||||
"count": self.counter,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class DirectMetric(Metric):
|
class DirectMetric(Metric):
|
||||||
|
@ -131,16 +131,15 @@ class ServiceHandler(object):
|
|||||||
|
|
||||||
def optimizeResampling(self, freqs, bandwidth):
|
def optimizeResampling(self, freqs, bandwidth):
|
||||||
freqs = sorted(freqs, key=lambda f: f["frequency"])
|
freqs = sorted(freqs, key=lambda f: f["frequency"])
|
||||||
distances = [{
|
distances = [
|
||||||
"frequency": freqs[i]["frequency"],
|
{"frequency": freqs[i]["frequency"], "distance": freqs[i + 1]["frequency"] - freqs[i]["frequency"]}
|
||||||
"distance": freqs[i+1]["frequency"] - freqs[i]["frequency"],
|
for i in range(0, len(freqs) - 1)
|
||||||
} for i in range(0, len(freqs)-1)]
|
]
|
||||||
|
|
||||||
distances = [d for d in distances if d["distance"] > 0]
|
distances = [d for d in distances if d["distance"] > 0]
|
||||||
|
|
||||||
distances = sorted(distances, key=lambda f: f["distance"], reverse=True)
|
distances = sorted(distances, key=lambda f: f["distance"], reverse=True)
|
||||||
|
|
||||||
|
|
||||||
def calculate_usage(num_splits):
|
def calculate_usage(num_splits):
|
||||||
splits = sorted([f["frequency"] for f in distances[0:num_splits]])
|
splits = sorted([f["frequency"] for f in distances[0:num_splits]])
|
||||||
previous = 0
|
previous = 0
|
||||||
@ -156,20 +155,11 @@ class ServiceHandler(object):
|
|||||||
return bandwidth + len(group) * (freqs[-1] - freqs[0] + 24000)
|
return bandwidth + len(group) * (freqs[-1] - freqs[0] + 24000)
|
||||||
|
|
||||||
total_bandwidth = sum([get_bandwitdh(group) for group in groups])
|
total_bandwidth = sum([get_bandwitdh(group) for group in groups])
|
||||||
return {
|
return {"num_splits": num_splits, "total_bandwidth": total_bandwidth, "groups": groups}
|
||||||
"num_splits": num_splits,
|
|
||||||
"total_bandwidth": total_bandwidth,
|
|
||||||
"groups": groups,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
usages = [calculate_usage(i) for i in range(0, len(freqs))]
|
usages = [calculate_usage(i) for i in range(0, len(freqs))]
|
||||||
# this is simulating no resampling. i haven't seen this as the best result yet
|
# this is simulating no resampling. i haven't seen this as the best result yet
|
||||||
usages += [{
|
usages += [{"num_splits": None, "total_bandwidth": bandwidth * len(freqs), "groups": [freqs]}]
|
||||||
"num_splits": None,
|
|
||||||
"total_bandwidth": bandwidth * len(freqs),
|
|
||||||
"groups": [freqs]
|
|
||||||
}]
|
|
||||||
results = sorted(usages, key=lambda f: f["total_bandwidth"])
|
results = sorted(usages, key=lambda f: f["total_bandwidth"])
|
||||||
|
|
||||||
for r in results:
|
for r in results:
|
||||||
|
@ -299,8 +299,7 @@ class Resampler(SdrSource):
|
|||||||
"nc -v 127.0.0.1 {nc_port}".format(nc_port=self.sdr.getPort()),
|
"nc -v 127.0.0.1 {nc_port}".format(nc_port=self.sdr.getPort()),
|
||||||
"csdr shift_addition_cc {shift}".format(shift=self.shift),
|
"csdr shift_addition_cc {shift}".format(shift=self.shift),
|
||||||
"csdr fir_decimate_cc {decimation} {ddc_transition_bw} HAMMING".format(
|
"csdr fir_decimate_cc {decimation} {ddc_transition_bw} HAMMING".format(
|
||||||
decimation=self.decimation,
|
decimation=self.decimation, ddc_transition_bw=self.transition_bw
|
||||||
ddc_transition_bw=self.transition_bw,
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -316,11 +315,9 @@ class Resampler(SdrSource):
|
|||||||
self.modificationLock.release()
|
self.modificationLock.release()
|
||||||
return
|
return
|
||||||
logger.debug("nmux_bufsize = %d, nmux_bufcnt = %d" % (nmux_bufsize, nmux_bufcnt))
|
logger.debug("nmux_bufsize = %d, nmux_bufcnt = %d" % (nmux_bufsize, nmux_bufcnt))
|
||||||
resampler_command += ["nmux --bufsize %d --bufcnt %d --port %d --address 127.0.0.1" % (
|
resampler_command += [
|
||||||
nmux_bufsize,
|
"nmux --bufsize %d --bufcnt %d --port %d --address 127.0.0.1" % (nmux_bufsize, nmux_bufcnt, self.port)
|
||||||
nmux_bufcnt,
|
]
|
||||||
self.port,
|
|
||||||
)]
|
|
||||||
cmd = " | ".join(resampler_command)
|
cmd = " | ".join(resampler_command)
|
||||||
logger.debug("resampler command: %s", cmd)
|
logger.debug("resampler command: %s", cmd)
|
||||||
self.process = subprocess.Popen(cmd, shell=True, preexec_fn=os.setpgrp)
|
self.process = subprocess.Popen(cmd, shell=True, preexec_fn=os.setpgrp)
|
||||||
|
@ -134,7 +134,9 @@ class WsjtChopper(threading.Thread):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
def decode(self, file):
|
def decode(self, file):
|
||||||
decoder = subprocess.Popen(self.decoder_commandline(file), stdout=subprocess.PIPE, cwd=self.tmp_dir, preexec_fn=lambda : os.nice(10))
|
decoder = subprocess.Popen(
|
||||||
|
self.decoder_commandline(file), stdout=subprocess.PIPE, cwd=self.tmp_dir, preexec_fn=lambda: os.nice(10)
|
||||||
|
)
|
||||||
while True:
|
while True:
|
||||||
line = decoder.stdout.readline()
|
line = decoder.stdout.readline()
|
||||||
if line is None or (isinstance(line, bytes) and len(line) == 0):
|
if line is None or (isinstance(line, bytes) and len(line) == 0):
|
||||||
@ -281,7 +283,6 @@ class WsjtParser(object):
|
|||||||
|
|
||||||
metric.inc()
|
metric.inc()
|
||||||
|
|
||||||
|
|
||||||
def parse_from_jt9(self, msg):
|
def parse_from_jt9(self, msg):
|
||||||
# ft8 sample
|
# ft8 sample
|
||||||
# '222100 -15 -0.0 508 ~ CQ EA7MJ IM66'
|
# '222100 -15 -0.0 508 ~ CQ EA7MJ IM66'
|
||||||
|
Loading…
Reference in New Issue
Block a user