node-red-contrib-knx-ultimate 8.1.0 → 8.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/nodes/commonFunctions.js +13 -151
  3. package/nodes/knxUltimate-config.html +96 -158
  4. package/nodes/knxUltimate-config.js +64 -58
  5. package/nodes/knxUltimate.html +4 -0
  6. package/nodes/knxUltimateUtility.html +7 -0
  7. package/nodes/knxUltimateViewer.html +3 -0
  8. package/nodes/knxUltimateViewer.js +3 -1
  9. package/nodes/locales/de/knxUltimate-config.html +8 -5
  10. package/nodes/locales/de/knxUltimate-config.json +22 -20
  11. package/nodes/locales/de/knxUltimate.html +2 -0
  12. package/nodes/locales/de/knxUltimateUtility.html +6 -0
  13. package/nodes/locales/de/knxUltimateViewer.html +2 -0
  14. package/nodes/locales/en/knxUltimate-config.html +8 -5
  15. package/nodes/locales/en/knxUltimate-config.json +22 -20
  16. package/nodes/locales/en/knxUltimate.html +2 -0
  17. package/nodes/locales/en/knxUltimateUtility.html +6 -0
  18. package/nodes/locales/en/knxUltimateViewer.html +2 -0
  19. package/nodes/locales/es/knxUltimate-config.html +12 -6
  20. package/nodes/locales/es/knxUltimate-config.json +22 -20
  21. package/nodes/locales/es/knxUltimate.html +2 -0
  22. package/nodes/locales/es/knxUltimateUtility.html +6 -0
  23. package/nodes/locales/es/knxUltimateViewer.html +2 -0
  24. package/nodes/locales/fr/knxUltimate-config.html +10 -7
  25. package/nodes/locales/fr/knxUltimate-config.json +22 -20
  26. package/nodes/locales/fr/knxUltimate.html +2 -0
  27. package/nodes/locales/fr/knxUltimateUtility.html +6 -0
  28. package/nodes/locales/fr/knxUltimateViewer.html +2 -0
  29. package/nodes/locales/it/knxUltimate-config.html +8 -5
  30. package/nodes/locales/it/knxUltimate-config.json +22 -20
  31. package/nodes/locales/it/knxUltimate.html +2 -0
  32. package/nodes/locales/it/knxUltimateUtility.html +6 -0
  33. package/nodes/locales/it/knxUltimateViewer.html +2 -0
  34. package/nodes/locales/zh-CN/knxUltimate-config.html +8 -5
  35. package/nodes/locales/zh-CN/knxUltimate-config.json +22 -20
  36. package/nodes/locales/zh-CN/knxUltimate.html +2 -0
  37. package/nodes/locales/zh-CN/knxUltimateUtility.html +6 -0
  38. package/nodes/locales/zh-CN/knxUltimateViewer.html +2 -0
  39. package/nodes/utils/fileStorage.js +376 -0
  40. package/nodes/utils/knxUtilityProfiles/runtime/autoresponder.js +15 -19
  41. package/nodes/utils/knxUtilityProfiles/runtime/logger.js +7 -4
  42. package/nodes/utils/knxUtilityProfiles/runtime/scenecontroller.js +12 -44
  43. package/nodes/utils/knxViewerHistory.js +49 -77
  44. package/package.json +2 -2
  45. package/resources/htmlUtils.js +24 -2
@@ -25,6 +25,7 @@ const loggerClass = require('./utils/sysLogger')
25
25
  const payloadRounder = require('./utils/payloadManipulation')
26
26
  const utils = require('./utils/utils')
27
27
  const dispatchWatchDogNodeError = require('./utils/watchDogErrorDispatcher')
28
+ const { createFileStorage } = require('./utils/fileStorage')
28
29
 
29
30
  // Versions logged once at startup (node package + KNXUltimate engine)
30
31
  let NODE_VERSION = 'unknown'
@@ -32,6 +33,19 @@ try { NODE_VERSION = require('../package.json').version } catch (e) { /* empty *
32
33
  let KNX_ENGINE_VERSION = 'unknown'
33
34
  try { KNX_ENGINE_VERSION = require('knxultimate/package.json').version } catch (e) { /* empty */ }
34
35
 
36
+ // Returns the group service of a bus telegram, or null when it is not one:
37
+ // transport control TPDUs (T_Connect, T_Disconnect, T_ACK, T_NAK: TPCI only, no APCI)
38
+ // and point-to-point telegrams (cEMI Ctrl2 address type 0 = individual destination).
39
+ const getGroupServiceEvent = (cEMIMessage) => {
40
+ const npdu = cEMIMessage?.npdu
41
+ if (!npdu || npdu.isTransportControl === true) return null
42
+ if (cEMIMessage.control?.addressType === 0) return null
43
+ if (npdu.isGroupRead) return 'GroupValue_Read'
44
+ if (npdu.isGroupResponse) return 'GroupValue_Response'
45
+ if (npdu.isGroupWrite) return 'GroupValue_Write'
46
+ return null
47
+ }
48
+
35
49
  // DATAPONT MANIPULATION HELPERS
36
50
  // ####################
37
51
  const sortBy = (field) => (a, b) => {
@@ -210,6 +224,8 @@ module.exports = (RED) => {
210
224
  node.port = parseInt(config.port)
211
225
  node.physAddr = config.physAddr // the KNX physical address we'd like to use
212
226
  node.suppressACKRequest = typeof config.suppressACKRequest === 'undefined' ? true : config.suppressACKRequest // enable this option to suppress the acknowledge flag with outgoing L_Data.req requests. LoxOne needs this
227
+ // TunnelUDP: wait for the TUNNELLING_ACK of each request (yes/no). "auto" leaves it to the KNX engine, which follows suppressACKRequest.
228
+ node.waitForTunnelingAck = config.waitForTunnelingAck === 'yes' ? true : config.waitForTunnelingAck === 'no' ? false : undefined
213
229
  node.linkStatus = 'disconnected' // Can be: connected or disconnected
214
230
  node.nodeClients = [] // Stores the registered clients
215
231
  node.KNXEthInterface = typeof config.KNXEthInterface === 'undefined' ? 'Auto' : config.KNXEthInterface
@@ -226,6 +242,16 @@ module.exports = (RED) => {
226
242
  try {
227
243
  node.sysLogger = new loggerClass({ loglevel: node.loglevel, setPrefix: node.type + ' <' + (node.name || node.id || '') + '>' })
228
244
  } catch (error) { console.log(error.stack) }
245
+ // File Cache Control: every file written by this gateway and by its nodes goes through this storage.
246
+ node.fileCacheMode = config.fileCacheMode || 'freshness'
247
+ node.fileStorage = createFileStorage({
248
+ ownerId: node.id,
249
+ mode: node.fileCacheMode,
250
+ interval: config.fileCacheInterval,
251
+ intervalUnit: config.fileCacheIntervalUnit,
252
+ log: (level, message) => node.sysLogger?.[level]?.(message)
253
+ })
254
+ node.persistFile = path.join(node.userDir, 'knxpersistvalues', 'knxpersist' + node.id + '.json')
229
255
  node.csv = readCSV(config.csv) // Array from ETS CSV Group Addresses {ga:group address, dpt: datapoint, devicename: full device name with main and subgroups}
230
256
  node.csvByGa = new Map()
231
257
  if (Array.isArray(node.csv)) {
@@ -247,15 +273,27 @@ module.exports = (RED) => {
247
273
  return node.exposedGAsByGa.get(ga)
248
274
  }
249
275
 
276
+ // The persist file is serialized only when the storage commits it.
277
+ const saveExposedGAs = () => {
278
+ node.fileStorage.writeFile(node.persistFile, () => JSON.stringify(node.exposedGAs))
279
+ }
280
+ const rawValueKey = (rawValue) => {
281
+ try { return Buffer.from(rawValue?.data ?? rawValue).toString('hex') } catch (error) { return undefined }
282
+ }
283
+
250
284
  node.upsertExposedGAEntry = (entry) => {
251
285
  if (!entry || typeof entry.ga !== 'string' || entry.ga === '') return undefined
252
286
  const existing = node.exposedGAsByGa.get(entry.ga)
253
287
  if (existing) {
288
+ // A repeated value does not need to be written again.
289
+ const changed = rawValueKey(existing.rawValue) !== rawValueKey(entry.rawValue) || existing.dpt !== entry.dpt || existing.devicename !== entry.devicename
254
290
  Object.assign(existing, entry)
291
+ if (changed) saveExposedGAs()
255
292
  return existing
256
293
  }
257
294
  node.exposedGAs.push(entry)
258
295
  node.exposedGAsByGa.set(entry.ga, entry)
296
+ saveExposedGAs()
259
297
  return entry
260
298
  }
261
299
 
@@ -263,7 +301,10 @@ module.exports = (RED) => {
263
301
  if (typeof ga !== 'string' || ga === '') return
264
302
  node.exposedGAsByGa.delete(ga)
265
303
  const index = node.exposedGAs.findIndex((item) => item.ga === ga)
266
- if (index > -1) node.exposedGAs.splice(index, 1)
304
+ if (index > -1) {
305
+ node.exposedGAs.splice(index, 1)
306
+ saveExposedGAs()
307
+ }
267
308
  }
268
309
 
269
310
  // 12/11/2021 Connect at start delay
@@ -520,7 +561,6 @@ module.exports = (RED) => {
520
561
  node.delaybetweentelegrams = (config.delaybetweentelegrams === undefined || config.delaybetweentelegrams === null || config.delaybetweentelegrams === '') ? 25 : Number(config.delaybetweentelegrams)
521
562
  if (node.delaybetweentelegrams < 25) node.delaybetweentelegrams = 25 // Protection avoiding handleKNXQueue hangs
522
563
  if (node.delaybetweentelegrams > 100) node.delaybetweentelegrams = 100 // Protection avoiding handleKNXQueue hangs
523
- node.timerSaveExposedGAs = null // Timer to save the exposed GA every once in a while
524
564
 
525
565
  // 05/12/2021 Set the protocol (this is undefined if coming from ild versions
526
566
  if (node.hostProtocol === 'Auto') {
@@ -781,50 +821,18 @@ module.exports = (RED) => {
781
821
  }
782
822
  })()
783
823
 
784
- // 04/04/2021 Supergiovane, creates the service paths where the persistent files are created.
785
- // The values file is stored only upon disconnection/close
824
+ // 04/04/2021 Supergiovane, persistent GA values. The file is written by the
825
+ // File Cache Control storage, according to the selected disk-wearing mode.
786
826
  // ************************
787
- function setupDirectory (_aPath) {
788
- if (!fs.existsSync(_aPath)) {
789
- // Create the path
790
- try {
791
- fs.mkdirSync(_aPath)
792
- return true
793
- } catch (error) {
794
- return false
795
- }
796
- } else {
797
- return true
798
- }
799
- }
800
- if (!setupDirectory(node.userDir)) {
801
- node.sysLogger?.error('Unable to set up MAIN directory: ' + node.userDir)
802
- }
803
- if (!setupDirectory(path.join(node.userDir, 'knxpersistvalues'))) {
804
- node.sysLogger?.error('Unable to set up cache directory: ' + path.join(node.userDir, 'knxpersistvalues'))
805
- } else {
806
- node.sysLogger?.info('payload cache set to ' + path.join(node.userDir, 'knxpersistvalues'))
807
- }
808
-
809
- async function saveExposedGAs () {
810
- const sFile = path.join(node.userDir, 'knxpersistvalues', 'knxpersist' + node.id + '.json')
811
- try {
812
- if (node.exposedGAs.length > 0) {
813
- fs.writeFileSync(sFile, JSON.stringify(node.exposedGAs))
814
- // node.sysLogger?.debug("wrote peristent values to the file " + sFile);
815
- }
816
- } catch (err) {
817
- node.sysLogger?.error('unable to write peristent values to the file ' + sFile + ' ' + err.message)
818
- }
819
- }
827
+ node.sysLogger?.info('payload cache set to ' + node.persistFile + ', file cache mode ' + node.fileStorage.mode)
820
828
  function loadExposedGAs () {
821
- const sFile = path.join(node.userDir, 'knxpersistvalues', 'knxpersist' + node.id + '.json')
822
829
  try {
823
- node.exposedGAs = JSON.parse(fs.readFileSync(sFile, 'utf8'))
830
+ // The storage returns the values not yet written to disk, too.
831
+ node.exposedGAs = JSON.parse(node.fileStorage.readFile(node.persistFile, 'utf8'))
824
832
  if (!Array.isArray(node.exposedGAs)) node.exposedGAs = []
825
833
  } catch (err) {
826
834
  node.exposedGAs = []
827
- node.sysLogger?.info('unable to read peristent file ' + sFile + ' ' + err.message)
835
+ node.sysLogger?.info('unable to read peristent file ' + node.persistFile + ' ' + err.message)
828
836
  }
829
837
  node.rebuildExposedGAIndex()
830
838
  }
@@ -900,12 +908,6 @@ module.exports = (RED) => {
900
908
  loadExposedGAs() // 04/04/2021 load the current values of GA payload
901
909
  node.sysLogger?.info('Loaded persist GA values', node.exposedGAs?.length)
902
910
 
903
- if (node.timerSaveExposedGAs !== null) clearInterval(node.timerSaveExposedGAs)
904
- node.timerSaveExposedGAs = setInterval(async () => {
905
- await saveExposedGAs()
906
- }, 5000)
907
- node.sysLogger?.info('Started timerSaveExposedGAs with array lenght ', node.exposedGAs?.length)
908
-
909
911
  try {
910
912
  const readHistory = []
911
913
 
@@ -1151,6 +1153,7 @@ module.exports = (RED) => {
1151
1153
  ipPort: node.port,
1152
1154
  physAddr: node.physAddr, // the KNX physical address we'd like to use
1153
1155
  suppress_ack_ldatareq: node.suppressACKRequest,
1156
+ waitForTunnelingAck: node.waitForTunnelingAck,
1154
1157
  loglevel: node.loglevel,
1155
1158
  hostProtocol: node.hostProtocol,
1156
1159
  isSecureKNXEnabled: node.knxSecureSelected,
@@ -1338,6 +1341,7 @@ module.exports = (RED) => {
1338
1341
  })
1339
1342
  node.knxConnection.on(knx.KNXClientEvents.connected, (info) => {
1340
1343
  node.linkStatus = 'connected'
1344
+ node.fileStorage.handleGatewayEvent()
1341
1345
 
1342
1346
  // Track serial driver for forced close on redeploy
1343
1347
  if (node.hostProtocol === 'SerialFT12' && node.knxConnection && node.knxConnection._serialDriver) {
@@ -1399,18 +1403,20 @@ module.exports = (RED) => {
1399
1403
  return
1400
1404
  }
1401
1405
 
1402
- let _evt = null
1403
- if (_datagram.cEMIMessage.npdu.isGroupRead) _evt = 'GroupValue_Read'
1404
- if (_datagram.cEMIMessage.npdu.isGroupResponse) _evt = 'GroupValue_Response'
1405
- if (_datagram.cEMIMessage.npdu.isGroupWrite) _evt = 'GroupValue_Write'
1406
-
1407
1406
  let _src = null
1408
1407
  _src = _datagram.cEMIMessage.srcAddress.toString()
1409
1408
 
1410
1409
  let _dest = null
1411
1410
  _dest = _datagram.cEMIMessage.dstAddress.toString()
1412
1411
 
1413
- if (_evt === null || _src === null || _dest === null) {
1412
+ // Point-to-point and transport control telegrams (e.g. an ETS device scan) are valid, but not for us
1413
+ const _evt = getGroupServiceEvent(_datagram.cEMIMessage)
1414
+ if (_evt === null) {
1415
+ node.sysLogger?.debug(`HandleBusEvent: ignored non group telegram src=${_src} dest=${_dest}`)
1416
+ return
1417
+ }
1418
+
1419
+ if (_src === null || _dest === null) {
1414
1420
  node.sysLogger?.warn(`HandleBusEvent: unable to parse telegram, ignored (evt=${_evt || 'n/a'} src=${_src || 'n/a'} dest=${_dest || 'n/a'})`)
1415
1421
  return
1416
1422
  };
@@ -2660,10 +2666,6 @@ module.exports = (RED) => {
2660
2666
  }, 10000)
2661
2667
 
2662
2668
  node.Disconnect = async (_sNodeStatus = '', _sColor = 'grey') => {
2663
- if (node.timerSaveExposedGAs !== null) {
2664
- clearInterval(node.timerSaveExposedGAs)
2665
- node.timerSaveExposedGAs = null
2666
- }
2667
2669
  if (node.timerDoInitialRead !== null) {
2668
2670
  clearTimeout(node.timerDoInitialRead) // 17/02/2020 Stop the initial read timer
2669
2671
  node.timerDoInitialRead = null
@@ -2724,7 +2726,7 @@ module.exports = (RED) => {
2724
2726
  }
2725
2727
 
2726
2728
  node.setAllClientsStatus('Disconnected', _sColor, _sNodeStatus)
2727
- await saveExposedGAs() // 04/04/2021 save the current values of GA payload
2729
+ node.fileStorage.handleGatewayEvent() // 04/04/2021 save the current values of GA payload
2728
2730
  node.sysLogger?.debug('Disconnected, node.autoReconnect:' + node.autoReconnect)
2729
2731
  }
2730
2732
 
@@ -2736,6 +2738,9 @@ module.exports = (RED) => {
2736
2738
  }
2737
2739
  await node.Disconnect()
2738
2740
  } catch (error) { /* empty */ }
2741
+ try {
2742
+ node.fileStorage.close()
2743
+ } catch (error) { /* empty */ }
2739
2744
  node.nodeClients = [] // 05/04/2022 Nullify
2740
2745
  try {
2741
2746
  node.sysLogger?.destroy()
@@ -2754,5 +2759,6 @@ module.exports = (RED) => {
2754
2759
  }
2755
2760
 
2756
2761
  module.exports.__test = {
2757
- resolveHostAddress
2762
+ resolveHostAddress,
2763
+ getGroupServiceEvent
2758
2764
  }
@@ -790,6 +790,9 @@ return msg;`
790
790
  node.initialread = 0;
791
791
  $("#node-input-initialread").val(0)
792
792
  }
793
+ // Reading the initial value from file is limited when the gateway does not write files.
794
+ const refreshFileCacheTip = KNX_bindFileCacheDisabledTip($("#knxUltimate-file-cache-tip"), $("#node-input-server"), () => ['2', '3'].includes(String($("#node-input-initialread").val())));
795
+ $("#node-input-initialread").on('change', refreshFileCacheTip);
793
796
 
794
797
  oNodeServer = RED.nodes.node($("#node-input-server").val());
795
798
  if (oNodeServer === undefined) {
@@ -1352,6 +1355,7 @@ return msg;`
1352
1355
  <option value=2 data-i18n="knxUltimate.properties.node-input-initialread2"></option>
1353
1356
  <option value=3 data-i18n="knxUltimate.properties.node-input-initialread3"></option>
1354
1357
  </select>
1358
+ <div class="form-tips" id="knxUltimate-file-cache-tip" style="display:none; margin-top:6px;"></div>
1355
1359
 
1356
1360
  </div>
1357
1361
  <div class="form-row" id="divInputRBE">
@@ -12,6 +12,8 @@
12
12
  const text = (key) => RED._('node-red-contrib-knx-ultimate/knxUltimateUtility:knxUltimateUtility.' + key);
13
13
  const activeType = (node) => node._utilityEditor ? node._utilityEditor.type() : node.utilityType;
14
14
  const validationContext = (node) => typeof node._utilityEditor?.values === 'function' ? node._utilityEditor.values() : node;
15
+ // Functions that save files through the gateway's File Cache Control.
16
+ const usesFiles = (type) => type === 'autoresponder' || type === 'scenecontroller' || (type === 'logger' && $('#node-input-saveMode').val() === 'emit_save');
15
17
 
16
18
  function buildDefaults() {
17
19
  // Node-RED must know every persistable field and the real config-node
@@ -136,6 +138,7 @@
136
138
  let closed = false;
137
139
  let helpTimer;
138
140
  const container = $('#knx-utility-profile-editor');
141
+ const refreshFileCacheTip = KNX_bindFileCacheDisabledTip($('#knx-utility-file-cache-tip'), $('#node-input-server'), () => usesFiles(selectedType));
139
142
 
140
143
  // Edit a separate context: profile hooks (including asynchronous ETS
141
144
  // suggestions) must never mutate the saved node before Done is pressed.
@@ -201,6 +204,8 @@
201
204
  $('#knx-utility-pin-description').text(text('pins.' + type));
202
205
  $('#node-input-name').attr('placeholder', isGlobalContext ? mounted.defaults.name.value : 'KNX Utility · ' + text('types.' + type));
203
206
  if (typeof mounted.oneditprepare === 'function') mounted.oneditprepare.call(context);
207
+ $('#node-input-saveMode').on('change.knxFileCacheTip', refreshFileCacheTip);
208
+ refreshFileCacheTip();
204
209
  // These controls are mounted after Node-RED attaches its initial
205
210
  // validation handlers. Trigger a shared field's standard handler so
206
211
  // the complete editor validates again while the user edits a profile.
@@ -250,6 +255,7 @@
250
255
  closed = true;
251
256
  dispose();
252
257
  $('#node-input-utilityType').off('.knxUtility');
258
+ $('#node-input-server').off('.knxFileCacheTip');
253
259
  }
254
260
  };
255
261
  const initialType = node.utilityType || 'alerter';
@@ -311,6 +317,7 @@
311
317
  <label for="node-input-server"><i class="fa fa-circle-o"></i> <span data-i18n="knxUltimateUtility.gateway"></span></label>
312
318
  <input type="text" id="node-input-server">
313
319
  </div>
320
+ <div class="form-tips" id="knx-utility-file-cache-tip" style="display:none"></div>
314
321
  <div class="form-row">
315
322
  <label for="node-input-name"><i class="fa fa-tag"></i> <span id="knx-utility-name-label" data-i18n="knxUltimateUtility.name"></span></label>
316
323
  <input type="text" id="node-input-name">
@@ -77,6 +77,8 @@
77
77
  const base = raw.split("-")[0];
78
78
  return ["en", "it", "de", "fr", "es"].includes(base) ? base : "en";
79
79
  };
80
+ // The history is kept only in memory when the gateway does not write files.
81
+ KNX_bindFileCacheDisabledTip($("#knx-viewer-file-cache-tip"), $("#node-input-server"));
80
82
  $("#knx-viewer-open-web-page").on("click", function (evt) {
81
83
  evt.preventDefault();
82
84
  const adminRoot = resolveAdminRoot();
@@ -128,6 +130,7 @@
128
130
  </label>
129
131
  <input type="text" id="node-input-server" />
130
132
  </div>
133
+ <div class="form-tips" id="knx-viewer-file-cache-tip" style="display:none;"></div>
131
134
 
132
135
  <div class="form-row">
133
136
  <label for="node-input-name">
@@ -4,6 +4,7 @@ const KNXAddress = require('knxultimate').KNXAddress
4
4
  const _ = require('lodash')
5
5
  const { getRequestAccessToken, normalizeAuthFromAccessTokenQuery } = require('./utils/httpAdminAccessToken')
6
6
  const createViewerHistory = require('./utils/knxViewerHistory')
7
+ const { storageOf } = require('./utils/fileStorage')
7
8
 
8
9
  const viewerRuntimeContexts = new WeakMap()
9
10
  const knxUltimateViewerVueDistDir = path.join(__dirname, 'plugins', 'knxUltimateViewer-vue')
@@ -314,7 +315,8 @@ module.exports = function (RED) {
314
315
  userDir: RED.settings.userDir,
315
316
  nodeId: node.id,
316
317
  gatewayId: node.serverKNX.id,
317
- onError: reportHistoryError
318
+ onError: reportHistoryError,
319
+ storage: storageOf(node.serverKNX)
318
320
  })
319
321
  node.viewerHistory.ready.catch(reportHistoryError)
320
322
  } catch (error) {
@@ -39,10 +39,10 @@ Dieser Node stellt die Verbindung zu deinem KNX/IP-Gateway her.
39
39
  |Eigenschaft|Beschreibung|
40
40
  |--|--|
41
41
  | Suppress repeated (R-Flag) telegrams fom BUS | Wiederholte BUS-Telegramme (R-Flag) ignorieren. |
42
- | Suppress ACK request in tunneling mode | Für sehr alte KNX/IP-Gateways: ACK ignorieren, alle Telegramme akzeptieren. |
42
+ | Bus-ACK-Anforderung unterdrücken | Bus-ACK. Wenn aktiviert, fordern die an den KNX-Bus gesendeten Telegramme (Tunnel UDP, Multicast und Serial FT1.2) keine Bestätigung der empfangenden Geräte mehr an. Bei Tunnel UDP und "Auf Tunnelling-ACK warten" auf Automatisch wartet der Knoten außerdem nicht mehr auf die Bestätigung der Schnittstelle. Nur aktivieren, wenn Ihre Schnittstelle es erfordert, z. B. einige alte oder Weinzierl-KNX/IP-Schnittstellen, eibPORT und Loxone. Standard: deaktiviert. |
43
+ | Auf Tunnelling-ACK warten (Tunnel UDP) | Schnittstellen-ACK. Bei Tunnel UDP wartet der Knoten, bis die KNX/IP-Schnittstelle jedes Telegramm bestätigt: Ein unbestätigtes Telegramm wird noch einmal gesendet, dann wird die Verbindung geschlossen und neu aufgebaut. Automatisch wartet nur, wenn "Bus-ACK-Anforderung unterdrücken" deaktiviert ist, wie in früheren Versionen. Ja wartet immer, Nein nie. eibPORT- und Loxone-Gateways benötigen "Bus-ACK-Anforderung unterdrücken" zusammen mit Ja. |
43
44
  | Flow-Bubbles-Plugin aktivieren | Zeigt im Editor neben jedem KNX Device Node eine kleine farbige Bubble an. Die Bubble spiegelt den zuletzt vom Gateway empfangenen Live-Status wider und wird abgeblendet, wenn die Daten veraltet sind. Nützlich bei Inbetriebnahme und Debugging. Standard: deaktiviert. |
44
45
  | Delay between each telegram (ms) | KNX erlaubt max. 50 Telegramme/s. 25-50 ms sind üblich; bei langsamen Verbindungen höher (z. B. 200-500 ms). |
45
- | Loglevel | Log-Detailgrad. Standard: "Error". |
46
46
  | Aktualisierung der Status-Badges | Legt fest, wie oft die Statusanzeige der Nodes erneuert wird. Mit einer Verzögerung werden Zwischenstände verworfen und nur der letzte Wert nach dem gewählten Intervall angezeigt. Wählen Sie **Sofort**, um das bisherige Echtzeitverhalten beizubehalten. |
47
47
  | Status Datum/Uhrzeit-Format | Legt fest, wie Datum/Uhrzeit im Status-Badge angezeigt werden (nützlich, wenn das OS-Locale nicht konfigurierbar ist). |
48
48
  | Benutzerdefiniertes Format | Wird verwendet, wenn **Benutzerdefiniert (Tokens)** gewählt ist. Tokens: `YYYY`, `YY`, `MMM`, `MM`, `DD`, `HH`, `mm`, `ss`, `A`, `a`, `Z`. Verwenden Sie `[Text]` für Literale. |
@@ -59,12 +59,15 @@ Dieser Node stellt die Verbindung zu deinem KNX/IP-Gateway her.
59
59
 
60
60
  <br/>
61
61
 
62
- **Werkzeuge**
62
+ **Datei-Cache-Steuerung**
63
63
 
64
64
  |Eigenschaft|Beschreibung|
65
65
  |--|--|
66
- | Gather debug info for troubleshoot | Button klicken und Ausgabe an ein GitHub-Issue anhängen. |
67
- | Get all used GA for KNX routing filter | Mit READ eine Textliste aller in Flows verwendeten GAs für dieses Gateway holen - zum Befüllen der Filtertabelle deines KNX/IP-Routers. |
66
+ | Loglevel | Log-Detailgrad. Standard: "Error". Das Log ist von der Schreibverschleiß-Verwaltung nicht betroffen. |
67
+ | Schreibverschleiß-Verwaltung | Legt fest, wie oft KNX Ultimate seine Dateien auf den Datenträger schreibt: GA-Werte, Szenen des Scene Controllers, AutoResponder-Werte, Logger-Datei und Viewer-Verlauf. Nützlich, um den Verschleiß von SD-Karten zu verringern. Dateien werden nur geschrieben, wenn sich ihr Inhalt geändert hat. **Aktualität zuerst** (Standard) speichert Änderungen alle 5 Sekunden. **Ausgewogen** speichert sie nur beim Verbinden oder Trennen des Gateways sowie wenn Node-RED stoppt oder das Gateway neu bereitgestellt wird. **Schreiben deaktivieren** schreibt nie auf den Datenträger: Die Daten bleiben nur im Speicher, und bei jedem Neustart von Node-RED gehen alle aktuellen GA-Werte und die von den KNX-Ultimate-Knoten gespeicherten Daten verloren. **Benutzerdefiniertes Intervall** speichert Änderungen im gewählten Intervall (5 Sekunden bis 30 Tage) sowie wenn Node-RED stoppt oder das Gateway neu bereitgestellt wird. |
68
+ | Schreibintervall | Sichtbar bei **Benutzerdefiniertes Intervall**. Wert und Einheit (Sekunden, Minuten, Stunden, Tage) des Schreibintervalls. |
69
+
70
+ > Ist das Schreiben deaktiviert, zeigen die KNX-Ultimate-Knoten, die Dateien verwenden (Device mit initialem Lesen aus Datei, Scene Controller, AutoResponder, Logger mit Speicherung in Datei, Viewer), einen Hinweis in ihrem Editor.
68
71
 
69
72
  <br/>
70
73
 
@@ -19,7 +19,7 @@
19
19
  "discovering": "Suche...",
20
20
  "interfaces_found": "Schnittstellen gefunden.",
21
21
  "discovery_failed": "Suche fehlgeschlagen.",
22
- "weinzierl_ack_autoenabled": "Weinzierl-Interface erkannt: 'Suppress ACK request' wurde automatisch aktiviert. Du kannst es im Tab 'Erweitert' deaktivieren.",
22
+ "weinzierl_ack_autoenabled": "Weinzierl-Interface erkannt: 'Bus-ACK-Anforderung unterdrücken' wurde automatisch aktiviert. Du kannst es im Tab 'Erweitert' deaktivieren.",
23
23
  "address": "Adresse",
24
24
  "iface_auto": "Auto",
25
25
  "iface_manual": "Schnittstellennamen manuell eingeben",
@@ -63,15 +63,20 @@
63
63
  "configuration": "Konfiguration",
64
64
  "advanced": "Erweitert",
65
65
  "ets_import": "ETS-Import",
66
- "utility": "Dienstprogramme"
66
+ "file_cache": "Datei-Cache-Steuerung"
67
67
  },
68
68
  "advanced": {
69
69
  "knx_phy_addr": "KNX-Adresse",
70
70
  "show_date_status": "Tag und Uhrzeit des letzten Updates im Status anzeigen",
71
71
  "show_device_status": "Gerätenamen im Status anzeigen (\"Alle Gruppenadressen abhören\" erforderlich)",
72
72
  "show_datapoint_status": "Datenpunkt im Status anzeigen",
73
- "suppress_ack": "ACK-Anfrage unterdrücken in Tunnel Modus",
74
- "suppress_ack_help": "Diese Option unterstützt die Kompatibilität mit der alten Firmware des alten IP-Interfaces.Achtung: Der Knoten kann die Trennung vom Gateway möglicherweise nicht bemerken. Verwenden Sie in diesem Fall den Watchdog im Ethernet+KNX-Twisted-Pair Modus.",
73
+ "suppress_ack": "Bus-ACK-Anforderung unterdrücken",
74
+ "suppress_ack_help": "Bus-ACK. Wenn aktiviert, fordern die an den KNX-Bus gesendeten Telegramme (Tunnel UDP, Multicast und Serial FT1.2) keine Bestätigung der empfangenden Geräte mehr an. Bei Tunnel UDP und \"Auf Tunnelling-ACK warten\" auf Automatisch wartet der Knoten außerdem nicht mehr auf die Bestätigung der Schnittstelle. Nur aktivieren, wenn Ihre Schnittstelle es erfordert, z. B. einige alte oder Weinzierl-KNX/IP-Schnittstellen, eibPORT und Loxone. Standard: deaktiviert.",
75
+ "wait_tunneling_ack": "Auf Tunnelling-ACK warten (Tunnel UDP)",
76
+ "wait_tunneling_ack_auto": "Automatisch (nur wenn die Bus-ACK-Anforderung nicht unterdrückt ist)",
77
+ "wait_tunneling_ack_yes": "Ja (einmal wiederholen, dann trennen)",
78
+ "wait_tunneling_ack_no": "Nein",
79
+ "wait_tunneling_ack_help": "Schnittstellen-ACK. Bei Tunnel UDP wartet der Knoten, bis die KNX/IP-Schnittstelle jedes Telegramm bestätigt: Ein unbestätigtes Telegramm wird noch einmal gesendet, dann wird die Verbindung geschlossen und neu aufgebaut. Automatisch wartet nur, wenn \"Bus-ACK-Anforderung unterdrücken\" deaktiviert ist, wie in früheren Versionen. Ja wartet immer, Nein nie. eibPORT- und Loxone-Gateways benötigen \"Bus-ACK-Anforderung unterdrücken\" zusammen mit Ja.",
75
80
  "ignoreTelegramsWithRepeatedFlag": "Wiederholt (R-Flag) telegramme vom BUS unterdrücken",
76
81
  "enable_flow_bubbles": "Flow-Bubbles-Plugin aktivieren",
77
82
  "enable_flow_bubbles_help": "Zeigt Live-Status-Bubbles neben KNX Device Nodes im Editor an. Nützlich bei Inbetriebnahme und Debugging.",
@@ -133,22 +138,19 @@
133
138
  "tunnel_user_password": "Tunnel-Benutzerpasswort",
134
139
  "ga_list_label": "ETS-Gruppenadressliste"
135
140
  },
136
- "utility": {
137
- "gather_debug": "Debug und Log zur Fehlersuche sammeln",
138
- "get_all_used_ga": "Alle verwendeten GA für KNX-Routing-Filter abrufen",
139
- "read_button": "Lesen",
140
- "copy_ga_router": "Kopieren Sie diese Gruppenadressen in die Routing-Tabelle Ihres KNX/IP-Routers.",
141
- "clear_persist_label": "Persistenten GA-Cache für dieses Gateway löschen",
142
- "clear_persist_button": "Löschen",
143
- "clear_persist_confirm": "Dadurch wird die persistente GA-Cache-Datei für dieses Gateway gelöscht. Fortfahren?",
144
- "clear_persist_ok": "Löschen",
145
- "clear_persist_cancel": "Abbrechen",
146
- "clear_persist_done": "Persistenter GA-Cache gelöscht.",
147
- "clear_persist_fail": "Persistenter GA-Cache konnte nicht gelöscht werden",
148
- "reveal_keyring_label": "Keyring-Passwörter im Klartext anzeigen (KNX Secure)",
149
- "reveal_keyring_button": "Anzeigen",
150
- "reveal_keyring_loading": "Keyring wird dekodiert, bitte warten...",
151
- "reveal_keyring_fail": "Keyring konnte nicht dekodiert werden. Prüfen Sie die Keyring-Datei und das allgemeine Passwort."
141
+ "file_cache": {
142
+ "mode": "Schreibverschleiß-Verwaltung",
143
+ "mode_freshness": "Aktualität zuerst",
144
+ "mode_balanced": "Ausgewogen",
145
+ "mode_disabled": "Schreiben deaktivieren",
146
+ "mode_custom": "Benutzerdefiniertes Intervall",
147
+ "interval": "Schreibintervall",
148
+ "unit_seconds": "Sekunden",
149
+ "unit_minutes": "Minuten",
150
+ "unit_hours": "Stunden",
151
+ "unit_days": "Tage",
152
+ "disabled_tip": "Das Schreiben auf den Datenträger ist deaktiviert (Datei-Cache-Steuerung des KNX-Gateways): Bei jedem Neustart von Node-RED gehen alle aktuellen GA-Werte und die von den KNX-Ultimate-Knoten gespeicherten Daten verloren.",
153
+ "description": "Legt fest, wie oft KNX Ultimate seine Dateien auf den Datenträger schreibt (GA-Werte, Szenen des Scene Controllers, AutoResponder-Werte, Logger-Datei, Viewer-Verlauf), um den Verschleiß von SD-Karten zu verringern. Dateien werden nur geschrieben, wenn sich ihr Inhalt geändert hat. Das Log ist nicht betroffen: Verwenden Sie dafür die Protokollstufe.<br/><b>Aktualität zuerst</b>: Änderungen werden alle 5 Sekunden gespeichert.<br/><b>Ausgewogen</b>: Änderungen werden nur beim Verbinden oder Trennen des Gateways gespeichert sowie wenn Node-RED stoppt oder das Gateway neu bereitgestellt wird.<br/><b>Schreiben deaktivieren</b>: Es wird nichts auf den Datenträger geschrieben.<br/><b>Benutzerdefiniertes Intervall</b>: Änderungen werden im gewählten Intervall (5 Sekunden bis 30 Tage) gespeichert sowie wenn Node-RED stoppt oder das Gateway neu bereitgestellt wird."
152
154
  }
153
155
  }
154
156
  }
@@ -54,6 +54,8 @@ Der Button wird nur eingeblendet, wenn die Option aktiv ist. Im Universalmodus i
54
54
  | Auf Lese-Telegramme reagieren | Sendet bei Read eine Nachricht an den Flow (z. B. um eigene Werte zu liefern). |
55
55
  | Multiply/Decimals/Negatives | Skaliert, rundet und behandelt negative Werte (nur numerische Werte). |
56
56
 
57
+ > 💾 Wann die von **Bei Verbindung/Wiederverbindung der Wert lesen** (aus Datei) genutzten GA-Werte auf den Datenträger geschrieben werden, bestimmt die **Datei-Cache-Steuerung** des KNX-Gateways. Mit **Schreiben deaktivieren** bleiben sie nur im Speicher und gehen bei jedem Neustart von Node-RED verloren. Siehe den Tab **Datei-Cache-Steuerung** des KNX-Gateways.
58
+
57
59
  <br/>
58
60
  <br/>
59
61
 
@@ -163,6 +163,8 @@ msg = {
163
163
 
164
164
  ## AutoResponder
165
165
 
166
+ > 💾 Wann die gespeicherten Werte auf den Datenträger geschrieben werden, bestimmt die **Datei-Cache-Steuerung** des KNX-Gateways. Mit **Schreiben deaktivieren** bleiben sie nur im Speicher und gehen bei jedem Neustart von Node-RED verloren. Siehe den Tab **Datei-Cache-Steuerung** des KNX-Gateways.
167
+
166
168
  Dieser Knoten antwortet auf Leseanfragen aus dem KNX -Bus.
167
169
 
168
170
  Der Knoten zeichnet alle an den KNX -Bus übertragenen Telegramme auf und speichert die Werte im Speicher.
@@ -502,6 +504,8 @@ global.set("KNXContextBanana_WRITE", toSend);
502
504
 
503
505
  ## Logger
504
506
 
507
+ > 💾 Wann die Daten der XML-Datei von **Payload senden und in Datei speichern** auf den Datenträger geschrieben werden, bestimmt die **Datei-Cache-Steuerung** des KNX-Gateways. Mit **Schreiben deaktivieren** bleiben sie nur im Speicher und gehen bei jedem Neustart von Node-RED verloren. Siehe den Tab **Datei-Cache-Steuerung** des KNX-Gateways.
508
+
505
509
  ### Logger
506
510
 
507
511
  Der Logger-Node zeichnet alle Telegramme auf und erzeugt eine ETS-Busmonitor-kompatible XML-Datei.
@@ -761,6 +765,8 @@ return msg;
761
765
 
762
766
  ## Szenensteuerung
763
767
 
768
+ > 💾 Wann die gespeicherten Szenen auf den Datenträger geschrieben werden, bestimmt die **Datei-Cache-Steuerung** des KNX-Gateways. Mit **Schreiben deaktivieren** bleiben sie nur im Speicher und gehen bei jedem Neustart von Node-RED verloren. Siehe den Tab **Datei-Cache-Steuerung** des KNX-Gateways.
769
+
764
770
  ### Scene Controller
765
771
 
766
772
  Der Scene-Controller-Node verhält sich wie ein KNX-Szenencontroller: Szenen speichern und abrufen.
@@ -19,6 +19,8 @@ Wählen Sie einen Viewer, durchsuchen Sie die Liste oder blättern Sie zu älter
19
19
 
20
20
  Der aktive Viewer-Knoten speichert den Verlauf automatisch in Dateien unter `userDir/knxultimatestorage/viewer`, getrennt nach Viewer und Gateway. Änderungen, die älter als 24 Stunden sind, werden automatisch entfernt. Nach einem Neustart von Node-RED lädt der Viewer den noch in diesem Zeitraum liegenden Verlauf.
21
21
 
22
+ > 💾 Wann die Verlaufsdateien auf den Datenträger geschrieben werden, bestimmt die **Datei-Cache-Steuerung** des KNX-Gateways. Mit **Schreiben deaktivieren** bleiben sie nur im Speicher und gehen bei jedem Neustart von Node-RED verloren. Siehe den Tab **Datei-Cache-Steuerung** des KNX-Gateways.
23
+
22
24
  Die Aufzeichnung beginnt, sobald der aktualisierte Viewer bereitgestellt ist und läuft. Frühere Bustelegramme werden nicht nachträglich rekonstruiert.
23
25
 
24
26
  ## Flow-Ausgänge
@@ -39,10 +39,10 @@
39
39
  |Property|Description|
40
40
  |--|--|
41
41
  | Suppress repeated (R-Flag) telegrams fom BUS | Ignore repeated KNX telegrams coming from the bus. Default is unchecked. |
42
- | Suppress ACK request in tunneling mode | Enable it if you have a very old KNX/IP gateway. It ignores the ACK procedure and accepts all telegrams. Default is unchecked.|
42
+ | Suppress the bus ACK request | Bus ACK. When checked, the telegrams sent to the KNX bus (Tunnel UDP, Multicast and Serial FT1.2) no longer ask the receiving devices for an acknowledgement. With Tunnel UDP and "Wait for the tunnelling ACK" set to Auto, the node also stops waiting for the interface's confirmation. Enable it only if your interface needs it, for example some old or Weinzierl KNX/IP interfaces, eibPORT and Loxone. Default is unchecked. |
43
+ | Wait for the tunnelling ACK (Tunnel UDP) | Interface ACK. With Tunnel UDP, the node waits for the KNX/IP interface to confirm every telegram: a telegram that is not confirmed is sent once more, then the connection is closed and opened again. Auto waits only when "Suppress the bus ACK request" is unchecked, as in previous versions. Yes always waits, No never waits. eibPORT and Loxone gateways need "Suppress the bus ACK request" checked together with Yes. |
43
44
  | Enable flow bubbles plugin | Draw a small coloured bubble next to each KNX Device node in the editor. The bubble reflects the latest live state received from the gateway and becomes dim when the data is stale. Useful during commissioning and debugging. Default is unchecked. |
44
45
  | Delay between each telegram (in milliseconds) | KNX specs states, that the maximum telegram sending speed is 50 telegrams per second. A speed between 25 and 50ms should be fine, unless you're connecting to a remote KNX Gateway via a slow internet connection (in this case, you should increase the value by, for example, 200 to 500ms or more). |
45
- | Loglevel | Log level, in case you need to debug something with the dev. Default is "Error", |
46
46
  | Node status throttle | Delay how often node badges are refreshed. When a delay is selected, intermediate status changes are discarded and the last one is shown after the chosen interval. Select **Immediate** to keep the legacy real-time behaviour. |
47
47
  | Status date/time format | Choose how the timestamp is shown in node status badges (useful when the host OS locale cannot be configured). |
48
48
  | Custom format | Used when **Custom (tokens)** is selected. Tokens: `YYYY`, `YY`, `MMM`, `MM`, `DD`, `HH`, `mm`, `ss`, `A`, `a`, `Z`. Use `[text]` for literals. |
@@ -59,12 +59,15 @@
59
59
 
60
60
  <br/>
61
61
 
62
- **Utility**
62
+ **File Cache Control**
63
63
 
64
64
  |Property|Description|
65
65
  |--|--|
66
- | Gather debug info for troubleshoot | Please click the button and add it to the gitHub issue you want to open, it will help me a lot to helping you. |
67
- | Get all used GA for KNX routing filter | Press READ to retrieve a plain text list of all group address belonging to this gateway, that has been used in the flows. You can use this list to populate your KNX/IP router filter table. |
66
+ | Loglevel | Log level, in case you need to debug something with the dev. Default is "Error". The log is not affected by the disk-wear management. |
67
+ | Disk-wear management | Sets how often KNX Ultimate writes its files to disk: GA values, Scene Controller scenes, AutoResponder values, Logger file and Viewer history. Useful to reduce the wear of SD cards. Files are written only when their content has changed. **Freshness priority** (default) saves the changes every 5 seconds. **Balanced** saves them only when the gateway connects or disconnects, and when Node-RED stops or the gateway is redeployed. **Disable writing** never writes to disk: the data is kept in memory only and, at every restart of Node-RED, all the current GA values and the data saved by the KNX Ultimate nodes are lost. **Custom interval** saves the changes at the chosen interval, from 5 seconds to 30 days, and when Node-RED stops or the gateway is redeployed. |
68
+ | Write interval | Visible with **Custom interval**. Number and unit (seconds, minutes, hours, days) of the write interval. |
69
+
70
+ > When writing is disabled, the KNX Ultimate nodes that use files (Device with initial read from file, Scene Controller, AutoResponder, Logger saving to file, Viewer) show a reminder in their editor.
68
71
 
69
72
  <br/>
70
73
 
@@ -19,7 +19,7 @@
19
19
  "discovering": "Discovering...",
20
20
  "interfaces_found": "interfaces found.",
21
21
  "discovery_failed": "Discovery failed.",
22
- "weinzierl_ack_autoenabled": "Weinzierl interface detected: 'Suppress ACK request' has been enabled automatically. You can disable it in the Advanced tab.",
22
+ "weinzierl_ack_autoenabled": "Weinzierl interface detected: 'Suppress the bus ACK request' has been enabled automatically. You can disable it in the Advanced tab.",
23
23
  "address": "Address",
24
24
  "iface_auto": "Auto",
25
25
  "iface_manual": "Manually enter interface's name",
@@ -64,15 +64,20 @@
64
64
  "configuration": "Configuration",
65
65
  "advanced": "Advanced",
66
66
  "ets_import": "ETS file import",
67
- "utility": "Utility"
67
+ "file_cache": "File Cache Control"
68
68
  },
69
69
  "advanced": {
70
70
  "knx_phy_addr": "KNX Physical Address",
71
71
  "show_date_status": "Show last update day and time in status",
72
72
  "show_device_status": "Show device name in status (require \"Listen all Group Address\" )",
73
73
  "show_datapoint_status": "Show datapoint in status",
74
- "suppress_ack": "Suppress ACK request in tunneling mode",
75
- "suppress_ack_help": "The option above helps old KNX/IP Interfaces compatibility. Warning: the node may not notice the disconnection from the gateway. In this case, use the watchdog in Ethernet+KNX twisted pair mode.",
74
+ "suppress_ack": "Suppress the bus ACK request",
75
+ "suppress_ack_help": "Bus ACK. When checked, the telegrams sent to the KNX bus (Tunnel UDP, Multicast and Serial FT1.2) no longer ask the receiving devices for an acknowledgement. With Tunnel UDP and \"Wait for the tunnelling ACK\" set to Auto, the node also stops waiting for the interface's confirmation. Enable it only if your interface needs it, for example some old or Weinzierl KNX/IP interfaces, eibPORT and Loxone. Default is unchecked.",
76
+ "wait_tunneling_ack": "Wait for the tunnelling ACK (Tunnel UDP)",
77
+ "wait_tunneling_ack_auto": "Auto (only if the bus ACK request is not suppressed)",
78
+ "wait_tunneling_ack_yes": "Yes (repeat once, then disconnect)",
79
+ "wait_tunneling_ack_no": "No",
80
+ "wait_tunneling_ack_help": "Interface ACK. With Tunnel UDP, the node waits for the KNX/IP interface to confirm every telegram: a telegram that is not confirmed is sent once more, then the connection is closed and opened again. Auto waits only when \"Suppress the bus ACK request\" is unchecked, as in previous versions. Yes always waits, No never waits. eibPORT and Loxone gateways need \"Suppress the bus ACK request\" checked together with Yes.",
76
81
  "ignoreTelegramsWithRepeatedFlag": "Suppress repeated (R-Flag) telegrams fom BUS",
77
82
  "enable_flow_bubbles": "Enable flow bubbles plugin",
78
83
  "enable_flow_bubbles_help": "Draw live status bubbles next to KNX Device nodes in the editor. Useful during commissioning and debugging.",
@@ -137,22 +142,19 @@
137
142
  "tunnel_user_password": "Tunnel user password",
138
143
  "ga_list_label": "ETS group address list"
139
144
  },
140
- "utility": {
141
- "gather_debug": "Gather debug and log for troubleshoot",
142
- "get_all_used_ga": "Get all used GA for KNX routing filter",
143
- "read_button": "Read",
144
- "copy_ga_router": "Copy these group addresses in your routing table list of your KNX/IP router.",
145
- "clear_persist_label": "Clear persisted GA cache for this gateway",
146
- "clear_persist_button": "Clear",
147
- "clear_persist_confirm": "This deletes the persisted GA cache file for this gateway. Continue?",
148
- "clear_persist_ok": "Delete",
149
- "clear_persist_cancel": "Cancel",
150
- "clear_persist_done": "Persisted GA cache deleted.",
151
- "clear_persist_fail": "Unable to delete persisted GA cache",
152
- "reveal_keyring_label": "Reveal keyring passwords in clear text (KNX Secure)",
153
- "reveal_keyring_button": "Reveal",
154
- "reveal_keyring_loading": "Decoding keyring, please wait...",
155
- "reveal_keyring_fail": "Unable to decode the keyring. Check the keyring file and the general password."
145
+ "file_cache": {
146
+ "mode": "Disk-wear management",
147
+ "mode_freshness": "Freshness priority",
148
+ "mode_balanced": "Balanced",
149
+ "mode_disabled": "Disable writing",
150
+ "mode_custom": "Custom interval",
151
+ "interval": "Write interval",
152
+ "unit_seconds": "seconds",
153
+ "unit_minutes": "minutes",
154
+ "unit_hours": "hours",
155
+ "unit_days": "days",
156
+ "disabled_tip": "Writing to disk is disabled (File Cache Control of the KNX gateway): at every restart of Node-RED, all the current GA values and the data saved by the KNX Ultimate nodes will be lost.",
157
+ "description": "Sets how often KNX Ultimate writes its files to disk (GA values, Scene Controller scenes, AutoResponder values, Logger file, Viewer history), to reduce the wear of SD cards. Files are written only when their content has changed. The log is not affected: use the log level for it.<br/><b>Freshness priority</b>: changes are saved every 5 seconds.<br/><b>Balanced</b>: changes are saved only when the gateway connects or disconnects, and when Node-RED stops or the gateway is redeployed.<br/><b>Disable writing</b>: nothing is written to disk.<br/><b>Custom interval</b>: changes are saved at the chosen interval (5 seconds to 30 days), and when Node-RED stops or the gateway is redeployed."
156
158
  }
157
159
  }
158
160
  }