@ray-js/lamp-schedule-core 1.0.4-beta-14 → 1.0.5-beta.1

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.
Files changed (34) hide show
  1. package/lib/dpParser/__test__/rhythms.test.js +7 -2
  2. package/lib/dpParser/__test__/rhythmsSigmesh.test.d.ts +1 -0
  3. package/lib/dpParser/__test__/rhythmsSigmesh.test.js +263 -0
  4. package/lib/dpParser/__test__/sleepSigmesh.test.d.ts +1 -0
  5. package/lib/dpParser/__test__/sleepSigmesh.test.js +183 -0
  6. package/lib/dpParser/index.d.ts +1 -1
  7. package/lib/dpParser/index.js +1 -1
  8. package/lib/dpParser/rhythms/index.d.ts +9 -0
  9. package/lib/dpParser/rhythms/index.js +27 -0
  10. package/lib/dpParser/{rhythms.d.ts → rhythms/rhythmsCommon.d.ts} +2 -3
  11. package/lib/dpParser/{rhythms.js → rhythms/rhythmsCommon.js} +6 -9
  12. package/lib/dpParser/rhythms/rhythmsSigmesh.d.ts +17 -0
  13. package/lib/dpParser/rhythms/rhythmsSigmesh.js +143 -0
  14. package/lib/dpParser/sleep/index.d.ts +1 -2
  15. package/lib/dpParser/sleep/index.js +13 -12
  16. package/lib/dpParser/sleep/sleepSigmesh.d.ts +20 -0
  17. package/lib/dpParser/sleep/sleepSigmesh.js +86 -98
  18. package/lib/dpParser/wakeup/index.d.ts +0 -2
  19. package/lib/dpParser/wakeup/index.js +12 -16
  20. package/lib/dpParser/wakeup/wakeupSigmesh.js +9 -1
  21. package/lib/hooks/useBaseLightDp.d.ts +1 -1
  22. package/lib/hooks/useBaseLightDp.js +1 -0
  23. package/lib/hooks/useCommonSupport.js +19 -0
  24. package/lib/hooks/useCycleDp.js +2 -0
  25. package/lib/hooks/useRandomDp.js +2 -0
  26. package/lib/hooks/useRhythmsDp.d.ts +3 -3
  27. package/lib/hooks/useRhythmsDp.js +2 -0
  28. package/lib/hooks/useSleepDp.js +2 -0
  29. package/lib/hooks/useWakeUpDp.js +2 -0
  30. package/lib/hooks/useWakeupDp.js +2 -0
  31. package/lib/types/rhythms.d.ts +16 -0
  32. package/lib/types/rhythms.js +3 -1
  33. package/lib/utils/ScheduleSupport.js +2 -0
  34. package/package.json +1 -1
@@ -71,7 +71,9 @@ describe('RhythmParser', () => {
71
71
  expect(result).toBe('');
72
72
  });
73
73
  it('should return empty string when support instance is missing', () => {
74
- getSupportIns.mockReturnValueOnce(null);
74
+ // getSupportIns is called in both the dispatcher and the common formatter,
75
+ // so we need to mock it for all calls within this test
76
+ getSupportIns.mockReturnValue(null);
75
77
  const result = rhythmParser.formatter({
76
78
  version: 1,
77
79
  power: true,
@@ -91,9 +93,12 @@ describe('RhythmParser', () => {
91
93
  });
92
94
  expect(result).toBe('');
93
95
  expect(scheduleLogger.error).toHaveBeenCalledWith('协议解析 rhythms formatter =====', '数据为空');
96
+ // Restore default mock
97
+ getSupportIns.mockReturnValue(createSupport(true));
94
98
  });
95
99
  it('should force temperature to 100 when device does not support temperature DP', () => {
96
- getSupportIns.mockReturnValueOnce(createSupport(false));
100
+ // getSupportIns is called in both the dispatcher and the common formatter
101
+ getSupportIns.mockReturnValue(createSupport(false));
97
102
  const result = rhythmParser.formatter({
98
103
  version: 0,
99
104
  power: true,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,263 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
2
+ import "core-js/modules/esnext.iterator.map.js";
3
+ jest.mock('@ray-js/panel-sdk/lib/utils', () => ({
4
+ generateDpStrStep: jest.fn(str => {
5
+ let index = 0;
6
+ return len => {
7
+ const segment = str.slice(index, index + len);
8
+ index += len;
9
+ return {
10
+ value: parseInt(segment, 16)
11
+ };
12
+ };
13
+ }),
14
+ numToHexString: jest.fn(num => num.toString(16).padStart(2, '0'))
15
+ }));
16
+ jest.mock('../../utils/ScheduleLogger', () => {
17
+ const logger = {
18
+ debug: jest.fn(),
19
+ warn: jest.fn(),
20
+ error: jest.fn(),
21
+ info: jest.fn()
22
+ };
23
+ return {
24
+ scheduleLogger: logger
25
+ };
26
+ });
27
+ jest.mock('../../hooks/useCommonSupport', () => ({
28
+ getSupportIns: jest.fn()
29
+ }));
30
+ jest.mock('../../utils/getDPByProtocol', () => ({
31
+ getDPByProtocol: jest.fn().mockReturnValue({
32
+ TEMPERATURE: 'temp_value'
33
+ })
34
+ }));
35
+ import { rhythmParserSigmesh, RhythmSigmesh } from '../rhythms/rhythmsSigmesh';
36
+ const {
37
+ getSupportIns
38
+ } = require('../../hooks/useCommonSupport');
39
+ const createSupport = function () {
40
+ let isSupportTemp = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
41
+ return {
42
+ isSigMeshDevice: jest.fn().mockReturnValue(true),
43
+ isSupportDp: jest.fn().mockImplementation(dp => {
44
+ if (dp === 'temp_value') {
45
+ return isSupportTemp;
46
+ }
47
+ return true;
48
+ })
49
+ };
50
+ };
51
+
52
+ /**
53
+ * 构建 sigmesh rhythms DP 字符串
54
+ * 格式: version(2) + power(2) + mode(2) + weeks(2) + paramMode(2) + number(2)
55
+ * + nodes[valid(2) + hour(2) + minute(2) + brightness(2) + temperature(2)]
56
+ */
57
+ const buildDpStr = function (nodes) {
58
+ let version = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
59
+ let power = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
60
+ let mode = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
61
+ let weeks = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0x7f;
62
+ let paramMode = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
63
+ const header = [version, power, mode, weeks, paramMode, nodes.length].map(v => v.toString(16).padStart(2, '0')).join('');
64
+ const body = nodes.map(node => [node.valid, node.hour, node.minute, node.brightness, node.temperature].map(v => v.toString(16).padStart(2, '0')).join('')).join('');
65
+ return `${header}${body}`;
66
+ };
67
+ describe('RhythmSigmesh parser & formatter', () => {
68
+ beforeEach(() => {
69
+ jest.clearAllMocks();
70
+ getSupportIns.mockReturnValue(createSupport(true));
71
+ });
72
+ describe('parser', () => {
73
+ it('returns default value when dp string is empty', () => {
74
+ const result = rhythmParserSigmesh.parser('');
75
+ expect(result).toEqual(new RhythmSigmesh().defaultValue);
76
+ });
77
+ it('returns default value when dp string length is invalid', () => {
78
+ // Too short
79
+ const result = rhythmParserSigmesh.parser('010100');
80
+ expect(result).toEqual(new RhythmSigmesh().defaultValue);
81
+ });
82
+ it('returns default value when node data is not aligned', () => {
83
+ // Header (12 chars) + partial node data (not multiple of 10)
84
+ // 14 chars header + 2 chars body (not 10)
85
+ const result = rhythmParserSigmesh.parser('01010000007f0104' + '01');
86
+ expect(result).toEqual(new RhythmSigmesh().defaultValue);
87
+ });
88
+ it('parses valid dp string with 4 nodes', () => {
89
+ const dpStr = buildDpStr([{
90
+ valid: 1,
91
+ hour: 6,
92
+ minute: 30,
93
+ brightness: 100,
94
+ temperature: 50
95
+ }, {
96
+ valid: 1,
97
+ hour: 11,
98
+ minute: 30,
99
+ brightness: 100,
100
+ temperature: 100
101
+ }, {
102
+ valid: 1,
103
+ hour: 17,
104
+ minute: 0,
105
+ brightness: 70,
106
+ temperature: 50
107
+ }, {
108
+ valid: 1,
109
+ hour: 20,
110
+ minute: 30,
111
+ brightness: 70,
112
+ temperature: 50
113
+ }]);
114
+ const result = rhythmParserSigmesh.parser(dpStr);
115
+ expect(result.version).toBe(1);
116
+ expect(result.power).toBe(true);
117
+ expect(result.mode).toBe(0);
118
+ expect(result.paramMode).toBe(1);
119
+ expect(result.number).toBe(4);
120
+ expect(result.rhythms).toHaveLength(4);
121
+ expect(result.rhythms[0]).toMatchObject({
122
+ power: true,
123
+ hour: 6,
124
+ minute: 30,
125
+ brightness: 100,
126
+ temperature: 50
127
+ });
128
+ expect(result.rhythms[3]).toMatchObject({
129
+ power: true,
130
+ hour: 20,
131
+ minute: 30,
132
+ brightness: 70,
133
+ temperature: 50
134
+ });
135
+ });
136
+ it('parses power=false correctly', () => {
137
+ const dpStr = buildDpStr([{
138
+ valid: 0,
139
+ hour: 8,
140
+ minute: 0,
141
+ brightness: 50,
142
+ temperature: 30
143
+ }], 1, 0);
144
+ const result = rhythmParserSigmesh.parser(dpStr);
145
+ expect(result.power).toBe(false);
146
+ expect(result.rhythms[0].power).toBe(false);
147
+ });
148
+ });
149
+ describe('formatter', () => {
150
+ it('returns empty string when data is null', () => {
151
+ const result = rhythmParserSigmesh.formatter(null);
152
+ expect(result).toBe('');
153
+ });
154
+ it('returns empty string when support is null', () => {
155
+ getSupportIns.mockReturnValueOnce(null);
156
+ const result = rhythmParserSigmesh.formatter({
157
+ version: 1,
158
+ power: true,
159
+ mode: 0,
160
+ weeks: [1, 1, 1, 1, 1, 1, 1, 0],
161
+ paramMode: 1,
162
+ number: 1,
163
+ rhythms: [{
164
+ power: true,
165
+ hour: 6,
166
+ minute: 30,
167
+ brightness: 100,
168
+ temperature: 50
169
+ }]
170
+ });
171
+ expect(result).toBe('');
172
+ });
173
+ it('formats valid data to dp string', () => {
174
+ const result = rhythmParserSigmesh.formatter({
175
+ version: 1,
176
+ power: true,
177
+ mode: 0,
178
+ weeks: [1, 1, 1, 1, 1, 1, 1, 0],
179
+ paramMode: 1,
180
+ number: 2,
181
+ rhythms: [{
182
+ power: true,
183
+ hour: 6,
184
+ minute: 30,
185
+ brightness: 100,
186
+ temperature: 50
187
+ }, {
188
+ power: false,
189
+ hour: 20,
190
+ minute: 0,
191
+ brightness: 70,
192
+ temperature: 30
193
+ }]
194
+ });
195
+ const expected = buildDpStr([{
196
+ valid: 1,
197
+ hour: 6,
198
+ minute: 30,
199
+ brightness: 100,
200
+ temperature: 50
201
+ }, {
202
+ valid: 0,
203
+ hour: 20,
204
+ minute: 0,
205
+ brightness: 70,
206
+ temperature: 30
207
+ }], 1, 1, 0, 0x7f, 1);
208
+ expect(result).toBe(expected);
209
+ });
210
+ it('forces temperature to 100 when device does not support temperature DP', () => {
211
+ getSupportIns.mockReturnValueOnce(createSupport(false));
212
+ const result = rhythmParserSigmesh.formatter({
213
+ version: 1,
214
+ power: true,
215
+ mode: 0,
216
+ weeks: [1, 1, 1, 1, 1, 1, 1, 0],
217
+ paramMode: 1,
218
+ number: 1,
219
+ rhythms: [{
220
+ power: true,
221
+ hour: 6,
222
+ minute: 0,
223
+ brightness: 50,
224
+ temperature: 30
225
+ }]
226
+ });
227
+ // temperature should be 100 (0x64), not 30 (0x1e)
228
+ expect(result.slice(-2)).toBe('64');
229
+ });
230
+ });
231
+ describe('round-trip', () => {
232
+ it('round-trips dp string through parser and formatter', () => {
233
+ const dpStr = buildDpStr([{
234
+ valid: 1,
235
+ hour: 6,
236
+ minute: 30,
237
+ brightness: 100,
238
+ temperature: 50
239
+ }, {
240
+ valid: 1,
241
+ hour: 11,
242
+ minute: 30,
243
+ brightness: 100,
244
+ temperature: 100
245
+ }, {
246
+ valid: 1,
247
+ hour: 17,
248
+ minute: 0,
249
+ brightness: 70,
250
+ temperature: 50
251
+ }, {
252
+ valid: 1,
253
+ hour: 20,
254
+ minute: 30,
255
+ brightness: 70,
256
+ temperature: 50
257
+ }]);
258
+ const parsed = rhythmParserSigmesh.parser(dpStr);
259
+ const formatted = rhythmParserSigmesh.formatter(parsed);
260
+ expect(formatted).toBe(dpStr);
261
+ });
262
+ });
263
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,183 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
2
+ import "core-js/modules/esnext.iterator.map.js";
3
+ jest.mock('@ray-js/panel-sdk/lib/utils', () => ({
4
+ generateDpStrStep: jest.fn(str => {
5
+ let index = 0;
6
+ return len => {
7
+ const segment = str.slice(index, index + len);
8
+ index += len;
9
+ return {
10
+ value: parseInt(segment, 16)
11
+ };
12
+ };
13
+ }),
14
+ numToHexString: jest.fn(num => num.toString(16).padStart(2, '0'))
15
+ }));
16
+ import { sleepParserSigmesh, SleepSigmesh } from '../sleep/sleepSigmesh';
17
+ const loopsToHex = loops => {
18
+ const binary = loops.split('').reverse().join('');
19
+ return parseInt(binary, 2);
20
+ };
21
+
22
+ /**
23
+ * 构建 sigmesh sleep DP 字符串
24
+ * 格式: version(2) + dataMode(2) + length(2) + nodes[onOff(2) + loops(2) + step(2) + hour(2) + minute(2) + brightness(2) + temperature(2)]
25
+ * 注意: sleep 模式不含 duration 字段(与 wakeup 的区别)
26
+ */
27
+ const buildDpStr = function (nodes) {
28
+ let version = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
29
+ let dataMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
30
+ const header = [version, dataMode, nodes.length].map(v => v.toString(16).padStart(2, '0')).join('');
31
+ const body = nodes.map(node => [node.onOff, node.loops, node.step, node.hour, node.minute, node.brightness, node.temperature].map(v => v.toString(16).padStart(2, '0')).join('')).join('');
32
+ return `${header}${body}`;
33
+ };
34
+ describe('SleepSigmesh parser & formatter', () => {
35
+ beforeEach(() => {
36
+ jest.clearAllMocks();
37
+ });
38
+ it('returns default value when dp string is empty', () => {
39
+ expect(sleepParserSigmesh.parser('')).toEqual(new SleepSigmesh().defaultValue);
40
+ });
41
+ it('returns default value when dp string length invalid', () => {
42
+ // header + incomplete node data (not multiple of 14 after header)
43
+
44
+ expect(sleepParserSigmesh.parser('01020112345')).toEqual(new SleepSigmesh().defaultValue);
45
+ });
46
+ it('parses valid dp string into nodes', () => {
47
+ const nodes = [{
48
+ onOff: 1,
49
+ loops: loopsToHex('1000000'),
50
+ step: 3,
51
+ hour: 6,
52
+ minute: 30,
53
+ brightness: 80,
54
+ temperature: 90
55
+ }, {
56
+ onOff: 0,
57
+ loops: loopsToHex('0100000'),
58
+ step: 5,
59
+ hour: 7,
60
+ minute: 45,
61
+ brightness: 60,
62
+ temperature: 70
63
+ }];
64
+ const dpStr = buildDpStr(nodes, 1, 2);
65
+ const result = sleepParserSigmesh.parser(dpStr);
66
+ expect(result.version).toBe(1);
67
+ expect(result.dataMode).toBe(2);
68
+ expect(result.length).toBe(2);
69
+ expect(result.nodes).toHaveLength(2);
70
+ expect(result.nodes[0]).toMatchObject({
71
+ onOff: true,
72
+ loops: '1000000',
73
+ step: 3,
74
+ hour: 6,
75
+ minute: 30,
76
+ brightness: 80,
77
+ temperature: 90,
78
+ index: 0
79
+ });
80
+ expect(result.nodes[1]).toMatchObject({
81
+ onOff: false,
82
+ loops: '0100000',
83
+ step: 5,
84
+ hour: 7,
85
+ minute: 45,
86
+ brightness: 60,
87
+ temperature: 70,
88
+ index: 1
89
+ });
90
+ });
91
+ it('does NOT parse duration field (sleep has no duration)', () => {
92
+ const nodes = [{
93
+ onOff: 1,
94
+ loops: loopsToHex('1111111'),
95
+ step: 2,
96
+ hour: 22,
97
+ minute: 0,
98
+ brightness: 50,
99
+ temperature: 30
100
+ }];
101
+ const dpStr = buildDpStr(nodes, 1, 1);
102
+ const result = sleepParserSigmesh.parser(dpStr);
103
+
104
+ // The parsed node should NOT have a duration field
105
+ expect(result.nodes[0]).not.toHaveProperty('duration');
106
+ expect(result.nodes).toHaveLength(1);
107
+ });
108
+ it('formats nodes back to dp string', () => {
109
+ const result = sleepParserSigmesh.formatter({
110
+ version: 1,
111
+ dataMode: '03',
112
+ length: 1,
113
+ nodes: [{
114
+ onOff: true,
115
+ loops: '1000000',
116
+ step: 10,
117
+ hour: 5,
118
+ minute: 15,
119
+ brightness: 90,
120
+ temperature: 50,
121
+ index: 0
122
+ }]
123
+ });
124
+ expect(result).toBe(buildDpStr([{
125
+ onOff: 1,
126
+ loops: loopsToHex('1000000'),
127
+ step: 10,
128
+ hour: 5,
129
+ minute: 15,
130
+ brightness: 90,
131
+ temperature: 50
132
+ }], 1, 3));
133
+ });
134
+ it('round-trips dp string through parser and formatter', () => {
135
+ const nodes = [{
136
+ onOff: 1,
137
+ loops: loopsToHex('1111111'),
138
+ step: 2,
139
+ hour: 12,
140
+ minute: 0,
141
+ brightness: 100,
142
+ temperature: 40
143
+ }];
144
+ const dpStr = buildDpStr(nodes, 2, 3);
145
+ const parsed = sleepParserSigmesh.parser(dpStr);
146
+ const formatted = sleepParserSigmesh.formatter(parsed);
147
+ expect(formatted).toBe(dpStr);
148
+ });
149
+ it('handles multiple nodes correctly', () => {
150
+ const nodes = [{
151
+ onOff: 1,
152
+ loops: loopsToHex('1010101'),
153
+ step: 1,
154
+ hour: 21,
155
+ minute: 30,
156
+ brightness: 80,
157
+ temperature: 60
158
+ }, {
159
+ onOff: 1,
160
+ loops: loopsToHex('0101010'),
161
+ step: 4,
162
+ hour: 22,
163
+ minute: 0,
164
+ brightness: 40,
165
+ temperature: 20
166
+ }, {
167
+ onOff: 0,
168
+ loops: loopsToHex('0000000'),
169
+ step: 6,
170
+ hour: 23,
171
+ minute: 15,
172
+ brightness: 10,
173
+ temperature: 100
174
+ }];
175
+ const dpStr = buildDpStr(nodes, 1, 1);
176
+ const parsed = sleepParserSigmesh.parser(dpStr);
177
+ expect(parsed.nodes).toHaveLength(3);
178
+ expect(parsed.nodes[2].onOff).toBe(false);
179
+ expect(parsed.nodes[2].brightness).toBe(10);
180
+ const formatted = sleepParserSigmesh.formatter(parsed);
181
+ expect(formatted).toBe(dpStr);
182
+ });
183
+ });
@@ -2,7 +2,7 @@
2
2
  import { scheduleDpCodes } from '../config/dpCodes';
3
3
  export { randomParser, getRandomParser } from './random';
4
4
  export { rhythmParser, getRhythmParser } from './rhythms';
5
- export { sleepParserCommon as sleepParser, getSleepParser, SleepParser } from './sleep';
5
+ export { sleepParserCommon as sleepParser, getSleepParser, SleepParser, sleepParserSigmesh, } from './sleep';
6
6
  export { rtcTimerParser, getRtcParser } from './rtcTimer';
7
7
  export { cycleParser, getCycleParser } from './cycle';
8
8
  export { wakeupParserCommon as wakeupParser, getWakeUpParser, WakeUpParser } from './wakeup';
@@ -9,7 +9,7 @@ import { timerReportParser } from './timerReport';
9
9
  import { getWakeUpParser } from './wakeup';
10
10
  export { randomParser, getRandomParser } from './random';
11
11
  export { rhythmParser, getRhythmParser } from './rhythms';
12
- export { sleepParserCommon as sleepParser, getSleepParser, SleepParser } from './sleep';
12
+ export { sleepParserCommon as sleepParser, getSleepParser, SleepParser, sleepParserSigmesh } from './sleep';
13
13
  export { rtcTimerParser, getRtcParser } from './rtcTimer';
14
14
  export { cycleParser, getCycleParser } from './cycle';
15
15
  export { wakeupParserCommon as wakeupParser, getWakeUpParser, WakeUpParser } from './wakeup';
@@ -0,0 +1,9 @@
1
+ import { TRhythmData, TRhythmDataSigmesh } from '../../types/rhythms';
2
+ export { default as RhythmFormatter, rhythmParserCommon } from './rhythmsCommon';
3
+ export { RhythmSigmesh, rhythmParserSigmesh } from './rhythmsSigmesh';
4
+ declare class RhythmParserDispatcher {
5
+ parser(dpValue: string): TRhythmData | TRhythmDataSigmesh;
6
+ formatter(data: TRhythmData | TRhythmDataSigmesh): string;
7
+ }
8
+ export declare const rhythmParser: RhythmParserDispatcher;
9
+ export declare const getRhythmParser: () => RhythmParserDispatcher;
@@ -0,0 +1,27 @@
1
+ import { getSupportIns } from '../../hooks/useCommonSupport';
2
+ export { default as RhythmFormatter, rhythmParserCommon } from './rhythmsCommon';
3
+ export { RhythmSigmesh, rhythmParserSigmesh } from './rhythmsSigmesh';
4
+ import { rhythmParserCommon } from './rhythmsCommon';
5
+ import { rhythmParserSigmesh } from './rhythmsSigmesh';
6
+ class RhythmParserDispatcher {
7
+ parser(dpValue) {
8
+ const support = getSupportIns();
9
+ const isSigmesh = support === null || support === void 0 ? void 0 : support.isSigMeshDevice();
10
+ if (isSigmesh) {
11
+ return rhythmParserSigmesh.parser(dpValue);
12
+ }
13
+ return rhythmParserCommon.parser(dpValue);
14
+ }
15
+ formatter(data) {
16
+ const support = getSupportIns();
17
+ const isSigmesh = support === null || support === void 0 ? void 0 : support.isSigMeshDevice();
18
+ if (isSigmesh) {
19
+ return rhythmParserSigmesh.formatter(data);
20
+ }
21
+ return rhythmParserCommon.formatter(data);
22
+ }
23
+ }
24
+ export const rhythmParser = new RhythmParserDispatcher();
25
+ export const getRhythmParser = () => {
26
+ return rhythmParser;
27
+ };
@@ -1,4 +1,4 @@
1
- import { TRhythmData } from '../types/rhythms';
1
+ import { TRhythmData } from '../../types/rhythms';
2
2
  export default class RhythmFormatter {
3
3
  uuid: string;
4
4
  defaultValue: any;
@@ -6,5 +6,4 @@ export default class RhythmFormatter {
6
6
  parser(dpValue?: string): any;
7
7
  formatter(data: TRhythmData): string;
8
8
  }
9
- export declare const rhythmParser: RhythmFormatter;
10
- export declare const getRhythmParser: () => RhythmFormatter;
9
+ export declare const rhythmParserCommon: RhythmFormatter;
@@ -2,11 +2,11 @@ import "core-js/modules/esnext.iterator.constructor.js";
2
2
  import "core-js/modules/esnext.iterator.map.js";
3
3
  import { generateDpStrStep, numToHexString } from '@ray-js/panel-sdk/lib/utils';
4
4
  import { padStart } from 'lodash-es';
5
- import { defaultValue } from '../config/rhythms/defaultValue';
6
- import { scheduleDpCodes } from '../config/dpCodes';
7
- import { scheduleLogger as ScheduleLogger } from '../utils/ScheduleLogger';
8
- import { getSupportIns } from '../hooks/useCommonSupport';
9
- import { getDPByProtocol } from '../utils/getDPByProtocol';
5
+ import { defaultValue } from '../../config/rhythms/defaultValue';
6
+ import { scheduleDpCodes } from '../../config/dpCodes';
7
+ import { scheduleLogger as ScheduleLogger } from '../../utils/ScheduleLogger';
8
+ import { getSupportIns } from '../../hooks/useCommonSupport';
9
+ import { getDPByProtocol } from '../../utils/getDPByProtocol';
10
10
  const {
11
11
  RHYTHM_MODE
12
12
  } = scheduleDpCodes;
@@ -120,7 +120,4 @@ export default class RhythmFormatter {
120
120
  }).join('')}`;
121
121
  }
122
122
  }
123
- export const rhythmParser = new RhythmFormatter();
124
- export const getRhythmParser = () => {
125
- return rhythmParser;
126
- };
123
+ export const rhythmParserCommon = new RhythmFormatter();
@@ -0,0 +1,17 @@
1
+ import { TRhythmDataSigmesh } from '../../types/rhythms';
2
+ export declare class RhythmSigmesh {
3
+ defaultValue: TRhythmDataSigmesh;
4
+ /**
5
+ * 解析 sigmesh 生物节律 DP 字符串
6
+ * 格式: version(2) + power(2) + mode(2) + weeks(2) + paramMode(2) + number(2) + nodes[valid(2) + hour(2) + minute(2) + brightness(2) + temperature(2)]
7
+ */
8
+ parser(dpValue: string): TRhythmDataSigmesh;
9
+ /**
10
+ * 将 sigmesh 生物节律数据编码为 DP 字符串
11
+ */
12
+ formatter(data: TRhythmDataSigmesh): string;
13
+ }
14
+ export declare const rhythmParserSigmesh: {
15
+ parser: (dpValue: string) => TRhythmDataSigmesh;
16
+ formatter: (dpData: TRhythmDataSigmesh) => string;
17
+ };
@@ -0,0 +1,143 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
2
+ import "core-js/modules/esnext.iterator.map.js";
3
+ /* eslint-disable no-console */
4
+ import { generateDpStrStep, numToHexString } from '@ray-js/panel-sdk/lib/utils';
5
+ import { padStart } from 'lodash-es';
6
+ import { scheduleLogger, scheduleLogger as ScheduleLogger } from '../../utils/ScheduleLogger';
7
+ import { getSupportIns } from '../../hooks/useCommonSupport';
8
+ import { getDPByProtocol } from '../../utils/getDPByProtocol';
9
+ const to16 = num => {
10
+ return numToHexString(num);
11
+ };
12
+ const defaultSigmeshRhythmsValue = {
13
+ version: 1,
14
+ power: false,
15
+ mode: 0,
16
+ weeks: [1, 1, 1, 1, 1, 1, 1, 0],
17
+ paramMode: 1,
18
+ number: 4,
19
+ rhythms: [{
20
+ power: true,
21
+ hour: 6,
22
+ minute: 30,
23
+ brightness: 100,
24
+ temperature: 50
25
+ }, {
26
+ power: true,
27
+ hour: 11,
28
+ minute: 30,
29
+ brightness: 100,
30
+ temperature: 100
31
+ }, {
32
+ power: true,
33
+ hour: 17,
34
+ minute: 0,
35
+ brightness: 70,
36
+ temperature: 50
37
+ }, {
38
+ power: true,
39
+ hour: 20,
40
+ minute: 30,
41
+ brightness: 70,
42
+ temperature: 50
43
+ }]
44
+ };
45
+ export class RhythmSigmesh {
46
+ defaultValue = (() => defaultSigmeshRhythmsValue)();
47
+
48
+ /**
49
+ * 解析 sigmesh 生物节律 DP 字符串
50
+ * 格式: version(2) + power(2) + mode(2) + weeks(2) + paramMode(2) + number(2) + nodes[valid(2) + hour(2) + minute(2) + brightness(2) + temperature(2)]
51
+ */
52
+ parser(dpValue) {
53
+ scheduleLogger.debug('Sigmesh dpParser ===> RhythmSigmesh parser: dpValue', dpValue);
54
+ if (!dpValue) {
55
+ ScheduleLogger.warn('dpParser ===> RhythmSigmesh parser: dpValue is empty');
56
+ return this.defaultValue;
57
+ }
58
+
59
+ // 头部 12 hex chars (6 字段 x 2), 每个节点 10 hex chars (5 字段 x 2)
60
+ if (dpValue.length < 12 || (dpValue.length - 12) % 10 !== 0) {
61
+ ScheduleLogger.warn('dpParser ===> RhythmSigmesh parser: dpValue length invalid', dpValue.length);
62
+ return this.defaultValue;
63
+ }
64
+ try {
65
+ const step = generateDpStrStep(dpValue);
66
+ const version = step(2).value;
67
+ const power = !!step(2).value;
68
+ const mode = step(2).value;
69
+ const weekNum = step(2).value;
70
+ const weeks = padStart(Number(weekNum).toString(2), 8, '0').split('').reverse().map(v => parseInt(v, 10));
71
+ const paramMode = step(2).value;
72
+ const number = step(2).value;
73
+ const rhythms = [];
74
+ for (let i = 0; i < number; i++) {
75
+ const valid = !!step(2).value;
76
+ const hour = step(2).value;
77
+ const minute = step(2).value;
78
+ const brightness = step(2).value;
79
+ const temperature = step(2).value;
80
+ rhythms.push({
81
+ power: valid,
82
+ hour,
83
+ minute,
84
+ brightness,
85
+ temperature
86
+ });
87
+ }
88
+ return {
89
+ version,
90
+ power,
91
+ mode,
92
+ weeks,
93
+ paramMode,
94
+ number,
95
+ rhythms
96
+ };
97
+ } catch (err) {
98
+ ScheduleLogger.error('dpParser ===> RhythmSigmesh parser error', err);
99
+ return this.defaultValue;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * 将 sigmesh 生物节律数据编码为 DP 字符串
105
+ */
106
+ formatter(data) {
107
+ scheduleLogger.debug('Sigmesh dpParser ===> RhythmSigmesh formatter: data', data);
108
+ const support = getSupportIns();
109
+ if (!data || !support) {
110
+ ScheduleLogger.error('dpParser ===> RhythmSigmesh formatter: data or support is empty');
111
+ return '';
112
+ }
113
+ try {
114
+ const {
115
+ power,
116
+ mode,
117
+ weeks,
118
+ rhythms
119
+ } = data;
120
+ const weekStr = [...weeks].reverse().join('').padStart(8, '0');
121
+ const number = rhythms.length;
122
+ const weeksValue = parseInt(weekStr, 2);
123
+
124
+ // 兼容 matter 设备,需要获取 dpCodes 来判断是否支持色温
125
+ const dpCodes = getDPByProtocol();
126
+ const isSupportWhiteTemp = support.isSupportDp(dpCodes.TEMPERATURE);
127
+ return `${to16(1)}${to16(Number(power))}${to16(mode)}${to16(weeksValue)}${to16(1)}${to16(number)}${rhythms.map(_ref => {
128
+ let {
129
+ power: valid,
130
+ hour,
131
+ minute,
132
+ brightness,
133
+ temperature
134
+ } = _ref;
135
+ return `${to16(Number(valid))}${to16(hour)}${to16(minute)}${to16(brightness)}${to16(isSupportWhiteTemp ? temperature : 100)}`;
136
+ }).join('')}`;
137
+ } catch (err) {
138
+ ScheduleLogger.error('dpParser ===> RhythmSigmesh formatter error', err);
139
+ return '';
140
+ }
141
+ }
142
+ }
143
+ export const rhythmParserSigmesh = new RhythmSigmesh();
@@ -1,8 +1,7 @@
1
- import { Support } from '../../utils/ScheduleSupport';
2
1
  export { sleepParser as sleepParserCommon, Sleep as SleepCommon } from './sleepCommon';
2
+ export { sleepParserSigmesh, SleepSigmesh } from './sleepSigmesh';
3
3
  import { TSleepDataSigmesh, TSleepData } from '../../types';
4
4
  export declare class SleepParser {
5
- support: Support;
6
5
  parser(dpStr: string): TSleepData | TSleepDataSigmesh;
7
6
  formatter(dpData: TSleepDataSigmesh | TSleepData): string;
8
7
  }
@@ -1,22 +1,23 @@
1
+ import { getSupportIns } from '../../hooks/useCommonSupport';
1
2
  export { sleepParser as sleepParserCommon, Sleep as SleepCommon } from './sleepCommon';
3
+ export { sleepParserSigmesh, SleepSigmesh } from './sleepSigmesh';
2
4
  import { sleepParser as sleepParserCommon } from './sleepCommon';
5
+ import { sleepParserSigmesh } from './sleepSigmesh';
3
6
  export class SleepParser {
4
7
  parser(dpStr) {
5
- // FIXME: 暂时不支持 Sigmesh 设备
6
- // const support = getSupportIns();
7
- // const isSigmesh = support.isSigMeshDevice();
8
- // if (isSigmesh) {
9
- // return sleepParserSigmesh.parser(dpStr) as TSleepDataSigmesh;
10
- // }
8
+ const support = getSupportIns();
9
+ const isSigmesh = support === null || support === void 0 ? void 0 : support.isSigMeshDevice();
10
+ if (isSigmesh) {
11
+ return sleepParserSigmesh.parser(dpStr);
12
+ }
11
13
  return sleepParserCommon.parser(dpStr);
12
14
  }
13
15
  formatter(dpData) {
14
- // FIXME: 暂时不支持 Sigmesh 设备
15
- // const support = getSupportIns();
16
- // const isSigmesh = support.isSigMeshDevice();
17
- // if (isSigmesh) {
18
- // return sleepParserSigmesh.formatter(dpData as TSleepDataSigmesh);
19
- // }
16
+ const support = getSupportIns();
17
+ const isSigmesh = support === null || support === void 0 ? void 0 : support.isSigMeshDevice();
18
+ if (isSigmesh) {
19
+ return sleepParserSigmesh.formatter(dpData);
20
+ }
20
21
  return sleepParserCommon.formatter(dpData);
21
22
  }
22
23
  }
@@ -0,0 +1,20 @@
1
+ import { TSleepDataSigmesh, TSleepNodeSigmesh } from '../../types';
2
+ export declare class SleepSigmesh {
3
+ defaultValue: TSleepDataSigmesh;
4
+ /**
5
+ * 解析 sigmesh 助眠 DP 字符串
6
+ * 格式: version(2) + dataMode(2) + length(2) + nodes[onOff(2) + loops(2) + step(2) + hour(2) + minute(2) + brightness(2) + temperature(2)]
7
+ * 每个节点 7 字段 x 2 hex = 14 hex chars
8
+ */
9
+ parser(dpStr: string): {
10
+ version: any;
11
+ dataMode: any;
12
+ length: any;
13
+ nodes: TSleepNodeSigmesh[];
14
+ };
15
+ formatter(data: TSleepDataSigmesh): string;
16
+ }
17
+ export declare const sleepParserSigmesh: {
18
+ parser: (dpValue: string) => TSleepDataSigmesh;
19
+ formatter: (dpData: TSleepDataSigmesh) => string;
20
+ };
@@ -1,101 +1,89 @@
1
- // /* eslint-disable no-console */
2
- // import { generateDpStrStep, numToHexString } from '@ray-js/panel-sdk/lib/utils';
3
- // import { padEnd } from 'lodash-es';
1
+ import "core-js/modules/esnext.iterator.constructor.js";
2
+ import "core-js/modules/esnext.iterator.for-each.js";
3
+ /* eslint-disable no-console */
4
+ import { generateDpStrStep, numToHexString } from '@ray-js/panel-sdk/lib/utils';
5
+ import { padEnd } from 'lodash-es';
6
+ import { scheduleLogger } from '../../utils/ScheduleLogger';
7
+ export class SleepSigmesh {
8
+ defaultValue = {
9
+ version: 0,
10
+ dataMode: '01',
11
+ length: 0,
12
+ nodes: []
13
+ };
4
14
 
5
- // import { TSleepDataSigmesh, TSleepNodeSigmesh } from '../../types';
6
- // import { isInIDEFun } from '../../utils/isInIDE';
15
+ /**
16
+ * 解析 sigmesh 助眠 DP 字符串
17
+ * 格式: version(2) + dataMode(2) + length(2) + nodes[onOff(2) + loops(2) + step(2) + hour(2) + minute(2) + brightness(2) + temperature(2)]
18
+ * 每个节点 7 字段 x 2 hex = 14 hex chars
19
+ */
20
+ parser(dpStr) {
21
+ scheduleLogger.debug('Sigmesh dpParser ===> SleepSigmesh parser: dpStr', dpStr);
22
+ if (!dpStr) {
23
+ return this.defaultValue;
24
+ }
25
+ // 头部 6 hex chars (3 字段 x 2), 每个节点 14 hex chars (7 字段 x 2)
26
+ if (dpStr.slice(6).length % 14 !== 0) {
27
+ return this.defaultValue;
28
+ }
29
+ const step = generateDpStrStep(dpStr);
30
+ const version = step(2).value; // 版本号
31
+ const dataMode = step(2).value; // 参数模式 0x01:仅含BT 0x02:仅含HSV 0x03:含HSVBT
32
+ const length = step(2).value; // 任务节点数 0x01:1 个节点 0x02:2 个节点 0x03:3 个节点 0x04:4 个节点
33
+ const nodes = [];
7
34
 
8
- // export class SleepSigmesh {
9
- // defaultValue: TSleepDataSigmesh = {
10
- // version: 0,
11
- // dataMode: '01',
12
- // length: 0,
13
- // nodes: [],
14
- // };
35
+ // 解析循环节点数据
36
+ for (let i = 0; i < length; i++) {
37
+ var _loopNum$toString;
38
+ const onOff = !!step(2).value;
39
+ const loopNum = step(2).value;
40
+ const loops = padEnd(loopNum === null || loopNum === void 0 || (_loopNum$toString = loopNum.toString(2)) === null || _loopNum$toString === void 0 ? void 0 : _loopNum$toString.split('').reverse().join(''), 7, '0');
41
+ const stepGrad = step(2).value;
42
+ const hour = step(2).value;
43
+ const minute = step(2).value;
44
+ const brightness = step(2).value;
45
+ const temperature = step(2).value;
46
+ // 注意: sleep 模式不含 duration 字段(与 wakeup 的区别)
15
47
 
16
- // parser(dpStr: string) {
17
- // if (!dpStr) {
18
- // return this.defaultValue;
19
- // }
20
- // if (dpStr.slice(6).length % 8 !== 0) {
21
- // return this.defaultValue;
22
- // }
23
- // const step = generateDpStrStep(dpStr);
24
-
25
- // const version = step(2).value; // 版本号
26
- // const dataMode = step(2).value; // 参数模式 0x01:仅含BT 0x02:仅含HSV 0x03:含HSVBT
27
- // const length = step(2).value; // 任务节点数 0x01:1 个节点 0x02:2 个节点 0x03:3 个节点 0x04:4 个节点
28
- // const nodes: TSleepNodeSigmesh[] = [];
29
-
30
- // // 解析循环节点数据
31
- // for (let i = 0; i < length; i++) {
32
- // const onOff = !!step(2).value;
33
- // const loopNum = step(2).value;
34
- // const loops = padEnd(loopNum?.toString(2)?.split('').reverse().join(''), 7, '0');
35
- // const stepGrad = step(2).value;
36
- // const hour = step(2).value;
37
- // const minute = step(2).value;
38
- // const brightness = step(2).value;
39
- // const temperature = step(2).value;
40
- // const duration = step(2).value;
41
-
42
- // const node = {
43
- // onOff, // 任务开关
44
- // loops, // 日期设定
45
- // step: stepGrad, // 渐变步进值
46
- // hour, // 起始小时
47
- // minute, // 起始分钟
48
- // brightness, // 亮度百分比
49
- // temperature, // 色温百分比
50
- // duration, // 持续时间 0 - 24, 对应 0-120 => 5分钟一个步进
51
- // index: i,
52
- // };
53
- // nodes.push(node);
54
- // }
55
-
56
- // return {
57
- // version,
58
- // dataMode,
59
- // length,
60
- // nodes,
61
- // };
62
- // }
63
-
64
- // formatter(data: TSleepDataSigmesh) {
65
- // const result = [
66
- // numToHexString(data.version),
67
- // numToHexString(data.dataMode === '01' ? 1 : data.dataMode === '02' ? 2 : 3),
68
- // numToHexString(data.length),
69
- // ];
70
-
71
- // data.nodes.forEach(node => {
72
- // result.push(
73
- // numToHexString(node.onOff ? 1 : 0),
74
- // numToHexString(parseInt(node?.loops?.split('')?.reverse()?.join(''), 2)),
75
- // numToHexString(node.step),
76
- // numToHexString(node.hour),
77
- // numToHexString(node.minute),
78
- // numToHexString(node.brightness),
79
- // numToHexString(node.temperature)
80
- // );
81
- // });
82
-
83
- // return result.join('');
84
- // }
85
- // }
86
-
87
- // export const sleepParserSigmesh: {
88
- // parser: (dpValue: string) => TSleepDataSigmesh;
89
- // formatter: (dpData: TSleepDataSigmesh) => string;
90
- // } = new SleepSigmesh();
91
-
92
- // // 使用示例
93
- // // if (isInIDEFun()) {
94
- // // const dpStr = '01020301020304050607080102030405060708';
95
- // // const result = sleepParserSigmesh.parser(dpStr);
96
- // // const formatted = sleepParserSigmesh.formatter(result);
97
- // // console.warn(formatted, 'formattedformatted1');
98
- // // if (dpStr !== formatted) {
99
- // // throw new Error('sleepParserSigmesh dp 转换失败, 请检查');
100
- // // }
101
- // // }
48
+ const node = {
49
+ onOff,
50
+ // 任务开关
51
+ loops,
52
+ // 日期设定
53
+ step: stepGrad,
54
+ // 渐变步进值
55
+ hour,
56
+ // 起始小时
57
+ minute,
58
+ // 起始分钟
59
+ brightness,
60
+ // 亮度百分比
61
+ temperature,
62
+ // 色温百分比
63
+ index: i
64
+ };
65
+ nodes.push(node);
66
+ }
67
+ return {
68
+ version,
69
+ dataMode,
70
+ length,
71
+ nodes
72
+ };
73
+ }
74
+ formatter(data) {
75
+ var _data$nodes$length, _data$nodes;
76
+ scheduleLogger.debug('Sigmesh dpParser ===> SleepSigmesh formatter: data', data);
77
+ // dataMode 可能是字符串 ('01'/'02'/'03') 或数字 (1/2/3)
78
+ const dataModeNum = typeof data.dataMode === 'string' ? parseInt(data.dataMode, 10) : data.dataMode;
79
+ // 使用 nodes.length 而非 data.length,因为调用方可能未更新 length 字段
80
+ const nodeCount = (_data$nodes$length = (_data$nodes = data.nodes) === null || _data$nodes === void 0 ? void 0 : _data$nodes.length) !== null && _data$nodes$length !== void 0 ? _data$nodes$length : data.length;
81
+ const result = [numToHexString(data.version), numToHexString(dataModeNum), numToHexString(nodeCount)];
82
+ data.nodes.forEach(node => {
83
+ var _node$loops;
84
+ result.push(numToHexString(node.onOff ? 1 : 0), numToHexString(parseInt(node === null || node === void 0 || (_node$loops = node.loops) === null || _node$loops === void 0 || (_node$loops = _node$loops.split('')) === null || _node$loops === void 0 || (_node$loops = _node$loops.reverse()) === null || _node$loops === void 0 ? void 0 : _node$loops.join(''), 2)), numToHexString(node.step), numToHexString(node.hour), numToHexString(node.minute), numToHexString(node.brightness), numToHexString(node.temperature));
85
+ });
86
+ return result.join('');
87
+ }
88
+ }
89
+ export const sleepParserSigmesh = new SleepSigmesh();
@@ -1,9 +1,7 @@
1
- import { Support } from '../../utils/ScheduleSupport';
2
1
  export { wakeupParser as wakeupParserCommon, WakeUp as WakeUpCommon } from './wakeupCommon';
3
2
  export { wakeupParserSigmesh, WakeUpSigmesh } from './wakeupSigmesh';
4
3
  import { TWakeUpDataSigmesh, TWakeUpData } from '../../types';
5
4
  export declare class WakeUpParser {
6
- support: Support;
7
5
  parser(dpStr: string): TWakeUpData | TWakeUpDataSigmesh;
8
6
  formatter(dpData: TWakeUpDataSigmesh | TWakeUpData): string;
9
7
  }
@@ -1,27 +1,23 @@
1
- // import { getSupportIns } from '../../hooks/useCommonSupport';
2
-
1
+ import { getSupportIns } from '../../hooks/useCommonSupport';
3
2
  export { wakeupParser as wakeupParserCommon, WakeUp as WakeUpCommon } from './wakeupCommon';
4
3
  export { wakeupParserSigmesh, WakeUpSigmesh } from './wakeupSigmesh';
5
4
  import { wakeupParser as wakeupParserCommon } from './wakeupCommon';
6
- // import { wakeupParserSigmesh } from './wakeupSigmesh';
7
-
5
+ import { wakeupParserSigmesh } from './wakeupSigmesh';
8
6
  export class WakeUpParser {
9
7
  parser(dpStr) {
10
- // FIXME: 暂时不支持 Sigmesh 设备
11
- // const support = getSupportIns();
12
- // const isSigmesh = support.isSigMeshDevice();
13
- // if (isSigmesh) {
14
- // return wakeupParserSigmesh.parser(dpStr) as TWakeUpDataSigmesh;
15
- // }
8
+ const support = getSupportIns();
9
+ const isSigmesh = support === null || support === void 0 ? void 0 : support.isSigMeshDevice();
10
+ if (isSigmesh) {
11
+ return wakeupParserSigmesh.parser(dpStr);
12
+ }
16
13
  return wakeupParserCommon.parser(dpStr);
17
14
  }
18
15
  formatter(dpData) {
19
- // FIXME: 暂时不支持 Sigmesh 设备
20
- // const support = getSupportIns();
21
- // const isSigmesh = support.isSigMeshDevice();
22
- // if (isSigmesh) {
23
- // return wakeupParserSigmesh.formatter(dpData as TWakeUpDataSigmesh);
24
- // }
16
+ const support = getSupportIns();
17
+ const isSigmesh = support === null || support === void 0 ? void 0 : support.isSigMeshDevice();
18
+ if (isSigmesh) {
19
+ return wakeupParserSigmesh.formatter(dpData);
20
+ }
25
21
  return wakeupParserCommon.formatter(dpData);
26
22
  }
27
23
  }
@@ -3,6 +3,7 @@ import "core-js/modules/esnext.iterator.for-each.js";
3
3
  /* eslint-disable no-console */
4
4
  import { generateDpStrStep, numToHexString } from '@ray-js/panel-sdk/lib/utils';
5
5
  import { padEnd } from 'lodash-es';
6
+ import { scheduleLogger } from '../../utils/ScheduleLogger';
6
7
  export class WakeUpSigmesh {
7
8
  defaultValue = {
8
9
  version: 0,
@@ -11,6 +12,7 @@ export class WakeUpSigmesh {
11
12
  nodes: []
12
13
  };
13
14
  parser(dpStr) {
15
+ scheduleLogger.debug('Sigmesh dpParser ===> WakeUpSigmesh parser: dpStr', dpStr);
14
16
  if (!dpStr) {
15
17
  return this.defaultValue;
16
18
  }
@@ -64,7 +66,13 @@ export class WakeUpSigmesh {
64
66
  };
65
67
  }
66
68
  formatter(data) {
67
- const result = [numToHexString(data.version), numToHexString(data.dataMode === '01' ? 1 : data.dataMode === '02' ? 2 : 3), numToHexString(data.length)];
69
+ var _data$nodes;
70
+ scheduleLogger.debug('Sigmesh dpParser ===> WakeUpSigmesh formatter: data', data);
71
+ // dataMode 可能是字符串 ('01'/'02'/'03') 或数字 (1/2/3)
72
+ const dataModeNum = typeof data.dataMode === 'string' ? parseInt(data.dataMode, 10) : data.dataMode;
73
+ // 使用 nodes.length 而非 data.length,因为调用方可能未更新 length 字段
74
+ const nodeCount = (_data$nodes = data.nodes) === null || _data$nodes === void 0 ? void 0 : _data$nodes.length;
75
+ const result = [numToHexString(data.version), numToHexString(dataModeNum), numToHexString(nodeCount)];
68
76
  data.nodes.forEach(node => {
69
77
  var _node$loops;
70
78
  result.push(numToHexString(node.onOff ? 1 : 0), numToHexString(parseInt(node === null || node === void 0 || (_node$loops = node.loops) === null || _node$loops === void 0 || (_node$loops = _node$loops.split('')) === null || _node$loops === void 0 || (_node$loops = _node$loops.reverse()) === null || _node$loops === void 0 ? void 0 : _node$loops.join(''), 2)), numToHexString(node.step), numToHexString(node.hour), numToHexString(node.minute), numToHexString(node.brightness), numToHexString(node.temperature), numToHexString(node.duration));
@@ -10,7 +10,7 @@ type TDpRes<T> = {
10
10
  };
11
11
  export declare function useBaseLightDp<T>(dpCode: string, defaultDpValue?: T): TDpRes<T>;
12
12
  export declare const getDpDataByMesh: (dpCodes?: string[]) => void;
13
- export declare const fetchDpData: (dpCodes?: string[]) => void;
13
+ export declare const fetchDpData: (dpCodes?: string[]) => Promise<void>;
14
14
  /**
15
15
  * 主动拉取 dp 数据, 仅支持 sigmesh 设备
16
16
  * @param dpCodes dpCode 数组
@@ -22,6 +22,7 @@ export function useBaseLightDp(dpCode, defaultDpValue) {
22
22
  const isInit = isInitFn();
23
23
  const preDpValue = useRef(null);
24
24
  const callback = useCallback(dpData => {
25
+ scheduleLogger.debug('useBaseLightDp callback', dpData);
25
26
  if (!isInit) {
26
27
  scheduleLogger.warn('useBaseLightDp callback is not init');
27
28
  return;
@@ -125,6 +125,25 @@ export const useScheduleInit = props => {
125
125
  ScheduleLogger.error('useScheduleInit registerDeviceListListener fail', err);
126
126
  }
127
127
  });
128
+
129
+ // 监听dp值变化 并触发
130
+ const callback = res => {
131
+ console.log('useScheduleInit data111', res);
132
+ if (!(res !== null && res !== void 0 && res.dps)) {
133
+ ScheduleLogger.warn(`useScheduleInit fail ${DP_CHANGE_EVENT_KEY}`, res);
134
+ return;
135
+ }
136
+ ScheduleLogger.info(`useScheduleInit ${DP_CHANGE_EVENT_KEY}`, res);
137
+ emitter.emit(DP_CHANGE_EVENT_KEY, {
138
+ deviceId: res.devId || res.deviceId,
139
+ dps: res === null || res === void 0 ? void 0 : res.dps
140
+ });
141
+ };
142
+ if (_isInit) {
143
+ ScheduleLogger.warn('useSupport: support is already initialized');
144
+ } else {
145
+ onDpDataChange(callback);
146
+ }
128
147
  }
129
148
  }, [_isInit, actions]);
130
149
  useEffect(() => {
@@ -2,6 +2,7 @@ import { useCallback, useMemo } from 'react';
2
2
  import { useBaseLightDp } from './useBaseLightDp';
3
3
  import { scheduleDpCodes } from '../config/dpCodes';
4
4
  import { getCycleParser } from '../dpParser/cycle';
5
+ import { scheduleLogger } from '../utils/ScheduleLogger';
5
6
  export function useCycleDp() {
6
7
  let dpCode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : scheduleDpCodes.CYCLE_TIMING;
7
8
  const {
@@ -10,6 +11,7 @@ export function useCycleDp() {
10
11
  } = useBaseLightDp(dpCode);
11
12
  const cycleParser = getCycleParser();
12
13
  const _updateDp = useCallback(dpData => {
14
+ scheduleLogger.debug('useCycleDp updateDp', dpData);
13
15
  updateDp(cycleParser.formatter(dpData));
14
16
  }, [cycleParser]);
15
17
  const _dpValue = useMemo(() => {
@@ -2,6 +2,7 @@ import { useCallback, useMemo } from 'react';
2
2
  import { useBaseLightDp } from './useBaseLightDp';
3
3
  import { scheduleDpCodes } from '../config/dpCodes';
4
4
  import { getRandomParser } from '../dpParser/random';
5
+ import { scheduleLogger } from '../utils/ScheduleLogger';
5
6
  export function useRandomDp() {
6
7
  let dpCode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : scheduleDpCodes.RANDOM_TIMING;
7
8
  const {
@@ -10,6 +11,7 @@ export function useRandomDp() {
10
11
  } = useBaseLightDp(dpCode);
11
12
  const randomParser = getRandomParser();
12
13
  const _updateDp = useCallback(dpData => {
14
+ scheduleLogger.debug('useRandomDp updateDp', dpData);
13
15
  updateDp(randomParser.formatter(dpData));
14
16
  }, [randomParser]);
15
17
  const _dpValue = useMemo(() => {
@@ -1,7 +1,7 @@
1
- import { TRhythmData } from '../types';
1
+ import { TRhythmData, TRhythmDataSigmesh } from '../types';
2
2
  type TDpRes = {
3
- dpValue: TRhythmData | null;
4
- updateDp: (value: TRhythmData) => void;
3
+ dpValue: TRhythmData | TRhythmDataSigmesh | null;
4
+ updateDp: (value: TRhythmData | TRhythmDataSigmesh) => void;
5
5
  };
6
6
  export declare function useRhythmsDp(dpCode?: "rhythm_mode"): TDpRes;
7
7
  export {};
@@ -2,6 +2,7 @@ import { useMemo } from 'react';
2
2
  import { useBaseLightDp } from './useBaseLightDp';
3
3
  import { scheduleDpCodes } from '../config/dpCodes';
4
4
  import { rhythmParser } from '../dpParser/rhythms';
5
+ import { scheduleLogger } from '../utils/ScheduleLogger';
5
6
  export function useRhythmsDp() {
6
7
  let dpCode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : scheduleDpCodes.RHYTHM_MODE;
7
8
  const {
@@ -17,6 +18,7 @@ export function useRhythmsDp() {
17
18
  return {
18
19
  dpValue: _dpValue,
19
20
  updateDp: dpData => {
21
+ scheduleLogger.debug('useRhythmsDp updateDp', dpData);
20
22
  updateDp(rhythmParser.formatter(dpData));
21
23
  }
22
24
  };
@@ -2,6 +2,7 @@ import { useMemo } from 'react';
2
2
  import { useBaseLightDp } from './useBaseLightDp';
3
3
  import { scheduleDpCodes } from '../config/dpCodes';
4
4
  import { getSleepParser } from '../dpParser/sleep';
5
+ import { scheduleLogger } from '../utils/ScheduleLogger';
5
6
  export function useSleepDp() {
6
7
  let dpCode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : scheduleDpCodes.SLEEP_MODE;
7
8
  const {
@@ -15,6 +16,7 @@ export function useSleepDp() {
15
16
  return {
16
17
  dpValue: _dpValue,
17
18
  updateDp: dpData => {
19
+ scheduleLogger.debug('useSleepDp updateDp', dpData);
18
20
  updateDp(sleepParser.formatter(dpData));
19
21
  }
20
22
  };
@@ -1,4 +1,5 @@
1
1
  import { useMemo } from 'react';
2
+ import { scheduleLogger } from '../utils/ScheduleLogger';
2
3
  import { useBaseLightDp } from './useBaseLightDp';
3
4
  import { scheduleDpCodes } from '../config/dpCodes';
4
5
  import { getWakeUpParser } from '../dpParser/wakeup';
@@ -15,6 +16,7 @@ export function useWakeUpDp() {
15
16
  return {
16
17
  dpValue: _dpValue,
17
18
  updateDp: dpData => {
19
+ scheduleLogger.debug('useWakeUpDp updateDp', dpData);
18
20
  updateDp(wakeUpParser.formatter(dpData));
19
21
  }
20
22
  };
@@ -1,4 +1,5 @@
1
1
  import { useMemo } from 'react';
2
+ import { scheduleLogger } from '../utils/ScheduleLogger';
2
3
  import { useBaseLightDp } from './useBaseLightDp';
3
4
  import { scheduleDpCodes } from '../config/dpCodes';
4
5
  import { getWakeUpParser } from '../dpParser/wakeup';
@@ -15,6 +16,7 @@ export function useWakeUpDp() {
15
16
  return {
16
17
  dpValue: _dpValue,
17
18
  updateDp: dpData => {
19
+ scheduleLogger.debug('useWakeUpDp updateDp', dpData);
18
20
  updateDp(wakeUpParser.formatter(dpData));
19
21
  }
20
22
  };
@@ -88,4 +88,20 @@ export declare enum ERhythmsType {
88
88
  'Normal' = 1,
89
89
  'NoNature' = 2
90
90
  }
91
+ export interface TRhythmNodeSigmesh {
92
+ power: boolean;
93
+ hour: number;
94
+ minute: number;
95
+ brightness: number;
96
+ temperature: number;
97
+ }
98
+ export interface TRhythmDataSigmesh {
99
+ version: number;
100
+ power: boolean;
101
+ mode: number;
102
+ weeks: number[];
103
+ paramMode: number;
104
+ number: number;
105
+ rhythms: TRhythmNodeSigmesh[];
106
+ }
91
107
  export {};
@@ -12,4 +12,6 @@ export let ERhythmsType = /*#__PURE__*/function (ERhythmsType) {
12
12
  // 常规的生物节律
13
13
  ERhythmsType[ERhythmsType["NoNature"] = 2] = "NoNature"; // 生物节律: 1. 没有自然模式的 2. 选择模式卡片在上方 3. 保存按钮在下方 4. 有同步逻辑
14
14
  return ERhythmsType;
15
- }({});
15
+ }({});
16
+
17
+ // =============== Sigmesh 生物节律类型 ===============
@@ -108,6 +108,8 @@ export class Support {
108
108
  deviceId: firstDevice === null || firstDevice === void 0 ? void 0 : firstDevice.devId,
109
109
  success: deviceInfoRes => {
110
110
  var _res$deviceList;
111
+ // eslint-disable-next-line no-param-reassign
112
+ delete deviceInfoRes.dps;
111
113
  // 从 deviceInfoRes 中筛选出 groupRes 中不存在的数据,合并到 res
112
114
  const filteredDeviceInfo = {};
113
115
  const _deviceInfo = _objectSpread(_objectSpread({}, groupRes), deviceInfoRes);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/lamp-schedule-core",
3
- "version": "1.0.4-beta-14",
3
+ "version": "1.0.5-beta.1",
4
4
  "description": "照明计划模块核心能力",
5
5
  "main": "./lib/index.js",
6
6
  "files": [