using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; using WingInterfaceLibrary.DB.Request; using WingInterfaceLibrary.DTO.Device; using WingInterfaceLibrary.DTO.LiveRoom; using WingInterfaceLibrary.DTO.Share; using WingInterfaceLibrary.Enum; using WingInterfaceLibrary.Interface; using WingInterfaceLibrary.Internal.Request; using WingInterfaceLibrary.Notifications; using WingInterfaceLibrary.Notifications.Live; using WingInterfaceLibrary.Notifications.Remote; using WingInterfaceLibrary.Request; using WingInterfaceLibrary.Request.Authentication; using WingInterfaceLibrary.Request.Device; using WingInterfaceLibrary.Request.Remote; using WingServerCommon.Config; using WingServerCommon.Interfaces.Cache; using WingServerCommon.Service; namespace WingDeviceService.Service { /// /// 设备直播 /// public partial class DeviceService : JsonRpcService, IDeviceService { /// /// 用户进入设备直播房间 /// /// 用户进入设备直播房间请求实体 /// public async Task JoinDeviceLiveRoomAsync(JoinDeviceLiveRoomRequest request) { var userInfo = await _authenticationService.GetTokenAsync(request); var deviceCode = request.DeviceCode; var deviceTokenInfo = CacheMaintenance.Instance.Get().Where(x => x.ClientId == deviceCode).FirstOrDefault(); if (deviceTokenInfo == null || !deviceTokenInfo.IsOnline) { ThrowCustomerException(CustomerRpcCode.DeviceNotOnline, "DeviceNotOnline"); } if (deviceTokenInfo.IsOldPlatform) { await _deviceForwardService.GetDeviceVideoInfosAsync(new GetDeviceVideoInfosRequest { DeviceCode = deviceCode }); } var deviceInfo = CacheMaintenance.Instance.Get().Get(deviceCode); if (deviceInfo == null) { ThrowCustomerException(CustomerRpcCode.DeviceNotExist, "Not find device"); } if (!deviceInfo.LiveOpened) { ThrowCustomerException(CustomerRpcCode.DeviceLiveClosed, "DeviceLiveClosed"); } return await JoinDeviceLiveRoomAsync(deviceCode, userInfo); } /// /// 用户离开设备直播房间 /// /// 用户离开设备直播房间请求实体 /// public async Task LeaveDeviceLiveRoomAsync(LeaveDeviceLiveRoomRequest request) { var userInfo = await _authenticationService.GetTokenAsync(request); var userCode = userInfo.ClientId; var deviceCode = request.DeviceCode; var liveRoom = await _rtcService.GetInitiatingRoomByDeviceCodeAsync(new GetInitiatingRoomByDeviceCodeRequest { DeviceCode = deviceCode }); if (liveRoom != null) { //移除观众 var removeViewerResult = await _rtcService.RemoveViewerAsync(new RemoveViewerRequest { LiveRoomCode = liveRoom.LiveRoomCode, UserCode = userInfo.ClientId, }); var timeoutTime = DateTime.UtcNow.AddSeconds(-1 * _reportStateTimeout); if (liveRoom.BusinessModule == BusinessModuleEnum.DeviceLiving && !liveRoom.ViewerInfos.Any(x => x.UserCode != userCode && x.LastReportTime >= timeoutTime)) { await _rtcService.CloseAsync(new CloseRequest { LiveRoomCode = liveRoom.LiveRoomCode }); } } return true; } /// /// 上报观看直播状态 /// /// 上报观看直播状态请求实体 /// public async Task ReportLiveViewStateAsync(ReportLiveViewStateRequest request) { var userInfo = await _authenticationService.GetTokenAsync(request); var deviceCode = request.DeviceCode; var liveRoom = await _rtcService.GetInitiatingRoomByDeviceCodeAsync(new GetInitiatingRoomByDeviceCodeRequest { DeviceCode = deviceCode }); if (liveRoom != null) { //添加观众 var addOrUpdateViewerResult = await _rtcService.SaveViewerAsync(new SaveViewerRequest { LiveRoomCode = liveRoom.LiveRoomCode, UserCode = userInfo.ClientId, UserName = userInfo.AccountName, }); } return true; } /// /// 生成设备直播分享地址 /// /// 生成设备直播分享地址请求实体 /// /// public async Task CreateLiveShareInfoAsync(CreateLiveShareInfoRequest request) { var deviceCode = request.DeviceCode; var deviceInfo = CacheMaintenance.Instance.Get().Get(deviceCode); if (deviceInfo == null) { ThrowCustomerException(CustomerRpcCode.DeviceNotExist, "Not find device"); } if (!deviceInfo.LiveOpened) { ThrowCustomerException(CustomerRpcCode.DeviceLiveClosed, "DeviceLiveClosed"); } var userInfo = await _authenticationService.GetTokenAsync(request); var shareInfo = new DeviceLiveShareInfoDTO { DeviceCode = request.DeviceCode, ShareUserCode = userInfo.Code, ShareUserName = userInfo.AccountName, ShareTime = DateTime.UtcNow, }; var shareContent = Newtonsoft.Json.JsonConvert.SerializeObject(shareInfo); var shortCode = await _shareDBService.AddShareInfoAsync(new AddShareInfoDBRequest { Data = new ShareDTO { ShareContent = shareContent } }); return new CreateLiveShareInfoResult { ShareUrl = string.Format(_deviceShareUrl, shortCode), }; } /// /// 用户进入设备直播房间(无token) /// /// 用户进入设备直播房间请求实体 /// /// public async Task JoinDeviceLiveRoomByShareAsync(JoinDeviceLiveRoomByShareRequest request) { if (string.IsNullOrWhiteSpace(request.ShareCode)) { ThrowCustomerException(CustomerRpcCode.ShareCodeIsEmpty, "ShareCodeIsEmpty"); } var shareResult = await _shareDBService.GetShareInfoAsync(new GetShareInfoDBRequest { ShortCode = request.ShareCode, }); if (string.IsNullOrWhiteSpace(shareResult.ShareContent)) { ThrowCustomerException(CustomerRpcCode.DeviceShareDataError, "DeviceShareDataError"); } DeviceLiveShareInfoDTO shareInfo = null; try { shareInfo = Newtonsoft.Json.JsonConvert.DeserializeObject(shareResult.ShareContent); } catch (Exception ex) { ThrowCustomerException(CustomerRpcCode.DeviceShareDataError, "DeviceShareDataError"); } if (shareInfo == null || shareInfo.ShareTime.AddSeconds(_shareEffectiveSeconds) < DateTime.UtcNow) { ThrowCustomerException(CustomerRpcCode.DeviceShareExpired, "DeviceShareExpired"); } var deviceCode = shareInfo.DeviceCode; var deviceInfo = CacheMaintenance.Instance.Get().Get(deviceCode); if (deviceInfo == null) { ThrowCustomerException(CustomerRpcCode.DeviceNotExist, "Not find device"); } if (!deviceInfo.LiveOpened) { ThrowCustomerException(CustomerRpcCode.DeviceLiveClosed, "DeviceLiveClosed"); } var deviceTokenInfo = CacheMaintenance.Instance.Get().Where(x => x.ClientId == deviceCode).FirstOrDefault(); if (deviceTokenInfo == null || !deviceTokenInfo.IsOnline) { ThrowCustomerException(CustomerRpcCode.DeviceNotOnline, "DeviceNotOnline"); } if (deviceTokenInfo.IsOldPlatform) { await _deviceForwardService.GetDeviceVideoInfosAsync(new GetDeviceVideoInfosRequest { DeviceCode = deviceCode }); } var joinResult = await JoinDeviceLiveRoomAsync(deviceCode); return new JoinDeviceLiveRoomByShareResult { RoomNo = joinResult.RoomNo, LiveProtocol = EnvironmentConfigs.General.LiveProtocolDetail(), ReportStateIntervalSeconds = joinResult.ReportStateIntervalSeconds, DeviceCode = joinResult.DeviceCode, MergedChannel = joinResult.MergedChannel, MergedVideoOutputWidth = joinResult.MergedVideoOutputWidth, MergedVideoOutputHeight = joinResult.MergedVideoOutputHeight, VideoDeviceInfos = joinResult.VideoDeviceInfos, IsOldPlatform = joinResult.IsOldPlatform, SupportRtc = joinResult.SupportRtc, }; } /// /// 用户离开设备直播房间(无token) /// /// 用户离开设备直播房间请求实体 /// /// public async Task LeaveDeviceLiveRoomByShareAsync(LeaveDeviceLiveRoomByShareRequest request) { if (string.IsNullOrWhiteSpace(request.DeviceCode)) { ThrowCustomerException(CustomerRpcCode.DeviceCodeIsEmpty, "DeviceCodeIsEmpty"); } if (string.IsNullOrWhiteSpace(request.ViewerUniqueId)) { ThrowCustomerException(CustomerRpcCode.UniqueIdIsEmpty, "UniqueIdIsEmpty"); } var userCode = request.ViewerUniqueId; var deviceCode = request.DeviceCode; var liveRoom = await _rtcService.GetInitiatingRoomByDeviceCodeAsync(new GetInitiatingRoomByDeviceCodeRequest { DeviceCode = deviceCode }); if (liveRoom != null) { //移除观众 var removeViewerResult = await _rtcService.RemoveViewerAsync(new RemoveViewerRequest { LiveRoomCode = liveRoom.LiveRoomCode, UserCode = userCode, }); var timeoutTime = DateTime.UtcNow.AddSeconds(-1 * _reportStateTimeout); if (liveRoom.BusinessModule == BusinessModuleEnum.DeviceLiving && !liveRoom.ViewerInfos.Any(x => x.UserCode != userCode && x.LastReportTime >= timeoutTime)) { await _rtcService.CloseAsync(new CloseRequest { LiveRoomCode = liveRoom.LiveRoomCode }); } } return true; } /// /// 上报观看直播状态(无token) /// /// 上报观看直播状态请求实体 /// /// public async Task ReportLiveViewStateByShareAsync(ReportLiveViewStateByShareRequest request) { if (string.IsNullOrWhiteSpace(request.DeviceCode)) { ThrowCustomerException(CustomerRpcCode.DeviceCodeIsEmpty, "DeviceCodeIsEmpty"); } if (string.IsNullOrWhiteSpace(request.ViewerUniqueId)) { ThrowCustomerException(CustomerRpcCode.UniqueIdIsEmpty, "UniqueIdIsEmpty"); } var deviceCode = request.DeviceCode; var liveRoom = await _rtcService.GetInitiatingRoomByDeviceCodeAsync(new GetInitiatingRoomByDeviceCodeRequest { DeviceCode = deviceCode }); if (liveRoom != null) { //添加观众 var uniqueId = request.ViewerUniqueId; var addOrUpdateViewerResult = await _rtcService.SaveViewerAsync(new SaveViewerRequest { LiveRoomCode = liveRoom.LiveRoomCode, UserCode = uniqueId, UserName = uniqueId, }); } return true; } /// /// 开始直播 /// /// /// /// private async Task JoinDeviceLiveRoomAsync(string deviceCode, TokenDTO userInfo = null) { var deviceInfo = CacheMaintenance.Instance.Get().Get(deviceCode); if (deviceInfo == null) { ThrowCustomerException(CustomerRpcCode.DeviceNotExist, "Not find device"); } var liveRoom = await _rtcService.GetInitiatingRoomByDeviceCodeAsync(new GetInitiatingRoomByDeviceCodeRequest { DeviceCode = deviceCode }); var deviceTokenInfo = CacheMaintenance.Instance.Get().Where(x => x.ClientId == deviceCode)?.FirstOrDefault(); LiveMemberDTO deviceMemberInfo; if (liveRoom != null) { if (liveRoom.LiveRoomCode == deviceCode) { //设备正在推流 deviceMemberInfo = liveRoom.DeviceInfos.FirstOrDefault(x => x.Code == deviceCode); if (deviceMemberInfo?.Status == LiveMemberStatus.Joined) { if (userInfo != null) { //添加观众 await _rtcService.SaveViewerAsync(new SaveViewerRequest { LiveRoomCode = liveRoom.LiveRoomCode, UserCode = userInfo.ClientId, UserName = userInfo.AccountName, }); } return new JoinDeviceLiveRoomResult { RoomNo = liveRoom.RtcRoomId, LiveProtocol = EnvironmentConfigs.General.LiveProtocolDetail(), ReportStateIntervalSeconds = _reportStateIntervalSeconds, DeviceCode = deviceCode, MergedChannel = deviceInfo.MergedChannel, MergedVideoOutputWidth = deviceInfo.MergedVideoOutputWidth, MergedVideoOutputHeight = deviceInfo.MergedVideoOutputHeight, VideoDeviceInfos = deviceMemberInfo.VideoDeviceInfos?.Select(x => new VideoDeviceInfoDTO { VideoDeviceId = x.VideoDeviceId, VideoDeviceSourceType = x.VideoDeviceSourceType, LiveData = x.LiveData })?.ToList() ?? new List(), IsOldPlatform = deviceTokenInfo != null && deviceTokenInfo.IsOnline && deviceTokenInfo.IsOldPlatform, SupportRtc = deviceInfo.SupportRtc, }; } } } //新增或更新设备直播间 var deviceName = deviceInfo.DisplayName; var deviceLiveInfo = new LiveMemberDTO { Code = deviceCode, Name = deviceName, MemberType = LiveMemberEnum.Device, HeadImageToken = deviceInfo.HeadPicUrl, Status = LiveMemberStatus.Accepted, }; var room = new LiveRoomDTO { LiveRoomCode = deviceCode, Name = deviceName, RelatedCode = deviceCode, BusinessModule = BusinessModuleEnum.DeviceLiving, Status = LiveRoomStatus.Default, UserInfos = new List(), DeviceInfos = new List { deviceLiveInfo } }; await _rtcService.AddOrUpdateLiveRoomAsync(new AddOrUpdateLiveRoomRequest { LiveRoom = room, }); var initiateResult = await _rtcService.InitiateAsync(new InitiateRequest { LiveRoomCode = deviceCode, InitiatorCode = deviceCode, }); deviceMemberInfo = initiateResult.DeviceInfos.FirstOrDefault(x => x.Code == deviceCode); if (userInfo != null) { //添加观众 await _rtcService.SaveViewerAsync(new SaveViewerRequest { LiveRoomCode = initiateResult.LiveRoomCode, UserCode = userInfo.ClientId, UserName = userInfo.AccountName, }); } return new JoinDeviceLiveRoomResult { RoomNo = initiateResult.RtcRoomId, LiveProtocol = EnvironmentConfigs.General.LiveProtocolDetail(), ReportStateIntervalSeconds = _reportStateIntervalSeconds, DeviceCode = deviceCode, MergedChannel = deviceInfo.MergedChannel, MergedVideoOutputWidth = deviceInfo.MergedVideoOutputWidth, MergedVideoOutputHeight = deviceInfo.MergedVideoOutputHeight, VideoDeviceInfos = deviceMemberInfo.VideoDeviceInfos?.Select(x => new VideoDeviceInfoDTO { VideoDeviceId = x.VideoDeviceId, VideoDeviceSourceType = x.VideoDeviceSourceType, LiveData = x.LiveData })?.ToList() ?? new List(), IsOldPlatform = deviceTokenInfo != null && deviceTokenInfo.IsOnline && deviceTokenInfo.IsOldPlatform, SupportRtc = deviceInfo.SupportRtc, }; } } }