这是这个系列的最后一篇,制作一个AutoCAD插件来获取AutoCAD的命令使用情况,并上传到云端服务。首先我使用创建一个AutoCAD 插件,这个向导会帮助我添加一些AutoCAD相关的引用。另外因为我要用到前面自定义的数据模型,在之前为了在这个项目中重用,我已经把他独立成一个单独的项目,现在在这个AutoCAD插件项目中添加到这个数据模型项目的引用。
本文连接:
在AutoCAD中获取命令的使用情况可以使用AutoCAD的一个非常简单的API,即监听Document 的CommandEnded事件。看下面的代码,首先定义了一个字典用于存储命令使用统计信息,然后定义了一个AutoCAD自定义命令,在这个命令中捕捉Document的Ended事件。在Document——Ended事件中,可以通过e.GobalCommandName取到执行成功的AutoCAD命令名字,添加到字典中。
private Dictionary<string, int> _commandHitDic = new Dictionary<string, int>(); [CommandMethod("ACV_MonitorCommandEvents")] public void MonitorCommandEvents_Method() { SubscribeToDoc(Application.DocumentManager.MdiActiveDocument); GetEditor().WriteMessage("Magic ball is listening, keep working... "); } public void SubscribeToDoc(Document doc) { doc.CommandEnded += new CommandEventHandler(doc_CommandEnded); } void doc_CommandEnded(object sender, CommandEventArgs e) { string commandName = e.GlobalCommandName; // filter out the custom commands of this application if (commandName.StartsWith("ACV")) { return; } AddCommandHit(commandName); } private void AddCommandHit(string commandName) { if (_commandHitDic.Keys.Contains<string>(commandName)) { _commandHitDic[commandName]++; } else { _commandHitDic.Add(commandName, 1); } }
下面就是把字典中的统计信息上传到云端。前面的文章中已经结束了云端REST服务的实现,AutoCAD插件作为客户端只要发送REST请求即可。这里我使用了一个比较流行的类库,废话不多说了,看代码:
[CommandMethod("ACV_UpdateToCloud")] public void UpdateToCloud() { UserCommandsHit usrCmdsHit = null; RestClient client = new RestClient(BASE_URL); client.AddHandler("application/json", new JsonDeserializer()); usrCmdsHit = GetUserCommadsHitByUserName(_userName, client); //CommandHit record with this username is not found in cloud //Add one record for this user. if (usrCmdsHit == null) { //add user command hit record usrCmdsHit = BuildNewUserCommandsHitFromDictionary(_userName,_commandHitDic); //POST to add new AddNewToCloud(usrCmdsHit, client); } else { //update the user command hit with dictionary usrCmdsHit = UpdateUserCommandsHitFromDictionary(usrCmdsHit,_commandHitDic); //PUT to update UpdateToCloud(usrCmdsHit, client); } GetEditor().WriteMessage("\n Your command usage statastic has been updated to cloud succesfully."); GetEditor().WriteMessage("\n Keep working or open http://acadcommandwebviewer.cloudapp.net/ with a modern broswerto view the magic ball ;) "); GetEditor().WriteMessage("\n Chrome/Firefox are recommended. "); System.Diagnostics.Process.Start("http://acadcommandwebviewer.cloudapp.net/"); } private UserCommandsHit GetUserCommadsHitByUserName( string userName, RestClient client) { UserCommandsHit usrCmdsHit = null; RestRequest reqGet = new RestRequest(); reqGet.Resource = "api/AcadCommands"; reqGet.Method = Method.GET; reqGet.RequestFormat = DataFormat.Json; reqGet.AddHeader("Accept", "Application/json"); reqGet.JsonSerializer = new RestSharp.Serializers.JsonSerializer(); reqGet.AddParameter("username", userName); var respGet = client.Execute<UserCommandsHit>(reqGet); if (respGet.StatusCode == System.Net.HttpStatusCode.OK) { if (respGet.Data != null) { usrCmdsHit = respGet.Data; } else { usrCmdsHit = Newtonsoft.Json.JsonConvert .DeserializeObject<UserCommandsHit>(respGet.Content); } } return usrCmdsHit; }
private UserCommandsHit BuildNewUserCommandsHitFromDictionary( string userName, Dictionary<string, int> commandHitDic) { UserCommandsHit usrCmdsHit = new UserCommandsHit(); usrCmdsHit.UserName = userName; List<CommandHit> list = new List<CommandHit>(); foreach (var cmdName in commandHitDic.Keys) { CommandHit ch = new CommandHit { CommandName = cmdName, HitNumber = commandHitDic[cmdName] }; list.Add(ch); } usrCmdsHit.CommandHits = list; return usrCmdsHit; } private UserCommandsHit UpdateUserCommandsHitFromDictionary( UserCommandsHit usrCmdsHit, Dictionary<string,int> commandHitDic) { foreach (var cmdName in commandHitDic.Keys) { int count = usrCmdsHit.CommandHits .Where<CommandHit>(p => p.CommandName == cmdName) .Count<CommandHit>(); if (count == 0) { CommandHit ch = new CommandHit { CommandName = cmdName, HitNumber = commandHitDic[cmdName] }; usrCmdsHit.CommandHits.Add(ch); } else { CommandHit ch = usrCmdsHit.CommandHits .First<CommandHit>(p => p.CommandName == cmdName); ch.HitNumber += commandHitDic[cmdName]; } } return usrCmdsHit; }
private void AddNewToCloud(UserCommandsHit usrCmdsHit, RestClient client) { RestRequest reqPost = new RestRequest(); reqPost.Resource = "api/AcadCommands"; reqPost.Method = Method.POST; reqPost.RequestFormat = DataFormat.Json; reqPost.AddHeader("Content-Type", "application/json"); reqPost.JsonSerializer = new RestSharp.Serializers.JsonSerializer(); reqPost.AddBody(usrCmdsHit); var respPost = client.Execute<UserCommandsHit>(reqPost); if (respPost.StatusCode == System.Net.HttpStatusCode.Created) { _commandHitDic.Clear(); GetEditor().WriteMessage("\nUpdate to cloud successfully."); } else { GetEditor().WriteMessage("\n Error:" + respPost.StatusCode); GetEditor().WriteMessage("\n" + respPost.Content); } }
private void UpdateToCloud(UserCommandsHit usrCmdsHit, RestClient client) { RestRequest reqPut = new RestRequest(); reqPut.Resource = "api/AcadCommands/" + usrCmdsHit.Id ; reqPut.Method = Method.PUT; reqPut.RequestFormat = DataFormat.Json; reqPut.AddHeader("Content-Type", "application/json"); reqPut.JsonSerializer = new JsonSerializer(); reqPut.AddBody(usrCmdsHit); var respPut = client.Execute<UserCommandsHit>(reqPut); if (respPut.StatusCode == System.Net.HttpStatusCode.OK) { _commandHitDic.Clear(); GetEditor().WriteMessage("\nUpdate to cloud successfully."); } else { GetEditor().WriteMessage("\n Error:" + respPut.StatusCode); GetEditor().WriteMessage("\n" + respPut.Content); } }
好了,整个过程也不复杂,总的来说就是通过REST和云端通信,把AutoCAD本地的信息上传到云端,进而可以在其他终端(浏览器,甚至手机)来做处理。这只是个小例子,也许你会有更实用的想法,不妨动手试试吧。