Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion controller/src/controller/subsystems/instrument_comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from ..constants import STIM_FINAL_SEXTANT
from ..constants import STIM_MODULE_ID_TO_WELL_IDX
from ..constants import StimScheduleType
from ..constants import StimulationStates
from ..constants import STM_VID
from ..exceptions import FirmwareGoingDormantError
from ..exceptions import IncorrectInstrumentConnectedError
Expand Down Expand Up @@ -729,7 +730,15 @@ async def _process_command_response(self, packet_type: int, response_data: bytes
f"Instrument running in {'offline' if self._system_in_offline_mode else 'online'} mode at time of connection"
)
case "end_offline_mode":
prev_command_info |= parse_end_offline_mode_bytes(response_data)
end_offline_mode_info = parse_end_offline_mode_bytes(response_data)
logger.info(f"Offline mode info: {end_offline_mode_info}")
prev_command_info |= end_offline_mode_info
# update which protocols are running since they may have stopped while in offline mode
self._protocols_running = {
protocol_idx
for protocol_idx, state in enumerate(prev_command_info["stimulation_protocol_statuses"])
if state == StimulationStates.RUNNING
}
# need to get sub wells before sending response
send_response = False
await self._send_data_packet(SerialCommPacketTypes.GET_SUB_WELLS)
Expand Down
28 changes: 20 additions & 8 deletions virtual-instrument/src/virtual_instrument/virtual_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@
from .exceptions import UnrecognizedSerialCommPacketTypeError
from .stimulation import StimulationProtocolManager

logging.basicConfig(format="%(asctime)s.%(msecs)03d -- %(message)s", datefmt="%H:%M:%S", level=logging.INFO)


logger = logging.getLogger(__name__)


MAGIC_WORD_LEN = len(SERIAL_COMM_MAGIC_WORD_BYTES)
AVERAGE_MC_REBOOT_DURATION_SECONDS = MAX_MC_REBOOT_DURATION_SECONDS / 2
Expand Down Expand Up @@ -348,7 +353,7 @@ def _get_timestamp(self) -> int:
return self._get_absolute_timer()

def _send_data_packet(
self, packet_type: int, data_to_send: bytes = bytes(0), truncate: bool = False
self, packet_type: SerialCommPacketTypes, data_to_send: bytes = bytes(0), truncate: bool = False
) -> None:
timestamp = self._get_timestamp()
data_packet = create_data_packet(timestamp, packet_type, data_to_send)
Expand All @@ -357,7 +362,7 @@ def _send_data_packet(
0, len(data_packet) - 1
)
data_packet = data_packet[trunc_index:]
print("SEND:", packet_type) # allow-print
logger.info(f"SEND: {packet_type}")

if self.conn:
self.conn.sendall(data_packet)
Expand Down Expand Up @@ -406,7 +411,7 @@ def _check_socket(self):
except BlockingIOError:
return

print(f"CONNECTION MADE: {addr}") # allow-print
logger.info(f"CONNECTION MADE: {addr}")
self.conn.setblocking(False)

def _handle_comm_from_controller(self) -> None:
Expand All @@ -421,6 +426,8 @@ def _handle_comm_from_controller(self) -> None:
if self._connection_status != InstrumentConnectionStatuses.OFFLINE:
raise

logger.info("DISCONNECT")

self.conn.close()
self.conn = None
return
Expand Down Expand Up @@ -472,7 +479,7 @@ def _process_main_module_command(self, comm_from_controller: bytes) -> None:
response_body = bytes(0)

packet_type = comm_from_controller[SERIAL_COMM_PACKET_TYPE_INDEX]
print("RECV:", packet_type) # allow-print
logger.info(f"RECV: {packet_type}")
if packet_type == SerialCommPacketTypes.REBOOT:
self._reboot_time_secs = perf_counter()
elif packet_type == SerialCommPacketTypes.HANDSHAKE:
Expand Down Expand Up @@ -718,6 +725,9 @@ def _update_sampling_period(self, comm_from_controller: bytes) -> bytes:
return update_status_byte

def _handle_status_beacon(self) -> None:
if self._connection_status == InstrumentConnectionStatuses.OFFLINE:
return

if self._time_of_last_status_beacon_secs is None:
self._send_status_beacon(truncate=self._time_of_last_handshake_secs is None)
return
Expand All @@ -730,7 +740,7 @@ def _send_status_beacon(self, truncate: bool = False) -> None:
self._send_data_packet(SerialCommPacketTypes.STATUS_BEACON, bytes(self._status_codes), truncate)

def _handle_barcode(self) -> None:
if self._ready_to_send_barcode:
if self._ready_to_send_barcode and self._connection_status != InstrumentConnectionStatuses.OFFLINE:
self._send_data_packet(
SerialCommPacketTypes.BARCODE_FOUND, bytes(self.default_plate_barcode, encoding="ascii")
)
Expand Down Expand Up @@ -766,6 +776,7 @@ def _handle_magnetometer_data_packet(self) -> None:
Since this process iterates once per 10 ms, it is possible that
more than one data packet must be sent.
"""

if self._timepoint_of_last_data_packet_us is None: # making mypy happy
raise NotImplementedError("_timepoint_of_last_data_packet_us should never be None here")
us_since_last_data_packet = _get_us_since_last_data_packet(self._timepoint_of_last_data_packet_us)
Expand All @@ -785,7 +796,8 @@ def _handle_magnetometer_data_packet(self) -> None:
# increment values
self._time_index_us += self._sampling_period_us
self._simulated_data_index = (self._simulated_data_index + 1) % simulated_data_len
# self._output_queue.put_nowait(data_packet_bytes)
# if self._connection_status != InstrumentConnectionStatuses.OFFLINE:
# self._output_queue.put_nowait(data_packet_bytes)
# update timepoint
self._timepoint_of_last_data_packet_us += num_packets_to_send * self._sampling_period_us

Expand Down Expand Up @@ -863,7 +875,7 @@ def _handle_stimulation_packets(self) -> None:
dur_since_subprotocol_start -= curr_subprotocol_duration_us
curr_subprotocol_duration_us = get_subprotocol_dur_us(curr_subprotocol)

if num_status_updates > 0:
if num_status_updates > 0 and self._connection_status != InstrumentConnectionStatuses.OFFLINE:
packet_bytes = bytes([num_status_updates]) + packet_bytes
self._send_data_packet(SerialCommPacketTypes.STIM_STATUS, packet_bytes)

Expand All @@ -878,7 +890,7 @@ def _handle_stimulation_packets(self) -> None:
self._is_stimulating = False

def _send_stim_sextant_status_update(self, sextant_num: int) -> None:
print("STIM SEXTANT:", sextant_num) # allow-print
logger.info(f"STIM SEXTANT: {sextant_num}")
self._send_data_packet(SerialCommPacketTypes.STIM_SEXTANT_STATUS, bytes([sextant_num]))

def _drain_all_queues(self) -> dict[str, Any]:
Expand Down
Loading