├── .github └── workflows │ ├── validate-hacs.yml │ └── validate-with-hassfest.yaml ├── .gitignore ├── .gitmodules ├── README.md ├── custom_components └── neerslag │ ├── __init__.py │ ├── config_flow.py │ ├── const.py │ ├── home-assistant-neerslag-card │ └── neerslag-card.js │ ├── load_frontend.py │ ├── manifest.json │ ├── sensor.py │ ├── strings.json │ └── translations │ ├── en.json │ ├── fr.json │ └── nl.json ├── documentation └── example.png └── hacs.json /.github/workflows/validate-hacs.yml: -------------------------------------------------------------------------------- 1 | name: Validate with HACS 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: "0 0 * * *" 8 | 9 | jobs: 10 | validate: 11 | runs-on: "ubuntu-latest" 12 | steps: 13 | - uses: "actions/checkout@v2" 14 | - name: HACS validation 15 | uses: "hacs/action@main" 16 | with: 17 | category: "integration" 18 | -------------------------------------------------------------------------------- /.github/workflows/validate-with-hassfest.yaml: -------------------------------------------------------------------------------- 1 | name: Validate with hassfest 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: "0 0 * * *" 8 | 9 | jobs: 10 | validate: 11 | runs-on: "ubuntu-latest" 12 | steps: 13 | - uses: "actions/checkout@v2" 14 | - uses: home-assistant/actions/hassfest@master -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | .vscode 3 | 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | share/python-wheels/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | MANIFEST 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | *.py,cover 54 | .hypothesis/ 55 | .pytest_cache/ 56 | cover/ 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | local_settings.py 65 | db.sqlite3 66 | db.sqlite3-journal 67 | 68 | # Flask stuff: 69 | instance/ 70 | .webassets-cache 71 | 72 | # Scrapy stuff: 73 | .scrapy 74 | 75 | # Sphinx documentation 76 | docs/_build/ 77 | 78 | # PyBuilder 79 | .pybuilder/ 80 | target/ 81 | 82 | # Jupyter Notebook 83 | .ipynb_checkpoints 84 | 85 | # IPython 86 | profile_default/ 87 | ipython_config.py 88 | 89 | # pyenv 90 | # For a library or package, you might want to ignore these files since the code is 91 | # intended to run in multiple environments; otherwise, check them in: 92 | # .python-version 93 | 94 | # pipenv 95 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 96 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 97 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 98 | # install all needed dependencies. 99 | #Pipfile.lock 100 | 101 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 102 | __pypackages__/ 103 | 104 | # Celery stuff 105 | celerybeat-schedule 106 | celerybeat.pid 107 | 108 | # SageMath parsed files 109 | *.sage.py 110 | 111 | # Environments 112 | .env 113 | .venv 114 | env/ 115 | venv/ 116 | ENV/ 117 | env.bak/ 118 | venv.bak/ 119 | 120 | # Spyder project settings 121 | .spyderproject 122 | .spyproject 123 | 124 | # Rope project settings 125 | .ropeproject 126 | 127 | # mkdocs documentation 128 | /site 129 | 130 | # mypy 131 | .mypy_cache/ 132 | .dmypy.json 133 | dmypy.json 134 | 135 | # Pyre type checker 136 | .pyre/ 137 | 138 | # pytype static type analyzer 139 | .pytype/ 140 | 141 | # Cython debug symbols 142 | cython_debug/ 143 | 144 | # Additional 145 | .storage/ 146 | www/ 147 | blueprints/ 148 | secrets.yaml 149 | scripts.yaml 150 | scenes.yaml 151 | home-assistant_v2.db 152 | home-assistant.log.1 153 | configuration.yaml 154 | automations.yaml 155 | .HA_VERSION 156 | home-assistant.log.fault 157 | home-assistant_v2.db-shm 158 | home-assistant_v2.db-wal 159 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aex351/home-assistant-neerslag-app/ca5244cb35843d8c9452438f8611065c970f6f9f/.gitmodules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![hacs_badge](https://img.shields.io/badge/HACS-Default-41BDF5.svg)](https://github.com/hacs/integration) 2 | # Neerslag App 3 | Neerslag app for Home Assistant. All-in-one package (Sensors + Card). 4 | 5 | Display rain forecast using Buienalarm and/or Buienradar sensor data. The Neerslag App (and the sensors) is fully configurable via the Home Assistant interface. 6 | 7 | > This package contains the Neerslag Card. Make sure to uninstall the Neerslag Card package from Home Assistant before using the Neerslag App to avoid unexpected behaviour. This includes manually removing the custom sensors. 8 | 9 | ## Features 10 | * Everything from the Neerslag Card; 11 | * Built-in Buienalarm and Buienradar sensors; 12 | * Ability to configure this app via the GUI; 13 | * Can use build-in Home Assistant configured location. 14 | 15 | ![Example](https://github.com/aex351/home-assistant-neerslag-app/raw/main/documentation/example.png) 16 | 17 | ## Installation overview 18 | 1) Install via HACS or manual; 19 | 2) Configure the Neerslag App (via interface); 20 | 3) Add the Neerslag Card to your dashboard. 21 | 22 | 23 | ## 1a. Install via HACS (recommended) 24 | This is the recommended option and also allows for easy updates. 25 | 1) Find this repository in HACS and click install 26 | 2) Restart Home Assistant and clear the browser cache; 27 | 3) Add the Neerslag App as an Integration in Home Assistant `(menu: settings -> devices & services -> add integration)`; 28 | 4) Restart Home Assistant and clear the browser cache (optional). 29 | 30 | For updates go to the Community Store (HACS) and click update. 31 | 32 | ## 1b. Manual install 33 | Not recommended, you will need to track updates manually by browsing to the repository; 34 | 1) Download the latest release of the Neerslag App from this repository; 35 | 2) In Home Assistant, create a folder `config/custom_components`; 36 | 3) Add the Neerslag App to the `custom_components` folder; 37 | 4) Restart Home Assistant; 38 | 5) Add the Neerslag App as an Integration in Home Assistant `(menu: settings -> devices & services -> add integration)`; 39 | 6) Restart Home Assistant and clear the browser cache (optional). 40 | 41 | For updates, repeat step 1 to 4. Home Assistant will not delete any configuration. 42 | 43 | ## 2. Configure the Neerslag App (via interface) 44 | The Neerslag App is fully configurable via the interface. 45 | 1) Go to `(menu: settings -> devices & services -> add integration)` and click on `configure`. 46 | 2) Select which sensor you want to use and provide the location data. There is an option to use the built-in Home Assistant location data. If this checkbox is selected, it will override the location settings of the individual sensors. 47 | 48 | ## 3. Add the Neerslag Card to your Dashboard 49 | 1) Go to your dashboard, go to `configure UI`; 50 | 2) Click `add card`; 51 | 3) Find the Neerslag Card in the list of cards; 52 | 4) Add the card and configure the card. 53 | 54 | > Note: Due to caching, The Neerslag Card might not be visible in the Home Assistant card selector directly after installing the Neerslag App. Restart Home Assistant and clear the browser cache to resolve this. 55 | 56 | ### Using one sensor: 57 | ```yaml 58 | type: 'custom:neerslag-card' 59 | title: Neerslag 60 | entity: sensor.neerslag_buienalarm_regen_data 61 | ``` 62 | ### Using two sensors: 63 | ```yaml 64 | type: 'custom:neerslag-card' 65 | title: Neerslag 66 | entities: 67 | - sensor.neerslag_buienalarm_regen_data 68 | - sensor.neerslag_buienradar_regen_data 69 | ``` 70 | > Note: If Home Assistant has not yet received data from the sensors, the card can remain blank. 71 | 72 | ### Advanced configuration options: 73 | Enable auto zoom to have the graph dynamically zoom in or out depending on the amount of rainfall. 74 | 75 | Note: By default auto zoom is disabled. Which gives the graph a fixed starting position displaying low, medium and heavy rainfall. Auto zoom will continue on extreme rainfall. Before version 2022.07.07.1 this setting was set to true. 76 | 77 | ```yaml 78 | autozoom: false 79 | ``` -------------------------------------------------------------------------------- /custom_components/neerslag/__init__.py: -------------------------------------------------------------------------------- 1 | """The Neerslag Sensor (Buienalarm / Buienradar) integration.""" 2 | import asyncio 3 | from .load_frontend import setup_view 4 | import logging 5 | 6 | from homeassistant.config_entries import ConfigEntry 7 | from homeassistant.core import HomeAssistant 8 | 9 | from .const import DOMAIN 10 | 11 | # TODO List the platforms that you want to support. 12 | # For your initial PR, limit it to 1 platform. 13 | PLATFORMS = ["sensor"] 14 | 15 | _LOGGER = logging.getLogger(__name__) 16 | 17 | 18 | async def options_update_listener(hass: HomeAssistant, config_entry: ConfigEntry): 19 | """Handle options update.""" 20 | 21 | _LOGGER.info("----------------This is being executed-------options_update_listener----------------") 22 | # await hass.config_entries.async_remove(config_entry.entry_id) 23 | # rr = hass.config_entries.async_entries(DOMAIN) 24 | # hass.config_entries.async_update_entry(config_entry, data=config_entry.options) 25 | # await hass.config_entries.async_reload(config_entry.entry_id) 26 | hass.config_entries.async_update_entry(config_entry, data=config_entry.options) 27 | 28 | 29 | async def async_setup(hass: HomeAssistant, config_entry: dict): 30 | """Set up the Neerslag Sensor (Buienalarm / Buienradar) component.""" 31 | hass.data.setdefault(DOMAIN, {}) 32 | await setup_view(hass) 33 | 34 | return True 35 | 36 | 37 | async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry): 38 | """Set up Neerslag Sensor (Buienalarm / Buienradar) from a config entry.""" 39 | 40 | # hass.states.async_set("neerslag_sensor.useBuienalarm", ConfigEntry.) 41 | 42 | # TODO Store an API object for your platforms to access 43 | # hass.data[DOMAIN][entry.entry_id] = MyApi(...) 44 | hass.data[DOMAIN][config_entry.entry_id] = {} 45 | 46 | hass_data = dict(config_entry.data) 47 | # Registers update listener to update config entry when options are updated. 48 | unsub_options_update_listener = config_entry.add_update_listener(options_update_listener) 49 | # Store a reference to the unsubscribe function to cleanup if an entry is unloaded. 50 | hass_data["unsub_options_update_listener"] = unsub_options_update_listener 51 | hass.data[DOMAIN][config_entry.entry_id] = hass_data 52 | 53 | await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) 54 | 55 | return True 56 | 57 | 58 | async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry): 59 | # Remove options_update_listener. 60 | 61 | _LOGGER.info("REMOVE ><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<") 62 | 63 | """Unload a config entry.""" 64 | unload_ok = all( 65 | await asyncio.gather( 66 | *[ 67 | hass.config_entries.async_forward_entry_unload(config_entry, platform) 68 | for platform in PLATFORMS 69 | ] 70 | ) 71 | ) 72 | 73 | hass.data[DOMAIN][config_entry.entry_id]["unsub_options_update_listener"]() 74 | 75 | if unload_ok: 76 | hass.data[DOMAIN].pop(config_entry.entry_id) 77 | 78 | return unload_ok 79 | -------------------------------------------------------------------------------- /custom_components/neerslag/config_flow.py: -------------------------------------------------------------------------------- 1 | """Config flow for Neerslag Sensor (Buienalarm / Buienradar) integration.""" 2 | import logging 3 | from typing import Optional 4 | 5 | import voluptuous as vol 6 | from homeassistant.core import callback 7 | 8 | from homeassistant import config_entries, core, exceptions 9 | 10 | from .const import DOMAIN # pylint:disable=unused-import 11 | 12 | _LOGGER = logging.getLogger(__name__) 13 | 14 | # TODO adjust the data schema to the data that you need 15 | STEP_USER_DATA_SCHEMA = vol.Schema({vol.Optional("buienalarm", default=False): bool, 16 | vol.Optional("buienalarmLatitude", description={"suggested_value": "55.000"}): str, 17 | vol.Optional("buienalarmLongitude", description={"suggested_value": "5.000"}): str, 18 | vol.Optional("buienradar", default=False): bool, 19 | vol.Optional("buienradarLatitude", description={"suggested_value": "55.00"}): str, 20 | vol.Optional("buienradarLongitude", description={"suggested_value": "5.00"}): str, 21 | vol.Optional("NeerslagSensorUseHAforLocation", default=True): bool 22 | }) 23 | 24 | 25 | async def validate_input(hass: core.HomeAssistant, data): 26 | """Validate the user input allows us to connect. 27 | 28 | Data has the keys from STEP_USER_DATA_SCHEMA with values provided by the user. 29 | """ 30 | # TODO validate the data can be used to set up a connection. 31 | 32 | # If your PyPI package is not built with async, pass your methods 33 | # to the executor: 34 | # await hass.async_add_executor_job( 35 | # your_validate_func, data["username"], data["password"] 36 | # ) 37 | 38 | # hub = PlaceholderHub(data["host"]) 39 | 40 | # if not await hub.authenticate(data["username"], data["password"]): 41 | # raise InvalidAuth 42 | 43 | # If you cannot connect: 44 | # throw CannotConnect 45 | # If the authentication is wrong: 46 | # InvalidAuth 47 | 48 | # Return info that you want to store in the config entry. 49 | return {"title": "Neerslag"} 50 | 51 | 52 | class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): 53 | """Handle a config flow for Neerslag Sensor (Buienalarm / Buienradar).""" 54 | 55 | VERSION = 1 56 | # TODO pick one of the available connection classes in homeassistant/config_entries.py 57 | CONNECTION_CLASS = config_entries.CONN_CLASS_UNKNOWN 58 | 59 | async def async_step_user(self, user_input=None): 60 | """Handle the initial step.""" 61 | 62 | if self._async_current_entries(): 63 | return self.async_abort(reason="single_instance_allowed") 64 | if self.hass.data.get(DOMAIN): 65 | return self.async_abort(reason="single_instance_allowed") 66 | 67 | if user_input is None: 68 | return self.async_show_form( 69 | step_id="user", data_schema=STEP_USER_DATA_SCHEMA 70 | ) 71 | 72 | errors = {} 73 | 74 | try: 75 | # info = await validate_input(self.hass, user_input) 76 | title = "Neerslag App" 77 | data = user_input 78 | # _LOGGER.info("Dit wordt nu uitgevoerd...........") 79 | # _LOGGER.info(data) 80 | 81 | except CannotConnect: 82 | errors["base"] = "cannot_connect" 83 | except InvalidAuth: 84 | errors["base"] = "invalid_auth" 85 | except Exception: # pylint: disable=broad-except 86 | _LOGGER.exception("Unexpected exception") 87 | errors["base"] = "unknown" 88 | else: 89 | return self.async_create_entry(title=title, data=data) 90 | 91 | return self.async_show_form( 92 | step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors 93 | ) 94 | 95 | @staticmethod 96 | @callback 97 | def async_get_options_flow(config_entry): 98 | """Get the options flow for this handler.""" 99 | return OptionsFlowHandler(config_entry) 100 | 101 | 102 | class OptionsFlowHandler(config_entries.OptionsFlow): 103 | 104 | def __init__(self, config_entry: config_entries.ConfigEntry) -> None: 105 | self.config_entry = config_entry 106 | 107 | async def async_step_init(self, user_input=None): 108 | 109 | # _LOGGER.info("HIER>>>") 110 | # _LOGGER.info(self.config_entry.data.get("buienalarmLatitude")) 111 | # _LOGGER.info(self.config_entry.data.get("buienalarm")) 112 | # _LOGGER.info(self.config_entry.data.get("NeerslagSensorUseHAforLocation")) 113 | testtest = vol.Schema({vol.Optional("buienalarm", default=self.config_entry.data.get("buienalarm")): bool, 114 | vol.Optional("buienalarmLatitude", default=self.config_entry.data.get("buienalarmLatitude")): str, 115 | vol.Optional("buienalarmLongitude", default=self.config_entry.data.get("buienalarmLongitude")): str, 116 | vol.Optional("buienradar", default=self.config_entry.data.get("buienradar")): bool, 117 | vol.Optional("buienradarLatitude", default=self.config_entry.data.get("buienradarLatitude")): str, 118 | vol.Optional("buienradarLongitude", default=self.config_entry.data.get("buienradarLongitude")): str, 119 | vol.Optional("NeerslagSensorUseHAforLocation", default=self.config_entry.data.get("NeerslagSensorUseHAforLocation")): bool 120 | }) 121 | 122 | # _LOGGER.info("----->>>>---------------") 123 | # _LOGGER.info(self.config_entry.options) 124 | # _LOGGER.info(self.config_entry.data) 125 | # _LOGGER.info("------<<<<--------------") 126 | """Manage the options.""" 127 | if user_input is not None: 128 | # _LOGGER.info(user_input) 129 | # _LOGGER.info("<><><><><><><><><><>") 130 | # self.config_entry.data = user_input 131 | return self.async_create_entry(title="", data=user_input) 132 | 133 | return self.async_show_form( 134 | step_id="init", 135 | data_schema=testtest, 136 | ) 137 | 138 | 139 | class CannotConnect(exceptions.HomeAssistantError): 140 | """Error to indicate we cannot connect.""" 141 | 142 | 143 | class InvalidAuth(exceptions.HomeAssistantError): 144 | """Error to indicate there is invalid auth.""" 145 | -------------------------------------------------------------------------------- /custom_components/neerslag/const.py: -------------------------------------------------------------------------------- 1 | """Constants for the Neerslag Sensor (Buienalarm / Buienradar) integration.""" 2 | 3 | DOMAIN = "neerslag" 4 | FRONTEND_SCRIPT_URL = "/neerslag-card.js" 5 | DATA_EXTRA_MODULE_URL = 'frontend_extra_module_url' -------------------------------------------------------------------------------- /custom_components/neerslag/load_frontend.py: -------------------------------------------------------------------------------- 1 | from homeassistant.core import HomeAssistant 2 | from homeassistant.components.frontend import add_extra_js_url 3 | from homeassistant.components.http import StaticPathConfig 4 | from aiohttp import web 5 | import logging 6 | import os 7 | from .const import FRONTEND_SCRIPT_URL, DATA_EXTRA_MODULE_URL 8 | import time 9 | 10 | _LOGGER = logging.getLogger(__name__) 11 | 12 | 13 | async def setup_view(hass: HomeAssistant): 14 | dir_path = os.path.dirname(os.path.realpath(__file__)) 15 | path_to_file = "{}/home-assistant-neerslag-card/neerslag-card.js".format(dir_path) 16 | should_cache = False 17 | 18 | timestamp = str(time.time()) 19 | frontend_script_url_with_parameter = FRONTEND_SCRIPT_URL+"?cache="+timestamp 20 | add_extra_js_url(hass, frontend_script_url_with_parameter , es5=False) 21 | 22 | await hass.http.async_register_static_paths([StaticPathConfig(FRONTEND_SCRIPT_URL, str(path_to_file), should_cache)]) -------------------------------------------------------------------------------- /custom_components/neerslag/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "domain": "neerslag", 3 | "name": "Neerslag App (Buienalarm / Buienradar)", 4 | "config_flow": true, 5 | "documentation": "https://github.com/aex351/home-assistant-neerslag-app", 6 | "requirements": [], 7 | "ssdp": [], 8 | "zeroconf": [], 9 | "homekit": {}, 10 | "dependencies": [], 11 | "issue_tracker": "https://github.com/aex351/home-assistant-neerslag-app/issues", 12 | "codeowners": [ 13 | "@aex351" 14 | ], 15 | "iot_class" : "cloud_polling", 16 | "version": "2024.12.29.0" 17 | } -------------------------------------------------------------------------------- /custom_components/neerslag/sensor.py: -------------------------------------------------------------------------------- 1 | from homeassistant.block_async_io import enable 2 | from homeassistant.helpers.entity_platform import EntityPlatform 3 | import logging 4 | from os import truncate 5 | import aiohttp 6 | 7 | from random import random 8 | import random as rand 9 | 10 | import json 11 | from homeassistant.helpers.entity import Entity 12 | from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, CONF_SOURCE 13 | from datetime import timedelta 14 | from homeassistant.config_entries import ConfigEntry 15 | from homeassistant.core import HomeAssistant 16 | from homeassistant.helpers.entity_platform import EntityPlatform, async_get_platforms 17 | 18 | 19 | from homeassistant.helpers.entity_registry import ( 20 | async_entries_for_config_entry, 21 | async_entries_for_device, 22 | ) 23 | 24 | 25 | _LOGGER = logging.getLogger(__name__) 26 | 27 | SCAN_INTERVAL = timedelta(seconds=180) 28 | 29 | 30 | async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities): 31 | """Set up sensor entity.""" 32 | 33 | # if config_entry.data.get("buienalarm") == True: 34 | # async_add_entities([NeerslagSensorBuienalarm(hass, config_entry)], update_before_add=True) 35 | 36 | # if config_entry.data.get("buienradar") == True: 37 | # async_add_entities([NeerslagSensorBuienradar(hass, config_entry)], update_before_add=True) 38 | # # async_add_entities([NeerslagSensor(hass, config_entry)]) 39 | 40 | # entity_registry_obj = await hass.helpers.entity_registry.async_get_registry() 41 | # registry_entry = entity_registry_obj.async_get(config_entry.unique_id) 42 | 43 | # dev_reg = await hass.helpers.device_registry.async_get_registry() 44 | # ent_reg = await hass.helpers.entity_registry.async_get_registry() 45 | 46 | # dds = async_get_platforms(hass, "neerslag") 47 | # _LOGGER.info(len(dds)) 48 | # async_reset 49 | 50 | # _LOGGER.info("----------->>>") 51 | # _LOGGER.info(dev_reg.devices) 52 | # _LOGGER.info(ent_reg.entities) 53 | 54 | # xx = "neerslag_DummyABC" 55 | # aa = ent_reg.async_get("sensor.neerslag_dummyabc") 56 | 57 | # _LOGGER.info("<<1aa<<<<<<<<<<<<<<<<<----------->>>") 58 | # _LOGGER.info(aa) 59 | # _LOGGER.info("<<>>") 60 | 61 | # bb = ent_reg.async_get_entity_id(domain='sensor', platform='neerslag', unique_id='neerslag-sensor-DummyABC') 62 | # _LOGGER.info(bb) 63 | # _LOGGER.info("<<>>") 64 | 65 | # cc = async_entries_for_config_entry(ent_reg, config_entry.entry_id) 66 | # _LOGGER.info(cc) 67 | # _LOGGER.info("<<>>") 68 | 69 | # ent_reg = hass.helpers.entity_registry.async_get_registry() 70 | # aaa = ent_reg.async_get_entity_id("neerslag", "sensor", self._unique_id) 71 | 72 | # _LOGGER.info(aaa) 73 | 74 | # _LOGGER.info(config_entry.entry_id) 75 | # _LOGGER.info(config_entry.unique_id) 76 | 77 | # rr = await config_entry.ConfigEntries.async_reload(config_entry.entry_id) 78 | # _LOGGER.info(rr) 79 | 80 | # async_add_entities([DummyABC(hass, config_entry)], update_before_add=True) 81 | # async_add_entities([DummyABC(hass, config_entry)], update_before_add=True) 82 | 83 | # if config_entry.data.get("buienalarm") == True: 84 | # _LOGGER.info("<><><><>----------------<><<><>") 85 | # async_add_entities([DummyABC(hass, config_entry, True)], update_before_add=True) 86 | 87 | # if config_entry.data.get("buienalarm") == False: 88 | # async_add_entities([DummyABC(hass, config_entry, False)], update_before_add=False) 89 | 90 | # if config_entry.data.get("buienradar") == True: 91 | # async_add_entities([DummyDEF(hass, config_entry, True)], update_before_add=True) 92 | 93 | # if config_entry.data.get("buienradar") == False: 94 | # async_add_entities([DummyDEF(hass, config_entry, False)], update_before_add=False) 95 | 96 | if config_entry.data.get("buienalarm") == True: 97 | async_add_entities([NeerslagSensorBuienalarm(hass, config_entry, True)], update_before_add=True) 98 | 99 | if config_entry.data.get("buienalarm") == False: 100 | async_add_entities([NeerslagSensorBuienalarm(hass, config_entry, False)], update_before_add=False) 101 | 102 | if config_entry.data.get("buienradar") == True: 103 | async_add_entities([NeerslagSensorBuienradar(hass, config_entry, True)], update_before_add=True) 104 | 105 | if config_entry.data.get("buienradar") == False: 106 | async_add_entities([NeerslagSensorBuienradar(hass, config_entry, False)], update_before_add=False) 107 | 108 | # async_add_entities([NeerslagSensor(hass, config_entry)]) 109 | 110 | # device_registry = await hass.helpers.device_registry.async_get_registry() 111 | # device_registry.async_get_or_create( 112 | # config_entry_id=config_entry.entry_id, 113 | # default_manufacturer="dummy data", 114 | # default_model="dummy data", 115 | # default_name="dummy data") 116 | 117 | 118 | class mijnBasis(Entity): 119 | _enabled = None 120 | _unique_id = None 121 | _name = None 122 | 123 | def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry, enabled: bool): 124 | _LOGGER.info("--<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>--->>>>>>>>>>>>>>>>>>>>>>>>") 125 | # self._enabled = enabled 126 | # config_entry.add_update_listener(self.mine_update_listener) 127 | 128 | async def mine_update_listener(self, hass: HomeAssistant, config_entry: ConfigEntry, pp=None): 129 | """Handle options update.""" 130 | 131 | # if(self._name == "neerslag_DummyABC"): 132 | # self._enabled = config_entry.data.get("buienalarm") 133 | 134 | # if(self._name == "neerslag_DummyDEF"): 135 | # self._enabled = config_entry.data.get("buienradar") 136 | 137 | if(self._name == "neerslag_buienalarm_regen_data"): 138 | self._enabled = config_entry.data.get("buienalarm") 139 | 140 | if(self._name == "neerslag_buienradar_regen_data"): 141 | self._enabled = config_entry.data.get("buienradar") 142 | 143 | # self._enabled = config_entry.data.get(enabled) 144 | # await hass.config_entries.async_remove(config_entry.entry_id) 145 | # rr = hass.config_entries.async_entries(DOMAIN) 146 | # hass.config_entries.async_update_entry(config_entry, data=config_entry.options) 147 | # await hass.config_entries.async_reload(config_entry.entry_id) 148 | 149 | @property 150 | def device_info(self): 151 | return { 152 | "identifiers": { 153 | # Serial numbers are unique identifiers within a specific domain 154 | ("neerslag", "neerslag-device") 155 | }, 156 | "name": "Neerslag App", 157 | "manufacturer": "aex351", 158 | "model": "All-in-one package", 159 | "sw_version": "", 160 | "via_device": ("neerslag", "abcd"), 161 | } 162 | 163 | @property 164 | def available(self) -> bool: 165 | """Return True if entity is available.""" 166 | return self._enabled 167 | 168 | @ property 169 | def state(self): 170 | return self._state 171 | 172 | @ property 173 | def name(self): 174 | return self._name 175 | 176 | @ property 177 | def unique_id(self): 178 | """Return unique ID.""" 179 | return self._unique_id 180 | 181 | async def async_update(self): 182 | self._state = random() 183 | return True 184 | 185 | 186 | class DummyABC(mijnBasis): 187 | def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry, enabled: bool): 188 | super().__init__(hass=hass, config_entry=config_entry, enabled=enabled) 189 | self._name = "neerslag_DummyABC" 190 | self._state = "working" # None 191 | self._attrs = ["data empty"] 192 | self._unique_id = "neerslag-sensor-DummyABC" 193 | 194 | self._enabled = enabled 195 | config_entry.add_update_listener(self.mine_update_listener) 196 | 197 | 198 | class DummyDEF(mijnBasis): 199 | def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry, enabled: bool): 200 | super().__init__(hass=hass, config_entry=config_entry, enabled=enabled) 201 | self._name = "neerslag_DummyDEF" 202 | self._state = "working" # None 203 | self._attrs = ["data empty"] 204 | self._unique_id = "neerslag-sensor-DummyDEF" 205 | 206 | # _LOGGER.info(">>>>>>>>>>>>>>>>>>>>>>>>") 207 | # _LOGGER.info(config_entry.entry_id) 208 | # _LOGGER.info(config_entry.unique_id) 209 | 210 | self._enabled = enabled 211 | config_entry.add_update_listener(self.mine_update_listener) 212 | 213 | 214 | class NeerslagSensorBuienalarm(mijnBasis): 215 | def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry, enabled: bool): 216 | super().__init__(hass=hass, config_entry=config_entry, enabled=enabled) 217 | self._name = "neerslag_buienalarm_regen_data" 218 | self._state = "working" # None 219 | self._attrs = ["data empty"] 220 | self._unique_id = "neerslag-sensor-buienalarm-1" 221 | 222 | self._enabled = enabled 223 | config_entry.add_update_listener(self.mine_update_listener) 224 | 225 | if config_entry.data.get("NeerslagSensorUseHAforLocation") == True: 226 | self._lat = hass.config.latitude 227 | self._lon = hass.config.longitude 228 | 229 | else: 230 | self._lat = config_entry.data.get("buienalarmLatitude") 231 | self._lon = config_entry.data.get("buienalarmLongitude") 232 | 233 | # format values, enforce 3 decimals 234 | self._lat = f'{float(self._lat):.3f}' 235 | self._lon = f'{float(self._lon):.3f}' 236 | 237 | # self._entity_picture = "https://www.buienalarm.nl/assets/img/social.png" 238 | self._icon = "mdi:weather-cloudy" 239 | 240 | @ property 241 | def icon(self): 242 | return self._icon 243 | 244 | @ property 245 | def state_attributes(self): 246 | if not len(self._attrs): 247 | return 248 | return self._attrs 249 | # return {"data": self._attrs} 250 | 251 | async def async_update(self): 252 | if(self._enabled == True): 253 | self._state = random() 254 | self._attrs = await self.getBuienalarmData() 255 | return True 256 | 257 | async def getBuienalarmData(self) -> str: 258 | data = json.loads('{"data":""}') 259 | # return data 260 | try: 261 | timeout = aiohttp.ClientTimeout(total=5) 262 | async with aiohttp.ClientSession() as session: 263 | url = 'https://cdn-secure.buienalarm.nl/api/3.4/forecast.php?lat=' + self._lat + '&lon=' + self._lon + '®ion=nl&c=' + str(rand.randint(0, 999999999999999)) 264 | async with session.get(url, timeout=timeout) as response: 265 | html = await response.text() 266 | dataRequest = html.replace('\r\n', ' ') 267 | if dataRequest == "" : 268 | dataRequest = "" 269 | data = json.loads('{"data":' + dataRequest + '}') 270 | # _LOGGER.info(data) 271 | await session.close() 272 | except: 273 | _LOGGER.info("getBuienalarmData - timeout") 274 | pass 275 | 276 | return data 277 | 278 | 279 | class NeerslagSensorBuienradar(mijnBasis): 280 | def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry, enabled: bool): 281 | super().__init__(hass=hass, config_entry=config_entry, enabled=enabled) 282 | 283 | self._name = "neerslag_buienradar_regen_data" 284 | self._state = "working" # None 285 | self._attrs = ["data empty"] 286 | self._unique_id = "neerslag-sensor-buienradar-1" 287 | 288 | self._enabled = enabled 289 | config_entry.add_update_listener(self.mine_update_listener) 290 | 291 | if config_entry.data.get("NeerslagSensorUseHAforLocation") == True: 292 | self._lat = hass.config.latitude 293 | self._lon = hass.config.longitude 294 | 295 | else: 296 | self._lat = config_entry.data.get("buienradarLatitude") 297 | self._lon = config_entry.data.get("buienradarLongitude") 298 | 299 | # format values, enforce 2 decimals 300 | self._lat = f'{float(self._lat):.2f}' 301 | self._lon = f'{float(self._lon):.2f}' 302 | 303 | # self._entity_picture = "https://cdn.buienradar.nl/resources/images/br-logo-square.png" 304 | self._icon = "mdi:weather-cloudy" 305 | 306 | @ property 307 | def icon(self): 308 | return self._icon 309 | 310 | @ property 311 | def state_attributes(self): 312 | if not len(self._attrs): 313 | return 314 | return self._attrs 315 | # return {"data": self._attrs} 316 | 317 | async def async_update(self): 318 | if(self._enabled == True): 319 | self._state = random() 320 | self._attrs = await self.getBuienradarData() 321 | return True 322 | 323 | async def getBuienradarData(self) -> str: 324 | data = json.loads('{"data":""}') 325 | # return data 326 | try: 327 | timeout = aiohttp.ClientTimeout(total=5) 328 | async with aiohttp.ClientSession() as session: 329 | # https://www.buienradar.nl/overbuienradar/gratis-weerdata 330 | url = 'https://gps.buienradar.nl/getrr.php?lat=' + self._lat + '&lon=' + self._lon + '&c=' + str(rand.randint(0, 999999999999999)) 331 | # _LOGGER.info(url) 332 | async with session.get(url, timeout=timeout) as response: 333 | html = await response.text() 334 | dataRequest = ' '.join(html.splitlines()) 335 | if dataRequest == "" : 336 | dataRequest = "" 337 | data = json.loads('{"data": "' + dataRequest + '"}') 338 | # _LOGGER.info(data) 339 | await session.close() 340 | except: 341 | _LOGGER.info("getBuienradarData - timeout") 342 | pass 343 | 344 | return data 345 | -------------------------------------------------------------------------------- /custom_components/neerslag/strings.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "step": { 4 | "user": { 5 | "title" : "Neerslag App set-up", 6 | "description" : "It can take a couple of minutes before the sensors to become active.", 7 | "data": { 8 | "host": "[%key:common::config_flow::data::host%]", 9 | "username": "[%key:common::config_flow::data::username%]", 10 | "password": "[%key:common::config_flow::data::password%]", 11 | "buienradar": "Enable Buienradar", 12 | "buienradarLatitude": "Latitude", 13 | "buienradarLongitude": "Longitude", 14 | "buienalarm": "Enable Buienalarm", 15 | "buienalarmLatitude": "Latitude", 16 | "buienalarmLongitude": "Longitude", 17 | "NeerslagSensorUseHAforLocation" : "Use the location settings (latitude/longitude) of Home Assistant (Overrides all other location settings)" 18 | } 19 | } 20 | }, 21 | "error": { 22 | "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", 23 | "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", 24 | "unknown": "[%key:common::config_flow::error::unknown%]" 25 | }, 26 | "abort": { 27 | "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" 28 | } 29 | }, 30 | "options":{ 31 | "step": { 32 | "init": { 33 | "title" : "Neerslag App options", 34 | "description" : "Changes (after clicking submit) take a couple of minutes to process.", 35 | "data": { 36 | "host": "[%key:common::config_flow::data::host%]", 37 | "username": "[%key:common::config_flow::data::username%]", 38 | "password": "[%key:common::config_flow::data::password%]", 39 | "buienradar": "Enable Buienradar", 40 | "buienradarLatitude": "Latitude", 41 | "buienradarLongitude": "Longitude", 42 | "buienalarm": "Enable Buienalarm", 43 | "buienalarmLatitude": "Latitude", 44 | "buienalarmLongitude": "Longitude", 45 | "NeerslagSensorUseHAforLocation" : "Use the location settings (latitude/longitude) of Home Assistant (Overrides all other location settings)" 46 | } 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /custom_components/neerslag/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "abort": { 4 | "already_configured": "Device is already configured" 5 | }, 6 | "error": { 7 | "cannot_connect": "Failed to connect", 8 | "invalid_auth": "Invalid authentication", 9 | "unknown": "Unexpected error" 10 | }, 11 | "step": { 12 | "user": { 13 | "data": { 14 | "NeerslagSensorUseHAforLocation": "Use the location settings (latitude/longitude) of Home Assistant (Overrides all other location settings)", 15 | "buienalarm": "Enable Buienalarm", 16 | "buienalarmLatitude": "Latitude", 17 | "buienalarmLongitude": "Longitude", 18 | "buienradar": "Enable Buienradar", 19 | "buienradarLatitude": "Latitude", 20 | "buienradarLongitude": "Longitude", 21 | "host": "Host", 22 | "password": "Password", 23 | "username": "Username" 24 | }, 25 | "description": "It can take a couple of minutes before the sensors to become active.", 26 | "title": "Neerslag App set-up" 27 | } 28 | } 29 | }, 30 | "options": { 31 | "step": { 32 | "init": { 33 | "data": { 34 | "NeerslagSensorUseHAforLocation": "Use the location settings (latitude/longitude) of Home Assistant (Overrides all other location settings)", 35 | "buienalarm": "Enable Buienalarm", 36 | "buienalarmLatitude": "Latitude", 37 | "buienalarmLongitude": "Longitude", 38 | "buienradar": "Enable Buienradar", 39 | "buienradarLatitude": "Latitude", 40 | "buienradarLongitude": "Longitude", 41 | "host": "Host", 42 | "password": "Password", 43 | "username": "Username" 44 | }, 45 | "description": "Changes (after clicking submit) take a couple of minutes to process.", 46 | "title": "Neerslag App options" 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /custom_components/neerslag/translations/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "abort": { 4 | "already_configured": "L'appareil est déjà configuré" 5 | }, 6 | "error": { 7 | "cannot_connect": "Connection impossible", 8 | "invalid_auth": "Authentification invalide", 9 | "unknown": "Erreur inconnue" 10 | }, 11 | "step": { 12 | "user": { 13 | "data": { 14 | "NeerslagSensorUseHAforLocation": "Utilisation des paramètres de localisation de Home Assistant (latitude/longitude ; outrepasse les autres paramètres de localisation)", 15 | "buienalarm": "Activer Buienalarm", 16 | "buienalarmLatitude": "Latitude", 17 | "buienalarmLongitude": "Longitude", 18 | "buienradar": "Activer Buienradar", 19 | "buienradarLatitude": "Latitude", 20 | "buienradarLongitude": "Longitude", 21 | "host": "Hôte", 22 | "password": "Mot de Passe", 23 | "username": "Nom d'utilisateur" 24 | }, 25 | "description": "Les senseurs peuvent prendre quelque minutes pour devenir actifs.", 26 | "title": "Configuration de l'application Neerslag" 27 | } 28 | } 29 | }, 30 | "options": { 31 | "step": { 32 | "init": { 33 | "data": { 34 | "NeerslagSensorUseHAforLocation": "Utilisation des paramètres de localisation de Home Assistant (latitude/longitude ; outrepasse les autres paramètres de localisation)", 35 | "buienalarm": "Activer Buienalarm", 36 | "buienalarmLatitude": "Latitude", 37 | "buienalarmLongitude": "Longitude", 38 | "buienradar": "Activer Buienradar", 39 | "buienradarLatitude": "Latitude", 40 | "buienradarLongitude": "Longitude", 41 | "host": "Hôte", 42 | "password": "Mot de Passe", 43 | "username": "Nom d'utilisateur" 44 | }, 45 | "description": "Les changements seront appliqués quelques minutes après soumission.", 46 | "title": "Options de l'application Neerslag" 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /custom_components/neerslag/translations/nl.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "abort": { 4 | "already_configured": "Het apparaat is al geconfigureerd" 5 | }, 6 | "error": { 7 | "cannot_connect": "Failed to connect", 8 | "invalid_auth": "Invalid authentication", 9 | "unknown": "Unexpected error" 10 | }, 11 | "step": { 12 | "user": { 13 | "data": { 14 | "NeerslagSensorUseHAforLocation": "Gebruik de locatie instellingen (latitude/longitude) van Home Assistant (deze optie overschrijft de andere locatie instellingen)", 15 | "buienalarm": "Activeer Buienalarm", 16 | "buienalarmLatitude": "Latitude", 17 | "buienalarmLongitude": "Longitude", 18 | "buienradar": "Activeer Buienradar", 19 | "buienradarLatitude": "Latitude", 20 | "buienradarLongitude": "Longitude", 21 | "host": "Host", 22 | "password": "Password", 23 | "username": "Username" 24 | }, 25 | "description": "Het kan een paar minuten duren voordat de sensors geactiveerd zijn.", 26 | "title": "Neerslag App set-up" 27 | } 28 | } 29 | }, 30 | "options": { 31 | "step": { 32 | "init": { 33 | "data": { 34 | "NeerslagSensorUseHAforLocation": "Gebruik de locatie instellingen (latitude/longitude) van Home Assistant (deze optie overschrijft de andere locatie instellingen)", 35 | "buienalarm": "Activeer Buienalarm", 36 | "buienalarmLatitude": "Latitude", 37 | "buienalarmLongitude": "Longitude", 38 | "buienradar": "Activeer Buienradar", 39 | "buienradarLatitude": "Latitude", 40 | "buienradarLongitude": "Longitude", 41 | "host": "Host", 42 | "password": "Password", 43 | "username": "Username" 44 | }, 45 | "description": "Het kan een paar minuten duren voordat de veranderingen verwerkt zijn.", 46 | "title": "Neerslag App opties" 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /documentation/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aex351/home-assistant-neerslag-app/ca5244cb35843d8c9452438f8611065c970f6f9f/documentation/example.png -------------------------------------------------------------------------------- /hacs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Neerslag App", 3 | "render_readme": true, 4 | "country": ["NL", "BE"] 5 | } --------------------------------------------------------------------------------