diff --git a/src/components/BootstrapBlazor.HikVision/Components/HikVision.razor b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor similarity index 79% rename from src/components/BootstrapBlazor.HikVision/Components/HikVision.razor rename to src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor index e4b02995..87b87f8e 100644 --- a/src/components/BootstrapBlazor.HikVision/Components/HikVision.razor +++ b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor @@ -1,5 +1,4 @@ @namespace BootstrapBlazor.Components @inherits BootstrapModuleComponentBase -
-
+
diff --git a/src/components/BootstrapBlazor.HikVision/Components/HikVision.razor.cs b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.cs similarity index 57% rename from src/components/BootstrapBlazor.HikVision/Components/HikVision.razor.cs rename to src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.cs index a8fa5e3e..40d87b33 100644 --- a/src/components/BootstrapBlazor.HikVision/Components/HikVision.razor.cs +++ b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.cs @@ -7,10 +7,10 @@ namespace BootstrapBlazor.Components; /// -/// 海康威视网络摄像机组件 +/// 海康威视网络摄像机组件 (Websdk Plugin 插件版本) /// -[JSModuleAutoLoader("./_content/BootstrapBlazor.HikVision/Components/HikVision.razor.js")] -public partial class HikVision +[JSModuleAutoLoader("./_content/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.js", JSObjectReference = true)] +public partial class HikVisionWebPlugin { /// /// 获得/设置 网络摄像机 IP 地址 @@ -54,6 +54,12 @@ public partial class HikVision [Parameter] public string? Height { get; set; } + /// + /// 获得/设置 插件初始化完成后回调方法 + /// + [Parameter] + public Func OnInitedAsync { get; set; } + private string? ClassString => CssBuilder.Default("bb-hik") .AddClassFromAttributes(AdditionalAttributes) .Build(); @@ -64,6 +70,21 @@ public partial class HikVision .AddStyleFromAttributes(AdditionalAttributes) .Build(); + /// + /// 获得 Websdk 插件是否初始化成功 + /// + public bool Inited { get; private set; } + + /// + /// 获得 是否已登录 + /// + public bool IsLogined { get; private set; } + + /// + /// 获得 是否正在实时预览 + /// + public bool IsRealPlaying { get; private set; } + /// /// /// @@ -84,9 +105,11 @@ protected override void OnParametersSet() /// /// /// - public async Task Login(string ip, int port, string userName, string password, LoginType loginType = LoginType.Http) + public async Task Login(string ip, int port, string userName, string password, LoginType loginType = LoginType.Http) { - await InvokeVoidAsync("login", Id, ip, port, userName, password, (int)loginType); + ThrowIfNotInited(); + IsLogined = await InvokeAsync("login", Id, ip, port, userName, password, (int)loginType) ?? false; + return IsLogined; } /// @@ -95,16 +118,23 @@ public async Task Login(string ip, int port, string userName, string password, L /// public async Task Logout() { - await InvokeVoidAsync("logout", Id); + if (IsLogined) + { + await InvokeVoidAsync("logout", Id); + } + IsLogined = false; } /// /// 开始实时预览方法 /// /// - public async Task StartRealPlay() + public async Task StartRealPlay(int streamType, int channelId) { - await InvokeVoidAsync("startRealPlay", Id); + if (IsLogined && !IsRealPlaying) + { + IsRealPlaying = await InvokeAsync("startRealPlay", Id, streamType, channelId) ?? false; + } } /// @@ -113,6 +143,36 @@ public async Task StartRealPlay() /// public async Task StopRealPlay() { - await InvokeVoidAsync("stopRealPlay", Id); + if (IsLogined && IsRealPlaying) + { + var result = await InvokeAsync("stopRealPlay", Id) ?? false; + if (result) + { + IsRealPlaying = false; + } + } + } + + private void ThrowIfNotInited() + { + if (!Inited) + { + throw new InvalidOperationException("HikVision Web Plugin not inited"); + } + } + + /// + /// 触发 回调方法由 JavaScript 调用 + /// + /// + [JSInvokable] + public async Task TriggerInited(bool inited) + { + Inited = inited; + + if (OnInitedAsync != null) + { + await OnInitedAsync(inited); + } } } diff --git a/src/components/BootstrapBlazor.HikVision/Components/HikVision.razor.js b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.js similarity index 73% rename from src/components/BootstrapBlazor.HikVision/Components/HikVision.razor.js rename to src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.js index 198f5c39..88a03384 100644 --- a/src/components/BootstrapBlazor.HikVision/Components/HikVision.razor.js +++ b/src/components/BootstrapBlazor.HikVision/Components/HikVisionWebPlugin.razor.js @@ -1,13 +1,14 @@ import { init as initVision, login, logout, startRealPlay, stopRealPlay, dispose as disposeVision } from '../hikvision.js'; import EventHandler from '../../BootstrapBlazor/modules/event-handler.js'; -export async function init(id) { +export async function init(id, invoke) { const el = document.getElementById(id); if (el === null) { return; } - await initVision(id); + const inited = await initVision(id); + await invoke.invokeMethodAsync('TriggerInited', inited); } export { login, logout, startRealPlay, stopRealPlay } diff --git a/src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js b/src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js index 6581b125..d95263af 100644 --- a/src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js +++ b/src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js @@ -11,17 +11,20 @@ export async function init(id) { const el = document.getElementById(id); if (el === null) { - return; + return false; } const result = await initWindow(id); if (result.inited === false) { - return; + return false; } Data.set(id, { - iWndIndex: result.iWndIndex + iWndIndex: result.iWndIndex, + inited: true }); + + return true; } const initWindow = id => { @@ -30,7 +33,7 @@ const initWindow = id => { bWndFull: true, iWndowType: 1, cbSelWnd: function (xmlDoc) { - result.iWndIndex = getTagNameFirstValue(xmlDoc, "SelectWnd") + result.iWndIndex = parseInt(getTagNameFirstValue(xmlDoc, "SelectWnd")); }, cbDoubleClickWnd: function (iWndIndex, bFullScreen) { @@ -59,6 +62,14 @@ const initWindow = id => { export async function login(id, ip, port, userName, password, loginType) { const vision = Data.get(id); + const { inited, logined } = vision; + if (inited !== true || ip.length === 0 || port <= 0 || userName.length === 0 || password.length === 0) { + return false; + } + if (logined === true) { + return true; + } + vision.szDeviceIdentify = `${ip}_${port}`; vision.logined = null; vision.loginErrorCode = null; @@ -84,9 +95,9 @@ export async function login(id, ip, port, userName, password, loginType) { return new Promise((resolve, reject) => { const handler = setInterval(async () => { - if (vision.logined !== void 0) { + if (vision.logined !== null) { clearInterval(handler) - resolve(vision); + resolve(vision.logined); } }, 16); }); @@ -152,34 +163,27 @@ const getChannelInfo = vision => { const handler = setInterval(() => { if (analog_completed && digital_completed && zero_completed) { clearInterval(handler) - resolve(vision); + resolve(); } }, 16); }); } -export function logout(id) { +export async function logout(id) { const vision = Data.get(id); - const { szDeviceIdentify } = vision; + const { szDeviceIdentify, logined } = vision; + if (logined !== true) { + vision.logined = false; + return; + } - let completed = null; - WebVideoCtrl.I_Logout(szDeviceIdentify).then(() => { - completed = true; - }, () => { - completed = false; - }); + stopRealPlay(id); - return new Promise((resolve, reject) => { - const handler = setInterval(() => { - if (completed !== null) { - clearInterval(handler) - resolve(vision); - } - }, 16); - }); + await WebVideoCtrl.I_Logout(szDeviceIdentify); + vision.logined = false; } -export async function startRealPlay(id) { +export async function startRealPlay(id, iStreamType, iChannelID) { const vision = Data.get(id); const { iWndIndex, szDeviceIdentify } = vision; @@ -188,26 +192,28 @@ export async function startRealPlay(id) { const oWndInfo = WebVideoCtrl.I_GetWindowStatus(iWndIndex); const iRtspPort = vision.devicePort.iRtspPort; - const iChannelID = 1; const bZeroChannel = false; - const iStreamType = 1; - + let completed = null; const startRealPlay = function () { WebVideoCtrl.I_StartRealPlay(szDeviceIdentify, { + iWndIndex: iWndIndex, iStreamType: iStreamType, iChannelID: iChannelID, bZeroChannel: bZeroChannel, iPort: iRtspPort, success: function () { - + vision.realPlaying = true; + completed = true; }, error: function (oError) { - + vision.realPlaying = false; + completed = false; } }); }; - if (oWndInfo != null) { + console.log(oWndInfo); + if (oWndInfo !== null) { WebVideoCtrl.I_Stop({ success: function () { startRealPlay(); @@ -217,39 +223,70 @@ export async function startRealPlay(id) { else { startRealPlay(); } + + return new Promise((resolve, reject) => { + const handler = setInterval(() => { + if (completed !== null) { + clearInterval(handler) + resolve(completed); + } + }, 16); + }); } export function stopRealPlay(id) { const vision = Data.get(id); - const { iWndIndex, szDeviceIdentify } = vision; + const { iWndIndex, realPlaying } = vision; + + if (realPlaying !== true) { + return true; + } const oWndInfo = WebVideoCtrl.I_GetWindowStatus(iWndIndex); + let completed = null; if (oWndInfo !== null) { WebVideoCtrl.I_Stop({ success: function () { - + vision.realPlaying = false; + completed = true; }, error: function (oError) { - + completed = false; } }); } + + return new Promise((resolve, reject) => { + const handler = setInterval(() => { + if (completed !== null) { + clearInterval(handler) + resolve(completed); + } + }, 16); + }); } export function dispose(id) { - stopRealPlay(id); - logout(id); + const vision = Data.get(id); + Data.remove(id); + + const { realPlaying, logined } = vision; + if (realPlaying === true) { + stopRealPlay(id); + } + if (logined === true) { + logout(id); + } WebVideoCtrl.I_DestroyPlugin(); - Data.remove(id); } -const getTagNameFirstValue = (xmlDoc, tagName) => { +const getTagNameFirstValue = (xmlDoc, tagName, defaultValue = '0') => { const tags = xmlDoc.getElementsByTagName(tagName); if (tags.length > 0) { return tags[0].textContent; } - return null; + return defaultValue; } const getTagNameValues = (xmlDoc, tagName) => {