@ray-js/lamp-schedule-core 1.0.4-beta-15 → 1.0.5-beta.2

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 (47) hide show
  1. package/lib/config/dpCodes.d.ts +5 -1
  2. package/lib/config/dpCodes.js +5 -1
  3. package/lib/dpParser/__test__/rhythms.test.js +7 -2
  4. package/lib/dpParser/__test__/rhythmsSigmesh.test.d.ts +1 -0
  5. package/lib/dpParser/__test__/rhythmsSigmesh.test.js +263 -0
  6. package/lib/dpParser/__test__/sleepSigmesh.test.d.ts +1 -0
  7. package/lib/dpParser/__test__/sleepSigmesh.test.js +183 -0
  8. package/lib/dpParser/brightAdjustData.d.ts +10 -0
  9. package/lib/dpParser/brightAdjustData.js +43 -0
  10. package/lib/dpParser/colourDataRaw.d.ts +14 -0
  11. package/lib/dpParser/colourDataRaw.js +56 -0
  12. package/lib/dpParser/index.d.ts +4 -1
  13. package/lib/dpParser/index.js +14 -1
  14. package/lib/dpParser/rhythms/index.d.ts +9 -0
  15. package/lib/dpParser/rhythms/index.js +27 -0
  16. package/lib/dpParser/{rhythms.d.ts → rhythms/rhythmsCommon.d.ts} +2 -3
  17. package/lib/dpParser/{rhythms.js → rhythms/rhythmsCommon.js} +6 -9
  18. package/lib/dpParser/rhythms/rhythmsSigmesh.d.ts +17 -0
  19. package/lib/dpParser/rhythms/rhythmsSigmesh.js +143 -0
  20. package/lib/dpParser/sleep/index.d.ts +1 -2
  21. package/lib/dpParser/sleep/index.js +13 -12
  22. package/lib/dpParser/sleep/sleepSigmesh.d.ts +20 -0
  23. package/lib/dpParser/sleep/sleepSigmesh.js +86 -98
  24. package/lib/dpParser/stripLocalTimer.d.ts +10 -0
  25. package/lib/dpParser/stripLocalTimer.js +107 -0
  26. package/lib/dpParser/wakeup/index.d.ts +0 -2
  27. package/lib/dpParser/wakeup/index.js +12 -16
  28. package/lib/dpParser/wakeup/wakeupSigmesh.js +9 -1
  29. package/lib/hooks/useBaseLightDp.d.ts +1 -1
  30. package/lib/hooks/useBaseLightDp.js +1 -0
  31. package/lib/hooks/useCommonSupport.js +19 -0
  32. package/lib/hooks/useCycleDp.js +2 -0
  33. package/lib/hooks/useDPByProtocol.d.ts +2 -0
  34. package/lib/hooks/useRandomDp.js +2 -0
  35. package/lib/hooks/useRhythmsDp.d.ts +3 -3
  36. package/lib/hooks/useRhythmsDp.js +2 -0
  37. package/lib/hooks/useSleepDp.js +2 -0
  38. package/lib/hooks/useWakeUpDp.js +2 -0
  39. package/lib/hooks/useWakeupDp.js +2 -0
  40. package/lib/types/rhythms.d.ts +16 -0
  41. package/lib/types/rhythms.js +3 -1
  42. package/lib/types/timer.d.ts +42 -0
  43. package/lib/utils/ScheduleSupport.d.ts +4 -0
  44. package/lib/utils/ScheduleSupport.js +9 -0
  45. package/lib/utils/getDPByProtocol.d.ts +4 -0
  46. package/lib/utils/matterDeviceUtils.d.ts +4 -0
  47. package/package.json +1 -1
@@ -19,7 +19,7 @@ export declare const scheduleDpCodes: {
19
19
  readonly CYCLE_TIMING: "cycle_timing";
20
20
  /** 通用本地定时 */
21
21
  readonly LOCAL_TIMER: "local_timer";
22
- /** 灯带本地定时 */
22
+ /** 灯带本地定时 Beacon */
23
23
  readonly STRIP_LOCAL_TIMER: "strip_local_timer";
24
24
  /** 定时同步 一般用于 Beacon */
25
25
  readonly TIMER_SYNC: "timer_sync";
@@ -33,6 +33,10 @@ export declare const scheduleDpCodes: {
33
33
  readonly BRIGHTNESS: "bright_value";
34
34
  /** 彩光 */
35
35
  readonly COLOUR_DATA: "colour_data";
36
+ /** 彩光原始数据 Beacon */
37
+ readonly COLOUR_DATA_RAW: "colour_data_raw";
38
+ /** 亮度调节 Beacon */
39
+ readonly BRIGHT_ADJUST_DATA: "bright_adjust_data";
36
40
  /** 模式 */
37
41
  readonly WORK_MODE: "work_mode";
38
42
  };
@@ -22,7 +22,7 @@ export const scheduleDpCodes = {
22
22
  [EScheduleType.CYCLE_TIMING]: 'cycle_timing',
23
23
  /** 通用本地定时 */
24
24
  [EScheduleType.LOCAL_TIMER]: 'local_timer',
25
- /** 灯带本地定时 */
25
+ /** 灯带本地定时 Beacon */
26
26
  [EScheduleType.STRIP_LOCAL_TIMER]: 'strip_local_timer',
27
27
  /** 定时同步 一般用于 Beacon */
28
28
  [EScheduleType.TIMER_SYNC]: 'timer_sync',
@@ -36,6 +36,10 @@ export const scheduleDpCodes = {
36
36
  BRIGHTNESS: 'bright_value',
37
37
  /** 彩光 */
38
38
  COLOUR_DATA: 'colour_data',
39
+ /** 彩光原始数据 Beacon */
40
+ COLOUR_DATA_RAW: 'colour_data_raw',
41
+ /** 亮度调节 Beacon */
42
+ BRIGHT_ADJUST_DATA: 'bright_adjust_data',
39
43
  /** 模式 */
40
44
  WORK_MODE: 'work_mode'
41
45
  };
@@ -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
+ });
@@ -0,0 +1,10 @@
1
+ import { TBrightAdjustData } from '../types';
2
+ export declare class BrightAdjustDataFormatter {
3
+ parser(dpValue: string): TBrightAdjustData;
4
+ formatter(data: TBrightAdjustData): string;
5
+ }
6
+ export declare const brightAdjustDataParser: {
7
+ parser: (dpValue: string) => TBrightAdjustData;
8
+ formatter: (data: TBrightAdjustData) => string;
9
+ };
10
+ export declare const getBrightAdjustDataParser: () => BrightAdjustDataFormatter;
@@ -0,0 +1,43 @@
1
+ /* eslint-disable no-console */
2
+
3
+ import { scheduleLogger as ScheduleLogger } from '../utils/ScheduleLogger';
4
+ export class BrightAdjustDataFormatter {
5
+ parser(dpValue) {
6
+ try {
7
+ ScheduleLogger.debug('dpParser ===> BrightAdjustDataFormatter parser dpValue:', dpValue);
8
+ if (!dpValue || dpValue.length < 6) {
9
+ return {
10
+ mode: 0,
11
+ brightness: 0
12
+ };
13
+ }
14
+ const mode = parseInt(dpValue.substring(0, 2), 16);
15
+ const brightness = parseInt(dpValue.substring(2, 6), 16);
16
+ return {
17
+ mode,
18
+ brightness
19
+ };
20
+ } catch (error) {
21
+ ScheduleLogger.error('dpParser ===> BrightAdjustDataFormatter parser error:', error);
22
+ return {
23
+ mode: 0,
24
+ brightness: 0
25
+ };
26
+ }
27
+ }
28
+ formatter(data) {
29
+ try {
30
+ ScheduleLogger.debug('dpParser ===> BrightAdjustDataFormatter formatter data:', data);
31
+ const modeStr = data.mode.toString(16).padStart(2, '0');
32
+ const brightnessStr = data.brightness.toString(16).padStart(4, '0');
33
+ return `${modeStr}${brightnessStr}`;
34
+ } catch (error) {
35
+ ScheduleLogger.error('dpParser ===> BrightAdjustDataFormatter formatter error:', error);
36
+ return '';
37
+ }
38
+ }
39
+ }
40
+ export const brightAdjustDataParser = new BrightAdjustDataFormatter();
41
+ export const getBrightAdjustDataParser = () => {
42
+ return brightAdjustDataParser;
43
+ };
@@ -0,0 +1,14 @@
1
+ import { TColourDataRaw } from '../types';
2
+ export declare class ColourDataRawFormatter {
3
+ parser(dpValue: string): TColourDataRaw;
4
+ formatter(data: {
5
+ hue: number;
6
+ saturation: number;
7
+ value: number;
8
+ } | TColourDataRaw): string;
9
+ }
10
+ export declare const colourDataRawParser: {
11
+ parser: (dpValue: string) => TColourDataRaw;
12
+ formatter: (data: any) => string;
13
+ };
14
+ export declare const getColourDataRawParser: () => ColourDataRawFormatter;
@@ -0,0 +1,56 @@
1
+ /* eslint-disable no-console */
2
+ import { numToHexString } from '@ray-js/panel-sdk/lib/utils';
3
+ import { scheduleLogger as ScheduleLogger } from '../utils/ScheduleLogger';
4
+ const toHex = function (value) {
5
+ let len = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
6
+ return numToHexString(value).padStart(len, '0');
7
+ };
8
+ export class ColourDataRawFormatter {
9
+ parser(dpValue) {
10
+ try {
11
+ ScheduleLogger.debug('dpParser ===> ColourDataRawFormatter parser dpValue:', dpValue);
12
+ if (!dpValue || dpValue.length < 8) {
13
+ return {
14
+ hue: 0,
15
+ saturation: 1000,
16
+ value: 1000
17
+ };
18
+ }
19
+ const hue = parseInt(dpValue.substring(0, 4), 16);
20
+ const saturation = parseInt(dpValue.substring(4, 6), 16) * 10;
21
+ const value = parseInt(dpValue.substring(6, 8), 16) * 10;
22
+ return {
23
+ hue,
24
+ saturation,
25
+ value
26
+ };
27
+ } catch (error) {
28
+ ScheduleLogger.error('dpParser ===> ColourDataRawFormatter parser error:', error);
29
+ return {
30
+ hue: 0,
31
+ saturation: 1000,
32
+ value: 1000
33
+ };
34
+ }
35
+ }
36
+ formatter(data) {
37
+ try {
38
+ ScheduleLogger.debug('dpParser ===> ColourDataRawFormatter formatter data:', data);
39
+ // 兼容两种数据格式: { hue, saturation, value } 或 { h, s, v }
40
+ const h = 'hue' in data ? data.hue : data.h;
41
+ const s = 'saturation' in data ? data.saturation : data.s;
42
+ const v = 'value' in data ? data.value : data.v;
43
+ const hStr = toHex(Math.floor(h), 4);
44
+ const sStr = toHex(Math.floor(s / 10), 2);
45
+ const vStr = toHex(Math.floor(v / 10), 2);
46
+ return `${hStr}${sStr}${vStr}`;
47
+ } catch (error) {
48
+ ScheduleLogger.error('dpParser ===> ColourDataRawFormatter formatter error:', error);
49
+ return '';
50
+ }
51
+ }
52
+ }
53
+ export const colourDataRawParser = new ColourDataRawFormatter();
54
+ export const getColourDataRawParser = () => {
55
+ return colourDataRawParser;
56
+ };
@@ -2,11 +2,14 @@
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
9
  export { timerReportParser } from './timerReport';
10
+ export { stripLocalTimerParser, getStripLocalTimerParser } from './stripLocalTimer';
11
+ export { brightAdjustDataParser, getBrightAdjustDataParser } from './brightAdjustData';
12
+ export { colourDataRawParser, getColourDataRawParser } from './colourDataRaw';
10
13
  type DpCode = keyof typeof scheduleDpCodes;
11
14
  /**
12
15
  * 自动匹配 dp 解析函数