sonar_socket2.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import socket
  2. import struct
  3. import select
  4. import time
  5. from io import BytesIO
  6. import matplotlib.pyplot as plt
  7. import matplotlib.image as image
  8. import construct as c
  9. import numpy as np
  10. from PIL import Image
  11. from db_connecter import UseDatabase
  12. from memory_storage import MemoryStorage
  13. from hard_disk_storage import HardDiskStorage
  14. from PIL import Image
  15. import ctypes
  16. import os
  17. SONAR_MODE = 'lvs34'
  18. redis_db = MemoryStorage()
  19. hard_disk_db = HardDiskStorage()
  20. data_heard = c.Struct(magic_number=c.Int32ul, length_mm=c.Int32ul, type=c.Int32ul)
  21. sonar_data = c.Struct(
  22. magic_number=c.Int32ul, # 固定不便,可能用于区分不同设备
  23. length_mm=c.Int32ul, # 数据包长度
  24. type=c.Int32ul, # 固定不变,可能用于识别声呐不同状态的数据
  25. sequence_count=c.Int32ul, # 每个包加一
  26. num_results=c.Int32ul, # 每包数据量
  27. pack_count=c.Int32ul, # 累加数据量,可能用于判断当前是第几个包
  28. length_data_mm=c.Int32ul, # 当前包数据量
  29. # pack_data=c.Array(c.this.length_data_mm, c.Byte) # 数据,怀疑是声呐数据
  30. pack_data=c.Bytes(c.this.length_data_mm)
  31. )
  32. def is_allowed_save():
  33. # 从redis获取是否存储标志,允许存储返回时间戳
  34. res = redis_db.get_value(['flag', 'timestamp', 'num', 'depth', 'temp', 'yaw', 'roll', 'pitch', 'servo_angle', 'img_type'])
  35. # {'flag': '0', 'timestamp': None, 'num': None, 'depth': '-2.350517511367798', 'temp': '7.96875', 'yaw': '310.625', 'roll': '-0.5', 'pitch': '178.75', 'servo_angle': '5', 'img_type': None}
  36. if 'flag' in res:
  37. if res['flag'] == '1':
  38. return res
  39. else:
  40. return False
  41. else:
  42. return False
  43. def get_uuid():
  44. sql = f"SELECT uuid FROM measurement_data ORDER BY id DESC LIMIT 1;"
  45. result = hard_disk_db.execute_sql(sql, None)
  46. if result:
  47. return result[0]['uuid']
  48. else:
  49. return None
  50. # 接收方
  51. def Receiver():
  52. group_ip = '239.254.2.16' # 组地址
  53. group_port = 50223 # 端口号
  54. # 创建IPv4/UDP套接字
  55. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
  56. sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  57. # 获取本地ip 先获取主机名,在通过主机名获取ip
  58. # local_ip = socket.gethostbyname(socket.gethostname()) #windows
  59. local_ip = '0.0.0.0' # ubuntu
  60. # local_ip = '192.168.1.188' # ubuntu
  61. # 绑定端口
  62. sock.bind((local_ip, group_port))
  63. mreq = struct.pack("=4sl", socket.inet_aton(group_ip), socket.INADDR_ANY)
  64. while True:
  65. try:
  66. # 加入组播组
  67. # 使用默认的IPV4组播接口
  68. sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
  69. break
  70. except Exception as e:
  71. print(e)
  72. time.sleep(1)
  73. sequence_count = None # 期望的序列号,用于检测是否丢失或乱序
  74. sonar_data_list = None
  75. count = 0
  76. save_img = 0
  77. path = '/data/bin_data/'
  78. sonar_temp = -10
  79. dll = ctypes.CDLL("/home/sencott/sonar/sonar/build/libImageDraw.so")
  80. while True:
  81. data, addr = sock.recvfrom(65536) # 接受数值大一点,防止被撑爆
  82. # print('images', len(data))
  83. if count < 100:
  84. count = count + 1
  85. if len(data) == 96:
  86. save_img = save_img + 1
  87. else:
  88. if save_img > 1:
  89. redis_db.set_value({'sonar_status': 'open'})
  90. else:
  91. redis_db.set_value({'sonar_status': 'close'})
  92. save_img = 0
  93. count = 0
  94. res = data_heard.parse(data)
  95. if res.magic_number == 2308 and res.type == 393284:
  96. res = sonar_data.parse(data)
  97. if res.pack_count == 0:
  98. sonar_data_list = res.pack_data
  99. sequence_count = res.sequence_count
  100. elif sequence_count == res.sequence_count:
  101. sonar_data_list = sonar_data_list + res.pack_data
  102. if sonar_data_list != None:
  103. debug = False
  104. if debug == True:
  105. # 显示及存储,调试使用
  106. if len(sonar_data_list) == res.num_results:
  107. if SONAR_MODE == 'lvs34':
  108. img = sonar_data_list[3645:] # lvs34
  109. elif SONAR_MODE == 'lvs62':
  110. img = sonar_data_list[1853:] # lvs62
  111. plt.clf() # 清除上一幅图像
  112. byte_stream = BytesIO(img)
  113. img = image.imread(byte_stream, format='jpeg')
  114. # # 图片保存
  115. # roiImg = Image.open(byte_stream)
  116. # roiImg.save('save.jpeg')
  117. plt.imshow(img)
  118. plt.pause(0.05) # 暂停0.05秒 这一句是实现动态更新的
  119. plt.ioff() # 关闭画图的窗口
  120. # redis_db.set_value({'flag': '0'})
  121. # if not save_info:
  122. # continue
  123. if len(sonar_data_list) == res.num_results:
  124. # print("数据包大小(字节):", len(sonar_data_list))
  125. if SONAR_MODE == 'lvs34':
  126. angle_data = sonar_data_list[68:2112] # lvs34
  127. img = sonar_data_list[3645:] # lvs34
  128. elif SONAR_MODE == 'lvs62':
  129. angle_data = sonar_data_list[68:1088] # lvs62
  130. img = sonar_data_list[1853:] # lvs62
  131. # print('save_image',img)
  132. image = angle_data + img
  133. # 预览图像
  134. dll.draw_image(ctypes.c_char_p('/data/tmp/'.encode()), ctypes.c_char_p('tmp'.encode()), image, len(image), 43)
  135. save_info = is_allowed_save()
  136. uuid = get_uuid()
  137. if save_info: # 允许存储
  138. # 数据库存储
  139. sql = f"insert into sonar_data (uuid,image_name, depth, temp, yaw, roll, pitch, servo_angle, sonar_temp) " \
  140. f"values (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
  141. res_data = redis_db.get_value(["sonar_temp"])
  142. if res_data['sonar_temp']:
  143. sonar_temp = res_data['sonar_temp']
  144. else:
  145. sonar_temp = -10
  146. if not uuid:
  147. continue
  148. val = (uuid,
  149. save_info['timestamp'][0:10] + '_' + save_info['img_type'] + '_' + save_info['num'],
  150. save_info['depth'],
  151. save_info['temp'], save_info['yaw'], save_info['roll'], save_info['pitch'],
  152. save_info['servo_angle'], sonar_temp)
  153. # 二进制文件存储
  154. img_name = save_info['timestamp'][0:10] + '_' + save_info['img_type'] + '_' + save_info['num']
  155. f1 = open(path + str(img_name) + '.bin', 'wb')
  156. f1.write(angle_data + img)
  157. f1.close()
  158. hard_disk_db.execute_sql(sql, val)
  159. # 图像解析存储
  160. save_path_in = '/data/img_data/'
  161. save_path_p = ctypes.c_char_p(save_path_in.encode())
  162. filename_p = ctypes.c_char_p(img_name.encode())
  163. if save_info['img_type'] == "s":
  164. mat_ptr = dll.draw_image(save_path_p, filename_p, angle_data + img, len(angle_data + img), 43)
  165. else:
  166. mat_ptr = dll.draw_image(save_path_p, filename_p, angle_data + img, len(angle_data + img), 34)
  167. redis_db.set_value({'flag': '0'}) # 存储完一帧,置零,否则会出现
  168. # packet_seq_num, total_packets, packet_data = data.split(b":") # 从数据包中解析序号、总包数和数据
  169. # print(packet_seq_num, total_packets, packet_data)
  170. # img = BytesIO(data)
  171. if __name__ == '__main__':
  172. Receiver()
  173. # while True:
  174. # save_info = is_allowed_save()
  175. # if not save_info:
  176. # continue
  177. # print(save_info)
  178. # conn = UseDatabase()
  179. # sql = f"insert into sonar_data (image_name, angle, images, depth, temp, yaw, roll, pitch, servo_angle) " \
  180. # f"values (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
  181. # val = (save_info['timestamp'] + '_' + save_info['num'], b'123', b'123', save_info['depth'],
  182. # save_info['temp'], save_info['yaw'], save_info['roll'], save_info['pitch'], save_info['servo_angle'])
  183. # conn.update(sql, val)
  184. # redis_db.set_value({'flag': '0'}) # 存储完一帧,置零