Commit 589f4562 by James Yuan

fix: 改点位倍率后即时重算并自动下发网关,补充 E 栋冰箱点表

保存/导入点位后同步 Windows 网关;倍率变更用 lastRaw 重算 lastEng,避免实时值仍按旧倍率显示。

Co-authored-by: Cursor <cursoragent@cursor.com>
parent fd50d6bd
......@@ -908,6 +908,33 @@ export async function createPoint(
return p
}
function usesLinearScale(dataType: string): boolean {
const t = (dataType || '').toLowerCase()
return !t.includes('float') && !t.includes('double') && !t.includes('bool')
}
/** 倍率/偏置变更时用 lastRaw 立即重算工程值(Float/Double 不乘 scale) */
function recomputeEngAfterScaleChange(cur: DevicePoint, next: DevicePoint): boolean {
const scaleChanged =
next.scale !== cur.scale ||
next.bias !== cur.bias ||
next.scaleOverride !== cur.scaleOverride
if (!scaleChanged) return false
if (next.lastRaw === null || next.lastRaw === undefined) return false
if (!usesLinearScale(next.dataType)) return false
next.lastEng = toEngineering(
next.lastRaw,
next.scale,
next.bias,
next.scaleOverride,
next.minRawRange,
next.maxRawRange,
next.minEngRange,
next.maxEngRange,
)
return true
}
export async function updatePoint(
id: string,
patch: Partial<DevicePoint>,
......@@ -921,6 +948,7 @@ export async function updatePoint(
id: cur.id,
updatedAt: now(),
}
const engRecomputed = recomputeEngAfterScaleChange(cur, next)
if (!isPgEnabled()) {
const i = mem.points.findIndex((x) => x.id === id)
mem.points[i] = next
......@@ -934,7 +962,9 @@ export async function updatePoint(
modbus_id=$8, modbus_register=$9, modbus_address=$10, description=$11, mask_bit=$12, bit=$13,
scale=$14, bias=$15, min_raw_range=$16, max_raw_range=$17, min_eng_range=$18, max_eng_range=$19,
item_id=$20, snapshot_path=$21, rw=$22, energy_kind=$23, scale_override=$24,
alarm_low=$25, alarm_high=$26, enabled=$27, updated_at=NOW()
alarm_low=$25, alarm_high=$26, enabled=$27,
last_eng=CASE WHEN $28::boolean THEN $29::double precision ELSE last_eng END,
updated_at=NOW()
WHERE id=$1`,
[
id,
......@@ -964,6 +994,8 @@ export async function updatePoint(
next.alarmLow,
next.alarmHigh,
next.enabled,
engRecomputed,
next.lastEng,
],
)
await bumpVersionPg()
......
......@@ -116,6 +116,18 @@ devicesRouter.delete('/:id', authRequired, requireRole('admin'), async (req, res
res.json({ ok: true })
})
/** 点表变更后异步下发网关;不阻塞保存成功响应,失败只打日志 */
function pushPointsToGatewayInBackground(reason: string) {
void syncPointsToGateway()
.then((r) => {
if (!r.ok) console.warn(`[devices] sync-gateway after ${reason}: ${r.message}`)
else console.log(`[devices] sync-gateway after ${reason}: ok v=${r.pointsVersion}`)
})
.catch((e) => {
console.warn(`[devices] sync-gateway after ${reason} threw`, e)
})
}
devicesRouter.get('/points', authRequired, async (req, res) => {
const gatewayId = req.query.gatewayId ? String(req.query.gatewayId) : undefined
const deviceId = req.query.deviceId ? String(req.query.deviceId) : undefined
......@@ -135,6 +147,7 @@ devicesRouter.post('/points', authRequired, requireRole('admin'), async (req, re
modbusAddress: Number(body.modbusAddress),
...body,
})
pushPointsToGatewayInBackground(`create-point ${point.id}`)
res.status(201).json(point)
} catch (e) {
res.status(400).json({ message: e instanceof Error ? e.message : '创建失败' })
......@@ -148,6 +161,7 @@ devicesRouter.patch('/points/:id', authRequired, requireRole('admin'), async (re
res.status(404).json({ message: '点位不存在' })
return
}
pushPointsToGatewayInBackground(`patch-point ${p.id}`)
res.json(p)
} catch (e) {
res.status(400).json({ message: e instanceof Error ? e.message : '更新失败' })
......@@ -160,6 +174,7 @@ devicesRouter.delete('/points/:id', authRequired, requireRole('admin'), async (r
res.status(404).json({ message: '点位不存在' })
return
}
pushPointsToGatewayInBackground(`delete-point ${req.params.id}`)
res.json({ ok: true })
})
......@@ -186,6 +201,7 @@ devicesRouter.post('/points/import', authRequired, requireRole('admin'), async (
encoding: req.body?.encoding,
replaceGateway: Boolean(req.body?.replaceGateway),
})
pushPointsToGatewayInBackground(`import-points ${gatewayId}`)
res.json(result)
} catch (e) {
res.status(400).json({ message: e instanceof Error ? e.message : '导入失败' })
......
id,Name,RegType,RegAddress,DataType,Modbus ID,Modbus Register,Modbus Address,Description,MaskBit,Bit,Scale,Bias,MinRawRange,MaxRawRange,MinEngRange,MaxEngRange,ItemID
id,Name,RegType,RegAddress,DataType,Modbus ID,Modbus Register,Modbus Address,Description,MaskBit,Bit,Scale,Bias,MinRawRange,MaxRawRange,MinEngRange,MaxEngRange,ItemID
1,冰箱1温度,4X(Holding Register),1,Short,1,4X(Holding Register),1,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱1.温度
2,冰箱2温度,4X(Holding Register),2,Short,1,4X(Holding Register),2,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱2.温度
3,冰箱3温度,4X(Holding Register),3,Short,1,4X(Holding Register),3,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱3.温度
4,冰箱4温度,4X(Holding Register),4,Short,1,4X(Holding Register),4,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱4.温度
5,冰箱5温度,4X(Holding Register),5,Short,1,4X(Holding Register),5,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱5.温度
6,冰箱6温度,4X(Holding Register),6,Short,1,4X(Holding Register),6,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱6.温度
7,冰箱7温度,4X(Holding Register),7,Short,1,4X(Holding Register),7,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱7.温度
8,冰箱8温度,4X(Holding Register),8,Short,1,4X(Holding Register),8,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱8.温度
9,冰箱1湿度,4X(Holding Register),21,Short,1,4X(Holding Register),21,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱1.湿度
10,冰箱2湿度,4X(Holding Register),22,Short,1,4X(Holding Register),22,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱2.湿度
11,冰箱3湿度,4X(Holding Register),23,Short,1,4X(Holding Register),23,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱3.湿度
12,冰箱4湿度,4X(Holding Register),24,Short,1,4X(Holding Register),24,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱4.湿度
13,冰箱5湿度,4X(Holding Register),25,Short,1,4X(Holding Register),25,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱5.湿度
14,冰箱6湿度,4X(Holding Register),26,Short,1,4X(Holding Register),26,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱6.湿度
15,冰箱7湿度,4X(Holding Register),27,Short,1,4X(Holding Register),27,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱7.湿度
16,冰箱8湿度,4X(Holding Register),28,Short,1,4X(Holding Register),28,E栋冰箱网关192.168.10.105,0,0,0,0,0,0,0,0,mb-105.E栋冰箱8.湿度
......@@ -422,7 +422,7 @@ async function savePoint() {
enabled: editPoint.value.enabled,
}),
})
message.value = '点位已保存'
message.value = '点位已保存(倍率已即时重算,并自动下发网关)'
editPoint.value = null
error.value = ''
if (returnToDeviceView.value && selectedDevice.value) {
......@@ -1206,12 +1206,12 @@ onUnmounted(stopViewRefresh)
</div>
<div class="field"><label>ItemID</label><input v-model="editPoint.itemId" /></div>
<div class="field">
<label>Scale</label>
<label>Scale(底表)</label>
<input v-model.number="editPoint.scale" type="number" step="any" />
</div>
<div class="field">
<label>Scale 覆盖</label>
<input v-model.number="editPoint.scaleOverride" type="number" step="any" />
<label>倍率(覆盖,优先生效)</label>
<input v-model.number="editPoint.scaleOverride" type="number" step="any" placeholder="空=用 Scale" />
</div>
<div class="field">
<label>告警下限</label>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment