package model import ( "fmt" "strings" "modelRT/constants" "modelRT/orm" ) var allowedMeasurementTypes = map[string]struct{}{ "TM": {}, "TS": {}, "TC": {}, "TA": {}, "SP": {}, } // MeasurementTypeFromDataSource returns the two-character measurement type // encoded in a CL3611 channel. Only TM, TS, TC, TA, and SP are valid. func MeasurementTypeFromDataSource(dataSource orm.JSONMap) (string, error) { dataSourceType, err := integerJSONValue(dataSource["type"]) if err != nil { return "", fmt.Errorf("invalid measurement data_source type: %w", err) } if dataSourceType != constants.DataSourceTypeCL3611 { return "", fmt.Errorf("measurement type requires data_source type %d, got %d", constants.DataSourceTypeCL3611, dataSourceType) } ioAddress, ok := dataSource["io_address"].(map[string]any) if !ok { if value, jsonMapOK := dataSource["io_address"].(orm.JSONMap); jsonMapOK { ioAddress = map[string]any(value) } else { return "", fmt.Errorf("measurement data_source io_address is not an object") } } channel, ok := ioAddress["channel"].(string) if !ok || len(channel) < 2 { return "", fmt.Errorf("measurement data_source channel must contain at least two characters") } measurementType := strings.ToUpper(channel[:2]) if _, ok := allowedMeasurementTypes[measurementType]; !ok { return "", fmt.Errorf("unsupported measurement type %q", measurementType) } return measurementType, nil } func integerJSONValue(value any) (int, error) { switch typed := value.(type) { case int: return typed, nil case int8: return int(typed), nil case int16: return int(typed), nil case int32: return int(typed), nil case int64: return int(typed), nil case float32: converted := int(typed) if typed != float32(converted) { return 0, fmt.Errorf("expected integer, got %v", typed) } return converted, nil case float64: converted := int(typed) if typed != float64(converted) { return 0, fmt.Errorf("expected integer, got %v", typed) } return converted, nil default: return 0, fmt.Errorf("expected integer, got %T", value) } }