iobroker.smartloadmanager 0.0.8 → 0.1.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.
package/README.md CHANGED
@@ -30,6 +30,10 @@ The **smartloadmanager** adapter is used for dynamic control of loads based on a
30
30
  Placeholder for the next version (at the beginning of the line):
31
31
  ### **WORK IN PROGRESS**
32
32
  -->
33
+ ### 0.1.0 (2025-11-07)
34
+
35
+ - (quorle) Added a checkbox for activating consumers from the settings to the object tree
36
+
33
37
  ### 0.0.8 (2025-10-03)
34
38
 
35
39
  - (quorle) Fix for binary consumers that do not turn off
@@ -57,11 +61,6 @@ The **smartloadmanager** adapter is used for dynamic control of loads based on a
57
61
  - (quorle) Adjustments package.json
58
62
  - (quorle) Code changed
59
63
 
60
- ### 0.0.2 (2025-09-03)
61
-
62
- - (quorle) Adjustments package.json
63
- - (quorle) Code changed
64
-
65
64
  ## License
66
65
 
67
66
  MIT License
@@ -113,23 +113,6 @@
113
113
  "zh-cn": "名称"
114
114
  }
115
115
  },
116
- {
117
- "type": "checkbox",
118
- "attr": "enabled",
119
- "title": {
120
- "en": "Active",
121
- "de": "Aktiv",
122
- "ru": "Активный",
123
- "pt": "Activo",
124
- "nl": "Actief",
125
- "fr": "Activité",
126
- "it": "Attivo",
127
- "es": "Activo",
128
- "pl": "Aktywne",
129
- "uk": "Активний",
130
- "zh-cn": "活动"
131
- }
132
- },
133
116
  {
134
117
  "type": "objectId",
135
118
  "attr": "datapoint",
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "smartloadmanager",
4
- "version": "0.0.8",
4
+ "version": "0.1.0",
5
5
  "news": {
6
+ "0.1.0": {
7
+ "en": "Added a checkbox for activating consumers from the settings to the object tree",
8
+ "de": "Hinzufügen eines Kontrollkästchens zur Aktivierung von Verbrauchern von den Einstellungen zum Objektbaum",
9
+ "ru": "Добавлен чекбокс для активации потребителей от настроек до дерева объектов",
10
+ "pt": "Adicionada uma caixa de seleção para ativar os consumidores das configurações para a árvore de objetos",
11
+ "nl": "Een selectievakje toegevoegd voor het activeren van consumenten van de instellingen naar de objectboom",
12
+ "fr": "Ajout d'une case à cocher pour activer les consommateurs depuis les paramètres vers l'arborescence des objets",
13
+ "it": "Aggiunto una casella di controllo per attivare i consumatori dalle impostazioni all'albero dell'oggetto",
14
+ "es": "Se agregó una casilla de verificación para activar a los consumidores desde la configuración hasta el árbol objeto",
15
+ "pl": "Dodano opcję aktywacji konsumentów od ustawień do drzewa obiektów",
16
+ "uk": "Додано прапорець для активації споживачів з налаштувань до дерева об'єкта",
17
+ "zh-cn": "从设置中添加一个激活消费者的复选框到对象树"
18
+ },
6
19
  "0.0.8": {
7
20
  "en": "Fix for binary consumers that do not turn off\nFix for heating elements that are not switched off at max temperature",
8
21
  "de": "Fix für binäre Verbraucher, die nicht ausschalten\nBefestigung für Heizelemente, die bei max Temperatur nicht abgeschaltet werden",
package/main.js CHANGED
@@ -66,14 +66,23 @@ class ZeroFeedIn extends utils.Adapter {
66
66
  this.consumerList = Array.isArray(this.config.consumer)
67
67
  ? this.config.consumer.filter(
68
68
  v =>
69
- v &&
70
- v.enabled &&
71
- (v.ruletype === 'battery' || ((v.datapoint || v.numericDatapoint) && v.performance > 0)),
69
+ v && (v.ruletype === 'battery' || ((v.datapoint || v.numericDatapoint) && v.performance > 0)),
72
70
  )
73
71
  : [];
74
72
 
75
73
  this.consumerList.forEach(v => (v.processingLockSwitch = false));
76
74
 
75
+ for (let i = 0; i < this.consumerList.length; i++) {
76
+ const v = this.consumerList[i];
77
+ const safeName = this.name2id(v.name);
78
+ const id = `${this.namespace}.consumer.${i}_${safeName}.active`;
79
+ const state = await this.getStateAsync(id);
80
+ if (state && state.val !== null) {
81
+ v.enabled = state.val;
82
+ this.log.debug(`"${v.name}": Active status taken from object tree (${state.val})`);
83
+ }
84
+ }
85
+
77
86
  this.log.info(`Loaded consumers: ${this.consumerList.map(v => v.name).join(', ')}`);
78
87
 
79
88
  await this.checkAndCreateConsumerObjects();
@@ -227,6 +236,20 @@ class ZeroFeedIn extends utils.Adapter {
227
236
  native: {},
228
237
  });
229
238
 
239
+ // === NEUER STATE: Aktiv-Status ============================
240
+ await this.setObjectNotExistsAsync(`${channelId}.active`, {
241
+ type: 'state',
242
+ common: {
243
+ name: `${v.name} aktiv`,
244
+ type: 'boolean',
245
+ role: 'switch',
246
+ read: true,
247
+ write: true,
248
+ def: v.enabled || false,
249
+ },
250
+ native: {},
251
+ });
252
+
230
253
  if (v.ruletype === 'battery') {
231
254
  await this.setObjectNotExistsAsync(`${channelId}.batterySetpoint`, {
232
255
  type: 'state',
@@ -303,6 +326,8 @@ class ZeroFeedIn extends utils.Adapter {
303
326
  await this.setStateAsync(`${this.namespace}.${channelId}.onTimerRemaining`, { val: 0, ack: true });
304
327
  await this.setStateAsync(`${this.namespace}.${channelId}.offTimerRemaining`, { val: 0, ack: true });
305
328
 
329
+ await this.setStateAsync(`${channelId}.active`, { val: v.enabled || false, ack: true });
330
+
306
331
  v.switchOnTime = finalOnTime;
307
332
  v.switchOffTime = finalOffTime;
308
333
  }
@@ -387,6 +412,19 @@ class ZeroFeedIn extends utils.Adapter {
387
412
  if (state && !state.ack) {
388
413
  this.log.debug(`State changed: ${id} => ${state.val}`);
389
414
 
415
+ // --- Aktiv-Status manuell umschalten ---------------------------------
416
+ if (id.match(/consumer\.(\d+)_.*?\.active/)) {
417
+ const match = id.match(/consumer\.(\d+)_.*?\.active/);
418
+ const index = parseInt(match[1]);
419
+ const v = this.consumerList[index];
420
+ if (v) {
421
+ v.enabled = state.val;
422
+ this.log.info(`Consumer "${v.name}" became ${state.val ? 'activated' : 'deactivated'}.`);
423
+ await this.setStateAsync(id, { val: state.val, ack: true });
424
+ }
425
+ return;
426
+ }
427
+
390
428
  // ControlMode Änderungen
391
429
  const match = id.match(/consumer\.(\d+)_.*?\.controlMode/);
392
430
  if (match) {
@@ -423,11 +461,7 @@ class ZeroFeedIn extends utils.Adapter {
423
461
  try {
424
462
  if (!this.feedInDatapoint) {
425
463
  this.log.warn('No FeedIn datapoint set – skipping checkConsumers()');
426
- await this.sendNotification(
427
- 'smartloadmanager',
428
- 'alert',
429
- '❗ Kein FeedIn-Datenpunkt gesetzt – Regelung übersprungen.',
430
- );
464
+ await this.sendNotification('smartloadmanager', 'alert', '❗ No FeedIn data point set – rule skipped.');
431
465
  this.checkRunning = false;
432
466
  if (this.checkQueued) {
433
467
  await this.checkConsumers();
@@ -456,6 +490,11 @@ class ZeroFeedIn extends utils.Adapter {
456
490
  this.log.debug(`Switch-on check for ${sortedOn.length} binary/heating-consumers.`);
457
491
 
458
492
  for (const v of sortedOn) {
493
+ // Überspringe deaktivierte Verbraucher
494
+ if (!v.enabled) {
495
+ this.log.debug(`"${v.name}" is deactivated – skipped (power-on check).`);
496
+ continue;
497
+ }
459
498
  const idx = this.consumerList.indexOf(v);
460
499
  const safeName = this.name2id(v.name);
461
500
  const id = `${this.namespace}.consumer.${idx}_${safeName}`;
@@ -510,7 +549,7 @@ class ZeroFeedIn extends utils.Adapter {
510
549
  if (v.enableDatapoint) {
511
550
  const enableState = await this.getForeignStateAsync(v.enableDatapoint);
512
551
  if (!enableState?.val) {
513
- this.log.debug(`"${v.name}" NICHT eingeschaltet – Hardware release missing.`);
552
+ this.log.debug(`"${v.name}" NOT switched on – Hardware release missing.`);
514
553
  continue;
515
554
  }
516
555
  }
@@ -577,6 +616,11 @@ class ZeroFeedIn extends utils.Adapter {
577
616
  const safeName = this.name2id(v.name);
578
617
  const id = `${this.namespace}.consumer.${idx}_${safeName}`;
579
618
  const mode = await this.getStateAsync(`${id}.controlMode`);
619
+ // Überspringe deaktivierte Verbraucher
620
+ if (!v.enabled) {
621
+ this.log.debug(`"${v.name}" is deactivated – will be skipped (power-off check).`);
622
+ continue;
623
+ }
580
624
  if (!mode || mode.val !== 2) {
581
625
  continue;
582
626
  }
@@ -704,6 +748,10 @@ class ZeroFeedIn extends utils.Adapter {
704
748
  // --- Batterie unverändert ---
705
749
  const batteryConsumers = this.consumerList.filter(c => c.ruletype === 'battery');
706
750
  for (const v of batteryConsumers) {
751
+ if (!v.enabled) {
752
+ this.log.debug(`"${v.name}" is deactivated – battery control skipped.`);
753
+ continue;
754
+ }
707
755
  await this.controlBattery(v, feedIn);
708
756
  }
709
757
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.smartloadmanager",
3
- "version": "0.0.8",
3
+ "version": "0.1.0",
4
4
  "description": "This adapter allows devices to be controlled via PV surplus and thus achieve zero feed-in.",
5
5
  "author": {
6
6
  "name": "quorle",
@@ -28,16 +28,16 @@
28
28
  "translate": "^3.0.1"
29
29
  },
30
30
  "devDependencies": {
31
- "@alcalzone/release-script": "^3.8.0",
32
- "@alcalzone/release-script-plugin-iobroker": "^3.7.2",
33
- "@alcalzone/release-script-plugin-license": "^3.7.0",
34
- "@alcalzone/release-script-plugin-manual-review": "^3.7.0",
35
- "@iobroker/adapter-dev": "^1.4.0",
36
- "@iobroker/eslint-config": "^2.1.0",
31
+ "@alcalzone/release-script": "^5.0.0",
32
+ "@alcalzone/release-script-plugin-iobroker": "^4.0.0",
33
+ "@alcalzone/release-script-plugin-license": "^4.0.0",
34
+ "@alcalzone/release-script-plugin-manual-review": "^4.0.0",
35
+ "@iobroker/adapter-dev": "^1.5.0",
36
+ "@iobroker/eslint-config": "^2.2.0",
37
37
  "@iobroker/testing": "^5.1.1",
38
38
  "@tsconfig/node20": "^20.1.6",
39
- "@types/node": "^24.3.1",
40
- "typescript": "~5.0.4"
39
+ "@types/node": "^24.9.2",
40
+ "typescript": "~5.9.3"
41
41
  },
42
42
  "main": "main.js",
43
43
  "files": [