"""Devices API endpoints.

This file is automatically @generated from the Meraki API specification.
Do not edit this file manually.

"""

from __future__ import annotations

import urllib.parse
from typing import TYPE_CHECKING, Any

from meraki_client.schemas import (
    BlinkDeviceLedsResponse,
    CreateDeviceLiveToolsArpTableCallback,
    CreateDeviceLiveToolsArpTableResponse,
    CreateDeviceLiveToolsCableTestCallback,
    CreateDeviceLiveToolsCableTestResponse,
    CreateDeviceLiveToolsLedsBlinkCallback,
    CreateDeviceLiveToolsLedsBlinkResponse,
    CreateDeviceLiveToolsMacTableCallback,
    CreateDeviceLiveToolsMacTableResponse,
    CreateDeviceLiveToolsMulticastRoutingCallback,
    CreateDeviceLiveToolsMulticastRoutingResponse,
    CreateDeviceLiveToolsPingCallback,
    CreateDeviceLiveToolsPingDeviceCallback,
    CreateDeviceLiveToolsPingDeviceResponse,
    CreateDeviceLiveToolsPingResponse,
    CreateDeviceLiveToolsThroughputTestCallback,
    CreateDeviceLiveToolsThroughputTestResponse,
    CreateDeviceLiveToolsWakeOnLanCallback,
    CreateDeviceLiveToolsWakeOnLanResponse,
    GetDeviceCellularSimsResponse,
    GetDeviceClientsResponseItem,
    GetDeviceLiveToolsArpTableResponse,
    GetDeviceLiveToolsCableTestResponse,
    GetDeviceLiveToolsLedsBlinkResponse,
    GetDeviceLiveToolsMacTableResponse,
    GetDeviceLiveToolsMulticastRoutingResponse,
    GetDeviceLiveToolsPingDeviceResponse,
    GetDeviceLiveToolsPingResponse,
    GetDeviceLiveToolsThroughputTestResponse,
    GetDeviceLiveToolsWakeOnLanResponse,
    GetDeviceLldpCdpResponse,
    GetDeviceLossAndLatencyHistoryResponseItem,
    GetDeviceManagementInterfaceResponse,
    GetDeviceResponse,
    RebootDeviceResponse,
    UpdateDeviceCellularSimsResponse,
    UpdateDeviceCellularSimsSimFailover,
    UpdateDeviceCellularSimsSimsItem,
    UpdateDeviceManagementInterfaceResponse,
    UpdateDeviceManagementInterfaceWan1,
    UpdateDeviceManagementInterfaceWan2,
    UpdateDeviceResponse,
)
from meraki_client.types import (
    GetDeviceLossAndLatencyHistoryUplink,
)

if TYPE_CHECKING:
    from meraki_client._session import PaginatedResponse, Session


class Devices:
    """Devices class."""

    def __init__(self, session: Session) -> None:
        self._session = session

    def get_device(self, serial: str) -> GetDeviceResponse:
        """Return a single device.

        [API documentation: getDevice](https://developer.cisco.com/meraki/api-v1/#!get-device)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "name": "My AP",
              "lat": 37.4180951010362,
              "lng": -122.098531723022,
              "address": "1600 Pennsylvania Ave",
              "notes": "My AP's note",
              "tags": [
                " recently-added "
              ],
              "networkId": "N_24329156",
              "serial": "Q234-ABCD-5678",
              "model": "MR34",
              "mac": "00:11:22:33:44:55",
              "lanIp": "1.2.3.4",
              "firmware": "wireless-25-14",
              "floorPlanId": "g_2176982374",
              "details": [
                {
                  "name": "Catalyst serial",
                  "value": "123ABC"
                }
              ],
              "beaconIdParams": {
                "uuid": "00000000-0000-0000-0000-000000000000",
                "major": 5,
                "minor": 3
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}"

        return self._session.get(
            scope="devices", operation_id="getDevice", path=path, response_schema=GetDeviceResponse
        )

    def update_device(
        self,
        serial: str,
        *,
        name: str | None = None,
        tags: list[str] | None = None,
        lat: float | None = None,
        lng: float | None = None,
        address: str | None = None,
        notes: str | None = None,
        move_map_marker: bool | None = None,
        switch_profile_id: str | None = None,
        floor_plan_id: str | None = None,
    ) -> UpdateDeviceResponse:
        """Update the attributes of a device.

        [API documentation: updateDevice](https://developer.cisco.com/meraki/api-v1/#!update-device)

        Args:
            serial: Serial.
            name: The name of a device.
            tags: The list of tags of a device.
            lat: The latitude of a device.
            lng: The longitude of a device.
            address: The address of a device.
            notes: The notes for the device. String. Limited to 255 characters.
            move_map_marker: Whether or not to set the latitude and longitude of a device based on
                the new address. Only applies when lat and lng are not specified.
            switch_profile_id: The ID of a switch template to bind to the device (for available
                switch templates, see the 'Switch Templates' endpoint). Use null to
                unbind the switch device from the current profile. For a device to be
                bindable to a switch template, it must (1) be a switch, and (2) belong
                to a network that is bound to a configuration template.
            floor_plan_id: The floor plan to associate to this device. null disassociates the device
                from the floorplan.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "name": "My AP",
              "lat": 37.4180951010362,
              "lng": -122.098531723022,
              "address": "1600 Pennsylvania Ave",
              "notes": "My AP's note",
              "tags": [
                " recently-added "
              ],
              "networkId": "N_24329156",
              "serial": "Q234-ABCD-5678",
              "model": "MR34",
              "mac": "00:11:22:33:44:55",
              "lanIp": "1.2.3.4",
              "firmware": "wireless-25-14",
              "floorPlanId": "g_2176982374",
              "details": [
                {
                  "name": "Catalyst serial",
                  "value": "123ABC"
                }
              ],
              "beaconIdParams": {
                "uuid": "00000000-0000-0000-0000-000000000000",
                "major": 5,
                "minor": 3
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if tags is not None:
            payload["tags"] = tags
        if lat is not None:
            payload["lat"] = lat
        if lng is not None:
            payload["lng"] = lng
        if address is not None:
            payload["address"] = address
        if notes is not None:
            payload["notes"] = notes
        if move_map_marker is not None:
            payload["moveMapMarker"] = move_map_marker
        if switch_profile_id is not None:
            payload["switchProfileId"] = switch_profile_id
        if floor_plan_id is not None:
            payload["floorPlanId"] = floor_plan_id

        return self._session.put(
            scope="devices",
            operation_id="updateDevice",
            path=path,
            json=payload,
            response_schema=UpdateDeviceResponse,
        )

    def blink_device_leds(
        self,
        serial: str,
        *,
        duration: int | None = None,
        period: int | None = None,
        duty: int | None = None,
    ) -> BlinkDeviceLedsResponse:
        """Blink the LEDs on a device.

        [API documentation: blinkDeviceLeds](https://developer.cisco.com/meraki/api-v1/#!blink-device-leds)

        Args:
            serial: Serial.
            duration: The duration in seconds. Must be between 5 and 120. Default is 20 seconds.
            period: The period in milliseconds. Must be between 100 and 1000. Default is 160
                milliseconds.
            duty: The duty cycle as the percent active. Must be between 10 and 90. Default is 50.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "duration": 20,
              "period": 160,
              "duty": 50
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/blinkLeds"

        payload: dict[str, Any] = {}
        if duration is not None:
            payload["duration"] = duration
        if period is not None:
            payload["period"] = period
        if duty is not None:
            payload["duty"] = duty

        return self._session.post(
            scope="devices",
            operation_id="blinkDeviceLeds",
            path=path,
            json=payload,
            response_schema=BlinkDeviceLedsResponse,
        )

    def get_device_cellular_sims(self, serial: str) -> GetDeviceCellularSimsResponse:
        """Return the SIM and APN configurations for a cellular device.

        [API documentation: getDeviceCellularSims](https://developer.cisco.com/meraki/api-v1/#!get-device-cellular-sims)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "sims": [
                {
                  "slot": "sim1",
                  "iccid": "123456789",
                  "imsi": "123456789012345",
                  "msisdn": "123456789012345",
                  "isPrimary": false,
                  "status": "inserted",
                  "apns": [
                    {
                      "name": "internet",
                      "allowedIpTypes": [
                        "ipv4",
                        "ipv6"
                      ],
                      "authentication": {
                        "type": "pap",
                        "username": "milesmeraki",
                        "password": "secret"
                      }
                    }
                  ]
                }
              ],
              "simOrdering": [
                "sim1",
                "sim2",
                "sim3"
              ],
              "simFailover": {
                "enabled": true,
                "timeout": 300
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/cellular/sims"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceCellularSims",
            path=path,
            response_schema=GetDeviceCellularSimsResponse,
        )

    def update_device_cellular_sims(
        self,
        serial: str,
        *,
        sims: list[UpdateDeviceCellularSimsSimsItem] | None = None,
        sim_ordering: list[str] | None = None,
        sim_failover: UpdateDeviceCellularSimsSimFailover | None = None,
    ) -> UpdateDeviceCellularSimsResponse:
        """Updates the SIM and APN configurations for a cellular device.

        [API documentation: updateDeviceCellularSims](https://developer.cisco.com/meraki/api-v1/#!update-device-cellular-sims)

        Args:
            serial: Serial.
            sims: List of SIMs. If a SIM was previously configured and not specified in this
                request, it will remain unchanged.
            sim_ordering: Specifies the ordering of all SIMs for an MG: primary, secondary, and not-
                in-use (when applicable). It's required for devices with 3 or more SIMs
                and can be used in place of 'isPrimary' for dual-SIM devices. To
                indicate eSIM, use 'sim3'. Sim failover will occur only between primary
                and secondary sim slots.
            sim_failover: SIM Failover settings.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "sims": [
                {
                  "slot": "sim1",
                  "iccid": "123456789",
                  "imsi": "123456789012345",
                  "msisdn": "123456789012345",
                  "isPrimary": false,
                  "status": "inserted",
                  "apns": [
                    {
                      "name": "internet",
                      "allowedIpTypes": [
                        "ipv4",
                        "ipv6"
                      ],
                      "authentication": {
                        "type": "pap",
                        "username": "milesmeraki",
                        "password": "secret"
                      }
                    }
                  ]
                }
              ],
              "simOrdering": [
                "sim1",
                "sim2",
                "sim3"
              ],
              "simFailover": {
                "enabled": true,
                "timeout": 300
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/cellular/sims"

        payload: dict[str, Any] = {}
        if sims is not None:
            payload["sims"] = [item.model_dump(by_alias=True, exclude_none=True) for item in sims]
        if sim_ordering is not None:
            payload["simOrdering"] = sim_ordering
        if sim_failover is not None:
            payload["simFailover"] = sim_failover.model_dump(by_alias=True, exclude_none=True)

        return self._session.put(
            scope="devices",
            operation_id="updateDeviceCellularSims",
            path=path,
            json=payload,
            response_schema=UpdateDeviceCellularSimsResponse,
        )

    def get_device_clients(
        self, serial: str, *, t0: str | None = None, timespan: float | None = None
    ) -> PaginatedResponse[GetDeviceClientsResponseItem]:
        """List the clients of a device, up to a maximum of a month ago.

        [API documentation: getDeviceClients](https://developer.cisco.com/meraki/api-v1/#!get-device-clients)

        Args:
            serial: Serial.
            t0: The beginning of the timespan for the data. The maximum lookback period is 31 days
                from today.
            timespan: The timespan for which the information will be fetched. If specifying
                timespan, do not specify parameter t0. The value must be in seconds and
                be less than or equal to 31 days. The default is 1 day.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "id": "k74272e",
                "mac": "22:33:44:55:66:77",
                "description": "Miles's phone",
                "mdnsName": "Miles's phone",
                "dhcpHostname": "MilesPhone",
                "user": "milesmeraki",
                "ip": "1.2.3.4",
                "vlan": "100",
                "namedVlan": "My VLAN",
                "switchport": "My switch port",
                "adaptivePolicyGroup": "101",
                "usage": {
                  "sent": 138.0,
                  "recv": 61.0
                }
              }
            ]
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/clients"

        params: dict[str, Any] = {}
        if t0 is not None:
            params["t0"] = t0
        if timespan is not None:
            params["timespan"] = timespan

        return self._session.get_pages(
            scope="devices",
            operation_id="getDeviceClients",
            path=path,
            params=params,
            item_schema=GetDeviceClientsResponseItem,
        )

    def create_device_live_tools_arp_table(
        self, serial: str, *, callback: CreateDeviceLiveToolsArpTableCallback | None = None
    ) -> CreateDeviceLiveToolsArpTableResponse:
        """Enqueue a job to perform a ARP table request for the device.

        [API documentation: createDeviceLiveToolsArpTable](https://developer.cisco.com/meraki/api-v1/#!create-device-live-tools-arp-table)

        Args:
            serial: Serial.
            callback: Details for the callback. Please include either an httpServerId OR url and
                sharedSecret.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "arpTableId": "1284392014819",
              "url": "/devices/Q234-ABCD-5678/liveTools/arpTable/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678"
              },
              "status": "complete",
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/liveTools/arpTable"

        payload: dict[str, Any] = {}
        if callback is not None:
            payload["callback"] = callback.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="devices",
            operation_id="createDeviceLiveToolsArpTable",
            path=path,
            json=payload,
            response_schema=CreateDeviceLiveToolsArpTableResponse,
        )

    def get_device_live_tools_arp_table(
        self, *, serial: str, arp_table_id: str
    ) -> GetDeviceLiveToolsArpTableResponse:
        """Return an ARP table live tool job.

        [API documentation: getDeviceLiveToolsArpTable](https://developer.cisco.com/meraki/api-v1/#!get-device-live-tools-arp-table)

        Args:
            serial: Serial.
            arp_table_id: Arp table ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "arpTableId": "1284392014819",
              "url": "/devices/Q234-ABCD-5678/liveTools/arpTable/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678"
              },
              "status": "complete",
              "entries": [
                {
                  "ip": "10.0.0.0/24",
                  "mac": "00:11:22:33:44:55",
                  "vlanId": 100,
                  "interface": "Vlan100",
                  "lastUpdatedAt": "2018-02-11T00:00:00.090210Z"
                }
              ],
              "error": "The device is unreachable."
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        arp_table_id = urllib.parse.quote(str(arp_table_id), safe="")
        path = f"/devices/{serial}/liveTools/arpTable/{arp_table_id}"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLiveToolsArpTable",
            path=path,
            response_schema=GetDeviceLiveToolsArpTableResponse,
        )

    def create_device_live_tools_cable_test(
        self,
        *,
        serial: str,
        ports: list[str],
        callback: CreateDeviceLiveToolsCableTestCallback | None = None,
    ) -> CreateDeviceLiveToolsCableTestResponse:
        """Enqueue a job to perform a cable test for the device on the specified ports.

        [API documentation: createDeviceLiveToolsCableTest](https://developer.cisco.com/meraki/api-v1/#!create-device-live-tools-cable-test)

        Args:
            serial: Serial.
            ports: A list of ports for which to perform the cable test. For Catalyst switches, IOS
                interface names are also supported, such as "GigabitEthernet1/0/8",
                "Gi1/0/8", or even "1/0/8".
            callback: Details for the callback. Please include either an httpServerId OR url and
                sharedSecret.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "cableTestId": "1284392014819",
              "url": "/devices/Q234-ABCD-5678/liveTools/cableTest/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678",
                "ports": [
                  "2",
                  "8"
                ]
              },
              "status": "complete",
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/liveTools/cableTest"

        payload: dict[str, Any] = {}
        if ports is not None:
            payload["ports"] = ports
        if callback is not None:
            payload["callback"] = callback.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="devices",
            operation_id="createDeviceLiveToolsCableTest",
            path=path,
            json=payload,
            response_schema=CreateDeviceLiveToolsCableTestResponse,
        )

    def get_device_live_tools_cable_test(
        self, *, serial: str, id: str
    ) -> GetDeviceLiveToolsCableTestResponse:
        """Return a cable test live tool job.

        [API documentation: getDeviceLiveToolsCableTest](https://developer.cisco.com/meraki/api-v1/#!get-device-live-tools-cable-test)

        Args:
            serial: Serial.
            id: ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "cableTestId": "1284392014819",
              "url": "/devices/Q234-ABCD-5678/liveTools/cableTest/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678",
                "ports": [
                  "2",
                  "8"
                ]
              },
              "status": "complete",
              "results": [
                {
                  "port": "2",
                  "status": "up",
                  "speedMbps": 10000,
                  "error": "An unexpected error occurred during the execution of the cable test.",
                  "pairs": [
                    {
                      "index": 0,
                      "status": "ok",
                      "lengthMeters": 1
                    }
                  ]
                }
              ],
              "error": "The device is unreachable."
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        id = urllib.parse.quote(str(id), safe="")
        path = f"/devices/{serial}/liveTools/cableTest/{id}"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLiveToolsCableTest",
            path=path,
            response_schema=GetDeviceLiveToolsCableTestResponse,
        )

    def create_device_live_tools_leds_blink(
        self,
        *,
        serial: str,
        duration: int,
        callback: CreateDeviceLiveToolsLedsBlinkCallback | None = None,
    ) -> CreateDeviceLiveToolsLedsBlinkResponse:
        """Enqueue a job to blink LEDs on a device.

        [API documentation: createDeviceLiveToolsLedsBlink](https://developer.cisco.com/meraki/api-v1/#!create-device-live-tools-leds-blink)

        Args:
            serial: Serial.
            duration: The duration in seconds to blink LEDs.
            callback: Details for the callback. Please include either an httpServerId OR url and
                sharedSecret.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "ledsBlinkId": "123",
              "url": "/devices/QXXX-YYYY-ZZZZ/liveTools/leds/blink/1738",
              "status": "complete",
              "request": {
                "serial": "Q234-ABCD-5678",
                "duration": 30
              },
              "error": "error description",
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/liveTools/leds/blink"

        payload: dict[str, Any] = {}
        if duration is not None:
            payload["duration"] = duration
        if callback is not None:
            payload["callback"] = callback.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="devices",
            operation_id="createDeviceLiveToolsLedsBlink",
            path=path,
            json=payload,
            response_schema=CreateDeviceLiveToolsLedsBlinkResponse,
        )

    def get_device_live_tools_leds_blink(
        self, *, serial: str, leds_blink_id: str
    ) -> GetDeviceLiveToolsLedsBlinkResponse:
        """Return a blink LEDs job.

        [API documentation: getDeviceLiveToolsLedsBlink](https://developer.cisco.com/meraki/api-v1/#!get-device-live-tools-leds-blink)

        Args:
            serial: Serial.
            leds_blink_id: Leds blink ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "ledsBlinkId": "123",
              "url": "/devices/QXXX-YYYY-ZZZZ/liveTools/leds/blink/1738",
              "status": "complete",
              "request": {
                "serial": "Q234-ABCD-5678",
                "duration": 30
              },
              "error": "error description"
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        leds_blink_id = urllib.parse.quote(str(leds_blink_id), safe="")
        path = f"/devices/{serial}/liveTools/leds/blink/{leds_blink_id}"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLiveToolsLedsBlink",
            path=path,
            response_schema=GetDeviceLiveToolsLedsBlinkResponse,
        )

    def create_device_live_tools_mac_table(
        self, serial: str, *, callback: CreateDeviceLiveToolsMacTableCallback | None = None
    ) -> CreateDeviceLiveToolsMacTableResponse:
        """Enqueue a job to request the MAC table from the device.

        [API documentation: createDeviceLiveToolsMacTable](https://developer.cisco.com/meraki/api-v1/#!create-device-live-tools-mac-table)

        Args:
            serial: Serial.
            callback: Details for the callback. Please include either an httpServerId OR url and
                sharedSecret.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "macTableId": "1284392014819",
              "url": "/devices/Q234-ABCD-5678/liveTools/macTable/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678"
              },
              "status": "complete",
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/liveTools/macTable"

        payload: dict[str, Any] = {}
        if callback is not None:
            payload["callback"] = callback.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="devices",
            operation_id="createDeviceLiveToolsMacTable",
            path=path,
            json=payload,
            response_schema=CreateDeviceLiveToolsMacTableResponse,
        )

    def get_device_live_tools_mac_table(
        self, *, serial: str, mac_table_id: str
    ) -> GetDeviceLiveToolsMacTableResponse:
        """Return a MAC table live tool job.

        [API documentation: getDeviceLiveToolsMacTable](https://developer.cisco.com/meraki/api-v1/#!get-device-live-tools-mac-table)

        Args:
            serial: Serial.
            mac_table_id: Mac table ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "macTableId": "1284392014819",
              "url": "/devices/Q234-ABCD-5678/liveTools/macTable/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678"
              },
              "status": "complete",
              "entries": [
                {
                  "mac": "00:11:22:33:44:55",
                  "port": "Tw1/0/9",
                  "vlanId": 100
                }
              ],
              "error": "The device is unreachable."
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        mac_table_id = urllib.parse.quote(str(mac_table_id), safe="")
        path = f"/devices/{serial}/liveTools/macTable/{mac_table_id}"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLiveToolsMacTable",
            path=path,
            response_schema=GetDeviceLiveToolsMacTableResponse,
        )

    def create_device_live_tools_multicast_routing(
        self, serial: str, *, callback: CreateDeviceLiveToolsMulticastRoutingCallback | None = None
    ) -> CreateDeviceLiveToolsMulticastRoutingResponse:
        """Enqueue a job to perform a Multicast routing request for the device.

        [API documentation: createDeviceLiveToolsMulticastRouting](https://developer.cisco.com/meraki/api-v1/#!create-device-live-tools-multicast-routing)

        Args:
            serial: Serial.
            callback: Details for the callback. Please include either an httpServerId OR url and
                sharedSecret.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "multicastRoutingId": "1284392014819",
              "url": "/devices/Q234-ABCD-5678/liveTools/multicastRouting/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678"
              },
              "status": "complete",
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/liveTools/multicastRouting"

        payload: dict[str, Any] = {}
        if callback is not None:
            payload["callback"] = callback.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="devices",
            operation_id="createDeviceLiveToolsMulticastRouting",
            path=path,
            json=payload,
            response_schema=CreateDeviceLiveToolsMulticastRoutingResponse,
        )

    def get_device_live_tools_multicast_routing(
        self, *, serial: str, multicast_routing_id: str
    ) -> GetDeviceLiveToolsMulticastRoutingResponse:
        """Return a Multicast routing live tool job.

        [API documentation: getDeviceLiveToolsMulticastRouting](https://developer.cisco.com/meraki/api-v1/#!get-device-live-tools-multicast-routing)

        Args:
            serial: Serial.
            multicast_routing_id: Multicast routing ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "multicastRoutingId": "1284392014819",
              "url": "/devices/Q234-ABCD-5678/liveTools/multicastRouting/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678"
              },
              "status": "complete",
              "interfaces": [
                {
                  "ip": "1.2.3.4",
                  "name": "Vlan20",
                  "subnet": "192.168.1.0/24",
                  "flags": [
                    "PIM"
                  ],
                  "neighbors": [
                    "123.123.123.1"
                  ]
                }
              ],
              "routes": [
                {
                  "source": "1.2.3.4",
                  "group": "1.2.3.5",
                  "rendezvousPoint": "10.0.0.0/24",
                  "incomingInterfaceName": "Vlan100",
                  "outgoingInterfaceNames": [
                    "Vlan20",
                    "Vlan50"
                  ],
                  "flags": [
                    "SPT"
                  ]
                }
              ],
              "error": "The device is unreachable."
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        multicast_routing_id = urllib.parse.quote(str(multicast_routing_id), safe="")
        path = f"/devices/{serial}/liveTools/multicastRouting/{multicast_routing_id}"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLiveToolsMulticastRouting",
            path=path,
            response_schema=GetDeviceLiveToolsMulticastRoutingResponse,
        )

    def create_device_live_tools_ping(
        self,
        *,
        serial: str,
        target: str,
        count: int | None = None,
        callback: CreateDeviceLiveToolsPingCallback | None = None,
    ) -> CreateDeviceLiveToolsPingResponse:
        """Enqueue a job to ping a target host from the device.

        [API documentation: createDeviceLiveToolsPing](https://developer.cisco.com/meraki/api-v1/#!create-device-live-tools-ping)

        Args:
            serial: Serial.
            target: FQDN, IPv4 or IPv6 address.
            count: Count parameter to pass to ping. [1..5], default 5.
            callback: Details for the callback. Please include either an httpServerId OR url and
                sharedSecret.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "pingId": "1284392014819",
              "url": "/devices/SERIAL/liveTools/ping/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678",
                "target": "75.75.75.75",
                "count": 2
              },
              "status": "complete",
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/liveTools/ping"

        payload: dict[str, Any] = {}
        if target is not None:
            payload["target"] = target
        if count is not None:
            payload["count"] = count
        if callback is not None:
            payload["callback"] = callback.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="devices",
            operation_id="createDeviceLiveToolsPing",
            path=path,
            json=payload,
            response_schema=CreateDeviceLiveToolsPingResponse,
        )

    def get_device_live_tools_ping(self, *, serial: str, id: str) -> GetDeviceLiveToolsPingResponse:
        """Return a ping job.

        [API documentation: getDeviceLiveToolsPing](https://developer.cisco.com/meraki/api-v1/#!get-device-live-tools-ping)

        Args:
            serial: Serial.
            id: ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "pingId": "1284392014819",
              "url": "/devices/SERIAL/liveTools/ping/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678",
                "target": "75.75.75.75",
                "count": 2
              },
              "status": "complete",
              "results": {
                "sent": 5,
                "received": 5,
                "loss": {
                  "percentage": 0.0
                },
                "latencies": {
                  "minimum": 15.8,
                  "average": 15.8,
                  "maximum": 15.9
                },
                "replies": [
                  {
                    "sequenceId": 1,
                    "size": 84,
                    "latency": 15.7
                  }
                ]
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        id = urllib.parse.quote(str(id), safe="")
        path = f"/devices/{serial}/liveTools/ping/{id}"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLiveToolsPing",
            path=path,
            response_schema=GetDeviceLiveToolsPingResponse,
        )

    def create_device_live_tools_ping_device(
        self,
        serial: str,
        *,
        count: int | None = None,
        callback: CreateDeviceLiveToolsPingDeviceCallback | None = None,
    ) -> CreateDeviceLiveToolsPingDeviceResponse:
        """Enqueue a job to check connectivity status to the device.

        [API documentation: createDeviceLiveToolsPingDevice](https://developer.cisco.com/meraki/api-v1/#!create-device-live-tools-ping-device)

        Args:
            serial: Serial.
            count: Count parameter to pass to ping. [1..5], default 5.
            callback: Details for the callback. Please include either an httpServerId OR url and
                sharedSecret.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "pingId": "1284392014819",
              "url": "/devices/SERIAL/liveTools/pingDevice/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678",
                "count": 2
              },
              "status": "complete",
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/liveTools/pingDevice"

        payload: dict[str, Any] = {}
        if count is not None:
            payload["count"] = count
        if callback is not None:
            payload["callback"] = callback.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="devices",
            operation_id="createDeviceLiveToolsPingDevice",
            path=path,
            json=payload,
            response_schema=CreateDeviceLiveToolsPingDeviceResponse,
        )

    def get_device_live_tools_ping_device(
        self, *, serial: str, id: str
    ) -> GetDeviceLiveToolsPingDeviceResponse:
        """Return a ping device job.

        [API documentation: getDeviceLiveToolsPingDevice](https://developer.cisco.com/meraki/api-v1/#!get-device-live-tools-ping-device)

        Args:
            serial: Serial.
            id: ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "pingId": "1284392014819",
              "url": "/devices/SERIAL/liveTools/pingDevice/1284392014819",
              "request": {
                "serial": "Q234-ABCD-5678",
                "count": 2
              },
              "status": "complete",
              "results": {
                "sent": 5,
                "received": 5,
                "loss": {
                  "percentage": 0.0
                },
                "latencies": {
                  "minimum": 15.8,
                  "average": 15.8,
                  "maximum": 15.9
                },
                "replies": [
                  {
                    "sequenceId": 1,
                    "size": 84,
                    "latency": 15.7
                  }
                ]
              },
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        id = urllib.parse.quote(str(id), safe="")
        path = f"/devices/{serial}/liveTools/pingDevice/{id}"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLiveToolsPingDevice",
            path=path,
            response_schema=GetDeviceLiveToolsPingDeviceResponse,
        )

    def create_device_live_tools_throughput_test(
        self, serial: str, *, callback: CreateDeviceLiveToolsThroughputTestCallback | None = None
    ) -> CreateDeviceLiveToolsThroughputTestResponse:
        """Enqueue a job to test a device throughput, the test will run for 10 secs to test throughput.

        [API documentation: createDeviceLiveToolsThroughputTest](https://developer.cisco.com/meraki/api-v1/#!create-device-live-tools-throughput-test)

        Args:
            serial: Serial.
            callback: Details for the callback. Please include either an httpServerId OR url and
                sharedSecret.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "throughputTestId": "123",
              "url": "/devices/QXXX-YYYY-ZZZZ/liveTools/throughputTest/123",
              "status": "complete",
              "result": {
                "speeds": {
                  "downstream": 123.456789
                }
              },
              "request": {
                "serial": "Q234-ABCD-5678"
              },
              "error": "error description",
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/liveTools/throughputTest"

        payload: dict[str, Any] = {}
        if callback is not None:
            payload["callback"] = callback.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="devices",
            operation_id="createDeviceLiveToolsThroughputTest",
            path=path,
            json=payload,
            response_schema=CreateDeviceLiveToolsThroughputTestResponse,
        )

    def get_device_live_tools_throughput_test(
        self, *, serial: str, throughput_test_id: str
    ) -> GetDeviceLiveToolsThroughputTestResponse:
        """Return a throughput test job.

        [API documentation: getDeviceLiveToolsThroughputTest](https://developer.cisco.com/meraki/api-v1/#!get-device-live-tools-throughput-test)

        Args:
            serial: Serial.
            throughput_test_id: Throughput test ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "throughputTestId": "123",
              "url": "/devices/QXXX-YYYY-ZZZZ/liveTools/throughputTest/123",
              "status": "complete",
              "result": {
                "speeds": {
                  "downstream": 123.456789
                }
              },
              "request": {
                "serial": "Q234-ABCD-5678"
              },
              "error": "error description"
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        throughput_test_id = urllib.parse.quote(str(throughput_test_id), safe="")
        path = f"/devices/{serial}/liveTools/throughputTest/{throughput_test_id}"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLiveToolsThroughputTest",
            path=path,
            response_schema=GetDeviceLiveToolsThroughputTestResponse,
        )

    def create_device_live_tools_wake_on_lan(
        self,
        *,
        serial: str,
        vlan_id: int,
        mac: str,
        callback: CreateDeviceLiveToolsWakeOnLanCallback | None = None,
    ) -> CreateDeviceLiveToolsWakeOnLanResponse:
        """Enqueue a job to send a Wake-on-LAN packet from the device.

        [API documentation: createDeviceLiveToolsWakeOnLan](https://developer.cisco.com/meraki/api-v1/#!create-device-live-tools-wake-on-lan)

        Args:
            serial: Serial.
            vlan_id: The target's VLAN (1 to 4094).
            mac: The target's MAC address.
            callback: Details for the callback. Please include either an httpServerId OR url and
                sharedSecret.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "wakeOnLanId": "123",
              "url": "/devices/QXXX-YYYY-ZZZZ/liveTools/wakeOnLan/1738",
              "status": "complete",
              "request": {
                "serial": "Q234-ABCD-5678",
                "vlanId": 12,
                "mac": "00:11:22:33:44:55"
              },
              "error": "The device is unreachable.",
              "callback": {
                "id": "1284392014819",
                "url": "https://webhook.site/28efa24e-f830-4d9f-a12b-fbb9e5035031",
                "status": "new"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/liveTools/wakeOnLan"

        payload: dict[str, Any] = {}
        if vlan_id is not None:
            payload["vlanId"] = vlan_id
        if mac is not None:
            payload["mac"] = mac
        if callback is not None:
            payload["callback"] = callback.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="devices",
            operation_id="createDeviceLiveToolsWakeOnLan",
            path=path,
            json=payload,
            response_schema=CreateDeviceLiveToolsWakeOnLanResponse,
        )

    def get_device_live_tools_wake_on_lan(
        self, *, serial: str, wake_on_lan_id: str
    ) -> GetDeviceLiveToolsWakeOnLanResponse:
        """Return a Wake-on-LAN job.

        [API documentation: getDeviceLiveToolsWakeOnLan](https://developer.cisco.com/meraki/api-v1/#!get-device-live-tools-wake-on-lan)

        Args:
            serial: Serial.
            wake_on_lan_id: Wake on lan ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "wakeOnLanId": "123",
              "url": "/devices/QXXX-YYYY-ZZZZ/liveTools/wakeOnLan/1738",
              "status": "complete",
              "request": {
                "serial": "Q234-ABCD-5678",
                "vlanId": 12,
                "mac": "00:11:22:33:44:55"
              },
              "error": "The device is unreachable."
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        wake_on_lan_id = urllib.parse.quote(str(wake_on_lan_id), safe="")
        path = f"/devices/{serial}/liveTools/wakeOnLan/{wake_on_lan_id}"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLiveToolsWakeOnLan",
            path=path,
            response_schema=GetDeviceLiveToolsWakeOnLanResponse,
        )

    def get_device_lldp_cdp(self, serial: str) -> GetDeviceLldpCdpResponse:
        """List LLDP and CDP information for a device.

        [API documentation: getDeviceLldpCdp](https://developer.cisco.com/meraki/api-v1/#!get-device-lldp-cdp)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "sourceMac": "00:11:22:33:44:55",
              "ports": {
                "22": {
                  "lldp": {
                    "systemName": "Meraki MS350-24X - Phineas",
                    "systemDescription": "Meraki MX64 Cloud Managed Router",
                    "portId": "11",
                    "chassisId": "88:15:44:c8:5d:58",
                    "managementVlan": 60,
                    "portVlan": 500,
                    "managementAddress": "192.168.1.128",
                    "portDescription": "12",
                    "systemCapabilities": "S-VLAN Component of a VLAN Bridge",
                    "sourcePort": "12"
                  },
                  "cdp": {
                    "platform": "MS350-24X",
                    "deviceId": "e0553d8cdf53",
                    "model": "cisco C9300-24P",
                    "version": "Catalyst L3 Switch Software (CAT9K_IOSXE), Experimental Version 17.6.20210422:140402",
                    "portId": "Port 10",
                    "nativeVlan": 1,
                    "vtpManagementDomain": "cisco",
                    "capabilities": "Switch",
                    "address": "192.168.1.128",
                    "sourcePort": "9"
                  },
                  "deviceMac": "00:11:22:33:44:55",
                  "device": {
                    "url": "https://dashboard.meraki.com/Wireless-Testing/n/scPLfd/manage/nodes/new_list/194114551275232"
                  }
                }
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/lldpCdp"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceLldpCdp",
            path=path,
            response_schema=GetDeviceLldpCdpResponse,
        )

    def get_device_loss_and_latency_history(
        self,
        *,
        serial: str,
        ip: str,
        t0: str | None = None,
        t1: str | None = None,
        timespan: float | None = None,
        resolution: int | None = None,
        uplink: GetDeviceLossAndLatencyHistoryUplink | None = None,
    ) -> PaginatedResponse[GetDeviceLossAndLatencyHistoryResponseItem]:
        """Get the uplink loss percentage and latency in milliseconds, and goodput in kilobits per second for MX, MG and Z devices.

        [API documentation: getDeviceLossAndLatencyHistory](https://developer.cisco.com/meraki/api-v1/#!get-device-loss-and-latency-history)

        Args:
            serial: Serial.
            t0: The beginning of the timespan for the data. The maximum lookback period is 60 days
                from today.
            t1: The end of the timespan for the data. t1 can be a maximum of 31 days after t0.
            timespan: The timespan for which the information will be fetched. If specifying
                timespan, do not specify parameters t0 and t1. The value must be in
                seconds and be less than or equal to 31 days. The default is 1 day.
            resolution: The time resolution in seconds for returned data. The valid resolutions are:
                60, 600, 3600, 86400. The default is 60.
            uplink: The WAN uplink used to obtain the requested stats. Valid uplinks are wan1, wan2,
                wan3, cellular. The default is wan1.
            ip: The destination IP used to obtain the requested stats. This is required.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "startTime": "2018-10-09T22:18:27Z",
                "endTime": "2018-10-09T22:19:27Z",
                "lossPercent": 5.23,
                "latencyMs": 324.12,
                "goodput": 1493,
                "jitter": 11.2
              }
            ]
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/lossAndLatencyHistory"

        params: dict[str, Any] = {}
        if t0 is not None:
            params["t0"] = t0
        if t1 is not None:
            params["t1"] = t1
        if timespan is not None:
            params["timespan"] = timespan
        if resolution is not None:
            params["resolution"] = resolution
        if uplink is not None:
            params["uplink"] = uplink
        if ip is not None:
            params["ip"] = ip

        return self._session.get_pages(
            scope="devices",
            operation_id="getDeviceLossAndLatencyHistory",
            path=path,
            params=params,
            item_schema=GetDeviceLossAndLatencyHistoryResponseItem,
        )

    def get_device_management_interface(self, serial: str) -> GetDeviceManagementInterfaceResponse:
        """Return the management interface settings for a device.

        [API documentation: getDeviceManagementInterface](https://developer.cisco.com/meraki/api-v1/#!get-device-management-interface)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "ddnsHostnames": {
                "activeDdnsHostname": "mx1-sample.dynamic-m.com",
                "ddnsHostnameWan1": "mx1-sample-1.dynamic-m.com",
                "ddnsHostnameWan2": "mx1-sample-2.dynamic-m.com"
              },
              "wan1": {
                "wanEnabled": "not configured",
                "usingStaticIp": true,
                "staticIp": "1.2.3.4",
                "staticSubnetMask": "255.255.255.0",
                "staticGatewayIp": "1.2.3.1",
                "staticDns": [
                  "1.2.3.2",
                  "1.2.3.3"
                ],
                "vlan": 7,
                "vrf": {
                  "name": "Mgmt-vrf"
                }
              },
              "wan2": {
                "wanEnabled": "enabled",
                "usingStaticIp": false,
                "staticIp": "1.2.3.4",
                "staticSubnetMask": "255.255.255.0",
                "staticGatewayIp": "1.2.3.1",
                "staticDns": [
                  "1.2.3.2",
                  "1.2.3.3"
                ],
                "vlan": 2,
                "vrf": {
                  "name": "Mgmt-vrf"
                }
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/managementInterface"

        return self._session.get(
            scope="devices",
            operation_id="getDeviceManagementInterface",
            path=path,
            response_schema=GetDeviceManagementInterfaceResponse,
        )

    def update_device_management_interface(
        self,
        serial: str,
        *,
        wan1: UpdateDeviceManagementInterfaceWan1 | None = None,
        wan2: UpdateDeviceManagementInterfaceWan2 | None = None,
    ) -> UpdateDeviceManagementInterfaceResponse:
        """Update the management interface settings for a device.

        [API documentation: updateDeviceManagementInterface](https://developer.cisco.com/meraki/api-v1/#!update-device-management-interface)

        Args:
            serial: Serial.
            wan1: WAN 1 settings.
            wan2: WAN 2 settings (only for MX devices).

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "ddnsHostnames": {
                "activeDdnsHostname": "mx1-sample.dynamic-m.com",
                "ddnsHostnameWan1": "mx1-sample-1.dynamic-m.com",
                "ddnsHostnameWan2": "mx1-sample-2.dynamic-m.com"
              },
              "wan1": {
                "wanEnabled": "not configured",
                "usingStaticIp": true,
                "staticIp": "1.2.3.4",
                "staticSubnetMask": "255.255.255.0",
                "staticGatewayIp": "1.2.3.1",
                "staticDns": [
                  "1.2.3.2",
                  "1.2.3.3"
                ],
                "vlan": 7,
                "vrf": {
                  "name": "Mgmt-vrf"
                }
              },
              "wan2": {
                "wanEnabled": "enabled",
                "usingStaticIp": false,
                "staticIp": "1.2.3.4",
                "staticSubnetMask": "255.255.255.0",
                "staticGatewayIp": "1.2.3.1",
                "staticDns": [
                  "1.2.3.2",
                  "1.2.3.3"
                ],
                "vlan": 2,
                "vrf": {
                  "name": "Mgmt-vrf"
                }
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/managementInterface"

        payload: dict[str, Any] = {}
        if wan1 is not None:
            payload["wan1"] = wan1.model_dump(by_alias=True, exclude_none=True)
        if wan2 is not None:
            payload["wan2"] = wan2.model_dump(by_alias=True, exclude_none=True)

        return self._session.put(
            scope="devices",
            operation_id="updateDeviceManagementInterface",
            path=path,
            json=payload,
            response_schema=UpdateDeviceManagementInterfaceResponse,
        )

    def reboot_device(self, serial: str) -> RebootDeviceResponse:
        """Reboot a device.

        [API documentation: rebootDevice](https://developer.cisco.com/meraki/api-v1/#!reboot-device)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "success": true
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/reboot"

        return self._session.post(
            scope="devices",
            operation_id="rebootDevice",
            path=path,
            response_schema=RebootDeviceResponse,
        )
