feat(platform): harden telemetry pipeline and unify Semi UI workspaces

This commit is contained in:
lingniu
2026-07-18 00:26:36 +08:00
parent 65b4e4f055
commit 159c80b0ae
136 changed files with 21616 additions and 1785 deletions

View File

@@ -0,0 +1,227 @@
package platform
import (
"encoding/json"
"fmt"
"strconv"
"strings"
)
// gb32960FieldReference is the platform copy of the authoritative Chinese
// terminology supplied for GB/T 32960 and the Guangdong fuel-cell extension.
// It enriches protocol values at read time without changing the stored RAW
// evidence or replacing the parser's stable source-field keys.
type gb32960FieldReference struct {
Label string
Unit string
Description string
ValueMappings []MetricValueMapping
}
func enumMappings(values ...string) []MetricValueMapping {
result := make([]MetricValueMapping, 0, len(values)/3)
for index := 0; index+2 < len(values); index += 3 {
result = append(result, MetricValueMapping{Value: values[index], Label: values[index+1], Description: values[index+2]})
}
return result
}
var gb32960PositionMappings = func() []MetricValueMapping {
result := make([]MetricValueMapping, 0, 8)
for value := 0; value < 8; value++ {
parts := []string{"有效定位", "北纬", "东经"}
if value&1 != 0 {
parts[0] = "无效定位"
}
if value&2 != 0 {
parts[1] = "南纬"
}
if value&4 != 0 {
parts[2] = "西经"
}
result = append(result, MetricValueMapping{
Value: strconv.Itoa(value),
Label: strings.Join(parts, " · "),
Description: "bit0 表示定位有效性bit1 表示纬度方向bit2 表示经度方向。",
})
}
return result
}()
var gb32960FieldReferences = map[string]gb32960FieldReference{
"gb32960.vehicle.vehicle_status": {Label: "车辆状态", Description: "车辆运行、停止等状态编码。", ValueMappings: enumMappings("1", "启动", "车辆处于可行驶启动状态。", "2", "熄火", "车辆处于熄火状态。", "3", "其他", "车辆处于其他状态。", "254", "异常", "协议异常值。", "255", "无效", "协议无效值。")},
"gb32960.vehicle.charge_status": {Label: "充电状态", Description: "车辆充电状态编码。", ValueMappings: enumMappings("1", "停车充电", "车辆停车充电。", "2", "行驶充电", "车辆行驶充电。", "3", "未充电", "车辆未充电。", "4", "充电完成", "车辆充电完成。", "254", "异常", "协议异常值。", "255", "无效", "协议无效值。")},
"gb32960.vehicle.running_mode": {Label: "运行模式", Description: "纯电、混合动力、燃料电池等运行模式编码。", ValueMappings: enumMappings("1", "纯电", "纯电驱动模式。", "2", "混合动力", "混合动力驱动模式。", "3", "燃料电池", "燃料电池驱动模式。", "254", "异常", "协议异常值。", "255", "无效", "协议无效值。")},
"gb32960.vehicle.speed_kmh": {Label: "车速", Unit: "km/h", Description: "车辆当前速度。"},
"gb32960.vehicle.total_mileage_km": {Label: "累计里程", Unit: "km", Description: "车辆累计行驶里程。"},
"gb32960.vehicle.total_voltage_v": {Label: "总电压", Unit: "V", Description: "动力系统总电压。"},
"gb32960.vehicle.total_current_a": {Label: "总电流", Unit: "A", Description: "动力系统总电流。"},
"gb32960.vehicle.soc_percent": {Label: "SOC", Unit: "%", Description: "动力电池荷电状态。"},
"gb32960.vehicle.dc_dc_status": {Label: "DC/DC 状态", Description: "DC/DC 工作状态编码。", ValueMappings: enumMappings("1", "工作", "DC/DC 处于工作状态。", "2", "断开", "DC/DC 处于断开状态。", "254", "异常", "协议异常值。", "255", "无效", "协议无效值。")},
"gb32960.vehicle.gear": {Label: "挡位原始值", Description: "挡位、驱动力和制动力组合原始编码。"},
"gb32960.vehicle.insulation_kohm": {Label: "绝缘电阻", Unit: "kΩ", Description: "高压系统绝缘电阻。"},
"gb32960.vehicle.accelerator_pct": {Label: "加速踏板行程", Unit: "%", Description: "2016 版字段,加速踏板开度。"},
"gb32960.vehicle.brake_pct": {Label: "制动踏板状态", Unit: "%", Description: "2016 版字段,制动踏板状态或开度。"},
"gb32960.drive_motor.serial_no": {Label: "驱动电机序号", Description: "电机编号。"},
"gb32960.drive_motor.state": {Label: "驱动电机状态", Description: "电机工作状态编码。", ValueMappings: enumMappings("1", "耗电", "驱动电机耗电。", "2", "发电", "驱动电机发电。", "3", "关闭", "驱动电机关闭。", "4", "准备", "驱动电机准备。", "254", "异常", "协议异常值。", "255", "无效", "协议无效值。")},
"gb32960.drive_motor.controller_temperature_c": {Label: "控制器温度", Unit: "℃", Description: "驱动电机控制器温度。"},
"gb32960.drive_motor.speed_rpm": {Label: "转速", Unit: "rpm", Description: "驱动电机转速。"},
"gb32960.drive_motor.torque_nm": {Label: "转矩", Unit: "N·m", Description: "驱动电机输出转矩。"},
"gb32960.drive_motor.motor_temperature_c": {Label: "电机温度", Unit: "℃", Description: "驱动电机温度。"},
"gb32960.drive_motor.controller_voltage_v": {Label: "控制器输入电压", Unit: "V", Description: "电机控制器直流母线输入电压。"},
"gb32960.drive_motor.controller_current_a": {Label: "控制器直流母线电流", Unit: "A", Description: "电机控制器直流母线电流。"},
"gb32960.fuel_cell.fuel_cell_voltage_v": {Label: "燃料电池电压", Unit: "V", Description: "燃料电池系统输出电压。"},
"gb32960.fuel_cell.fuel_cell_current_a": {Label: "燃料电池电流", Unit: "A", Description: "燃料电池系统输出电流。"},
"gb32960.fuel_cell.hydrogen_consumption_kg_per_100km": {Label: "氢耗", Unit: "kg/100km", Description: "燃料电池氢气消耗率。"},
"gb32960.fuel_cell.temperature_probe_values_c": {Label: "探针温度", Unit: "℃", Description: "燃料电池温度探针列表。"},
"gb32960.fuel_cell.max_hydrogen_temperature_c": {Label: "氢系统最高温度", Unit: "℃", Description: "氢系统最高温度。"},
"gb32960.fuel_cell.max_hydrogen_concentration_percent": {Label: "最高氢浓度", Unit: "%", Description: "氢气浓度最高值。"},
"gb32960.fuel_cell.max_hydrogen_pressure_mpa": {Label: "最高氢压力", Unit: "MPa", Description: "氢系统最高压力。"},
"gb32960.fuel_cell.dc_dc_status": {Label: "高压 DC/DC 状态", Description: "燃料电池高压 DC/DC 状态。"},
"gb32960.fuel_cell.max_hydrogen_temperature_probe_id": {Label: "最高氢温探针编号", Description: "检测到氢系统最高温度的探针编号。"},
"gb32960.fuel_cell.max_hydrogen_concentration_probe_id": {Label: "最高氢浓度探针编号", Description: "检测到最高氢浓度的探针编号。"},
"gb32960.fuel_cell.max_hydrogen_pressure_probe_id": {Label: "最高氢压探针编号", Description: "检测到最高氢压力的探针编号。"},
"gb32960.position.position_status": {Label: "定位状态标志", Description: "定位有效性及经纬度方向标志。", ValueMappings: gb32960PositionMappings},
"gb32960.position.coordinate_system": {Label: "坐标系", Description: "2025 版新增坐标系编码。", ValueMappings: enumMappings("1", "WGS84", "WGS84 坐标系。", "2", "GCJ-02", "GCJ-02 坐标系。", "3", "其他", "其他坐标系。")},
"gb32960.position.longitude": {Label: "经度", Unit: "°", Description: "车辆经度。"},
"gb32960.position.latitude": {Label: "纬度", Unit: "°", Description: "车辆纬度。"},
"gb32960.alarm.max_alarm_level": {Label: "最高报警等级", Description: "当前最高报警等级。", ValueMappings: enumMappings("0", "无故障", "当前无报警故障。", "1", "一级故障", "一级报警故障。", "2", "二级故障", "二级报警故障。", "3", "三级故障", "三级报警故障。")},
"gb32960.alarm.general_alarm_flag": {Label: "通用报警标志", Description: "通用报警位图。"},
"gb32960.alarm.battery_faults": {Label: "可充电储能装置故障码", Description: "动力电池相关故障码列表。"},
"gb32960.alarm.motor_faults": {Label: "驱动电机故障码", Description: "驱动电机相关故障码列表。"},
"gb32960.alarm.engine_faults": {Label: "发动机故障码", Description: "发动机相关故障码列表。"},
"gb32960.alarm.other_faults": {Label: "其他故障码", Description: "其他故障码列表。"},
"gb32960.gd_fc_stack.stack_count": {Label: "电堆数量", Description: "本包包含的电堆数量。"},
"gb32960.gd_fc_stack.engine_work_state": {Label: "发动机工作状态", Description: "燃料电池发动机工作状态。"},
"gb32960.gd_fc_stack.stack_water_outlet_temp_c": {Label: "电堆出水温度", Unit: "℃", Description: "电堆冷却水出口温度。"},
"gb32960.gd_fc_stack.hydrogen_inlet_pressure_kpa": {Label: "氢气入口压力", Unit: "kPa", Description: "电堆氢气入口压力。"},
"gb32960.gd_fc_stack.air_inlet_pressure_kpa": {Label: "空气入口压力", Unit: "kPa", Description: "电堆空气入口压力。"},
"gb32960.gd_fc_stack.air_inlet_temp_c": {Label: "空气入口温度", Unit: "℃", Description: "电堆空气入口温度。"},
"gb32960.gd_fc_stack.max_cell_voltage_v": {Label: "单体最高电压", Unit: "V", Description: "本电堆单体最高电压。"},
"gb32960.gd_fc_stack.min_cell_voltage_v": {Label: "单体最低电压", Unit: "V", Description: "本电堆单体最低电压。"},
"gb32960.gd_fc_stack.avg_cell_voltage_v": {Label: "单体平均电压", Unit: "V", Description: "本电堆单体平均电压。"},
"gb32960.gd_fc_stack.cell_count": {Label: "单体总数", Description: "电堆单体总数量。"},
"gb32960.gd_fc_stack.frame_cell_start": {Label: "本帧单体起始序号", Description: "当前分段电压起始单体序号。"},
"gb32960.gd_fc_stack.frame_cell_count": {Label: "本帧单体数量", Description: "当前分段包含的单体数量。"},
"gb32960.gd_fc_stack.frame_cell_voltages_v": {Label: "本帧单体电压列表", Unit: "V", Description: "当前分段的单体电压数组;未跨帧合并时不代表完整电堆快照。"},
"gb32960.gd_fc_dcdc.input_voltage_v": {Label: "输入电压", Unit: "V", Description: "DC/DC 输入电压。"},
"gb32960.gd_fc_dcdc.input_current_a": {Label: "输入电流", Unit: "A", Description: "DC/DC 输入电流。"},
"gb32960.gd_fc_dcdc.output_voltage_v": {Label: "输出电压", Unit: "V", Description: "DC/DC 输出电压。"},
"gb32960.gd_fc_dcdc.output_current_a": {Label: "输出电流", Unit: "A", Description: "DC/DC 输出电流。"},
"gb32960.gd_fc_dcdc.controller_temp_c": {Label: "控制器温度", Unit: "℃", Description: "DC/DC 控制器温度。"},
"gb32960.gd_fc_air_conditioner.status": {Label: "空调状态", Description: "空调工作状态。", ValueMappings: enumMappings("0", "关闭", "空调关闭。", "1", "启动", "空调启动。", "254", "异常", "协议异常值。", "255", "无效", "协议无效值。")},
"gb32960.gd_fc_air_conditioner.power_kw": {Label: "空调功率", Unit: "kW", Description: "空调消耗功率。"},
"gb32960.gd_fc_air_conditioner.compressor_input_voltage_v": {Label: "压缩机输入电压", Unit: "V", Description: "空调压缩机输入电压。"},
"gb32960.gd_fc_vehicle_info.collision_alarm": {Label: "碰撞报警", Description: "碰撞报警状态。", ValueMappings: enumMappings("0", "无碰撞报警", "当前无碰撞报警。", "1", "有碰撞报警", "当前有碰撞报警。", "254", "异常", "协议异常值。", "255", "无效", "协议无效值。")},
"gb32960.gd_fc_vehicle_info.ambient_temp_c": {Label: "环境温度", Unit: "℃", Description: "车辆环境温度。"},
"gb32960.gd_fc_vehicle_info.ambient_pressure_kpa": {Label: "环境压力", Unit: "kPa", Description: "车辆环境压力。"},
"gb32960.gd_fc_vehicle_info.hydrogen_mass_kg": {Label: "车载氢量", Unit: "kg", Description: "当前车载氢气质量。"},
}
func canonicalGB32960ReferenceKey(sourceField string) string {
sourceField = strings.ToLower(strings.TrimSpace(sourceField))
if !strings.HasPrefix(sourceField, "gb32960.") {
return sourceField
}
if strings.HasPrefix(sourceField, "gb32960.drive_motor.") {
return "gb32960.drive_motor." + lastSourcePart(sourceField)
}
if strings.HasPrefix(sourceField, "gb32960.gd_fc_stack.") {
return "gb32960.gd_fc_stack." + lastSourcePart(sourceField)
}
return sourceField
}
func lastSourcePart(sourceField string) string {
if index := strings.LastIndexByte(sourceField, '.'); index >= 0 && index+1 < len(sourceField) {
return sourceField[index+1:]
}
return sourceField
}
func gb32960ReferenceForSource(sourceField string) (gb32960FieldReference, bool) {
reference, ok := gb32960FieldReferences[canonicalGB32960ReferenceKey(sourceField)]
if !ok {
return gb32960FieldReference{}, false
}
reference.ValueMappings = append([]MetricValueMapping(nil), reference.ValueMappings...)
return reference, true
}
func protocolDisplayValue(sourceField string, value any) string {
reference, ok := gb32960ReferenceForSource(sourceField)
if !ok || len(reference.ValueMappings) == 0 || value == nil {
return ""
}
raw := metricMappingValue(value)
for _, mapping := range reference.ValueMappings {
if mapping.Value == raw {
return fmt.Sprintf("%s%s", mapping.Label, raw)
}
}
return fmt.Sprintf("未知状态(%s", raw)
}
func metricMappingValue(value any) string {
switch typed := value.(type) {
case json.Number:
return typed.String()
case float64:
if typed == float64(int64(typed)) {
return strconv.FormatInt(int64(typed), 10)
}
return strconv.FormatFloat(typed, 'f', -1, 64)
case float32:
return strconv.FormatFloat(float64(typed), 'f', -1, 32)
case int:
return strconv.Itoa(typed)
case int8:
return strconv.FormatInt(int64(typed), 10)
case int16:
return strconv.FormatInt(int64(typed), 10)
case int32:
return strconv.FormatInt(int64(typed), 10)
case int64:
return strconv.FormatInt(typed, 10)
case uint:
return strconv.FormatUint(uint64(typed), 10)
case uint8:
return strconv.FormatUint(uint64(typed), 10)
case uint16:
return strconv.FormatUint(uint64(typed), 10)
case uint32:
return strconv.FormatUint(uint64(typed), 10)
case uint64:
return strconv.FormatUint(typed, 10)
default:
return strings.TrimSpace(fmt.Sprint(value))
}
}
func enrichMetricDefinitions(definitions []MetricDefinition) []MetricDefinition {
result := make([]MetricDefinition, len(definitions))
copy(result, definitions)
for index := range result {
definition := &result[index]
sourceField := definition.SourceFields["GB32960"]
reference, ok := gb32960ReferenceForSource(sourceField)
if !ok {
continue
}
if len(definition.Protocols) == 1 && strings.EqualFold(definition.Protocols[0], "GB32960") {
definition.Label = reference.Label
definition.Description = reference.Description
definition.Unit = reference.Unit
}
definition.ValueMappings = reference.ValueMappings
}
return result
}