@boozilla/homebridge-shome 1.0.12 → 1.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.
@@ -14,11 +14,13 @@ export class ShomeClient {
14
14
  deviceId;
15
15
  cachedAccessToken = null;
16
16
  ihdId = null;
17
+ homeId = null;
17
18
  tokenExpiry = 0;
18
19
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
20
  putQueue = [];
20
21
  isProcessingPut = false;
21
22
  loginPromise = null;
23
+ pendingPutRequests = new Set();
22
24
  constructor(log, username, password, deviceId) {
23
25
  this.log = log;
24
26
  this.username = username;
@@ -70,6 +72,7 @@ export class ShomeClient {
70
72
  if (response.data && response.data.accessToken) {
71
73
  this.cachedAccessToken = response.data.accessToken;
72
74
  this.ihdId = response.data.ihdId;
75
+ this.homeId = response.data.homeId;
73
76
  const payload = JSON.parse(Buffer.from(this.cachedAccessToken.split('.')[1], 'base64').toString());
74
77
  this.tokenExpiry = payload.exp * 1000;
75
78
  this.log.info('Successfully logged in to sHome API.');
@@ -85,9 +88,9 @@ export class ShomeClient {
85
88
  throw error;
86
89
  }
87
90
  }
88
- enqueuePut(request) {
91
+ enqueuePut(request, deviceId) {
89
92
  return new Promise((resolve, reject) => {
90
- this.putQueue.push({ request, resolve, reject });
93
+ this.putQueue.push({ request, resolve, reject, deviceId });
91
94
  this.processPutQueue();
92
95
  });
93
96
  }
@@ -98,6 +101,9 @@ export class ShomeClient {
98
101
  this.isProcessingPut = true;
99
102
  while (this.putQueue.length > 0) {
100
103
  const task = this.putQueue.shift();
104
+ if (task.deviceId) {
105
+ this.pendingPutRequests.add(task.deviceId);
106
+ }
101
107
  try {
102
108
  const result = await this.executeWithRetries(task.request, true);
103
109
  task.resolve(result);
@@ -105,6 +111,11 @@ export class ShomeClient {
105
111
  catch (error) {
106
112
  task.reject(error);
107
113
  }
114
+ finally {
115
+ if (task.deviceId) {
116
+ this.pendingPutRequests.delete(task.deviceId);
117
+ }
118
+ }
108
119
  await new Promise(resolve => setTimeout(resolve, REQUEST_DELAY_MS));
109
120
  }
110
121
  this.isProcessingPut = false;
@@ -113,8 +124,6 @@ export class ShomeClient {
113
124
  let retries = 0;
114
125
  while (true) {
115
126
  try {
116
- // For non-queued (concurrent) requests, we need to ensure login happens before the request.
117
- // For queued requests, the login is handled as part of the queue, so we can just await it.
118
127
  if (!isQueued) {
119
128
  await this.login();
120
129
  }
@@ -137,11 +146,13 @@ export class ShomeClient {
137
146
  this.log.warn(`Request failed. Retrying in ${backoffTime}ms... (Attempt ${retries}/${MAX_RETRIES})`);
138
147
  }
139
148
  await new Promise(resolve => setTimeout(resolve, backoffTime));
140
- // After a failure, always ensure we are logged in before the next attempt.
141
149
  await this.login();
142
150
  }
143
151
  }
144
152
  }
153
+ isDeviceBusy(deviceId) {
154
+ return this.pendingPutRequests.has(deviceId);
155
+ }
145
156
  async getDeviceList() {
146
157
  return this.executeWithRetries(async () => {
147
158
  const token = this.cachedAccessToken;
@@ -173,17 +184,18 @@ export class ShomeClient {
173
184
  return response.data.deviceInfoList || null;
174
185
  });
175
186
  }
176
- async setDevice(thingId, deviceId, type, controlType, state, nickname) {
177
- return this.enqueuePut(async () => {
187
+ async setDevice(thingId, subDeviceId, type, controlType, state, nickname) {
188
+ const deviceId = `${thingId}-${subDeviceId}`;
189
+ const request = async () => {
178
190
  const token = this.cachedAccessToken;
179
191
  if (!token) {
180
192
  return false;
181
193
  }
182
194
  const createDate = this.getDateTime();
183
- const hashData = this.sha512(`IHRESTAPI${thingId}${deviceId}${state}${createDate}`);
195
+ const hashData = this.sha512(`IHRESTAPI${thingId}${subDeviceId}${state}${createDate}`);
184
196
  const typePath = type.toLowerCase().replace(/_/g, '');
185
197
  const controlPath = controlType.toLowerCase().replace(/_/g, '-');
186
- await axios.put(`${BASE_URL}/v18/settings/${typePath}/${thingId}/${deviceId}/${controlPath}`, null, {
198
+ await axios.put(`${BASE_URL}/v18/settings/${typePath}/${thingId}/${subDeviceId}/${controlPath}`, null, {
187
199
  params: {
188
200
  createDate,
189
201
  [controlType === 'WINDSPEED' ? 'mode' : 'state']: state,
@@ -191,13 +203,15 @@ export class ShomeClient {
191
203
  },
192
204
  headers: { 'Authorization': `Bearer ${token}` },
193
205
  });
194
- const displayName = nickname || `${thingId}/${deviceId}`;
206
+ const displayName = nickname || deviceId;
195
207
  this.log.info(`[${displayName}] state set to ${state}.`);
196
208
  return true;
197
- });
209
+ };
210
+ return this.enqueuePut(request, deviceId);
198
211
  }
199
212
  async unlockDoorlock(thingId, nickname) {
200
- return this.enqueuePut(async () => {
213
+ const deviceId = thingId;
214
+ const request = async () => {
201
215
  const token = this.cachedAccessToken;
202
216
  if (!token) {
203
217
  return false;
@@ -215,8 +229,52 @@ export class ShomeClient {
215
229
  const displayName = nickname || thingId;
216
230
  this.log.info(`Unlocked [${displayName}].`);
217
231
  return true;
232
+ };
233
+ return this.enqueuePut(request, deviceId);
234
+ }
235
+ async getVisitorHistory() {
236
+ return this.executeWithRetries(async () => {
237
+ const token = this.cachedAccessToken;
238
+ if (!token || !this.homeId) {
239
+ this.log.error('Cannot fetch visitor history: Not logged in or homeId is missing.');
240
+ return [];
241
+ }
242
+ const createDate = this.getDateTime();
243
+ const offset = 0;
244
+ const hashData = this.sha512(`IHRESTAPI${this.homeId}${offset}${createDate}`);
245
+ const response = await axios.get(`${BASE_URL}/v16/histories/${this.homeId}/video-histories`, {
246
+ params: { createDate, hashData, offset },
247
+ headers: { 'Authorization': `Bearer ${token}` },
248
+ });
249
+ return response.data.videoList || [];
218
250
  });
219
251
  }
252
+ async getThumbnailImage(visitor) {
253
+ const request = async () => {
254
+ const token = this.cachedAccessToken;
255
+ if (!token) {
256
+ this.log.error('Cannot fetch thumbnail: Not logged in.');
257
+ return null;
258
+ }
259
+ if (!visitor.sttId) {
260
+ this.log.error('Cannot fetch thumbnail: sttId is missing from visitor object.');
261
+ return null;
262
+ }
263
+ const createDate = this.getDateTime();
264
+ const hashData = this.sha512(`IHRESTAPI${visitor.sttId}${createDate}`);
265
+ const thumbnailUrl = `${BASE_URL}/v16/histories/${visitor.sttId}/video-thumbnail`;
266
+ const response = await axios.get(thumbnailUrl, {
267
+ params: {
268
+ createDate,
269
+ hashData,
270
+ },
271
+ headers: { 'Authorization': `Bearer ${token}` },
272
+ responseType: 'arraybuffer',
273
+ });
274
+ return Buffer.from(response.data, 'binary');
275
+ };
276
+ return this.executeWithRetries(request);
277
+ }
220
278
  sha512(input) {
221
279
  return CryptoJS.SHA512(input).toString();
222
280
  }
@@ -1 +1 @@
1
- {"version":3,"file":"shomeClient.js","sourceRoot":"","sources":["../src/shomeClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shomeClient.js","sourceRoot":"","sources":["../src/shomeClient.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@boozilla/homebridge-shome",
3
3
  "displayName": "sHome Plugin",
4
- "version": "1.0.12",
4
+ "version": "1.1.0",
5
5
  "private": false,
6
6
  "description": "A Homebridge plugin for Samsung Smart Home",
7
7
  "author": "boozilla",
@@ -0,0 +1,49 @@
1
+ import { PlatformAccessory, Service } from 'homebridge';
2
+ import { ShomePlatform } from '../platform.js';
3
+ import { ShomeCameraController } from '../controller/cameraController.js';
4
+ import { Visitor } from '../shomeClient.js';
5
+
6
+ export class DoorbellAccessory {
7
+ private doorbellService: Service;
8
+ private motionService: Service;
9
+ private cameraController: ShomeCameraController;
10
+
11
+ constructor(
12
+ private readonly platform: ShomePlatform,
13
+ private readonly accessory: PlatformAccessory,
14
+ ) {
15
+ this.accessory.getService(this.platform.Service.AccessoryInformation)!
16
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, 'sHome')
17
+ .setCharacteristic(this.platform.Characteristic.Model, 'Doorbell')
18
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, 'shome-doorbell');
19
+
20
+ // 1. 초인종 서비스 설정
21
+ this.doorbellService = this.accessory.getService(this.platform.Service.Doorbell)
22
+ || this.accessory.addService(this.platform.Service.Doorbell);
23
+ this.doorbellService.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent);
24
+
25
+ // 2. 카메라 컨트롤러 초기화
26
+ this.cameraController = new ShomeCameraController(this.platform, this.accessory);
27
+
28
+ // 3. 움직임 감지 서비스 추가
29
+ this.motionService = this.accessory.getService(this.platform.Service.MotionSensor)
30
+ || this.accessory.addService(this.platform.Service.MotionSensor, 'Doorbell Motion');
31
+
32
+ // 4. ✨ 핵심 수정: 초인종 서비스에 모션 센서 서비스를 연결합니다.
33
+ this.doorbellService.addLinkedService(this.motionService);
34
+ }
35
+
36
+ public newVisitor(visitor: Visitor) {
37
+ this.platform.log.info(`New visitor event at [${visitor.deviceLabel}]. Ringing doorbell and updating snapshot data.`);
38
+
39
+ this.cameraController.updateVisitor(visitor);
40
+
41
+ this.doorbellService.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent)
42
+ .updateValue(this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
43
+
44
+ this.motionService.getCharacteristic(this.platform.Characteristic.MotionDetected).updateValue(true);
45
+ setTimeout(() => {
46
+ this.motionService.getCharacteristic(this.platform.Characteristic.MotionDetected).updateValue(false);
47
+ }, 1000);
48
+ }
49
+ }
@@ -0,0 +1,92 @@
1
+ import {
2
+ CameraController,
3
+ CameraStreamingDelegate,
4
+ HAP,
5
+ H264Profile,
6
+ H264Level,
7
+ Logger,
8
+ PlatformAccessory,
9
+ SnapshotRequest,
10
+ SnapshotRequestCallback,
11
+ } from 'homebridge';
12
+ import { ShomePlatform } from '../platform.js';
13
+ import { Visitor } from '../shomeClient.js';
14
+
15
+ export class ShomeCameraController implements CameraStreamingDelegate {
16
+ private readonly hap: HAP;
17
+ private readonly log: Logger;
18
+ private latestVisitor: Visitor | null = null;
19
+ public readonly controller: CameraController;
20
+
21
+ constructor(
22
+ private readonly platform: ShomePlatform,
23
+ private readonly accessory: PlatformAccessory,
24
+ ) {
25
+ this.hap = this.platform.api.hap;
26
+ this.log = this.platform.log;
27
+
28
+ this.controller = new this.hap.CameraController({
29
+ cameraStreamCount: 2,
30
+ delegate: this,
31
+ streamingOptions: {
32
+ supportedCryptoSuites: [this.hap.SRTPCryptoSuites.AES_CM_128_HMAC_SHA1_80],
33
+ video: {
34
+ resolutions: [
35
+ [1280, 720, 30],
36
+ [320, 240, 30],
37
+ ],
38
+ codec: {
39
+ profiles: [H264Profile.BASELINE],
40
+ levels: [H264Level.LEVEL3_1],
41
+ },
42
+ },
43
+ },
44
+ });
45
+
46
+ let cameraOperatingMode = this.accessory.getService(this.hap.Service.CameraOperatingMode);
47
+ if (!cameraOperatingMode) {
48
+ cameraOperatingMode = this.accessory.addService(this.hap.Service.CameraOperatingMode, this.accessory.displayName + ' Mode');
49
+ }
50
+ cameraOperatingMode.setCharacteristic(this.hap.Characteristic.EventSnapshotsActive, this.hap.Characteristic.EventSnapshotsActive.ENABLE);
51
+
52
+ if (!this.accessory.getService(this.hap.Service.CameraRTPStreamManagement)) {
53
+ this.accessory.addService(this.hap.Service.CameraRTPStreamManagement, this.accessory.displayName + ' Stream Management');
54
+ }
55
+ }
56
+
57
+ public async handleSnapshotRequest(request: SnapshotRequest, callback: SnapshotRequestCallback): Promise<void> {
58
+ this.log.info('Handling snapshot request...');
59
+
60
+ if (!this.latestVisitor) {
61
+ this.log.warn('No visitor data available for snapshot. This will result in a "No Response" error until the first doorbell event.');
62
+ return callback(new Error('No snapshot available'));
63
+ }
64
+
65
+ try {
66
+ const imageBuffer = await this.platform.shomeClient.getThumbnailImage(this.latestVisitor);
67
+
68
+ if (imageBuffer) {
69
+ this.log.info('Snapshot fetched successfully via shomeClient.');
70
+ callback(undefined, imageBuffer);
71
+ } else {
72
+ throw new Error('Failed to retrieve image buffer from shomeClient.');
73
+ }
74
+ } catch (error) {
75
+ this.log.error('Failed to get snapshot:', error);
76
+ callback(error as Error);
77
+ }
78
+ }
79
+
80
+ public updateVisitor(visitor: Visitor) {
81
+ this.log.debug(`Updating latest visitor data for sttId: ${visitor.sttId}`);
82
+ this.latestVisitor = visitor;
83
+ }
84
+
85
+ prepareStream(): Promise<void> {
86
+ return Promise.resolve();
87
+ }
88
+
89
+ handleStreamRequest(): void {
90
+ // Streaming not supported
91
+ }
92
+ }
package/src/platform.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import { API, Characteristic, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service } from 'homebridge';
2
2
  import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
3
- import { ShomeClient, MainDevice, SubDevice } from './shomeClient.js';
3
+ import { ShomeClient, MainDevice, SubDevice, Visitor } from './shomeClient.js';
4
4
  import { LightAccessory } from './accessories/lightAccessory.js';
5
5
  import { VentilatorAccessory } from './accessories/ventilatorAccessory.js';
6
6
  import { HeaterAccessory } from './accessories/heaterAccessory.js';
7
7
  import { DoorlockAccessory } from './accessories/doorlockAccessory.js';
8
+ import { DoorbellAccessory } from './accessories/doorbellAccessory.js';
8
9
 
9
10
  const CONTROLLABLE_MULTI_DEVICE_TYPES = ['LIGHT', 'HEATER', 'VENTILATOR'];
10
11
  const SPECIAL_CONTROLLABLE_TYPES = ['DOORLOCK'];
11
12
 
12
- // Define a type for our accessory handlers
13
- type AccessoryHandler = LightAccessory | VentilatorAccessory | HeaterAccessory | DoorlockAccessory;
13
+ type AccessoryHandler = LightAccessory | VentilatorAccessory | HeaterAccessory | DoorlockAccessory | DoorbellAccessory;
14
14
 
15
15
  export class ShomePlatform implements DynamicPlatformPlugin {
16
16
  public readonly Service: typeof Service;
@@ -21,6 +21,8 @@ export class ShomePlatform implements DynamicPlatformPlugin {
21
21
  private pollingInterval: number;
22
22
  private pollingTimer?: NodeJS.Timeout;
23
23
 
24
+ private lastCheckedTimestamp: Date = new Date();
25
+
24
26
  constructor(
25
27
  public readonly log: Logger,
26
28
  public readonly config: PlatformConfig,
@@ -44,6 +46,8 @@ export class ShomePlatform implements DynamicPlatformPlugin {
44
46
  this.config.deviceId,
45
47
  );
46
48
 
49
+ this.log.info(`Video Doorbell service is active. Baseline time: ${this.lastCheckedTimestamp.toISOString()}`);
50
+
47
51
  this.api.on('didFinishLaunching', () => {
48
52
  this.discoverDevices();
49
53
  if (this.pollingInterval > 0) {
@@ -72,10 +76,6 @@ export class ShomePlatform implements DynamicPlatformPlugin {
72
76
  const devices = await this.shomeClient.getDeviceList();
73
77
  const foundAccessories: PlatformAccessory[] = [];
74
78
 
75
- if (!devices || devices.length === 0) {
76
- this.log.warn('No devices found on your sHome account.');
77
- }
78
-
79
79
  for (const device of devices) {
80
80
  if (CONTROLLABLE_MULTI_DEVICE_TYPES.includes(device.thngModelTypeName)) {
81
81
  const deviceInfoList = await this.shomeClient.getDeviceInfo(device.thngId, device.thngModelTypeName);
@@ -90,11 +90,14 @@ export class ShomePlatform implements DynamicPlatformPlugin {
90
90
  const uuid = this.api.hap.uuid.generate(device.thngId);
91
91
  const accessory = this.setupAccessory(device, null, uuid);
92
92
  foundAccessories.push(accessory);
93
- } else {
94
- this.log.info(`Ignoring device: ${device.nickname} (Type: ${device.thngModelTypeName})`);
95
93
  }
96
94
  }
97
95
 
96
+ const doorbellUUID = this.api.hap.uuid.generate('shome-doorbell');
97
+ const doorbellDevice = { thngModelTypeName: 'DOORBELL', nickname: 'Doorbell', thngId: 'shome-doorbell' } as MainDevice;
98
+ const doorbellAccessory = this.setupAccessory(doorbellDevice, null, doorbellUUID);
99
+ foundAccessories.push(doorbellAccessory);
100
+
98
101
  const accessoriesToRemove = this.accessories.filter(cachedAccessory =>
99
102
  !foundAccessories.some(foundAccessory => foundAccessory.UUID === cachedAccessory.UUID),
100
103
  );
@@ -114,29 +117,31 @@ export class ShomePlatform implements DynamicPlatformPlugin {
114
117
  const displayName = subDevice ? subDevice.nickname : mainDevice.nickname;
115
118
  const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
116
119
 
120
+ const accessory = existingAccessory ?? new this.api.platformAccessory(displayName, uuid);
121
+ accessory.context.device = mainDevice;
122
+ accessory.context.subDevice = subDevice;
123
+
117
124
  if (existingAccessory) {
118
125
  this.log.info('Restoring existing accessory from cache:', displayName);
119
- existingAccessory.context.device = mainDevice;
120
- existingAccessory.context.subDevice = subDevice;
121
- this.createAccessory(existingAccessory);
122
- return existingAccessory;
123
126
  } else {
124
127
  this.log.info('Adding new accessory:', displayName);
125
- const accessory = new this.api.platformAccessory(displayName, uuid);
126
- accessory.context.device = mainDevice;
127
- accessory.context.subDevice = subDevice;
128
- this.createAccessory(accessory);
129
128
  this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
130
- return accessory;
131
129
  }
130
+
131
+ this.createAccessoryHandler(accessory);
132
+ return accessory;
132
133
  }
133
134
 
134
- createAccessory(accessory: PlatformAccessory) {
135
+ createAccessoryHandler(accessory: PlatformAccessory) {
135
136
  const device = accessory.context.device;
136
137
  const accessoryType = device.thngModelTypeName;
137
138
 
138
- if (!this.accessoryHandlers.has(accessory.UUID)) {
139
- switch (accessoryType) {
139
+ if (this.accessoryHandlers.has(accessory.UUID)) {
140
+ return;
141
+ }
142
+
143
+ if (accessory.context.subDevice) {
144
+ switch (device.thngModelTypeName) {
140
145
  case 'LIGHT':
141
146
  this.accessoryHandlers.set(accessory.UUID, new LightAccessory(this, accessory));
142
147
  break;
@@ -146,42 +151,107 @@ export class ShomePlatform implements DynamicPlatformPlugin {
146
151
  case 'HEATER':
147
152
  this.accessoryHandlers.set(accessory.UUID, new HeaterAccessory(this, accessory));
148
153
  break;
149
- case 'DOORLOCK':
150
- this.accessoryHandlers.set(accessory.UUID, new DoorlockAccessory(this, accessory));
151
- break;
152
154
  }
155
+ return;
156
+ }
157
+
158
+ switch (accessoryType) {
159
+ case 'DOORLOCK':
160
+ this.accessoryHandlers.set(accessory.UUID, new DoorlockAccessory(this, accessory));
161
+ break;
162
+ case 'DOORBELL':
163
+ this.accessoryHandlers.set(accessory.UUID, new DoorbellAccessory(this, accessory));
164
+ break;
153
165
  }
154
166
  }
155
167
 
156
168
  startPolling() {
157
- this.log.info(`Starting periodic device state polling every ${this.pollingInterval / 1000} seconds.`);
169
+ this.log.info(`Starting periodic state polling every ${this.pollingInterval / 1000} seconds.`);
158
170
  this.pollingTimer = setInterval(async () => {
159
- this.log.debug('Polling for device updates...');
171
+ this.log.debug('Polling for updates...');
160
172
  try {
161
- const devices = await this.shomeClient.getDeviceList();
162
- for (const device of devices) {
163
- if (CONTROLLABLE_MULTI_DEVICE_TYPES.includes(device.thngModelTypeName)) {
164
- const deviceInfoList = await this.shomeClient.getDeviceInfo(device.thngId, device.thngModelTypeName);
165
- if (deviceInfoList) {
166
- for (const subDevice of deviceInfoList) {
167
- const subUuid = this.api.hap.uuid.generate(`${device.thngId}-${subDevice.deviceId}`);
168
- const handler = this.accessoryHandlers.get(subUuid) as LightAccessory | HeaterAccessory | VentilatorAccessory;
169
- if (handler) {
170
- handler.updateState(subDevice);
171
- }
172
- }
173
+ await this.pollDeviceUpdates();
174
+ await this.checkForNewVisitors();
175
+ } catch (error) {
176
+ this.log.error('An error occurred during polling:', error);
177
+ }
178
+ }, this.pollingInterval);
179
+ }
180
+
181
+ async pollDeviceUpdates() {
182
+ const devices = await this.shomeClient.getDeviceList();
183
+ for (const device of devices) {
184
+ if (CONTROLLABLE_MULTI_DEVICE_TYPES.includes(device.thngModelTypeName)) {
185
+ const deviceInfoList = await this.shomeClient.getDeviceInfo(device.thngId, device.thngModelTypeName);
186
+ if (deviceInfoList) {
187
+ for (const subDevice of deviceInfoList) {
188
+ const deviceId = `${device.thngId}-${subDevice.deviceId}`;
189
+ if (this.shomeClient.isDeviceBusy(deviceId)) {
190
+ this.log.debug(`Skipping polling update for ${subDevice.nickname} as it has a pending request.`);
191
+ continue;
173
192
  }
174
- } else if (SPECIAL_CONTROLLABLE_TYPES.includes(device.thngModelTypeName)) {
175
- const uuid = this.api.hap.uuid.generate(device.thngId);
176
- const handler = this.accessoryHandlers.get(uuid) as DoorlockAccessory;
193
+ const subUuid = this.api.hap.uuid.generate(deviceId);
194
+ const handler = this.accessoryHandlers.get(subUuid) as LightAccessory | HeaterAccessory | VentilatorAccessory;
177
195
  if (handler) {
178
- handler.updateState(device);
196
+ handler.updateState(subDevice);
179
197
  }
180
198
  }
181
199
  }
182
- } catch (error) {
183
- this.log.error('An error occurred during polling:', error);
200
+ } else if (SPECIAL_CONTROLLABLE_TYPES.includes(device.thngModelTypeName)) {
201
+ const deviceId = device.thngId;
202
+ if (this.shomeClient.isDeviceBusy(deviceId)) {
203
+ this.log.debug(`Skipping polling update for ${device.nickname} as it has a pending request.`);
204
+ continue;
205
+ }
206
+ const uuid = this.api.hap.uuid.generate(deviceId);
207
+ const handler = this.accessoryHandlers.get(uuid) as DoorlockAccessory;
208
+ if (handler) {
209
+ handler.updateState(device);
210
+ }
184
211
  }
185
- }, this.pollingInterval);
212
+ }
213
+ }
214
+
215
+ async checkForNewVisitors() {
216
+ this.log.debug('Checking for new doorbell events...');
217
+ const visitorList = await this.shomeClient.getVisitorHistory();
218
+ const newVisitors: Visitor[] = [];
219
+
220
+ for (const visitor of visitorList) {
221
+ const visitorTime = this.parseRecodDt(visitor.recodDt);
222
+ if (visitorTime > this.lastCheckedTimestamp) {
223
+ newVisitors.push(visitor);
224
+ }
225
+ }
226
+
227
+ if (newVisitors.length > 0) {
228
+ this.log.info(`Found ${newVisitors.length} new doorbell event(s).`);
229
+ newVisitors.sort((a, b) => a.recodDt.localeCompare(b.recodDt));
230
+
231
+ const doorbellUUID = this.api.hap.uuid.generate('shome-doorbell');
232
+ const doorbellHandler = this.accessoryHandlers.get(doorbellUUID) as DoorbellAccessory | undefined;
233
+
234
+ if (doorbellHandler) {
235
+ for (const visitor of newVisitors) {
236
+ doorbellHandler.newVisitor(visitor);
237
+ }
238
+ } else {
239
+ this.log.warn('Doorbell accessory handler not found.');
240
+ }
241
+
242
+ const latestVisitor = newVisitors[newVisitors.length - 1];
243
+ this.lastCheckedTimestamp = this.parseRecodDt(latestVisitor.recodDt);
244
+ this.log.debug(`Updated last checked timestamp to: ${this.lastCheckedTimestamp.toISOString()}`);
245
+ }
246
+ }
247
+
248
+ private parseRecodDt(recodDt: string): Date {
249
+ const year = parseInt(recodDt.substring(0, 4), 10);
250
+ const month = parseInt(recodDt.substring(4, 6), 10) - 1;
251
+ const day = parseInt(recodDt.substring(6, 8), 10);
252
+ const hour = parseInt(recodDt.substring(8, 10), 10);
253
+ const minute = parseInt(recodDt.substring(10, 12), 10);
254
+ const second = parseInt(recodDt.substring(12, 14), 10);
255
+ return new Date(year, month, day, hour, minute, second);
186
256
  }
187
257
  }