SEm/escapeLab/safe
|
Opening the safe
The safe is opened by turning an encoder up to the first value, then back to the second, and so on, until the 4 values have been reached. Once the final position has been reached, the rotating lever allows to open the safe. Pressing on the encoder button allows to verify the sequence currently stored by the safe's controller.
This can be tested with the sequence [12, 4, 15, 8]
which doesn't open the safe but displays a smiley.
Verifying the codes
The numbers of the test sequence can be verified by their MD5 hash. To do so, create a text file containing the decimal value of the number to test (2 ASCII characters) followed by 0Ah. Test it on Linux:
cd /tmp echo 10 > test.txt md5sum test.txt
This should return:
31d30eea8d0968d6458e0ad0027c9f80 test.txt
The tasks have the following MD5:
5b6b41ed9b343fed9cd05a66d36650f0 7c5aba41f53293b712fd86d08ed5b36e 54a24082cfebcd031ae7d0275379511e ecf27a776cdfc771defab1c5d19de9ab
Testing the opening of the safe
The following code is programmed in the safe's microcontroller, except for the opening_sequence
.
It allows to find out how the unlocking system works.
# http://microbit-micropython.readthedocs.io/ from microbit import * # ----------------------------------------------------------------------------- # Constants # opening_sequence = [0, 0, 0, 0] test_sequence = [12, 4, 15, 8] positon_min = 0 positon_max = 99 safe_open_button = button_a encoder_button = button_b encoder_pin_high = pin8 encoder_pin_low = pin12 open_safe_pin = pin16 rotating_right = True rotating_left = not rotating_right count_to_display_units = 200 sequence_item_display_interval = 1000 test_sequence_found_image = Image.HAPPY safe_open_sequence_found_image = Image.FABULOUS open_safe_duration = 2000 # ----------------------------------------------------------------------------- # Functions # def get_encoder_value(): encoder_value = \ 2*encoder_pin_high.read_digital() + \ encoder_pin_low.read_digital() return(encoder_value) def update_position(position, encoder_previous_value, encoder_value): encoder_up = [1, 3, 0, 2] if encoder_value == encoder_up[encoder_previous_value]: position = position + 1 else: position = position - 1 if position < positon_min: position = positon_max if position > positon_max: position = positon_min return(position) def display_binary(position): no_intensity = '0' max_intensity = '9' bits_per_line = 4 # prepare bits 3:0 hex_line_0 = "" for index in range(bits_per_line): if position % 2 > 0: hex_line_0 = max_intensity + hex_line_0 else: hex_line_0 = no_intensity + hex_line_0 position = int(position/2) hex_line_0 = '0' + hex_line_0 # prepare bits 7:4 hex_line_1 = "" for index in range(bits_per_line): if position % 2 > 0: hex_line_1 = max_intensity + hex_line_1 else: hex_line_1 = no_intensity + hex_line_1 position = int(position/2) hex_line_1 = '0' + hex_line_1 # display image display.show(Image( "00000:" + hex_line_1 + ":00000:" + hex_line_0 + ":00000" )) def display_tens(position): if position > 9: display.show(str(int(position/10)), wait=False) else: display.show(str(position % 10), wait=False) def display_units(position): display.show(str(position % 10), wait=False) def display_sequence(sequence): for index in range(len(sequence)): if sequence[index] > 9: display.scroll(str(int(sequence[index]/10))) display_units(sequence[index]) sleep(sequence_item_display_interval) def add_to_history(value, history): new_history = history[1:] + [value] return(new_history) def open_safe(): open_safe_pin.write_digital(1) sleep(open_safe_duration) open_safe_pin.write_digital(0) # ----------------------------------------------------------------------------- # Main loop # encoder_value = get_encoder_value() previous_encoder_value = encoder_value encoder_position = 0 previous_encoder_position = encoder_position display_units(encoder_position) activity_counter = 0 history = [0, 0, 0, 0] rotating_direction = rotating_right previous_rotating_direction = rotating_direction while True: # read encoder encoder_value = get_encoder_value() # update position if previous_encoder_value != encoder_value: encoder_position = update_position( encoder_position, previous_encoder_value, encoder_value ) if encoder_position > previous_encoder_position: rotating_direction = rotating_right else: rotating_direction = rotating_left if rotating_direction != previous_rotating_direction: history = add_to_history(previous_encoder_position, history) display_binary(encoder_position) previous_encoder_value = encoder_value previous_encoder_position = encoder_position previous_rotating_direction = rotating_direction activity_counter = 0 # display history if encoder_button.is_pressed(): display_sequence(history) # check history and open safe if safe_open_button.is_pressed(): if add_to_history(encoder_position, history) == opening_sequence: display.show(safe_open_sequence_found_image) open_safe() elif add_to_history(encoder_position, history) == test_sequence: display.show(test_sequence_found_image) else: display_sequence(test_sequence)