diff --git a/src/components/BootstrapBlazor.HikVision/BootstrapBlazor.HikVision.csproj b/src/components/BootstrapBlazor.HikVision/BootstrapBlazor.HikVision.csproj index e35c13f3..d1ed5412 100644 --- a/src/components/BootstrapBlazor.HikVision/BootstrapBlazor.HikVision.csproj +++ b/src/components/BootstrapBlazor.HikVision/BootstrapBlazor.HikVision.csproj @@ -1,7 +1,7 @@ - 10.0.5 + 10.0.6 diff --git a/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.cs b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.cs index 3e4e09ec..88712dae 100644 --- a/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.cs +++ b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.cs @@ -280,7 +280,7 @@ public async Task OpenSound() if (IsLogin && IsRealPlaying) { var code = await InvokeAsync("openSound", Id); - ret = code == 0; + ret = code == 100; } return ret; } @@ -295,7 +295,7 @@ public async Task CloseSound() if (IsLogin && IsRealPlaying) { var code = await InvokeAsync("closeSound", Id); - ret = code == 0; + ret = code == 100; } return ret; } @@ -311,8 +311,60 @@ public async Task SetVolume(int value) if (IsLogin && IsRealPlaying) { var code = await InvokeAsync("setVolume", Id, Math.Max(0, Math.Min(100, value))); - ret = code == 0; + ret = code == 100; } return ret; } + + /// + /// 抓图方法返回 Url + /// + /// + public async Task CapturePictureAndDownload() + { + if (IsLogin && IsRealPlaying) + { + await InvokeVoidAsync("capturePictureAndDownload", Id); + } + } + + private TaskCompletionSource? _captureTaskCompletionSource = null; + + /// + /// 抓图方法返回 Url + /// + /// + public async Task CapturePicture(CancellationToken token = default) + { + IJSStreamReference? ret = null; + if (IsLogin && IsRealPlaying) + { + _captureTaskCompletionSource = new(); + + try + { + await InvokeVoidAsync("capturePicture", token, Id); + ret = await _captureTaskCompletionSource.Task; + } + catch (Exception ex) + { + _captureTaskCompletionSource.SetException(ex); + } + } + return ret; + } + + /// + /// 抓图返回文件流方法 由 Javascript 调用 + /// + /// + /// + [JSInvokable] + public async Task TriggerReceivePictureStream(IJSStreamReference stream) + { + if (_captureTaskCompletionSource != null) + { + _captureTaskCompletionSource.SetResult(stream); + } + } } diff --git a/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.js b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.js index 290de54d..07009e82 100644 --- a/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.js +++ b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.js @@ -1,4 +1,4 @@ -import { init as initVision, login as loginVision, logout, startRealPlay, stopRealPlay, openSound, closeSound, setVolume, dispose as disposeVision } from '../hikvision.js'; +import { init as initVision, login as loginVision, logout, startRealPlay, stopRealPlay, openSound, closeSound, setVolume, capturePicture, capturePictureAndDownload, dispose as disposeVision } from '../hikvision.js'; import Data from '../../BootstrapBlazor/modules/data.js'; export async function init(id, invoke) { @@ -29,7 +29,7 @@ export async function login(id, ip, port, userName, password, loginType) { return logined; } -export { logout, startRealPlay, stopRealPlay, openSound, closeSound, setVolume } +export { logout, startRealPlay, stopRealPlay, openSound, closeSound, setVolume, capturePicture, capturePictureAndDownload } export function dispose(id) { disposeVision(id); diff --git a/src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js b/src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js index f49fbb05..7e8f8be2 100644 --- a/src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js +++ b/src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js @@ -355,7 +355,7 @@ export async function openSound(id) { return 101; } - let code = 0; + let code = 100; try { await WebVideoCtrl.I_OpenSound(iWndIndex); } @@ -374,7 +374,7 @@ export async function closeSound(id) { return 101; } - let code = 0; + let code = 100; try { await WebVideoCtrl.I_CloseSound(iWndIndex); } @@ -398,7 +398,7 @@ export async function setVolume(id, value) { v = 50; } - let code = 0; + let code = 100; try { await WebVideoCtrl.I_SetVolume(Math.min(100, Math.max(0, v))); } @@ -409,6 +409,63 @@ export async function setVolume(id, value) { return code; } +export async function capturePicture(id) { + const vision = Data.get(id); + const { realPlaying } = vision; + + if (realPlaying !== true) { + return ""; + } + + try { + const base64 = await WebVideoCtrl.I_CapturePicData(); + if (base64) { + const bytes = base64ToArray(base64); + return DotNet.createJSStreamReference(bytes.buffer); + } + } + catch (ex) { + return null; + } +} + +const base64ToArray = base64String => { + const base64Data = base64String.split(',')[1] || base64String; + const binaryString = atob(base64Data); + const length = binaryString.length; + const bytes = new Uint8Array(length); + + for (let i = 0; i < length; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + + return bytes; +} + +export async function capturePictureAndDownload(id) { + const vision = Data.get(id); + const { realPlaying } = vision; + + if (realPlaying !== true) { + return; + } + + try { + const base64 = await WebVideoCtrl.I_CapturePicData(); + if (base64) { + const anchorElement = document.createElement('a'); + anchorElement.href = `data:image/jpg;base64,${base64}`; + anchorElement.download = `capture_${new Date().getTime()}.jpg`; + document.body.appendChild(anchorElement); + anchorElement.click(); + document.body.removeChild(anchorElement); + } + } + catch (ex) { + + } +} + export function dispose(id) { const vision = Data.get(id); const { realPlaying, logined, observer } = vision;