using HiTeachCE.Dtos; using HiTeachCE.Helpers; using HiTeachCE.Models; using HiTeachCE.Services; using IdentityModel; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using TEAMModelOS; using TEAMModelOS.SDK.Context.Configuration; using TEAMModelOS.SDK.Context.Exception; using TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest; using TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse; using TEAMModelOS.SDK.Helper.Common.CollectionHelper; namespace HiTeachCE.Controllers { [Route("api/[controller]")] [ApiController] public class MqttController:BaseController { public static int smsTTL = 4 * 60; public static int ticketTTL = 1 * 24 * 60 * 60; //public static int freeTTL = 7 * 24 * 60 * 60; public static int deviceTTL = 1 * 24 * 60 * 60; public static string freeOrg = "7f847a9f05224184a5d01ee69a6b00d6"; public static string model_teach = "teach"; public static string model_prepare = "prepare"; private readonly OrganizationService organizationService; private readonly MemberService memberService; private readonly ActivationCodeService activationCodeService; public MqttController( OrganizationService organization, MemberService member, ActivationCodeService activationCode) { organizationService = organization; memberService = member; activationCodeService = activationCode; } /// /// 注册装置 /// /// /// [HttpPost("regist")] [Authorize(Policy = Constant.Role_Lecturer)] public BaseJosnRPCResponse Regist(JosnRPCRequest> request) { JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom(); string unionid = GetLoginUser(JwtClaimTypes.Id); /** "params": { "deviceId": "f67fb5dd-ee1b-d3b7-9b95-61022d7e8acd", "clientId": "931dee8c-74be-4c9b-a602-c74583b0e985", } */ if (request.@params.TryGetValue("deviceId", out string deviceId) && request.@params.TryGetValue("orgCode", out string orgCode) && !string.IsNullOrEmpty(unionid)) { Dictionary dict = ActivationValid(orgCode, unionid); if (dict != null && dict.TryGetValue("flag", out object flag) && bool.Parse(flag.ToString())) { if (RedisHelper.HExists("device:" + deviceId, deviceId)) { } else { RedisHelper.HSet("device-oud:" + deviceId, deviceId, new OrgUserDevice {orgCode=orgCode,deviceId=deviceId,unionid=unionid }); RedisHelper.HSet("device:" + deviceId, deviceId, null); RedisHelper.Expire("device-oud:" + deviceId, deviceTTL); RedisHelper.Expire("device:" + deviceId, deviceTTL); } return builder.Data(new Dictionary { { "deviceId", deviceId } }).build(); } else { throw new BizException("授权失败!", 2); } } else { throw new BizException("参数错误!", 2); } } /// /// 创建教室 /// /// /// [HttpPost("createGroup")] [Authorize(Policy = Constant.Role_Lecturer)] public BaseJosnRPCResponse CreateGroup(JosnRPCRequest> request) { /** "params": { "deviceId": "f67fb5dd-ee1b-d3b7-9b95-61022d7e8acd", "doBoundGroupNum": false, "extraInfo": {} } */ JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom(); //string ClientId =// new List() { "fb564dde14df423cafac2085936e3b96" }; // GetLoginUser(JwtClaimTypes.ClientId); string groupNum; if (request.@params.TryGetValue("deviceId", out string deviceId) ) { if (RedisHelper.HExists("device:" + deviceId, deviceId)) { groupNum = RedisHelper.HGet("device:" + deviceId, deviceId); if (string.IsNullOrEmpty(groupNum)) { do { groupNum = RandGroupNum(); } while (RedisHelper.Exists("group:" + groupNum)); RedisHelper.HSet("group:" + groupNum, deviceId, null); RedisHelper.Expire("group:" + groupNum, deviceTTL); RedisHelper.HSet("device:" + deviceId, deviceId, groupNum); } } else { throw new BizException("装置未注册", 2); } } else { throw new BizException("参数错误", 2); } return builder.Data(groupNum).build(); } public string RandGroupNum() { Random random = new Random(); String result = ""; for (int i = 0; i < 6; i++) { result += random.Next(0, 10); } return result; } /// /// 加入教室 /// /// /// [HttpPost("joinGroup")] [Authorize(Policy = Constant.Role_LecturerLearner)] public BaseJosnRPCResponse JoinGroup(JosnRPCRequest> request) { // string ClientId = GetLoginUser(JwtClaimTypes.ClientId); string Unionid = GetLoginUser(JwtClaimTypes.Id); string Role = GetLoginUser(JwtClaimTypes.Role); JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom(); Dictionary dict; /** "params": { "deviceId": "f67fb5dd-ee1b-d3b7-9b95-61022d7e8acd", "groupNum": "818288" } */ if (request.@params.TryGetValue("deviceId", out string deviceId) && request.@params.TryGetValue("groupNum", out string groupNum) && !string.IsNullOrEmpty(deviceId) && !string.IsNullOrEmpty(groupNum) ) { if (RedisHelper.Exists("group:" + groupNum)) { Dictionary member = RedisHelper.HGetAll("group:" + groupNum); if (member != null) { foreach (string key in member.Keys) { if (member[key] != null && member[key].role .Contains("lecturer") && Role.Contains("lecturer") && Unionid != member[key].unionid) { throw new BizException("教室只能有一个创建者加入", ResponseCode.DATA_EXIST); } } } dict = MqttInfo(deviceId, deviceId, groupNum, Unionid, Role); Dictionary members = RedisHelper.HGetAll("group:" + groupNum); List learners = new List(); MQTTMember lecturer = null; foreach (string key in members.Keys) { if (members[key].role.Contains("lecturer")) { lecturer= members[key]; } else { learners.Add(members[key]); } } dict.Add("lecturer", lecturer); dict.Add("learners", learners); } else { throw new BizException("教室不存在", 2); } } else { throw new BizException("参数错误", 2); } return builder.Data(dict).build(); } private static Dictionary MqttInfo(string ClientId, string deviceId, string groupNum, string Unionid, string Role) { string brokerHostName = BaseConfigModel.Configuration["brokerHostName"]; Dictionary dict = new Dictionary(); string password = brokerHostName + "/" + groupNum + "/" + deviceId + "/" + ClientId; //发给前端使用的 string h1 = BCrypt.Net.BCrypt.HashPassword(password); //后端存储使用的 string h2 = BCrypt.Net.BCrypt.HashPassword(h1, BCrypt.Net.SaltRevision.Revision2); bool validPassword = BCrypt.Net.BCrypt.Verify(h1, h2); string uname = password; Dictionary connectInfo = new Dictionary { { "brokerHostName", brokerHostName }, { "brokerHostNameWSS", "wss://" +brokerHostName+"/mqtt/"} , { "clientID", deviceId }, //使用BCrypt加密 { "password",h1} , { "username",uname} }; Dictionary subscribeTopic = BaseConfigModel.Configuration.GetSection("SubscribeTopic").Get>(); subscribeTopic["receiveMsg"] = subscribeTopic["receiveMsg"].Replace("{deviceId}", deviceId); Dictionary publishTopic = BaseConfigModel.Configuration.GetSection("PublishTopic").Get>(); publishTopic["sendMsg"] = publishTopic["sendMsg"].Replace("{deviceId}", deviceId).Replace("{groupNum}", groupNum); dict.Add("mqtt", new Dictionary() { { "connectInfo", connectInfo }, { "publishTopic", publishTopic }, { "subscribeTopic", subscribeTopic } }); List topic = new List(); topic.AddRange(publishTopic.Values.ToList()); topic.AddRange(subscribeTopic.Values.ToList()); MQTTInfo mqtt = new MQTTInfo { brokerHostName = brokerHostName, brokerHostNameWSS = "wss://" + brokerHostName + "/mqtt/", clientID = deviceId, //使用BCrypt加密 password = h2, username = uname, topic = topic }; var groupMember = new MQTTMember { clientId = ClientId, deviceId = deviceId, unionid = Unionid, role = Role, groupNum = groupNum }; RedisHelper.HSet("group:" + groupNum, deviceId, groupMember); RedisHelper.HSet("mqtt:" + deviceId, deviceId, mqtt); RedisHelper.Expire("mqtt:" + deviceId, deviceTTL); return dict; } /// /// 教学认证 /// /// /// [HttpPost("auth")] [Authorize(Policy = Constant.Role_Lecturer)] public BaseJosnRPCResponse Auth(JosnRPCRequest request) { JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom(); string unionid = GetLoginUser(JwtClaimTypes.Id); string phoneNumber = GetLoginUser(JwtClaimTypes.PhoneNumber); Expression> mlinq = null; mlinq = m => m.unionid == unionid; List> dict = new List>(); List members = memberService.GetList(mlinq); if (members.IsNotEmpty()) { foreach (var code in members) { var dt = ActivationValid(code.orgCode, unionid); if (dt != null) { dict.Add(dt); } } } else { long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds(); ///处理该机构是否激活人数达到上线 Expression> limitlinq = null; limitlinq = m => m.orgCode == freeOrg && m.status == 1; List countMembers = memberService.GetList(limitlinq); Expression> alinq = null; alinq = m => m.orgCode == freeOrg && m.status == 1; List activationCodes = activationCodeService.GetList(alinq); if (activationCodes.IsNotEmpty()) { //判断组织机构人员是否已经达到最大激活数量 if (countMembers.IsNotEmpty() && countMembers.Count >= activationCodes[0].maximum) { //throw new BizException(":HiTeachCE(测试)授权人数超过上限!", 2); } else { List RootUsers = BaseConfigModel.Configuration.GetSection("RootUser").Get>(); string role = "admin,lecturer"; if (RootUsers.Contains(phoneNumber)) { role = "root," + role; } Member member = new Member { id = Guid.NewGuid().ToString(), orgCode = freeOrg, admin = 0, status = 1, // expires = time + freeTTL, unionid = unionid, createTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds() }; bool flag = memberService.Insert(member); if (flag) { var dt = ActivationValid(freeOrg, unionid); if (dt != null) { dict.Add(dt); } } else { //throw new BizException("无法加入:HiTeachCE(测试)!", 2); } } } else { } } return builder.Data(dict).build(); } public Dictionary ActivationValid(string orgCode, string unionid) { //调用ActivationCode Expression> olinq = null; olinq = m => m.code == orgCode; Organization org = organizationService.GetList(olinq).FirstOrDefault(); if (org != null) { Dictionary dict = new Dictionary() { { "org", new { orgCode = "", name = org.name } }, { "flag", false } }; if (org.status != 1) { dict.Add("msg", "组织机构被禁用!"); } else { //验证组织机构的激活码状态,时间,最大人数 Expression> linq = null; linq = m => m.orgCode == org.code; List activationCodes = activationCodeService.GetList(linq); if (activationCodes.IsNotEmpty()) { if (activationCodes[0].status == 1) { long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds(); if (activationCodes[0].expires > time) { int max = activationCodes[0].maximum; Expression> mlinq = null; mlinq = l => l.orgCode == org.code; List members = memberService.GetList(mlinq); if (members.Count > max) { dict.Add("msg", "产品授权人数超过上限!"); } else { if (members.Where(x => x.status == 1).Select(x => x.unionid).ToList().Contains(unionid)) { dict["org"] = new { orgCode = org.code, name = org.name }; dict["flag"] = true; } else { dict.Add("msg", "组织机构未对该用户授权!"); } } } else { dict.Add("msg", "产品授权已经过期!"); } } else { dict.Add("msg", "组织机构授权状态被禁用!"); } } else { dict.Add("msg", "组织机构没有授权信息!"); } } return dict; } return null; } } }