Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
andrejs2 authored Jul 31, 2024
1 parent bad9674 commit 38641df
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 0 deletions.
11 changes: 11 additions & 0 deletions custom_component/manifest(1).json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"domain": "arso_weather_conditions",
"name": "ARSO Weather Conditions",
"documentation": "https://www.home-assistant.io/integrations/arso_weather_conditions",
"requirements": [
"feedparser==6.0.8"
],
"dependencies": [],
"codeowners": ["@your_github_username"],
"version": "1.0.0"
}
170 changes: 170 additions & 0 deletions custom_component/sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import homeassistant.helpers.config_validation as cv
import voluptuous as vol # Import voluptuous for schema validation
import asyncio
import aiohttp # For asynchronous HTTP requests
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.const import (
CONF_NAME, UnitOfTemperature,
UnitOfPressure, UnitOfSpeed, UnitOfLength, PERCENTAGE
)
import logging
import feedparser
import re

# Setup logger
_LOGGER = logging.getLogger(__name__)

CONF_RSS_URL = "rss_url"

# Update PLATFORM_SCHEMA to use voluptuous' Optional, use vol.Optional instead of cv.Optional
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_NAME, default="ARSO Weather Conditions"): cv.string,
}
)

def setup_platform(hass, config, add_entities, discovery_info=None):
_LOGGER.info("Setting up ARSO Weather Conditions platform")
name = config.get(CONF_NAME)
rss_url = "https://meteo.arso.gov.si/uploads/probase/www/observ/surface/text/sl/observation_LJUBL-ANA_BEZIGRAD_latest.rss" # Hardcoded RSS URL
_LOGGER.debug(f"Configured with name: {name}, rss_url: {rss_url}")
add_entities([ArsoWeatherConditionsSensor(name, rss_url)])

class ArsoWeatherConditionsSensor(SensorEntity):
def __init__(self, name, rss_url):
_LOGGER.info(f"Initializing ARSO Weather Conditions sensor with name: {name} and rss_url: {rss_url}")
self._name = name
self._rss_url = rss_url
self._state = None
self._attributes = {}

@property
def name(self):
return self._name

@property
def state(self):
return self._state

@property
def extra_state_attributes(self):
return self._attributes

async def async_update(self): # Use async_update for asynchronous operations
_LOGGER.info("Updating ARSO Weather Conditions sensor")
try:
# Fetch RSS feed content
feed_content = await fetch_rss_feed(self._rss_url)

# Ensure feed content is fetched successfully
if feed_content is None:
_LOGGER.error("Failed to fetch RSS feed content")
return

# Parse RSS feed
_LOGGER.debug("Parsing RSS feed content")
feed = await parse_rss_feed(feed_content)

# Ensure feed is successfully parsed
if feed is None:
_LOGGER.error("Failed to parse RSS feed")
return

# Extract weather details from the first entry
_LOGGER.debug("Extracting weather details from RSS feed")
entry = feed.entries[0]
details = extract_weather_details(entry)

# Set the state and attributes
self._state = details.get('condition')
self._attributes = {
'temperature': details.get('temperature'),
'temperature_unit': UnitOfTemperature.CELSIUS,
'wind_bearing': details.get('wind_bearing'),
'wind_speed': details.get('wind_speed'),
'wind_speed_unit': UnitOfSpeed.METERS_PER_SECOND,
'visibility': details.get('native_visibility'),
'visibility_unit': UnitOfLength.KILOMETERS,
'pressure': details.get('native_pressure'),
'pressure_unit': UnitOfPressure.MBAR,
'dew_point': details.get('native_dew_point'),
'humidity': details.get('humidity'),
'humidity_unit': PERCENTAGE,
}
_LOGGER.info(f"Updated state: {self._state} with attributes: {self._attributes}")

except Exception as e:
_LOGGER.error(f"Error updating ARSO Weather Conditions sensor: {e}")

# Function to fetch RSS feed content using aiohttp for non-blocking calls
async def fetch_rss_feed(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
response.raise_for_status()
return await response.text()

# Function to parse RSS feed content asynchronously
async def parse_rss_feed(feed_content):
loop = asyncio.get_event_loop()
return await loop.run_in_executor(None, feedparser.parse, feed_content)

# Mapping from Slovenian weather conditions to English terms
weather_condition_map = {
"pretežno jasno": "sunny",
"jasno": "sunny",
"delno oblačno": "partlycloudy",
"pretežno oblačno": "cloudy",
"oblačno": "cloudy",
"megla": "fog",
"megleno": "fog",
"dež": "rainy",
"deževno": "rainy",
"plohe": "pouring",
"nevihte": "lightning-rainy",
"sneženje": "snowy",
"snežna ploha": "snowy-rainy",
"toča": "hail",
"izjemno": "exceptional",
}

# Function to extract data using regex patterns
def extract_from_text(pattern, text, flags=re.IGNORECASE):
match = re.search(pattern, text, flags)
if match:
return match.group(1)
return None

# Function to extract weather details from an RSS feed entry
def extract_weather_details(entry):
details = {}

# Patterns to extract weather data
patterns = {
'temperature': r'(\d+)\s*°C',
'wind_bearing': r'Piha\s.*\((\w+)\):',
'wind_speed': r'Piha\s.*\(\w+\):\s(\d+)\sm/s',
'native_visibility': r'Vidnost:\s*(\d+)\s*km',
'native_pressure': r'Zračni tlak:\s*(\d+)\s*mbar',
'native_dew_point': r'Temperatura rosišča:\s*(\d+)\s*°C',
'humidity': r'Vlažnost zraka:\s*(\d+)\s*%'
}

combined_text = f"{entry.title} {entry.summary}"

for key, pattern in patterns.items():
details[key] = extract_from_text(pattern, combined_text)

# Extract weather condition from title
weather_condition_slovenian = extract_from_text(r':\s*(.*?),\s*\d+\s*°C', entry.title)
if weather_condition_slovenian:
details['condition'] = weather_condition_map.get(weather_condition_slovenian.lower(), weather_condition_slovenian)

# Special handling for wind bearing mappings
wind_bearing_map = {
'JZ': 'SW', 'JV': 'SE', 'SZ': 'NW', 'SV': 'NE',
'J': 'S', 'Z': 'W', 'S': 'N', 'V': 'E'
}
if 'wind_bearing' in details:
details['wind_bearing'] = wind_bearing_map.get(details['wind_bearing'], details['wind_bearing'])

return details

0 comments on commit 38641df

Please sign in to comment.