sonar_socket3_test.py 10 KB

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