diff --git a/.coveragerc b/.coveragerc
index 341494b14245416f64a0eb9eca30263f582170f0..20c6fd2c60e1edda16f1681c56b4bc61e83582b6 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -976,6 +976,7 @@ omit =
     homeassistant/components/raincloud/*
     homeassistant/components/rainmachine/__init__.py
     homeassistant/components/rainmachine/binary_sensor.py
+    homeassistant/components/rainmachine/button.py
     homeassistant/components/rainmachine/model.py
     homeassistant/components/rainmachine/sensor.py
     homeassistant/components/rainmachine/switch.py
diff --git a/homeassistant/components/rainmachine/__init__.py b/homeassistant/components/rainmachine/__init__.py
index c30ce81dc6dae9198823b0fc49164682d2572f8d..dccdaaba74c136f2b8a6882c8eb5b05dfe915c06 100644
--- a/homeassistant/components/rainmachine/__init__.py
+++ b/homeassistant/components/rainmachine/__init__.py
@@ -30,11 +30,7 @@ from homeassistant.helpers import (
     entity_registry as er,
 )
 from homeassistant.helpers.entity import DeviceInfo
-from homeassistant.helpers.update_coordinator import (
-    CoordinatorEntity,
-    DataUpdateCoordinator,
-    UpdateFailed,
-)
+from homeassistant.helpers.update_coordinator import CoordinatorEntity, UpdateFailed
 from homeassistant.util.network import is_ip_address
 
 from .config_flow import get_client_controller
@@ -49,20 +45,13 @@ from .const import (
     LOGGER,
 )
 from .model import RainMachineEntityDescription
+from .util import RainMachineDataUpdateCoordinator
 
 DEFAULT_SSL = True
 
 CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False)
 
-PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR, Platform.SWITCH]
-
-UPDATE_INTERVALS = {
-    DATA_PROVISION_SETTINGS: timedelta(minutes=1),
-    DATA_PROGRAMS: timedelta(seconds=30),
-    DATA_RESTRICTIONS_CURRENT: timedelta(minutes=1),
-    DATA_RESTRICTIONS_UNIVERSAL: timedelta(minutes=1),
-    DATA_ZONES: timedelta(seconds=15),
-}
+PLATFORMS = [Platform.BINARY_SENSOR, Platform.BUTTON, Platform.SENSOR, Platform.SWITCH]
 
 CONF_CONDITION = "condition"
 CONF_DEWPOINT = "dewpoint"
@@ -134,13 +123,21 @@ SERVICE_RESTRICT_WATERING_SCHEMA = SERVICE_SCHEMA.extend(
     }
 )
 
+COORDINATOR_UPDATE_INTERVAL_MAP = {
+    DATA_PROVISION_SETTINGS: timedelta(minutes=1),
+    DATA_PROGRAMS: timedelta(seconds=30),
+    DATA_RESTRICTIONS_CURRENT: timedelta(minutes=1),
+    DATA_RESTRICTIONS_UNIVERSAL: timedelta(minutes=1),
+    DATA_ZONES: timedelta(seconds=15),
+}
+
 
 @dataclass
 class RainMachineData:
     """Define an object to be stored in `hass.data`."""
 
     controller: Controller
-    coordinators: dict[str, DataUpdateCoordinator]
+    coordinators: dict[str, RainMachineDataUpdateCoordinator]
 
 
 @callback
@@ -233,24 +230,25 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
 
         return data
 
+    async def async_init_coordinator(
+        coordinator: RainMachineDataUpdateCoordinator,
+    ) -> None:
+        """Initialize a RainMachineDataUpdateCoordinator."""
+        await coordinator.async_initialize()
+        await coordinator.async_config_entry_first_refresh()
+
     controller_init_tasks = []
     coordinators = {}
-
-    for api_category in (
-        DATA_PROGRAMS,
-        DATA_PROVISION_SETTINGS,
-        DATA_RESTRICTIONS_CURRENT,
-        DATA_RESTRICTIONS_UNIVERSAL,
-        DATA_ZONES,
-    ):
-        coordinator = coordinators[api_category] = DataUpdateCoordinator(
+    for api_category, update_interval in COORDINATOR_UPDATE_INTERVAL_MAP.items():
+        coordinator = coordinators[api_category] = RainMachineDataUpdateCoordinator(
             hass,
-            LOGGER,
+            entry=entry,
             name=f'{controller.name} ("{api_category}")',
-            update_interval=UPDATE_INTERVALS[api_category],
+            api_category=api_category,
+            update_interval=update_interval,
             update_method=partial(async_update, api_category),
         )
-        controller_init_tasks.append(coordinator.async_refresh())
+        controller_init_tasks.append(async_init_coordinator(coordinator))
 
     await asyncio.gather(*controller_init_tasks)
 
@@ -439,12 +437,6 @@ class RainMachineEntity(CoordinatorEntity):
         self.update_from_latest_data()
         self.async_write_ha_state()
 
-    async def async_added_to_hass(self) -> None:
-        """Handle entity which will be added."""
-        await super().async_added_to_hass()
-        self.update_from_latest_data()
-
     @callback
     def update_from_latest_data(self) -> None:
         """Update the state."""
-        raise NotImplementedError
diff --git a/homeassistant/components/rainmachine/button.py b/homeassistant/components/rainmachine/button.py
new file mode 100644
index 0000000000000000000000000000000000000000..14bfb8786422af443a177fe7e9c7016fb7ac0a6f
--- /dev/null
+++ b/homeassistant/components/rainmachine/button.py
@@ -0,0 +1,90 @@
+"""Buttons for the RainMachine integration."""
+from __future__ import annotations
+
+from collections.abc import Awaitable, Callable
+from dataclasses import dataclass
+
+from regenmaschine.controller import Controller
+from regenmaschine.errors import RainMachineError
+
+from homeassistant.components.button import (
+    ButtonDeviceClass,
+    ButtonEntity,
+    ButtonEntityDescription,
+)
+from homeassistant.config_entries import ConfigEntry
+from homeassistant.core import HomeAssistant
+from homeassistant.exceptions import HomeAssistantError
+from homeassistant.helpers.dispatcher import async_dispatcher_send
+from homeassistant.helpers.entity import EntityCategory
+from homeassistant.helpers.entity_platform import AddEntitiesCallback
+
+from . import RainMachineData, RainMachineEntity
+from .const import DATA_PROVISION_SETTINGS, DOMAIN
+from .model import RainMachineEntityDescription
+
+
+@dataclass
+class RainMachineButtonDescriptionMixin:
+    """Define an entity description mixin for RainMachine buttons."""
+
+    push_action: Callable[[Controller], Awaitable]
+
+
+@dataclass
+class RainMachineButtonDescription(
+    ButtonEntityDescription,
+    RainMachineEntityDescription,
+    RainMachineButtonDescriptionMixin,
+):
+    """Describe a RainMachine button description."""
+
+
+BUTTON_KIND_REBOOT = "reboot"
+
+
+async def _async_reboot(controller: Controller) -> None:
+    """Reboot the RainMachine."""
+    await controller.machine.reboot()
+
+
+BUTTON_DESCRIPTIONS = (
+    RainMachineButtonDescription(
+        key=BUTTON_KIND_REBOOT,
+        name="Reboot",
+        api_category=DATA_PROVISION_SETTINGS,
+        push_action=_async_reboot,
+    ),
+)
+
+
+async def async_setup_entry(
+    hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
+) -> None:
+    """Set up RainMachine buttons based on a config entry."""
+    data: RainMachineData = hass.data[DOMAIN][entry.entry_id]
+
+    async_add_entities(
+        RainMachineButton(entry, data, description)
+        for description in BUTTON_DESCRIPTIONS
+    )
+
+
+class RainMachineButton(RainMachineEntity, ButtonEntity):
+    """Define a RainMachine button."""
+
+    _attr_device_class = ButtonDeviceClass.RESTART
+    _attr_entity_category = EntityCategory.CONFIG
+
+    entity_description: RainMachineButtonDescription
+
+    async def async_press(self) -> None:
+        """Send out a restart command."""
+        try:
+            await self.entity_description.push_action(self._data.controller)
+        except RainMachineError as err:
+            raise HomeAssistantError(
+                f'Error while pressing button "{self.entity_id}": {err}'
+            ) from err
+
+        async_dispatcher_send(self.hass, self.coordinator.signal_reboot_requested)
diff --git a/homeassistant/components/rainmachine/manifest.json b/homeassistant/components/rainmachine/manifest.json
index b318ef7f295e83e4f165de09c92de64afb49cc7f..4d60730ba6cde8db38f34b1a70e806e69702dd08 100644
--- a/homeassistant/components/rainmachine/manifest.json
+++ b/homeassistant/components/rainmachine/manifest.json
@@ -3,7 +3,7 @@
   "name": "RainMachine",
   "config_flow": true,
   "documentation": "https://www.home-assistant.io/integrations/rainmachine",
-  "requirements": ["regenmaschine==2022.07.1"],
+  "requirements": ["regenmaschine==2022.07.3"],
   "codeowners": ["@bachya"],
   "iot_class": "local_polling",
   "homekit": {
diff --git a/homeassistant/components/rainmachine/util.py b/homeassistant/components/rainmachine/util.py
index 6bf15f2fb9c5dd417c96d42e44e9c6d1c6cbc6fe..dc772690ec54163644685c3b57950778eb4f3a51 100644
--- a/homeassistant/components/rainmachine/util.py
+++ b/homeassistant/components/rainmachine/util.py
@@ -1,9 +1,23 @@
 """Define RainMachine utilities."""
 from __future__ import annotations
 
+from collections.abc import Awaitable, Callable
+from datetime import timedelta
 from typing import Any
 
 from homeassistant.backports.enum import StrEnum
+from homeassistant.config_entries import ConfigEntry
+from homeassistant.core import HomeAssistant, callback
+from homeassistant.helpers.dispatcher import (
+    async_dispatcher_connect,
+    async_dispatcher_send,
+)
+from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
+
+from .const import LOGGER
+
+SIGNAL_REBOOT_COMPLETED = "rainmachine_reboot_completed_{0}"
+SIGNAL_REBOOT_REQUESTED = "rainmachine_reboot_requested_{0}"
 
 
 class RunStates(StrEnum):
@@ -29,3 +43,82 @@ def key_exists(data: dict[str, Any], search_key: str) -> bool:
         if isinstance(value, dict):
             return key_exists(value, search_key)
     return False
+
+
+class RainMachineDataUpdateCoordinator(DataUpdateCoordinator[dict]):
+    """Define an extended DataUpdateCoordinator."""
+
+    config_entry: ConfigEntry
+
+    def __init__(
+        self,
+        hass: HomeAssistant,
+        *,
+        entry: ConfigEntry,
+        name: str,
+        api_category: str,
+        update_interval: timedelta,
+        update_method: Callable[..., Awaitable],
+    ) -> None:
+        """Initialize."""
+        super().__init__(
+            hass,
+            LOGGER,
+            name=name,
+            update_interval=update_interval,
+            update_method=update_method,
+        )
+
+        self._rebooting = False
+        self._signal_handler_unsubs: list[Callable[..., None]] = []
+        self.config_entry = entry
+        self.signal_reboot_completed = SIGNAL_REBOOT_COMPLETED.format(
+            self.config_entry.entry_id
+        )
+        self.signal_reboot_requested = SIGNAL_REBOOT_REQUESTED.format(
+            self.config_entry.entry_id
+        )
+
+    async def async_initialize(self) -> None:
+        """Initialize the coordinator."""
+
+        @callback
+        def async_reboot_completed() -> None:
+            """Respond to a reboot completed notification."""
+            LOGGER.debug("%s responding to reboot complete", self.name)
+            self._rebooting = False
+            self.last_update_success = True
+            self.async_update_listeners()
+
+        @callback
+        def async_reboot_requested() -> None:
+            """Respond to a reboot request."""
+            LOGGER.debug("%s responding to reboot request", self.name)
+            self._rebooting = True
+            self.last_update_success = False
+            self.async_update_listeners()
+
+        for signal, func in (
+            (self.signal_reboot_completed, async_reboot_completed),
+            (self.signal_reboot_requested, async_reboot_requested),
+        ):
+            self._signal_handler_unsubs.append(
+                async_dispatcher_connect(self.hass, signal, func)
+            )
+
+        @callback
+        def async_check_reboot_complete() -> None:
+            """Check whether an active reboot has been completed."""
+            if self._rebooting and self.last_update_success:
+                LOGGER.debug("%s discovered reboot complete", self.name)
+                async_dispatcher_send(self.hass, self.signal_reboot_completed)
+
+        self.async_add_listener(async_check_reboot_complete)
+
+        @callback
+        def async_teardown() -> None:
+            """Tear the coordinator down appropriately."""
+            for unsub in self._signal_handler_unsubs:
+                unsub()
+
+        self.config_entry.async_on_unload(async_teardown)
diff --git a/requirements_all.txt b/requirements_all.txt
index c1badeb18deb9849315e5e2a3a1ec39564a5dc31..3abb34ff5dad9f6b933ca9f42579c343d4ffbb0c 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -2081,7 +2081,7 @@ raincloudy==0.0.7
 raspyrfm-client==1.2.8
 
 # homeassistant.components.rainmachine
-regenmaschine==2022.07.1
+regenmaschine==2022.07.3
 
 # homeassistant.components.renault
 renault-api==0.1.11
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index 7ef2f0ff1b037240875e60562d0dfb64e1205e96..96845b12579c9b51eee13e6f649d94ee2a9e45f2 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -1402,7 +1402,7 @@ radios==0.1.1
 radiotherm==2.1.0
 
 # homeassistant.components.rainmachine
-regenmaschine==2022.07.1
+regenmaschine==2022.07.3
 
 # homeassistant.components.renault
 renault-api==0.1.11