muse-api 2.0.0__py3-none-any.whl
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.
- Muse_Data.py +225 -0
- Muse_HW.py +547 -0
- Muse_Utils.py +2882 -0
- muse_api-2.0.0.dist-info/METADATA +726 -0
- muse_api-2.0.0.dist-info/RECORD +8 -0
- muse_api-2.0.0.dist-info/WHEEL +5 -0
- muse_api-2.0.0.dist-info/licenses/LICENSE +674 -0
- muse_api-2.0.0.dist-info/top_level.txt +3 -0
Muse_Utils.py
ADDED
|
@@ -0,0 +1,2882 @@
|
|
|
1
|
+
""" Muse_Utils.py: Muse utilities for encoding and decoding of command and messages.
|
|
2
|
+
|
|
3
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
4
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
5
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
|
6
|
+
version.
|
|
7
|
+
|
|
8
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
9
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
10
|
+
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
11
|
+
|
|
12
|
+
You should have received a copy of the GNU General Public License along with
|
|
13
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
__authors__ = ["Luigi Mattiello", "Francesca Palazzo", "Roberto Bortoletto"]
|
|
17
|
+
__contact__ = "info@221e.com"
|
|
18
|
+
__copyright__ = "Copyright (c) 2020 by 221e srl."
|
|
19
|
+
__credits__ = ["Luigi Mattiello", "Francesca Palazzo", "Roberto Bortoletto"]
|
|
20
|
+
__deprecated__ = False
|
|
21
|
+
__email__ = "roberto.bortoletto@221e.com"
|
|
22
|
+
__license__ = "GNU General Public License"
|
|
23
|
+
__maintainer__ = "Roberto Bortoletto"
|
|
24
|
+
__status__ = "Production"
|
|
25
|
+
__version__ = "2.0.0"
|
|
26
|
+
|
|
27
|
+
import copy
|
|
28
|
+
import ctypes
|
|
29
|
+
import datetime
|
|
30
|
+
import struct
|
|
31
|
+
import math
|
|
32
|
+
|
|
33
|
+
from Muse_HW import Muse_HW as MH
|
|
34
|
+
from Muse_Data import *
|
|
35
|
+
from typing import Optional
|
|
36
|
+
|
|
37
|
+
class Muse_Utils:
|
|
38
|
+
"""Utilities related to communication protocol specifications.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
# USB WRAPPER FUNCTIONS
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def _WrapMessage(buffer):
|
|
45
|
+
"""
|
|
46
|
+
Adds header and trailer to a standard command.
|
|
47
|
+
.. code-block:: python
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
buffer:
|
|
51
|
+
Input byte array to be wrapped.
|
|
52
|
+
"""
|
|
53
|
+
wrapped_buffer = None
|
|
54
|
+
if (buffer != None):
|
|
55
|
+
#Define wrapped message buffer
|
|
56
|
+
wrapped_buffer = [0]* (len(buffer)+4)
|
|
57
|
+
|
|
58
|
+
#Add header to input buffer
|
|
59
|
+
wrapped_buffer[0] = 0x3f # ?
|
|
60
|
+
wrapped_buffer[1] = 0x21 # !
|
|
61
|
+
|
|
62
|
+
#Copy main content
|
|
63
|
+
buffer_copy = copy.copy(buffer)
|
|
64
|
+
wrapped_buffer[2:] = buffer_copy
|
|
65
|
+
|
|
66
|
+
#Add trailer to input buffer
|
|
67
|
+
wrapped_buffer.append(0x21) # !
|
|
68
|
+
wrapped_buffer.append(0x3f) # ?
|
|
69
|
+
|
|
70
|
+
return wrapped_buffer
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
def _ExtractMessage(buffer):
|
|
74
|
+
"""
|
|
75
|
+
Removes header and trailer from a standard command.
|
|
76
|
+
.. code-block:: python
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
buffer:
|
|
80
|
+
Input byte array from which the header and trailer must be removed.
|
|
81
|
+
"""
|
|
82
|
+
#Remove header and trailer from input buffer
|
|
83
|
+
dewrapped_buffer = None
|
|
84
|
+
if (buffer != None):
|
|
85
|
+
#copio dal secondo carattere in poi, poi tolgo il trailer
|
|
86
|
+
dewrapped_buffer = copy.copy(buffer[2:])[:-2]
|
|
87
|
+
return dewrapped_buffer
|
|
88
|
+
|
|
89
|
+
# end of USB WRAPPER FUNCTIONS
|
|
90
|
+
|
|
91
|
+
# ENCODING COMMAND IMPLEMENTATION
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def Cmd_Acknowledge(ack: MH.AcknowledgeType, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
95
|
+
"""
|
|
96
|
+
Builds command to send Acknowledge.
|
|
97
|
+
.. code-block:: python
|
|
98
|
+
|
|
99
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
100
|
+
cmd = Muse_Utils.Cmd_Acknowledge(ack=MH.AcnowledgeType.ACK_SUCCESS)
|
|
101
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
ack:
|
|
105
|
+
Acknowledge type (ACK_SUCCESS = 0x00, ACK_ERROR = 0x01).
|
|
106
|
+
channel:
|
|
107
|
+
Communication channel over which the command will be sent.
|
|
108
|
+
"""
|
|
109
|
+
# Definition of message buffer
|
|
110
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_ACKNOWLEDGE)
|
|
111
|
+
|
|
112
|
+
buffer[0] = 0x00
|
|
113
|
+
|
|
114
|
+
#Set payload length
|
|
115
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_ACKNOWLEDGE.value - 2
|
|
116
|
+
|
|
117
|
+
buffer[2] = MH.Command.CMD_STATE.value
|
|
118
|
+
buffer[3] = ack
|
|
119
|
+
buffer[4] = MH.SystemState.SYS_CALIB.value
|
|
120
|
+
|
|
121
|
+
return buffer
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def Cmd_GetSystemState(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
125
|
+
"""
|
|
126
|
+
Builds command to retrieve current system state.
|
|
127
|
+
.. code-block:: python
|
|
128
|
+
|
|
129
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
130
|
+
cmd = Muse_Utils.Cmd_GetSystemState()
|
|
131
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
channel:
|
|
135
|
+
Communication channel over which the command will be sent.
|
|
136
|
+
"""
|
|
137
|
+
#Definition of message buffer
|
|
138
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_STATE)
|
|
139
|
+
|
|
140
|
+
#Get state command
|
|
141
|
+
buffer[0] = MH.Command.CMD_STATE.value + MH.READ_BIT_MASK
|
|
142
|
+
|
|
143
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
144
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
145
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
146
|
+
|
|
147
|
+
return buffer
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def Cmd_StartStream(mode: MH.DataMode, frequency: MH.DataFrequency, enableDirect = True, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
151
|
+
"""
|
|
152
|
+
Builds command to start acquisition in stream mode.
|
|
153
|
+
.. code-block:: python
|
|
154
|
+
|
|
155
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
156
|
+
cmd = Muse_Utils.Cmd_StartStream(MH.DataMode.DATA_MODE_AXL, MH.DataFrequency.DATA_FREQ_50Hz, enableDirect=True)
|
|
157
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
mode:
|
|
161
|
+
Identifies the set of data to be acquired.
|
|
162
|
+
frequency:
|
|
163
|
+
Identifies the data acquisition frequency.
|
|
164
|
+
enableDirect:
|
|
165
|
+
Allows to select the stream type (i.e., direct=True or buffered=False).
|
|
166
|
+
channel:
|
|
167
|
+
Communication channel over which the command will be sent.
|
|
168
|
+
"""
|
|
169
|
+
#Definition of message buffer
|
|
170
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_START_STREAM)
|
|
171
|
+
|
|
172
|
+
#Start stream acquisition using set state command
|
|
173
|
+
buffer[0] = MH.Command.CMD_STATE.value
|
|
174
|
+
|
|
175
|
+
#Set payload length
|
|
176
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_START_STREAM.value - 2
|
|
177
|
+
|
|
178
|
+
#Set tx type based on boolean flag value
|
|
179
|
+
if (enableDirect):
|
|
180
|
+
buffer[2] = MH.SystemState.SYS_TX_DIRECT.value
|
|
181
|
+
else:
|
|
182
|
+
buffer[2] = MH.SystemState.SYS_TX_BUFFERED.value
|
|
183
|
+
|
|
184
|
+
#Set acquisition mode
|
|
185
|
+
tmp = struct.pack("I", mode.value)
|
|
186
|
+
buffer[3:6] = tmp[:3]
|
|
187
|
+
|
|
188
|
+
#Set acquisition frequency
|
|
189
|
+
buffer[6] = frequency.value
|
|
190
|
+
|
|
191
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
192
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
193
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
194
|
+
|
|
195
|
+
return buffer
|
|
196
|
+
|
|
197
|
+
@staticmethod
|
|
198
|
+
def Cmd_StartLog(mode: MH.DataMode, frequency: MH.DataFrequency, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
199
|
+
"""
|
|
200
|
+
Builds command to stop any data acquisition procedure.
|
|
201
|
+
.. code-block:: python
|
|
202
|
+
|
|
203
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
204
|
+
cmd = Muse_Utils.Cmd_StartLog(MH.DataMode.DATA_MODE_AXL, MH.DataFrequency.DATA_FREQ_50Hz)
|
|
205
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
mode:
|
|
209
|
+
Identifies the set of data to be acquired.
|
|
210
|
+
frequency:
|
|
211
|
+
Identifies the data acquisition frequency.
|
|
212
|
+
channel:
|
|
213
|
+
Communication channel over which the command will be sent.
|
|
214
|
+
"""
|
|
215
|
+
#Definition of message buffer
|
|
216
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_START_LOG)
|
|
217
|
+
|
|
218
|
+
#Start stream acquisition using set state command
|
|
219
|
+
buffer[0] = MH.Command.CMD_STATE.value
|
|
220
|
+
|
|
221
|
+
#Set payload length
|
|
222
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_START_LOG.value - 2
|
|
223
|
+
|
|
224
|
+
#Set state - LOG
|
|
225
|
+
buffer[2] = MH.SystemState.SYS_LOG.value
|
|
226
|
+
|
|
227
|
+
#Set acquisition mode
|
|
228
|
+
tmp = struct.pack("I", mode.value)
|
|
229
|
+
buffer[3:6] = tmp[:3]
|
|
230
|
+
|
|
231
|
+
#Set acquisition frequency
|
|
232
|
+
buffer[6] = frequency.value
|
|
233
|
+
|
|
234
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
235
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
236
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
237
|
+
|
|
238
|
+
return buffer
|
|
239
|
+
|
|
240
|
+
@staticmethod
|
|
241
|
+
def Cmd_StopAcquisition(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
242
|
+
"""
|
|
243
|
+
Builds command to stop any data acquisition procedure.
|
|
244
|
+
.. code-block:: python
|
|
245
|
+
|
|
246
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
247
|
+
cmd = Muse_Utils.Cmd_StopAcquisition()
|
|
248
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
channel:
|
|
252
|
+
Communication channel over which the command will be sent.
|
|
253
|
+
"""
|
|
254
|
+
#Definition of message buffer
|
|
255
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_STOP_ACQUISITION)
|
|
256
|
+
|
|
257
|
+
#Set IDLE state to stop any acquisition procedure
|
|
258
|
+
buffer[0] = MH.Command.CMD_STATE.value
|
|
259
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_STOP_ACQUISITION.value - 2
|
|
260
|
+
buffer[2] = MH.SystemState.SYS_IDLE.value
|
|
261
|
+
|
|
262
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
263
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
264
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
265
|
+
|
|
266
|
+
return buffer
|
|
267
|
+
|
|
268
|
+
@staticmethod
|
|
269
|
+
def Cmd_Restart(restartMode : MH.RestartMode, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
270
|
+
"""
|
|
271
|
+
Builds command to set restart device.
|
|
272
|
+
.. code-block:: python
|
|
273
|
+
|
|
274
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
275
|
+
restart_mode = MH.RestartMode.APPLICATION
|
|
276
|
+
cmd = Muse_Utils.Cmd_Restart(restart_mode)
|
|
277
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
restartMode:
|
|
281
|
+
Allows to select the restart mode (i.e., APPLICATION, BOOT or RESET).
|
|
282
|
+
channel:
|
|
283
|
+
Communication channel over which the command will be sent.
|
|
284
|
+
"""
|
|
285
|
+
#Definition of message buffer
|
|
286
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_RESTART)
|
|
287
|
+
|
|
288
|
+
#Set RESTART command with the specified restart mode (i.e., boot or app)
|
|
289
|
+
buffer[0] = MH.Command.CMD_RESTART.value
|
|
290
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_RESTART.value - 2
|
|
291
|
+
buffer[2] = restartMode.value
|
|
292
|
+
|
|
293
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
294
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
295
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
296
|
+
|
|
297
|
+
return buffer
|
|
298
|
+
|
|
299
|
+
@staticmethod
|
|
300
|
+
def Cmd_GetApplicationInfo(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
301
|
+
"""
|
|
302
|
+
Builds command to retrive application firmware information.
|
|
303
|
+
.. code-block:: python
|
|
304
|
+
|
|
305
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
306
|
+
cmd = Muse_Utils.Cmd_GetApplicationInfo()
|
|
307
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
channel:
|
|
311
|
+
Communication channel over which the command will be sent.
|
|
312
|
+
"""
|
|
313
|
+
#Definition of message buffer
|
|
314
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_APP_INFO)
|
|
315
|
+
|
|
316
|
+
#Get firmware application info
|
|
317
|
+
buffer[0] = MH.Command.CMD_APP_INFO.value + MH.READ_BIT_MASK
|
|
318
|
+
|
|
319
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
320
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
321
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
322
|
+
|
|
323
|
+
return buffer
|
|
324
|
+
|
|
325
|
+
@staticmethod
|
|
326
|
+
def Cmd_GetBatteryCharge(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
327
|
+
"""
|
|
328
|
+
Builds command to retrieve battery charge level [%].
|
|
329
|
+
.. code-block:: python
|
|
330
|
+
|
|
331
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
332
|
+
cmd = Muse_Utils.Cmd_GetBatteryCharge()
|
|
333
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
channel:
|
|
337
|
+
Communication channel over which the command will be sent.
|
|
338
|
+
"""
|
|
339
|
+
#Definition of message buffer
|
|
340
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_BATTERY_CHARGE)
|
|
341
|
+
|
|
342
|
+
#Get battery charge
|
|
343
|
+
buffer[0] = MH.Command.CMD_BATTERY_CHARGE.value + MH.READ_BIT_MASK
|
|
344
|
+
|
|
345
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
346
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
347
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
348
|
+
|
|
349
|
+
return buffer
|
|
350
|
+
|
|
351
|
+
@staticmethod
|
|
352
|
+
def Cmd_GetBatteryVoltage(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
353
|
+
"""
|
|
354
|
+
Builds command to retrieve battery voltage level [mV].
|
|
355
|
+
.. code-block:: python
|
|
356
|
+
|
|
357
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
358
|
+
cmd = Muse_Utils.Cmd_GetBatteryVoltage()
|
|
359
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
channel:
|
|
363
|
+
Communication channel over which the command will be sent.
|
|
364
|
+
"""
|
|
365
|
+
#Definition of message buffer
|
|
366
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_BATTERY_VOLTAGE)
|
|
367
|
+
|
|
368
|
+
#Get battery voltage
|
|
369
|
+
buffer[0] = MH.Command.CMD_BATTERY_VOLTAGE.value + MH.READ_BIT_MASK
|
|
370
|
+
|
|
371
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
372
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
373
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
374
|
+
|
|
375
|
+
return buffer
|
|
376
|
+
|
|
377
|
+
@staticmethod
|
|
378
|
+
def Cmd_GetDeviceCheckup(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
379
|
+
"""
|
|
380
|
+
Builds command to retrieve system check-up register value.
|
|
381
|
+
.. code-block:: python
|
|
382
|
+
|
|
383
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
384
|
+
cmd = Muse_Utils.Cmd_GetDeviceCheckup()
|
|
385
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
386
|
+
|
|
387
|
+
Args:
|
|
388
|
+
channel:
|
|
389
|
+
Communication channel over which the command will be sent.
|
|
390
|
+
"""
|
|
391
|
+
#Definition of message buffer
|
|
392
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_CHECK_UP)
|
|
393
|
+
|
|
394
|
+
#Get check up register value
|
|
395
|
+
buffer[0] = MH.Command.CMD_CHECK_UP.value + MH.READ_BIT_MASK
|
|
396
|
+
|
|
397
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
398
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
399
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
400
|
+
|
|
401
|
+
return buffer
|
|
402
|
+
|
|
403
|
+
@staticmethod
|
|
404
|
+
def Cmd_GetFirmwareVersion(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
405
|
+
"""
|
|
406
|
+
Builds command to retrieve current firmware versions (i.e., both bootloader and application).
|
|
407
|
+
.. code-block:: python
|
|
408
|
+
|
|
409
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
410
|
+
cmd = Muse_Utils.Cmd_GetFirmwareVersion()
|
|
411
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
412
|
+
|
|
413
|
+
Args:
|
|
414
|
+
channel:
|
|
415
|
+
Communication channel over which the command will be sent.
|
|
416
|
+
"""
|
|
417
|
+
#Definition of message buffer
|
|
418
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_FW_VERSION)
|
|
419
|
+
|
|
420
|
+
#Get firmware version labels (i.e., bootloader and application firmware)
|
|
421
|
+
buffer[0] = MH.Command.CMD_FW_VERSION.value + MH.READ_BIT_MASK
|
|
422
|
+
|
|
423
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
424
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
425
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
426
|
+
|
|
427
|
+
return buffer
|
|
428
|
+
|
|
429
|
+
@staticmethod
|
|
430
|
+
def Cmd_SetTime(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
431
|
+
"""
|
|
432
|
+
Builds command to update date/time.
|
|
433
|
+
.. code-block:: python
|
|
434
|
+
|
|
435
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
436
|
+
cmd = Muse_Utils.Cmd_SetTime()
|
|
437
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
438
|
+
|
|
439
|
+
Args:
|
|
440
|
+
channel:
|
|
441
|
+
Communication channel over which the command will be sent.
|
|
442
|
+
"""
|
|
443
|
+
#Definition of message buffer
|
|
444
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_SET_TIME)
|
|
445
|
+
|
|
446
|
+
#Set time using current timespan since 1970
|
|
447
|
+
buffer[0] = MH.Command.CMD_TIME.value
|
|
448
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_SET_TIME.value - 2
|
|
449
|
+
|
|
450
|
+
#Get current timespan since 1/1/1970
|
|
451
|
+
time_span = datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1, 0, 0, 0)
|
|
452
|
+
seconds_since_epoch = ctypes.c_long(int(time_span.total_seconds())).value
|
|
453
|
+
|
|
454
|
+
#Set payload - seconds since epoch (4 bytes)
|
|
455
|
+
#pack takes values that aren't bytes and convert them into bytes
|
|
456
|
+
payload = struct.pack("<I", seconds_since_epoch)
|
|
457
|
+
|
|
458
|
+
buffer[2:] = payload[:]
|
|
459
|
+
|
|
460
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
461
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
462
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
463
|
+
|
|
464
|
+
return buffer
|
|
465
|
+
|
|
466
|
+
@staticmethod
|
|
467
|
+
def Cmd_GetTime(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
468
|
+
"""
|
|
469
|
+
Builds command to retrieve current date/time.
|
|
470
|
+
.. code-block:: python
|
|
471
|
+
|
|
472
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
473
|
+
cmd = Muse_Utils.Cmd_GetTime()
|
|
474
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
475
|
+
|
|
476
|
+
Args:
|
|
477
|
+
channel:
|
|
478
|
+
Communication channel over which the command will be sent.
|
|
479
|
+
"""
|
|
480
|
+
#Definition of message buffer
|
|
481
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_TIME)
|
|
482
|
+
|
|
483
|
+
#Get current datetime
|
|
484
|
+
buffer[0] = MH.Command.CMD_TIME.value + MH.READ_BIT_MASK
|
|
485
|
+
|
|
486
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
487
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
488
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
489
|
+
|
|
490
|
+
return buffer
|
|
491
|
+
|
|
492
|
+
@staticmethod
|
|
493
|
+
def Cmd_GetDeviceName(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
494
|
+
"""
|
|
495
|
+
Builds command to retrieve device name (i.e., the name advertised by the Bluetooth module).
|
|
496
|
+
.. code-block:: python
|
|
497
|
+
|
|
498
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
499
|
+
cmd = Muse_Utils.Cmd_GetDeviceName()
|
|
500
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
501
|
+
|
|
502
|
+
Args:
|
|
503
|
+
channel:
|
|
504
|
+
Communication channel over which the command will be sent.
|
|
505
|
+
"""
|
|
506
|
+
|
|
507
|
+
#Definition of message buffer
|
|
508
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_BLE_NAME)
|
|
509
|
+
|
|
510
|
+
#Get device name (i.e., ble name)
|
|
511
|
+
buffer[0] = MH.Command.CMD_BLE_NAME.value + MH.READ_BIT_MASK
|
|
512
|
+
|
|
513
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
514
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
515
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
516
|
+
|
|
517
|
+
return buffer
|
|
518
|
+
|
|
519
|
+
@staticmethod
|
|
520
|
+
def Cmd_SetDeviceName(bleName, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
521
|
+
"""
|
|
522
|
+
Builds command to change the device name (i.e., the name advertised by the Bluetooth module).
|
|
523
|
+
.. code-block:: python
|
|
524
|
+
|
|
525
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
526
|
+
cmd = Muse_Utils.Cmd_SetDeviceName(bleName="my_muse")
|
|
527
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
528
|
+
|
|
529
|
+
Args:
|
|
530
|
+
bleName:
|
|
531
|
+
New device name to be set.
|
|
532
|
+
channel:
|
|
533
|
+
Communication channel over which the command will be sent.
|
|
534
|
+
"""
|
|
535
|
+
#Definition of message buffer
|
|
536
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_SET_BLE_NAME)
|
|
537
|
+
|
|
538
|
+
#Check bleName to be set consistency before proceeding
|
|
539
|
+
if (bleName != "" and len(bleName) < 16):
|
|
540
|
+
|
|
541
|
+
buffer[0] = MH.Command.CMD_BLE_NAME.value
|
|
542
|
+
|
|
543
|
+
respLen = len(bleName)
|
|
544
|
+
buffer[1:1] = respLen.to_bytes(1, 'big')
|
|
545
|
+
|
|
546
|
+
for i in range(len(bleName)):
|
|
547
|
+
buffer[2 + i:] = bytearray(bleName[i],'utf-8')
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
551
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
552
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
553
|
+
|
|
554
|
+
return buffer
|
|
555
|
+
|
|
556
|
+
@staticmethod
|
|
557
|
+
def Cmd_GetDeviceID(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
558
|
+
"""
|
|
559
|
+
Builds command to retrieve the device unique identifier.
|
|
560
|
+
.. code-block:: python
|
|
561
|
+
|
|
562
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
563
|
+
cmd = Muse_Utils.Cmd_GetDeviceID()
|
|
564
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
565
|
+
|
|
566
|
+
Args:
|
|
567
|
+
channel:
|
|
568
|
+
Communication channel over which the command will be sent.
|
|
569
|
+
"""
|
|
570
|
+
#Definition of message buffer
|
|
571
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_DEVICE_ID)
|
|
572
|
+
|
|
573
|
+
#Get device unique identifier
|
|
574
|
+
buffer[0] = MH.Command.CMD_DEVICE_ID.value + MH.READ_BIT_MASK
|
|
575
|
+
|
|
576
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
577
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
578
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
579
|
+
|
|
580
|
+
return buffer
|
|
581
|
+
|
|
582
|
+
@staticmethod
|
|
583
|
+
def Cmd_GetDeviceSkills(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
584
|
+
"""
|
|
585
|
+
Builds command to retrieve the devices skills (i.e. hardware and software features provided by the device).
|
|
586
|
+
The response to this command will return a byte array containing 4 bytes corresponding to hardware skills and the next 4 bytes corresponding to software skills.
|
|
587
|
+
.. code-block:: python
|
|
588
|
+
|
|
589
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
590
|
+
cmd = Muse_Utils.Cmd_GetDeviceSkills()
|
|
591
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
592
|
+
|
|
593
|
+
Args:
|
|
594
|
+
channel:
|
|
595
|
+
Communication channel over which the command will be sent.
|
|
596
|
+
"""
|
|
597
|
+
#Definition of message buffer
|
|
598
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_DEVICE_SKILLS)
|
|
599
|
+
|
|
600
|
+
#Get device skills (i.e., hardware or software based on specified flag)
|
|
601
|
+
buffer[0] = MH.Command.CMD_DEVICE_SKILLS.value + MH.READ_BIT_MASK
|
|
602
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_GET_DEVICE_SKILLS.value - 2
|
|
603
|
+
|
|
604
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
605
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
606
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
607
|
+
|
|
608
|
+
return buffer
|
|
609
|
+
|
|
610
|
+
@staticmethod
|
|
611
|
+
def Cmd_GetMemoryStatus(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
612
|
+
"""
|
|
613
|
+
Builds command to retrieve current memory status.
|
|
614
|
+
.. code-block:: python
|
|
615
|
+
|
|
616
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
617
|
+
cmd = Muse_Utils.Cmd_GetMemoryStatus()
|
|
618
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
619
|
+
|
|
620
|
+
Args:
|
|
621
|
+
channel:
|
|
622
|
+
Communication channel over which the command will be sent.
|
|
623
|
+
"""
|
|
624
|
+
#Definition of message buffer
|
|
625
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_MEM_CONTROL)
|
|
626
|
+
|
|
627
|
+
# Get available memory
|
|
628
|
+
buffer[0] = MH.Command.CMD_MEM_CONTROL.value + MH.READ_BIT_MASK
|
|
629
|
+
|
|
630
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
631
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
632
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
633
|
+
|
|
634
|
+
return buffer
|
|
635
|
+
|
|
636
|
+
@staticmethod
|
|
637
|
+
def Cmd_EraseMemory(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
638
|
+
"""
|
|
639
|
+
Builds command to erase device memory.
|
|
640
|
+
.. code-block:: python
|
|
641
|
+
|
|
642
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
643
|
+
cmd = Muse_Utils.Cmd_EraseMemory()
|
|
644
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
645
|
+
|
|
646
|
+
Args:
|
|
647
|
+
channel:
|
|
648
|
+
Communication channel over which the command will be sent.
|
|
649
|
+
"""
|
|
650
|
+
#Definition of message buffer
|
|
651
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_SET_MEM_CONTROL)
|
|
652
|
+
|
|
653
|
+
#Erase memory
|
|
654
|
+
bulk_erase = 1 # Parameter to erase all memory
|
|
655
|
+
buffer[0] = MH.Command.CMD_MEM_CONTROL.value
|
|
656
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_SET_MEM_CONTROL.value - 2
|
|
657
|
+
buffer[2] = bulk_erase
|
|
658
|
+
|
|
659
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
660
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
661
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
662
|
+
|
|
663
|
+
return buffer
|
|
664
|
+
|
|
665
|
+
@staticmethod
|
|
666
|
+
def Cmd_MemoryFileInfo(fileId, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
667
|
+
"""
|
|
668
|
+
Builds command to retrieve file information.
|
|
669
|
+
.. code-block:: python
|
|
670
|
+
|
|
671
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
672
|
+
cmd = Muse_Utils.Cmd_MemoryFileInfo(fileId=0)
|
|
673
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
674
|
+
|
|
675
|
+
Args:
|
|
676
|
+
fileId:
|
|
677
|
+
File identifier.
|
|
678
|
+
channel:
|
|
679
|
+
Communication channel over which the command will be sent.
|
|
680
|
+
"""
|
|
681
|
+
#Definition of message buffer
|
|
682
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_MEM_FILE_INFO)
|
|
683
|
+
|
|
684
|
+
#Retrieve file information given a specific file identifier
|
|
685
|
+
buffer[0] = MH.Command.CMD_MEM_FILE_INFO.value + MH.READ_BIT_MASK
|
|
686
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_GET_MEM_FILE_INFO.value - 2
|
|
687
|
+
|
|
688
|
+
#Set file id as a 2-bytes unsigned integer value
|
|
689
|
+
valueBytes = fileId.to_bytes(2, byteorder='little')
|
|
690
|
+
buffer[2] = valueBytes[0]
|
|
691
|
+
buffer[3] = valueBytes[1]
|
|
692
|
+
|
|
693
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
694
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
695
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
696
|
+
|
|
697
|
+
return buffer
|
|
698
|
+
|
|
699
|
+
@staticmethod
|
|
700
|
+
def Cmd_MemoryFileDownload(fileId, channel = MH.CommunicationChannel.CHANNEL_USB):
|
|
701
|
+
"""
|
|
702
|
+
Builds command to activate a memory file offload procedure.
|
|
703
|
+
.. code-block:: python
|
|
704
|
+
|
|
705
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
706
|
+
cmd = Muse_Utils.Cmd_MemoryFileDownload(fileId=0)
|
|
707
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
708
|
+
|
|
709
|
+
Args:
|
|
710
|
+
fileId:
|
|
711
|
+
File identifier.
|
|
712
|
+
channel:
|
|
713
|
+
Communication channel over which the command will be sent.
|
|
714
|
+
"""
|
|
715
|
+
#Definition of message buffer
|
|
716
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_MEM_FILE_DOWNLOAD)
|
|
717
|
+
|
|
718
|
+
#Start file offload procedure
|
|
719
|
+
buffer[0] = MH.Command.CMD_MEM_FILE_DOWNLOAD.value
|
|
720
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_GET_MEM_FILE_DOWNLOAD.value - 2
|
|
721
|
+
|
|
722
|
+
#Set file identifier
|
|
723
|
+
valueBytes = fileId.to_bytes(2, byteorder='little')
|
|
724
|
+
buffer[2] = valueBytes[0]
|
|
725
|
+
buffer[3] = valueBytes[1]
|
|
726
|
+
|
|
727
|
+
#Set file offload channel (USB vs BLE)
|
|
728
|
+
buffer[4] = channel.value
|
|
729
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
730
|
+
buffer[4] = 0x00; #set by default to USB channel (if 0x01 it manages the BLE transfer)
|
|
731
|
+
|
|
732
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
733
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
734
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
735
|
+
|
|
736
|
+
return buffer
|
|
737
|
+
|
|
738
|
+
@staticmethod
|
|
739
|
+
def Cmd_GetClockOffset(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
740
|
+
"""Builds command to retrieve current clock offset.
|
|
741
|
+
|
|
742
|
+
Args:
|
|
743
|
+
channel: Communication channel over which the command will be sent.
|
|
744
|
+
"""
|
|
745
|
+
#Definition of message buffer
|
|
746
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_CLK_OFFSET)
|
|
747
|
+
|
|
748
|
+
#Get clock offset
|
|
749
|
+
buffer[0] = MH.Command.CMD_CLK_OFFSET.value + MH.READ_BIT_MASK
|
|
750
|
+
|
|
751
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
752
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
753
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
754
|
+
|
|
755
|
+
return buffer
|
|
756
|
+
|
|
757
|
+
@staticmethod
|
|
758
|
+
def Cmd_SetClockOffset(inOffset = 0, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
759
|
+
"""Builds command to trigger a clock offset estimation procedure.
|
|
760
|
+
|
|
761
|
+
Args:
|
|
762
|
+
inOffset: Allows to specify a custom clock offset to be set.
|
|
763
|
+
channel: Communication channel over which the command will be sent.
|
|
764
|
+
"""
|
|
765
|
+
#Definition of message buffer
|
|
766
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_SET_CLK_OFFSET)
|
|
767
|
+
|
|
768
|
+
#Set clock offset
|
|
769
|
+
buffer[0] = MH.Command.CMD_CLK_OFFSET.value
|
|
770
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_SET_CLK_OFFSET.value - 2
|
|
771
|
+
|
|
772
|
+
valueBytes = inOffset.to_bytes(8, byteorder="little")
|
|
773
|
+
buffer[9] = valueBytes[7]
|
|
774
|
+
buffer[8] = valueBytes[6]
|
|
775
|
+
buffer[7] = valueBytes[5]
|
|
776
|
+
buffer[6] = valueBytes[4]
|
|
777
|
+
buffer[5] = valueBytes[3]
|
|
778
|
+
buffer[4] = valueBytes[2]
|
|
779
|
+
buffer[3] = valueBytes[1]
|
|
780
|
+
buffer[2] = valueBytes[0]
|
|
781
|
+
|
|
782
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
783
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
784
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
785
|
+
|
|
786
|
+
return buffer
|
|
787
|
+
|
|
788
|
+
@staticmethod
|
|
789
|
+
def Cmd_EnterTimeSync(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
790
|
+
"""Builds command to enter timesync routine.
|
|
791
|
+
|
|
792
|
+
Args:
|
|
793
|
+
channel: Communication channel over which the command will be sent.
|
|
794
|
+
"""
|
|
795
|
+
#Definition of message buffer
|
|
796
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_ENTER_TIME_SYNC)
|
|
797
|
+
|
|
798
|
+
# Start timesync procedure
|
|
799
|
+
buffer[0] = MH.Command.CMD_TIME_SYNC.value
|
|
800
|
+
|
|
801
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
802
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
803
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
804
|
+
|
|
805
|
+
return buffer
|
|
806
|
+
|
|
807
|
+
@staticmethod
|
|
808
|
+
def Cmd_ExitTimeSync(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
809
|
+
"""Builds command to exit timesync routine.
|
|
810
|
+
|
|
811
|
+
Args:
|
|
812
|
+
channel: Communication channel over which the command will be sent.
|
|
813
|
+
"""
|
|
814
|
+
#Definition of message buffer
|
|
815
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_EXIT_TIME_SYNC)
|
|
816
|
+
|
|
817
|
+
#Stop timesync procedure
|
|
818
|
+
buffer[0] = MH.Command.CMD_EXIT_TIME_SYNC.value
|
|
819
|
+
|
|
820
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
821
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
822
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
823
|
+
|
|
824
|
+
return buffer
|
|
825
|
+
|
|
826
|
+
@staticmethod
|
|
827
|
+
def Cmd_SetSensorsFullScale(gyrFS: MH.GyroscopeFS, axlFS: MH.AccelerometerFS, magFS: MH.MagnetometerFS, hdrFS : MH.AccelerometerHDRFS, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
828
|
+
"""
|
|
829
|
+
Builds command to set a custom sensors full scale configuration.
|
|
830
|
+
.. code-block:: python
|
|
831
|
+
|
|
832
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
833
|
+
gyro_FS = MH.GyroscopeFS.GYR_FS_2000dps
|
|
834
|
+
axl_FS = MH.AccelerometerFS.AXL_FS_32g
|
|
835
|
+
mag_FS = MH.MagnetometerFS.MAG_FS_08G
|
|
836
|
+
hdr_FS = MH.AccelerometerHDRFS.HDR_FS_100g
|
|
837
|
+
cmd = Muse_Utils.Cmd_SetSensorsFullScale(gyro_FS, axl_FS, mag_FS, hdr_FS)
|
|
838
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
839
|
+
|
|
840
|
+
Args:
|
|
841
|
+
gyrFS:
|
|
842
|
+
Gyroscope full scale code.
|
|
843
|
+
axlFS:
|
|
844
|
+
Accelerometer full scale code.
|
|
845
|
+
magFS:
|
|
846
|
+
Magnetometer full scale code.
|
|
847
|
+
hdrFS:
|
|
848
|
+
High Dynamic Range (HDR) Accelerometer code
|
|
849
|
+
channel:
|
|
850
|
+
Communication channel over which the command will be sent.
|
|
851
|
+
"""
|
|
852
|
+
#Definition of message buffer
|
|
853
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_SET_SENSORS_FS)
|
|
854
|
+
|
|
855
|
+
#Set sensors full scale configuration
|
|
856
|
+
buffer[0] = MH.Command.CMD_SENSORS_FS.value
|
|
857
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_SET_SENSORS_FS.value - 2
|
|
858
|
+
|
|
859
|
+
#Build integer configuration code to be sent
|
|
860
|
+
buffer[2] = (axlFS.value | gyrFS.value | hdrFS.value | magFS.value)
|
|
861
|
+
|
|
862
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
863
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
864
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
865
|
+
|
|
866
|
+
return buffer
|
|
867
|
+
|
|
868
|
+
@staticmethod
|
|
869
|
+
def Cmd_GetSensorsFullScale(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
870
|
+
"""
|
|
871
|
+
Get the current stored sensors full scales.
|
|
872
|
+
.. code-block:: python
|
|
873
|
+
|
|
874
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
875
|
+
cmd = Muse_Utils.Cmd_GetSensorsFullScale()
|
|
876
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
877
|
+
|
|
878
|
+
Args:
|
|
879
|
+
channel:
|
|
880
|
+
Communication channel over which the command will be sent.
|
|
881
|
+
"""
|
|
882
|
+
#Definition of message buffer
|
|
883
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_SENSORS_FS)
|
|
884
|
+
|
|
885
|
+
#Get current sensors full scale configuration
|
|
886
|
+
buffer[0] = MH.Command.CMD_SENSORS_FS.value + MH.READ_BIT_MASK
|
|
887
|
+
|
|
888
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
889
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
890
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
891
|
+
|
|
892
|
+
return buffer
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
#CMD_CALIB_MATRIX = 0x48
|
|
896
|
+
@staticmethod
|
|
897
|
+
def Cmd_SetCalibrationMatrix(rowId: bytes, colId: bytes, r1: float, r2: float, r3: float, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
898
|
+
|
|
899
|
+
#Definition of message buffer
|
|
900
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_SET_CALIB_MATRIX)
|
|
901
|
+
|
|
902
|
+
#Set calibration matrix components
|
|
903
|
+
buffer[0] = MH.Command.CMD_CALIB_MATRIX.value
|
|
904
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_SET_CALIB_MATRIX.value - 2
|
|
905
|
+
|
|
906
|
+
#Payload
|
|
907
|
+
buffer[2] = rowId; #Row index in the range 0-2
|
|
908
|
+
buffer[3] = colId; #Column index in the range 0-3
|
|
909
|
+
|
|
910
|
+
# Values for a given row and col
|
|
911
|
+
valByteArray = struct.pack("<f", r1)
|
|
912
|
+
buffer[4:] = valByteArray[:]
|
|
913
|
+
valByteArray = struct.pack("<f", r2)
|
|
914
|
+
buffer[8:] = valByteArray[:]
|
|
915
|
+
valByteArray = struct.pack("<f", r3)
|
|
916
|
+
buffer[12:] = valByteArray[:]
|
|
917
|
+
|
|
918
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
919
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
920
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
return buffer
|
|
924
|
+
|
|
925
|
+
@staticmethod
|
|
926
|
+
def Cmd_GetCalibrationMatrix(calibrationType: bytes, colId: bytes, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
927
|
+
"""
|
|
928
|
+
Get a specific row of a calibration matrix.
|
|
929
|
+
.. code-block:: python
|
|
930
|
+
|
|
931
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
932
|
+
cmd = Muse_Utils.Cmd_GetCalibrationMatrix(calibrationType=0x01, colId=0)
|
|
933
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
934
|
+
|
|
935
|
+
Args:
|
|
936
|
+
calibrationType:
|
|
937
|
+
Define the MEMS calibration you want to retrieve (Accelerometer: 0x01, Gyroscope: 0x02, Magnetometer: 0x03).
|
|
938
|
+
colId:
|
|
939
|
+
Column index in the range 0-3.
|
|
940
|
+
channel:
|
|
941
|
+
Communication channel over which the command will be sent.
|
|
942
|
+
"""
|
|
943
|
+
#Definition of message buffer
|
|
944
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_CALIB_MATRIX)
|
|
945
|
+
|
|
946
|
+
#Get current calibration matrix values
|
|
947
|
+
buffer[0] = MH.Command.CMD_CALIB_MATRIX.value + MH.READ_BIT_MASK
|
|
948
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_GET_CALIB_MATRIX.value - 2
|
|
949
|
+
|
|
950
|
+
#Set row/col payload indexes to be retrieved
|
|
951
|
+
buffer[2] = calibrationType
|
|
952
|
+
buffer[3] = colId
|
|
953
|
+
|
|
954
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
955
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
956
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
957
|
+
|
|
958
|
+
return buffer
|
|
959
|
+
|
|
960
|
+
@staticmethod
|
|
961
|
+
def Cmd_SetButtonLogConfiguration(mode: MH.DataMode, frequency : MH.DataFrequency, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
962
|
+
"""
|
|
963
|
+
Set the button log configuration.
|
|
964
|
+
.. code-block:: python
|
|
965
|
+
|
|
966
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
967
|
+
cmd = Muse_Utils.Cmd_SetButtonLogConfiguration(mode=MH.DataMode.DATA_MODE_IMU, frequency=MH.DataFrequency.DATA_FREQ_50Hz)
|
|
968
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
969
|
+
|
|
970
|
+
Args:
|
|
971
|
+
mode:
|
|
972
|
+
Identifies the set of data to be acquired.
|
|
973
|
+
frequency:
|
|
974
|
+
Identifies the data acquisition frequency.
|
|
975
|
+
channel:
|
|
976
|
+
Communication channel over which the command will be sent.
|
|
977
|
+
"""
|
|
978
|
+
#Definition of message buffer
|
|
979
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_SET_BUTTON_LOG)
|
|
980
|
+
|
|
981
|
+
#Set log mode command
|
|
982
|
+
buffer[0] = MH.Command.CMD_BUTTON_LOG.value
|
|
983
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_SET_BUTTON_LOG.value - 2
|
|
984
|
+
|
|
985
|
+
#Set log mode code
|
|
986
|
+
tmp = struct.pack("I", mode.value)
|
|
987
|
+
buffer[2:5] = tmp[:3]
|
|
988
|
+
|
|
989
|
+
#Set log frequency
|
|
990
|
+
buffer[5] = frequency.value
|
|
991
|
+
|
|
992
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
993
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
994
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
return buffer
|
|
998
|
+
|
|
999
|
+
@staticmethod
|
|
1000
|
+
def Cmd_GetButtonLogConfiguration(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1001
|
+
"""
|
|
1002
|
+
Get the current button log configuration.
|
|
1003
|
+
.. code-block:: python
|
|
1004
|
+
|
|
1005
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1006
|
+
cmd = Muse_Utils.Cmd_GetButtonLogConfiguration()
|
|
1007
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1008
|
+
|
|
1009
|
+
Args:
|
|
1010
|
+
channel:
|
|
1011
|
+
Communication channel over which the command will be sent.
|
|
1012
|
+
"""
|
|
1013
|
+
#Definition of message buffer
|
|
1014
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_BUTTON_LOG)
|
|
1015
|
+
|
|
1016
|
+
#Get current log mode
|
|
1017
|
+
buffer[0] = MH.Command.CMD_BUTTON_LOG.value + MH.READ_BIT_MASK
|
|
1018
|
+
|
|
1019
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
1020
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
1021
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1022
|
+
|
|
1023
|
+
return buffer
|
|
1024
|
+
|
|
1025
|
+
@staticmethod
|
|
1026
|
+
def Cmd_GetUserConfiguration(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1027
|
+
"""
|
|
1028
|
+
Get the current user configuration parameters.
|
|
1029
|
+
.. code-block:: python
|
|
1030
|
+
|
|
1031
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1032
|
+
cmd = Muse_Utils.Cmd_GetUserConfiguration()
|
|
1033
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1034
|
+
|
|
1035
|
+
Args:
|
|
1036
|
+
channel:
|
|
1037
|
+
Communication channel over which the command will be sent.
|
|
1038
|
+
"""
|
|
1039
|
+
#Definition of message buffer
|
|
1040
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_USER_CONFIG)
|
|
1041
|
+
|
|
1042
|
+
#Get current user configuration
|
|
1043
|
+
buffer[0] = MH.Command.CMD_USER_CONFIG.value + MH.READ_BIT_MASK
|
|
1044
|
+
|
|
1045
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
1046
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
1047
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1048
|
+
|
|
1049
|
+
return buffer
|
|
1050
|
+
|
|
1051
|
+
@staticmethod
|
|
1052
|
+
def Cmd_SetUserConfiguration(standby: Optional[bool]=None, memory:Optional[bool]=None,
|
|
1053
|
+
streaming_channel:Optional[MH.StreamingChannel]=None, mpe9dof:Optional[bool]=None,
|
|
1054
|
+
slowfreq:Optional[bool]=None, channel=MH.CommunicationChannel.CHANNEL_BLE):
|
|
1055
|
+
"""
|
|
1056
|
+
Set the User Configuration.
|
|
1057
|
+
.. code-block:: python
|
|
1058
|
+
|
|
1059
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1060
|
+
# Enable Standby
|
|
1061
|
+
cmd = Muse_Utils.Cmd_SetUserConfiguration(standby = True)
|
|
1062
|
+
# Enable BLE channel for streaming
|
|
1063
|
+
cmd = Muse_Utils.Cmd_SetUserConfiguration(streaming_channel = MH.StreamingChannel.CHANNEL_BLE)
|
|
1064
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1065
|
+
|
|
1066
|
+
Args:
|
|
1067
|
+
standby (bool):
|
|
1068
|
+
It allows to enable (True) or disable (False) automatic standby. If enabled, the device will move to standby condition after 120 seconds of inactivity. The default value is ENABLED (value: 1). The system can also be forced into standby by using the button when the automatic standby is disabled. If the device is connected, the system is prevented from going into standby condition.
|
|
1069
|
+
memory (bool):
|
|
1070
|
+
It allows to enable (True) or disable (False) memory management using a circular buffer instead of a linear one. The default value is DISABLED (value: 0). If enabled, the memory is treated as a circular buffer, which means that when the memory runs out, the oldest data is deleted to make space for new. This means that a log can never be interrupted by an end-of-memory condition.
|
|
1071
|
+
streaming_channel (Muse_HW.StreamingChannel):
|
|
1072
|
+
It allows to select the streaming channel. It is mutually exlusive among BLE, USB, TCP and MQTT.
|
|
1073
|
+
mpe9dof (bool):
|
|
1074
|
+
It allows to enable (True) or disable (False) the use of the magnetometer in the MPE. The default value is DISABLED (value: 0). If enabled, it indicates that the MPE algorithm will take into account the magnetometer in its orientation estimation.
|
|
1075
|
+
slowfreq (bool):
|
|
1076
|
+
It allows to enable (True) or disable (False) the use of the slow frequency mode.
|
|
1077
|
+
channel (Muse_HW.CommunicationChannel):
|
|
1078
|
+
Communication channel over which the command will be sent.
|
|
1079
|
+
|
|
1080
|
+
"""
|
|
1081
|
+
# Definition of message buffer
|
|
1082
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_SET_USER_CONFIG)
|
|
1083
|
+
|
|
1084
|
+
# Set a custom user configuration
|
|
1085
|
+
buffer[0] = MH.Command.CMD_USER_CONFIG.value
|
|
1086
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_SET_USER_CONFIG.value - 2
|
|
1087
|
+
|
|
1088
|
+
# Initialize bit-mask
|
|
1089
|
+
bitMask = 0
|
|
1090
|
+
|
|
1091
|
+
# Build configuration code to be sent using user input
|
|
1092
|
+
config_code = 0
|
|
1093
|
+
if not(standby is None):
|
|
1094
|
+
bitMask = bitMask + MH.UserConfigMask.USER_CFG_MASK_AUTO_STANDBY.value
|
|
1095
|
+
if (standby):
|
|
1096
|
+
config_code |= MH.UserConfigMask.USER_CFG_MASK_AUTO_STANDBY.value
|
|
1097
|
+
if not(memory is None):
|
|
1098
|
+
bitMask = bitMask + MH.UserConfigMask.USER_CFG_MASK_CIRCULAR_MEMORY.value
|
|
1099
|
+
if (memory):
|
|
1100
|
+
config_code |= MH.UserConfigMask.USER_CFG_MASK_CIRCULAR_MEMORY.value
|
|
1101
|
+
|
|
1102
|
+
# STEAMING configurations are mutually exclusive
|
|
1103
|
+
if not(streaming_channel is None):
|
|
1104
|
+
|
|
1105
|
+
bitMask = bitMask + MH.UserConfigMask.USER_CFG_MASK_STREAMING_CHANNEL.value
|
|
1106
|
+
|
|
1107
|
+
mqttcommands=False
|
|
1108
|
+
if (streaming_channel == MH.StreamingChannel.CHANNEL_BLE):
|
|
1109
|
+
config_code |= MH.UserConfigMask.USER_CFG_MASK_BLE_STREAM.value
|
|
1110
|
+
elif (streaming_channel == MH.StreamingChannel.CHANNEL_USB):
|
|
1111
|
+
config_code |= MH.UserConfigMask.USER_CFG_MASK_USB_STREAM.value
|
|
1112
|
+
elif (streaming_channel == MH.StreamingChannel.CHANNEL_TCP):
|
|
1113
|
+
config_code |= MH.UserConfigMask.USER_CFG_MASK_TCP_STREAM.value
|
|
1114
|
+
mqttcommands = True
|
|
1115
|
+
elif (streaming_channel == MH.StreamingChannel.CHANNEL_MQTT):
|
|
1116
|
+
config_code |= MH.UserConfigMask.USER_CFG_MASK_MQTT_STREAM.value
|
|
1117
|
+
mqttcommands = True
|
|
1118
|
+
|
|
1119
|
+
# Update mqtt commands flag
|
|
1120
|
+
bitMask = bitMask + MH.UserConfigMask.USER_CFG_MASK_MQTT_COMMANDS.value
|
|
1121
|
+
if (mqttcommands):
|
|
1122
|
+
config_code |= MH.UserConfigMask.USER_CFG_MASK_MQTT_COMMANDS.value
|
|
1123
|
+
|
|
1124
|
+
|
|
1125
|
+
if not(mpe9dof is None):
|
|
1126
|
+
bitMask = bitMask + MH.UserConfigMask.USER_CFG_MASK_9DOF_MPE.value
|
|
1127
|
+
if (mpe9dof):
|
|
1128
|
+
config_code |= MH.UserConfigMask.USER_CFG_MASK_9DOF_MPE.value
|
|
1129
|
+
if not(slowfreq is None):
|
|
1130
|
+
bitMask = bitMask + MH.UserConfigMask.USER_CFG_MASK_SLOW_FREQUENCY.value
|
|
1131
|
+
if (slowfreq):
|
|
1132
|
+
config_code |= MH.UserConfigMask.USER_CFG_MASK_SLOW_FREQUENCY.value
|
|
1133
|
+
|
|
1134
|
+
# Set bit-mask
|
|
1135
|
+
tmp = bitMask.to_bytes(2, byteorder='little')
|
|
1136
|
+
buffer[2:4] = tmp
|
|
1137
|
+
|
|
1138
|
+
# Set configuration code
|
|
1139
|
+
tmp = config_code.to_bytes(2, byteorder='little')
|
|
1140
|
+
buffer[4:6] = tmp
|
|
1141
|
+
|
|
1142
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1143
|
+
if channel == MH.CommunicationChannel.CHANNEL_USB:
|
|
1144
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1145
|
+
|
|
1146
|
+
return bytes(buffer)
|
|
1147
|
+
|
|
1148
|
+
# WiFi commands
|
|
1149
|
+
|
|
1150
|
+
@staticmethod
|
|
1151
|
+
def Cmd_SetWifiSSIDHead(ssid: str, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1152
|
+
"""
|
|
1153
|
+
Set the SSID for WiFi connection (header part).
|
|
1154
|
+
.. code-block:: python
|
|
1155
|
+
|
|
1156
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1157
|
+
SSID_string = "221e_wifi"
|
|
1158
|
+
cmd = Muse_Utils.Cmd_SetWifiSSIDHead(ssid = SSID_string)
|
|
1159
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1160
|
+
|
|
1161
|
+
Args:
|
|
1162
|
+
ssid (str):
|
|
1163
|
+
It is a 2 up to 32 bytes hex string representing the SSID to be set.
|
|
1164
|
+
channel:
|
|
1165
|
+
Communication channel over which the command will be sent.
|
|
1166
|
+
"""
|
|
1167
|
+
# Definition of message buffer
|
|
1168
|
+
buffer = bytearray()
|
|
1169
|
+
|
|
1170
|
+
#Check bleName to be set consistency before proceeding
|
|
1171
|
+
if (ssid != "" and len(ssid) <= 18):
|
|
1172
|
+
|
|
1173
|
+
# Definition of message buffer
|
|
1174
|
+
buffer = bytearray(len(ssid))
|
|
1175
|
+
|
|
1176
|
+
# Set the SSID of the network – head part
|
|
1177
|
+
buffer[0] = MH.Command.CMD_WIFI_SSID_HEAD.value
|
|
1178
|
+
buffer[1] = len(ssid)
|
|
1179
|
+
|
|
1180
|
+
for i in range(len(ssid)):
|
|
1181
|
+
buffer[2 + i:] = bytearray(ssid[i],'utf-8')
|
|
1182
|
+
|
|
1183
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1184
|
+
if channel == MH.CommunicationChannel.CHANNEL_USB:
|
|
1185
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1186
|
+
|
|
1187
|
+
return buffer
|
|
1188
|
+
|
|
1189
|
+
@staticmethod
|
|
1190
|
+
def Cmd_SetWifiSSIDCont(ssid: str, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1191
|
+
"""
|
|
1192
|
+
Set the SSID for WiFi connection (continuation part).
|
|
1193
|
+
.. code-block:: python
|
|
1194
|
+
|
|
1195
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1196
|
+
SSID_string = "221e_wifi_with_long_SSID"
|
|
1197
|
+
# Send the first part of SSID to be set
|
|
1198
|
+
cmd = Muse_Utils.Cmd_SetWifiSSIDHead(ssid = SSID_string[:18])
|
|
1199
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1200
|
+
# Send the remaining part of SSID to be set
|
|
1201
|
+
cmd = Muse_Utils.Cmd_SetWifiSSIDCont(ssid = SSID_string[18:])
|
|
1202
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1203
|
+
|
|
1204
|
+
Args:
|
|
1205
|
+
ssid (str):
|
|
1206
|
+
It is a 2 up to 32 bytes hex string representing the SSID to be set.
|
|
1207
|
+
channel:
|
|
1208
|
+
Communication channel over which the command will be sent.
|
|
1209
|
+
"""
|
|
1210
|
+
# Definition of message buffer
|
|
1211
|
+
buffer = bytearray()
|
|
1212
|
+
|
|
1213
|
+
#Check bleName to be set consistency before proceeding
|
|
1214
|
+
if (ssid != "" and len(ssid) <= 14):
|
|
1215
|
+
|
|
1216
|
+
# Definition of message buffer
|
|
1217
|
+
buffer = bytearray(len(ssid))
|
|
1218
|
+
|
|
1219
|
+
# Set the SSID of the network – head part
|
|
1220
|
+
buffer[0] = MH.Command.CMD_WIFI_SSID_CONT.value
|
|
1221
|
+
buffer[1] = len(ssid)
|
|
1222
|
+
|
|
1223
|
+
for i in range(len(ssid)):
|
|
1224
|
+
buffer[2 + i:] = bytearray(ssid[i],'utf-8')
|
|
1225
|
+
|
|
1226
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1227
|
+
if channel == MH.CommunicationChannel.CHANNEL_USB:
|
|
1228
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1229
|
+
|
|
1230
|
+
return buffer
|
|
1231
|
+
|
|
1232
|
+
@staticmethod
|
|
1233
|
+
def Cmd_SetWifiPassowrdHead(password: str, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1234
|
+
"""
|
|
1235
|
+
Set the password for WiFi connection (header part).
|
|
1236
|
+
.. code-block:: python
|
|
1237
|
+
|
|
1238
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1239
|
+
password_string = "221e_wifiPassword"
|
|
1240
|
+
cmd = Muse_Utils.Cmd_SetWifiPassowrdHead(password = password_string)
|
|
1241
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1242
|
+
|
|
1243
|
+
Args:
|
|
1244
|
+
password (str):
|
|
1245
|
+
It is a hex string representing the password to be set.
|
|
1246
|
+
channel:
|
|
1247
|
+
Communication channel over which the command will be sent.
|
|
1248
|
+
"""
|
|
1249
|
+
# Definition of message buffer
|
|
1250
|
+
buffer = bytearray()
|
|
1251
|
+
|
|
1252
|
+
#Check bleName to be set consistency before proceeding
|
|
1253
|
+
if (password != "" and len(password) <= 18):
|
|
1254
|
+
|
|
1255
|
+
# Definition of message buffer
|
|
1256
|
+
buffer = bytearray(len(password))
|
|
1257
|
+
|
|
1258
|
+
# Set the Password of the network – head part
|
|
1259
|
+
buffer[0] = MH.Command.CMD_WIFI_PSW_HEAD.value
|
|
1260
|
+
buffer[1] = len(password)
|
|
1261
|
+
|
|
1262
|
+
for i in range(len(password)):
|
|
1263
|
+
buffer[2 + i:] = bytearray(password[i],'utf-8')
|
|
1264
|
+
|
|
1265
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1266
|
+
if channel == MH.CommunicationChannel.CHANNEL_USB:
|
|
1267
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1268
|
+
|
|
1269
|
+
return buffer
|
|
1270
|
+
|
|
1271
|
+
@staticmethod
|
|
1272
|
+
def Cmd_SetWifiPassowrdCont(password: str, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1273
|
+
"""
|
|
1274
|
+
Set the password for WiFi connection (header part).
|
|
1275
|
+
.. code-block:: python
|
|
1276
|
+
|
|
1277
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1278
|
+
password_string = "221e_very_long_wifi_password"
|
|
1279
|
+
# Send the first part of the password to be set
|
|
1280
|
+
cmd = Muse_Utils.Cmd_SetWifiPassowrdHead(password = password_string[:18])
|
|
1281
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1282
|
+
# Send continuation part of the password to be set
|
|
1283
|
+
cmd = Muse_Utils.Cmd_SetWifiPassowrdCont(password = password_string[18:])
|
|
1284
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1285
|
+
|
|
1286
|
+
Args:
|
|
1287
|
+
password (str):
|
|
1288
|
+
It is a hex string representing the password to be set.
|
|
1289
|
+
channel:
|
|
1290
|
+
Communication channel over which the command will be sent.
|
|
1291
|
+
"""
|
|
1292
|
+
# Definition of message buffer
|
|
1293
|
+
buffer = bytearray()
|
|
1294
|
+
|
|
1295
|
+
#Check bleName to be set consistency before proceeding
|
|
1296
|
+
if (password != "" and len(password) <= 18):
|
|
1297
|
+
|
|
1298
|
+
# Definition of message buffer
|
|
1299
|
+
buffer = bytearray(len(password))
|
|
1300
|
+
|
|
1301
|
+
# Set the Password of the network – head part
|
|
1302
|
+
buffer[0] = MH.Command.CMD_WIFI_PSW_CONT.value
|
|
1303
|
+
buffer[1] = len(password)
|
|
1304
|
+
|
|
1305
|
+
for i in range(len(password)):
|
|
1306
|
+
buffer[2 + i:] = bytearray(password[i],'utf-8')
|
|
1307
|
+
|
|
1308
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1309
|
+
if channel == MH.CommunicationChannel.CHANNEL_USB:
|
|
1310
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1311
|
+
|
|
1312
|
+
return buffer
|
|
1313
|
+
|
|
1314
|
+
@staticmethod
|
|
1315
|
+
def Cmd_SetWifiStreamHostHead(hostname: str, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1316
|
+
"""
|
|
1317
|
+
Set the hostname for WiFi connection (header part).
|
|
1318
|
+
.. code-block:: python
|
|
1319
|
+
|
|
1320
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1321
|
+
host = "192.168.137.1"
|
|
1322
|
+
cmd = Muse_Utils.Cmd_SetWifiStreamHostHead(hostname = host)
|
|
1323
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1324
|
+
|
|
1325
|
+
Args:
|
|
1326
|
+
hostname (str):
|
|
1327
|
+
It is a hex string representing the hostname to be set.
|
|
1328
|
+
channel:
|
|
1329
|
+
Communication channel over which the command will be sent.
|
|
1330
|
+
"""
|
|
1331
|
+
# Definition of message buffer
|
|
1332
|
+
buffer = bytearray()
|
|
1333
|
+
|
|
1334
|
+
#Check bleName to be set consistency before proceeding
|
|
1335
|
+
if (hostname != "" and len(hostname) <= 18):
|
|
1336
|
+
|
|
1337
|
+
# Definition of message buffer
|
|
1338
|
+
buffer = bytearray(len(hostname))
|
|
1339
|
+
|
|
1340
|
+
# Set the Host of the network – head part
|
|
1341
|
+
buffer[0] = MH.Command.CMD_WIFI_STREAM_HOST_HEAD.value
|
|
1342
|
+
buffer[1] = len(hostname)
|
|
1343
|
+
|
|
1344
|
+
for i in range(len(hostname)):
|
|
1345
|
+
buffer[2 + i:] = bytearray(hostname[i],'utf-8')
|
|
1346
|
+
|
|
1347
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1348
|
+
if channel == MH.CommunicationChannel.CHANNEL_USB:
|
|
1349
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1350
|
+
|
|
1351
|
+
return buffer
|
|
1352
|
+
|
|
1353
|
+
@staticmethod
|
|
1354
|
+
def Cmd_SetWifiStreamHostCont(hostname: str, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1355
|
+
"""
|
|
1356
|
+
Set the hostname for WiFi connection (continuation part).
|
|
1357
|
+
.. code-block:: python
|
|
1358
|
+
|
|
1359
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1360
|
+
host = "my_very_long_hostname.com"
|
|
1361
|
+
# header part
|
|
1362
|
+
cmd = Muse_Utils.Cmd_SetWifiStreamHostHead(hostname = host[:18])
|
|
1363
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1364
|
+
# continuation part
|
|
1365
|
+
cmd = Muse_Utils.Cmd_SetWifiStreamHostCont(hostname = host[18:])
|
|
1366
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1367
|
+
|
|
1368
|
+
Args:
|
|
1369
|
+
hostname (str):
|
|
1370
|
+
It is a hex string representing the continuation part of hostname to be set.
|
|
1371
|
+
channel:
|
|
1372
|
+
Communication channel over which the command will be sent.
|
|
1373
|
+
"""
|
|
1374
|
+
# Definition of message buffer
|
|
1375
|
+
buffer = bytearray()
|
|
1376
|
+
|
|
1377
|
+
#Check bleName to be set consistency before proceeding
|
|
1378
|
+
if (hostname != "" and len(hostname) <= 18):
|
|
1379
|
+
|
|
1380
|
+
# Definition of message buffer
|
|
1381
|
+
buffer = bytearray(len(hostname))
|
|
1382
|
+
|
|
1383
|
+
# Set the Host of the network – head part
|
|
1384
|
+
buffer[0] = MH.Command.CMD_WIFI_STREAM_HOST_CONT.value
|
|
1385
|
+
buffer[1] = len(hostname)
|
|
1386
|
+
|
|
1387
|
+
for i in range(len(hostname)):
|
|
1388
|
+
buffer[2 + i:] = bytearray(hostname[i],'utf-8')
|
|
1389
|
+
|
|
1390
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1391
|
+
if channel == MH.CommunicationChannel.CHANNEL_USB:
|
|
1392
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1393
|
+
|
|
1394
|
+
return buffer
|
|
1395
|
+
|
|
1396
|
+
@staticmethod
|
|
1397
|
+
def Cmd_SetWifiStreamHostPort(port: int, channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1398
|
+
"""
|
|
1399
|
+
Set the hostname for WiFi connection (header part).
|
|
1400
|
+
.. code-block:: python
|
|
1401
|
+
|
|
1402
|
+
CMD_UUID = "d5913036-2d8a-41ee-85b9-4e361aa5c8a7"
|
|
1403
|
+
host_port = 1883
|
|
1404
|
+
cmd = Muse_Utils.Cmd_GetWifiStreamHostHead(port = host_port)
|
|
1405
|
+
await client.write_gatt_char(char_specifier=CMD_UUID, data=cmd, response=True)
|
|
1406
|
+
|
|
1407
|
+
Args:
|
|
1408
|
+
port (int):
|
|
1409
|
+
It is a 16-bit unsigned integer representing the host port to which the muse device will be connected to.
|
|
1410
|
+
channel:
|
|
1411
|
+
Communication channel over which the command will be sent.
|
|
1412
|
+
"""
|
|
1413
|
+
# Definition of message buffer
|
|
1414
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_SET_WIFI_STREAM_HOST_PORT)
|
|
1415
|
+
|
|
1416
|
+
# Set the Host of the network – head part
|
|
1417
|
+
buffer[0] = MH.Command.CMD_WIFI_STREAM_HOST_PORT.value
|
|
1418
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_SET_WIFI_STREAM_HOST_PORT.value - 2
|
|
1419
|
+
|
|
1420
|
+
payload = struct.pack('<H', port)
|
|
1421
|
+
|
|
1422
|
+
buffer[2:] = payload[:]
|
|
1423
|
+
|
|
1424
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1425
|
+
if channel == MH.CommunicationChannel.CHANNEL_USB:
|
|
1426
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1427
|
+
|
|
1428
|
+
return buffer
|
|
1429
|
+
|
|
1430
|
+
@staticmethod
|
|
1431
|
+
def Cmd_GetWifiSSIDHead(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1432
|
+
"""
|
|
1433
|
+
Get the SSID currently set for WiFi connection (header part).
|
|
1434
|
+
.. code-block:: python
|
|
1435
|
+
|
|
1436
|
+
SSID_head = Muse_Utils.Cmd_GetWifiSSIDHead(channel = MH.CommunicationChannel.CHANNEL_BLE)
|
|
1437
|
+
print(SSID_head)
|
|
1438
|
+
|
|
1439
|
+
Args:
|
|
1440
|
+
channel:
|
|
1441
|
+
Communication channel over which the command will be sent.
|
|
1442
|
+
"""
|
|
1443
|
+
#Definition of message buffer
|
|
1444
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_WIFI_SSID_HEAD)
|
|
1445
|
+
|
|
1446
|
+
#Get device name (i.e., ble name)
|
|
1447
|
+
buffer[0] = MH.Command.CMD_WIFI_SSID_HEAD.value + MH.READ_BIT_MASK
|
|
1448
|
+
|
|
1449
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
1450
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
1451
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1452
|
+
|
|
1453
|
+
return buffer
|
|
1454
|
+
|
|
1455
|
+
@staticmethod
|
|
1456
|
+
def Cmd_GetWifiSSIDCont(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1457
|
+
"""
|
|
1458
|
+
Get the SSID currently set for WiFi connection (continuation part).
|
|
1459
|
+
.. code-block:: python
|
|
1460
|
+
|
|
1461
|
+
SSID_continuation = Muse_Utils.Cmd_GetWifiSSIDCont(channel = MH.CommunicationChannel.CHANNEL_BLE)
|
|
1462
|
+
print(SSID_continuation)
|
|
1463
|
+
|
|
1464
|
+
Args:
|
|
1465
|
+
channel:
|
|
1466
|
+
Communication channel over which the command will be sent.
|
|
1467
|
+
"""
|
|
1468
|
+
#Definition of message buffer
|
|
1469
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_WIFI_SSID_CONT)
|
|
1470
|
+
|
|
1471
|
+
buffer[0] = MH.Command.CMD_WIFI_SSID_CONT.value + MH.READ_BIT_MASK
|
|
1472
|
+
|
|
1473
|
+
#Wrap message with header and trailer in the case of USB communication
|
|
1474
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
1475
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1476
|
+
|
|
1477
|
+
return buffer
|
|
1478
|
+
|
|
1479
|
+
@staticmethod
|
|
1480
|
+
def Cmd_GetWifiStreamHostHead(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1481
|
+
"""
|
|
1482
|
+
Get the hostname currently set for WiFi connection (header part).
|
|
1483
|
+
.. code-block:: python
|
|
1484
|
+
|
|
1485
|
+
host_head = Muse_Utils.Cmd_GetWifiStreamHostHead(channel = MH.CommunicationChannel.CHANNEL_BLE)
|
|
1486
|
+
print(host_head)
|
|
1487
|
+
|
|
1488
|
+
Args:
|
|
1489
|
+
channel:
|
|
1490
|
+
Communication channel over which the command will be sent.
|
|
1491
|
+
"""
|
|
1492
|
+
# Definition of message buffer
|
|
1493
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_WIFI_STREAM_HOST_HEAD)
|
|
1494
|
+
|
|
1495
|
+
# Set the header part of Host of the network
|
|
1496
|
+
buffer[0] = MH.Command.CMD_WIFI_STREAM_HOST_HEAD.value + MH.READ_BIT_MASK
|
|
1497
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_GET_WIFI_STREAM_HOST_HEAD.value - 2
|
|
1498
|
+
|
|
1499
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1500
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
1501
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1502
|
+
|
|
1503
|
+
return buffer
|
|
1504
|
+
|
|
1505
|
+
@staticmethod
|
|
1506
|
+
def Cmd_GetWifiStreamHostCont(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1507
|
+
"""
|
|
1508
|
+
Get the hostname currently set for WiFi connection (continuation part).
|
|
1509
|
+
.. code-block:: python
|
|
1510
|
+
|
|
1511
|
+
host_continuation = Muse_Utils.Cmd_GetWifiStreamHostCont(channel = MH.CommunicationChannel.CHANNEL_BLE)
|
|
1512
|
+
print(host_continuation)
|
|
1513
|
+
|
|
1514
|
+
Args:
|
|
1515
|
+
channel:
|
|
1516
|
+
Communication channel over which the command will be sent.
|
|
1517
|
+
"""
|
|
1518
|
+
# Definition of message buffer
|
|
1519
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_WIFI_STREAM_HOST_CONT)
|
|
1520
|
+
|
|
1521
|
+
# Set the continuation part of Host of the network
|
|
1522
|
+
buffer[0] = MH.Command.CMD_WIFI_STREAM_HOST_CONT.value + MH.READ_BIT_MASK
|
|
1523
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_GET_WIFI_STREAM_HOST_CONT.value - 2
|
|
1524
|
+
|
|
1525
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1526
|
+
if (channel == MH.CommunicationChannel.CHANNEL_USB):
|
|
1527
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1528
|
+
|
|
1529
|
+
return buffer
|
|
1530
|
+
|
|
1531
|
+
@staticmethod
|
|
1532
|
+
def Cmd_GetWifiStreamHostPort(channel = MH.CommunicationChannel.CHANNEL_BLE):
|
|
1533
|
+
"""
|
|
1534
|
+
Get the host port set for WiFi connection.
|
|
1535
|
+
.. code-block:: python
|
|
1536
|
+
|
|
1537
|
+
port = Muse_Utils.Cmd_GetWifiStreamHostPort(channel = MH.CommunicationChannel.CHANNEL_BLE)
|
|
1538
|
+
print(port)
|
|
1539
|
+
|
|
1540
|
+
Args:
|
|
1541
|
+
channel:
|
|
1542
|
+
Communication channel over which the command will be sent.
|
|
1543
|
+
"""
|
|
1544
|
+
# Definition of message buffer
|
|
1545
|
+
buffer = bytearray(MH.CommandLength.CMD_LENGTH_GET_WIFI_STREAM_HOST_PORT)
|
|
1546
|
+
|
|
1547
|
+
# Set the Port of the network
|
|
1548
|
+
buffer[0] = MH.Command.CMD_WIFI_STREAM_HOST_PORT.value + MH.READ_BIT_MASK
|
|
1549
|
+
buffer[1] = MH.CommandLength.CMD_LENGTH_GET_WIFI_STREAM_HOST_PORT.value - 2
|
|
1550
|
+
|
|
1551
|
+
# Wrap message with header and trailer in the case of USB communication
|
|
1552
|
+
if channel == MH.CommunicationChannel.CHANNEL_USB:
|
|
1553
|
+
return Muse_Utils._WrapMessage(buffer)
|
|
1554
|
+
|
|
1555
|
+
return buffer
|
|
1556
|
+
|
|
1557
|
+
# end ENCODING COMMAND IMPLEMENTATION
|
|
1558
|
+
|
|
1559
|
+
# DECODING FUNCTIONS
|
|
1560
|
+
|
|
1561
|
+
@staticmethod
|
|
1562
|
+
def ParseCommandCharacteristic(channel: MH.CommunicationChannel, buffer: bytearray):
|
|
1563
|
+
"""
|
|
1564
|
+
Parse command characteristic to get a command response object. Manage also header and trailer removal in case of BLE or USB channel
|
|
1565
|
+
|
|
1566
|
+
Args:
|
|
1567
|
+
channel:
|
|
1568
|
+
Communication channel over which the command will be sent.
|
|
1569
|
+
buffer (bytearray):
|
|
1570
|
+
Byte array to be parsed.
|
|
1571
|
+
|
|
1572
|
+
Returns:
|
|
1573
|
+
response:
|
|
1574
|
+
CommandResponse type output
|
|
1575
|
+
"""
|
|
1576
|
+
if (channel == MH.CommunicationChannel.CHANNEL_BLE):
|
|
1577
|
+
response = CommandResponse(buffer)
|
|
1578
|
+
else:
|
|
1579
|
+
response = CommandResponse(Muse_Utils._ExtractMessage(buffer))
|
|
1580
|
+
|
|
1581
|
+
return response
|
|
1582
|
+
|
|
1583
|
+
@staticmethod
|
|
1584
|
+
def Dec_SystemState(response: CommandResponse):
|
|
1585
|
+
"""
|
|
1586
|
+
Decode system state.
|
|
1587
|
+
|
|
1588
|
+
Args:
|
|
1589
|
+
response:
|
|
1590
|
+
CommandResponse object to be decoded.
|
|
1591
|
+
|
|
1592
|
+
Returns:
|
|
1593
|
+
state:
|
|
1594
|
+
Output reference to the SystemState value.
|
|
1595
|
+
"""
|
|
1596
|
+
state = MH.SystemState.SYS_NONE.value
|
|
1597
|
+
|
|
1598
|
+
#Decode system state given command response
|
|
1599
|
+
if ((response.tx & 0x7F) == MH.Command.CMD_STATE.value and
|
|
1600
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1601
|
+
|
|
1602
|
+
state = response.payload[0]
|
|
1603
|
+
|
|
1604
|
+
return state
|
|
1605
|
+
|
|
1606
|
+
@staticmethod
|
|
1607
|
+
def Dec_ApplicationInfo(response: CommandResponse):
|
|
1608
|
+
"""
|
|
1609
|
+
Decode firmware application information.
|
|
1610
|
+
|
|
1611
|
+
Args:
|
|
1612
|
+
response:
|
|
1613
|
+
CommandResponse object to be decoded.
|
|
1614
|
+
|
|
1615
|
+
Returns:
|
|
1616
|
+
(crc, length):
|
|
1617
|
+
- Output reference to the Circular Redundancy Check (CRC) as 32-bit unsigned integer.
|
|
1618
|
+
- Output reference to the length of the application firmware (i.e., number of bytes), as a 32-bit unsigned integer.
|
|
1619
|
+
"""
|
|
1620
|
+
crc = 0
|
|
1621
|
+
length = 0
|
|
1622
|
+
|
|
1623
|
+
#Decode firmware application info given command response payload
|
|
1624
|
+
if ( response.tx == MH.Command.CMD_APP_INFO and
|
|
1625
|
+
response.ack== MH.AcknowledgeType.ACK_SUCCESS.value):
|
|
1626
|
+
|
|
1627
|
+
crc = int.from_bytes(response.payload[:4], byteorder='little', signed=False)
|
|
1628
|
+
length = int.from_bytes(response.payload[4: ], byteorder='little', signed=False)
|
|
1629
|
+
|
|
1630
|
+
return crc, length
|
|
1631
|
+
|
|
1632
|
+
@staticmethod
|
|
1633
|
+
def Dec_BatteryCharge(response: CommandResponse):
|
|
1634
|
+
"""
|
|
1635
|
+
Decode battery charge level.
|
|
1636
|
+
|
|
1637
|
+
Args:
|
|
1638
|
+
response:
|
|
1639
|
+
CommandResponse object to be decoded.
|
|
1640
|
+
|
|
1641
|
+
Returns:
|
|
1642
|
+
charge:
|
|
1643
|
+
Output reference to battery charge value [%].
|
|
1644
|
+
"""
|
|
1645
|
+
charge = -1
|
|
1646
|
+
|
|
1647
|
+
#Decode battery charge percentage value given command response payload
|
|
1648
|
+
if (response.tx == MH.Command.CMD_BATTERY_CHARGE and
|
|
1649
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS.value):
|
|
1650
|
+
|
|
1651
|
+
charge = response.payload[0]
|
|
1652
|
+
|
|
1653
|
+
return charge
|
|
1654
|
+
|
|
1655
|
+
@staticmethod
|
|
1656
|
+
def Dec_BatteryVoltage(response: CommandResponse):
|
|
1657
|
+
"""
|
|
1658
|
+
Decode battery voltage level.
|
|
1659
|
+
|
|
1660
|
+
Args:
|
|
1661
|
+
response:
|
|
1662
|
+
CommandResponse object to be decoded.
|
|
1663
|
+
|
|
1664
|
+
Returns:
|
|
1665
|
+
voltage:
|
|
1666
|
+
Output reference to battery voltage value [mV].
|
|
1667
|
+
"""
|
|
1668
|
+
#Decode battery voltage [mV] value given command response payload
|
|
1669
|
+
if (response.tx == MH.Command.CMD_BATTERY_VOLTAGE and
|
|
1670
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS.value):
|
|
1671
|
+
|
|
1672
|
+
voltage = struct.unpack('<H', response.payload)[0]
|
|
1673
|
+
|
|
1674
|
+
return voltage
|
|
1675
|
+
|
|
1676
|
+
@staticmethod
|
|
1677
|
+
def Dec_CheckUp(response: CommandResponse):
|
|
1678
|
+
"""
|
|
1679
|
+
Decode check-up register code.
|
|
1680
|
+
|
|
1681
|
+
Args:
|
|
1682
|
+
response:
|
|
1683
|
+
CommandResponse object to be decoded.
|
|
1684
|
+
|
|
1685
|
+
Returns:
|
|
1686
|
+
checkup:
|
|
1687
|
+
Output reference to check-up register code.
|
|
1688
|
+
"""
|
|
1689
|
+
#Decode checkup register value, as string, given the command response payload
|
|
1690
|
+
tmpOut = ""
|
|
1691
|
+
|
|
1692
|
+
#Decode current checkup register value given command response payload
|
|
1693
|
+
if (response.tx == MH.Command.CMD_CHECK_UP and
|
|
1694
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1695
|
+
|
|
1696
|
+
for i in range(response.len-2):
|
|
1697
|
+
tmpOut += format(response.payload[i], '02X') + ' '
|
|
1698
|
+
|
|
1699
|
+
checkup = tmpOut
|
|
1700
|
+
|
|
1701
|
+
return checkup
|
|
1702
|
+
|
|
1703
|
+
@staticmethod
|
|
1704
|
+
def Dec_FirmwareVersion(response: CommandResponse):
|
|
1705
|
+
"""
|
|
1706
|
+
Decode firmware version labels.
|
|
1707
|
+
|
|
1708
|
+
Args:
|
|
1709
|
+
response:
|
|
1710
|
+
CommandResponse object to be decoded.
|
|
1711
|
+
|
|
1712
|
+
Returns:
|
|
1713
|
+
(bootrev, apprev):
|
|
1714
|
+
- bootrev: Output reference to boot loader firmware version label.
|
|
1715
|
+
- apprev: Output reference to application firmware version label.
|
|
1716
|
+
"""
|
|
1717
|
+
boot_rev = "x.x.x"
|
|
1718
|
+
app_rev = "x.x.x"
|
|
1719
|
+
|
|
1720
|
+
#Decode current firmware versions given command response payload
|
|
1721
|
+
if (response.tx == MH.Command.CMD_FW_VERSION and
|
|
1722
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1723
|
+
|
|
1724
|
+
#Decode bootloader and application firmware versions
|
|
1725
|
+
words = str(response.payload, 'utf-8').replace('\0', ' ').split()
|
|
1726
|
+
|
|
1727
|
+
boot_rev = words[0]
|
|
1728
|
+
app_rev = str(response.payload[7]) + '.' + str(response.payload[8]) + '.' + str(response.payload[9]) # words[1]
|
|
1729
|
+
|
|
1730
|
+
return boot_rev, app_rev
|
|
1731
|
+
|
|
1732
|
+
@staticmethod
|
|
1733
|
+
def Dec_DateTime(response: CommandResponse):
|
|
1734
|
+
"""
|
|
1735
|
+
Decode date/time.
|
|
1736
|
+
|
|
1737
|
+
Args:
|
|
1738
|
+
response:
|
|
1739
|
+
CommandResponse object to be decoded.
|
|
1740
|
+
|
|
1741
|
+
Returns:
|
|
1742
|
+
current_time:
|
|
1743
|
+
Output reference to the current date/time.
|
|
1744
|
+
"""
|
|
1745
|
+
time = datetime.datetime(1970, 1, 1, 0, 0, 0)
|
|
1746
|
+
|
|
1747
|
+
#Decode current Date/Time given command response payload
|
|
1748
|
+
if (response.tx == MH.Command.CMD_TIME and
|
|
1749
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1750
|
+
|
|
1751
|
+
epoch = datetime.datetime(1970, 1, 1) # UTC time
|
|
1752
|
+
time = epoch + datetime.timedelta(seconds=int.from_bytes(response.payload, byteorder='little'))
|
|
1753
|
+
|
|
1754
|
+
return time
|
|
1755
|
+
|
|
1756
|
+
@staticmethod
|
|
1757
|
+
def Dec_DeviceName(response: CommandResponse):
|
|
1758
|
+
"""
|
|
1759
|
+
Decode device name (i.e., it is the name advertised by Bluetooth module).
|
|
1760
|
+
|
|
1761
|
+
Args:
|
|
1762
|
+
response:
|
|
1763
|
+
CommandResponse object to be decoded.
|
|
1764
|
+
|
|
1765
|
+
Returns:
|
|
1766
|
+
name:
|
|
1767
|
+
Output reference to device name.
|
|
1768
|
+
"""
|
|
1769
|
+
name = "-"
|
|
1770
|
+
|
|
1771
|
+
#Decode current device name (i.e., ble name) given command response payload
|
|
1772
|
+
if (response.tx == MH.Command.CMD_BLE_NAME.value and
|
|
1773
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1774
|
+
|
|
1775
|
+
name = str(response.payload, 'utf-8')
|
|
1776
|
+
|
|
1777
|
+
return name
|
|
1778
|
+
|
|
1779
|
+
@staticmethod
|
|
1780
|
+
def Dec_DeviceID(response: CommandResponse):
|
|
1781
|
+
"""
|
|
1782
|
+
Decode device unique identifier.
|
|
1783
|
+
|
|
1784
|
+
Args:
|
|
1785
|
+
response:
|
|
1786
|
+
CommandResponse object to be decoded.
|
|
1787
|
+
|
|
1788
|
+
Returns:
|
|
1789
|
+
id:
|
|
1790
|
+
Output reference to device unique identifier.
|
|
1791
|
+
"""
|
|
1792
|
+
id = ""
|
|
1793
|
+
|
|
1794
|
+
#Decode current device unique identifier given command response payload
|
|
1795
|
+
if (response.tx == MH.Command.CMD_DEVICE_ID and
|
|
1796
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1797
|
+
|
|
1798
|
+
#Revert array before printing string in order to keep endianness in byte representation
|
|
1799
|
+
response.payload.reverse
|
|
1800
|
+
for i in range(response.len - 2):
|
|
1801
|
+
id += format(response.payload[i], '02X')
|
|
1802
|
+
|
|
1803
|
+
return id
|
|
1804
|
+
|
|
1805
|
+
@staticmethod
|
|
1806
|
+
def Dec_DeviceSkills(response: CommandResponse):
|
|
1807
|
+
"""
|
|
1808
|
+
Decode hardware and software skills.
|
|
1809
|
+
|
|
1810
|
+
Args:
|
|
1811
|
+
response:
|
|
1812
|
+
CommandResponse object to be decoded.
|
|
1813
|
+
|
|
1814
|
+
Returns:
|
|
1815
|
+
hw_skills:
|
|
1816
|
+
Output reference to hardware skills.
|
|
1817
|
+
sw_skills:
|
|
1818
|
+
Output reference to software skills.
|
|
1819
|
+
"""
|
|
1820
|
+
hw_skills = {}
|
|
1821
|
+
sw_skills = {}
|
|
1822
|
+
|
|
1823
|
+
#Get skills code to be parsed
|
|
1824
|
+
skillsCode = struct.unpack("<I", response.payload[:4])[0]
|
|
1825
|
+
|
|
1826
|
+
#Extract hardware skills given the overall skills code
|
|
1827
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_GYRO.value) > 0):
|
|
1828
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_GYRO.value: "GYR"})
|
|
1829
|
+
|
|
1830
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_AXL.value) > 0):
|
|
1831
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_AXL.value: "AXL"})
|
|
1832
|
+
|
|
1833
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_MAGN.value) > 0):
|
|
1834
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_MAGN.value: "MAG"})
|
|
1835
|
+
|
|
1836
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_HDR.value) > 0):
|
|
1837
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_HDR.value: "HDR"})
|
|
1838
|
+
|
|
1839
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_TEMP.value) > 0):
|
|
1840
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_TEMP.value: "TEMP"})
|
|
1841
|
+
|
|
1842
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_RH.value) > 0):
|
|
1843
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_RH.value: "RH"})
|
|
1844
|
+
|
|
1845
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_BAR.value) > 0):
|
|
1846
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_BAR.value: "BAR"})
|
|
1847
|
+
|
|
1848
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_LUM_VIS.value) > 0):
|
|
1849
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_LUM_VIS.value: "LUM/VIS"})
|
|
1850
|
+
|
|
1851
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_LUM_IR.value) > 0):
|
|
1852
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_LUM_IR.value: "LUM/IR"})
|
|
1853
|
+
|
|
1854
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_RANGE.value) > 0):
|
|
1855
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_RANGE.value: "RANGE"})
|
|
1856
|
+
|
|
1857
|
+
if ((skillsCode & MH.HardwareSkills.SKILLS_HW_MIC.value) > 0):
|
|
1858
|
+
hw_skills.update({MH.HardwareSkills.SKILLS_HW_MIC.value: "MIC"})
|
|
1859
|
+
|
|
1860
|
+
|
|
1861
|
+
#Get skills code to be parsed
|
|
1862
|
+
skillsCode = struct.unpack("<I", response.payload[4:])[0]
|
|
1863
|
+
|
|
1864
|
+
#Extract software skills given the overall skills code
|
|
1865
|
+
if ((skillsCode & MH.SoftwareSkills.SKILLS_SW_MPE.value) > 0):
|
|
1866
|
+
sw_skills.update({MH.SoftwareSkills.SKILLS_SW_MPE.value: "MPE"})
|
|
1867
|
+
|
|
1868
|
+
if ((skillsCode & MH.SoftwareSkills.SKILLS_SW_MAD.value) > 0):
|
|
1869
|
+
sw_skills.update({MH.SoftwareSkills.SKILLS_SW_MAD.value: "MAD"})
|
|
1870
|
+
|
|
1871
|
+
return hw_skills, sw_skills
|
|
1872
|
+
|
|
1873
|
+
@staticmethod
|
|
1874
|
+
def Dec_MemoryStatus(response: CommandResponse):
|
|
1875
|
+
"""
|
|
1876
|
+
Decode memory status information.
|
|
1877
|
+
|
|
1878
|
+
Args:
|
|
1879
|
+
response:
|
|
1880
|
+
CommandResponse object to be decoded.
|
|
1881
|
+
|
|
1882
|
+
Returns:
|
|
1883
|
+
(available_memory, number_of_files):
|
|
1884
|
+
- Output reference to available memory.
|
|
1885
|
+
- Output reference to number of files currently saved in memory.
|
|
1886
|
+
"""
|
|
1887
|
+
available_memory = 100
|
|
1888
|
+
number_of_files = 0
|
|
1889
|
+
|
|
1890
|
+
#Decode current memory status given command response payload
|
|
1891
|
+
if (response.tx == MH.Command.CMD_MEM_CONTROL and
|
|
1892
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1893
|
+
|
|
1894
|
+
#Get available free memory (i.e., percentage value)
|
|
1895
|
+
available_memory = response.payload[0]
|
|
1896
|
+
|
|
1897
|
+
#Get number of files currently saved in memory
|
|
1898
|
+
|
|
1899
|
+
number_of_files = int.from_bytes(response.payload[1:3], byteorder='little', signed=False)
|
|
1900
|
+
|
|
1901
|
+
return available_memory, number_of_files
|
|
1902
|
+
|
|
1903
|
+
@staticmethod
|
|
1904
|
+
def Dec_FileInfo(response: CommandResponse):
|
|
1905
|
+
"""
|
|
1906
|
+
Decode file information.
|
|
1907
|
+
|
|
1908
|
+
Args:
|
|
1909
|
+
response:
|
|
1910
|
+
CommandResponse object to be decoded.
|
|
1911
|
+
|
|
1912
|
+
Returns:
|
|
1913
|
+
file_info:
|
|
1914
|
+
Output reference to a FileInfo structure.
|
|
1915
|
+
"""
|
|
1916
|
+
#Decode current file info given command response payload
|
|
1917
|
+
if (response.tx == MH.Command.CMD_MEM_FILE_INFO and
|
|
1918
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1919
|
+
|
|
1920
|
+
#Decode file timestamp
|
|
1921
|
+
tmp = bytearray(8)
|
|
1922
|
+
tmp[:5] = response.payload[:5]
|
|
1923
|
+
ts = struct.unpack("<Q", tmp)[0]
|
|
1924
|
+
ts += MH.REFERENCE_EPOCH * 1000
|
|
1925
|
+
|
|
1926
|
+
#Decode sensors full scales
|
|
1927
|
+
|
|
1928
|
+
#Pad 1-bytes response with further 3-bytes before converting to UInt32 and extracting configuration codes
|
|
1929
|
+
tmp = bytearray(4)
|
|
1930
|
+
tmp[0] = response.payload[5]
|
|
1931
|
+
code = struct.unpack("<I", tmp)[0]
|
|
1932
|
+
#DecodeMEMSConfiguration(response.payload[5], out gyrConfig, out axlConfig, out magConfig, out hdrConfig);
|
|
1933
|
+
gyrConfig, axlConfig, magConfig, hdrConfig = Muse_Utils.DecodeMEMSConfiguration(code)
|
|
1934
|
+
|
|
1935
|
+
#Decode data acquisition mode
|
|
1936
|
+
tmp = bytearray(4)
|
|
1937
|
+
tmp[:3] = response.payload[6:9]
|
|
1938
|
+
dm = struct.unpack("<I", tmp)[0]
|
|
1939
|
+
|
|
1940
|
+
#Update file_info object
|
|
1941
|
+
file_info = FileInfo(ts, gyrConfig, axlConfig, magConfig, hdrConfig, dm, response.payload[9])
|
|
1942
|
+
|
|
1943
|
+
return file_info
|
|
1944
|
+
|
|
1945
|
+
@staticmethod
|
|
1946
|
+
def Dec_ClockOffset(response: CommandResponse):
|
|
1947
|
+
"""
|
|
1948
|
+
Decode clock offset.
|
|
1949
|
+
|
|
1950
|
+
Args:
|
|
1951
|
+
response:
|
|
1952
|
+
CommandResponse object to be decoded.
|
|
1953
|
+
|
|
1954
|
+
Returns:
|
|
1955
|
+
clock_offset:
|
|
1956
|
+
Output reference to clock offset.
|
|
1957
|
+
"""
|
|
1958
|
+
clock_offset = 0
|
|
1959
|
+
|
|
1960
|
+
#Decode current file info given command response payload
|
|
1961
|
+
if (response.tx == MH.Command.CMD_CLK_OFFSET and
|
|
1962
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1963
|
+
|
|
1964
|
+
tmp = bytearray(8)
|
|
1965
|
+
tmp[:5] = response.payload[:5]
|
|
1966
|
+
clock_offset = struct.unpack("<Q", tmp)[0]
|
|
1967
|
+
|
|
1968
|
+
return clock_offset
|
|
1969
|
+
|
|
1970
|
+
@staticmethod
|
|
1971
|
+
def Dec_SensorsFullScales(response: CommandResponse):
|
|
1972
|
+
"""
|
|
1973
|
+
Decode sensors full scale / sensitivity configuration.
|
|
1974
|
+
|
|
1975
|
+
Args:
|
|
1976
|
+
response:
|
|
1977
|
+
CommandResponse object to be decoded.
|
|
1978
|
+
|
|
1979
|
+
Returns:
|
|
1980
|
+
(gyrConfig, axlConfig, magConfig, hdrConfig):
|
|
1981
|
+
- gyrConfig: Output reference to Gyroscope configuration.
|
|
1982
|
+
- axlConfig: Output reference to Accelerometer configuration.
|
|
1983
|
+
- magConfig: Output reference to Magnetometer configuration.
|
|
1984
|
+
- hdrConfig: Output reference to High Dynamic Range (HDR) Accelerometer configuration.
|
|
1985
|
+
"""
|
|
1986
|
+
gyrConfig = SensorConfig(0,0)
|
|
1987
|
+
axlConfig = SensorConfig(0,0)
|
|
1988
|
+
magConfig = SensorConfig(0,0)
|
|
1989
|
+
hdrConfig = SensorConfig(0,0)
|
|
1990
|
+
|
|
1991
|
+
#Decode current sensors full scales (i.e., gyr / axl / hdr / mag) given command response payload
|
|
1992
|
+
if (response.tx == MH.Command.CMD_SENSORS_FS and
|
|
1993
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
1994
|
+
|
|
1995
|
+
|
|
1996
|
+
#Pad 3-bytes response.payload array with a further byte before converting to UInt32 and extracting configuration codes
|
|
1997
|
+
tmp = bytearray(4)
|
|
1998
|
+
tmp = response.payload[:3]
|
|
1999
|
+
code = struct.unpack("<I", tmp + b"\x00")[0]
|
|
2000
|
+
|
|
2001
|
+
#Extract MEMS configurations
|
|
2002
|
+
#DecodeMEMSConfiguration(response.payload[0], out gyrConfig, out axlConfig, out magConfig, out hdrConfig);
|
|
2003
|
+
gyrConfig, axlConfig, magConfig, hdrConfig = Muse_Utils.DecodeMEMSConfiguration(code)
|
|
2004
|
+
|
|
2005
|
+
|
|
2006
|
+
|
|
2007
|
+
return gyrConfig, axlConfig, magConfig, hdrConfig
|
|
2008
|
+
|
|
2009
|
+
@staticmethod
|
|
2010
|
+
def Dec_CalibrationMatrixValues(col_val: bytearray):
|
|
2011
|
+
"""
|
|
2012
|
+
Decode calibration matric values
|
|
2013
|
+
|
|
2014
|
+
Args:
|
|
2015
|
+
col_val (bytearray):
|
|
2016
|
+
bytearray containing column values to be decoded.
|
|
2017
|
+
|
|
2018
|
+
Returns:
|
|
2019
|
+
col_values:
|
|
2020
|
+
float list of decoded column values.
|
|
2021
|
+
"""
|
|
2022
|
+
col_values = [0.0, 0.0, 0.0]
|
|
2023
|
+
|
|
2024
|
+
for i in range(3):
|
|
2025
|
+
start_index = i * 4
|
|
2026
|
+
tmp = col_val[start_index:start_index+4]
|
|
2027
|
+
col_values[i] = struct.unpack("<f", tmp)[0]
|
|
2028
|
+
|
|
2029
|
+
return col_values
|
|
2030
|
+
|
|
2031
|
+
@staticmethod
|
|
2032
|
+
def Dec_ButtonLogConfiguration(response: CommandResponse):
|
|
2033
|
+
"""
|
|
2034
|
+
Decode button log configuration.
|
|
2035
|
+
|
|
2036
|
+
Args:
|
|
2037
|
+
response:
|
|
2038
|
+
CommandResponse object to be decoded.
|
|
2039
|
+
|
|
2040
|
+
Returns:
|
|
2041
|
+
(mode, frequency):
|
|
2042
|
+
- mode: Output reference to current acquisition mode configured.
|
|
2043
|
+
- frequency: Output reference to current acquisition frequency configured.
|
|
2044
|
+
"""
|
|
2045
|
+
mode = ""
|
|
2046
|
+
frequency = ""
|
|
2047
|
+
|
|
2048
|
+
#Decode current sensors full scales (i.e., gyr / axl / hdr / mag) given command response payload
|
|
2049
|
+
if (response.tx == MH.Command.CMD_BUTTON_LOG and
|
|
2050
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
2051
|
+
|
|
2052
|
+
#Pad 3-bytes response.payload array with a further byte before converting to UInt32
|
|
2053
|
+
tmp = bytearray(4)
|
|
2054
|
+
tmp = response.payload[:3]
|
|
2055
|
+
code = struct.unpack("<I", tmp + b"\x00")[0]
|
|
2056
|
+
|
|
2057
|
+
#Build acquisition mode string description
|
|
2058
|
+
mode = Muse_Utils.DataModeToString(code)
|
|
2059
|
+
|
|
2060
|
+
#Set acquisition frequency string representation
|
|
2061
|
+
frequency = str(MH.DataFrequency(response.payload[3]).value)
|
|
2062
|
+
|
|
2063
|
+
return mode, frequency
|
|
2064
|
+
|
|
2065
|
+
@staticmethod
|
|
2066
|
+
def Dec_UserConfiguration(response: CommandResponse):
|
|
2067
|
+
"""
|
|
2068
|
+
Decode user configuration packet.
|
|
2069
|
+
|
|
2070
|
+
Args:
|
|
2071
|
+
response:
|
|
2072
|
+
CommandResponse object to be decoded.
|
|
2073
|
+
|
|
2074
|
+
Returns:
|
|
2075
|
+
userConfig:
|
|
2076
|
+
Output reference to user configuration object (type UserConfig).
|
|
2077
|
+
"""
|
|
2078
|
+
#Get code from which the user configuration must be extracted
|
|
2079
|
+
code = struct.unpack('<H', response.payload)[0]
|
|
2080
|
+
|
|
2081
|
+
#Set internal boolean flags
|
|
2082
|
+
standby = False
|
|
2083
|
+
memory = False
|
|
2084
|
+
ble = False
|
|
2085
|
+
usb = False
|
|
2086
|
+
tcp = False
|
|
2087
|
+
mqtt = False
|
|
2088
|
+
mpe9dof = False
|
|
2089
|
+
slowfreq = False
|
|
2090
|
+
mqttcommands = False
|
|
2091
|
+
|
|
2092
|
+
if ((code & MH.UserConfigMask.USER_CFG_MASK_AUTO_STANDBY.value) > 0):
|
|
2093
|
+
standby = True
|
|
2094
|
+
if ((code & MH.UserConfigMask.USER_CFG_MASK_CIRCULAR_MEMORY.value) > 0):
|
|
2095
|
+
memory = True
|
|
2096
|
+
if ((code & MH.UserConfigMask.USER_CFG_MASK_STREAMING_CHANNEL.value) == MH.UserConfigMask.USER_CFG_MASK_BLE_STREAM.value):
|
|
2097
|
+
ble = True
|
|
2098
|
+
if ((code & MH.UserConfigMask.USER_CFG_MASK_STREAMING_CHANNEL.value) == MH.UserConfigMask.USER_CFG_MASK_USB_STREAM.value):
|
|
2099
|
+
usb = True
|
|
2100
|
+
if ((code & MH.UserConfigMask.USER_CFG_MASK_STREAMING_CHANNEL.value) == MH.UserConfigMask.USER_CFG_MASK_TCP_STREAM.value):
|
|
2101
|
+
tcp = True
|
|
2102
|
+
if ((code & MH.UserConfigMask.USER_CFG_MASK_STREAMING_CHANNEL.value) == MH.UserConfigMask.USER_CFG_MASK_MQTT_STREAM.value):
|
|
2103
|
+
mqtt = True
|
|
2104
|
+
if ((code & MH.UserConfigMask.USER_CFG_MASK_9DOF_MPE.value) > 0):
|
|
2105
|
+
mpe9dof = True
|
|
2106
|
+
if ((code & MH.UserConfigMask.USER_CFG_MASK_SLOW_FREQUENCY.value) > 0):
|
|
2107
|
+
slowfreq = True
|
|
2108
|
+
if ((code & MH.UserConfigMask.USER_CFG_MASK_MQTT_COMMANDS.value) > 0):
|
|
2109
|
+
mqttcommands = True
|
|
2110
|
+
|
|
2111
|
+
return UserConfig(standby, memory, ble, usb, tcp, mqtt, mpe9dof, slowfreq, mqttcommands)
|
|
2112
|
+
|
|
2113
|
+
@staticmethod
|
|
2114
|
+
def GetPacketDimension(inMode: MH.DataMode) -> int:
|
|
2115
|
+
"""
|
|
2116
|
+
Returns the data packet dimension corresponding to a given data acquisition mode.
|
|
2117
|
+
|
|
2118
|
+
Args:
|
|
2119
|
+
inMode:
|
|
2120
|
+
Data acquisition mode as DataMode type.
|
|
2121
|
+
|
|
2122
|
+
Returns:
|
|
2123
|
+
packet_dimension:
|
|
2124
|
+
A integer value representing the data packet dimension.
|
|
2125
|
+
"""
|
|
2126
|
+
packet_dimension = 0
|
|
2127
|
+
|
|
2128
|
+
#Compute packet dimension given data acquisition mode
|
|
2129
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_GYRO.value) > 0):
|
|
2130
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_GYRO.value)
|
|
2131
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_AXL.value) > 0):
|
|
2132
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_AXL.value)
|
|
2133
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_HDR.value) > 0):
|
|
2134
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_HDR.value)
|
|
2135
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_MAGN.value) > 0):
|
|
2136
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_MAGN.value)
|
|
2137
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_ORIENTATION.value) > 0):
|
|
2138
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_ORIENTATION.value)
|
|
2139
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_TIMESTAMP.value) > 0):
|
|
2140
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_TIMESTAMP.value)
|
|
2141
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_TEMP_HUM.value) > 0):
|
|
2142
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_TEMP_HUM.value)
|
|
2143
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_TEMP_PRESS.value) > 0):
|
|
2144
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_TEMP_PRESS)
|
|
2145
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_RANGE.value) > 0):
|
|
2146
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_RANGE.value)
|
|
2147
|
+
if ((inMode.value & MH.DataMode.DATA_MODE_SOUND.value) > 0):
|
|
2148
|
+
packet_dimension += int(MH.DataSize.DATA_SIZE_SOUND.value)
|
|
2149
|
+
|
|
2150
|
+
#Check packet dimension consistency
|
|
2151
|
+
#It MUST be a dividend of 120 (2040)
|
|
2152
|
+
if (packet_dimension == 6 or packet_dimension == 12 or packet_dimension == 24 or
|
|
2153
|
+
packet_dimension == 30 or packet_dimension == 60):
|
|
2154
|
+
return packet_dimension
|
|
2155
|
+
|
|
2156
|
+
#Return -1 in case of data dimension inconsistency
|
|
2157
|
+
return -1
|
|
2158
|
+
|
|
2159
|
+
@staticmethod
|
|
2160
|
+
def GetNumberOfPackets(inMode: MH.DataMode):
|
|
2161
|
+
"""
|
|
2162
|
+
Returns the overall number of data packets contained into a 128-bytes data characteristic given a data acquisition mode.
|
|
2163
|
+
|
|
2164
|
+
Args:
|
|
2165
|
+
inMode:
|
|
2166
|
+
Data acquisition mode as DataMode type.
|
|
2167
|
+
|
|
2168
|
+
Returns:
|
|
2169
|
+
num_of_packets:
|
|
2170
|
+
A integer value representing the number of data packets.
|
|
2171
|
+
"""
|
|
2172
|
+
# Compute packet dimension and check its consistency given data acquisition mode
|
|
2173
|
+
packet_dimension = Muse_Utils.GetPacketDimension(inMode)
|
|
2174
|
+
|
|
2175
|
+
num_of_packets = -1
|
|
2176
|
+
# Compute overall number of packets contained into a data characteristic update
|
|
2177
|
+
if (packet_dimension != -1):
|
|
2178
|
+
num_of_packets = (120 / packet_dimension)
|
|
2179
|
+
|
|
2180
|
+
# Return -1 in case of data dimension inconsistency
|
|
2181
|
+
return num_of_packets
|
|
2182
|
+
|
|
2183
|
+
@staticmethod
|
|
2184
|
+
def DecodePacket(buffer: bytearray, timestamp: int, mode: MH.DataMode, gyr_res: float, axl_res: float, mag_res: float, hdr_res: float):
|
|
2185
|
+
"""
|
|
2186
|
+
Decode data packet.
|
|
2187
|
+
|
|
2188
|
+
Args:
|
|
2189
|
+
buffer (bytearray):
|
|
2190
|
+
Bytearray to be decoded.
|
|
2191
|
+
timestamp (int):
|
|
2192
|
+
Reference timestamp related to the last notification.
|
|
2193
|
+
mode (Muse_HW.DataMode):
|
|
2194
|
+
Data acquisition mode.
|
|
2195
|
+
gyr_res (float):
|
|
2196
|
+
Gyroscope sensitivity coefficient.
|
|
2197
|
+
axl_res (float):
|
|
2198
|
+
Accelerometer sensitivity coefficient.
|
|
2199
|
+
mag_res (float):
|
|
2200
|
+
Magnetometer sensitivity coefficient.
|
|
2201
|
+
hdr_res (float):
|
|
2202
|
+
High Dynamic Range (HDR) Accelerometer sensitivity coefficient.
|
|
2203
|
+
|
|
2204
|
+
Returns:
|
|
2205
|
+
current_data (Muse_Data):
|
|
2206
|
+
A Muse_Data object with decoded data.
|
|
2207
|
+
"""
|
|
2208
|
+
#Check input buffer consistency
|
|
2209
|
+
if (buffer != None and len(buffer) > 0):
|
|
2210
|
+
|
|
2211
|
+
#Define muse data container
|
|
2212
|
+
packet_index_offset = 0
|
|
2213
|
+
|
|
2214
|
+
current_data = Muse_Data()
|
|
2215
|
+
#Set overall timestamp reference
|
|
2216
|
+
current_data.overall_timestamp = timestamp
|
|
2217
|
+
current_data.timestamp = timestamp
|
|
2218
|
+
|
|
2219
|
+
#Ther order of IF statements is related to the order with which the data coming within each packet in order to properly update the packet_index_offset
|
|
2220
|
+
if ((mode & MH.DataMode.DATA_MODE_GYRO.value) > 0):
|
|
2221
|
+
|
|
2222
|
+
#Decode Gyroscope reading
|
|
2223
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_GYRO.value))
|
|
2224
|
+
|
|
2225
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_GYRO.value)]
|
|
2226
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_GYRO.value)
|
|
2227
|
+
|
|
2228
|
+
current_data.gyr = Muse_Utils.DataTypeGYR(current_packet, gyr_res)
|
|
2229
|
+
|
|
2230
|
+
|
|
2231
|
+
if ((mode & MH.DataMode.DATA_MODE_AXL.value) > 0):
|
|
2232
|
+
|
|
2233
|
+
#Decode Accelerometer reading
|
|
2234
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_AXL.value))
|
|
2235
|
+
|
|
2236
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_AXL.value)]
|
|
2237
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_AXL.value)
|
|
2238
|
+
|
|
2239
|
+
current_data.axl = Muse_Utils.DataTypeAXL(current_packet, axl_res)
|
|
2240
|
+
|
|
2241
|
+
|
|
2242
|
+
if ((mode & MH.DataMode.DATA_MODE_MAGN.value) > 0):
|
|
2243
|
+
|
|
2244
|
+
# Decode Magnetometer reading
|
|
2245
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_MAGN.value))
|
|
2246
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_MAGN.value)]
|
|
2247
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_MAGN.value)
|
|
2248
|
+
|
|
2249
|
+
current_data.mag = Muse_Utils.DataTypeMAGN(current_packet, mag_res)
|
|
2250
|
+
|
|
2251
|
+
|
|
2252
|
+
if ((mode & MH.DataMode.DATA_MODE_HDR.value) > 0):
|
|
2253
|
+
|
|
2254
|
+
#Decode Accelerometer HDR reading
|
|
2255
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_HDR.value))
|
|
2256
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_HDR.value)]
|
|
2257
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_HDR.value)
|
|
2258
|
+
|
|
2259
|
+
current_data.hdr = Muse_Utils.DataTypeHDR(current_packet, hdr_res)
|
|
2260
|
+
|
|
2261
|
+
|
|
2262
|
+
if ((mode & MH.DataMode.DATA_MODE_ORIENTATION.value) > 0):
|
|
2263
|
+
|
|
2264
|
+
#Decode orientation quaternion
|
|
2265
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_ORIENTATION.value))
|
|
2266
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_ORIENTATION.value)]
|
|
2267
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_ORIENTATION.value)
|
|
2268
|
+
|
|
2269
|
+
current_data.quat = Muse_Utils.DataTypeOrientation(current_packet)
|
|
2270
|
+
current_data.euler = Muse_Utils.GetAnglesFromQuaternion(current_data.quat)
|
|
2271
|
+
|
|
2272
|
+
|
|
2273
|
+
if ((mode & MH.DataMode.DATA_MODE_TIMESTAMP.value) > 0):
|
|
2274
|
+
|
|
2275
|
+
#Decode timestamp
|
|
2276
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_TIMESTAMP.value))
|
|
2277
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_TIMESTAMP.value)]
|
|
2278
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_TIMESTAMP.value)
|
|
2279
|
+
|
|
2280
|
+
current_data.timestamp = Muse_Utils.DataTypeTimestamp(current_packet)
|
|
2281
|
+
|
|
2282
|
+
|
|
2283
|
+
if ((mode & MH.DataMode.DATA_MODE_TEMP_HUM.value) > 0):
|
|
2284
|
+
|
|
2285
|
+
#Decode temperature and humidity reading
|
|
2286
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_TEMP_HUM.value))
|
|
2287
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_TEMP_HUM.value)]
|
|
2288
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_TEMP_HUM.value)
|
|
2289
|
+
|
|
2290
|
+
current_data.th = Muse_Utils.DataTypeTempHum(current_packet)
|
|
2291
|
+
|
|
2292
|
+
|
|
2293
|
+
if ((mode & MH.DataMode.DATA_MODE_TEMP_PRESS.value) > 0):
|
|
2294
|
+
|
|
2295
|
+
#Decode temperature and barometric pressure reading
|
|
2296
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_TEMP_PRESS.value))
|
|
2297
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_TEMP_PRESS.value)]
|
|
2298
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_TEMP_PRESS.value)
|
|
2299
|
+
|
|
2300
|
+
current_data.tp = Muse_Utils.DataTypeTempPress(current_packet)
|
|
2301
|
+
|
|
2302
|
+
|
|
2303
|
+
if ((mode & MH.DataMode.DATA_MODE_RANGE.value) > 0):
|
|
2304
|
+
|
|
2305
|
+
#Decode distance / luminosity reading
|
|
2306
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_RANGE.value))
|
|
2307
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_RANGE.value)]
|
|
2308
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_RANGE.value)
|
|
2309
|
+
|
|
2310
|
+
tmp = Muse_Utils.DataTypeRange(current_packet)
|
|
2311
|
+
current_data.light = Light(tmp[0],tmp[1],tmp[2],tmp[3])
|
|
2312
|
+
|
|
2313
|
+
|
|
2314
|
+
if ((mode & MH.DataMode.DATA_MODE_SOUND.value) > 0):
|
|
2315
|
+
|
|
2316
|
+
#Decode sound reading
|
|
2317
|
+
current_packet = bytearray(int(MH.DataSize.DATA_SIZE_SOUND.value))
|
|
2318
|
+
current_packet[:] = buffer[packet_index_offset:packet_index_offset+int(MH.DataSize.DATA_SIZE_SOUND.value)]
|
|
2319
|
+
packet_index_offset += int(MH.DataSize.DATA_SIZE_SOUND.value)
|
|
2320
|
+
|
|
2321
|
+
current_data.sound = Muse_Utils.DataTypeSound(current_packet)
|
|
2322
|
+
|
|
2323
|
+
|
|
2324
|
+
return current_data
|
|
2325
|
+
|
|
2326
|
+
return None
|
|
2327
|
+
|
|
2328
|
+
@staticmethod
|
|
2329
|
+
def Dec_WifiSSIDHead(response: CommandResponse):
|
|
2330
|
+
"""
|
|
2331
|
+
Decode SSID Head(i.e., it is the SSID advertised by Bluetooth module).
|
|
2332
|
+
|
|
2333
|
+
Args:
|
|
2334
|
+
response:
|
|
2335
|
+
CommandResponse object to be decoded.
|
|
2336
|
+
|
|
2337
|
+
Returns:
|
|
2338
|
+
ssid:
|
|
2339
|
+
Output reference to SSID head part.
|
|
2340
|
+
|
|
2341
|
+
"""
|
|
2342
|
+
ssid = ""
|
|
2343
|
+
|
|
2344
|
+
#Decode SSID given command response payload
|
|
2345
|
+
if (response.tx == MH.Command.CMD_WIFI_SSID_HEAD.value and
|
|
2346
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
2347
|
+
|
|
2348
|
+
ssid = str(response.payload, 'utf-8')
|
|
2349
|
+
|
|
2350
|
+
return ssid
|
|
2351
|
+
|
|
2352
|
+
@staticmethod
|
|
2353
|
+
def Dec_WifiSSIDCont(response: CommandResponse):
|
|
2354
|
+
"""
|
|
2355
|
+
Decode device SSID Continuation part(i.e., it is the SSID advertised by Bluetooth module).
|
|
2356
|
+
|
|
2357
|
+
Args:
|
|
2358
|
+
response:
|
|
2359
|
+
CommandResponse object to be decoded.
|
|
2360
|
+
|
|
2361
|
+
Returns:
|
|
2362
|
+
ssid:
|
|
2363
|
+
Output reference to SSID continuation part.
|
|
2364
|
+
"""
|
|
2365
|
+
ssid = ""
|
|
2366
|
+
|
|
2367
|
+
#Decode SSID given command response payload
|
|
2368
|
+
if (response.tx == MH.Command.CMD_WIFI_SSID_CONT.value and
|
|
2369
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS):
|
|
2370
|
+
|
|
2371
|
+
ssid = str(response.payload, 'utf-8')
|
|
2372
|
+
|
|
2373
|
+
return ssid
|
|
2374
|
+
|
|
2375
|
+
@staticmethod
|
|
2376
|
+
def Dec_WifiStreamHostHead(response: CommandResponse):
|
|
2377
|
+
"""
|
|
2378
|
+
Decode Stream Host Head.
|
|
2379
|
+
|
|
2380
|
+
Args:
|
|
2381
|
+
response:
|
|
2382
|
+
CommandResponse object to be decoded.
|
|
2383
|
+
|
|
2384
|
+
Returns:
|
|
2385
|
+
host:
|
|
2386
|
+
Output reference to host head part.
|
|
2387
|
+
"""
|
|
2388
|
+
#Decode battery voltage [mV] value given command response payload
|
|
2389
|
+
if (response.tx == MH.Command.CMD_WIFI_STREAM_HOST_HEAD and
|
|
2390
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS.value):
|
|
2391
|
+
|
|
2392
|
+
host = str(response.payload, 'utf-8')
|
|
2393
|
+
|
|
2394
|
+
return host
|
|
2395
|
+
|
|
2396
|
+
@staticmethod
|
|
2397
|
+
def Dec_WifiStreamHostCont(response: CommandResponse):
|
|
2398
|
+
"""
|
|
2399
|
+
Decode Stream Host continuation part.
|
|
2400
|
+
|
|
2401
|
+
Args:
|
|
2402
|
+
response:
|
|
2403
|
+
CommandResponse object to be decoded.
|
|
2404
|
+
|
|
2405
|
+
Returns:
|
|
2406
|
+
host:
|
|
2407
|
+
Output reference to the remaining part of host.
|
|
2408
|
+
"""
|
|
2409
|
+
#Decode battery voltage [mV] value given command response payload
|
|
2410
|
+
if (response.tx == MH.Command.CMD_WIFI_STREAM_HOST_CONT and
|
|
2411
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS.value):
|
|
2412
|
+
|
|
2413
|
+
host = str(response.payload, 'utf-8')
|
|
2414
|
+
|
|
2415
|
+
return host
|
|
2416
|
+
|
|
2417
|
+
@staticmethod
|
|
2418
|
+
def Dec_WifiStreamHostPort(response: CommandResponse):
|
|
2419
|
+
"""
|
|
2420
|
+
Decode Stream Host port.
|
|
2421
|
+
|
|
2422
|
+
Args:
|
|
2423
|
+
response:
|
|
2424
|
+
CommandResponse object to be decoded.
|
|
2425
|
+
|
|
2426
|
+
Returns:
|
|
2427
|
+
port:
|
|
2428
|
+
Output reference to the WiFi port.
|
|
2429
|
+
"""
|
|
2430
|
+
#Decode battery voltage [mV] value given command response payload
|
|
2431
|
+
if (response.tx == MH.Command.CMD_WIFI_STREAM_HOST_PORT and
|
|
2432
|
+
response.ack == MH.AcknowledgeType.ACK_SUCCESS.value):
|
|
2433
|
+
|
|
2434
|
+
port = struct.unpack('<H', response.payload)[0]
|
|
2435
|
+
|
|
2436
|
+
return port
|
|
2437
|
+
|
|
2438
|
+
@staticmethod
|
|
2439
|
+
def DataTypeGYR(current_payload: bytearray, gyr_res: float):
|
|
2440
|
+
"""Decode Gyroscope reading.
|
|
2441
|
+
|
|
2442
|
+
Args:
|
|
2443
|
+
current_payload (bytearray):
|
|
2444
|
+
Bytes array to be decoded.
|
|
2445
|
+
gyr_res (float):
|
|
2446
|
+
Gyroscope sensitivity coefficient.
|
|
2447
|
+
|
|
2448
|
+
Returns:
|
|
2449
|
+
current_data: 3-elements array of float (i.e., x, y, z channels) containing Gyroscope data
|
|
2450
|
+
"""
|
|
2451
|
+
#Define 3-elements array of float (i.e., x, y, z channels)
|
|
2452
|
+
current_data = [0.0]*3
|
|
2453
|
+
|
|
2454
|
+
#Iterate across Gyroscope channels
|
|
2455
|
+
for i in range(3):
|
|
2456
|
+
|
|
2457
|
+
#Extract channel raw value (i.e., 2-bytes each)
|
|
2458
|
+
raw_value = current_payload[2*i:2*(i+1)]
|
|
2459
|
+
# Convert to Int16 and apply sensitivity scaling
|
|
2460
|
+
current_data[i] = int.from_bytes(raw_value, byteorder='little', signed=True) * gyr_res
|
|
2461
|
+
|
|
2462
|
+
|
|
2463
|
+
#Return decoded Gyroscope reading
|
|
2464
|
+
return current_data
|
|
2465
|
+
|
|
2466
|
+
@staticmethod
|
|
2467
|
+
def DataTypeAXL(current_payload: bytearray, axl_res: float):
|
|
2468
|
+
"""Decode Accelerometer reading.
|
|
2469
|
+
|
|
2470
|
+
Args:
|
|
2471
|
+
current_payload (bytearray):
|
|
2472
|
+
Bytes array to be decoded.
|
|
2473
|
+
axl_res (float):
|
|
2474
|
+
Accelerometer sensitivity coefficient.
|
|
2475
|
+
|
|
2476
|
+
Returns:
|
|
2477
|
+
current_data: 3-elements array of float (i.e., x, y, z channels) containing Accelerometer data
|
|
2478
|
+
"""
|
|
2479
|
+
current_data = [0.0] * 3
|
|
2480
|
+
|
|
2481
|
+
#Accelerometer
|
|
2482
|
+
for i in range(3):
|
|
2483
|
+
#Extract channel raw value (i.e., 2-bytes each)
|
|
2484
|
+
raw_value = current_payload[2*i:2*(i+1)]
|
|
2485
|
+
# Convert to Int16 and apply sensitivity scaling
|
|
2486
|
+
current_data[i] = int.from_bytes(raw_value, byteorder='little', signed=True) * axl_res
|
|
2487
|
+
|
|
2488
|
+
|
|
2489
|
+
return current_data
|
|
2490
|
+
|
|
2491
|
+
@staticmethod
|
|
2492
|
+
def DataTypeMAGN(current_payload: bytearray, mag_res: float):
|
|
2493
|
+
"""Decode Magnetometer reading.
|
|
2494
|
+
|
|
2495
|
+
Args:
|
|
2496
|
+
current_payload (bytearray):
|
|
2497
|
+
Bytes array to be decoded.
|
|
2498
|
+
mag_res (float):
|
|
2499
|
+
Magnetometer sensitivity coefficient.
|
|
2500
|
+
|
|
2501
|
+
Returns:
|
|
2502
|
+
current_data: 3-elements array of float (i.e., x, y, z channels) containing Magnetometer data
|
|
2503
|
+
"""
|
|
2504
|
+
current_data = [0.0] * 3
|
|
2505
|
+
|
|
2506
|
+
#Magnetometer
|
|
2507
|
+
for i in range(3):
|
|
2508
|
+
#Extract channel raw value (i.e., 2-bytes each)
|
|
2509
|
+
raw_value = current_payload[2*i:2*(i+1)]
|
|
2510
|
+
# Convert to Int16 and apply sensitivity scaling
|
|
2511
|
+
current_data[i] = int.from_bytes(raw_value, byteorder='little', signed=True) * mag_res
|
|
2512
|
+
|
|
2513
|
+
|
|
2514
|
+
return current_data
|
|
2515
|
+
|
|
2516
|
+
@staticmethod
|
|
2517
|
+
def DataTypeHDR(current_payload: bytearray, hdr_res: float):
|
|
2518
|
+
"""Decode High Dynamic Range (HDR) Accelerometer reading.
|
|
2519
|
+
|
|
2520
|
+
Args:
|
|
2521
|
+
current_payload (bytearray):
|
|
2522
|
+
Bytes array to be decoded.
|
|
2523
|
+
hdr_res (float):
|
|
2524
|
+
High Dynamic Range (HDR) Accelerometer sensitivity coefficient.
|
|
2525
|
+
|
|
2526
|
+
Returns:
|
|
2527
|
+
current_data: 3-elements array of float (i.e., x, y, z channels) containing High Dynamic Range (HDR) Accelerometer data
|
|
2528
|
+
"""
|
|
2529
|
+
current_data = [0.0]*3
|
|
2530
|
+
tmp = bytearray(2)
|
|
2531
|
+
|
|
2532
|
+
#Accelerometer HDR
|
|
2533
|
+
for i in range(3):
|
|
2534
|
+
#Extract channel raw value (i.e., 2-bytes each)
|
|
2535
|
+
raw_value = current_payload[2*i:2*(i+1)]
|
|
2536
|
+
# Convert to Int16 and apply sensitivity scaling
|
|
2537
|
+
current_data[i] = int.from_bytes(raw_value, byteorder='little', signed=True) * hdr_res
|
|
2538
|
+
|
|
2539
|
+
return current_data
|
|
2540
|
+
|
|
2541
|
+
@staticmethod
|
|
2542
|
+
def DataTypeOrientation(current_payload: bytearray):
|
|
2543
|
+
"""Decode orientation (unit) quaternion
|
|
2544
|
+
|
|
2545
|
+
Args:
|
|
2546
|
+
current_payload (bytearray):
|
|
2547
|
+
Bytes array to be decoded.
|
|
2548
|
+
|
|
2549
|
+
Returns:
|
|
2550
|
+
current_data: 4-elements array of float (i.e., qw, qi, qj, qk) containing Quaternion components
|
|
2551
|
+
"""
|
|
2552
|
+
#Define 4-elements array of float (i.e., qw, qi, qj, qk channels)
|
|
2553
|
+
current_data = [0.0] * 4
|
|
2554
|
+
|
|
2555
|
+
#Orientation Quaternion (i.e., UNIT QUATERNION)
|
|
2556
|
+
tempFloat = [0.0] * 3
|
|
2557
|
+
for i in range(3):
|
|
2558
|
+
|
|
2559
|
+
#Extract channel raw value (i.e., 2-bytes each) and convert to Int16
|
|
2560
|
+
tempFloat[i] = int.from_bytes(current_payload[2*i:2*i+2], byteorder='little', signed=True)
|
|
2561
|
+
|
|
2562
|
+
#Keep into account the data resolution
|
|
2563
|
+
tempFloat[i] /= 32767
|
|
2564
|
+
|
|
2565
|
+
#Assign imaginary parts of quaternion
|
|
2566
|
+
current_data[i + 1] = tempFloat[i]
|
|
2567
|
+
|
|
2568
|
+
|
|
2569
|
+
#Compute real component of quaternion given immaginary parts
|
|
2570
|
+
current_data[0] = math.sqrt(1 - (current_data[1] * current_data[1] +
|
|
2571
|
+
current_data[2] * current_data[2] + current_data[3] * current_data[3]))
|
|
2572
|
+
|
|
2573
|
+
#Return decoded Unit Quaternion
|
|
2574
|
+
return current_data
|
|
2575
|
+
|
|
2576
|
+
@staticmethod
|
|
2577
|
+
def GetAnglesFromQuaternion(q):
|
|
2578
|
+
"""Compute Euler Angles given a unit quaternion.
|
|
2579
|
+
|
|
2580
|
+
Args:
|
|
2581
|
+
q:
|
|
2582
|
+
Unit quaternion to be converted (4-elements array of float).
|
|
2583
|
+
|
|
2584
|
+
Returns:
|
|
2585
|
+
result: 3-elements array of float (i.e., roll, pitch and yaw) containing Euler Angles
|
|
2586
|
+
"""
|
|
2587
|
+
result = [0.0] * 3
|
|
2588
|
+
|
|
2589
|
+
#Compute Euler Angles given a unit quaternion
|
|
2590
|
+
result[0] = float(math.atan2(2 * (q[0] * q[1] + q[2] * q[3]), 1 - 2 * (q[1] * q[1] + q[2] * q[2])) * 180 / math.pi)
|
|
2591
|
+
result[1] = float(math.asin(2 * q[0] * q[2] - 2 * q[3] * q[1]) * 180 / math.pi)
|
|
2592
|
+
result[2] = float(math.atan2(2 * (q[0] * q[3] + q[1] * q[2]), 1 - 2 * (q[2] * q[2] + q[3] * q[3])) * 180 / math.pi)
|
|
2593
|
+
|
|
2594
|
+
return result
|
|
2595
|
+
|
|
2596
|
+
@staticmethod
|
|
2597
|
+
def DataTypeTimestamp(current_payload: bytearray):
|
|
2598
|
+
"""Decode timestamp.
|
|
2599
|
+
|
|
2600
|
+
Args:
|
|
2601
|
+
current_payload (bytearray):
|
|
2602
|
+
Bytes array to be decoded.
|
|
2603
|
+
|
|
2604
|
+
Returns:
|
|
2605
|
+
currentData: A unsigned long integer value representing the timestamp in epoch format.
|
|
2606
|
+
"""
|
|
2607
|
+
#Set current data variable to 0
|
|
2608
|
+
currentData = 0
|
|
2609
|
+
|
|
2610
|
+
#Get raw byte array representation to be decoded
|
|
2611
|
+
tmp = bytearray(8)
|
|
2612
|
+
|
|
2613
|
+
# Copy the first 6 bytes of currentPayload into tmp
|
|
2614
|
+
tmp[:6] = current_payload[:6]
|
|
2615
|
+
|
|
2616
|
+
# Convert the first 6 bytes of tmp to a 64-bit unsigned integer
|
|
2617
|
+
tempTime = struct.unpack("<Q", tmp)[0] & 0x0000FFFFFFFFFFFF
|
|
2618
|
+
|
|
2619
|
+
# Add the reference epoch (in milliseconds) to tempTime
|
|
2620
|
+
tempTime += MH.REFERENCE_EPOCH * 1000
|
|
2621
|
+
|
|
2622
|
+
currentData = tempTime
|
|
2623
|
+
|
|
2624
|
+
return currentData
|
|
2625
|
+
|
|
2626
|
+
@staticmethod
|
|
2627
|
+
def DataTypeTempHum(current_payload: bytearray):
|
|
2628
|
+
"""Decode temperature and humidity reading.
|
|
2629
|
+
|
|
2630
|
+
Args:
|
|
2631
|
+
current_payload (bytearray):
|
|
2632
|
+
Bytes array to be decoded.
|
|
2633
|
+
|
|
2634
|
+
Returns:
|
|
2635
|
+
current_data: An array of float (i.e., temperature, humidity)
|
|
2636
|
+
"""
|
|
2637
|
+
#Define 2-elements array of float (i.e., temperature, humidity)
|
|
2638
|
+
current_data = [0.0] * 2
|
|
2639
|
+
|
|
2640
|
+
#Temperature
|
|
2641
|
+
#Define temporary internal variable used for data conversion
|
|
2642
|
+
tmp = bytearray(2)
|
|
2643
|
+
# Copy the first 2 bytes of currentPayload into tmp
|
|
2644
|
+
tmp[:2] = current_payload[0:2]
|
|
2645
|
+
# Convert to UInt16 and apply sensitivity scaling
|
|
2646
|
+
current_data[0] = int.from_bytes(tmp, byteorder='little', signed=False)
|
|
2647
|
+
current_data[0] *= 0.002670
|
|
2648
|
+
current_data[0] -= 45
|
|
2649
|
+
|
|
2650
|
+
#Humidity
|
|
2651
|
+
tmp[:2] = current_payload[2:4]
|
|
2652
|
+
# Convert to UInt16 and apply sensitivity scaling
|
|
2653
|
+
current_data[1] = int.from_bytes(tmp, byteorder='little', signed=False)
|
|
2654
|
+
current_data[1] *= 0.001907
|
|
2655
|
+
current_data[1] -= 6
|
|
2656
|
+
|
|
2657
|
+
#Return decoded data
|
|
2658
|
+
return current_data
|
|
2659
|
+
|
|
2660
|
+
@staticmethod
|
|
2661
|
+
def DataTypeTempPress(current_payload: bytearray):
|
|
2662
|
+
"""Decode temperature and barometric pressure reading.
|
|
2663
|
+
|
|
2664
|
+
Args:
|
|
2665
|
+
current_payload (bytearray):
|
|
2666
|
+
Bytes array to be decoded.
|
|
2667
|
+
|
|
2668
|
+
Returns:
|
|
2669
|
+
current_data: An array of float (i.e., temperature, pressure)
|
|
2670
|
+
"""
|
|
2671
|
+
#Define 2-elements array of float (i.e., temperature, pressure)
|
|
2672
|
+
current_data = [0.0] * 2
|
|
2673
|
+
|
|
2674
|
+
#Temperature
|
|
2675
|
+
#Define temporary internal variable used for data conversion
|
|
2676
|
+
tmp = bytearray(2)
|
|
2677
|
+
# Copy the first 2 bytes of currentPayload into tmp
|
|
2678
|
+
tmp[:2] = current_payload[3:5]
|
|
2679
|
+
# Convert to UInt16 and apply sensitivity scaling
|
|
2680
|
+
current_data[0] = int.from_bytes(tmp, byteorder='little', signed=False)
|
|
2681
|
+
current_data[0] /= 100
|
|
2682
|
+
|
|
2683
|
+
#Pressure
|
|
2684
|
+
tmp = bytearray(3)
|
|
2685
|
+
tmp[:3] = current_payload[0:3]
|
|
2686
|
+
# Convert to UInt16 and apply sensitivity scaling
|
|
2687
|
+
current_data[1] = int.from_bytes(tmp, byteorder='little', signed=False)
|
|
2688
|
+
current_data[1] /= 4096
|
|
2689
|
+
|
|
2690
|
+
#Return decoded data
|
|
2691
|
+
return current_data
|
|
2692
|
+
|
|
2693
|
+
@staticmethod
|
|
2694
|
+
def DataTypeRange(current_payload: bytearray):
|
|
2695
|
+
"""Decode Light sensor data.
|
|
2696
|
+
|
|
2697
|
+
Args:
|
|
2698
|
+
current_payload (bytearray):
|
|
2699
|
+
Bytes array to be decoded.
|
|
2700
|
+
|
|
2701
|
+
Returns:
|
|
2702
|
+
current_data: A 4-element float array (i.e., range, vis, ir, lux)
|
|
2703
|
+
"""
|
|
2704
|
+
current_data = [0] * 4
|
|
2705
|
+
|
|
2706
|
+
#Define temporary internal variable used for data conversion
|
|
2707
|
+
tmp = bytearray(2)
|
|
2708
|
+
# Copy the first 2 bytes of currentPayload into tmp
|
|
2709
|
+
tmp[:2] = current_payload[0:2]
|
|
2710
|
+
# Convert to UInt16
|
|
2711
|
+
range = int.from_bytes(tmp, byteorder='little', signed=False)
|
|
2712
|
+
|
|
2713
|
+
tmp[:2] = current_payload[2:4]
|
|
2714
|
+
# Convert to UInt16
|
|
2715
|
+
vis = int.from_bytes(tmp, byteorder='little', signed=False)
|
|
2716
|
+
|
|
2717
|
+
tmp[:2] = current_payload[4:6]
|
|
2718
|
+
# Convert to UInt16
|
|
2719
|
+
ir = int.from_bytes(tmp, byteorder='little', signed=False)
|
|
2720
|
+
|
|
2721
|
+
current_data[0] = range
|
|
2722
|
+
current_data[1] = vis
|
|
2723
|
+
current_data[2] = ir
|
|
2724
|
+
|
|
2725
|
+
lux = 0.0
|
|
2726
|
+
if vis > 0:
|
|
2727
|
+
if (ir / vis < 0.109):
|
|
2728
|
+
lux = 1.534 * vis - 3.759 * ir
|
|
2729
|
+
elif (ir / vis < 0.429):
|
|
2730
|
+
lux = 1.339 * vis - 1.972 * ir
|
|
2731
|
+
elif (ir / vis < 0.95 * 1.45):
|
|
2732
|
+
lux = 0.701 * vis - 0.483 * ir
|
|
2733
|
+
elif (ir / vis < 1.5 * 1.45):
|
|
2734
|
+
lux = 2.0 * 0.701 * vis - 1.18 * 0.483 * ir
|
|
2735
|
+
elif (ir / vis < 2.5 * 1.45):
|
|
2736
|
+
lux = 4.0 * 0.701 * vis - 1.33 * 0.483 * ir
|
|
2737
|
+
else:
|
|
2738
|
+
lux = 8.0 * 0.701 * vis
|
|
2739
|
+
else:
|
|
2740
|
+
# manage division by zero
|
|
2741
|
+
lux = 0.0
|
|
2742
|
+
|
|
2743
|
+
current_data[3] = round(lux)
|
|
2744
|
+
|
|
2745
|
+
return current_data
|
|
2746
|
+
|
|
2747
|
+
@staticmethod
|
|
2748
|
+
def DataTypeSound(current_payload: bytearray):
|
|
2749
|
+
"""Decode Sound data. TO BE IMPLEMENTED
|
|
2750
|
+
"""
|
|
2751
|
+
current_data = 0.0
|
|
2752
|
+
|
|
2753
|
+
return current_data
|
|
2754
|
+
|
|
2755
|
+
@staticmethod
|
|
2756
|
+
def DecodeMEMSConfiguration(code: int):
|
|
2757
|
+
"""Decode sensors configuration in terms of full scale and sensitivity.
|
|
2758
|
+
|
|
2759
|
+
Args:
|
|
2760
|
+
code (int):
|
|
2761
|
+
24-bit unsigned integer code.
|
|
2762
|
+
|
|
2763
|
+
Returns:
|
|
2764
|
+
(gyrConfig, axlConfig, magConfig, hdrConfig):
|
|
2765
|
+
- gyrConfig: Output reference to Gyroscope configuration.
|
|
2766
|
+
- axlConfig: Output reference to Accelerometer configuration.
|
|
2767
|
+
- magConfig: Output reference to Magnetometer configuration.
|
|
2768
|
+
- hdrConfig: Output reference to HDR Accelerometer configuration.
|
|
2769
|
+
"""
|
|
2770
|
+
#Apply bitwise mask to get sensor full scale code (i.e., gyr, axl, hdr, mag LSB-order)
|
|
2771
|
+
gyrCode = (code & MH.MEMS_FullScaleMask.SENSORSFS_MASK_GYRO.value)
|
|
2772
|
+
axlCode = (code & MH.MEMS_FullScaleMask.SENSORSFS_MASK_AXL.value)
|
|
2773
|
+
hdrCode = (code & MH.MEMS_FullScaleMask.SENSORSFS_MASK_HDR.value)
|
|
2774
|
+
magCode = (code & MH.MEMS_FullScaleMask.SENSORSFS_MASK_MAGN.value)
|
|
2775
|
+
|
|
2776
|
+
#Gyroscope
|
|
2777
|
+
gyrConfig = MH.Gyroscope_CFG[gyrCode]
|
|
2778
|
+
#Accelerometer
|
|
2779
|
+
axlConfig = MH.Accelerometer_CFG[axlCode]
|
|
2780
|
+
#Magnetometer
|
|
2781
|
+
magConfig = MH.Magnetometer_CFG[magCode]
|
|
2782
|
+
# HDR Accelerometer
|
|
2783
|
+
hdrConfig = MH.AccelerometerHDR_CFG[hdrCode]
|
|
2784
|
+
|
|
2785
|
+
return gyrConfig, axlConfig, magConfig, hdrConfig
|
|
2786
|
+
|
|
2787
|
+
@staticmethod
|
|
2788
|
+
def DataModeToString(code: int) -> str:
|
|
2789
|
+
"""Create a string representation of data acquisition mode.
|
|
2790
|
+
|
|
2791
|
+
Args:
|
|
2792
|
+
code (int):
|
|
2793
|
+
32-bit unsigned integer code.
|
|
2794
|
+
|
|
2795
|
+
Returns:
|
|
2796
|
+
modeString:
|
|
2797
|
+
string representation of data acquisition mode.
|
|
2798
|
+
"""
|
|
2799
|
+
modeString = ""
|
|
2800
|
+
|
|
2801
|
+
#Build acquisition mode string description
|
|
2802
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_GYRO.value).value) > 0):
|
|
2803
|
+
if (len(modeString)>0):
|
|
2804
|
+
modeString += " | "
|
|
2805
|
+
modeString += "GYR"
|
|
2806
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_AXL.value).value) > 0):
|
|
2807
|
+
if (len(modeString)>0):
|
|
2808
|
+
modeString += " | "
|
|
2809
|
+
modeString += "AXL"
|
|
2810
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_HDR.value).value) > 0):
|
|
2811
|
+
if (len(modeString)>0):
|
|
2812
|
+
modeString += " | "
|
|
2813
|
+
modeString += "HDR"
|
|
2814
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_MAGN.value).value) > 0):
|
|
2815
|
+
if (len(modeString)>0):
|
|
2816
|
+
modeString += " | "
|
|
2817
|
+
modeString += "MAG"
|
|
2818
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_ORIENTATION.value).value) > 0):
|
|
2819
|
+
if (len(modeString)>0):
|
|
2820
|
+
modeString += " | "
|
|
2821
|
+
modeString += "QUAT"
|
|
2822
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_TIMESTAMP.value).value) > 0):
|
|
2823
|
+
if (len(modeString)>0):
|
|
2824
|
+
modeString += " | "
|
|
2825
|
+
modeString += "TIME"
|
|
2826
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_TEMP_HUM.value).value) > 0):
|
|
2827
|
+
if (len(modeString)>0):
|
|
2828
|
+
modeString += " | "
|
|
2829
|
+
modeString += "TH"
|
|
2830
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_TEMP_PRESS.value).value) > 0):
|
|
2831
|
+
if (len(modeString)>0):
|
|
2832
|
+
modeString += " | "
|
|
2833
|
+
modeString += "TP"
|
|
2834
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_RANGE.value).value) > 0):
|
|
2835
|
+
if (len(modeString)>0):
|
|
2836
|
+
modeString += " | "
|
|
2837
|
+
modeString += "RANGE"
|
|
2838
|
+
if ((code & ctypes.c_uint32(MH.DataMode.DATA_MODE_SOUND.value).value) > 0):
|
|
2839
|
+
if (len(modeString)>0):
|
|
2840
|
+
modeString += " | "
|
|
2841
|
+
modeString += "MIC"
|
|
2842
|
+
|
|
2843
|
+
if (modeString != ""):
|
|
2844
|
+
modeString.join(", ")
|
|
2845
|
+
|
|
2846
|
+
return modeString
|
|
2847
|
+
|
|
2848
|
+
@staticmethod
|
|
2849
|
+
def DataFrequencyToString(frequency: MH.DataFrequency) -> str:
|
|
2850
|
+
"""Create a string representation of data acquisition mode.
|
|
2851
|
+
|
|
2852
|
+
Args:
|
|
2853
|
+
frequency (Muse_HW.DataFrequency):
|
|
2854
|
+
DataFrequency value of sampling frequency
|
|
2855
|
+
|
|
2856
|
+
Returns:
|
|
2857
|
+
string representation of data acquisition frequency.
|
|
2858
|
+
"""
|
|
2859
|
+
if frequency == MH.DataFrequency.DATA_FREQ_25Hz :
|
|
2860
|
+
return "25 Hz"
|
|
2861
|
+
|
|
2862
|
+
if frequency == MH.DataFrequency.DATA_FREQ_50Hz:
|
|
2863
|
+
return "50 Hz"
|
|
2864
|
+
|
|
2865
|
+
if frequency == MH.DataFrequency.DATA_FREQ_100Hz:
|
|
2866
|
+
return "100 Hz"
|
|
2867
|
+
|
|
2868
|
+
if frequency == MH.DataFrequency.DATA_FREQ_200Hz:
|
|
2869
|
+
return "200 Hz"
|
|
2870
|
+
|
|
2871
|
+
if frequency == MH.DataFrequency.DATA_FREQ_400Hz:
|
|
2872
|
+
return "400 Hz"
|
|
2873
|
+
|
|
2874
|
+
if frequency == MH.DataFrequency.DATA_FREQ_800Hz:
|
|
2875
|
+
return "800 Hz"
|
|
2876
|
+
|
|
2877
|
+
if frequency == MH.DataFrequency.DATA_FREQ_1600Hz:
|
|
2878
|
+
return "1600 Hz"
|
|
2879
|
+
else:
|
|
2880
|
+
return "NONE"
|
|
2881
|
+
|
|
2882
|
+
# end DECODING FUNCTIONS
|