Newer Older
110 lines | 4.761kb
Bogdan Timofte authored 2 weeks ago
1
<script type="text/x-red" data-template-name="snzb-05p-homekit-adapter">
2
  <div class="form-row">
3
    <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
4
    <input type="text" id="node-input-name" placeholder="Name">
5
  </div>
6
  <div class="form-row">
7
    <label for="node-input-site"><i class="fa fa-globe"></i> Site</label>
8
    <input type="text" id="node-input-site" placeholder="vad">
9
  </div>
10
  <div class="form-row">
11
    <label for="node-input-location"><i class="fa fa-home"></i> Location</label>
12
    <input type="text" id="node-input-location" placeholder="bathroom">
13
  </div>
14
  <div class="form-row">
15
    <label for="node-input-accessory"><i class="fa fa-dot-circle-o"></i> Accessory</label>
16
    <input type="text" id="node-input-accessory" placeholder="sink-sensor">
17
  </div>
18
  <div class="form-row">
19
    <label for="node-input-batteryLowThreshold">Battery low threshold (%)</label>
20
    <input type="number" id="node-input-batteryLowThreshold" min="0" max="100" placeholder="20">
21
  </div>
22
</script>
23

            
24
<script type="text/x-red" data-help-name="snzb-05p-homekit-adapter">
25
  <p>
26
    Consumes HomeBus telemetry for a single <code>SNZB-05P</code> endpoint and projects it to HomeKit services.
27
  </p>
28
  <p>
29
    Output 3 is not a publish stream anymore. It controls a Node-RED <code>mqtt in</code> node with dynamic subscriptions.
30
  </p>
31
  <p>
32
    On start, the node emits:
33
    <code>subscribe &lt;site&gt;/home/&lt;location&gt;/+/&lt;accessory&gt;/last</code>,
34
    <code>subscribe &lt;site&gt;/home/&lt;location&gt;/+/&lt;accessory&gt;/value</code>, and
35
    <code>subscribe &lt;site&gt;/home/&lt;location&gt;/+/&lt;accessory&gt;/availability</code>.
36
  </p>
37
  <p>
38
    The node keeps <code>.../last</code> subscribed until the cold-start bootstrap is complete for all required values.
39
    A value is considered satisfied when it arrived either from <code>last</code> or from live <code>value</code>.
40
    Only then does the node emit <code>unsubscribe .../last</code>.
41
  </p>
42
  <p>
43
    Supported input topic shape:
44
    <code>&lt;site&gt;/home/&lt;location&gt;/&lt;capability&gt;/&lt;accessory&gt;/value</code>,
45
    <code>&lt;site&gt;/home/&lt;location&gt;/&lt;capability&gt;/&lt;accessory&gt;/last</code>, and
46
    <code>&lt;site&gt;/home/&lt;location&gt;/&lt;capability&gt;/&lt;accessory&gt;/availability</code>.
47
  </p>
48
  <p>
49
    The node accepts scalar <code>value</code> payloads, string/boolean <code>availability</code> payloads,
50
    and timestamped <code>last</code> envelopes of the form
51
    <code>{ value, observed_at, quality }</code>. For <code>last</code>, only <code>payload.value</code> is used.
52
  </p>
53
  <h3>Capabilities</h3>
54
  <p>
55
    Mappings:
56
    <code>water_leak -&gt; Leak Sensor</code>,
57
    <code>battery + battery_low -&gt; Battery</code>.
58
    Optional <code>tamper</code> updates are folded into HomeKit status flags when available.
59
  </p>
60
  <p>
61
    Subscription topics are generated from the configured <code>site</code>, <code>location</code>, and
62
    <code>accessory</code>. The bus segment remains fixed to <code>home</code>.
63
  </p>
64
  <h3>Outputs</h3>
65
  <ol>
66
    <li>Leak Sensor: <code>{ LeakDetected, StatusActive, StatusFault, StatusLowBattery, StatusTampered }</code></li>
67
    <li>Battery Service: <code>{ StatusLowBattery, BatteryLevel, ChargingState }</code></li>
68
    <li><code>mqtt in</code> dynamic control messages: <code>{ action, topic }</code></li>
69
  </ol>
70
  <h3>HomeKit Service Setup</h3>
71
  <p>
72
    The linked <code>homekit-service</code> nodes should explicitly materialize the optional characteristics used by this adapter.
73
    Set the Battery service node <code>characteristicProperties</code> to:
74
  </p>
75
  <pre><code>{"BatteryLevel":{},"ChargingState":{}}</code></pre>
76
  <p>
77
    Without these optional characteristics, HomeKit may keep default values until a later update or ignore the fields during startup.
78
  </p>
79
</script>
80

            
81
<script>
82
  function requiredText(v) {
83
    return !!(v && String(v).trim());
84
  }
85

            
86
  RED.nodes.registerType("snzb-05p-homekit-adapter", {
87
    category: "myNodes",
88
    color: "#d7f0d1",
89
    defaults: {
90
      name: { value: "" },
91
      outputTopic: { value: "" },
92
      mqttBus: { value: "" },
93
      site: { value: "", validate: requiredText },
94
      location: { value: "", validate: requiredText },
95
      accessory: { value: "", validate: requiredText },
96
      mqttSite: { value: "" },
97
      mqttRoom: { value: "" },
98
      mqttSensor: { value: "" },
99
      batteryLowThreshold: { value: 20, validate: RED.validators.number() },
100
      publishCacheWindowSec: { value: "" }
101
    },
102
    inputs: 1,
103
    outputs: 3,
104
    icon: "font-awesome/fa-tint",
105
    label: function() {
106
      return this.name || "snzb-05p-homekit-adapter";
107
    },
108
    paletteLabel: "snzb-05p homekit"
109
  });
110
</script>