Moduł VHF-tropo

pull/4/merge
pawel 2023-08-27 07:17:12 +02:00
rodzic 2e7a49b2a1
commit 14032b9d94
45 zmienionych plików z 315 dodań i 2 usunięć

Wyświetl plik

@ -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"),
/*
*
*

Wyświetl plik

@ -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.

BIN
pl_google/vhf_e.ogg 100644

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

BIN
pl_google/vhf_n.ogg 100644

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.

BIN
pl_google/vhf_s.ogg 100644

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.

BIN
pl_google/vhf_w.ogg 100644

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.

BIN
vhf_map.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 89 KiB

271
vhf_tropo_sq9atk.py 100755
Wyświetl plik

@ -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",
}