@feezal/feezal-element 3.0.13 → 3.0.14

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.
@@ -0,0 +1,112 @@
1
+ /**
2
+ * E156 — cross-component discovery fragments.
3
+ *
4
+ * Discovery used to match an element only to entities whose component EQUALS
5
+ * the element's own. That is too strict: a device of one component is often
6
+ * controllable by an element of another. These fragments express the two
7
+ * crossings the item asked for, ONCE, so the ~10 switch elements and the three
8
+ * slider elements do not each carry (and drift on) their own copy.
9
+ *
10
+ * The mechanism is `discovery.accepts` — see `elementAcceptsComponent` /
11
+ * `discoveryCandidates` in `www/src/feezal-discovery-stamp.js`. A variant may
12
+ * carry a `when(config)` guard (does this entity actually support this?) and a
13
+ * `label` suffix (which row is which, U56-style).
14
+ */
15
+
16
+ /**
17
+ * A `light` offered to a *-switch: drive the lamp as plain on/off.
18
+ *
19
+ * **Map order is load-bearing.** The stamp applies keys in insertion order and
20
+ * later writes win, and the DSL's `onlyWhen` can only test equality — there is
21
+ * no "unless". So the generic `payload_on`/`payload_off` are applied FIRST and
22
+ * the Homematic-style override LAST, where its `alsoSet` can overwrite them.
23
+ * Reordering this map silently changes which payloads a dimmer gets.
24
+ */
25
+ export const switchAcceptsLight = {
26
+ component: 'light',
27
+ map: {
28
+ // ── generic on/off light (zigbee2mqtt, HA) ────────────────────────
29
+ name: 'label',
30
+ payload_on: 'payload-on',
31
+ payload_off: 'payload-off',
32
+ state_topic: 'subscribe',
33
+ state_command_topic: 'publish',
34
+ command_topic: 'publish',
35
+ value_template: {attr: 'message-property', transform: 'valueTemplateToPath'},
36
+
37
+ // ── Homematic-style dimmer: on/off IS the LEVEL value (E77/E126) ──
38
+ // The light card toggles on with the 1.005 OLD_LEVEL sentinel to restore
39
+ // the previous brightness; a switch has no "previous brightness" to
40
+ // restore and no way to represent 1.005, so it drives full-on/off with
41
+ // 1 / 0. These come last so `alsoSet` overwrites the payload_on
42
+ // (= '1.005') the generic rows above already wrote.
43
+ brightness_state_topic: {attr: 'subscribe', onlyWhen: {on_off_source: 'brightness'}},
44
+ message_property_brightness: {attr: 'message-property', onlyWhen: {on_off_source: 'brightness'}},
45
+ brightness_command_topic: {
46
+ attr: 'publish',
47
+ onlyWhen: {on_off_source: 'brightness'},
48
+ alsoSet: {'payload-on': '1', 'payload-off': '0'},
49
+ },
50
+ },
51
+ };
52
+
53
+ // A settable axis needs a COMMAND topic. This is the guardrail the item calls
54
+ // out: a slider must never be offered a read-only value, so every variant below
55
+ // gates on the write path existing. A `sensor` has no command topic at all and
56
+ // therefore never reaches a slider; a light with no brightness never shows up
57
+ // as a brightness row.
58
+ const settable = key => cfg => Boolean(cfg[key]);
59
+
60
+ /**
61
+ * Everything a *-slider can drive. There is no "slider" entity type, so the
62
+ * descriptor has no base `component` — every match arrives through `accepts`,
63
+ * and one light yields up to TWO rows (brightness, colour temp).
64
+ */
65
+ export const sliderDiscovery = {
66
+ accepts: [
67
+ {
68
+ component: 'light',
69
+ label: 'brightness',
70
+ when: settable('brightness_command_topic'),
71
+ map: {
72
+ name: 'label',
73
+ brightness_state_topic: 'subscribe',
74
+ brightness_command_topic: 'publish',
75
+ brightness_min: {attr: 'min'},
76
+ // HA/z2m call the top of the range brightness_scale (254 on
77
+ // zigbee, 1 on Homematic LEVEL). Absent → the slider's own
78
+ // 0–100 default stands.
79
+ brightness_scale: {attr: 'max'},
80
+ message_property_brightness: 'message-property',
81
+ },
82
+ },
83
+ {
84
+ component: 'light',
85
+ label: 'color temp',
86
+ when: settable('color_temp_command_topic'),
87
+ map: {
88
+ name: 'label',
89
+ color_temp_state_topic: 'subscribe',
90
+ color_temp_command_topic: 'publish',
91
+ // Mireds are the wire unit here: the slider publishes the raw
92
+ // value, so the range is taken as-is rather than converted to
93
+ // kelvin the way a light card's colour-temp control does.
94
+ min_mireds: {attr: 'min'},
95
+ max_mireds: {attr: 'max'},
96
+ },
97
+ },
98
+ {
99
+ component: 'number',
100
+ when: settable('command_topic'),
101
+ map: {
102
+ name: 'label',
103
+ state_topic: 'subscribe',
104
+ command_topic: 'publish',
105
+ min: {attr: 'min'},
106
+ max: {attr: 'max'},
107
+ step: {attr: 'step'},
108
+ value_template: {attr: 'message-property', transform: 'valueTemplateToPath'},
109
+ },
110
+ },
111
+ ],
112
+ };
package/package.json CHANGED
@@ -16,6 +16,7 @@
16
16
  "feezal-element.js",
17
17
  "feezal-color.js",
18
18
  "feezal-conditions.js",
19
+ "feezal-discovery-fragments.js",
19
20
  "feezal-friendly-name.js",
20
21
  "feezal-hm-fault.js",
21
22
  "feezal-movement.js",
@@ -41,5 +42,5 @@
41
42
  "url": "git+https://github.com/feezal/feezal.git",
42
43
  "directory": "www/packages/@feezal/feezal-element"
43
44
  },
44
- "version": "3.0.13"
45
+ "version": "3.0.14"
45
46
  }