""" 2026/3/29 """ import struct import math def calc_telem(value: float, method: str, param_str: str, ref_cache: dict) -> float: #def telem_calc(value: float, method: str, param_str: str, ref_cache: dict) -> float: try: x = value # 空方法:原值 if not method: return x # 数值拟合 y = a*x + b if method == "数值拟合": a, b = map(float, param_str.split(',')) return a * x + b # 电压1:V = D/255*5.1 D无符号整型 elif method == "电压1": D = int(x) return D / 255.0 * 5.1 # 电压6:V = D*20/65535 D有符号整型 elif method == "电压6": D = int(x) return D * 20.0 / 65535.0 # 电压3:V = D*0.000305185 D有符号整型 elif method == "电压3": D = int(x) return D * 0.000305185 # 电压2:V= D *10/4096-5 D有符号整型 elif method == "电压2": D = int(x ) return D * 10 / 4096 - 5 # # 电阻拟合1 # elif method == "电阻拟合1": # D = int(x) # V = D / 255.0 * 5.1 # ref_key = param_str.strip() # Vref = ref_cache.get(ref_key, 5.1) # if abs(Vref - V) < 1e-12: # return 0.0 # Rr = 10000.0 # return V * Rr / (Vref - V) # 电阻拟合1 elif method == "电阻拟合1": D = int(x) V = D / 255.0 * 5.1 # V基准固定为 5.0V Vref = 5.0 if abs(Vref - V) < 1e-12: return 0.0 Rr = 10000.0 return V * Rr / (Vref - V) # # 特殊公式8(按你描述完整实现) # elif method == "特殊公式8": # raw = int(x) # if param_str: # parts = param_str.split(',') # else: # parts = [] # flag = int(parts[0]) if len(parts) >= 1 else 0 # if flag == 0: # # 遥测状态字:16位处理 # w = raw & 0xFFFF # bh = (w >> 8) & 0xFF # bl = w & 0xFF # bh8 = bh + 0x8 # bl8 = bl + 0x8 # h4 = (bh8 >> 4) & 0xF # l4 = (bl8 >> 4) & 0xF # B1 = (l4 << 4) | h4 # else: # # 遥控状态字:8位直接用 # B1 = raw & 0xFF # # 后面位比较逻辑你需要我也可以补全 # return float(B1) elif method == "特殊公式8": """ 最新规则: 1) 原始值取整 2) 低 16bit:低位 3) 高 4bit :高位 4) 合并 = (高位4bit << 16) | 低位16bit 5) 结果 = 合并值 × 0.00205479 """ raw_int = int(x) & 0xFFFFFFFF # 取32位无符号 # 低位 16bit low16 = raw_int & 0xFFFF # 高位 4bit(最后4bit) high4 = (raw_int >> 28) & 0x0F # 合并 20bit:高4位 <<16 | 低16位 combined = (high4 << 16) | low16 # 乘以系数 result = combined * 0.00205479 return float(result) # 状态量 / 10进制:不处理 elif method in ["状态量", "10进制"]: return x return x except Exception as e: return value import struct import math def poly4_calc(D): """正向 4 次多项式计算 y""" y = (-49.736 * (D ** 4) + 383.38 * (D ** 3) - 1068.5 * (D ** 2) + 1309.9 * D - 684.71) return y def inverse_poly4_fit(y): """ 逆运算:已知 y → 求 D 适用于:y ∈ [-112, 42] """ if not (-112 <= y <= 42): return 0.0 # 超范围保护 # 二分法区间(根据你的遥测范围实测得出) left = 1.5 right = 4.5 eps = 1e-5 for _ in range(50): mid = (left + right) / 2 current_y = poly4_calc(mid) if current_y < y: left = mid else: right = mid return (left + right) / 2 # 固定系数 Rr = 10000.0 A = -6.01188 B = 4622.53337 C = -86421.72414 def calc_t_from_V(V): """正向:V → t(内部用)""" if V >= 5.0: V = 4.9999 if V <= 0: V = 0.0001 R = V * Rr / (5.0 - V) lnR = math.log(R) sqrt_val = math.sqrt(B**2 - 4 * C * (A - lnR)) t = 2 * C / (sqrt_val - B) - 273.15 return t def calc_V_from_t(t_target): """ 逆运算:已知温度 t → 求遥测电压 V :param t_target: 目标温度 ℃ :return: V (V),精度 0.0001 """ # 电压范围 0 ~ 5V left = 0.0001 right = 4.9999 eps = 1e-5 # 二分法迭代 50 次足够精确 for _ in range(50): mid = (left + right) / 2 t_mid = calc_t_from_V(mid) if t_mid < t_target: left = mid else: right = mid return (left + right) / 2 def inverse_quadratic_fit(y, coeffs, y_min, y_max): """ 通用二次多项式逆运算(3个拟合参数) 公式:y = a2*D² + a1*D + a0 已知 y → 求 D(只返回合法正根) 参数: y: 目标物理值 coeffs: 拟合系数 [a2, a1, a0] y_min: y 有效最小值 y_max: y 有效最大值 返回: D: 原始码值 """ # 1. 边界限幅 y_clamped = max(y_min, min(y, y_max)) # 2. 取出系数 a2, a1, a0 = coeffs # 3. 构建一元二次方程标准形式:A*D² + B*D + C = 0 A = a2 B = a1 C = a0 - y_clamped # 4. 求判别式 delta = B ** 2 - 4 * A * C if delta < 0: delta = 0 # 防止无实根 # 5. 求正根(遥测D一定为正) D = (-B + (delta ** 0.5)) / (2 * A) # 6. 保证 D 不为负 return max(D, 0.0) def calc_telem_reverse(result: float, method: str, param_str: str) -> float: """ 【逆运算】 输入:A 软件发来的 结果值 输出:反推出来的 原始值 D 完全按你提供的处理方法反向计算 """ try: y = result # ===================== 空方法:直接返回 ===================== if not method: return y # ===================== 数值拟合:Y = a*x + b → x=(y-b)/a ===================== if method == "数值拟合": a, b = map(float, param_str.split(',')) x = (y - b) / a return x # ===================== 电压1:V = D/255*5.1 → D=V*255/5.1 ===================== elif method == "电压1": D = y * 255.0 / 5.1 return float(int(round(D))) # 原始是无符号整型 # ===================== 电压6:V = D*20/65535 → D=V*65535/20 ===================== elif method == "电压6": D = y * 65535.0 / 20.0 return float(int(round(D))) # 有符号整型 # ===================== 电压3:V = D*0.000305185 → D=V / 0.000305185 ===================== elif method == "电压3": D = y / 0.000305185 return float(int(round(D))) # 有符号整型 # ===================== 电压2:V电压2 = D *10/4096-5,其中D为无符号整型,计算时转化成十进制数。 → D=(V + 5)*409.6 ===================== elif method == "电压2": D = (y + 5) * 409.6 return float(int(round(D))) # 有符号整型 # ===================== 电阻拟合1 → 逆运算 ===================== # 公式: # V = D/255*5.1 # R = V*10000/(5.0 - V) # 逆推 D #2026/3/30手算验证公式是正确的 elif method == "电阻拟合1": R = y Vref = 5.0 Rr = 10000.0 # 逆推 V if R <= 0.0: V = 0.0 else: V = (R * Vref) / (R + Rr) # 逆推 D D = V * 255.0 / 5.1 return float(int(round(D))) # ===================== 特殊公式8(逆运算) ===================== # 正向:combined = (high4 <<16) | low16 result = combined * 0.00205479 # 逆向:combined = y / 0.00205479 # high4 = (combined >> 16) & 0xF # low16 = combined & 0xFFFF # raw = (high4 << 28) | low16 elif method == "特殊公式8": combined = int(round(y / 0.00205479)) low16 = combined & 0xFFFF high4 = (combined >> 16) & 0x0F raw = (high4 << 28) | low16 return float(raw) # ===================== 状态量 / 10进制:直接返回 ===================== elif method in ["状态量", "10进制"]: return y elif method == "特殊公式11-1": """ M057JG023 / M057JG024 专用逆运算 输入:物理值 y 输出:原始值 m(用于组帧) """ # if y < (0.0973 * 1840 + 180): # 区间1:y < 359.032 # m = (y - 180) / 0.0973 # elif y > (0.0974 * 1840 - 179.46): # 区间2:y > -0.444 # m = (y + 179.46) / 0.0974 # else: # m=1840 # m = 1840.0 #2026/5/7修正公式 if y < (180): # 区间1: m = (y + 179.46) / 0.0974 elif y > (180): # 区间2: m = (y - 180) / 0.0973 else: # m=1840 m = 0.0 # 组帧需要整数,返回四舍五入 return float(round(m)) elif method == "电压2,数值拟合": """ 逆运算,先反解数值拟合,再反推电压2 """ a, b = map(float, param_str.split(',')) x = (y - b) / a D = (x + 5) * 409.6## 电压2 return float(int(round(D))) # 有符号整型 elif method == "电压1,数值拟合": """ 逆运算,先反解数值拟合,再反推电压2 """ a, b = map(float, param_str.split(',')) x = (y - b) / a D = x * 255.0 / 5.1## 电压1 return float(int(round(D))) # 有符号整型 elif method == "电压1,数值拟合5": """ 逆运算,先反解数值拟合(5次方程),再反推电压2 """ x = inverse_poly4_fit(y) ##2分法求解5次方程 D = x * 255.0 / 5.1## 电压1 return float(int(round(D))) # 有符号整型 elif method == "电阻拟合1,MF501(电阻)": x = calc_V_from_t(y) #2分法 R = x Vref = 5.0 Rr = 10000.0 # 逆推 V if R <= 0.0: V = 0.0 else: V = (R * Vref) / (R + Rr) # 逆推 D D = V * 255.0 / 5.1 return float(int(round(D))) elif method == "电压1,数值拟合3": a, b,c,y_min,y_max = map(float, param_str.split(',')) coeffs = [a,b,c] return inverse_quadratic_fit(y, coeffs, y_min, y_max) elif method == "电压6,数值拟合": """ 逆运算,先反解数值拟合,再反推电压2 """ a, b = map(float, param_str.split(',')) x = (y - b) / a D = x * 65535.0 / 20.0 #电压6 return float(int(round(D))) # 有符号整型 except Exception as e: return result