MilestoneSystemsInc / PowerShellSamples

A collection of samples for managing your Milestone XProtect VMS using MilestonePSTools in PowerShell
https://www.milestonepstools.com
MIT License
36 stars 12 forks source link

request for method to add camera event #105

Closed jiemjiem closed 11 months ago

jiemjiem commented 1 year ago

hello Could you add new methods to add events on camera? (camera "event" tab in milestone) Thanks

joshooaj commented 1 year ago

Hi @jiemjiem,

Solid request - I would definitely like have those commands in the module. I'll aim to add it for 23.2.3. We're about to publish 23.2.2 with new connection-related commands introducing "named connection profiles" that are persisted to your local user profile so that you don't have to explicitly logon every time you use the module, as well as commands for configuring webhooks.

There are also some neat improvements under the hood with custom attributes used to improve error messaging around version and feature requirements, as well as update the docs based on those declared requirement attributes.

Here are the new commands coming up:

Until some cmdlets for working with hardware based events are introduced, you can access these from the existing Camera (or mic, or input, etc) objects. For example, here is a script to enable all inputs on the selected hardware, and add/enable all the events available on those inputs (input rising/falling for example).

Connect-ManagementServer -ShowDialog -AcceptEula -Force
$hardwares = Get-VmsHardware | Out-GridView -OutputMode Multiple -Title "Enable input and rising/falling events on selected hardware"

foreach ($hardware in $hardwares) {
    foreach ($inputEvent in $hardware | Get-Input) {
        if (-not $inputEvent.Enabled) {
            Write-Host "Enabling input $($inputEvent.Name) on $($hardware.Name)"
            $inputEvent.Enabled = $true
            $inputEvent.Save()
        }
        $hardwareDeviceEvents = $inputEvent.HardwareDeviceEventFolder.HardwareDeviceEvents[0]
        $dirty = $false
        foreach ($eventItem in $hardwareDeviceEvents.HardwareDeviceEventChildItems) {
            if (-not $eventItem.EventUsed) {
                Write-Host "Adding $($eventItem.DisplayName) to input $($inputEvent.Name) on $($hardware.Name)"
                $eventItem.EventUsed = $true
                $dirty = $true
            }
            if (-not $eventItem.Enabled) {
                Write-Host "Enabling $($eventItem.DisplayName) for use on input $($inputEvent.Name) on $($hardware.Name)"
                $eventItem.Enabled = $true
                $dirty = $true
            }
        }
        if ($dirty) {
            $hardwareDeviceEvents.Save()
        }
    }
}
joshooaj commented 11 months ago

Hi @jiemjiem

I'm exploring ideas for commands to add/remove events on all devices - hardware, cams, mics, speakers, metadata, and IO. Do you have any ideas about how you would expect to work with them in PowerShell?

Events on all of these devices are accessed the same way, so I'm tempted to have Get-VmsDeviceEvent and Set-VmsDeviceEvent.

The commands work well for getting all available events on a device, whether they're "Used" which means they've been "added" in the management client, whether they're "Enabled" meaning they're added, AND enabled, and you can modify those properties with the Set command.

I like the idea of a single pair of commands for this, but I'm betting most users will look for a command like "Add/Remove-VmsCameraEvent" or similar. Maybe we could have a single command pair, but create aliases to point "Get-VmsCameraEvent" to "Get-VmsDeviceEvent" for example?

#Requires -Modules @{ ModuleName = 'MilestonePSTools'; ModuleVersion = '23.2.2' }

function Get-VmsDeviceEvent {
    [CmdletBinding()]
    [MilestonePSTools.RequiresVmsConnection()]
    [MilestonePSTools.RequiresVmsVersion('21.1')]
    [OutputType([VideoOS.Platform.ConfigurationItems.HardwareDeviceEventChildItem])]
    param (
        [Parameter(Mandatory, ValueFromPipeline)]
        [VideoOS.Platform.ConfigurationItems.IConfigurationItem]
        $Device,

        [Parameter()]
        [bool]
        $Used,

        [Parameter()]
        [bool]
        $Enabled
    )

    process {
        $Device.HardwareDeviceEventFolder.ClearChildrenCache()
        $hardwareDeviceEvent = $Device.HardwareDeviceEventFolder.HardwareDeviceEvents | Select-Object -First 1
        foreach ($childItem in $hardwareDeviceEvent.HardwareDeviceEventChildItems) {
            if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Used') -and $childItem.EventUsed -ne $Used) {
                continue
            }
            if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Enabled') -and $childItem.Enabled -ne $Enabled) {
                continue
            }
            $childItem | Add-Member -MemberType NoteProperty -Name Device -Value $Device
            $childItem | Add-Member -MemberType NoteProperty -Name HardwareDeviceEvent -Value $hardwareDeviceEvent
            $childItem
        }
    }
}

function Set-VmsDeviceEvent {
    [CmdletBinding(SupportsShouldProcess)]
    [MilestonePSTools.RequiresVmsConnection()]
    [MilestonePSTools.RequiresVmsVersion('21.1')]
    [OutputType([VideoOS.Platform.ConfigurationItems.HardwareDeviceEventChildItem])]
    param (
        [Parameter(Mandatory, ValueFromPipeline)]
        [ValidateScript({
                if ($null -eq ($_ | Get-Member -MemberType NoteProperty -Name HardwareDeviceEvent)) {
                    throw 'DeviceEvent must be returned by Get-VmsDeviceEvent or it does not have a NoteProperty member named HardwareDeviceEvent.'
                }
                $true
            })]
        [VideoOS.Platform.ConfigurationItems.HardwareDeviceEventChildItem]
        $DeviceEvent,

        [Parameter()]
        [bool]
        $Used,

        [Parameter()]
        [bool]
        $Enabled,

        [Parameter()]
        [string]
        $Index
    )

    begin {
        $modified = @{}
    }

    process {
        $changes = @{}
        if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Used') -and $DeviceEvent.EventUsed -ne $Used) {
            $changes['EventUsed'] = $Used            
        }
        if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Enabled') -and $DeviceEvent.Enabled -ne $Enabled) {
            $changes['Enabled'] = $Enabled         
        }
        if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('Index') -and $DeviceEvent.EventIndex -ne $Index) {
            $changes['EventIndex'] = $Index
        }

        # Management Client sets EventUsed and Enabled to the same value when you add or remove them in the UI.
        # This will ensure we don't leave Enabled set to true after setting EventUsed to false.
        if ($changes.ContainsKey('EventUsed') -and $changes['EventUsed'] -ne $DeviceEvent.Enabled) {
            $changes['Enabled'] = $changes['EventUsed']
        }

        if ($changes.Count -gt 0 -and $PSCmdlet.ShouldProcess($DeviceEvent.Device.Name, "Update '$($DeviceEvent.DisplayName)' device event settings")) {
            foreach ($kvp in $changes.GetEnumerator()) {
                $DeviceEvent.($kvp.Key) = $kvp.Value
            }
            $modified[$DeviceEvent.Path] = $DeviceEvent
        }
    }

    end {
        foreach ($item in $modified.Values) {
            try {
                Write-Verbose "Saving device event changes on $($item.Device.Name)."
                $item.HardwareDeviceEvent.Save()
            } catch {
                throw
            }
        }
    }
}
jiemjiem commented 11 months ago

Hi, In my case I only need to add the event "operations" to all my axis cams. Sorry I don't know if there is a difference between "device events" and "cam events" and I hope to be able to do it in 2020R3 release...

joshooaj commented 11 months ago

I believe we're taking about the same events - the place in Management Client when looking at a camera, there's an Events tab, and you can click "Add" to add that camera-based event to Milestone?

This capability wasn't added to the configuration api until 2021 R1 so even though you can use a newer MilestonePSTools version, the server needs to support the API request. So you'll need to upgrade your VMS version to automate configuration of camera-based events.