# Restart Devices

import { Badge } from "zudoku/ui/Badge";

<div className="flex flex-wrap gap-2 not-prose mb-4">
  <Badge variant="outline">Automation</Badge>
  <Badge variant="secondary" className="font-mono text-xs">
    GET /v1/devices
  </Badge>
  <Badge variant="secondary" className="font-mono text-xs">
    POST /v1/tasks
  </Badge>
</div>

Restart the devices that support the task, and confirm they return online.

:::tip

You can adjust the script to your needs. Change the conditions, variables, and values to
produce the output you want.

:::

<Recipe
  language={["python", "javascript"]}
  steps={[
    {
      title: "Set up the request",
      body: "Use the access token returned by the [Authenticate](/recipes/authentication) recipe.",
      code: {
        python:
          'import json\nimport time\n\nimport requests\n\nBASE = "https://api.securithings.com"\nheaders = {"Authorization": f"Bearer {access_token}"}',
        javascript:
          'const BASE = "https://api.securithings.com";\nconst headers = {\n  Authorization: `Bearer ${accessToken}`,\n};\nconst sleep = (ms) =>\n  new Promise((resolve) => setTimeout(resolve, ms));',
      },
    },
    {
      title: "Select target devices",
      body: "Narrow the fleet with any filter the [devices endpoint](/api/devices) accepts. `availableTask.restartDevice` reports whether the task can be executed on the device.",
      code: {
        python:
          'devices = requests.get(\n    f"{BASE}/v1/devices",\n    params={"limit": 100},\n    headers=headers,\n).json()["devices"]\n\ntargets = [\n    device["id"]\n    for device in devices\n    if device["availableTask"]["restartDevice"]\n]',
        javascript:
          'const query = new URLSearchParams({ limit: "100" });\nconst devicesResponse = await fetch(\n  `${BASE}/v1/devices?${query}`,\n  { headers },\n);\nconst { devices } = await devicesResponse.json();\n\nconst targets = [];\nfor (const device of devices) {\n  if (device.availableTask.restartDevice) {\n    targets.push(device.id);\n  }\n}',
      },
    },
    {
      title: "Execute the task",
      body: "`restartDevice` requires no configuration, so no payload is sent.",
      code: {
        python:
          'response = requests.post(\n    f"{BASE}/v1/tasks",\n    json={\n        "taskType": "restartDevice",\n        "devices": [\n            {"deviceId": device_id}\n            for device_id in targets\n        ],\n    },\n    headers=headers,\n)\ntask_id = response.json()["taskId"]',
        javascript:
          'const taskResponse = await fetch(`${BASE}/v1/tasks`, {\n  method: "POST",\n  headers: {\n    ...headers,\n    "Content-Type": "application/json",\n  },\n  body: JSON.stringify({\n    taskType: "restartDevice",\n    devices: targets.map((deviceId) => ({\n      deviceId,\n    })),\n  }),\n});\nconst { taskId } = await taskResponse.json();',
      },
    },
    {
      title: "Poll for completion",
      body: "The task is done once every device task reaches `completed`.",
      code: {
        python:
          'while True:\n    task = requests.get(\n        f"{BASE}/v1/tasks/{task_id}",\n        headers=headers,\n    ).json()\n    pending = [\n        device_task\n        for device_task in task["deviceTasks"]\n        if device_task["status"] != "completed"\n    ]\n    if not pending:\n        break\n    time.sleep(30)',
        javascript:
          'let task;\nwhile (true) {\n  const statusResponse = await fetch(\n    `${BASE}/v1/tasks/${taskId}`,\n    { headers },\n  );\n  task = await statusResponse.json();\n  const pending = task.deviceTasks.filter(\n    (deviceTask) => deviceTask.status !== "completed",\n  );\n  if (pending.length === 0) break;\n  await sleep(30000);\n}',
      },
    },
    {
      title: "Build the result",
      body: "Read each device back to check its `status` after the restart.",
      code: {
        python:
          'result = {"taskId": task_id, "devices": []}\n\nfor device_id in targets:\n    device = requests.get(\n        f"{BASE}/v1/devices/{device_id}",\n        headers=headers,\n    ).json()\n    result["devices"].append(\n        {\n            "id": device["id"],\n            "name": device["name"],\n            "status": device["status"],\n        }\n    )\n    time.sleep(1)  # 1 request per second\n\nprint(json.dumps(result, indent=2))',
        javascript:
          "const result = { taskId, devices: [] };\n\nfor (const deviceId of targets) {\n  const deviceResponse = await fetch(\n    `${BASE}/v1/devices/${deviceId}`,\n    { headers },\n  );\n  const device = await deviceResponse.json();\n  result.devices.push({\n    id: device.id,\n    name: device.name,\n    status: device.status,\n  });\n  await sleep(1000); // 1 request per second\n}\n\nconsole.log(JSON.stringify(result, null, 2));",
      },
    },
  ]}
  response={`{
  "taskId": "23bpozz1mpjjedtr",
  "devices": [
    {
      "id": "9ff559ee-38b6-11f1-81cb-465864a35d0a",
      "name": "192.168.2.69 - Unit",
      "status": "online"
    },
    {
      "id": "dc7d4ef1-6bf9-11f1-b083-d27bafcacdf8",
      "name": "192.168.2.70 - Unit",
      "status": "offline"
    }
  ]
}`}
/>
