server-simulator.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. import numpy as np
  2. import scipy.interpolate as interp
  3. import msgpack
  4. import json
  5. import socket
  6. import time as tm
  7. class ServerSimulator:
  8. def __init__(self):
  9. self.events = []
  10. self.rfwaves = {"default": (np.ones(512, dtype=np.int16) * np.floor(3.3 / 5 * 32767), np.zeros(512, dtype=np.int16))} # Default RF wave is a 100-sample pulse at max amplitude
  11. self.time = 0
  12. #Socket parameters
  13. self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  14. self.sock.bind(('127.0.0.1', 5003))
  15. self.sock.listen()
  16. self.conn = 0
  17. self.magic = 0xAA
  18. self.cmd = 0x00
  19. self.data = {}
  20. self.simview = {}
  21. #Simulation parameters
  22. self.level = 20000
  23. self.simview = {
  24. "time": np.array([], dtype=np.int64),
  25. "channel_g": np.array([], dtype=np.int16),
  26. "channel_rf_ttl": np.array([], dtype=np.int16),
  27. "channel_adc_ttl": np.array([], dtype=np.int16),
  28. "channel_rf": np.array([], dtype=np.int16)
  29. }
  30. #32bit Codes
  31. self.errCode = 0x00000000
  32. self.statCode = 0x00000000
  33. # Command callbacks
  34. self.cmd_dict = {
  35. 0x10: self.addEvent,
  36. 0x20: self.getRfwaveTable,
  37. 0x30: self.runEventList,
  38. 0x40: self.sendSimViewData,
  39. 0x60: self.clearEventList,
  40. 0x70: self.setFrequency,
  41. 0x00: self.disconnect
  42. }
  43. def connect(self):
  44. self.conn, self.addr = self.sock.accept()
  45. print(f"New connection from {self.addr}")
  46. return True
  47. def disconnect(self):
  48. self.conn.close()
  49. print(f"Connection with {self.addr} closed")
  50. return True
  51. def getErrorMsg(self, errCode, errString):
  52. error = {
  53. "magic": self.magic,
  54. "cmd": 0xFF,
  55. "code": errCode,
  56. "message": errString
  57. }
  58. return msgpack.packb(error, use_bin_type=True)
  59. def getStatusMsg(self, statCode, statString):
  60. status = {
  61. "magic": self.magic,
  62. "cmd": 0xFE,
  63. "code": statCode,
  64. "message": statString
  65. }
  66. return msgpack.packb(status, use_bin_type=True)
  67. def acceptCommand(self):
  68. try:
  69. rawdata = self.conn.recv(4096)
  70. # Check if data is received
  71. if not rawdata:
  72. return 2
  73. # Unpack data using msgpack
  74. self.data = msgpack.unpackb(rawdata, raw=False)
  75. if self.data["magic"] != self.magic:
  76. print("Invalid magic byte")
  77. self.errCode = 0x00000051 # Invalid magic byte
  78. self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid magic byte"))
  79. return 2
  80. if self.data["cmd"] not in self.cmd_dict.keys():
  81. print("Invalid command")
  82. self.errCode = 0x00000052 # Invalid command
  83. self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid command"))
  84. return 2
  85. print(f"Received command: {self.data['cmd']}")
  86. # Process command
  87. self.cmd = self.data["cmd"]
  88. self.cmd_dict[self.cmd](self.data)
  89. except Exception as e:
  90. print(f"Exception: {e}")
  91. return False
  92. return True
  93. def addEvent(self, data):
  94. if not all (k in data for k in ("time", "duration", "wave", "time_front_rf_trigger", "time_back_rf_trigger", "rf_start", "rf_end", "time_front_adc_trigger", "time_back_adc_trigger")):
  95. print("Missing event parameters")
  96. self.errCode = 0x00000001 # Missing parameters
  97. self.conn.sendall(self.getErrorMsg(self.errCode, "Missing event parameters"))
  98. return 2
  99. event = {
  100. "start_time": data["time"],
  101. "duration": data["duration"],
  102. "wave": data["wave"],
  103. "carrier_freq": data["carrier_freq"],
  104. "time_front_rf_trigger": data["time_front_rf_trigger"],
  105. "time_back_rf_trigger": data["time_back_rf_trigger"],
  106. "rf_start": data["rf_start"],
  107. "rf_end": data["rf_end"],
  108. "time_front_adc_trigger": data["time_front_adc_trigger"],
  109. "time_back_adc_trigger": data["time_back_adc_trigger"],
  110. "phase_offset": data["phase_offset"]
  111. }
  112. if event["start_time"] < self.time:
  113. print("Event start time is in the past")
  114. self.errCode = 0x00000002 # Event in the past
  115. self.conn.sendall(self.getErrorMsg(self.errCode, "Event start time is in the past"))
  116. return 2
  117. if event["time_front_rf_trigger"] < 0 or event["time_back_rf_trigger"] < 0 or event["rf_start"] < 0 or event["rf_end"] < 0:
  118. print("RF trigger times and delays must be non-negative")
  119. self.errCode = 0x00000003 # Negative times
  120. self.conn.sendall(self.getErrorMsg(self.errCode, "RF trigger times and delays must be non-negative"))
  121. return 2
  122. if event["time_front_adc_trigger"] < 0 or event["time_back_adc_trigger"] < 0:
  123. print("ADC trigger times must be non-negative")
  124. self.errCode = 0x00000004 # Negative times
  125. self.conn.sendall(self.getErrorMsg(self.errCode, "ADC trigger times must be non-negative"))
  126. return 2
  127. if event["time_front_rf_trigger"] > event["duration"] or event["time_back_rf_trigger"] > event["duration"]:
  128. print("RF trigger times must be within event duration")
  129. self.errCode = 0x00000005 # RF trigger times out of bounds
  130. self.conn.sendall(self.getErrorMsg(self.errCode, "RF trigger times must be within event duration"))
  131. return 2
  132. if event["rf_start"] > event["duration"] or event["rf_end"] > event["duration"]:
  133. print("RF start and end times must be within event duration")
  134. self.errCode = 0x00000006 # RF start/end times out of bounds
  135. self.conn.sendall(self.getErrorMsg(self.errCode, "RF start and end times must be within event duration"))
  136. return 2
  137. if event["time_front_adc_trigger"] > event["duration"] or event["time_back_adc_trigger"] > event["duration"]:
  138. print("ADC trigger times must be within event duration")
  139. self.errCode = 0x00000007 # ADC trigger times out of bounds
  140. self.conn.sendall(self.getErrorMsg(self.errCode, "ADC trigger times must be within event duration"))
  141. return 2
  142. if event["time_front_rf_trigger"] < event["time_back_rf_trigger"]:
  143. print("RF triggers and delays overlap")
  144. self.errCode = 0x00000008 # RF triggers overlap
  145. self.conn.sendall(self.getErrorMsg(self.errCode, "RF triggers and delays overlap"))
  146. return 2
  147. if event["time_front_adc_trigger"] < event["time_back_adc_trigger"]:
  148. print("ADC triggers overlap")
  149. self.errCode = 0x00000009 # ADC triggers overlap
  150. self.conn.sendall(self.getErrorMsg(self.errCode, "ADC triggers overlap"))
  151. return 2
  152. if event["rf_start"] > event["rf_end"]:
  153. print("RF start and end times overlap")
  154. self.errCode = 0x0000000A # RF start/end times overlap
  155. self.conn.sendall(self.getErrorMsg(self.errCode, "RF start and end times overlap"))
  156. return 2
  157. if event["rf_start"] < event["time_back_rf_trigger"] or event["rf_end"] > event["time_front_rf_trigger"]:
  158. print("RF start and end times must be within RF trigger times")
  159. self.errCode = 0x0000000B # RF start/end times outside triggers
  160. self.conn.sendall(self.getErrorMsg(self.errCode, "RF start and end times must be within RF trigger times"))
  161. return 2
  162. if event["rf_end"] - event["rf_start"] < len(self.rfwaves[event["wave"]]):
  163. print("RF pulse duration must be at least as long as the wave length")
  164. self.errCode = 0x0000000C # Insufficient RF pulse duration
  165. self.conn.sendall(self.getErrorMsg(self.errCode, "RF pulse duration must be at least as long as the wave length"))
  166. return 2
  167. self.events.append(event)
  168. self.time = event["start_time"] + event["duration"]
  169. print(f"Added event: {event}")
  170. self.conn.sendall(self.getStatusMsg(0x00000010, "Event added successfully"))
  171. return True
  172. def getRfwaveTable(self, data):
  173. if not all (k in data for k in ("wavetype", "total_length", "total_packets", "packet_length")):
  174. print("Missing RF wave parameters")
  175. self.errCode = 0x0000000F # Missing parameters
  176. self.conn.sendall(self.getErrorMsg(self.errCode, "Missing RF wave parameters"))
  177. return 2
  178. wavetype = data["wavetype"]
  179. total_length = data["total_length"]
  180. total_packets = data["total_packets"]
  181. total_wave_q = np.array([], dtype=np.int16)
  182. total_wave_i = np.array([], dtype=np.int16)
  183. self.conn.sendall(self.getStatusMsg(0x00000001, f"Ready to receive RF wave data packets"))
  184. for i in range(total_packets):
  185. print(f"Send packet {i}...")
  186. rawdata = self.conn.recv(4096)
  187. if not rawdata:
  188. print("No data received for RF wave packet")
  189. return 2
  190. packet_data = msgpack.unpackb(rawdata, raw=False)
  191. if packet_data["magic"] != self.magic:
  192. print("Invalid magic byte in RF wave packet")
  193. self.errCode = 0x00000014 # Invalid magic byte
  194. self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid magic byte in RF wave packet"))
  195. return 2
  196. if packet_data["cmd"] != 0x2C:
  197. print("Invalid command in RF wave packet")
  198. self.errCode = 0x00000013 # Invalid command
  199. self.conn.sendall(self.getErrorMsg(self.errCode, "Invalid command in RF wave packet"))
  200. return 2
  201. if "wavedata_q" not in packet_data or "wavedata_i" not in packet_data:
  202. print("Missing wave data in RF wave packet")
  203. self.errCode = 0x00000010 # Missing wave data
  204. self.conn.sendall(self.getErrorMsg(self.errCode, "Missing wave data in RF wave packet"))
  205. return 2
  206. wave_q = np.frombuffer(packet_data["wavedata_q"], dtype=np.int16)
  207. wave_i = np.frombuffer(packet_data["wavedata_i"], dtype=np.int16)
  208. if len(wave_q) != len(wave_i):
  209. print("In-phase and quadrature wave data must have the same length in RF wave packet")
  210. self.errCode = 0x00000012 # Mismatched wave data lengths
  211. self.conn.sendall(self.getErrorMsg(self.errCode, "In-phase and quadrature wave data must have the same length in RF wave packet"))
  212. return 2
  213. total_wave_q = np.concatenate([total_wave_q, wave_q])
  214. total_wave_i = np.concatenate([total_wave_i, wave_i])
  215. print(f"Received RF wave packet {i+1}/{total_packets} with length {len(wave_q)}")
  216. self.conn.sendall(self.getStatusMsg(0x00000002, f"Received RF wave packet {i+1}/{total_packets} with length {len(wave_q)}"))
  217. self.conn.recv(1024) # Wait for ACK before receiving next packet
  218. print("ACK recieved!")
  219. if len(total_wave_q) != total_length or len(total_wave_i) != total_length:
  220. print("Total wave data length does not match expected length")
  221. self.errCode = 0x00000011 # Total length mismatch
  222. self.conn.sendall(self.getErrorMsg(self.errCode, "Total wave data length does not match expected length"))
  223. return 2
  224. self.rfwaves[data["wavetype"]] = (total_wave_q, total_wave_i)
  225. print(f"RF wave '{wavetype}' received successfully with total length {total_length}")
  226. self.conn.sendall(self.getStatusMsg(0x00000003, f"RF wave '{wavetype}' received successfully with total length {total_length}"))
  227. self.conn.recv(1024)
  228. return True
  229. def runEventList(self, data):
  230. time_linspace = np.linspace(0, self.time, self.time+1)
  231. self.simview["time"] = time_linspace.astype(np.int64)
  232. channel_g = np.ones(self.time+1, dtype=np.int16) * np.floor(3.3 / 5 * 32767).astype(np.int16)
  233. channel_rf_ttl = np.zeros(self.time+1, dtype=np.int16)
  234. channel_adc_ttl = np.zeros(self.time+1, dtype=np.int16)
  235. channel_rf = np.zeros(self.time+1, dtype=np.int16)
  236. for event in self.events:
  237. print(f"Running event: {event}")
  238. # Simulate RF pulse
  239. rf_wave_q = self.rfwaves[event["wave"]][0]
  240. rf_wave_i = self.rfwaves[event["wave"]][1]
  241. rf_pulse_length = event["rf_end"] - event["rf_start"]
  242. rf_trigger_length = -event["time_back_rf_trigger"] + event["time_front_rf_trigger"]
  243. adc_trigger_length = -event["time_back_adc_trigger"] + event["time_front_adc_trigger"]
  244. rf_wave_length = len(rf_wave_q)
  245. event_length = event["duration"]
  246. rf_time = np.linspace(0, rf_pulse_length, rf_pulse_length+1)
  247. rf_trigger_time = np.linspace(0, rf_trigger_length, rf_trigger_length+1)
  248. adc_trigger_time = np.linspace(0, adc_trigger_length, adc_trigger_length+1)
  249. event_time = np.linspace(0, event_length, event_length+1)
  250. print(f"RF pulse length: {rf_pulse_length}, RF trigger length: {rf_trigger_length}, ADC trigger length: {adc_trigger_length}, Event length: {event_length}")
  251. if rf_pulse_length < rf_wave_length:
  252. print("RF pulse length is shorter than RF wave length, cannot run event")
  253. self.errCode = 0x00000031 # Invalid RF pulse length
  254. self.conn.sendall(self.getErrorMsg(self.errCode, "RF pulse length is shorter than RF wave length, cannot run event"))
  255. continue
  256. print("Interpolating RF wave to fit pulse duration...")
  257. interp_wave_q = np.zeros(rf_pulse_length, dtype=np.int16)
  258. interp_wave_i = np.zeros(rf_pulse_length, dtype=np.int16)
  259. if data["interpolation_method"] == "linear":
  260. interp_func_q = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_q, kind='linear')
  261. interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='linear')
  262. interp_wave_q = interp_func_q(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
  263. interp_wave_i = interp_func_i(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
  264. elif data["interpolation_method"] == "nearest":
  265. interp_func_q = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_q, kind='nearest')
  266. interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='nearest')
  267. interp_wave_q = interp_func_q(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
  268. interp_wave_i = interp_func_i(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
  269. elif data["interpolation_method"] == "cubic":
  270. interp_func_q = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_q, kind='cubic')
  271. interp_func_i = interp.interp1d(np.linspace(0, rf_wave_length, rf_wave_length), rf_wave_i, kind='cubic')
  272. interp_wave_q = interp_func_q(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
  273. interp_wave_i = interp_func_i(rf_time * (rf_wave_length / rf_pulse_length)).astype(np.int16)
  274. channel_rf[event["start_time"]+event["rf_start"]:event["start_time"]+event["rf_end"]+1] = np.floor((interp_wave_q * np.sin(2 * np.pi * event["carrier_freq"] * rf_time * 8e-9) - interp_wave_i * np.cos(2 * np.pi * event["carrier_freq"] * rf_time * 8e-9)) / np.sqrt(2)).astype(np.int16)
  275. channel_rf_ttl[event["start_time"]+event["time_back_rf_trigger"]:event["start_time"]+event["time_front_rf_trigger"]+1] = np.int16(1 * np.floor(3.3 / 5 * 32767))
  276. channel_adc_ttl[event["start_time"]+event["time_back_adc_trigger"]:event["start_time"]+event["time_front_adc_trigger"]+1] = np.int16(1 * np.floor(3.3 / 5 * 32767))
  277. channel_g[event["start_time"]:(event["start_time"]+event["duration"]+1)] = 0
  278. self.simview["channel_g"] = channel_g
  279. self.simview["channel_rf_ttl"] = channel_rf_ttl
  280. self.simview["channel_adc_ttl"] = channel_adc_ttl
  281. self.simview["channel_rf"] = channel_rf
  282. print(f"Simulation data: time length {len(self.simview['time'])}, channel_g length {len(self.simview['channel_g'])}, channel_rf_ttl length {len(self.simview['channel_rf_ttl'])}, channel_adc_ttl length {len(self.simview['channel_adc_ttl'])}, channel_rf length {len(self.simview['channel_rf'])}")
  283. self.conn.sendall(self.getStatusMsg(0x00000032, "Event list simulation complete"))
  284. return True
  285. def sendSimViewData(self, data):
  286. data_length = len(self.simview["time"])
  287. channels = ["channel_g", "channel_rf_ttl", "channel_adc_ttl", "channel_rf", "time"]
  288. packet_size = 512
  289. total_packets = (data_length * len(channels)) // packet_size + 1
  290. packet_index = 0
  291. self.conn.sendall(self.getStatusMsg(0x00000043, f"Ready to send simulation data in {total_packets} packets with size {packet_size} bytes"))
  292. self.conn.recv(4096) # ACK
  293. print(f"Starting to send simulation data: total length {data_length}, total packets {total_packets}")
  294. for channel in channels:
  295. channel_data = self.simview[channel]
  296. for i in range(0, len(channel_data), packet_size):
  297. packet_index += 1
  298. packet_data = None
  299. if i + packet_size > len(channel_data):
  300. packet_data = channel_data[i:]
  301. else:
  302. packet_data = channel_data[i:i+packet_size]
  303. packet_msg = {
  304. "magic": self.magic,
  305. "cmd": 0x33,
  306. "channel": channel,
  307. "total_packets": total_packets,
  308. "packet_index": packet_index,
  309. "data": packet_data.tobytes(),
  310. "data_length": len(packet_data)
  311. }
  312. print(f"Sending packet {packet_index}/{total_packets} for channel '{channel}' with data length {len(packet_data)}")
  313. self.conn.sendall(msgpack.packb(packet_msg, use_bin_type=True))
  314. self.conn.recv(4096) # Wait for ACK
  315. print("Simulation data sent successfully")
  316. self.conn.sendall(self.getStatusMsg(0x00000044, "All simulation data packets sent"))
  317. return True
  318. def clearEventList(self, data):
  319. self.events = []
  320. self.time = 0
  321. self.conn.sendall(self.getStatusMsg(0x00000064, "Event list cleared"))
  322. return True
  323. def setFrequency(self, data):
  324. if "frequency" not in data:
  325. print("Missing frequency parameter")
  326. self.errCode = 0x00000020 # Missing parameter
  327. self.conn.sendall(self.getErrorMsg(self.errCode, "Missing frequency parameter"))
  328. return 2
  329. self.freq = data["frequency"]
  330. self.conn.sendall(self.getStatusMsg(0x00000071, f"Frequency set to {self.freq} Hz"))
  331. return True
  332. server = ServerSimulator()
  333. while server.connect():
  334. while server.acceptCommand():
  335. pass