homebridge-aiseg-awning-window-command 0.2.4 → 0.2.6

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/CHANGELOG.md ADDED
@@ -0,0 +1,51 @@
1
+ # Changelog
2
+
3
+ ## 0.2.6
4
+
5
+ - Added Home app screenshots to the README.
6
+ - Changed the README version history from a link-only section to an inline visible history.
7
+ - Kept the v0.2.5 tilt snapping behavior and simplified UI settings.
8
+
9
+ ## 0.2.5
10
+
11
+ - Improved the snap behavior of the HomeKit tilt slider for AiSEG2 awning windows.
12
+ - Tilt values now snap more firmly to 0°, 15°, 30°, 45°, and 60°.
13
+ - Updated the README and CHANGELOG documentation.
14
+ - Hid internal AiSEG request parameters to simplify the Homebridge UI settings.
15
+
16
+ ### Notes
17
+
18
+ This plugin is designed and tested for Sankyo Aluminum awning windows connected to AiSEG2.
19
+
20
+ Normal users only need:
21
+
22
+ - AiSEG2 IP address or host name
23
+ - AiSEG web password
24
+ - Node ID for each window
25
+
26
+ Each window's Node ID can be checked on the AiSEG2 web page under **Device Control > Window Sash**.
27
+ Open the browser developer tools with **F12**, go to **Network > Fetch/XHR**, press an action button, open the `operation` request, and check the 9-digit `nodeId` value in the request payload.
28
+
29
+ ## 0.2.4
30
+
31
+ - Refactored Python scripts to use a shared `aiseg_device.py` core.
32
+ - Kept `aiseg_window.py` as a compatibility wrapper.
33
+ - Continued to bundle package-local Python scripts.
34
+ - Continued to avoid Python `requests` dependency.
35
+
36
+ ## 0.2.3
37
+
38
+ - Bundled the AiSEG awning Python script inside the npm package.
39
+ - Removed fixed private IP, password, and node ID values from the packaged script.
40
+ - Passed user-specific values from Homebridge config to Python via environment variables.
41
+ - Removed dependency on the external Python `requests` package.
42
+
43
+ ## 0.2.2
44
+
45
+ - Improved HomeKit awning window behavior.
46
+ - Added better motion guard handling for open, close, and tilt operations.
47
+ - Improved HomeKit display consistency during AiSEG state polling.
48
+
49
+ ## 0.2.1 and earlier
50
+
51
+ - Early development releases for AiSEG2 awning window control.
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
@@ -1,62 +1,141 @@
1
1
  # homebridge-aiseg-awning-window-command
2
2
 
3
- Homebridge plugin for AiSEG2 awning windows
3
+ Homebridge plugin for AiSEG2-connected awning windows.
4
4
 
5
- ## Overview
5
+ This plugin exposes AiSEG2 awning windows as HomeKit `WindowCovering` accessories.
6
6
 
7
- This is a command-based Homebridge platform plugin for AiSEG-controlled devices.
7
+ ## Screenshots
8
8
 
9
- The plugin calls external commands for actions and optional status polling.
10
- It is designed for environments where a separate script can already operate the target AiSEG device.
9
+ <p>
10
+ <img src="./docs/homekit-tile.jpg" alt="Home app tile view showing the awning window at 50 percent open" width="260">
11
+ <img src="./docs/homekit-settings.jpg" alt="Home app settings view showing the awning window tilt slider" width="260">
12
+ </p>
11
13
 
12
- ## Requirements
14
+ The screenshots show the Home app tile view and the detail view with the horizontal tilt slider.
15
+
16
+ ## Features
17
+
18
+ - Open / close control from HomeKit
19
+ - HomeKit horizontal tilt angle control
20
+ - Stop switch accessory
21
+ - Status polling from AiSEG2
22
+ - Motion guard to reduce stale-state jumps
23
+ - Strong tilt snapping for HomeKit
24
+ - Package-local Python scripts included
25
+ - No external Python `requests` dependency
26
+ - Shared AiSEG Python core used internally
27
+
28
+ ## Supported HomeKit tilt values
29
+
30
+ The HomeKit tilt slider is snapped to the following values:
31
+
32
+ | HomeKit tilt | AiSEG command |
33
+ |---:|---|
34
+ | 0° | close |
35
+ | 15° | angle1 |
36
+ | 30° | angle2 |
37
+ | 45° | angle3 |
38
+ | 60° | open |
39
+
40
+ Starting from v0.2.5, the plugin more strongly echoes the snapped tilt value back to HomeKit.
41
+ This helps prevent the Home app slider from visually stopping around intermediate values such as 25°.
42
+
43
+ ## Notes
44
+
45
+ This plugin is designed and tested for Sankyo Aluminum awning windows connected to AiSEG2.
46
+
47
+ Normal users only need to configure:
48
+
49
+ - AiSEG2 IP address or host name
50
+ - AiSEG web password
51
+ - Node ID for each window
52
+
53
+ Internal AiSEG request parameters are hidden from the Homebridge UI because they normally do not need to be changed.
54
+
55
+ ## How to find the Node ID
13
56
 
57
+ You can check each window's Node ID from the AiSEG2 web page:
58
+
59
+ 1. Open the AiSEG2 web interface.
60
+ 2. Go to **Device Control > Window Sash**.
61
+ 3. Open the browser developer tools with **F12**.
62
+ 4. Go to the **Network** tab and filter by **Fetch/XHR**.
63
+ 5. Press an action button for the target window.
64
+ 6. Open the `operation` request.
65
+ 7. Check the request payload. The window Node ID is the 9-digit `nodeId` value.
66
+
67
+ ## Tested environment
68
+
69
+ - AiSEG2
70
+ - Sankyo Aluminum awning windows
71
+ - AiSEG adapter / related Panasonic equipment: MKN7751K
14
72
  - Homebridge 2.x
15
- - Node.js 22 or later
16
- - Working command or script for device operation
17
- - Optional status command for state polling
73
+ - Node.js 24.x
18
74
 
19
- ## Installation
75
+ ## Hidden internal settings
20
76
 
21
- ```bash
22
- npm install -g homebridge-aiseg-awning-window-command
23
- ```
77
+ The following AiSEG request parameters are intentionally hidden from the Homebridge UI:
24
78
 
25
- ## Configuration
79
+ - device type
80
+ - page
81
+ - page326
82
+ - track
83
+ - request_by_form
84
+ - acceptId
26
85
 
27
- Use the Homebridge UI to configure this plugin.
86
+ The plugin still uses internal defaults for these values.
28
87
 
29
- Typical settings include:
88
+ ## Related plugin
30
89
 
31
- - display name
32
- - command path
33
- - open / close / stop / position commands where supported
34
- - status command
35
- - polling interval
36
- - movement guard / transition timing where supported
90
+ For AiSEG3 blind shutters, use:
37
91
 
38
- ## Notes
92
+ - `homebridge-aiseg-shutter-command`
93
+
94
+ ## Requirements
95
+
96
+ - Homebridge
97
+ - Node.js
98
+ - Python 3 available in the Homebridge environment
99
+
100
+ No additional Python package installation is required.
101
+
102
+ ## Version history
103
+
104
+ ### 0.2.6
105
+
106
+ - Added screenshots to the README.
107
+ - Changed the README version history from a link-only section to an inline visible history.
108
+ - Kept the v0.2.5 tilt snapping behavior and simplified UI settings.
109
+
110
+ ### 0.2.5
111
+
112
+ - Improved the snap behavior of the HomeKit tilt slider for AiSEG2 awning windows.
113
+ - Tilt values now snap more firmly to 0°, 15°, 30°, 45°, and 60°.
114
+ - Updated the README and CHANGELOG documentation.
115
+ - Hid internal AiSEG request parameters to simplify the Homebridge UI settings.
116
+
117
+ ### 0.2.4
39
118
 
40
- This plugin does not include AiSEG login or operation scripts.
41
- Prepare and test the command scripts before configuring Homebridge.
119
+ - Refactored Python scripts to use a shared `aiseg_device.py` core.
120
+ - Kept `aiseg_window.py` as a compatibility wrapper.
121
+ - Continued to bundle package-local Python scripts.
122
+ - Continued to avoid Python `requests` dependency.
42
123
 
43
- A command should be tested manually first, for example:
124
+ ### 0.2.3
44
125
 
45
- ```bash
46
- python3 /path/to/script.py target status
47
- python3 /path/to/script.py target open
48
- python3 /path/to/script.py target close
49
- ```
126
+ - Bundled the AiSEG awning Python script inside the npm package.
127
+ - Removed fixed private IP, password, and node ID values from the packaged script.
128
+ - Passed user-specific values from Homebridge config to Python via environment variables.
129
+ - Removed dependency on the external Python `requests` package.
50
130
 
51
- ## Troubleshooting
131
+ ### 0.2.2
52
132
 
53
- If the accessory does not respond:
133
+ - Improved HomeKit awning window behavior.
134
+ - Added better motion guard handling for open, close, and tilt operations.
135
+ - Improved HomeKit display consistency during AiSEG state polling.
54
136
 
55
- 1. Run the configured command manually.
56
- 2. Confirm the command path is correct inside the Homebridge environment.
57
- 3. Confirm the Homebridge container has permission to execute the command.
58
- 4. Check Homebridge logs for command timeout or stderr output.
137
+ ### 0.2.1 and earlier
59
138
 
60
- ## Disclaimer
139
+ - Early development releases for AiSEG2 awning window control.
61
140
 
62
- This project is not affiliated with Apple, Homebridge, Panasonic, or AiSEG.
141
+ See [CHANGELOG.md](./CHANGELOG.md) for the same history in changelog format.
@@ -115,42 +115,6 @@
115
115
  "aisegId"
116
116
  ]
117
117
  }
118
- },
119
- "deviceType": {
120
- "title": "種別",
121
- "description": "AiSEG2オーニング窓の種別です。通常は 0x0f です。",
122
- "type": "string",
123
- "default": "0x0f"
124
- },
125
- "page": {
126
- "title": "Page",
127
- "description": "詳細設定です。通常は 1 です。",
128
- "type": "string",
129
- "default": "1"
130
- },
131
- "page326": {
132
- "title": "Page326",
133
- "description": "詳細設定です。通常は 1 です。",
134
- "type": "string",
135
- "default": "1"
136
- },
137
- "track": {
138
- "title": "Track",
139
- "description": "詳細設定です。通常は 326 です。",
140
- "type": "string",
141
- "default": "326"
142
- },
143
- "requestByForm": {
144
- "title": "Request By Form",
145
- "description": "詳細設定です。通常は 1 です。",
146
- "type": "string",
147
- "default": "1"
148
- },
149
- "acceptId": {
150
- "title": "Accept ID",
151
- "description": "詳細設定です。通常は 65550 です。",
152
- "type": "string",
153
- "default": "65550"
154
118
  }
155
119
  },
156
120
  "required": [
Binary file
Binary file
package/index.js CHANGED
@@ -162,17 +162,52 @@ class AwningWindow {
162
162
  .onGet(() => this.positionState);
163
163
 
164
164
  this.service.getCharacteristic(this.Characteristic.CurrentHorizontalTiltAngle)
165
- .setProps({ minValue: 0, maxValue: 60, minStep: 15 })
165
+ .setProps({ minValue: 0, maxValue: 60, minStep: 15, validValues: [0, 15, 30, 45, 60] })
166
166
  .onGet(() => this.currentTilt);
167
167
 
168
168
  this.service.getCharacteristic(this.Characteristic.TargetHorizontalTiltAngle)
169
- .setProps({ minValue: 0, maxValue: 60, minStep: 15 })
169
+ .setProps({ minValue: 0, maxValue: 60, minStep: 15, validValues: [0, 15, 30, 45, 60] })
170
170
  .onGet(() => this.targetTilt)
171
171
  .onSet(async (value) => this.setTargetTilt(value));
172
172
 
173
173
  this.updateHomeKit();
174
174
  }
175
175
 
176
+
177
+ forceTiltSnap(snapped, source, mirrorCurrent) {
178
+ const v = clamp(Number(snapped), 0, 60);
179
+
180
+ this.targetTilt = v;
181
+
182
+ const targetChar = this.service.getCharacteristic(this.Characteristic.TargetHorizontalTiltAngle);
183
+ const currentChar = this.service.getCharacteristic(this.Characteristic.CurrentHorizontalTiltAngle);
184
+
185
+ targetChar.updateValue(v);
186
+
187
+ if (mirrorCurrent) {
188
+ this.currentTilt = v;
189
+ currentChar.updateValue(v);
190
+ }
191
+
192
+ // HomeKit sometimes keeps the raw slider value briefly.
193
+ // Echo the snapped value several times so 25° etc. returns to 15/30/45/60 cleanly.
194
+ for (const delay of [100, 350, 900]) {
195
+ setTimeout(() => {
196
+ if (this.targetTilt === v || Date.now() < this.motionUntil) {
197
+ targetChar.updateValue(v);
198
+
199
+ if (mirrorCurrent) {
200
+ currentChar.updateValue(v);
201
+ }
202
+
203
+ if (source && this.lastUnknownStatus === "__never__") {
204
+ // no-op: keep linter-free structure without extra log noise
205
+ }
206
+ }
207
+ }, delay);
208
+ }
209
+ }
210
+
176
211
  async setTargetPosition(value) {
177
212
  const raw = clamp(Number(value), 0, 100);
178
213
  const normalized = raw <= 50 ? 0 : 100;
@@ -201,14 +236,14 @@ class AwningWindow {
201
236
 
202
237
  this.log.info(`[${this.name}] TargetHorizontalTiltAngle ${raw} -> ${snapped}`);
203
238
 
204
- this.targetTilt = snapped;
205
- this.service.getCharacteristic(this.Characteristic.TargetHorizontalTiltAngle).updateValue(snapped);
239
+ this.forceTiltSnap(snapped, "setTargetTilt-start", false);
206
240
 
207
241
  if (snapped === 0) {
208
242
  this.targetPosition = 0;
209
243
  this.service.getCharacteristic(this.Characteristic.TargetPosition).updateValue(0);
210
244
  this.startMotion("closed", this.motionGuardSeconds, 0);
211
245
  await this.runAction("close", "tilt 0 / close");
246
+ this.forceTiltSnap(0, "tilt-close-done", true);
212
247
  return;
213
248
  }
214
249
 
@@ -217,6 +252,7 @@ class AwningWindow {
217
252
  this.service.getCharacteristic(this.Characteristic.TargetPosition).updateValue(100);
218
253
  this.startMotion("open", Math.max(this.motionGuardSeconds, this.openAcceptDelaySeconds), 60);
219
254
  await this.runAction("open", "tilt 60 / open");
255
+ this.forceTiltSnap(60, "tilt-open-done", true);
220
256
  return;
221
257
  }
222
258
 
@@ -227,12 +263,15 @@ class AwningWindow {
227
263
  if (snapped === 15) {
228
264
  this.startMotion("angle1", this.tiltMotionGuardSeconds, 15);
229
265
  await this.runAction("angle1", "angle1");
266
+ this.forceTiltSnap(15, "angle1-done", true);
230
267
  } else if (snapped === 30) {
231
268
  this.startMotion("angle2", this.tiltMotionGuardSeconds, 30);
232
269
  await this.runAction("angle2", "angle2");
270
+ this.forceTiltSnap(30, "angle2-done", true);
233
271
  } else {
234
272
  this.startMotion("angle3", this.tiltMotionGuardSeconds, 45);
235
273
  await this.runAction("angle3", "angle3");
274
+ this.forceTiltSnap(45, "angle3-done", true);
236
275
  }
237
276
  }
238
277
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-aiseg-awning-window-command",
3
- "version": "0.2.4",
4
- "description": "Homebridge plugin for AiSEG2 awning windows",
3
+ "version": "0.2.6",
4
+ "description": "Homebridge plugin for AiSEG2 awning windows with HomeKit tilt snapping",
5
5
  "main": "index.js",
6
6
  "keywords": [
7
7
  "homebridge-plugin",
@@ -10,7 +10,13 @@
10
10
  "window",
11
11
  "homekit",
12
12
  "homebridge",
13
- "command"
13
+ "command",
14
+ "aiseg2",
15
+ "window-covering",
16
+ "tilt",
17
+ "sankyo",
18
+ "sankyo-aluminum",
19
+ "panasonic"
14
20
  ],
15
21
  "engines": {
16
22
  "homebridge": ">=1.8.0",
@@ -23,6 +29,10 @@
23
29
  "README.md",
24
30
  "LICENSE",
25
31
  "scripts/aiseg_window.py",
26
- "scripts/aiseg_device.py"
27
- ]
32
+ "scripts/aiseg_device.py",
33
+ "CHANGELOG.md",
34
+ "docs/homekit-tile.jpg",
35
+ "docs/homekit-settings.jpg"
36
+ ],
37
+ "displayName": "Homebridge AiSEG Awning Window Command"
28
38
  }