@switchbot/homebridge-switchbot 5.0.0-beta.11 → 5.0.0-beta.13
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/dist/baseMatterAccessory.test.d.ts +2 -0
- package/dist/baseMatterAccessory.test.d.ts.map +1 -0
- package/dist/baseMatterAccessory.test.js +71 -0
- package/dist/baseMatterAccessory.test.js.map +1 -0
- package/dist/devices-matter/BaseMatterAccessory.d.ts +15 -0
- package/dist/devices-matter/BaseMatterAccessory.d.ts.map +1 -1
- package/dist/devices-matter/BaseMatterAccessory.js +120 -0
- package/dist/devices-matter/BaseMatterAccessory.js.map +1 -1
- package/dist/devices-matter/ColorLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ColorLightAccessory.js +12 -12
- package/dist/devices-matter/ColorLightAccessory.js.map +1 -1
- package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ColorTemperatureLightAccessory.js +5 -7
- package/dist/devices-matter/ColorTemperatureLightAccessory.js.map +1 -1
- package/dist/devices-matter/DimmableLightAccessory.js +9 -9
- package/dist/devices-matter/DimmableLightAccessory.js.map +1 -1
- package/dist/devices-matter/ExtendedColorLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ExtendedColorLightAccessory.js +14 -15
- package/dist/devices-matter/ExtendedColorLightAccessory.js.map +1 -1
- package/dist/devices-matter/OnOffLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/OnOffLightAccessory.js +8 -16
- package/dist/devices-matter/OnOffLightAccessory.js.map +1 -1
- package/dist/devices-matter/OnOffOutletAccessory.d.ts +2 -0
- package/dist/devices-matter/OnOffOutletAccessory.d.ts.map +1 -1
- package/dist/devices-matter/OnOffOutletAccessory.js +10 -7
- package/dist/devices-matter/OnOffOutletAccessory.js.map +1 -1
- package/dist/devices-matter/OnOffSwitchAccessory.js +2 -2
- package/dist/devices-matter/OnOffSwitchAccessory.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -63
- package/dist/index.js.map +1 -1
- package/dist/platform-matter.d.ts.map +1 -1
- package/dist/platform-matter.js +37 -22
- package/dist/platform-matter.js.map +1 -1
- package/dist/utils.d.ts +35 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +98 -0
- package/dist/utils.js.map +1 -1
- package/dist/utils.test.d.ts +2 -0
- package/dist/utils.test.d.ts.map +1 -0
- package/dist/utils.test.js +95 -0
- package/dist/utils.test.js.map +1 -0
- package/docs/variables/default.html +1 -1
- package/package.json +1 -1
- package/src/baseMatterAccessory.test.ts +88 -0
- package/src/devices-matter/BaseMatterAccessory.ts +118 -0
- package/src/devices-matter/ColorLightAccessory.ts +12 -12
- package/src/devices-matter/ColorTemperatureLightAccessory.ts +5 -7
- package/src/devices-matter/DimmableLightAccessory.ts +9 -9
- package/src/devices-matter/ExtendedColorLightAccessory.ts +14 -15
- package/src/devices-matter/OnOffLightAccessory.ts +8 -16
- package/src/devices-matter/OnOffOutletAccessory.ts +12 -7
- package/src/devices-matter/OnOffSwitchAccessory.ts +2 -2
- package/src/index.ts +4 -64
- package/src/platform-matter.ts +36 -22
- package/src/utils.test.ts +96 -0
- package/src/utils.ts +97 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { createPlatformProxy, detectMatter } from './utils.js'
|
|
4
|
+
|
|
5
|
+
describe('detectMatter', () => {
|
|
6
|
+
it('returns enabled true when api.isMatterEnabled is a function that returns true', () => {
|
|
7
|
+
const api: any = { isMatterEnabled: () => true }
|
|
8
|
+
const info = detectMatter(api)
|
|
9
|
+
expect(info.enabled).toBe(true)
|
|
10
|
+
expect(info.reason).toMatch(/isMatterEnabled\(\)/)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('returns enabled true when api.isMatterEnabled is a truthy property', () => {
|
|
14
|
+
const api: any = { isMatterEnabled: true }
|
|
15
|
+
const info = detectMatter(api)
|
|
16
|
+
expect(info.enabled).toBe(true)
|
|
17
|
+
expect(info.reason).toMatch(/property present/)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('uses server fallback when present', () => {
|
|
21
|
+
const api: any = { server: { isMatterEnabled: () => false } }
|
|
22
|
+
const info = detectMatter(api)
|
|
23
|
+
expect(info.enabled).toBe(false)
|
|
24
|
+
expect(info.reason).toMatch(/server.isMatterEnabled\(\)/)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('returns enabled false with a reason when no API is present', () => {
|
|
28
|
+
const api: any = {}
|
|
29
|
+
const info = detectMatter(api)
|
|
30
|
+
expect(info.enabled).toBe(false)
|
|
31
|
+
expect(typeof info.reason).toBe('string')
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
describe('createPlatformProxy', () => {
|
|
36
|
+
it('selects HAP platform when Matter is disabled and delegates configureAccessory', () => {
|
|
37
|
+
class HapStub {
|
|
38
|
+
public static created = false
|
|
39
|
+
public configured: any = undefined
|
|
40
|
+
constructor(public log: any, public config: any, public api: any) {
|
|
41
|
+
HapStub.created = true
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
configureAccessory(acc: any) {
|
|
45
|
+
this.configured = acc
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
class MatterStub {
|
|
50
|
+
constructor() {
|
|
51
|
+
throw new Error('should not be constructed')
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const ProxyCtor = createPlatformProxy(HapStub as any, MatterStub as any)
|
|
56
|
+
const log = { info: vi.fn() }
|
|
57
|
+
const api = { isMatterEnabled: false }
|
|
58
|
+
const proxy = new (ProxyCtor as any)(log, {}, api)
|
|
59
|
+
|
|
60
|
+
// delegate should be instance of HapStub
|
|
61
|
+
expect(HapStub.created).toBe(true)
|
|
62
|
+
expect(typeof proxy.delegate.configureAccessory).toBe('function')
|
|
63
|
+
proxy.configureAccessory('accessory')
|
|
64
|
+
expect(proxy.delegate.configured).toBe('accessory')
|
|
65
|
+
// log should mention HAP
|
|
66
|
+
expect((log.info as any).mock.calls[0][0]).toMatch(/HAP/)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('selects Matter platform when isMatterEnabled is true', () => {
|
|
70
|
+
class HapStub2 {
|
|
71
|
+
constructor() {
|
|
72
|
+
throw new Error('should not be constructed')
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
class MatterStub2 {
|
|
77
|
+
public configured: any = undefined
|
|
78
|
+
constructor(public log: any, public config: any, public api: any) {}
|
|
79
|
+
|
|
80
|
+
configureMatterAccessory(acc: any) {
|
|
81
|
+
this.configured = acc
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const ProxyCtor = createPlatformProxy(HapStub2 as any, MatterStub2 as any)
|
|
86
|
+
const log = { info: vi.fn() }
|
|
87
|
+
const api = { isMatterEnabled: () => true }
|
|
88
|
+
const proxy = new (ProxyCtor as any)(log, {}, api)
|
|
89
|
+
|
|
90
|
+
// delegate should be instance of MatterStub2
|
|
91
|
+
expect(typeof proxy.delegate.configureMatterAccessory).toBe('function')
|
|
92
|
+
;(proxy as any).configureMatterAccessory('macc')
|
|
93
|
+
expect(proxy.delegate.configured).toBe('macc')
|
|
94
|
+
expect((log.info as any).mock.calls[0][0]).toMatch(/Matter/)
|
|
95
|
+
})
|
|
96
|
+
})
|
package/src/utils.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
*
|
|
3
3
|
* util.ts: @switchbot/homebridge-switchbot platform class.
|
|
4
4
|
*/
|
|
5
|
+
import type { API } from 'homebridge'
|
|
5
6
|
import type { blindTilt, curtain, curtain3, device } from 'node-switchbot'
|
|
6
7
|
|
|
7
8
|
import type { devicesConfig } from './settings.js'
|
|
@@ -716,3 +717,99 @@ export function cleanDeviceConfig(deviceConfig?: Record<string, Record<string, a
|
|
|
716
717
|
}
|
|
717
718
|
return undefined
|
|
718
719
|
}
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* Detect whether Matter is enabled/available on the provided Homebridge API object.
|
|
723
|
+
* This encapsulates the multi-fallback detection used across the project.
|
|
724
|
+
*/
|
|
725
|
+
/**
|
|
726
|
+
* Detect whether Matter is enabled on the provided Homebridge API object.
|
|
727
|
+
* Returns an object with an `enabled` boolean and an optional `reason` string
|
|
728
|
+
* describing which check matched (useful for diagnostics).
|
|
729
|
+
*/
|
|
730
|
+
export function detectMatter(apiObj: API): { enabled: boolean, reason?: string } {
|
|
731
|
+
try {
|
|
732
|
+
const maybe = (apiObj as any).isMatterEnabled
|
|
733
|
+
if (typeof maybe === 'function') {
|
|
734
|
+
return { enabled: Boolean(maybe.call(apiObj)), reason: 'api.isMatterEnabled() returned truthy' }
|
|
735
|
+
}
|
|
736
|
+
if (typeof maybe !== 'undefined') {
|
|
737
|
+
return { enabled: Boolean(maybe), reason: 'api.isMatterEnabled property present' }
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
const server = (apiObj as any).server ?? (apiObj as any).homebridgeServer ?? (apiObj as any).homebridge_server
|
|
741
|
+
const serverMaybe = server?.isMatterEnabled
|
|
742
|
+
if (typeof serverMaybe === 'function') {
|
|
743
|
+
return { enabled: Boolean(serverMaybe.call(server)), reason: 'server.isMatterEnabled() returned truthy' }
|
|
744
|
+
}
|
|
745
|
+
if (typeof server?.isMatterEnabled !== 'undefined') {
|
|
746
|
+
return { enabled: Boolean(server.isMatterEnabled), reason: 'server.isMatterEnabled property present' }
|
|
747
|
+
}
|
|
748
|
+
} catch (e: any) {
|
|
749
|
+
return { enabled: false, reason: `error during detection: ${String(e?.message ?? e)}` }
|
|
750
|
+
}
|
|
751
|
+
return { enabled: false, reason: 'no isMatterEnabled API or server fallback detected' }
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Backwards-compatible boolean wrapper for detectMatter.
|
|
756
|
+
*/
|
|
757
|
+
export function detectMatterEnabled(apiObj: API): boolean {
|
|
758
|
+
return detectMatter(apiObj).enabled
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Create a Platform proxy class that selects between two platform constructors
|
|
763
|
+
* (HAP vs Matter) at runtime using `detectMatter`. Returns a class suitable
|
|
764
|
+
* for passing to `api.registerPlatform`.
|
|
765
|
+
*/
|
|
766
|
+
export function createPlatformProxy(HAPCtor: any, MatterCtor: any) {
|
|
767
|
+
return class PlatformProxy {
|
|
768
|
+
delegate: any
|
|
769
|
+
|
|
770
|
+
constructor(public readonly log: any, public readonly config: any, public readonly api: API) {
|
|
771
|
+
const matterInfo = detectMatter(this.api)
|
|
772
|
+
const isMatter = matterInfo.enabled
|
|
773
|
+
const reason = matterInfo.reason ? ` Reason: ${matterInfo.reason}` : ''
|
|
774
|
+
this.log.info?.(`Homebridge SwitchBot Plugin initializing in ${isMatter ? 'Matter' : 'HAP'} mode.${reason}`)
|
|
775
|
+
const PlatformCtor = isMatter ? MatterCtor : HAPCtor
|
|
776
|
+
this.delegate = new PlatformCtor(this.log, this.config, this.api)
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
configureAccessory(accessory: any): void {
|
|
780
|
+
try {
|
|
781
|
+
if (this.delegate && typeof this.delegate.configureAccessory === 'function') {
|
|
782
|
+
return this.delegate.configureAccessory(accessory)
|
|
783
|
+
}
|
|
784
|
+
} catch (e) {
|
|
785
|
+
// swallow — preserve previous behaviour where delegate errors don't bubble here
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
configureMatterAccessory?(accessory: any): void {
|
|
790
|
+
try {
|
|
791
|
+
if (this.delegate && typeof this.delegate.configureMatterAccessory === 'function') {
|
|
792
|
+
return this.delegate.configureMatterAccessory(accessory)
|
|
793
|
+
}
|
|
794
|
+
} catch (e) {
|
|
795
|
+
// swallow — delegate may not implement this or may throw
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
get accessories(): any {
|
|
800
|
+
try {
|
|
801
|
+
return this.delegate?.accessories
|
|
802
|
+
} catch (e) {
|
|
803
|
+
return undefined
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
get matterAccessories(): any {
|
|
808
|
+
try {
|
|
809
|
+
return this.delegate?.matterAccessories
|
|
810
|
+
} catch (e) {
|
|
811
|
+
return undefined
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
}
|