diff --git a/homeassistant/components/lifx/__init__.py b/homeassistant/components/lifx/__init__.py
index 9d4e2d5facff9f4358b7cfd99a8cb7bc94ae18ab..ec54382ec40e7fb1c010e034d7c679f5581d2acc 100644
--- a/homeassistant/components/lifx/__init__.py
+++ b/homeassistant/components/lifx/__init__.py
@@ -57,7 +57,7 @@ CONFIG_SCHEMA = vol.All(
 )
 
 
-PLATFORMS = [Platform.LIGHT]
+PLATFORMS = [Platform.BUTTON, Platform.LIGHT]
 DISCOVERY_INTERVAL = timedelta(minutes=15)
 MIGRATION_INTERVAL = timedelta(minutes=5)
 
@@ -173,7 +173,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
 
 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
     """Set up LIFX from a config entry."""
-
     if async_entry_is_legacy(entry):
         return True
 
diff --git a/homeassistant/components/lifx/button.py b/homeassistant/components/lifx/button.py
new file mode 100644
index 0000000000000000000000000000000000000000..6d3f4fe51bf38f3082ce7b43b97d5e9e785add1f
--- /dev/null
+++ b/homeassistant/components/lifx/button.py
@@ -0,0 +1,77 @@
+"""Button entity for LIFX devices.."""
+from __future__ import annotations
+
+from homeassistant.components.button import (
+    ButtonDeviceClass,
+    ButtonEntity,
+    ButtonEntityDescription,
+)
+from homeassistant.config_entries import ConfigEntry
+from homeassistant.core import HomeAssistant
+from homeassistant.helpers.entity import EntityCategory
+from homeassistant.helpers.entity_platform import AddEntitiesCallback
+
+from .const import DOMAIN, IDENTIFY, RESTART
+from .coordinator import LIFXUpdateCoordinator
+from .entity import LIFXEntity
+
+RESTART_BUTTON_DESCRIPTION = ButtonEntityDescription(
+    key=RESTART,
+    name="Restart",
+    device_class=ButtonDeviceClass.RESTART,
+    entity_registry_enabled_default=False,
+    entity_category=EntityCategory.DIAGNOSTIC,
+)
+
+IDENTIFY_BUTTON_DESCRIPTION = ButtonEntityDescription(
+    key=IDENTIFY,
+    name="Identify",
+    entity_registry_enabled_default=False,
+    entity_category=EntityCategory.DIAGNOSTIC,
+)
+
+
+async def async_setup_entry(
+    hass: HomeAssistant,
+    entry: ConfigEntry,
+    async_add_entities: AddEntitiesCallback,
+) -> None:
+    """Set up LIFX from a config entry."""
+    domain_data = hass.data[DOMAIN]
+    coordinator: LIFXUpdateCoordinator = domain_data[entry.entry_id]
+    async_add_entities(
+        cls(coordinator) for cls in (LIFXRestartButton, LIFXIdentifyButton)
+    )
+
+
+class LIFXButton(LIFXEntity, ButtonEntity):
+    """Base LIFX button."""
+
+    _attr_has_entity_name: bool = True
+
+    def __init__(self, coordinator: LIFXUpdateCoordinator) -> None:
+        """Initialise a LIFX button."""
+        super().__init__(coordinator)
+        self._attr_unique_id = (
+            f"{coordinator.serial_number}_{self.entity_description.key}"
+        )
+
+
+class LIFXRestartButton(LIFXButton):
+    """LIFX restart button."""
+
+    entity_description = RESTART_BUTTON_DESCRIPTION
+
+    async def async_press(self) -> None:
+        """Restart the bulb on button press."""
+        self.bulb.set_reboot()
+
+
+class LIFXIdentifyButton(LIFXButton):
+    """LIFX identify button."""
+
+    entity_description = IDENTIFY_BUTTON_DESCRIPTION
+
+    async def async_press(self) -> None:
+        """Identify the bulb by flashing it when the button is pressed."""
+        await self.coordinator.async_identify_bulb()
diff --git a/homeassistant/components/lifx/const.py b/homeassistant/components/lifx/const.py
index ec756c2091fe17034bba6ad073792c51f000f78c..f6ec653c994c4ffcffdb284b9345f7302bca01ea 100644
--- a/homeassistant/components/lifx/const.py
+++ b/homeassistant/components/lifx/const.py
@@ -14,6 +14,21 @@ UNAVAILABLE_GRACE = 90
 
 CONF_SERIAL = "serial"
 
+IDENTIFY_WAVEFORM = {
+    "transient": True,
+    "color": [0, 0, 1, 3500],
+    "skew_ratio": 0,
+    "period": 1000,
+    "cycles": 3,
+    "waveform": 1,
+    "set_hue": True,
+    "set_saturation": True,
+    "set_brightness": True,
+    "set_kelvin": True,
+}
+IDENTIFY = "identify"
+RESTART = "restart"
+
 DATA_LIFX_MANAGER = "lifx_manager"
 
 _LOGGER = logging.getLogger(__name__)
diff --git a/homeassistant/components/lifx/coordinator.py b/homeassistant/components/lifx/coordinator.py
index bb3dd60b32609a02b4cf938ed5bf5ea799ecda1d..1f3f49368ca73f6431c47cfa5b146fb2065b77b8 100644
--- a/homeassistant/components/lifx/coordinator.py
+++ b/homeassistant/components/lifx/coordinator.py
@@ -4,7 +4,7 @@ from __future__ import annotations
 import asyncio
 from datetime import timedelta
 from functools import partial
-from typing import cast
+from typing import Any, cast
 
 from aiolifx.aiolifx import Light
 from aiolifx.connection import LIFXConnection
@@ -15,6 +15,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda
 
 from .const import (
     _LOGGER,
+    IDENTIFY_WAVEFORM,
     MESSAGE_RETRIES,
     MESSAGE_TIMEOUT,
     TARGET_ANY,
@@ -75,6 +76,24 @@ class LIFXUpdateCoordinator(DataUpdateCoordinator):
             self.device.host_firmware_version,
         )
 
+    @property
+    def label(self) -> str:
+        """Return the label of the bulb."""
+        return cast(str, self.device.label)
+
+    async def async_identify_bulb(self) -> None:
+        """Identify the device by flashing it three times."""
+        bulb: Light = self.device
+        if bulb.power_level:
+            # just flash the bulb for three seconds
+            await self.async_set_waveform_optional(value=IDENTIFY_WAVEFORM)
+            return
+        # Turn the bulb on first, flash for 3 seconds, then turn off
+        await self.async_set_power(state=True, duration=1)
+        await self.async_set_waveform_optional(value=IDENTIFY_WAVEFORM)
+        await asyncio.sleep(3)
+        await self.async_set_power(state=False, duration=1)
+
     async def _async_update_data(self) -> None:
         """Fetch all device data from the api."""
         async with self.lock:
@@ -119,6 +138,14 @@ class LIFXUpdateCoordinator(DataUpdateCoordinator):
             if zone == top - 1:
                 zone -= 1
 
+    async def async_set_waveform_optional(
+        self, value: dict[str, Any], rapid: bool = False
+    ) -> None:
+        """Send a set_waveform_optional message to the device."""
+        await async_execute_lifx(
+            partial(self.device.set_waveform_optional, value=value, rapid=rapid)
+        )
+
     async def async_get_color(self) -> None:
         """Send a get color message to the device."""
         await async_execute_lifx(self.device.get_color)
diff --git a/homeassistant/components/lifx/entity.py b/homeassistant/components/lifx/entity.py
new file mode 100644
index 0000000000000000000000000000000000000000..0007ab998a96abb93cb070d1050adf92bec99a13
--- /dev/null
+++ b/homeassistant/components/lifx/entity.py
@@ -0,0 +1,28 @@
+"""Support for LIFX lights."""
+from __future__ import annotations
+
+from aiolifx import products
+
+from homeassistant.helpers import device_registry as dr
+from homeassistant.helpers.entity import DeviceInfo
+from homeassistant.helpers.update_coordinator import CoordinatorEntity
+
+from .const import DOMAIN
+from .coordinator import LIFXUpdateCoordinator
+
+
+class LIFXEntity(CoordinatorEntity[LIFXUpdateCoordinator]):
+    """Representation of a LIFX entity with a coordinator."""
+
+    def __init__(self, coordinator: LIFXUpdateCoordinator) -> None:
+        """Initialise the light."""
+        super().__init__(coordinator)
+        self.bulb = coordinator.device
+        self._attr_device_info = DeviceInfo(
+            identifiers={(DOMAIN, coordinator.serial_number)},
+            connections={(dr.CONNECTION_NETWORK_MAC, coordinator.mac_address)},
+            manufacturer="LIFX",
+            name=coordinator.label,
+            model=products.product_map.get(self.bulb.product, "LIFX Bulb"),
+            sw_version=self.bulb.host_firmware_version,
+        )
diff --git a/homeassistant/components/lifx/light.py b/homeassistant/components/lifx/light.py
index 28a678d5e8f6925ffc11d495a4a6b84a9814dc64..67bb3e91748d75cd5eec79c44e4ebb022c471c0c 100644
--- a/homeassistant/components/lifx/light.py
+++ b/homeassistant/components/lifx/light.py
@@ -6,7 +6,6 @@ from datetime import datetime, timedelta
 import math
 from typing import Any
 
-from aiolifx import products
 import aiolifx_effects as aiolifx_effects_module
 import voluptuous as vol
 
@@ -20,20 +19,18 @@ from homeassistant.components.light import (
     LightEntityFeature,
 )
 from homeassistant.config_entries import ConfigEntry
-from homeassistant.const import ATTR_ENTITY_ID, ATTR_MODEL, ATTR_SW_VERSION
+from homeassistant.const import ATTR_ENTITY_ID
 from homeassistant.core import CALLBACK_TYPE, HomeAssistant
 from homeassistant.exceptions import HomeAssistantError
 from homeassistant.helpers import entity_platform
 import homeassistant.helpers.config_validation as cv
-import homeassistant.helpers.device_registry as dr
-from homeassistant.helpers.entity import DeviceInfo
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
 from homeassistant.helpers.event import async_track_point_in_utc_time
-from homeassistant.helpers.update_coordinator import CoordinatorEntity
 import homeassistant.util.color as color_util
 
 from .const import DATA_LIFX_MANAGER, DOMAIN
 from .coordinator import LIFXUpdateCoordinator
+from .entity import LIFXEntity
 from .manager import (
     SERVICE_EFFECT_COLORLOOP,
     SERVICE_EFFECT_PULSE,
@@ -92,7 +89,7 @@ async def async_setup_entry(
     async_add_entities([entity])
 
 
-class LIFXLight(CoordinatorEntity[LIFXUpdateCoordinator], LightEntity):
+class LIFXLight(LIFXEntity, LightEntity):
     """Representation of a LIFX light."""
 
     _attr_supported_features = LightEntityFeature.TRANSITION | LightEntityFeature.EFFECT
@@ -105,10 +102,9 @@ class LIFXLight(CoordinatorEntity[LIFXUpdateCoordinator], LightEntity):
     ) -> None:
         """Initialize the light."""
         super().__init__(coordinator)
-        bulb = coordinator.device
-        self.mac_addr = bulb.mac_addr
-        self.bulb = bulb
-        bulb_features = lifx_features(bulb)
+
+        self.mac_addr = self.bulb.mac_addr
+        bulb_features = lifx_features(self.bulb)
         self.manager = manager
         self.effects_conductor: aiolifx_effects_module.Conductor = (
             manager.effects_conductor
@@ -116,25 +112,13 @@ class LIFXLight(CoordinatorEntity[LIFXUpdateCoordinator], LightEntity):
         self.postponed_update: CALLBACK_TYPE | None = None
         self.entry = entry
         self._attr_unique_id = self.coordinator.serial_number
-        self._attr_name = bulb.label
+        self._attr_name = self.bulb.label
         self._attr_min_mireds = math.floor(
             color_util.color_temperature_kelvin_to_mired(bulb_features["max_kelvin"])
         )
         self._attr_max_mireds = math.ceil(
             color_util.color_temperature_kelvin_to_mired(bulb_features["min_kelvin"])
         )
-        info = DeviceInfo(
-            identifiers={(DOMAIN, coordinator.serial_number)},
-            connections={(dr.CONNECTION_NETWORK_MAC, coordinator.mac_address)},
-            manufacturer="LIFX",
-            name=self.name,
-        )
-        _map = products.product_map
-        if (model := (_map.get(bulb.product) or bulb.product)) is not None:
-            info[ATTR_MODEL] = str(model)
-        if (version := bulb.host_firmware_version) is not None:
-            info[ATTR_SW_VERSION] = version
-        self._attr_device_info = info
         if bulb_features["min_kelvin"] != bulb_features["max_kelvin"]:
             color_mode = ColorMode.COLOR_TEMP
         else:
diff --git a/tests/components/lifx/__init__.py b/tests/components/lifx/__init__.py
index fdea992c87d6f9f6e07c0cc4fc1fa93526535837..8259314e77c2e4a466aeb12078ee3b24d7bb8ad3 100644
--- a/tests/components/lifx/__init__.py
+++ b/tests/components/lifx/__init__.py
@@ -3,7 +3,7 @@ from __future__ import annotations
 
 import asyncio
 from contextlib import contextmanager
-from unittest.mock import AsyncMock, MagicMock, patch
+from unittest.mock import AsyncMock, MagicMock, Mock, patch
 
 from aiolifx.aiolifx import Light
 
@@ -72,6 +72,8 @@ def _mocked_bulb() -> Light:
     bulb.label = LABEL
     bulb.color = [1, 2, 3, 4]
     bulb.power_level = 0
+    bulb.fire_and_forget = AsyncMock()
+    bulb.set_reboot = Mock()
     bulb.try_sending = AsyncMock()
     bulb.set_infrared = MockLifxCommand(bulb)
     bulb.get_color = MockLifxCommand(bulb)
@@ -79,6 +81,7 @@ def _mocked_bulb() -> Light:
     bulb.set_color = MockLifxCommand(bulb)
     bulb.get_hostfirmware = MockLifxCommand(bulb)
     bulb.get_version = MockLifxCommand(bulb)
+    bulb.set_waveform_optional = MockLifxCommand(bulb)
     bulb.product = 1  # LIFX Original 1000
     return bulb
 
diff --git a/tests/components/lifx/test_button.py b/tests/components/lifx/test_button.py
new file mode 100644
index 0000000000000000000000000000000000000000..a485c882100a965b1c1f4c1cc2770f2532b3c2aa
--- /dev/null
+++ b/tests/components/lifx/test_button.py
@@ -0,0 +1,132 @@
+"""Tests for button platform."""
+from homeassistant.components import lifx
+from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN
+from homeassistant.components.lifx.const import DOMAIN
+from homeassistant.const import ATTR_ENTITY_ID, CONF_HOST
+from homeassistant.core import HomeAssistant
+from homeassistant.helpers import entity_registry as er
+from homeassistant.setup import async_setup_component
+
+from . import (
+    DEFAULT_ENTRY_TITLE,
+    IP_ADDRESS,
+    MAC_ADDRESS,
+    SERIAL,
+    _mocked_bulb,
+    _patch_config_flow_try_connect,
+    _patch_device,
+    _patch_discovery,
+)
+
+from tests.common import MockConfigEntry
+
+
+async def test_button_restart(hass: HomeAssistant) -> None:
+    """Test that a bulb can be restarted."""
+    config_entry = MockConfigEntry(
+        domain=DOMAIN,
+        title=DEFAULT_ENTRY_TITLE,
+        data={CONF_HOST: IP_ADDRESS},
+        unique_id=MAC_ADDRESS,
+    )
+    config_entry.add_to_hass(hass)
+    bulb = _mocked_bulb()
+    with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
+        device=bulb
+    ), _patch_device(device=bulb):
+        await async_setup_component(hass, lifx.DOMAIN, {lifx.DOMAIN: {}})
+        await hass.async_block_till_done()
+
+    unique_id = f"{SERIAL}_restart"
+    entity_id = "button.my_bulb_restart"
+
+    entity_registry = er.async_get(hass)
+    entity = entity_registry.async_get(entity_id)
+    assert entity
+    assert entity.disabled
+    assert entity.unique_id == unique_id
+
+    enabled_entity = entity_registry.async_update_entity(entity_id, disabled_by=None)
+    assert not enabled_entity.disabled
+
+    with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
+        device=bulb
+    ), _patch_device(device=bulb):
+        await hass.config_entries.async_reload(config_entry.entry_id)
+        await hass.async_block_till_done()
+
+    await hass.services.async_call(
+        BUTTON_DOMAIN, "press", {ATTR_ENTITY_ID: entity_id}, blocking=True
+    )
+
+    bulb.set_reboot.assert_called_once()
+
+
+async def test_button_identify(hass: HomeAssistant) -> None:
+    """Test that a bulb can be identified."""
+    config_entry = MockConfigEntry(
+        domain=DOMAIN,
+        title=DEFAULT_ENTRY_TITLE,
+        data={CONF_HOST: IP_ADDRESS},
+        unique_id=MAC_ADDRESS,
+    )
+    config_entry.add_to_hass(hass)
+    bulb = _mocked_bulb()
+    with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
+        device=bulb
+    ), _patch_device(device=bulb):
+        await async_setup_component(hass, lifx.DOMAIN, {lifx.DOMAIN: {}})
+        await hass.async_block_till_done()
+
+    unique_id = f"{SERIAL}_identify"
+    entity_id = "button.my_bulb_identify"
+
+    entity_registry = er.async_get(hass)
+    entity = entity_registry.async_get(entity_id)
+    assert entity
+    assert entity.disabled
+    assert entity.unique_id == unique_id
+
+    enabled_entity = entity_registry.async_update_entity(entity_id, disabled_by=None)
+    assert not enabled_entity.disabled
+
+    with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
+        device=bulb
+    ), _patch_device(device=bulb):
+        await hass.config_entries.async_reload(config_entry.entry_id)
+        await hass.async_block_till_done()
+
+    await hass.services.async_call(
+        BUTTON_DOMAIN, "press", {ATTR_ENTITY_ID: entity_id}, blocking=True
+    )
+
+    assert len(bulb.set_power.calls) == 2
+
+    waveform_call_dict = bulb.set_waveform_optional.calls[0][1]
+    waveform_call_dict.pop("callb")
+    assert waveform_call_dict == {
+        "rapid": False,
+        "value": {
+            "transient": True,
+            "color": [0, 0, 1, 3500],
+            "skew_ratio": 0,
+            "period": 1000,
+            "cycles": 3,
+            "waveform": 1,
+            "set_hue": True,
+            "set_saturation": True,
+            "set_brightness": True,
+            "set_kelvin": True,
+        },
+    }
+
+    bulb.set_power.reset_mock()
+    bulb.set_waveform_optional.reset_mock()
+    bulb.power_level = 65535
+
+    await hass.services.async_call(
+        BUTTON_DOMAIN, "press", {ATTR_ENTITY_ID: entity_id}, blocking=True
+    )
+
+    assert len(bulb.set_waveform_optional.calls) == 1
+    assert len(bulb.set_power.calls) == 0