qlsdk2 0.6.0__tar.gz → 0.6.0a2__tar.gz

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 (86) hide show
  1. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/PKG-INFO +1 -1
  2. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/setup.py +1 -1
  3. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/entity/__init__.py +32 -90
  4. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/persist/ars_edf.py +101 -80
  5. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/persist/rsc_edf.py +12 -20
  6. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/command/__init__.py +12 -26
  7. qlsdk2-0.6.0a2/src/qlsdk/rsc/device/arskindling.py +386 -0
  8. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/device/base.py +82 -158
  9. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/device/c16_rs.py +5 -1
  10. qlsdk2-0.6.0a2/src/qlsdk/rsc/device/c256_rs.py +360 -0
  11. qlsdk2-0.6.0a2/src/qlsdk/rsc/device/c64_rs.py +359 -0
  12. qlsdk2-0.6.0a2/src/qlsdk/rsc/device/c64s1.py +365 -0
  13. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/interface/device.py +1 -22
  14. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/paradigm.py +6 -127
  15. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/parser/base.py +6 -11
  16. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk2.egg-info/PKG-INFO +1 -1
  17. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk2.egg-info/SOURCES.txt +1 -2
  18. qlsdk2-0.6.0/src/qlsdk/rsc/device/arskindling.py +0 -324
  19. qlsdk2-0.6.0/src/qlsdk/rsc/device/c256_rs.py +0 -44
  20. qlsdk2-0.6.0/src/qlsdk/rsc/device/c64_rs.py +0 -29
  21. qlsdk2-0.6.0/src/qlsdk/rsc/device/c64s1.py +0 -29
  22. qlsdk2-0.6.0/test/test_bdf.py +0 -212
  23. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/README.md +0 -0
  24. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/setup.cfg +0 -0
  25. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/__init__.py +0 -0
  26. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/ar4/__init__.py +0 -0
  27. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/ar4m/__init__.py +0 -0
  28. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/__init__.py +0 -0
  29. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/crc/__init__.py +0 -0
  30. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/crc/crctools.py +0 -0
  31. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/device.py +0 -0
  32. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/exception.py +0 -0
  33. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/filter/__init__.py +0 -0
  34. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/filter/norch.py +0 -0
  35. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/local.py +0 -0
  36. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/message/__init__.py +0 -0
  37. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/message/command.py +0 -0
  38. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/message/tcp.py +0 -0
  39. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/message/udp.py +0 -0
  40. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/network/__init__.py +0 -0
  41. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/network/monitor.py +0 -0
  42. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/core/utils.py +0 -0
  43. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/entity/__init__.py +0 -0
  44. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/entity/message.py +0 -0
  45. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/entity/signal.py +0 -0
  46. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/interface/__init__.py +0 -0
  47. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/interface/analyzer.py +0 -0
  48. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/interface/collector.py +0 -0
  49. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/interface/device.py +0 -0
  50. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/interface/parser.py +0 -0
  51. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/interface/stimulator.py +0 -0
  52. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/interface/store.py +0 -0
  53. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/persist/__init__.py +0 -0
  54. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/persist/edf.py +0 -0
  55. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/persist/stream.py +0 -0
  56. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/__init__.py +0 -0
  57. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/device/__init__.py +0 -0
  58. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/device/device_factory.py +0 -0
  59. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/eegion.py +0 -0
  60. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/entity.py +0 -0
  61. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/interface/__init__.py +0 -0
  62. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/interface/command.py +0 -0
  63. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/interface/handler.py +0 -0
  64. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/interface/parser.py +0 -0
  65. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/manager/__init__.py +0 -0
  66. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/manager/container.py +0 -0
  67. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/manager/search.py +0 -0
  68. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/network/__init__.py +0 -0
  69. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/network/discover.py +0 -0
  70. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/parser/__init__.py +0 -0
  71. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/parser/base-new.py +0 -0
  72. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/parser/rsc.py +0 -0
  73. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/rsc/proxy.py +0 -0
  74. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/sdk/__init__.py +0 -0
  75. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/sdk/ar4sdk.py +0 -0
  76. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/sdk/hub.py +0 -0
  77. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/sdk/libs/libAr4SDK.dll +0 -0
  78. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/sdk/libs/libwinpthread-1.dll +0 -0
  79. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/x8/__init__.py +0 -0
  80. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk/x8m/__init__.py +0 -0
  81. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk2.egg-info/dependency_links.txt +0 -0
  82. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk2.egg-info/requires.txt +0 -0
  83. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/src/qlsdk2.egg-info/top_level.txt +0 -0
  84. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/test/test.222.py +0 -0
  85. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/test/test.py +0 -0
  86. {qlsdk2-0.6.0 → qlsdk2-0.6.0a2}/test/test_ar4m.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qlsdk2
3
- Version: 0.6.0
3
+ Version: 0.6.0a2
4
4
  Summary: SDK for quanlan device
5
5
  Home-page: https://github.com/hehuajun/qlsdk
6
6
  Author: hehuajun
@@ -6,7 +6,7 @@ with open("README.md", "r", encoding='utf-8' ) as fh:
6
6
 
7
7
  setuptools.setup(
8
8
  name="qlsdk2",
9
- version="0.6.0",
9
+ version="0.6.0a2",
10
10
  author="hehuajun",
11
11
  author_email="hehuajun@eegion.com",
12
12
  description="SDK for quanlan device",
@@ -19,8 +19,7 @@ class RscPacket(Packet):
19
19
  self.filter = None
20
20
  self.data_len = None
21
21
  self.trigger = None
22
- self.eeg = None # 数字信号
23
- self.eeg_p = None # 物理值
22
+ self.eeg = None
24
23
 
25
24
  @staticmethod
26
25
  def transfer(body: bytes) -> 'RscPacket':
@@ -51,68 +50,47 @@ class RscPacket(Packet):
51
50
  for i in range(ch_num)
52
51
  ]
53
52
 
54
- logger.trace(packet)
55
-
53
+ # logger.trace(self)
56
54
  return packet
57
-
58
- def copy(self) -> 'RscPacket':
59
- packet = RscPacket()
60
- packet.time_stamp = self.time_stamp
61
- packet.pkg_id = self.pkg_id
62
- packet.result = self.result
63
- packet.channels = self.channels
64
- packet.origin_sample_rate = self.origin_sample_rate
65
- packet.sample_rate = self.sample_rate
66
- packet.sample_num = self.sample_num
67
- packet.resolution = self.resolution
68
- packet.filter = self.filter
69
- packet.data_len = self.data_len
70
- packet.trigger = self.trigger
71
- packet.eeg = self.eeg
72
- return packet
73
55
 
74
56
  def __str__(self):
75
- return f"""[
76
- "time_stamp": {self.time_stamp}
77
- "pkg_id": {self.pkg_id}
78
- "channels": {self.channels}
79
- "trigger": {self.trigger}
80
- "eeg": {self.eeg}
81
- ]"""
57
+ return f"""
58
+ time_stamp: {self.time_stamp}
59
+ pkg_id: {self.pkg_id}
60
+ origin_sample_rate: {self.origin_sample_rate}
61
+ sample_rate: {self.sample_rate}
62
+ sample_num: {self.sample_num}
63
+ resolution: {self.resolution}
64
+ filter: {self.filter}
65
+ channels: {self.channels}
66
+ data len: {self.data_len}
67
+ trigger: {self.trigger}
68
+ eeg: {self.eeg}
69
+ """
82
70
 
83
71
  class ImpedancePacket(Packet):
84
72
  def __init__(self):
85
73
  super().__init__()
74
+ self.data_len = None
86
75
  self.impedance = None
87
76
 
88
- @staticmethod
89
- def transfer(body:bytes) -> 'ImpedancePacket':
90
- packet = ImpedancePacket()
91
- packet.time_stamp = int.from_bytes(body[0:8], 'little')
92
- # packet.result = body[8]
93
- packet.pkg_id = int.from_bytes(body[9: 13], 'little')
94
- packet.channels = to_channels(body[13: 45])
95
- # packet.sample_rate = int.from_bytes(body[45: 49], 'little')
96
- # packet.sample_len = int.from_bytes(body[49: 53], 'little')
97
- # packet.resolution = int(int(body[53]) / 8)
98
- # packet.filter = int(int(body[54]) / 8)
99
- # packet.wave_type = int(int(body[55]) / 8)
100
- # packet.wave_freq = int.from_bytes(body[56: 60], 'little')
101
- # packet.data_len = int.from_bytes(body[60: 64], 'little')
102
- b_impedance = body[64:]
103
- packet.impedance = [int.from_bytes(b_impedance[j * 4 : j * 4 + 4], 'little', signed=False) for j in range(len(packet.channels))]
104
-
105
- logger.trace(f"impedance: {packet}")
77
+ def transfer(self, body:bytes) -> 'ImpedancePacket':
78
+ self.time_stamp = int.from_bytes(body[0:8], 'little')
79
+ self.result = body[8]
80
+ self.pkg_id = int.from_bytes(body[9: 13], 'little')
81
+ self.channels = to_channels(body[13: 45])
82
+
83
+ logger.debug(f"impedance: {self}")
106
84
 
107
- return packet
108
-
109
85
  def __str__(self):
110
- return f"""[
111
- "time_stamp": {self.time_stamp}
112
- "pkg_id": {self.pkg_id}
113
- "channels": {self.channels}
114
- "impedance": {self.impedance}
115
- ]"""
86
+ return f"""
87
+ time_stamp: {self.time_stamp}
88
+ pkg_id: {self.pkg_id}
89
+ result: {self.result}
90
+ channels: {self.channels}
91
+ data len: {self.data_len}
92
+ impedance: {self.impedance}
93
+ """
116
94
 
117
95
 
118
96
  class C256RSPacket(Packet):
@@ -183,40 +161,4 @@ class C256RSPacket(Packet):
183
161
  offset += 4 + channel_size * packet.resolution
184
162
 
185
163
  logger.trace(packet)
186
- return packet
187
-
188
-
189
- class C256ImpedancePacket(Packet):
190
- def __init__(self):
191
- super().__init__()
192
- self.impedance = None
193
-
194
- @staticmethod
195
- def transfer(body:bytes) -> 'ImpedancePacket':
196
- packet = ImpedancePacket()
197
- packet.time_stamp = int.from_bytes(body[0:8], 'little')
198
- # packet.result = body[8]
199
- packet.pkg_id = int.from_bytes(body[9: 13], 'little')
200
- packet.channels = to_channels(body[13: 45])
201
- # packet.sample_rate = int.from_bytes(body[45: 49], 'little')
202
- # packet.sample_len = int.from_bytes(body[49: 53], 'little')
203
- # packet.resolution = int(int(body[53]) / 8)
204
- # packet.filter = int(int(body[54]) / 8)
205
- # packet.wave_type = int(int(body[55]) / 8)
206
- # packet.wave_freq = int.from_bytes(body[56: 60], 'little')
207
- # packet.data_len = int.from_bytes(body[60: 64], 'little')
208
- b_impedance = body[64:]
209
- packet.impedance = [int.from_bytes(b_impedance[j : j + 4], 'little', signed=False) for j in range(len(packet.channels))]
210
-
211
- logger.trace(f"impedance: {packet}")
212
-
213
- def __str__(self):
214
- return f"""
215
- time_stamp: {self.time_stamp}
216
- pkg_id: {self.pkg_id}
217
- result: {self.result}
218
- channels: {self.channels}
219
- data len: {self.data_len}
220
- impedance: {self.impedance}
221
- """
222
-
164
+ return packet
@@ -85,67 +85,67 @@ class ARSKindlingEDFHandler(object):
85
85
  "D" : [7, 8, 5, 6, 3, 4, 1, 2, 9, 10, 11, 12, 13, 14],
86
86
  }
87
87
 
88
- # self._channel_mapping = {
89
- # 1: "D7",
90
- # 2: "D8",
91
- # 3: "D5",
92
- # 4: "D6",
93
- # 5: "D3",
94
- # 6: "D4",
95
- # 7: "D1",
96
- # 8: "D2",
97
- # 9: "D9",
98
- # 10: "D10",
99
- # 11: "D11",
100
- # 12: "D12",
101
- # 13: "D13",
102
- # 14: "D14",
88
+ self._channel_mapping = {
89
+ 1: "D7",
90
+ 2: "D8",
91
+ 3: "D5",
92
+ 4: "D6",
93
+ 5: "D3",
94
+ 6: "D4",
95
+ 7: "D1",
96
+ 8: "D2",
97
+ 9: "D9",
98
+ 10: "D10",
99
+ 11: "D11",
100
+ 12: "D12",
101
+ 13: "D13",
102
+ 14: "D14",
103
103
 
104
- # 17: "C7",
105
- # 18: "C8",
106
- # 19: "C5",
107
- # 20: "C6",
108
- # 21: "C3",
109
- # 22: "C4",
110
- # 23: "C1",
111
- # 24: "C2",
112
- # 25: "C9",
113
- # 26: "C10",
114
- # 27: "C11",
115
- # 28: "C12",
116
- # 29: "C13",
117
- # 30: "C14",
104
+ 17: "C7",
105
+ 18: "C8",
106
+ 19: "C5",
107
+ 20: "C6",
108
+ 21: "C3",
109
+ 22: "C4",
110
+ 23: "C1",
111
+ 24: "C2",
112
+ 25: "C9",
113
+ 26: "C10",
114
+ 27: "C11",
115
+ 28: "C12",
116
+ 29: "C13",
117
+ 30: "C14",
118
118
 
119
- # 33: "B7",
120
- # 34: "B8",
121
- # 35: "B5",
122
- # 36: "B6",
123
- # 37: "B3",
124
- # 38: "B4",
125
- # 39: "B1",
126
- # 40: "B2",
127
- # 41: "B9",
128
- # 42: "B10",
129
- # 43: "B11",
130
- # 44: "B12",
131
- # 45: "B13",
132
- # 46: "B14",
119
+ 33: "B7",
120
+ 34: "B8",
121
+ 35: "B5",
122
+ 36: "B6",
123
+ 37: "B3",
124
+ 38: "B4",
125
+ 39: "B1",
126
+ 40: "B2",
127
+ 41: "B9",
128
+ 42: "B10",
129
+ 43: "B11",
130
+ 44: "B12",
131
+ 45: "B13",
132
+ 46: "B14",
133
133
 
134
- # 49: "A7",
135
- # 50: "A8",
136
- # 51: "A5",
137
- # 52: "A6",
138
- # 53: "A3",
139
- # 54: "A4",
140
- # 55: "A1",
141
- # 56: "A2",
142
- # 57: "A9",
143
- # 58: "A10",
144
- # 59: "A11",
145
- # 60: "A12",
146
- # 61: "A13",
147
- # 62: "A14"
148
- # }
134
+ 49: "A7",
135
+ 50: "A8",
136
+ 51: "A5",
137
+ 52: "A6",
138
+ 53: "A3",
139
+ 54: "A4",
140
+ 55: "A1",
141
+ 56: "A2",
142
+ 57: "A9",
143
+ 58: "A10",
144
+ 59: "A11",
145
+ 60: "A12",
146
+ 61: "A13",
147
+ 62: "A14"
148
+ }
149
149
 
150
150
  self._lock = Lock()
151
151
 
@@ -172,8 +172,6 @@ class ARSKindlingEDFHandler(object):
172
172
  self._device_type = "C64RS"
173
173
  elif device_type == 0x40:
174
174
  self._device_type = "LJ64S1"
175
- elif device_type == 0x60:
176
- self._device_type = "ArsKindling"
177
175
  else:
178
176
  self._device_type = hex(device_type)
179
177
 
@@ -197,32 +195,55 @@ class ARSKindlingEDFHandler(object):
197
195
  if packet is None:
198
196
  # self._edf_writer_thread.stop_recording()
199
197
  for k in self._edf_handler.keys():
200
- self._edf_handler[k].write(None)
198
+ self._edf_handler[k].append(None)
201
199
  return
202
200
 
203
- #按分区写入数据
201
+ #按分区写入数据
202
+
204
203
  for k in self._channel_spilt.keys():
205
- logger.trace(f'分区{k}写入数据到文件')
206
- if k in packet.channels.keys():
207
- p = packet
208
- self.writeA(p, k)
204
+ logger.info(f'分区{k}, {self._channel_spilt[k]}')
205
+ p = packet
206
+ self.writeA(p, self._channel_spilt[k], k)
207
+
208
+ # with self._lock:
209
+ # if self.channels is None:
210
+ # logger.info(f"开始记录数据到文件...")
211
+ # self.channels = packet.channels
212
+ # self._first_pkg_id = packet.pkg_id if self._first_pkg_id is None else self._first_pkg_id
213
+ # self._first_timestamp = packet.time_stamp if self._first_timestamp is None else self._first_timestamp
214
+ # self._start_time = datetime.now()
215
+ # logger.info(f"第一个包id: {self._first_pkg_id }, 时间戳:{self._first_timestamp}, 当前时间:{datetime.now().timestamp()} offset: {datetime.now().timestamp() - self._first_timestamp}")
216
+
217
+ # if self._last_pkg_id and self._last_pkg_id != packet.pkg_id - 1:
218
+ # self._lost_packets += packet.pkg_id - self._last_pkg_id - 1
219
+ # logger.warning(f"数据包丢失: {self._last_pkg_id} -> {packet.pkg_id}, 丢包数: {packet.pkg_id - self._last_pkg_id - 1}")
220
+
221
+ # self._last_pkg_id = packet.pkg_id
222
+ # self._total_packets += 1
223
+
224
+ # if self._edf_writer_thread is None:
225
+ # self._edf_writer_thread = EDFStreamWriter(self.channels, self.sample_rate, self.physical_max, self.physical_min, self.file_type, self.file_name)
226
+ # self._edf_writer_thread.set_start_time(self._start_time)
227
+ # self._edf_writer_thread.start()
228
+ # logger.info(f"开始写入数据: {self.file_name}")
229
+
230
+ # self._edf_writer_thread.append(packet.eeg)
209
231
 
210
- def writeA(self, packet: RscPacket, name='A'):
232
+ def writeA(self, packet: RscPacket, channel_filter, name='A'):
211
233
  # 参数检查
212
- if packet is None:
234
+ if packet is None or channel_filter is None:
213
235
  logger.warning("空数据,忽略")
214
236
  return
215
-
216
- channels = packet.channels.get(name, None)
217
- eeg = packet.eeg.get(name, None)
218
237
 
219
- if eeg is None :
220
- logger.trace(f"分区{name}没有可用的数据,跳过文件写入")
221
- return
238
+ channel_pos = intersection_positions(packet.channels, channel_filter)
239
+
240
+ if channel_pos is None or len(channel_pos) == 0 :
241
+ logger.debug(f"没有指定分区{name}的通道,跳过")
242
+ pass
222
243
 
223
244
  # 分区数据包写入
224
245
  if name not in self._edf_handler.keys():
225
- edf_handler = RscEDFHandler(self.sample_rate, self.physical_max , self.physical_min, self.resolution)
246
+ edf_handler = RscEDFHandler(self.sample_rate, self.digital_max , self.digital_min, self.resolution)
226
247
  edf_handler.set_device_type(self._device_type)
227
248
  edf_handler.set_device_no(self._device_no)
228
249
  edf_handler.set_storage_path(self._storage_path)
@@ -230,12 +251,15 @@ class ARSKindlingEDFHandler(object):
230
251
  logger.info(f"开始写入分区{name}的数据到文件")
231
252
  self._edf_handler[name] = edf_handler
232
253
 
254
+ # 保留本分区的通道和数据
255
+ channels = [packet.channels[p] for p in channel_pos]
256
+ eeg = [packet.eeg[p] for p in channel_pos]
257
+
233
258
  # 新建数据包实例
234
259
  data = RscPacket()
235
260
  data.time_stamp = packet.time_stamp
236
261
  data.pkg_id = packet.pkg_id
237
- # data.channels = channels
238
- data.channels = self.channel_display(channels, name)
262
+ data.channels = channels
239
263
  data.origin_sample_rate = packet.origin_sample_rate
240
264
  data.sample_rate = packet.sample_rate
241
265
  data.sample_num = packet.sample_num
@@ -252,6 +276,3 @@ class ARSKindlingEDFHandler(object):
252
276
  # trigger现在(20250702)多个分区共享, 分发到所有分区文件中标记
253
277
  for k in self._edf_handler.keys():
254
278
  self._edf_handler[k].trigger(desc, cur_time)
255
-
256
- def channel_display(self, channel, name: str):
257
- return [f'{name}-{channel_id}' for channel_id in channel]
@@ -15,7 +15,7 @@ EDF_FILE_TYPE = {
15
15
  }
16
16
 
17
17
  class EDFStreamWriter(Thread):
18
- def __init__(self, channels, sample_frequency, physical_max, physical_min, file_type, file_path, record_duration=None):
18
+ def __init__(self, channels, sample_frequency, physical_max, digital_min, file_type, file_path, record_duration=None):
19
19
 
20
20
  super().__init__()
21
21
  self._writer : EdfWriter = None
@@ -32,7 +32,7 @@ class EDFStreamWriter(Thread):
32
32
  self._n_channels = len(channels)
33
33
  self.sample_frequency = sample_frequency
34
34
  self.physical_max = physical_max
35
- self.physical_min = physical_min
35
+ self.physical_min = digital_min
36
36
  # 和位数相关,edf 16 bits/bdf 24 bits
37
37
  self.digital_max = 8388607 if file_type == EDF_FILE_TYPE['bdf'] else 32767
38
38
  self.digital_min = -8388608 if file_type == EDF_FILE_TYPE['bdf'] else -32768
@@ -46,7 +46,6 @@ class EDFStreamWriter(Thread):
46
46
  self.equipment = "equipment"
47
47
  self.patient_code = "patient_code"
48
48
  self.patient_name = "patient_name"
49
- logger.info(f'digital_max:{self.digital_max}, digital_min:{self.digital_min}, physical_max:{self.physical_max}, physical_min:{self.physical_min}')
50
49
 
51
50
  def set_channels(self, channels):
52
51
  self._channels = channels
@@ -62,7 +61,7 @@ class EDFStreamWriter(Thread):
62
61
  self._recording = False
63
62
 
64
63
  def append(self, data):
65
- if data is not None:
64
+ if data:
66
65
  # 数据
67
66
  self.data_queue.put(data)
68
67
 
@@ -128,7 +127,6 @@ class EDFStreamWriter(Thread):
128
127
 
129
128
  # 配置通道参数
130
129
  signal_headers = []
131
- logger.trace(f"sf: {self.sample_frequency}, pm: {self.physical_max}, pn: {self.physical_min}, dm: {self.digital_max}, dn: {self.digital_min}")
132
130
  for ch in range(self._n_channels):
133
131
  signal_headers.append({
134
132
  "label": f'channels {self._channels[ch]}',
@@ -171,16 +169,14 @@ class EDFStreamWriter(Thread):
171
169
  # 写入1秒的数据
172
170
  def _write_block(self, block):
173
171
  logger.trace(f"写入数据: {block}")
174
- # 转换数据类型为float64-物理信号uV int32-数字信号
175
- data_input = block.astype(np.int32)
176
- logger.trace(f"写入数据-real: {data_input}")
172
+ # 转换数据类型为float64
173
+ data_float64 = block.astype(np.float64)
177
174
  # 写入时转置为(样本数, 通道数)格式
178
- self._writer.writeSamples(data_input, digital=True)
175
+ self._writer.writeSamples(data_float64)
179
176
  self._duration += 1
180
177
 
181
178
  if self._duration % 10 == 0: # 每10秒打印一次进度
182
179
  logger.info(f"数据记录中... 文件名:{self.file_path}, 已记录时长: {self._duration}秒")
183
-
184
180
 
185
181
  # 用作数据结构一致化处理,通过调用公共类写入edf文件
186
182
  # 入参包含写入edf的全部前置参数
@@ -204,7 +200,7 @@ class RscEDFHandler(object):
204
200
  self.physical_max = physical_max
205
201
  self.physical_min = physical_min
206
202
  self.digital_max = 8388607 if resolution == 24 else 32767
207
- self.digital_min = -8388608 if resolution == 24 else - 32768
203
+ self.digital_min = -8388607 if resolution == 24 else - 32768
208
204
  self.file_type = EDF_FILE_TYPE["bdf"] if resolution == 24 else EDF_FILE_TYPE["edf"]
209
205
  # 点分辨率
210
206
  self.resolution = resolution
@@ -230,8 +226,8 @@ class RscEDFHandler(object):
230
226
  self._end_time = None
231
227
  self._patient_code = "patient_code"
232
228
  self._patient_name = "patient_name"
233
- self._device_type = "0000"
234
- self._device_no = "00000000"
229
+ self._device_type = "24130032"
230
+ self._device_no = "24130032"
235
231
  self._total_packets = 0
236
232
  self._lost_packets = 0
237
233
  self._storage_path = storage_path
@@ -246,7 +242,7 @@ class RscEDFHandler(object):
246
242
  suffix = "bdf" if self.resolution == 24 else "edf"
247
243
 
248
244
  # 文件名称
249
- file_name = f"{self._file_prefix}_{self._device_no}_{self._start_time.strftime('%y%m%d%H%M%S')}.{suffix}" if self._file_prefix else f"{self._device_no}_{self._start_time.strftime('%y%m%d%H%I%M')}.{suffix}"
245
+ file_name = f"{self._file_prefix}_{self._device_no}_{self._start_time.strftime('%y%m%d%H%I%M')}.{suffix}" if self._file_prefix else f"{self._device_no}_{self._start_time.strftime('%y%m%d%H%I%M')}.{suffix}"
250
246
 
251
247
  if self._storage_path:
252
248
  try:
@@ -264,8 +260,6 @@ class RscEDFHandler(object):
264
260
  self._device_type = "C64RS"
265
261
  elif device_type == 0x40:
266
262
  self._device_type = "LJ64S1"
267
- elif device_type == 0x45:
268
- self._device_type = "C256RS"
269
263
  elif device_type == 0x51:
270
264
  self._device_type = "C256RS"
271
265
  elif device_type == 0x60:
@@ -296,8 +290,6 @@ class RscEDFHandler(object):
296
290
  logger.info(f"收到结束信号,即将停止写入数据:{self.file_name}")
297
291
  self._edf_writer_thread.stop_recording()
298
292
  return
299
-
300
- logger.debug(f"packet: {packet}")
301
293
 
302
294
  with self._lock:
303
295
  if self.channels is None:
@@ -320,7 +312,6 @@ class RscEDFHandler(object):
320
312
  self._edf_writer_thread.set_start_time(self._start_time)
321
313
  self._edf_writer_thread.start()
322
314
  logger.info(f"开始写入数据: {self.file_name}")
323
- self._edf_writer_thread.equipment = f'{self._device_type}_{self._device_no}'
324
315
 
325
316
  self._edf_writer_thread.append(packet.eeg)
326
317
 
@@ -340,4 +331,5 @@ class RscEDFHandler(object):
340
331
  else: onset = 0
341
332
  else:
342
333
  onset = cur_time - self._first_timestamp
343
- self._edf_writer_thread.trigger(onset, desc)
334
+ self._edf_writer_thread.trigger(onset, desc)
335
+
@@ -48,9 +48,8 @@ class DeviceCommand(abc.ABC):
48
48
  """构建消息体"""
49
49
  return b''
50
50
  def pack_header(self, body_len: int) -> bytes:
51
- # device_id = int(self.device.device_id) if self.device and self.device.device_id else 0
51
+ device_id = int(self.device.device_id) if self.device and self.device.device_id else 0
52
52
  device_type = int(self.device.device_type) if self.device and self.device.device_type else 0
53
- device_id = bytes.fromhex(self.device.device_id)[::-1] if self.device.device_id else bytes.fromhex('00000000')
54
53
 
55
54
  #兼容设计
56
55
  b_device_type = None
@@ -62,7 +61,7 @@ class DeviceCommand(abc.ABC):
62
61
  DeviceCommand.HEADER_PREFIX
63
62
  + int(2).to_bytes(1, 'little') # pkgType
64
63
  + device_type.to_bytes(1, 'little')
65
- + device_id
64
+ + device_id.to_bytes(4, 'little')
66
65
  + (DeviceCommand.HEADER_LEN + body_len + 2).to_bytes(4, 'little') # +1 for checksum
67
66
  + self.cmd_code.to_bytes(2, 'little')
68
67
  )
@@ -205,15 +204,6 @@ class StopAcquisitionCommand(DeviceCommand):
205
204
  class SetImpedanceParamCommand(DeviceCommand):
206
205
  cmd_code = 0x411
207
206
  cmd_desc = "设置阻抗测量参数"
208
- def pack_body(self):
209
-
210
- return self.device.gen_set_impedance_param()
211
- def parse_body(self, body):
212
- result = body[8]
213
- if result == 0x00:
214
- logger.info("阻抗测量参数设置成功")
215
- else:
216
- logger.warning(f"阻抗测量参数设置失败: {int(result)}")
217
207
 
218
208
  # 启动阻抗测量
219
209
  class StartImpedanceCommand(DeviceCommand):
@@ -221,16 +211,13 @@ class StartImpedanceCommand(DeviceCommand):
221
211
  cmd_desc = "启动阻抗测量"
222
212
  def pack_body(self):
223
213
  body = bytes.fromhex('0000')
224
- body += to_bytes(self.device.get_impedance_channels())
214
+ body += to_bytes(self.device.acq_channels)
225
215
  body += bytes.fromhex('0000000000000000') # 8字节占位符
226
216
  return body
227
217
 
228
218
  def parse_body(self, body):
229
- result = body[8]
230
- if result == 0x00:
231
- logger.info("阻抗测量启动成功")
232
- else:
233
- logger.warning(f"阻抗测量启动失败: {int(result)}")
219
+ logger.info(f"Received StartImpedance response: {body.hex()}")
220
+ return super().parse_body(body)
234
221
 
235
222
 
236
223
  # 停止阻抗测量
@@ -246,7 +233,7 @@ class StartStimulationCommand(DeviceCommand):
246
233
  cmd_code = 0x48C
247
234
  cmd_desc = "启动刺激"
248
235
  def pack_body(self):
249
- return self.device.get_stim_param()
236
+ return self.device.stim_paradigm.to_bytes()
250
237
  # return bytes.fromhex('01000000000000008813000000000000010000000000000000000140420f00640064000000803f0000010000000000000000000000000000000000000000008813000000000000')
251
238
  def parse_body(self, body: bytes):
252
239
  # time - 8B
@@ -256,9 +243,8 @@ class StartStimulationCommand(DeviceCommand):
256
243
  # error_channel - 8B
257
244
  # error_channel= int.from_bytes(body[9:17], 'big')
258
245
  channels = to_channels(body[9:17])
259
- logger.info(f"通道 {channels} 刺激开始")
260
- if self.device:
261
- self.device.trigger(f"通道 {channels} 刺激开始")
246
+ logger.success(f"通道 {channels} 刺激开始")
247
+ self.device.trigger(f"通道 {channels} 刺激开始")
262
248
  # error_type - 1B
263
249
  error_type = body[17]
264
250
 
@@ -282,9 +268,8 @@ class StopStimulationNotifyCommand(DeviceCommand):
282
268
  # error_channel - 8B
283
269
  # error_channel= int.from_bytes(body[9:17], 'big')
284
270
  channels = to_channels(body[9:17])
285
- logger.info(f"通道 {channels} 刺激结束")
286
- if self.device:
287
- self.device.trigger(f"通道 {channels} 刺激结束", time)
271
+ logger.success(f"通道 {channels} 刺激结束")
272
+ self.device.trigger(f"通道 {channels} 刺激结束", time)
288
273
  # error_type - 1B
289
274
  error_type = body[17]
290
275
  # 刺激信息
@@ -312,7 +297,8 @@ class ImpedanceDataCommand(DeviceCommand):
312
297
  cmd_desc = "阻抗数据"
313
298
 
314
299
  def parse_body(self, body: bytes):
315
- self.device.produce(body, type="impedance")
300
+ # logger.info(f"Received impedance data: {body.hex()}")
301
+ packet = ImpedancePacket().transfer(body)
316
302
 
317
303
  # 信号数据
318
304
  class SignalDataCommand(DeviceCommand):