kopia lustrzana https://github.com/sq9atk/sr0wx
Moduł VHF-tropo
rodzic
2e7a49b2a1
commit
14032b9d94
|
@ -16,6 +16,36 @@ $slownik = array(
|
|||
|
||||
# TA TABLICA TO TYLKO PRZECHOWALNIA
|
||||
$slownik_wszystkie = array(
|
||||
/*
|
||||
*
|
||||
*
|
||||
* VHF TROPO
|
||||
*/
|
||||
array("propagacja w paśmie fał ha ef", "vhf_propagacja_w_pasmie_vhf"),
|
||||
array("deiks info senter", "vhf_dx_info_center"),
|
||||
array("uwaga", "vhf_uwaga"),
|
||||
array("warunki podwyższone", "vhf_warunki_podwyzszone"),
|
||||
|
||||
array("brak szans na łączność troposferyczną", "vhf_brak_szans_na_lacznosc_troposferyczna"),
|
||||
array("minimalne szanse na łączność troposferyczną", "vhf_minimalne_szanse_na_lacznosc_troposferyczna"),
|
||||
array("niewielkie szanse na łączność troposferyczną", "vhf_niewielkie_szanse_na_lacznosc_troposferyczna"),
|
||||
array("spore szanse na łączność troposferyczną", "vhf_spore_szanse_na_lacznosc_troposferyczna"),
|
||||
array("duże szanse na łączność troposferyczną", "vhf_duze_szanse_na_lacznosc_troposferyczna"),
|
||||
array("bardzo duże szanse na łączność troposferyczną", "vhf_bardzo_duze_szanse_na_lacznosc_troposferyczna"),
|
||||
array("wyjątkowo duże szanse na łączność troposferyczną", "vhf_wyjatkowo_duze_szanse_na_lacznosc_troposferyczna"),
|
||||
|
||||
array("najlepsze warunki w kierunku", "vhf_najlepsze_warunki_w_kierunku"),
|
||||
array("oraz", "vhf_oraz"),
|
||||
array("północnym", "vhf_n"),
|
||||
array("północno-wschodnim", "vhf_ne"),
|
||||
array("wschodnim", "vhf_e"),
|
||||
array("połódniowo-wschodnim", "vhf_se"),
|
||||
array("połódniowym", "vhf_s"),
|
||||
array("połódniowo-zachodnim", "vhf_sw"),
|
||||
array("zachodnim", "vhf_w"),
|
||||
array("północno-zachodnim", "vhf_nw"),
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
|
|
16
config.py
16
config.py
|
@ -27,7 +27,7 @@
|
|||
# Będąc w katalogu audio_generator:
|
||||
# php index.php
|
||||
#
|
||||
# Generowane są sample z tablicy $słownik z pliku slownik.php.
|
||||
# Generowane są sample z tablicy $słownik z pliku slownik.php.
|
||||
# Pozostałe tablice to tylko przechowalnia fraz go wygenerowania.
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@ log_handlers = [{
|
|||
'log_level': logging.INFO,
|
||||
'class': logging.StreamHandler,
|
||||
'config': {'stream': None},
|
||||
},{
|
||||
},{
|
||||
'log_level': logging.DEBUG,
|
||||
'class': logging.handlers.TimedRotatingFileHandler,
|
||||
'config': {
|
||||
|
@ -320,6 +320,17 @@ radioactivesq9atk = RadioactiveSq9atk(
|
|||
## więcej czujników na stronie http://radioactiveathome.org/map/
|
||||
)
|
||||
|
||||
# ---------------
|
||||
# vhf_propagation_sq9atk
|
||||
# ---------------
|
||||
from vhf_tropo_sq9atk import VhfTropoSq9atk
|
||||
vhftroposq9atk = VhfTropoSq9atk(
|
||||
language=pl_google,
|
||||
service_url="https://www.dxinfocentre.com/tropo_eur.html",
|
||||
qthLon=20.00,
|
||||
qthLat=50.00
|
||||
)
|
||||
|
||||
# ---------------
|
||||
# propagation_sq9atk
|
||||
# ---------------
|
||||
|
@ -361,6 +372,7 @@ modules = [
|
|||
imgwpodestsq9atk, # wodowskazy
|
||||
airpollutionsq9atk, # zanieczyszczenia powietrza z GIOŚ
|
||||
#airlysq9atk, # zanieczyszczenia powietrza z Airly
|
||||
vhftroposq9atk, # vhf tropo propagacja
|
||||
propagationsq9atk, # propagacja KF
|
||||
geomagneticsq9atk, # zaburzenia geomagnetyczne
|
||||
radioactivesq9atk, # promieniowanie jonizujące
|
||||
|
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 89 KiB |
|
@ -0,0 +1,271 @@
|
|||
#!/usr/bin/python -tt
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
import logging
|
||||
import socket
|
||||
import requests
|
||||
|
||||
from PIL import Image
|
||||
from pprint import pprint
|
||||
|
||||
from sr0wx_module import SR0WXModule
|
||||
|
||||
class VhfTropoSq9atk(SR0WXModule):
|
||||
"""Klasa pobierająca dane kalendarzowe"""
|
||||
|
||||
def __init__(self, language, service_url, qthLon, qthLat):
|
||||
self.__service_url = service_url
|
||||
self.__language = language
|
||||
self.__logger = logging.getLogger(__name__)
|
||||
|
||||
self.__areaSize = 70
|
||||
self.__colorSampleScatter = 5
|
||||
|
||||
self.__qthLon = float(qthLon)
|
||||
self.__qthLat = float(qthLat)
|
||||
|
||||
self.__mapLonStart = float(-10)
|
||||
self.__mapLonEnd = float(40)
|
||||
|
||||
self.__mapLatStart = float(56)
|
||||
self.__mapLatEnd = float(27)
|
||||
|
||||
def getHtmlFromUrl(self, url):
|
||||
try:
|
||||
resp = requests.get(url)
|
||||
if resp.status_code == 200:
|
||||
return resp.content
|
||||
else:
|
||||
print("HTML response error")
|
||||
return None
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("HTML download error: %s" % e)
|
||||
return None
|
||||
|
||||
def findMapUrlInHtml(self, html, target_id):
|
||||
pattern = r'<img\s+(?:[^>]*\s+)?id="' + re.escape(target_id) + r'"(?:[^>]*)\s+src="([^"]+)"'
|
||||
match = re.search(pattern, html, re.IGNORECASE)
|
||||
if match:
|
||||
mapUrl = match.group(1)
|
||||
return mapUrl
|
||||
else:
|
||||
return None
|
||||
|
||||
def downloadMapFile(self, mapUrl, targetFileName):
|
||||
try:
|
||||
self.__logger.info("::: Odpytuję adres: " + mapUrl)
|
||||
response = requests.get(mapUrl, timeout=30)
|
||||
|
||||
with open(targetFileName, "wb") as mapFile:
|
||||
mapFile.write(response.content)
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
print("Przekroczono czas oczekiwania")
|
||||
except Exception as e:
|
||||
print("Błąd pobierania mapy: %s" % e)
|
||||
return
|
||||
|
||||
|
||||
def readMapImageFile(self, fileName):
|
||||
|
||||
mapImg = Image.open(fileName, 'r')
|
||||
mapRgbImg = mapImg.convert('RGB')
|
||||
mapCropped = mapRgbImg.crop((43, 67, 888, 654))
|
||||
try:
|
||||
mapCropped.save(fileName)
|
||||
|
||||
except Exception as e:
|
||||
print("Błąd odczytu pliku z mapą: %s" % e)
|
||||
return mapCropped
|
||||
|
||||
def lonLatToMapXY(self, lon, lat, imgWidth, imgHeight):
|
||||
self.__logger.info("::: Przetwarzam dane...")
|
||||
imgWidth = float(imgWidth)
|
||||
imgHeight = float(imgHeight)
|
||||
lonRange = self.__mapLonEnd - self.__mapLonStart
|
||||
latRange = self.__mapLatEnd - self.__mapLatStart
|
||||
lonMod = (imgWidth / lonRange)
|
||||
latMod = (imgHeight / latRange)
|
||||
pixelY = round(latMod * (lat - self.__mapLatStart))
|
||||
pixelX = round(lonMod * (lon - self.__mapLonStart))
|
||||
|
||||
return int(pixelX), int(pixelY)
|
||||
|
||||
def prepareSamplesCoordinates(self, x_center, y_center, size, maxWidth, maxHeight):
|
||||
half_size = size // 2
|
||||
|
||||
if y_center + half_size > maxHeight:
|
||||
y_center = maxHeight - half_size
|
||||
|
||||
if y_center - half_size < 0:
|
||||
y_center = half_size
|
||||
|
||||
if x_center + half_size > maxWidth:
|
||||
x_center = maxWidth - half_size
|
||||
|
||||
if x_center - half_size < 0:
|
||||
x_center = half_size
|
||||
|
||||
coordinates = []
|
||||
for dx in range(-half_size, half_size + 1):
|
||||
for dy in range(-half_size, half_size + 1):
|
||||
coordinates.append((x_center + dx, y_center + dy))
|
||||
|
||||
return coordinates[::self.__colorSampleScatter]
|
||||
|
||||
def collectSamplesColors(self, image, coordinates):
|
||||
colors = []
|
||||
for x, y in coordinates:
|
||||
pixel_value = image.getpixel((x, y))
|
||||
colorHex = '#%02x%02x%02x' % pixel_value
|
||||
if colorHex != '#ffffff' and colorHex != '#000000':
|
||||
colors.append(colorHex)
|
||||
|
||||
return colors
|
||||
|
||||
def calculateColorsOccurence(self, input_array):
|
||||
total_elements = len(input_array)
|
||||
frequency_dict = {}
|
||||
|
||||
for value in input_array:
|
||||
if value in frequency_dict:
|
||||
frequency_dict[value] += 1
|
||||
else:
|
||||
frequency_dict[value] = 1
|
||||
|
||||
percentage_frequencies = {}
|
||||
for key, value in frequency_dict.items():
|
||||
percentage = (value / float(total_elements)) * 100
|
||||
percentage_frequencies[key] = percentage
|
||||
|
||||
return sorted(percentage_frequencies.items(), key=lambda item: item[1], reverse=True)
|
||||
|
||||
def getColorPunctation(self, colorHex):
|
||||
colors = {
|
||||
'#141414' : 0.00, #czarny
|
||||
'#8200dc' : 1.00, #fioletowy
|
||||
'#3377ff' : 2.00, #błękitny
|
||||
'#02d0a1' : 3.00, #pistacjowy
|
||||
'#a0e632' : 4.00, #cytrynowy
|
||||
'#e6dc32' : 5.00, #żółty
|
||||
'#e6af2d' : 6.00, #musztardowy
|
||||
'#f08228' : 7.00, #pomarańczowy
|
||||
'#fa3c3c' : 8.00, #czerwony
|
||||
'#ff80c0' : 9.00, #różowy
|
||||
'#ffb4dc' : 10.00, #różowy pastelowy
|
||||
'#cc86cc' : 11.00, #różowy szary
|
||||
'#c0c0c0' : 12.00 #szary
|
||||
}
|
||||
|
||||
result = False
|
||||
for color, value in colors.iteritems():
|
||||
if color == colorHex:
|
||||
result = value
|
||||
return result
|
||||
|
||||
def countVHFCondition(self, colorsPercentage):
|
||||
divider = 0.00
|
||||
score = 0.00
|
||||
for row in colorsPercentage:
|
||||
colorHex = row[0]
|
||||
percentage = row[1]
|
||||
colorPunctation = self.getColorPunctation(colorHex)
|
||||
divider += percentage
|
||||
score += percentage * colorPunctation
|
||||
conditionValue = score / divider
|
||||
|
||||
return conditionValue
|
||||
|
||||
def getLocationCondition(self, mapImg, x, y):
|
||||
maxWidth, maxHeight = mapImg.size
|
||||
|
||||
samplesCoordinates = self.prepareSamplesCoordinates(x, y, self.__areaSize, maxWidth, maxHeight)
|
||||
samples = self.collectSamplesColors(mapImg, samplesCoordinates)
|
||||
|
||||
occurences = self.calculateColorsOccurence(samples)
|
||||
locationConditionValue = self.countVHFCondition(occurences)
|
||||
|
||||
return locationConditionValue
|
||||
|
||||
def getDirectionalConditions(self, mapImg, x, y):
|
||||
shift = self.__areaSize/2
|
||||
shift = self.__areaSize
|
||||
|
||||
return {
|
||||
'N' : self.getLocationCondition(mapImg, x, y-shift),
|
||||
'NE' : self.getLocationCondition(mapImg, x+shift, y-shift),
|
||||
'E' : self.getLocationCondition(mapImg, x+shift, y),
|
||||
'SE' : self.getLocationCondition(mapImg, x+shift, y+shift),
|
||||
'S' : self.getLocationCondition(mapImg, x, y+shift),
|
||||
'SW' : self.getLocationCondition(mapImg, x-shift, y+shift),
|
||||
'W' : self.getLocationCondition(mapImg, x-shift, y),
|
||||
'NW' : self.getLocationCondition(mapImg, x-shift, y-shift),
|
||||
}
|
||||
|
||||
|
||||
def getTopDirectionsValues(self, input_table, threshold):
|
||||
filtered_rows = []
|
||||
for key, value in input_table.iteritems():
|
||||
if value > threshold:
|
||||
filtered_rows.append((key, value))
|
||||
|
||||
filtered_rows.sort(key=lambda x: x[1], reverse=True)
|
||||
|
||||
keys = ['vhf_' + row[0].lower() for row in filtered_rows[:2]]
|
||||
|
||||
if len(keys) == 2:
|
||||
keys.insert(1, 'vhf_oraz')
|
||||
|
||||
return keys
|
||||
|
||||
def prepareMessage(self, mainConditionValue, directionalConditionsValues):
|
||||
message = 'vhf_brak_szans_na_lacznosc_troposferyczna'
|
||||
|
||||
if mainConditionValue > 0.3:
|
||||
message = 'vhf_minimalne_szanse_na_lacznosc_troposferyczna'
|
||||
if mainConditionValue > 0.5:
|
||||
message = 'vhf_niewielkie_szanse_na_lacznosc_troposferyczna'
|
||||
if mainConditionValue > 1:
|
||||
message = 'vhf_spore_szanse_na_lacznosc_troposferyczna'
|
||||
if mainConditionValue > 2:
|
||||
message = 'vhf_duze_szanse_na_lacznosc_troposferyczna'
|
||||
if mainConditionValue > 5:
|
||||
message = 'vhf_bardzo_duze_szanse_na_lacznosc_troposferyczna'
|
||||
if mainConditionValue > 8:
|
||||
message = 'vhf_wyjatkowo_duze_szanse_na_lacznosc_troposferyczna'
|
||||
if mainConditionValue > 3:
|
||||
message = ' vhf_uwaga vhf_warunki_podwyzszone _ ' + message
|
||||
if mainConditionValue > 0.5:
|
||||
message += ' vhf_najlepsze_warunki_w_kierunku '
|
||||
message += " _ ".join( self.getTopDirectionsValues(directionalConditionsValues, mainConditionValue))
|
||||
|
||||
return message
|
||||
|
||||
|
||||
def get_data(self):
|
||||
html = self.getHtmlFromUrl(self.__service_url)
|
||||
mapUrl = self.findMapUrlInHtml(html, "imgClickAndChange")
|
||||
|
||||
self.downloadMapFile(mapUrl, 'vhf_map.png')
|
||||
|
||||
mapImg = self.readMapImageFile('vhf_map.png')
|
||||
|
||||
mapWidth, mapHeight = mapImg.size
|
||||
|
||||
x, y = self.lonLatToMapXY(self.__qthLon, self.__qthLat, mapWidth, mapHeight)
|
||||
|
||||
mainConditionValue = self.getLocationCondition(mapImg, x, y)
|
||||
directionalConditionsValues = self.getDirectionalConditions(mapImg, x, y)
|
||||
|
||||
message = " ".join([
|
||||
" _ vhf_propagacja_w_pasmie_vhf _ ",
|
||||
" " . join([ self.prepareMessage(mainConditionValue, directionalConditionsValues) ]),
|
||||
" _ "
|
||||
])
|
||||
|
||||
return {
|
||||
"message": message,
|
||||
"source": "vhf_dx_info_center",
|
||||
}
|
Ładowanie…
Reference in New Issue