明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1893|回复: 9

运行在CAD上显示当前天气的插件

[复制链接]
发表于 2025-8-2 14:46:15 | 显示全部楼层 |阅读模式
本帖最后由 shujh1989 于 2025-8-2 14:51 编辑

最近有点无聊。第一次写.net版本的插件,可以显示当前城市的天气。apikey在高德可以免费申请。
  1. using Autodesk.AutoCAD.Runtime;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using System.Windows;
  4. using System.Net.Http;
  5. using Newtonsoft.Json;
  6. using System.Threading.Tasks;
  7. using System.Windows.Controls;
  8. using System.Windows.Media;
  9. using System;

  10. public class WeatherPlugin : IExtensionApplication
  11. {
  12.     private static Window weatherWindow;

  13.     public void Initialize()
  14.     {
  15.         Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nWeather Plugin Initialized\n");
  16.     }

  17.     public void Terminate()
  18.     {
  19.         if (weatherWindow != null)
  20.         {
  21.             weatherWindow.Close();
  22.         }
  23.     }

  24.     [CommandMethod("WTR")]
  25.     public async void ShowWeatherCommand()
  26.     {
  27.         if (weatherWindow != null)
  28.         {
  29.             weatherWindow.Close();
  30.         }

  31.         weatherWindow = new Window
  32.         {
  33.             Title = "当前天气",
  34.             Width = 400,
  35.             Height = 300,
  36.             WindowStartupLocation = WindowStartupLocation.CenterScreen,
  37.             Topmost = true,
  38.             ResizeMode = ResizeMode.CanResizeWithGrip
  39.         };

  40.         var stackPanel = new StackPanel
  41.         {
  42.             Margin = new Thickness(10),
  43.             Background = Brushes.White
  44.         };

  45.         var cityLabel = new Label { Content = "请输入城市:" };
  46.         var cityTextBox = new TextBox { Width = 200, Margin = new Thickness(0, 5, 0, 5) };
  47.         var getWeatherButton = new Button
  48.         {
  49.             Content = "获取天气",
  50.             Width = 100,
  51.             Margin = new Thickness(0, 5, 0, 5)
  52.         };
  53.         var weatherInfo = new Label { Content = "正在加载您的位置天气...", Margin = new Thickness(0, 5, 0, 5) };

  54.         stackPanel.Children.Add(cityLabel);
  55.         stackPanel.Children.Add(cityTextBox);
  56.         stackPanel.Children.Add(getWeatherButton);
  57.         stackPanel.Children.Add(weatherInfo);

  58.         weatherWindow.Content = stackPanel;

  59.         getWeatherButton.Click += async (s, e) =>
  60.         {
  61.             string city = cityTextBox.Text.Trim();
  62.             if (!string.IsNullOrEmpty(city))
  63.             {
  64.                 weatherInfo.Content = "正在加载...";
  65.                 try
  66.                 {
  67.                     string weatherData = await GetWeatherData(city);
  68.                     weatherInfo.Content = weatherData;
  69.                 }
  70.                 catch (System.Exception ex)
  71.                 {
  72.                     weatherInfo.Content = $"错误: {ex.Message}";
  73.                 }
  74.             }
  75.             else
  76.             {
  77.                 weatherInfo.Content = "请输入城市名称。";
  78.             }
  79.         };

  80.         try
  81.         {
  82.             string city = await GetCityFromIP();
  83.             string weatherData = await GetWeatherData(city);
  84.             weatherInfo.Content = weatherData;
  85.             cityTextBox.Text = city;
  86.         }
  87.         catch (System.Exception ex)
  88.         {
  89.             weatherInfo.Content = $"加载本地天气失败: {ex.Message}";
  90.         }

  91.         Autodesk.AutoCAD.ApplicationServices.Core.Application.ShowModelessWindow(weatherWindow);
  92.     }

  93.     private async Task<string> GetCityFromIP()
  94.     {
  95.         try
  96.         {
  97.             using (var client = new HttpClient())
  98.             {
  99.                 client.Timeout = TimeSpan.FromSeconds(10);
  100.                 string apiKey = "你申请的APIKey"; // 替换为实际的高德地图Web服务API Key
  101.                 string url = $"https://restapi.amap.com/v3/ip?key={apiKey}";
  102.                 var response = await client.GetAsync(url);
  103.                 response.EnsureSuccessStatusCode();

  104.                 string json = await response.Content.ReadAsStringAsync();
  105.                 System.Diagnostics.Debug.WriteLine(json); // 调试输出JSON
  106.                 var locationData = JsonConvert.DeserializeObject<IPLocationResponse>(json);

  107.                 // 检查API状态
  108.                 if (locationData.Status != "1")
  109.                 {
  110.                     throw new System.Exception($"IP定位失败: {locationData.Info}");
  111.                 }

  112.                 // 返回adcode
  113.                 if (!string.IsNullOrEmpty(locationData.Adcode))
  114.                 {
  115.                     return locationData.Adcode; // 返回adcode,如 "110101"
  116.                 }
  117.                 throw new System.Exception("未获取到城市adcode");
  118.             }
  119.         }
  120.         catch (System.Exception ex)
  121.         {
  122.             System.Diagnostics.Debug.WriteLine($"GetCityFromIP 错误: {ex.Message}");
  123.             return "110101"; // 默认返回北京东城区的adcode
  124.         }
  125.     }

  126.     // 定义强类型类以解析高德IP定位API的JSON响应
  127.     public class IPLocationResponse
  128.     {
  129.         public string Status { get; set; }
  130.         public string Info { get; set; }
  131.         public string Infocode { get; set; }
  132.         public string Province { get; set; }
  133.         public string City { get; set; }
  134.         public string Adcode { get; set; }
  135.         public string Rectangle { get; set; }
  136.     }

  137.     private async Task<string> GetWeatherData(string city)
  138.     {
  139.         string apiKey = "你申请的API Key"; // 替换为实际Key
  140.         string url = $"https://restapi.amap.com/v3/weather/weatherInfo?city={city}&key={apiKey}&extensions=base&output=JSON";

  141.         try
  142.         {
  143.             using (var client = new HttpClient())
  144.             {
  145.                 client.Timeout = TimeSpan.FromSeconds(10);
  146.                 var response = await client.GetAsync(url);
  147.                 response.EnsureSuccessStatusCode();

  148.                 string json = await response.Content.ReadAsStringAsync();
  149.                 System.Diagnostics.Debug.WriteLine(json); // 调试输出JSON

  150.                 // 使用强类型解析JSON,增加可靠性
  151.                 var weatherData = JsonConvert.DeserializeObject<WeatherResponse>(json);

  152.                 // 检查API状态
  153.                 if (weatherData.Status != "1")
  154.                 {
  155.                     throw new System.Exception($"API错误: {weatherData.Info} (infocode: {weatherData.Infocode})");
  156.                 }

  157.                 // 检查lives数组是否存在且不为空
  158.                 if (weatherData.Lives == null || weatherData.Lives.Length == 0)
  159.                 {
  160.                     throw new System.Exception("未找到天气数据,请检查城市编码或名称");
  161.                 }

  162.                 // 获取实况天气数据
  163.                 var liveWeather = weatherData.Lives[0];
  164.                 return $"城市 {liveWeather.City} 的天气:\n" +
  165.                        $"状况: {liveWeather.Weather}\n" +
  166.                        $"温度: {liveWeather.Temperature}°C\n" +
  167.                        $"湿度: {liveWeather.Humidity}%\n" +
  168.                        $"风向: {liveWeather.Winddirection}\n" +
  169.                        $"风力: {liveWeather.Windpower}级\n" +
  170.                        $"数据更新时间: {liveWeather.Reporttime}";
  171.             }
  172.         }
  173.         catch (HttpRequestException ex)
  174.         {
  175.             throw new System.Exception($"网络错误: {ex.Message}");
  176.         }
  177.         catch (TaskCanceledException)
  178.         {
  179.             throw new System.Exception("请求超时");
  180.         }
  181.         catch (JsonException ex)
  182.         {
  183.             throw new System.Exception($"JSON解析失败: {ex.Message}");
  184.         }
  185.         catch (System.Exception ex)
  186.         {
  187.             throw new System.Exception($"获取天气数据失败: {ex.Message}");
  188.         }
  189.     }

  190.     // 定义强类型类以解析JSON
  191.     public class WeatherResponse
  192.     {
  193.         public string Status { get; set; }
  194.         public string Count { get; set; }
  195.         public string Info { get; set; }
  196.         public string Infocode { get; set; }
  197.         public LiveWeather[] Lives { get; set; }
  198.     }

  199.     public class LiveWeather
  200.     {
  201.         public string Province { get; set; }
  202.         public string City { get; set; }
  203.         public string Adcode { get; set; }
  204.         public string Weather { get; set; }
  205.         public string Temperature { get; set; }
  206.         public string Winddirection { get; set; }
  207.         public string Windpower { get; set; }
  208.         public string Humidity { get; set; }
  209.         public string Reporttime { get; set; }
  210.         public string Temperature_float { get; set; }
  211.         public string Humidity_float { get; set; }
  212.     }
  213. }


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
回复

使用道具 举报

发表于 2025-8-2 14:52:56 | 显示全部楼层
你们把CAD玩坏了。有点不务正业了。
回复 支持 反对

使用道具 举报

发表于 2025-8-2 16:14:24 | 显示全部楼层
看来是个高手,都已经会异步了,
不过少了一个缓存层,当天应该不要重复去取.
回复 支持 反对

使用道具 举报

发表于 2025-8-2 16:38:01 | 显示全部楼层
效果什么样子的啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-8-2 17:28:16 | 显示全部楼层
你有种再说一遍 发表于 2025-8-2 16:14
看来是个高手,都已经会异步了,
不过少了一个缓存层,当天应该不要重复去取.

,惭愧,用ai写的程序拼的。ai一步一步教出来的,刚刚知道怎么编译程序。
回复 支持 反对

使用道具 举报

发表于 2025-8-2 17:31:37 | 显示全部楼层
本帖最后由 你有种再说一遍 于 2025-8-8 23:06 编辑
shujh1989 发表于 2025-8-2 17:28
,惭愧,用ai写的程序拼的。ai一步一步教出来的,刚刚知道怎么编译程序。

那你用AI的话,就需要继续追问了,
异步用不好的话会有奇特的效果.
例如Task就必须要await,
不然在独立进程下,启动后执行一半任务就死亡的线程.
任务即使完成了,但是由于没有设置信号机制,
导致它结束连接数据库失败而空转,出现隐藏bug,泄漏资源.

回复 支持 反对

使用道具 举报

发表于 2025-8-5 10:16:27 来自手机 | 显示全部楼层
厉害厉害,支持分享
回复 支持 反对

使用道具 举报

发表于 2025-8-7 10:10:35 | 显示全部楼层
可以,虽然槽点太多了,这篇文章最有用的地方是,知道了高德可以申请免费api
回复 支持 反对

使用道具 举报

发表于 2025-8-7 23:23:21 | 显示全部楼层
直接显示在状态栏更好一些
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-11-16 04:03 , Processed in 0.155418 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表