Files
lingniu-vehicle-ingest/vehicle-data-platform/apps/api/internal/config/config.go
T
lingniu d6b957dfc8 feat: sync vehicle monitoring and accumulated platform updates
Add monitoring metrics, numeric sorting, report-time display, vehicle number labels, and map layout fixes. Include accumulated mileage, hydrogen, OneOS authentication, open platform, ingestion, deployment, and UI updates.

Exclude temporary files, generated reports, and credentials. Validate frontend 632 tests and production build, API packages, vehicle-map tests, and release installer tests. Gateway suite has one pre-existing date-sensitive identity throttling test failure reproduced on the parent commit.
2026-10-26 18:05:59 +08:00

243 lines
10 KiB
Go

package config
import (
"os"
"strconv"
"strings"
"time"
)
type Config struct {
DailyGeographyEnabled bool
HTTPAddr string
StaticDir string
MySQLDSN string
RedisAddr string
RedisUsername string
RedisPassword string
RedisDB int
TDengineDriver string
TDengineDSN string
TDengineDatabase string
CapacityCheckBin string
AuthToken string
AuthMode string
AuthTokensJSON string
BootstrapAdminUsername string
BootstrapAdminPassword string
SessionTTL time.Duration
OneOSSSOEnabled bool
OneOSIntrospectionURL string
OneOSServiceToken string
OneOSSigningSecret string
OneOSAudience string
OneOSDefaultMenus []string
OneOSRequestTimeout time.Duration
OneOSSessionTTL time.Duration
OneOSProfileEnabled bool
OneOSAuthEnabled bool
OneOSProfileBaseURL string
OneOSProfileServiceToken string
OneOSProfileIssuer string
OneOSProfileAllowedTenant string
OneOSProfileTimeout time.Duration
OneOSPublicOrigin string
OneOSPasswordEnabled bool
OneOSPasswordClientID string
OneOSPasswordRSAPublicKey string
OneOSLoginTicketExchangePath string
OneOSLoginTicketServiceToken string
OneOSDevIntegration bool
OneOSLocalBackend bool
OneOSVehicleQueryScope bool
OneOSDevDataProxyURL string
OneOSDevDataProxyToken string
OneOSLocalOnly bool
OneOSVehicleScopePath string
DataMode string
ExportDir string
RequestTimeout time.Duration
AMapWebJSKey string
AMapAPIKey string
AMapSecurityCode string
AMapServiceHost string
PlatformRelease string
AlertEvaluationInterval time.Duration
AlertStreamMode string
AlertStreamKafkaBrokers []string
AlertStreamKafkaTopics []string
AlertStreamKafkaGroup string
AlertStreamBatchSize int
AlertStreamBatchWait time.Duration
AlertStreamLateness time.Duration
AlertNotificationTargetsJSON string
AlertNotificationSMSURL string
AlertNotificationSMSSecret string
AlertNotificationEmailURL string
AlertNotificationEmailSecret string
AlertNotificationWeComURL string
AlertNotificationWeComSecret string
AlertNotificationBatchSize int
AlertNotificationPollInterval time.Duration
AlertNotificationLease time.Duration
AlertNotificationTimeout time.Duration
HistoryCleanupAutomation bool
HistoryCleanupPollInterval time.Duration
HistoryCleanupLease time.Duration
}
func Load() Config {
return Config{
HTTPAddr: env("HTTP_ADDR", ":20300"),
StaticDir: env("STATIC_DIR", ""),
MySQLDSN: os.Getenv("MYSQL_DSN"),
RedisAddr: os.Getenv("REDIS_ADDR"),
RedisUsername: os.Getenv("REDIS_USERNAME"),
RedisPassword: os.Getenv("REDIS_PASSWORD"),
RedisDB: envInt("REDIS_DB", 50),
TDengineDriver: env("TDENGINE_DRIVER", "taosWS"),
TDengineDSN: os.Getenv("TDENGINE_DSN"),
TDengineDatabase: env("TDENGINE_DATABASE", "lingniu_vehicle_ts"),
CapacityCheckBin: os.Getenv("CAPACITY_CHECK_BIN"),
AuthToken: os.Getenv("AUTH_TOKEN"),
AuthMode: authMode(),
AuthTokensJSON: os.Getenv("AUTH_TOKENS_JSON"),
BootstrapAdminUsername: os.Getenv("BOOTSTRAP_ADMIN_USERNAME"),
BootstrapAdminPassword: os.Getenv("BOOTSTRAP_ADMIN_PASSWORD"),
SessionTTL: time.Duration(envInt("AUTH_SESSION_TTL_HOURS", 12)) * time.Hour,
OneOSSSOEnabled: envBool("ONEOS_SSO_ENABLED", false),
OneOSIntrospectionURL: os.Getenv("ONEOS_SSO_INTROSPECTION_URL"),
OneOSServiceToken: os.Getenv("ONEOS_SSO_SERVICE_TOKEN"),
OneOSSigningSecret: os.Getenv("ONEOS_SSO_SIGNING_SECRET"),
OneOSAudience: env("ONEOS_SSO_AUDIENCE", "vehicle-platform"),
OneOSDefaultMenus: splitCSV(env("ONEOS_SSO_DEFAULT_MENUS", "vehicles")),
OneOSRequestTimeout: time.Duration(envInt("ONEOS_SSO_REQUEST_TIMEOUT_MS", 3000)) * time.Millisecond,
OneOSSessionTTL: time.Duration(envInt("ONEOS_SSO_SESSION_TTL_MINUTES", 30)) * time.Minute,
OneOSProfileEnabled: envBool("ONEOS_PROFILE_ENABLED", false),
OneOSAuthEnabled: envBool("ONEOS_AUTH_ENABLED", false),
OneOSProfileBaseURL: os.Getenv("ONEOS_PROFILE_BASE_URL"),
OneOSProfileServiceToken: os.Getenv("ONEOS_PROFILE_SERVICE_TOKEN"),
OneOSProfileIssuer: os.Getenv("ONEOS_PROFILE_ISSUER"),
OneOSProfileAllowedTenant: os.Getenv("ONEOS_PROFILE_ALLOWED_TENANT"),
OneOSProfileTimeout: time.Duration(envInt("ONEOS_PROFILE_TIMEOUT_MS", 3500)) * time.Millisecond,
OneOSPublicOrigin: os.Getenv("ONEOS_PUBLIC_ORIGIN"),
OneOSPasswordEnabled: envBool("ONEOS_PASSWORD_ENABLED", false),
OneOSPasswordClientID: os.Getenv("ONEOS_PASSWORD_CLIENT_ID"),
OneOSPasswordRSAPublicKey: os.Getenv("ONEOS_PASSWORD_RSA_PUBLIC_KEY"),
OneOSLoginTicketExchangePath: os.Getenv("ONEOS_LOGIN_TICKET_EXCHANGE_PATH"),
OneOSLoginTicketServiceToken: os.Getenv("ONEOS_LOGIN_TICKET_SERVICE_TOKEN"),
OneOSDevIntegration: envBool("ONEOS_DEV_INTEGRATION", false),
OneOSLocalBackend: envBool("ONEOS_LOCAL_BACKEND", false),
OneOSVehicleQueryScope: envBool("ONEOS_VEHICLE_QUERY_SCOPE", false),
OneOSDevDataProxyURL: os.Getenv("ONEOS_DEV_DATA_PROXY_URL"),
OneOSDevDataProxyToken: os.Getenv("ONEOS_DEV_DATA_PROXY_TOKEN"),
OneOSLocalOnly: envBool("ONEOS_LOCAL_ONLY", false),
OneOSVehicleScopePath: os.Getenv("ONEOS_VEHICLE_SCOPE_PATH"),
DataMode: dataMode(),
ExportDir: os.Getenv("EXPORT_DIR"),
RequestTimeout: time.Duration(envInt("REQUEST_TIMEOUT_MS", 5000)) * time.Millisecond,
AMapWebJSKey: os.Getenv("AMAP_WEB_JS_KEY"),
AMapAPIKey: os.Getenv("AMAP_API_KEY"),
DailyGeographyEnabled: envBool("DAILY_GEOGRAPHY_ENABLED", false),
AMapSecurityCode: os.Getenv("AMAP_SECURITY_JS_CODE"),
AMapServiceHost: os.Getenv("AMAP_SECURITY_SERVICE_HOST"),
PlatformRelease: os.Getenv("PLATFORM_RELEASE"),
AlertEvaluationInterval: time.Duration(envInt("ALERT_EVALUATION_INTERVAL_SEC", 10)) * time.Second,
AlertStreamMode: strings.ToLower(env("ALERT_STREAM_MODE", "disabled")),
AlertStreamKafkaBrokers: splitCSV(firstEnv("ALERT_STREAM_KAFKA_BROKERS", "KAFKA_BROKERS")),
AlertStreamKafkaTopics: splitCSV(env("ALERT_STREAM_KAFKA_TOPICS", "vehicle.fields.go.gb32960.v1,vehicle.fields.go.jt808.v1,vehicle.fields.go.yutong-mqtt.v1")),
AlertStreamKafkaGroup: env("ALERT_STREAM_KAFKA_GROUP", "vehicle-alert-stream-v1"),
AlertStreamBatchSize: envInt("ALERT_STREAM_BATCH_SIZE", 200),
AlertStreamBatchWait: time.Duration(envInt("ALERT_STREAM_BATCH_WAIT_MS", 100)) * time.Millisecond,
AlertStreamLateness: time.Duration(envInt("ALERT_STREAM_LATENESS_SEC", 120)) * time.Second,
AlertNotificationTargetsJSON: os.Getenv("ALERT_NOTIFICATION_TARGETS_JSON"),
AlertNotificationSMSURL: os.Getenv("ALERT_NOTIFICATION_SMS_URL"),
AlertNotificationSMSSecret: os.Getenv("ALERT_NOTIFICATION_SMS_SECRET"),
AlertNotificationEmailURL: os.Getenv("ALERT_NOTIFICATION_EMAIL_URL"),
AlertNotificationEmailSecret: os.Getenv("ALERT_NOTIFICATION_EMAIL_SECRET"),
AlertNotificationWeComURL: os.Getenv("ALERT_NOTIFICATION_WECOM_URL"),
AlertNotificationWeComSecret: os.Getenv("ALERT_NOTIFICATION_WECOM_SECRET"),
AlertNotificationBatchSize: envInt("ALERT_NOTIFICATION_BATCH_SIZE", 20),
AlertNotificationPollInterval: time.Duration(envInt("ALERT_NOTIFICATION_POLL_INTERVAL_MS", 1000)) * time.Millisecond,
AlertNotificationLease: time.Duration(envInt("ALERT_NOTIFICATION_LEASE_SEC", 30)) * time.Second,
AlertNotificationTimeout: time.Duration(envInt("ALERT_NOTIFICATION_TIMEOUT_MS", 5000)) * time.Millisecond,
HistoryCleanupAutomation: envBool("HISTORY_EXPORT_CLEANUP_AUTOMATION_ENABLED", false),
HistoryCleanupPollInterval: time.Duration(envInt("HISTORY_EXPORT_CLEANUP_POLL_SEC", 60)) * time.Second,
HistoryCleanupLease: time.Duration(envInt("HISTORY_EXPORT_CLEANUP_LEASE_SEC", 300)) * time.Second,
}
}
func firstEnv(keys ...string) string {
for _, key := range keys {
if value := os.Getenv(key); value != "" {
return value
}
}
return ""
}
func splitCSV(raw string) []string {
parts := strings.Split(raw, ",")
values := make([]string, 0, len(parts))
seen := map[string]bool{}
for _, part := range parts {
part = strings.TrimSpace(part)
if part != "" && !seen[part] {
seen[part] = true
values = append(values, part)
}
}
return values
}
func dataMode() string {
if value := os.Getenv("DATA_MODE"); value != "" {
return value
}
if os.Getenv("MYSQL_DSN") != "" {
return "production"
}
return "mock"
}
func authMode() string {
if value := os.Getenv("AUTH_MODE"); value != "" {
return value
}
if os.Getenv("AUTH_TOKEN") != "" || os.Getenv("AUTH_TOKENS_JSON") != "" {
return "enforce"
}
return "disabled"
}
func env(key, fallback string) string {
if value := os.Getenv(key); value != "" {
return value
}
return fallback
}
func envInt(key string, fallback int) int {
raw := os.Getenv(key)
if raw == "" {
return fallback
}
value, err := strconv.Atoi(raw)
if err != nil {
return fallback
}
return value
}
func envBool(key string, fallback bool) bool {
raw := strings.ToLower(strings.TrimSpace(os.Getenv(key)))
switch raw {
case "1", "true", "yes", "on":
return true
case "0", "false", "no", "off":
return false
default:
return fallback
}
}