diff --git a/HMIcode/SmallProject/.vs/ProjectEvaluation/smallproject.metadata.v7.bin b/HMIcode/SmallProject/.vs/ProjectEvaluation/smallproject.metadata.v7.bin
new file mode 100644
index 0000000..40162aa
Binary files /dev/null and b/HMIcode/SmallProject/.vs/ProjectEvaluation/smallproject.metadata.v7.bin differ
diff --git a/HMIcode/SmallProject/.vs/ProjectEvaluation/smallproject.projects.v7.bin b/HMIcode/SmallProject/.vs/ProjectEvaluation/smallproject.projects.v7.bin
new file mode 100644
index 0000000..070cfdc
Binary files /dev/null and b/HMIcode/SmallProject/.vs/ProjectEvaluation/smallproject.projects.v7.bin differ
diff --git a/HMIcode/SmallProject/.vs/SmallProject/DesignTimeBuild/.dtbcache.v2 b/HMIcode/SmallProject/.vs/SmallProject/DesignTimeBuild/.dtbcache.v2
new file mode 100644
index 0000000..02594a6
Binary files /dev/null and b/HMIcode/SmallProject/.vs/SmallProject/DesignTimeBuild/.dtbcache.v2 differ
diff --git a/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/47464208-905c-4968-b7b4-daab71868c10.vsidx b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/47464208-905c-4968-b7b4-daab71868c10.vsidx
new file mode 100644
index 0000000..7c93b3f
Binary files /dev/null and b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/47464208-905c-4968-b7b4-daab71868c10.vsidx differ
diff --git a/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/99016061-35df-4ad0-b450-4d2ed0662252.vsidx b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/99016061-35df-4ad0-b450-4d2ed0662252.vsidx
new file mode 100644
index 0000000..44cd1cd
Binary files /dev/null and b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/99016061-35df-4ad0-b450-4d2ed0662252.vsidx differ
diff --git a/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/d8c4e8e4-1873-4e77-8586-5052f00c4dfb.vsidx b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/d8c4e8e4-1873-4e77-8586-5052f00c4dfb.vsidx
new file mode 100644
index 0000000..be6bbf5
Binary files /dev/null and b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/d8c4e8e4-1873-4e77-8586-5052f00c4dfb.vsidx differ
diff --git a/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/ec6c225a-3a78-469e-b487-b371c742c8a7.vsidx b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/ec6c225a-3a78-469e-b487-b371c742c8a7.vsidx
new file mode 100644
index 0000000..e3d6f27
Binary files /dev/null and b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/ec6c225a-3a78-469e-b487-b371c742c8a7.vsidx differ
diff --git a/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/f5ecb179-9d7b-4c07-b409-f6e5f7fc6b55.vsidx b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/f5ecb179-9d7b-4c07-b409-f6e5f7fc6b55.vsidx
new file mode 100644
index 0000000..d349136
Binary files /dev/null and b/HMIcode/SmallProject/.vs/SmallProject/FileContentIndex/f5ecb179-9d7b-4c07-b409-f6e5f7fc6b55.vsidx differ
diff --git a/HMIcode/SmallProject/.vs/SmallProject/v17/.futdcache.v2 b/HMIcode/SmallProject/.vs/SmallProject/v17/.futdcache.v2
new file mode 100644
index 0000000..8b06c54
Binary files /dev/null and b/HMIcode/SmallProject/.vs/SmallProject/v17/.futdcache.v2 differ
diff --git a/HMIcode/SmallProject/OpenBLive/Client/BApiClient.cs b/HMIcode/SmallProject/OpenBLive/Client/BApiClient.cs
new file mode 100644
index 0000000..25857bf
--- /dev/null
+++ b/HMIcode/SmallProject/OpenBLive/Client/BApiClient.cs
@@ -0,0 +1,55 @@
+using Newtonsoft.Json;
+using OpenBLive.Client.Data;
+using OpenBLive.Runtime;
+
+namespace OpenBLive.Client
+{
+ public class BApiClient : IBApiClient
+ {
+ ///
+ /// 开启互动玩法
+ ///
+ ///
+ ///
+ ///
+ public async Task StartInteractivePlay(string code, string appId)
+ {
+ var respStr = await BApi.StartInteractivePlay(code, appId);
+ return JsonConvert.DeserializeObject(respStr);
+ }
+
+ ///
+ /// 关闭应用
+ ///
+ /// 应用Id
+ /// 开启应用 返回的gameId
+ ///
+ public async Task EndInteractivePlay(string appId, string gameId)
+ {
+ var respStr = await BApi.EndInteractivePlay(appId, gameId);
+ return JsonConvert.DeserializeObject(respStr);
+ }
+
+ ///
+ /// 批量应用心跳
+ ///
+ /// 开启应用 返回的gameId
+ ///
+ public async Task HeartBeatInteractivePlay(string gameId)
+ {
+ var respStr = await BApi.HeartBeatInteractivePlay(gameId);
+ return JsonConvert.DeserializeObject(respStr);
+ }
+
+ ///
+ /// 批量应用心跳
+ ///
+ /// 开启应用 返回的gameId
+ ///
+ public async Task BatchHeartBeatInteractivePlay(string[] gameIds)
+ {
+ var respStr = await BApi.BatchHeartBeatInteractivePlay(gameIds);
+ return JsonConvert.DeserializeObject(respStr);
+ }
+ }
+}
diff --git a/HMIcode/SmallProject/OpenBLive/Client/Data/AppStartInfo.cs b/HMIcode/SmallProject/OpenBLive/Client/Data/AppStartInfo.cs
new file mode 100644
index 0000000..16948b3
--- /dev/null
+++ b/HMIcode/SmallProject/OpenBLive/Client/Data/AppStartInfo.cs
@@ -0,0 +1,110 @@
+using Newtonsoft.Json;
+
+namespace OpenBLive.Client.Data
+{
+ public class AppStartInfo
+ {
+ ///
+ /// 请求相应 非0为异常case 业务处理
+ ///
+ [JsonProperty("code")]
+ public int Code;
+ ///
+ /// 异常case提示文案
+ ///
+ [JsonProperty("message")]
+ public string Message;
+ ///
+ ///响应体
+ ///
+ [JsonProperty("data")]
+ public AppStartData Data { get; set; }
+
+
+ ///
+ /// 获取GameId
+ ///
+ ///
+ public string GetGameId() => Data?.GameInfo?.GameId;
+ ///
+ /// 获取长链地址
+ ///
+ ///
+ public IList GetWssLink() => Data?.WebsocketInfo?.WssLink;
+
+
+ ///
+ /// 获取长链地址
+ ///
+ ///
+ public string GetAuthBody() => Data?.WebsocketInfo?.AuthBody;
+ }
+
+
+
+ public class AppStartData
+ {
+ ///
+ /// 场次信息
+ ///
+ [JsonProperty("game_info")]
+ public AppStartGameInfo GameInfo;
+ ///
+ /// 长连信息
+ ///
+ [JsonProperty("websocket_info")]
+ public AppStartWebsocketInfo WebsocketInfo;
+ ///
+ /// 主播信息
+ ///
+ [JsonProperty("anchor_info")]
+ public AppStartAnchorInfo AnchorInfo;
+ }
+
+ public class AppStartGameInfo
+ {
+ ///
+ /// 场次id,心跳key(心跳保持20s-60s)调用一次,超过60s无心跳自动关闭,长连停止推送消息
+ ///
+ [JsonProperty("game_id")]
+ public string GameId;
+ }
+ public class AppStartWebsocketInfo
+ {
+ ///
+ /// 长连使用的请求json体 第三方无需关注内容,建立长连时使用即可
+ ///
+ [JsonProperty("auth_body")]
+ public string AuthBody;
+ ///
+ /// wss 长连地址
+ ///
+ [JsonProperty("wss_link")]
+ public List WssLink;
+ }
+
+
+ public class AppStartAnchorInfo
+ {
+ ///
+ /// 主播房间号
+ ///
+ [JsonProperty("room_id")]
+ public long RoomId;
+ ///
+ /// 主播昵称
+ ///
+ [JsonProperty("uname")]
+ public string UName;
+ ///
+ /// 主播头像
+ ///
+ [JsonProperty("uface")]
+ public string UFace;
+ ///
+ /// 主播Uid
+ ///
+ [JsonProperty("uid")]
+ public string Uid;
+ }
+}
diff --git a/HMIcode/SmallProject/OpenBLive/Client/Data/EmptyInfo.cs b/HMIcode/SmallProject/OpenBLive/Client/Data/EmptyInfo.cs
new file mode 100644
index 0000000..7059cff
--- /dev/null
+++ b/HMIcode/SmallProject/OpenBLive/Client/Data/EmptyInfo.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace OpenBLive.Client.Data
+{
+ public class EmptyInfo
+ {
+ ///
+ /// 请求相应 非0为异常case 业务处理
+ ///
+ [JsonProperty("code")]
+ public int Code;
+ ///
+ /// 异常case提示文案
+ ///
+ [JsonProperty("message")]
+ public string Message;
+
+ }
+}
diff --git a/HMIcode/SmallProject/OpenBLive/Client/IBApiClient.cs b/HMIcode/SmallProject/OpenBLive/Client/IBApiClient.cs
new file mode 100644
index 0000000..87598ac
--- /dev/null
+++ b/HMIcode/SmallProject/OpenBLive/Client/IBApiClient.cs
@@ -0,0 +1,43 @@
+using OpenBLive.Client.Data;
+
+namespace OpenBLive.Client
+{
+ ///
+ /// BapiClient 相关文档 https://open-live.bilibili.com/document/doc&tool/auth.html
+ ///
+ public interface IBApiClient
+ {
+ ///
+ /// 开启应用
+ ///
+ ///
+ /// 身份码
+ /// 获取地址 :https://link.bilibili.com/p/center/index#/my-room/start-live
+ ///
+ ///
+ /// AppId
+ /// 申请的应用Id
+ ///
+ ///
+ Task StartInteractivePlay(string code, string appId);
+ ///
+ /// 关闭应用
+ ///
+ /// 应用Id
+ /// 开启玩法 返回的gameId
+ ///
+ Task EndInteractivePlay(string appId, string gameId);
+ ///
+ /// 应用心跳
+ ///
+ /// 开启玩法 返回的gameId
+ ///
+ Task HeartBeatInteractivePlay(string gameId);
+ ///
+ /// 批量应用心跳
+ ///
+ /// 开启玩法 返回的gameId
+ ///
+ Task BatchHeartBeatInteractivePlay(string[] gameIds);
+ }
+}
diff --git a/HMIcode/SmallProject/OpenBLive/OpenBLive.csproj b/HMIcode/SmallProject/OpenBLive/OpenBLive.csproj
new file mode 100644
index 0000000..3b32491
--- /dev/null
+++ b/HMIcode/SmallProject/OpenBLive/OpenBLive.csproj
@@ -0,0 +1,23 @@
+
+
+
+ Library
+ net6.0
+ enable
+ enable
+
+
+
+ 1701;1702;CS8618;CS8625;8603;8600;8601
+
+
+
+ 1701;1702;CS8618;CS8625;8603;8600;8601
+
+
+
+
+
+
+
+
diff --git a/HMIcode/SmallProject/OpenBLive/Runtime/BApi.cs b/HMIcode/SmallProject/OpenBLive/Runtime/BApi.cs
new file mode 100644
index 0000000..1436ae9
--- /dev/null
+++ b/HMIcode/SmallProject/OpenBLive/Runtime/BApi.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using OpenBLive.Runtime.Data;
+using OpenBLive.Runtime.Utilities;
+using Logger = OpenBLive.Runtime.Utilities.Logger;
+#if NET5_0_OR_GREATER
+using System.Net;
+#elif UNITY_2020_3_OR_NEWER
+using UnityEngine.Networking;
+#endif
+
+namespace OpenBLive.Runtime
+{
+ ///
+ /// 各类b站api
+ ///
+ public static class BApi
+ {
+ ///
+ /// 是否为测试环境的api
+ ///
+ public static bool isTestEnv;
+
+ ///
+ /// 开放平台域名
+ ///
+ private static string OpenLiveDomain =>
+ isTestEnv ? "http://test-live-open.biliapi.net" : "https://live-open.biliapi.com";
+
+ ///
+ /// 应用开启
+ ///
+ private const string k_InteractivePlayStart = "/v2/app/start";
+
+ ///
+ /// 应用关闭
+ ///
+ private const string k_InteractivePlayEnd = "/v2/app/end";
+
+ ///
+ /// 应用心跳
+ ///
+ private const string k_InteractivePlayHeartBeat = "/v2/app/heartbeat";
+
+ ///
+ /// 应用批量心跳
+ ///
+ private const string k_InteractivePlayBatchHeartBeat = "/v2/app/batchHeartbeat";
+
+
+ private const string k_Post = "POST";
+
+
+
+ public static async Task StartInteractivePlay(string code, string appId)
+ {
+ var postUrl = OpenLiveDomain + k_InteractivePlayStart;
+ var param = $"{{\"code\":\"{code}\",\"app_id\":{appId}}}";
+
+ var result = await RequestWebUTF8(postUrl, k_Post, param);
+
+ return result;
+ }
+
+ public static async Task EndInteractivePlay(string appId, string gameId)
+ {
+ var postUrl = OpenLiveDomain + k_InteractivePlayEnd;
+ var param = $"{{\"app_id\":{appId},\"game_id\":\"{gameId}\"}}";
+
+ var result = await RequestWebUTF8(postUrl, k_Post, param);
+ return result;
+ }
+
+ public static async Task HeartBeatInteractivePlay(string gameId)
+ {
+ var postUrl = OpenLiveDomain + k_InteractivePlayHeartBeat;
+ string param = "";
+ if (gameId != null)
+ {
+ param = $"{{\"game_id\":\"{gameId}\"}}";
+
+ }
+
+ var result = await RequestWebUTF8(postUrl, k_Post, param);
+ return result;
+ }
+
+ public static async Task BatchHeartBeatInteractivePlay(string[] gameIds)
+ {
+ var postUrl = OpenLiveDomain + k_InteractivePlayBatchHeartBeat;
+ GameIds games = new GameIds()
+ {
+ gameIds = gameIds
+ };
+ var param = JsonConvert.SerializeObject(games);
+ var result = await RequestWebUTF8(postUrl, k_Post, param);
+ return result;
+ }
+
+ private static async Task RequestWebUTF8(string url, string method, string param,
+ string cookie = null)
+ {
+#if NET5_0_OR_GREATER
+ string result = "";
+ HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
+ req.Method = method;
+
+ if (param != null)
+ {
+ SignUtility.SetReqHeader(req, param, cookie);
+ }
+
+ HttpWebResponse httpResponse = (HttpWebResponse)(await req.GetResponseAsync());
+ Stream stream = httpResponse.GetResponseStream();
+
+ if (stream != null)
+ {
+ using StreamReader reader = new StreamReader(stream, Encoding.UTF8);
+ result = await reader.ReadToEndAsync();
+ }
+
+ return result;
+
+#elif UNITY_2020_3_OR_NEWER
+ UnityWebRequest webRequest = new UnityWebRequest(url);
+ webRequest.method = method;
+ if (param != null)
+ {
+ SignUtility.SetReqHeader(webRequest, param, cookie);
+ }
+
+ webRequest.downloadHandler = new DownloadHandlerBuffer();
+ webRequest.disposeUploadHandlerOnDispose = true;
+ webRequest.disposeDownloadHandlerOnDispose = true;
+ await webRequest.SendWebRequest();
+ var text = webRequest.downloadHandler.text;
+
+ webRequest.Dispose();
+ return text;
+#endif
+ }
+#if UNITY_2020_3_OR_NEWER
+ private static TaskAwaiter GetAwaiter(this UnityEngine.AsyncOperation asyncOp)
+ {
+ var tcs = new TaskCompletionSource