# solargis
**Repository Path**: milletes/solargis
## Basic Information
- **Project Name**: solargis
- **Description**: 使用go语言对接solargis光功率预测
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-08-11
- **Last Updated**: 2026-06-24
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
1. requestXml 参数配置在配置文件中yaml
2. 有对应的模块接受配置文件中的参数
3. 有对应的模块读取配置文件参数,发送给接受模块
4. 形成最终xml,并访问API
5. 接收API,元数据输出为xml文件,输出数据集为csv文件
6. 完善周期调用
7. 完善当前和1-14天的预测数据的处理
8. 完善文件工具类
9. 完善异常处理
10. 完善日志处理
11. 完善配置文件动态加载
12. 增加ui用于用户读取和写入参数到配置文件中
增加读取yaml的依赖
增加生成xml的依赖
🎯 项目概述
这是一个 SolarGIS 数据获取与管理系统,用于定时从 SolarGIS API 获取太阳能气象数据,并将数据保存为 XML 和 CSV 格式,同时支持文件自动转移和 Windows 服务部署。
📁 项目结构
plainText
solargis/
├── main.go # 主程序入口(支持Windows服务)
├── config/
│ ├── config.go # 配置管理模块
│ ├── config.yaml # 主配置文件
│ ├── config_init.yaml # 初始化配置模板
│ └── templates/ # XML请求模板目录
│ ├── a.xml
│ └── b.xml
├── task/
│ ├── RequtesTools.go # API请求工具(请求、解析、写入文件)
│ └── FileTransferScheduler.go # 文件定时转移调度器
├── model/
│ ├── requestModel/RequestData.go # 请求数据构建(模板加载、日期填充)
│ └── responseModel/ResponseData.go # 响应数据模型
├── logging/
│ └── Logger.go # 日志系统(文件+控制台)
├── build.bat # 编译脚本
├── install-service.bat # Windows服务安装脚本
└── uninstall-service.bat # Windows服务卸载脚本
🔧 核心功能模块
1. API 数据请求 (RequtesTools.go)
当日数据请求:获取当天的太阳能气象数据
未来数据请求:获取未来 N 天的预测数据(默认14天)
支持 XML 模板动态填充日期
响应数据保存为 XML 和 CSV 格式
2. 定时任务调度 (main.go)
使用 cron 调度器,三个定时任务:
当日请求:每15分钟执行一次(0 */15 * * * *)
未来请求:每天4次(00:00, 06:00, 12:00, 18:00)
文件转移:每天凌晨1点执行(0 0 1 * * *)
3. 文件转移 (FileTransferScheduler.go)
自动将数据从 solargis 目录转移到 solargis2 目录
支持配置多个源目录和目标目录
4. 配置管理 (config.go)
YAML 格式配置文件
支持环境变量 SOLARGIS_CONFIG_PATH 指定配置路径
线程安全的配置读取
5. 日志系统 (Logger.go)
四级日志:DEBUG、INFO、WARNING、ERROR
同时输出到文件和控制台
日志文件位置:可执行文件同级 logs/app.log
6. Windows 服务支持 (main.go)
支持作为 Windows 服务运行
使用 WinSW 包装
支持自动启动、停止、重启
🔄 工作流程
plainText
1. 程序启动
↓
2. 加载配置文件 (config.yaml)
↓
3. 初始化日志系统
↓
4. 注册定时任务
├─ 当日请求 (每15分钟)
├─ 未来请求 (每天4次)
└─ 文件转移 (每天凌晨1点)
↓
5. 定时任务触发
├─ 读取XML模板
├─ 填充日期参数
├─ 发送HTTP请求到SolarGIS API
├─ 解析XML响应
└─ 保存为XML和CSV文件
↓
6. 文件转移任务
└─ 将数据文件转移到目标目录
📦 技术栈
组件 技术
语言 Go 1.24
定时任务 github.com/robfig/cron/v3
配置解析 gopkg.in/yaml.v3
Windows服务 golang.org/x/sys/windows/svc
数据格式 XML、CSV、YAML
⚠️ 发现的问题
死代码:ExtractTemplateName 函数未被使用,可以删除
拼写错误:文件名 RequtesTools.go 应为 RequestsTools.go
文档拼写:redme.md 应为 README.md
配置文件不一致:config_init.yaml 和 config.yaml 结构有差异
📝 配置文件示例
主要配置项:
API密钥:当日/未来请求的授权密钥
存储路径:数据文件保存位置
Cron表达式:定时任务执行时间
模板目录:XML请求模板位置
文件转移:源目录和目标目录映射
Parameters processing 中key的说明
The following table lists available parameters for use in the attribute of .
[//]: # (These parameters define which data will be included in the response.@key)
| Parameter | Description | Tier |
|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| GHI | Global Horizontal Irradiation [kWh/m2, Wh/m2, W/m2]. Regarding units see below note. | Basic |
| GHI_C | Clear-sky Global Horizontal Irradiation [kWh/m2, Wh/m2, W/m2] | Professional |
| GHI_UNC_HIGH | GHI high estimate (10 % probability of exceedance) [kWh/m2, Wh/m2, W/m2] | Professional |
| GHI_UNC_LOW | GHI low estimate (90 % probability of exceedance) [kWh/m2, Wh/m2, W/m2] | Professional |
| DNI | Direct Normal Irradiation [kWh/m2, Wh/m2, W/m2] | Basic |
| DNI_C | Clear-sky Direct Normal Irradiation [kWh/m2, Wh/m2, W/m2] | Professional |
| DIF | Diffuse Horizontal Irradiation [kWh/m2, Wh/m2, W/m2] | Basic |
| GTI | Global Tilted Irradiation [kWh/m2, Wh/m2, W/m2] | Basic |
| GTI_UNC_HIGH | GTI high estimate (10 % probability of exceedance) [kWh/m2, Wh/m2, W/m2] | Professional |
| GTI_UNC_LOW | GTI low estimate (90 % probability of exceedance) [kWh/m2, Wh/m2, W/m2] | Professional |
| GTI_C | Global tilted clear-sky irradiance [W/m2] | Professional |
| CI_FLAG | Cloud identification quality flag [categories] | Basic |
| FLAG_R | deprecated alias for CI_FLAG | |
| KTM | Deprecated alias of KC. Can be discontinued in future versions. | Professional |
| KC | Clear-sky index [unitless] | Professional |
| KT | clearness index, values range (0, 1.1), during the night -9 | Professional |
| PAR | Photo-synthetically Active Irradiation [kWh/m2, Wh/m2, W/m2] | Professional |
| SE | Sun Altitude (Elevation) Angle [deg.] | Basic |
| SA | Sun Azimuth Angle [deg.] | Basic |
| TEMP | Air Temperature at 2m [deg. C] | Basic |
| TD | Dew Point Temperature [deg. C] | Professional |
| WBT | Wet Bulb Temperature [deg. C] | Professional |
| AP | Atmospheric Pressure [hPa] | Professional |
| RH | Relative Humidity [%] | Professional |
| WS | Wind Speed [m/s] | Basic |
| WD | Wind Direction [deg.] | Basic |
| PREC | Precipitation Rate [kg/m2] | Professional |
| PWAT | Precipitable Water [kg/m2] | Professional |
| PVOUT | Photovoltaic Output [kW, kWh]. Regarding units see below note. | Basic |
| PVOUT_UNC_HIGH | PVOUT high estimate (10 % probability of exceedance) [kW, kWh] | Professional |
| PVOUT_UNC_LOW | PVOUT low estimate (90 % probability of exceedance) [kW, kWh] | Professional |
| SDWE | Water equivalent of accumulated snow depth [kg/m2] | Professional |
| SWE | Deprecated alias of SDWE. Can be discontinued in future versions. SDWE will be returned in a response. | Professional |
| TMOD | Module temperature [deg. C]. This parameter needs a PV system defined in the request, at least in a mimimal setup like: <pv:system installedPower="1"><pv:module type="CSI"/><pv:inverter/><pv:losses/></pv:system> | Professional |
| WG | Wind Gust [m/s] | Professional |
| WS100 | Wind speed at 100 m [m/s] | Professional |
| WD100 | Wind direction at 100 m [deg.] | Professional |
| SFWE | Water equivalent of fresh snowfall rate [kg/m2/hour] - source ERA5 , the latest data available is approx. one month backward (no data for very recent or forecast period) | Professional |
| INC | Incidence angle of direct irradiance [deg.], this parameter needs GTI or PVOUT in the request | Professional |
| TILT | Tilt of inclined surface [deg.], this parameter needs GTI or PVOUT in the request | Basic |
| ASPECT | Aspect of inclined surface [deg.], this parameter needs GTI or PVOUT in the request | Basic |
中文版本
| 参数 |描述 | 层级 |
|:-----------------|---------------------------------------------------------------------------------------------------------------------------------|--------------|
| GHI | 全球水平辐照度 [kWh/m², Wh/m², W/m²](单位说明见下方注释) | 基础级 |
| GHI_C | 晴空全球水平辐照度 [kWh/m², Wh/m², W/m²] | 专业级 |
| GHI_UNC_HIGH | GHI 高估值(10% 超越概率)[kWh/m², Wh/m², W/m²] | 专业级 |
| GHI_UNC_LOW | GHI 低估值(90% 超越概率)[kWh/m², Wh/m², W/m²] | 专业级 |
| DNI | 直接法向辐照度 [kWh/m², Wh/m², W/m²] | 基础级 |
| DNI_C | 晴空直接法向辐照度 [kWh/m², Wh/m², W/m²] | 专业级 |
| DIF | 散射水平辐照度 [kWh/m², Wh/m², W/m²] | 基础级 |
| GTI | 全球倾斜辐照度 [kWh/m², Wh/m², W/m²] | 基础级 |
| GTI_UNC_HIGH | GTI 高估值(10% 超越概率)[kWh/m², Wh/m², W/m²] | 专业级 |
| GTI_UNC_LOW | GTI 低估值(90% 超越概率)[kWh/m², Wh/m², W/m²] | 专业级 |
| GTI_C | 晴空全球倾斜辐照度 [W/m²] | 专业级 |
| CI_FLAG | 云识别质量标志 [类别] | 基础级 |
| FLAG_R | CI_FLAG 的弃用别名 | - |
| KTM | KC 的弃用别名(未来版本可能停用) | 专业级 |
| KC | 晴空指数 [无量纲] | 专业级 |
| KT | 晴朗指数,取值范围 (0, 1.1),夜间为 -9 | 专业级 |
| PAR | 光合有效辐照度 [kWh/m², Wh/m², W/m²] | 专业级 |
| SE | 太阳高度角 [度] | 基础级 |
| SA | 太阳方位角 [度] | 基础级 |
| TEMP | 2米高度气温 [摄氏度] | 基础级 |
| TD | 露点温度 [摄氏度] | 专业级 |
| WBT | 湿球温度 [摄氏度] | 专业级 |
| AP | 大气压 [hPa] | 专业级 |
| RH | 相对湿度 [%] | 专业级 |
| WS | 风速 [米/秒] | 基础级 |
| WD | 风向 [度] | 基础级 |
| PREC | 降水率 [千克/平方米] | 专业级 |
| PWAT | 可降水量 [千克/平方米] | 专业级 |
| PVOUT | 光伏输出 [kW, kWh](单位说明见下方注释) | 基础级 |
| PVOUT_UNC_HIGH | PVOUT 高估值(10% 超越概率)[kW, kWh] | 专业级 |
| PVOUT_UNC_LOW | PVOUT 低估值(90% 超越概率)[kW, kWh] | 专业级 |
| SDWE | 积雪深度水当量 [千克/平方米] | 专业级 |
| SWE | SDWE 的弃用别名(未来版本可能停用,响应中返回 SDWE) | 专业级 |
| TMOD | 组件温度 [摄氏度](需在请求中定义光伏系统,最小配置示例:``) | 专业级 |
| WG | 阵风风速 [米/秒] | 专业级 |
[//]: # (PV array geometry
)
[//]: # (Element: "")
Namespace: http://solargis.info/schema/common-pv.xsd
Description: The element specifies the mounting type of the PV system, which is used for calculating GTI (Global Tilted Irradiation) and PVOUT (Photovoltaic Output). If this element is omitted and GTI/PVOUT is requested, flat-lying PV panels are assumed (GTI = GHI).
Content: None (attributes only).
| Attribute | Required | Description | Default/Example |
|--------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|
| @type | Yes | Specifies the mounting geometry type. Accepted values are: GeometryFixedOneAngle, GeometryOneAxisHorizontalNS, GeometryOneAxisInclinedNS, GeometryOneAxisVertical, GeometryTwoAxisAstronomical. | Example: pv:GeometryFixedOneAngle |
| @azimuth | No | True geographical azimuth in degrees (0° = North, 90° = East, 180° = South, 270° = West). Required for GeometryFixedOneAngle. Defaults to 180° for trackers. | Example: 180 |
| @tilt | No | Tilt of the panel surface in degrees (0° = horizontal, 90° = vertical). Required for GeometryFixedOneAngle and GeometryOneAxisVertical. | Example: 25 |
| @axisTilt | No | Tilt of the inclined rotating axis in degrees (0° = horizontal, 90° = vertical). Applicable only to GeometryOneAxisInclinedNS. Defaults to 30°. | Example: 30 |
| @rotationLimitEast | No | Rotation limit for trackers on the east side. Defaults vary by tracker type. Must be less than or equal to @rotationLimitWest. | Example: -90 |
| @rotationLimitWest | No | Rotation limit for trackers on the west side. Defaults vary by tracker type. Must be greater than or equal to @rotationLimitEast. | Example: 90 |
| @tiltLimitMin | No | Minimum tilt limit for trackers with a horizontal axis (GeometryTwoAxisAstronomical). Default is 0°. Must be less than or equal to @tiltLimitMax. | Example: 0 |
| @tiltLimitMax | No | Maximum tilt limit for trackers with a horizontal axis (GeometryTwoAxisAstronomical). Default is 90°. Must be greater than or equal to @tiltLimitMin. | Example: 60 |
| @backTracking | No | Boolean value indicating whether the tracker avoids shading from neighboring structures (true) or moves freely (false). Default is false. | Example: "true" |
中文翻译
| attribute | required | description | default/example |
|---------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------|
| @type | yes | 指定安装几何类型。允许的值为:geometryfixedoneangle, geometryoneaxishorizontalns, geometryoneaxisinclinedns, geometryoneaxisvertical, geometrytwoaxisastronomical。 | 示例:pv:geometryfixedoneangle |
| @azimuth | no | 真实地理方位角(单位:度,0° = 北,90° = 东,180° = 南,270° = 西)。对 geometryfixedoneangle 类型为必填项。对于跟踪器默认为 180°。 | 示例:180 |
| @tilt | no | 面板表面倾斜角(单位:度,0° = 水平,90° = 垂直)。对 geometryfixedoneangle 和 geometryoneaxisvertical 类型为必填项。 | 示例:25 |
| @axistilt | no | 倾斜旋转轴的倾斜角(单位:度,0° = 水平,90° = 垂直)。仅适用于 geometryoneaxisinclinedns 类型。默认值为 30°。 | 示例:30 |
| @rotationlimiteast | no | 东侧跟踪器的旋转限制。默认值因跟踪器类型而异。必须小于或等于 @rotationlimitwest。 | 示例:-90 |
| @rotationlimitwest | no | 西侧跟踪器的旋转限制。默认值因跟踪器类型而异。必须大于或等于 @rotationlimiteast。 | 示例:90 |
| @tiltlimitmin | no | 具有水平轴的跟踪器(geometrytwoaxisastronomical)的最小倾斜限制。默认值为 0°。必须小于或等于 @tiltlimitmax。 | 示例:0 |
| @tiltlimitmax | no | 具有水平轴的跟踪器(geometrytwoaxisastronomical)的最大倾斜限制。默认值为 90°。必须大于或等于 @tiltlimitmin。 | 示例:60 |
| @backtracking | no | 布尔值,表示跟踪器是否启用避让(true)以避免相邻结构的遮挡,或自由移动(false)。默认值为 false。 | 示例:"true" |
要将当前项目打包为Windows服务,推荐使用WinSW工具。以下是详细步骤:
## 1. 下载并准备WinSW
1. 从 https://github.com/winsw/winsw 下载 `WinSW.NET461.exe`
2. 将其重命名为 `solargis-service.exe`
## 2. 创建服务配置文件
创建 `solargis-service.xml` 配置文件:
```xml
SolarGIS
SolarGIS Service
SolarGIS数据采集服务
%BASE%\solargis.exe
rotate
%BASE%\logs
%BASE%
1 hour
```
## 3. 修改程序代码支持服务模式
修改 [main.go](file://D:\ProjectWork\go\goWork\xunda\solargis\main.go) 文件,添加Windows服务支持:
```
package main
import (
"log"
"os"
"solargis/config"
"solargis/logging"
"solargis/model/requestModel"
"solargis/task"
// 添加Windows服务支持包
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/debug"
)
const defaultConfigPath = "config/config.yaml"
func init() {
// 初始化日志系统
if err := logging.Init(); err != nil {
log.Printf("日志系统初始化失败: %v", err)
}
configPath := getConfigPath()
_, err := config.LoadConfig(configPath)
if err != nil {
log.Printf("加载配置失败: %v", err)
}
}
func getConfigPath() string {
// 从环境变量中获取配置文件路径
path := os.Getenv("SOLARGIS_CONFIG_PATH")
if path == "" {
return defaultConfigPath
}
return path
}
// 主函数修改为支持服务模式
func main() {
isIntSrv, err := svc.IsWindowsService()
if err != nil {
log.Fatalf("failed to determine if we are running in service mode: %v", err)
}
if isIntSrv {
// 作为Windows服务运行
logging.Info.Println("作为Windows服务运行")
runService()
} else {
// 作为普通程序运行
logging.Info.Println("作为普通程序运行")
runApplication()
}
}
func runService() {
// 使用debug包运行服务
debug.Run("SolarGIS", &solargisService{})
}
func runApplication() {
getConfig := config.GetConfig()
if getConfig == nil {
logging.Error.Fatal("配置获取失败,程序退出")
return
}
// 启动定时任务
startTimers(getConfig)
}
// Windows服务结构体
type solargisService struct{}
func (m *solargisService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown
changes <- svc.Status{State: svc.StartPending}
// 启动应用程序逻辑
go func() {
getConfig := config.GetConfig()
if getConfig != nil {
startTimers(getConfig)
}
}()
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
loop:
for {
select {
case c := <-r:
switch c.Cmd {
case svc.Interrogate:
changes <- c.CurrentStatus
case svc.Stop, svc.Shutdown:
// 服务停止逻辑
logging.Info.Println("服务正在停止")
break loop
default:
continue loop
}
}
}
changes <- svc.Status{State: svc.StopPending}
return
}
func currentRequest(getConfig *config.Config) {
data, err := requestModel.BuildDailyRequest(getConfig, getConfig.API.Today.Value)
if err != nil {
logging.Error.Printf("构建每日请求失败: %v", err)
}
logging.Info.Printf("生成的请求数据:%v", string(data))
task.Request(string(data), getConfig.API.Today.Key, getConfig.File.Path, getConfig.API.Today.Value)
}
func futureRequest(getConfig *config.Config) {
data, err := requestModel.BuildDailyRequest(getConfig, getConfig.API.FutureDay.Value)
if err != nil {
logging.Error.Printf("构建未来请求失败: %v", err)
}
logging.Info.Printf("%v", string(data))
task.Request(string(data), getConfig.API.FutureDay.Key, getConfig.File.Path, getConfig.API.FutureDay.Value)
}
func startTimers(getConfig *config.Config) {
// currentRequest 定时器:每10分钟执行一次
go func() {
currentRequest(getConfig)
ticker := time.NewTicker(10 * time.Minute)
defer ticker.Stop()
for {
select {
case <-ticker.C:
currentRequest(getConfig)
}
}
}()
// futureRequest 定时器:每天4次(00:00, 06:00, 12:00, 18:00)
go func() {
for {
now := time.Now()
nextRun := getNextRunTime(now)
duration := nextRun.Sub(now)
logging.Info.Printf("下次 futureRequest 执行时间: %v", nextRun)
<-time.After(duration)
futureRequest(getConfig)
}
}()
// 阻塞主程序,保持定时器运行
select {}
}
func getNextRunTime(now time.Time) time.Time {
// 设定今天的起始时间
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
// 定义执行时间点(小时)
runHours := []int{0, 6, 12, 18}
// 查找下一个执行时间
for _, hour := range runHours {
runTime := today.Add(time.Duration(hour) * time.Hour)
if runTime.After(now) {
return runTime
}
}
// 如果今天的时间点都已过,则返回明天的第一个时间点
return today.Add(24 * time.Hour)
}
```
## 4. 安装和运行服务
创建安装脚本 `install-service.bat`:
```batch
@echo off
echo 安装SolarGIS服务...
solargis-service.exe install
echo 启动SolarGIS服务...
solargis-service.exe start
echo 服务安装完成
pause
```
创建卸载脚本 `uninstall-service.bat`:
```batch
@echo off
echo 停止SolarGIS服务...
solargis-service.exe stop
echo 卸载SolarGIS服务...
solargis-service.exe uninstall
echo 服务卸载完成
pause
```
## 5. 打包文件结构
确保以下文件在同一目录下:
```
solargis.exe # 主程序
solargis-service.exe # WinSW服务包装器
solargis-service.xml # 服务配置文件
install-service.bat # 安装脚本
uninstall-service.bat # 卸载脚本
config/ # 配置文件目录
config.yaml # 配置文件
```
## 6. 安装服务
以管理员身份运行 `install-service.bat` 即可安装并启动服务。
通过以上步骤,您的程序就可以作为Windows服务运行,支持自动启动、自动重启等服务特性。
如果配置文件再其他位置,可以配置环境变量SOLARGIS_CONFIG_PATH 指定配置文件路径。