sensor-sdk 0.0.4__py3-none-any.whl → 0.0.6__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.

Potentially problematic release.


This version of sensor-sdk might be problematic. Click here for more details.

@@ -1,6 +1,8 @@
1
1
  import asyncio
2
2
  from collections import deque
3
+ import platform
3
4
  from queue import Queue
5
+ import struct
4
6
  from typing import Deque, List
5
7
 
6
8
  from sensor.gforce import DataSubscription, GForce
@@ -42,6 +44,7 @@ class SensorProfileDataCtx:
42
44
  self.deviceMac = deviceMac
43
45
  self._device_info: DeviceInfo = None
44
46
 
47
+ self._is_initing = False
45
48
  self._is_running = True
46
49
  self._is_data_transfering = False
47
50
  self.isUniversalStream: bool = gForce._is_universal_stream
@@ -79,7 +82,7 @@ class SensorProfileDataCtx:
79
82
  return self._is_data_transfering
80
83
 
81
84
  def hasInit(self):
82
- return self.featureMap != 0 and self.notifyDataFlag != 0
85
+ return not self._is_initing and self.featureMap != 0 and self.notifyDataFlag != 0
83
86
 
84
87
  def hasEMG(self):
85
88
  return (self.featureMap & FeatureMaps.GFD_FEAT_EMG.value) != 0
@@ -198,32 +201,44 @@ class SensorProfileDataCtx:
198
201
 
199
202
  async def fetchDeviceInfo(self) -> DeviceInfo:
200
203
  info = DeviceInfo()
201
- info.MTUSize = self.gForce.client.mtu_size
204
+ if platform.system() != "Linux":
205
+ info.MTUSize = self.gForce.client.mtu_size
206
+ else:
207
+ info.MTUSize = 0
208
+ print("get_device_name")
202
209
  info.DeviceName = await self.gForce.get_device_name()
210
+ print("get_model_number")
203
211
  info.ModelName = await self.gForce.get_model_number()
212
+ print("get_hardware_revision")
204
213
  info.HardwareVersion = await self.gForce.get_hardware_revision()
214
+ print("get_firmware_revision")
205
215
  info.FirmwareVersion = await self.gForce.get_firmware_revision()
206
216
  return info
207
217
 
208
218
  async def init(self, packageCount: int) -> bool:
219
+ if self._is_initing:
220
+ return False
209
221
  try:
222
+ self._is_initing = True
210
223
  info = await self.fetchDeviceInfo()
211
-
212
224
  await self.initDataTransfer(True)
213
-
214
225
  if self.hasImpedance():
215
226
  self.notifyDataFlag |= DataSubscription.DNF_IMPEDANCE
216
227
 
217
228
  if self.hasEEG():
229
+ print("initEEG")
218
230
  info.EegChannelCount = await self.initEEG(packageCount)
219
231
 
220
232
  if self.hasECG():
233
+ print("initECG")
221
234
  info.EcgChannelCount = await self.initECG(packageCount)
222
235
 
223
236
  if self.hasBrth():
237
+ print("initBrth")
224
238
  info.BrthChannelCount = await self.initBrth(packageCount)
225
239
 
226
240
  if self.hasIMU():
241
+ print("initIMU")
227
242
  imuChannelCount = await self.initIMU(packageCount)
228
243
  info.AccChannelCount = imuChannelCount
229
244
  info.GyroChannelCount = imuChannelCount
@@ -233,9 +248,11 @@ class SensorProfileDataCtx:
233
248
  if not self.isUniversalStream:
234
249
  await self.initDataTransfer(False)
235
250
 
251
+ self._is_initing = False
236
252
  return True
237
253
  except Exception as e:
238
254
  print(e)
255
+ self._is_initing = False
239
256
  return False
240
257
 
241
258
  async def start_streaming(self) -> bool:
@@ -263,16 +280,16 @@ class SensorProfileDataCtx:
263
280
  await self.gForce.set_subscription(0)
264
281
  return True
265
282
 
266
- def process_data(self, buf: Queue[SensorData]):
283
+ def process_data(self, buf: Queue[SensorData], sensor):
267
284
  try:
268
285
  data: bytes = self._rawDataBuffer.get_nowait()
269
286
  except Exception as e:
270
287
  return
271
288
 
272
- self._processDataPackage(data, buf)
289
+ self._processDataPackage(data, buf, sensor)
273
290
  self._rawDataBuffer.task_done()
274
291
 
275
- def _processDataPackage(self, data: bytes, buf: Queue[SensorData]):
292
+ def _processDataPackage(self, data: bytes, buf: Queue[SensorData], sensor):
276
293
  v = data[0]
277
294
  if v == DataType.NTF_IMPEDANCE:
278
295
  offset = 1
@@ -283,15 +300,14 @@ class SensorProfileDataCtx:
283
300
  saturationData = []
284
301
 
285
302
  dataCount = (len(data) - 3) // 4 // 2
303
+
286
304
  for index in range(dataCount):
287
- impedance_bytes = data[offset : offset + 4]
288
- impedance = int.from_bytes(impedance_bytes, byteorder="little")
305
+ impedance = struct.unpack_from("<f", data, offset)[0]
289
306
  offset += 4
290
307
  impedanceData.append(impedance)
291
308
 
292
309
  for index in range(dataCount):
293
- saturation_bytes = data[offset : offset + 4]
294
- saturation = int.from_bytes(saturation_bytes, byteorder="little")
310
+ saturation = struct.unpack_from("<f", data, offset)[0]
295
311
  offset += 4
296
312
  saturationData.append(saturation / 10) # firmware value range 0 - 1000
297
313
 
@@ -300,28 +316,26 @@ class SensorProfileDataCtx:
300
316
 
301
317
  elif v == DataType.NTF_EEG:
302
318
  sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_EEG]
303
- if self.checkReadSamples(data, sensor_data, 3, 0):
319
+ if self.checkReadSamples(sensor, data, sensor_data, 3, 0):
304
320
  self.sendSensorData(sensor_data, buf)
305
321
  elif v == DataType.NTF_ECG:
306
322
  sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_ECG]
307
- if self.checkReadSamples(data, sensor_data, 3, 0):
323
+ if self.checkReadSamples(sensor, data, sensor_data, 3, 0):
308
324
  self.sendSensorData(sensor_data, buf)
309
325
  elif v == DataType.NTF_BRTH:
310
326
  sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_BRTH]
311
- if self.checkReadSamples(data, sensor_data, 3, 0):
327
+ if self.checkReadSamples(sensor, data, sensor_data, 3, 0):
312
328
  self.sendSensorData(sensor_data, buf)
313
329
  elif v == DataType.NTF_IMU:
314
330
  sensor_data_acc = self.sensorDatas[SensorDataType.DATA_TYPE_ACC]
315
- if self.checkReadSamples(data, sensor_data_acc, 3, 6):
331
+ if self.checkReadSamples(sensor, data, sensor_data_acc, 3, 6):
316
332
  self.sendSensorData(sensor_data_acc, buf)
317
333
 
318
334
  sensor_data_gyro = self.sensorDatas[SensorDataType.DATA_TYPE_GYRO]
319
- if self.checkReadSamples(data, sensor_data_gyro, 9, 6):
335
+ if self.checkReadSamples(sensor, data, sensor_data_gyro, 9, 6):
320
336
  self.sendSensorData(sensor_data_gyro, buf)
321
337
 
322
- def checkReadSamples(
323
- self, data: bytes, sensorData: SensorData, dataOffset: int, dataGap: int
324
- ):
338
+ def checkReadSamples(self, sensor, data: bytes, sensorData: SensorData, dataOffset: int, dataGap: int):
325
339
  offset = 1
326
340
  v = data[0]
327
341
  if not self._is_data_transfering:
@@ -340,12 +354,22 @@ class SensorProfileDataCtx:
340
354
 
341
355
  deltaPackageIndex = packageIndex - lastPackageIndex
342
356
  if deltaPackageIndex > 1:
343
- lostSampleCount = sensorData.packageSampleCount * (
344
- deltaPackageIndex - 1
345
- )
346
- print(
347
- f"lost dataType {sensorData.dataType} -> data {sensorData.deviceMac} {lostSampleCount}"
357
+ lostSampleCount = sensorData.packageSampleCount * (deltaPackageIndex - 1)
358
+ lostLog = (
359
+ "MSG|LOST SAMPLE|MAC|"
360
+ + str(sensorData.deviceMac)
361
+ + "|TYPE|"
362
+ + str(sensorData.dataType)
363
+ + "|COUNT|"
364
+ + str(lostSampleCount)
348
365
  )
366
+ # print(lostLog)
367
+ if sensor._event_loop != None and sensor._on_error_callback != None:
368
+ try:
369
+ sensor._event_loop.call_soon_threadsafe(sensor._on_error_callback, sensor, lostLog)
370
+ except Exception as e:
371
+ pass
372
+
349
373
  self.readSamples(data, sensorData, 0, dataGap, lostSampleCount)
350
374
  if newPackageIndex == 0:
351
375
  sensorData.lastPackageIndex = 65535
@@ -356,7 +380,8 @@ class SensorProfileDataCtx:
356
380
  self.readSamples(data, sensorData, dataOffset, dataGap, 0)
357
381
  sensorData.lastPackageIndex = newPackageIndex
358
382
  sensorData.lastPackageCounter += 1
359
- except Exception:
383
+ except Exception as e:
384
+ print(e)
360
385
  return False
361
386
  return True
362
387
 
@@ -385,19 +410,19 @@ class SensorProfileDataCtx:
385
410
  channelSamples.append([])
386
411
 
387
412
  for sampleIndex in range(sampleCount):
388
- for channelIndex, impedanceChannelIndex in enumerate(
389
- range(sensorData.channelCount)
390
- ):
413
+ for channelIndex, impedanceChannelIndex in enumerate(range(sensorData.channelCount)):
391
414
  if (sensorData.channelMask & (1 << channelIndex)) != 0:
392
415
  samples = channelSamples[channelIndex]
393
416
  impedance = 0.0
394
417
  saturation = 0.0
418
+
395
419
  if sensorData.dataType == DataType.NTF_ECG:
396
- impedanceChannelIndex = self.sensorDatas[
397
- SensorDataType.DATA_TYPE_EEG
398
- ].channelCount
399
- impedance = _impedanceData[impedanceChannelIndex]
400
- saturation = _saturationData[impedanceChannelIndex]
420
+ impedanceChannelIndex = self.sensorDatas[SensorDataType.DATA_TYPE_EEG].channelCount
421
+
422
+ if impedanceChannelIndex < len(_impedanceData):
423
+ impedance = _impedanceData[impedanceChannelIndex]
424
+ saturation = _saturationData[impedanceChannelIndex]
425
+
401
426
  impedanceChannelIndex += 1
402
427
 
403
428
  dataItem = Sample()
@@ -424,11 +449,7 @@ class SensorProfileDataCtx:
424
449
  )
425
450
  offset += 2
426
451
  elif sensorData.resolutionBits == 24:
427
- rawData = (
428
- (data[offset] << 16)
429
- | (data[offset + 1] << 8)
430
- | data[offset + 2]
431
- )
452
+ rawData = (data[offset] << 16) | (data[offset + 1] << 8) | data[offset + 2]
432
453
  rawData -= 8388608
433
454
  offset += 3
434
455
 
@@ -765,9 +786,7 @@ class SensorProfileDataCtx:
765
786
 
766
787
  return crc8
767
788
 
768
- def processUniversalData(
769
- self, buf: Queue[SensorData], loop: asyncio.AbstractEventLoop, sensor, callback
770
- ):
789
+ def processUniversalData(self, buf: Queue[SensorData], loop: asyncio.AbstractEventLoop, sensor, callback):
771
790
 
772
791
  while self._is_running:
773
792
  try:
@@ -795,28 +814,22 @@ class SensorProfileDataCtx:
795
814
  index += 1
796
815
  continue
797
816
  crc = self._concatDataBuffer[index + 1 + n + 1]
798
- calc_crc = self.calc_crc8(
799
- self._concatDataBuffer[index + 2 : index + 2 + n]
800
- )
817
+ calc_crc = self.calc_crc8(self._concatDataBuffer[index + 2 : index + 2 + n])
801
818
  if crc != calc_crc:
802
819
  index += 1
803
820
  continue
804
821
  if self._is_data_transfering:
805
- data_package = bytes(
806
- self._concatDataBuffer[index + 2 : index + 2 + n]
807
- )
808
- self._processDataPackage(data_package, buf)
822
+ data_package = bytes(self._concatDataBuffer[index + 2 : index + 2 + n])
823
+ self._processDataPackage(data_package, buf, sensor)
809
824
  while self._is_running and self.isDataTransfering:
810
825
  sensorData: SensorData = None
811
826
  try:
812
827
  sensorData = buf.get_nowait()
813
828
  except Exception as e:
814
829
  break
815
- if sensorData != None and callback != None:
830
+ if loop != None and sensorData != None and callback != None:
816
831
  try:
817
- loop.call_soon_threadsafe(
818
- callback, sensor, sensorData
819
- )
832
+ loop.call_soon_threadsafe(callback, sensor, sensorData)
820
833
  except Exception as e:
821
834
  print(e)
822
835
 
@@ -832,18 +845,13 @@ class SensorProfileDataCtx:
832
845
  index += 1
833
846
  continue
834
847
  crc = self._concatDataBuffer[index + 1 + n + 1]
835
- calc_crc = self.calc_crc8(
836
- self._concatDataBuffer[index + 2 : index + 2 + n]
837
- )
848
+ calc_crc = self.calc_crc8(self._concatDataBuffer[index + 2 : index + 2 + n])
838
849
  if crc != calc_crc:
839
850
  index += 1
840
851
  continue
841
- data_package = bytes(
842
- self._concatDataBuffer[index + 2 : index + 2 + n]
843
- )
844
- loop.call_soon_threadsafe(
845
- self.gForce._on_cmd_response, None, data_package
846
- )
852
+ data_package = bytes(self._concatDataBuffer[index + 2 : index + 2 + n])
853
+ if loop != None:
854
+ loop.call_soon_threadsafe(self.gForce._on_cmd_response, None, data_package)
847
855
  last_cut = index = index + 2 + n
848
856
  else:
849
857
  index += 1