connection.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import threading
  2. import time
  3. import serial
  4. import serial.tools.list_ports
  5. import Log_handler
  6. class SerialConnection:
  7. def __init__(self):
  8. self._ser = None
  9. self.port = None
  10. self.log_handler = Log_handler.get_log_handler()
  11. # try connecting to an available port
  12. def open(self, port = None, baudrate = 1000000):
  13. if port != None:
  14. self.port = port
  15. if self.port:
  16. try:
  17. self._ser = serial.Serial(self.port, baudrate)
  18. print("SERIAL: connected to " + self.port)
  19. self.log_handler.add_item("SERIAL: connected to " + self.port)
  20. except serial.SerialException as e:
  21. print("SERIAL:", e)
  22. self.log_handler.add_item("SERIAL:", e)
  23. else:
  24. for port, name, _ in serial.tools.list_ports.comports():
  25. try:
  26. self._ser = serial.Serial(port, baudrate)
  27. print("SERIAL: connected to " + port + ", name: " + name)
  28. self.log_handler.add_item("SERIAL: connected to " + port + ", name: " + name)
  29. self.port = port
  30. break
  31. except serial.SerialException as e:
  32. print("SERIAL:", e)
  33. self.log_handler.add_item("SERIAL:", e)
  34. if not self._ser:
  35. print("SERIAL: no device available")
  36. self.log_handler.add_item("SERIAL: no device available")
  37. def send(self, bytes):
  38. if self._ser:
  39. try:
  40. return self._ser.write(bytes)
  41. except serial.SerialException:
  42. self._ser = None
  43. else:
  44. time.sleep(10)
  45. self.open()
  46. return None
  47. def read(self, n=64):
  48. if self._ser:
  49. try:
  50. return self._ser.read(n)
  51. except AttributeError as e:
  52. print("SERIAL:", e)
  53. self.log_handler.add_item("SERIAL:", e)
  54. return None
  55. except serial.SerialException as e:
  56. print("SERIAL:", e)
  57. self.log_handler.add_item("SERIAL:", e)
  58. if self._ser.isOpen():
  59. self._ser.close()
  60. self._ser = None
  61. return None
  62. else:
  63. time.sleep(10)
  64. self.open()
  65. return None
  66. def readline(self):
  67. if self._ser:
  68. try:
  69. return self._ser.readline()
  70. except AttributeError as e:
  71. print("SERIAL:", e)
  72. self.log_handler.add_item("SERIAL:", e)
  73. return None
  74. except serial.SerialException as e:
  75. print("SERIAL:", e)
  76. self.log_handler.add_item("SERIAL:", e)
  77. if self._ser.isOpen():
  78. self._ser.close()
  79. self._ser = None
  80. return None
  81. else:
  82. time.sleep(10)
  83. self.open()
  84. return None
  85. def isConnected(self):
  86. return self._ser != None
  87. def close(self):
  88. if self._ser:
  89. self._ser.close()
  90. self._ser = None
  91. class ArduinoSlave(SerialConnection):
  92. def __init__(self):
  93. super().__init__()
  94. self.sensorData = [0] * 13
  95. self._recvCbs = []
  96. self._t = threading.Thread(target=self._readSensors, args=())
  97. self._t.daemon = True # thread dies when main thread (only non-daemon thread) exits.
  98. def open(self, port = None, baudrate = 1000000):
  99. super().open(port, baudrate)
  100. if not self._t.is_alive():
  101. self._t.start()
  102. def close(self):
  103. super().close()
  104. def getAcusticRTTs(self): # in microseconds
  105. return (
  106. int(self.sensorData[0]) / 16,
  107. int(self.sensorData[1]) / 16
  108. )
  109. def getMagneticField(self): # in mT
  110. return (
  111. int(self.sensorData[2]) / 1000,
  112. int(self.sensorData[3]) / 1000,
  113. int(self.sensorData[4]) / 1000
  114. )
  115. def getAccelValues(self):
  116. return (
  117. int(self.sensorData[5]) / 1000,
  118. int(self.sensorData[6]) / 1000,
  119. int(self.sensorData[7]) / 1000
  120. )
  121. def getGyroValues(self):
  122. return (
  123. int(self.sensorData[8]) / 1000,
  124. int(self.sensorData[9]) / 1000,
  125. int(self.sensorData[10]) / 1000
  126. )
  127. def getTemperature(self): # in °C
  128. return int(self.sensorData[11]) / 1000
  129. def addRecvCallback(self, cb):
  130. self._recvCbs.append(cb)
  131. def _readSensors(self):
  132. while True:
  133. data = super().readline()
  134. if data and len(data) > 2:
  135. data = str(data, encoding="ASCII", errors="ignore")
  136. vals = data[:-2].split('\t')
  137. if vals[0] == "DATA:" and len(vals) >= 13:
  138. self.sensorData = vals[1:]
  139. for cb in self._recvCbs:
  140. cb(self.sensorData)
  141. else:
  142. print("SERIAL: ", data[:-2])
  143. self.log_handler.add_item("SERIAL: ", data[:-2])
  144. # this allows the usage of a single instance of ArduinoSlave
  145. _conn = None
  146. def globalArduinoSlave():
  147. global _conn
  148. if not _conn:
  149. _conn = ArduinoSlave()
  150. return _conn
  151. if __name__ == "__main__":
  152. arduino = ArduinoSlave()
  153. def cb(x):
  154. print(arduino.getAcusticRTTs(), arduino.getMagneticField(), arduino.getTemperature())
  155. arduino.addRecvCallback(cb)
  156. arduino.open()
  157. while True:
  158. time.sleep(1)