Add update script, enhance admin features, and improve styles
- Created a PowerShell script (update.ps1) for automating the process of pulling the latest repository changes, stopping, building, and starting the Docker Compose stack. - Updated App.jsx to include new admin sections for alarms and integrations, added state management for runner jobs, and enhanced permission checks. - Extended the API module (api.js) with new endpoints for managing integrations and runner jobs. - Improved CSS styles for a more compact and responsive layout in the admin interface, focusing on source and datapoint cards.
This commit is contained in:
+37
-1
@@ -278,6 +278,9 @@ function parseModbusCsv(payload) {
|
||||
dataType: get("datatype", "holding-register"),
|
||||
kind: normalizePointKind(get("kind", get("type", "analog"))),
|
||||
enabled: payload.enabled === true,
|
||||
alarmEnabled: payload.alarmEnabled === true,
|
||||
alarmCondition: normalizeText(payload.alarmCondition),
|
||||
alarmGroupId: normalizeText(payload.alarmGroupId),
|
||||
writeMode: normalizeWriteMode(get("writemode", payload.writeMode || "")),
|
||||
condition: get("condition", payload.condition || ""),
|
||||
scale: Number(get("scale", 1)) || 1,
|
||||
@@ -328,6 +331,9 @@ function parseKnxXml(payload) {
|
||||
dataType: dpt || "group-address",
|
||||
kind: dpt.startsWith("1.") ? "digital" : "analog",
|
||||
enabled: payload.enabled === true,
|
||||
alarmEnabled: payload.alarmEnabled === true,
|
||||
alarmCondition: normalizeText(payload.alarmCondition),
|
||||
alarmGroupId: normalizeText(payload.alarmGroupId),
|
||||
writeMode: normalizeWriteMode(payload.writeMode || ""),
|
||||
condition: payload.condition || "",
|
||||
host: payload.host || "",
|
||||
@@ -364,6 +370,9 @@ function createManualDatapoint(store, payload) {
|
||||
unit: normalizePointUnit(payload.unit, payload.kind),
|
||||
kind: normalizePointKind(payload.kind),
|
||||
enabled: payload.enabled !== false,
|
||||
alarmEnabled: payload.alarmEnabled === true,
|
||||
alarmCondition: normalizeText(payload.alarmCondition),
|
||||
alarmGroupId: normalizeText(payload.alarmGroupId),
|
||||
writeMode: normalizeWriteMode(payload.writeMode || source.writeMode),
|
||||
condition: normalizeText(payload.condition),
|
||||
dataType: normalizeText(payload.dataType || (protocol === "knx-ip" ? "group-address" : "holding-register")),
|
||||
@@ -398,6 +407,9 @@ function createScanDatapoint(source, payload, index) {
|
||||
unit: normalizePointUnit(payload.unit, payload.kind),
|
||||
kind: normalizePointKind(payload.kind),
|
||||
enabled: payload.enabled === true,
|
||||
alarmEnabled: payload.alarmEnabled === true,
|
||||
alarmCondition: normalizeText(payload.alarmCondition),
|
||||
alarmGroupId: normalizeText(payload.alarmGroupId),
|
||||
writeMode: normalizeWriteMode(payload.writeMode || source.writeMode),
|
||||
condition: normalizeText(payload.condition),
|
||||
dataType: normalizeText(payload.dataType),
|
||||
@@ -446,7 +458,7 @@ function buildScannedDatapoints(store, source, rawPoints, toPayload) {
|
||||
pointIndex: existing.pointIndex,
|
||||
alias: !existingAlias || existingLooksLikeScanDefault ? scanned.alias : existing.alias,
|
||||
name: scanned.name || existing.name,
|
||||
unit: normalizePointUnit(existing.unit || scanned.unit, existing.kind || scanned.kind),
|
||||
unit: existing.enabled === true ? normalizePointUnit(existing.unit || scanned.unit, existing.kind || scanned.kind) : normalizePointUnit(scanned.unit || existing.unit, scanned.kind || existing.kind),
|
||||
kind: existing.kind || scanned.kind,
|
||||
enabled: existing.enabled === true,
|
||||
writeMode: normalizeWriteMode(existing.writeMode || scanned.writeMode),
|
||||
@@ -1066,6 +1078,11 @@ function sendBacnetWhoIs(client, routing, deviceId) {
|
||||
throw new Error("Who-Is konnte nicht ausgel?st werden.");
|
||||
}
|
||||
|
||||
function bacnetUnitSymbol(value) {
|
||||
const unit = Number(value);
|
||||
const map = { 3: "A", 5: "V", 53: "Pa", 62: "°C", 63: "K", 95: "", 98: "%" };
|
||||
return Object.prototype.hasOwnProperty.call(map, unit) ? map[unit] : "";
|
||||
}
|
||||
function readBacnetProperty(client, host, objectId, propertyId) {
|
||||
return new Promise((resolve) => {
|
||||
client.readProperty(host, objectId, propertyId, (error, value) => {
|
||||
@@ -1092,6 +1109,7 @@ async function scanBacnetObjects(client, device, portNumber) {
|
||||
const objectName = await readBacnetProperty(client, host, objectId, 77);
|
||||
const description = await readBacnetProperty(client, host, objectId, 28);
|
||||
const presentValue = await readBacnetProperty(client, host, objectId, 85);
|
||||
const units = await readBacnetProperty(client, host, objectId, 117);
|
||||
const raw = presentValue?.values?.[0]?.value ?? null;
|
||||
const label = bacnetObjectLabel(objectId);
|
||||
const name = normalizeText(objectName?.values?.[0]?.value) || label;
|
||||
@@ -1100,6 +1118,8 @@ async function scanBacnetObjects(client, device, portNumber) {
|
||||
id: host + "-" + objectId.type + "-" + objectId.instance,
|
||||
host,
|
||||
port: portNumber,
|
||||
deviceId: device.deviceId,
|
||||
deviceName: device.name || "BACnet Gerät " + device.deviceId,
|
||||
objectType: objectId.type,
|
||||
objectInstance: objectId.instance,
|
||||
propertyId: 85,
|
||||
@@ -1109,6 +1129,7 @@ async function scanBacnetObjects(client, device, portNumber) {
|
||||
description: alias,
|
||||
alias,
|
||||
kind: typeof raw === "boolean" || objectId.type >= 3 && objectId.type <= 5 ? "digital" : "analog",
|
||||
unit: typeof raw === "boolean" || objectId.type >= 3 && objectId.type <= 5 ? "bool" : bacnetUnitSymbol(units?.values?.[0]?.value),
|
||||
currentValue: raw,
|
||||
hasValue: raw !== null,
|
||||
});
|
||||
@@ -1947,9 +1968,11 @@ const server = createServer(async (req, res) => {
|
||||
updatedAt: store.updatedAt,
|
||||
sourceCount: store.sources.length,
|
||||
datapointCount: store.datapoints.length,
|
||||
alarmDatapointCount: store.datapoints.filter((item) => item.alarmEnabled === true).length,
|
||||
sources: store.sources.map((source) => ({
|
||||
...source,
|
||||
datapointCount: store.datapoints.filter((item) => item.sourceId === source.id).length,
|
||||
alarmDatapointCount: store.datapoints.filter((item) => item.sourceId === source.id && item.alarmEnabled === true).length,
|
||||
})),
|
||||
latestScans: {
|
||||
opcua: store.scans.opcua[0] || null,
|
||||
@@ -2046,6 +2069,9 @@ const server = createServer(async (req, res) => {
|
||||
store.datapoints[index] = {
|
||||
...store.datapoints[index],
|
||||
enabled: typeof body.enabled === "boolean" ? body.enabled : store.datapoints[index].enabled,
|
||||
alarmEnabled: typeof body.alarmEnabled === "boolean" ? body.alarmEnabled : store.datapoints[index].alarmEnabled === true,
|
||||
alarmCondition: typeof body.alarmCondition === "string" ? body.alarmCondition.trim() : store.datapoints[index].alarmCondition,
|
||||
alarmGroupId: typeof body.alarmGroupId === "string" ? body.alarmGroupId.trim() : store.datapoints[index].alarmGroupId,
|
||||
writeMode: typeof body.writeMode === "string" ? normalizeWriteMode(body.writeMode) : store.datapoints[index].writeMode,
|
||||
condition: typeof body.condition === "string" ? body.condition.trim() : store.datapoints[index].condition,
|
||||
pointIndex: body.pointIndex ? normalizePointIndex(body.pointIndex, store.datapoints[index].pointIndex) : store.datapoints[index].pointIndex,
|
||||
@@ -2222,3 +2248,13 @@ server.listen(port, () => {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user