Error changing device address using Set-VmsHardware in Powershell

I have written a script to automate moving Axis cameras to a new subnet. The part of the script that changes the device IP and gateway setting works just fine but I can’t get it to update Milestone using Set-VmsHardware. All of the fields (current IP, new IP, new gateway, username, password, and camera ID) are in a CSV file. Here is the script I am testing:

# Prompt the operator for the CSV file path and file name
 
$csvFilePath = Read-Host -Prompt "Enter the path and file name of the CSV file"
 
 
 
# Read CSV file
 
$cameras = Import-Csv -Path $csvFilePath
 
 
 
# Prompt for the log file location
 
$logFilePath = "C:\temp\CameraUpdateLog.log"
 
Add-Content -Path $logFilePath -Value "IP and Gateway Update Script Run: $(Get-Date)"
 
 
 
foreach ($camera in $cameras) {
 
  $cameraIP = $camera.Address
 
  $newIP = $camera.NewIPAddress
 
  $newGateway = $camera.NewDefaultGateway
 
  $username = $camera.Username
 
  $password = $camera.Password
 
	$camname = $camera.Name
 
 
 
  # Convert password to secure string and create PSCredential object
 
  $securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
 
  $credential = New-Object System.Management.Automation.PSCredential ($username, $securePassword)
 
 
 
  # URL to update IP and Gateway
 
  $url = "http://${cameraIP}/axis-cgi/param.cgi?action=update&Network.IPAddress=$newIP&Network.DefaultRouter=$newGateway"
 
 
 
  try {
 
    # Set the new IP and Gateway using Digest Authentication
 
    $response = Invoke-WebRequest -Uri $url -Credential $credential -Method GET -UseBasicParsing
 
    $message = "Success: IP and Gateway for camera $camname at $cameraIP updated to IP: $newIP, Gateway: $newGateway."
 
    Write-Host $message
 
    Add-Content -Path $logFilePath -Value $message
 
 
 
    # If IP change was successful, update Milestone
 
    $hardwareId = $camera.Id
 
 
 
    # Get the hardware object based on the hardware ID
 
    $hardware = Get-VMSHardware | Where-Object { $_.Id -eq "$hardwareId" }
 
 
 
    if ($hardware) {
 
      try {
 
        # Update the hardware IP address in Milestone
 
        Set-VMSHardware -Hardware $hardware -Address $newIP
 
        $milestoneMessage = "Milestone updated for camera $($camera.Name) with new IP $newIP."
 
        Write-Host $milestoneMessage
 
        Add-Content -Path $logFilePath -Value $milestoneMessage
 
      } catch {
 
        $milestoneError = "Failed to update Milestone for camera $($camera.Name) with new IP ${newIP}: $($_.Exception.Message)"
 
        Write-Host $milestoneError
 
        Add-Content -Path $logFilePath -Value $milestoneError
 
      }
 
    } else {
 
      $errorNoHardware = "Hardware ID $hardwareId not found in Milestone for camera $($camera.Name)."
 
      Write-Host $errorNoHardware
 
      Add-Content -Path $logFilePath -Value $errorNoHardware
 
    }
 
 
 
  } catch {
 
    $errorMessage = "Failed to update IP and Gateway for camera $($camera.Name) at ${cameraIP}: $($_.Exception.Message)"
 
    Write-Host $errorMessage
 
    Add-Content -Path $logFilePath -Value $errorMessage
 
  }
 
}

I keep getting the following error:

Failed to update Milestone for camera (camera name) with new IP (x.x.x.x): Exception calling "Save" with "0" argument(s): "Exception of type 'VideoOS.Platform.Proxy.ConfigApi.ValidateResultException' was thrown."

I tried running Set-VmsHardware manually as well and the full error is

Exception calling "Save" with "0" argument(s): "Exception of type 'VideoOS.Platform.Proxy.ConfigApi.ValidateResultException' was thrown."
At C:\Program Files\WindowsPowerShell\Modules\MilestonePSTools\24.1.27\MilestonePSTools.psm1:9406 char:25
+                         $hw.Save()
+                         ~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ValidateResultException

If I run Get-VmsHardware it shows the device has the new IP address

However it doesn’t change / update in the Management Client or reconnect to the device or reconnect the video stream.

Any suggestions on what I’m doing wrong or what I need to change?

I was able to get the script working by changing a few things but I don’t remember exactly what I changed lol. Here is the working script

# Prompt the operator for the CSV file path and file name
$csvFilePath = Read-Host -Prompt "Enter the path and file name of the CSV file"
 
# Read CSV file
$cameras = Import-Csv -Path $csvFilePath
 
# Prompt for the log file location
$logFilePath = "C:\temp\CameraUpdateLog.log"
Add-Content -Path $logFilePath -Value "IP and Gateway Update Script Run: $(Get-Date)"
 
foreach ($camera in $cameras) {
    $cameraIP = $camera.Address
    $newIP = $camera.NewIPAddress
    $newGateway = $camera.NewDefaultGateway
    $username = $camera.Username
    $password = $camera.Password
	$camname = $camera.Name
 
    # Convert password to secure string and create PSCredential object
    $securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential ($username, $securePassword)
 
    # URL to update IP and Gateway
    $url = "http://${cameraIP}/axis-cgi/param.cgi?action=update&Network.IPAddress=$newIP&Network.DefaultRouter=$newGateway"
 
    try {
        # Set the new IP and Gateway using Digest Authentication
        $response = Invoke-WebRequest -Uri $url -Credential $credential -Method GET -UseBasicParsing
        $message = "Success: IP and Gateway for camera $camname at $cameraIP updated to IP: $newIP, Gateway: $newGateway."
        Write-Host $message
        Add-Content -Path $logFilePath -Value $message
 
        # If IP change was successful, update Milestone
        $hardwareId = $camera.Id
 
        # Get the hardware object based on the hardware ID
        $hardware = Get-VMSHardware | Where-Object { $_.Id -eq "$hardwareId" }
 
        if ($hardware) {
            $newName = "$camname [$newIP]"
            $formattedNewIP = "http://$newIP"
 
            try {
                # Update the hardware IP address and name in Milestone
                Set-VMSHardware -Hardware $hardware -Address $formattedNewIP -Name $newName
                $milestoneMessage = "Milestone updated for camera $($camera.Name) with new IP $newIP."
                Write-Host $milestoneMessage
                Add-Content -Path $logFilePath -Value $milestoneMessage
            } catch {
                $milestoneError = "Failed to update Milestone for camera $($camera.Name) with new IP ${newIP}: $($_.Exception.Message)"
                Write-Host $milestoneError
                Add-Content -Path $logFilePath -Value $milestoneError
            }
        } else {
            $errorNoHardware = "Hardware ID $hardwareId not found in Milestone for camera $($camera.Name)."
            Write-Host $errorNoHardware
            Add-Content -Path $logFilePath -Value $errorNoHardware
        }
 
    } catch {
        $errorMessage = "Failed to update IP and Gateway for camera $($camera.Name) at ${cameraIP}: $($_.Exception.Message)"
        Write-Host $errorMessage
        Add-Content -Path $logFilePath -Value $errorMessage
    }
}