示例#1
0
class BindTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/simple.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc)
        # Stabilization
        self.interpreter.execute_once()

    def test_bind(self):
        with open('tests/yaml/simple.yaml') as f:
            other_sc = io.import_from_yaml(f)
        other_interpreter = Interpreter(other_sc)

        self.interpreter.bind(other_interpreter)
        self.assertIn(other_interpreter.queue, self.interpreter._bound)

        self.interpreter.raise_event(InternalEvent('test'))
        self.assertTrue(self.interpreter._internal_events.pop(), Event('test'))
        self.assertTrue(other_interpreter._external_events.pop(),
                        Event('test'))

    def test_bind_callable(self):
        with open('tests/yaml/simple.yaml') as f:
            other_sc = io.import_from_yaml(f)
        other_interpreter = Interpreter(other_sc)

        self.interpreter.bind(other_interpreter.queue)
        self.assertIn(other_interpreter.queue, self.interpreter._bound)

        self.interpreter.raise_event(InternalEvent('test'))
        self.assertTrue(self.interpreter._internal_events.pop(), Event('test'))
        self.assertTrue(other_interpreter._external_events.pop(),
                        Event('test'))
示例#2
0
class RemoteElevatorTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator.yaml') as f:
            elevator = io.import_from_yaml(f)
        with open('docs/examples/elevator_buttons.yaml') as f:
            buttons = io.import_from_yaml(f)

        self.elevator = Interpreter(elevator)
        self.buttons = Interpreter(buttons)
        self.buttons.bind(self.elevator)

    def test_button(self):
        self.assertEqual(self.elevator.context['current'], 0)

        self.buttons.queue(Event('button_2_pushed'))
        self.buttons.execute()

        event = self.elevator._events.pop()
        self.assertEqual(event.name, 'floorSelected')
        self.assertEqual(event.data['floor'], 2)

        self.buttons.queue(Event('button_2_pushed'))
        self.buttons.execute()
        self.elevator.execute()

        self.assertEqual(self.elevator.context['current'], 2)

    def test_button_0_on_groundfloor(self):
        self.assertEqual(self.elevator.context['current'], 0)

        self.buttons.queue(Event('button_0_pushed'))
        self.buttons.execute()
        self.elevator.execute()

        self.assertEqual(self.elevator.context['current'], 0)
示例#3
0
class BindTests(unittest.TestCase):
    def setUp(self):
        with open('tests/yaml/simple.yaml') as f:
            sc = io.import_from_yaml(f)
        self.interpreter = Interpreter(sc)
        # Stabilization
        self.interpreter.execute_once()

    def test_bind(self):
        with open('tests/yaml/simple.yaml') as f:
            other_sc = io.import_from_yaml(f)
        other_interpreter = Interpreter(other_sc)

        self.interpreter.bind(other_interpreter)
        self.assertIn(other_interpreter.queue, self.interpreter._bound)

        self.interpreter.raise_event(InternalEvent('test'))
        self.assertTrue(self.interpreter._internal_events.pop(), Event('test'))
        self.assertTrue(other_interpreter._external_events.pop(), Event('test'))

    def test_bind_callable(self):
        with open('tests/yaml/simple.yaml') as f:
            other_sc = io.import_from_yaml(f)
        other_interpreter = Interpreter(other_sc)

        self.interpreter.bind(other_interpreter.queue)
        self.assertIn(other_interpreter.queue, self.interpreter._bound)

        self.interpreter.raise_event(InternalEvent('test'))
        self.assertTrue(self.interpreter._internal_events.pop(), Event('test'))
        self.assertTrue(other_interpreter._external_events.pop(), Event('test'))
示例#4
0
class RemoteElevatorTests(unittest.TestCase):
    def setUp(self):
        with open('docs/examples/elevator/elevator.yaml') as f:
            elevator = io.import_from_yaml(f)
        with open('docs/examples/elevator/elevator_buttons.yaml') as f:
            buttons = io.import_from_yaml(f)

        self.elevator = Interpreter(elevator)
        self.buttons = Interpreter(buttons)
        self.buttons.bind(self.elevator)

    def test_button(self):
        self.assertEqual(self.elevator.context['current'], 0)

        self.buttons.queue(Event('button_2_pushed'))
        self.buttons.execute()

        event = self.elevator._external_events.pop()
        self.assertEqual(event.name, 'floorSelected')
        self.assertEqual(event.data['floor'], 2)

        self.buttons.queue(Event('button_2_pushed'))
        self.buttons.execute()
        self.elevator.execute()

        self.assertEqual(self.elevator.context['current'], 2)

    def test_button_0_on_groundfloor(self):
        self.assertEqual(self.elevator.context['current'], 0)

        self.buttons.queue(Event('button_0_pushed'))
        self.buttons.execute()
        self.elevator.execute()

        self.assertEqual(self.elevator.context['current'], 0)
示例#5
0
class BindTests(unittest.TestCase):
    def setUp(self):
        sc = io.import_from_yaml(open('tests/yaml/simple.yaml'))
        self.interpreter = Interpreter(sc)

    def test_bind(self):
        other_sc = io.import_from_yaml(open('tests/yaml/simple.yaml'))
        other_interpreter = Interpreter(other_sc)

        self.interpreter.bind(other_interpreter)
        self.assertEqual(self.interpreter._bound, [other_interpreter.send])

        self.interpreter.send(Event('test'), internal=True)
        self.assertTrue(self.interpreter._events.pop(), Event('test'))
        self.assertTrue(other_interpreter._events.pop(), Event('test'))

    def test_bind_callable(self):
        other_sc = io.import_from_yaml(open('tests/yaml/simple.yaml'))
        other_interpreter = Interpreter(other_sc)

        self.interpreter.bind(other_interpreter.send)
        self.assertEqual(self.interpreter._bound, [other_interpreter.send])

        self.interpreter.send(Event('test'), internal=True)
        self.assertTrue(self.interpreter._events.pop(), Event('test'))
        self.assertTrue(other_interpreter._events.pop(), Event('test'))
示例#6
0
def remote_elevator(elevator):
    sc = import_from_yaml(
        filepath='docs/examples/elevator/elevator_buttons.yaml')
    remote = Interpreter(sc)
    remote.bind(elevator)
    return remote
示例#7
0
class StopwatchApplication(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        with open('stopwatch.yaml') as f:
            statechart = import_from_yaml(f)
        self.interpreter = Interpreter(statechart)
        self.interpreter.time = time.time()

        # Bind interpreter events to the GUI
        self.interpreter.bind(self.event_handler)

        # Run the interpreter
        self.run()

    def run(self):
        # This function does essentially the same job than ``sismic.interpreter.run_in_background``
        # but uses Tkinter's mainloop instead of a Thread, which is more adequate.

        # Update internal clock and execute interpreter
        self.interpreter.time = time.time()
        self.interpreter.execute()

        # Queue a call every 100ms on tk's mainloop
        self.after(100, self.run)

        # Update the widget that contains the list of active states.
        self.w_states['text'] = 'active states: ' + ', '.join(
            self.interpreter.configuration)

    def create_widgets(self):
        self.pack()

        # Add buttons
        self.w_btn_start = tk.Button(self, text='start', command=self._start)
        self.w_btn_stop = tk.Button(self, text='stop', command=self._stop)
        self.w_btn_split = tk.Button(self, text='split', command=self._split)
        self.w_btn_unsplit = tk.Button(self,
                                       text='unsplit',
                                       command=self._unsplit)
        self.w_btn_reset = tk.Button(self, text='reset', command=self._reset)
        self.w_btn_quit = tk.Button(self, text='quit', command=self._quit)

        # Initial button states
        self.w_btn_stop['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.DISABLED

        # Pack
        self.w_btn_start.pack(side=tk.LEFT, )
        self.w_btn_stop.pack(side=tk.LEFT, )
        self.w_btn_split.pack(side=tk.LEFT, )
        self.w_btn_unsplit.pack(side=tk.LEFT, )
        self.w_btn_reset.pack(side=tk.LEFT, )
        self.w_btn_quit.pack(side=tk.LEFT, )

        # Active states label
        self.w_states = tk.Label(root)
        self.w_states.pack(side=tk.BOTTOM, fill=tk.X)

        # Timer label
        self.w_timer = tk.Label(root, font=("Helvetica", 16), pady=5)
        self.w_timer.pack(side=tk.BOTTOM, fill=tk.X)

    def event_handler(self, event):
        # Update text widget when timer value is updated
        if event.name == 'refresh':
            self.w_timer['text'] = event.time

    def _start(self):
        self.interpreter.queue(Event('start'))
        self.w_btn_start['state'] = tk.DISABLED
        self.w_btn_stop['state'] = tk.NORMAL

    def _stop(self):
        self.interpreter.queue(Event('stop'))
        self.w_btn_start['state'] = tk.NORMAL
        self.w_btn_stop['state'] = tk.DISABLED

    def _reset(self):
        self.interpreter.queue(Event('reset'))

    def _split(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.NORMAL

    def _unsplit(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.NORMAL
        self.w_btn_unsplit['state'] = tk.DISABLED

    def _quit(self):
        self.master.destroy()
示例#8
0
文件: microwave.py 项目: AvdN/sismic
class MicrowaveApplication(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        with open('microwave.yaml') as f:
            statechart = import_from_yaml(f)
        self.interpreter = Interpreter(statechart)

        # Bind interpreter events to the GUI
        self.interpreter.bind(self.event_handler)

        self.execute()

    def execute(self):
        self.interpreter.execute()

        # Update the widget that contains the list of active states.
        self.w_states['text'] = '\n'.join(self.interpreter.configuration)

        self.w_timer['text'] = 'M.timer: %d' % self.interpreter.context.get(
            'controller.timer', 'undefined')
        self.w_power['text'] = 'M.power: %d' % self.interpreter.context.get(
            'controller.power', 'undefined')

    def create_widgets(self):
        self.pack(fill=tk.BOTH)

        # MAIN frame containing all others
        left_frame = tk.Frame(self)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH)

        # INPUT frame
        input_frame = tk.LabelFrame(left_frame, text='INPUT BUTTONS')
        input_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        self.w_power_inc = tk.Button(input_frame,
                                     text='power +',
                                     command=partial(
                                         self.send_event,
                                         event_name='input_power_inc'))
        self.w_power_dec = tk.Button(input_frame,
                                     text='power -',
                                     command=partial(
                                         self.send_event,
                                         event_name='input_power_dec'))
        self.w_power_reset = tk.Button(input_frame,
                                       text='power reset',
                                       command=partial(
                                           self.send_event,
                                           event_name='input_power_reset'))

        self.w_power_inc.pack(side=tk.TOP, fill=tk.X)
        self.w_power_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_power_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_timer_inc = tk.Button(input_frame,
                                     text='timer +',
                                     command=partial(
                                         self.send_event,
                                         event_name='input_timer_inc'))
        self.w_timer_dec = tk.Button(input_frame,
                                     text='timer -',
                                     command=partial(
                                         self.send_event,
                                         event_name='input_timer_dec'))
        self.w_timer_reset = tk.Button(input_frame,
                                       text='timer 0',
                                       command=partial(
                                           self.send_event,
                                           event_name='input_timer_reset'))

        self.w_timer_inc.pack(side=tk.TOP, fill=tk.X,
                              pady=(8,
                                    0))  # leave some space before first button
        self.w_timer_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_timer_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_cooking_start = tk.Button(input_frame,
                                         text='start',
                                         command=partial(
                                             self.send_event,
                                             event_name='input_cooking_start'))
        self.w_cooking_stop = tk.Button(input_frame,
                                        text='stop',
                                        command=partial(
                                            self.send_event,
                                            event_name='input_cooking_stop'))

        self.w_cooking_start.pack(
            side=tk.TOP, fill=tk.X,
            pady=(8, 0))  # leave some space before first button
        self.w_cooking_stop.pack(side=tk.TOP, fill=tk.X)

        # SENSORS frame
        sensors_frame = tk.LabelFrame(left_frame, text='SENSORS')
        sensors_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # SENSORS > Clock frame
        clock_frame = tk.LabelFrame(sensors_frame, text='Clock')
        clock_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_clock = tk.Label(clock_frame)

        self.w_tick = tk.Button(clock_frame,
                                text='tick',
                                command=partial(self.send_event,
                                                event_name='timer_tick'))
        self.w_tick.pack(side=tk.TOP, fill=tk.X)

        # SENSORS > WeightSensor frame
        weight_frame = tk.LabelFrame(sensors_frame, text='WeightSensor')
        weight_frame.pack(side=tk.TOP, fill=tk.BOTH, pady=(8, 0))
        self.w_weight = tk.Label(weight_frame)

        self.w_item_placed = tk.Button(weight_frame,
                                       text='place item',
                                       command=partial(
                                           self.send_event,
                                           event_name='item_placed'))
        self.w_item_removed = tk.Button(weight_frame,
                                        text='remove item',
                                        command=partial(
                                            self.send_event,
                                            event_name='item_removed'))

        self.w_item_placed.pack(side=tk.TOP, fill=tk.X)
        self.w_item_removed.pack(side=tk.TOP, fill=tk.X)

        # SENSORS > Door frame
        door_frame = tk.LabelFrame(sensors_frame, text='Door')
        door_frame.pack(side=tk.TOP, fill=tk.BOTH, pady=(8, 0))
        self.w_door = tk.Label(door_frame)

        self.w_door_opened = tk.Button(door_frame,
                                       text='open door',
                                       command=partial(
                                           self.send_event,
                                           event_name='door_opened'))
        self.w_door_closed = tk.Button(door_frame,
                                       text='close door',
                                       command=partial(
                                           self.send_event,
                                           event_name='door_closed'))

        self.w_door_opened.pack(side=tk.TOP, fill=tk.X)
        self.w_door_closed.pack(side=tk.TOP, fill=tk.X)

        # ACTUATORS frame
        right_frame = tk.LabelFrame(self, text='ACTUATORS')
        right_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # Display component
        display_frame = tk.LabelFrame(right_frame, text='Display')
        display_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_display = tk.Label(display_frame)
        self.w_display.pack(side=tk.TOP)

        # Lamp component
        lamp_frame = tk.LabelFrame(right_frame, text='Lamp')
        lamp_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_lamp = tk.Label(lamp_frame)
        self.w_lamp.pack(side=tk.TOP)

        # Heating component
        heating_frame = tk.LabelFrame(right_frame, text='Heating')
        heating_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_heating_power = tk.Label(heating_frame)
        self.w_heating_status = tk.Label(heating_frame)
        self.w_heating_power.pack(side=tk.TOP)
        self.w_heating_status.pack(side=tk.TOP)

        # Beeper component
        beep_frame = tk.LabelFrame(right_frame, text='Beeper')
        beep_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_beep = tk.Label(beep_frame)
        self.w_beep.pack(side=tk.TOP)

        # Turntable component
        turntable_frame = tk.LabelFrame(right_frame, text='Turntable')
        turntable_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_turntable = tk.Label(turntable_frame)
        self.w_turntable.pack(side=tk.TOP)

        # Oven controller statechart component
        controller_frame = tk.LabelFrame(self, text='Oven Controller')
        controller_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))
        # Microwave Controller Statechart status
        # statechart_frame = tk.LabelFrame(right_frame2, text='Controller')
        # statechart_frame.pack(side=tk.TOP, fill=tk.BOTH)

        states_frame = tk.LabelFrame(controller_frame, text='States')
        states_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_states = tk.Label(states_frame)
        self.w_states.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))

        variables_frame = tk.LabelFrame(controller_frame, text='Variables')
        variables_frame.pack(side=tk.TOP, fill=tk.BOTH, pady=(8, 0))
        self.w_timer = tk.Label(variables_frame)
        self.w_timer.pack(side=tk.BOTTOM, fill=tk.X)

        self.w_power = tk.Label(variables_frame)
        self.w_power.pack(side=tk.BOTTOM, fill=tk.X)

    def event_handler(self, event):
        name = event.name

        if name == 'lamp_switch_on':
            self.w_lamp['text'] = 'on'
        elif name == 'lamp_switch_off':
            self.w_lamp['text'] = 'off'
        elif name == 'display_set':
            self.w_display['text'] = event.text
        elif name == 'display_clear':
            self.w_display['text'] = ''
        elif name == 'heating_set_power':
            self.w_heating_power['text'] = event.power
        elif name == 'heating_on':
            self.w_heating_status['text'] = 'on'
        elif name == 'heating_off':
            self.w_heating_status['text'] = 'off'
        elif name == 'beep':
            self.w_beep['text'] = event.number
        elif name == 'turntable_start':
            self.w_turntable['text'] = 'on'
        elif name == 'turntable_stop':
            self.w_turntable['text'] = 'off'
        else:
            raise ValueError('Unknown event %s' % event)

    def send_event(self, event_name):
        self.interpreter.queue(Event(event_name))
        self.execute()

    def _quit(self):
        self.master.destroy()
示例#9
0
class StopwatchApplication(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        with open('stopwatch.yaml') as f:
            statechart = import_from_yaml(f)
        self.interpreter = Interpreter(statechart, initial_time=time.time())

        # Bind interpreter events to the GUI
        self.interpreter.bind(self.event_handler)

        # Run the interpreter
        self.run()

    def run(self):
        # This function does essentially the same job than ``sismic.interpreter.run_in_background``
        # but uses Tkinter's mainloop instead of a Thread, which is more adequate.

        # Update internal clock and execute interpreter
        self.interpreter.time = time.time()
        self.interpreter.execute()

        # Queue a call every 100ms on tk's mainloop
        self.after(100, self.run)

        # Update the widget that contains the list of active states.
        self.w_states['text'] = 'active states: ' + ', '.join(self.interpreter.configuration)

    def create_widgets(self):
        self.pack()

        # Add buttons
        self.w_btn_start = tk.Button(self, text='start', command=self._start)
        self.w_btn_stop = tk.Button(self, text='stop', command=self._stop)
        self.w_btn_split = tk.Button(self, text='split', command=self._split)
        self.w_btn_unsplit = tk.Button(self, text='unsplit', command=self._unsplit)
        self.w_btn_reset = tk.Button(self, text='reset', command=self._reset)
        self.w_btn_quit = tk.Button(self, text='quit', command=self._quit)

        # Initial button states
        self.w_btn_stop['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.DISABLED

        # Pack
        self.w_btn_start.pack(side=tk.LEFT,)
        self.w_btn_stop.pack(side=tk.LEFT,)
        self.w_btn_split.pack(side=tk.LEFT,)
        self.w_btn_unsplit.pack(side=tk.LEFT,)
        self.w_btn_reset.pack(side=tk.LEFT,)
        self.w_btn_quit.pack(side=tk.LEFT,)

        # Active states label
        self.w_states = tk.Label(root)
        self.w_states.pack(side=tk.BOTTOM, fill=tk.X)

        # Timer label
        self.w_timer = tk.Label(root, font=("Helvetica", 16), pady=5)
        self.w_timer.pack(side=tk.BOTTOM, fill=tk.X)

    def event_handler(self, event):
        # Update text widget when timer value is updated
        if event.name == 'refresh':
            self.w_timer['text'] = event.time

    def _start(self):
        self.interpreter.queue(Event('start'))
        self.w_btn_start['state'] = tk.DISABLED
        self.w_btn_stop['state'] = tk.NORMAL

    def _stop(self):
        self.interpreter.queue(Event('stop'))
        self.w_btn_start['state'] = tk.NORMAL
        self.w_btn_stop['state'] = tk.DISABLED

    def _reset(self):
        self.interpreter.queue(Event('reset'))

    def _split(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.DISABLED
        self.w_btn_unsplit['state'] = tk.NORMAL

    def _unsplit(self):
        self.interpreter.queue(Event('split'))
        self.w_btn_split['state'] = tk.NORMAL
        self.w_btn_unsplit['state'] = tk.DISABLED

    def _quit(self):
        self.master.destroy()
示例#10
0
class MicrowaveApplication(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        with open('microwave.yaml') as f:
            statechart = import_from_yaml(f)
        self.interpreter = Interpreter(statechart)

        # Bind interpreter events to the GUI
        self.interpreter.bind(self.event_handler)

        self.execute()

    def execute(self):
        self.interpreter.execute()

        # Update the widget that contains the list of active states.
        self.w_states['text'] = '\n'.join(self.interpreter.configuration)

        self.w_timer['text'] = 'M.timer: %d' % self.interpreter.context.get('controller.timer', 'undefined')
        self.w_power['text'] = 'M.power: %d' % self.interpreter.context.get('controller.power', 'undefined')

    def create_widgets(self):
        self.pack(fill=tk.BOTH)

        # MAIN frame containing all others
        left_frame = tk.Frame(self)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH)

        # INPUT frame
        input_frame = tk.LabelFrame(left_frame, text='INPUT BUTTONS')
        input_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        self.w_power_inc = tk.Button(input_frame, text='power +',
                                     command=partial(self.send_event, event_name='input_power_inc'))
        self.w_power_dec = tk.Button(input_frame, text='power -',
                                     command=partial(self.send_event, event_name='input_power_dec'))
        self.w_power_reset = tk.Button(input_frame, text='power reset',
                                       command=partial(self.send_event, event_name='input_power_reset'))

        self.w_power_inc.pack(side=tk.TOP, fill=tk.X)
        self.w_power_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_power_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_timer_inc = tk.Button(input_frame, text='timer +',
                                     command=partial(self.send_event, event_name='input_timer_inc'))
        self.w_timer_dec = tk.Button(input_frame, text='timer -',
                                     command=partial(self.send_event, event_name='input_timer_dec'))
        self.w_timer_reset = tk.Button(input_frame, text='timer 0',
                                       command=partial(self.send_event, event_name='input_timer_reset'))

        self.w_timer_inc.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))  # leave some space before first button
        self.w_timer_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_timer_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_cooking_start = tk.Button(input_frame, text='start',
                                         command=partial(self.send_event, event_name='input_cooking_start'))
        self.w_cooking_stop = tk.Button(input_frame, text='stop',
                                        command=partial(self.send_event, event_name='input_cooking_stop'))

        self.w_cooking_start.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))  # leave some space before first button
        self.w_cooking_stop.pack(side=tk.TOP, fill=tk.X)

        # SENSORS frame
        sensors_frame = tk.LabelFrame(left_frame, text='SENSORS')
        sensors_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # SENSORS > Clock frame
        clock_frame = tk.LabelFrame(sensors_frame, text='Clock')
        clock_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_clock = tk.Label(clock_frame)

        self.w_tick = tk.Button(clock_frame, text='tick', command=partial(self.send_event, event_name='timer_tick'))
        self.w_tick.pack(side=tk.TOP, fill=tk.X)

        # SENSORS > WeightSensor frame
        weight_frame = tk.LabelFrame(sensors_frame, text='WeightSensor')
        weight_frame.pack(side=tk.TOP, fill=tk.BOTH, pady=(8, 0))
        self.w_weight = tk.Label(weight_frame)

        self.w_item_placed = tk.Button(weight_frame, text='place item',
                                       command=partial(self.send_event, event_name='item_placed'))
        self.w_item_removed = tk.Button(weight_frame, text='remove item',
                                        command=partial(self.send_event, event_name='item_removed'))

        self.w_item_placed.pack(side=tk.TOP, fill=tk.X)
        self.w_item_removed.pack(side=tk.TOP, fill=tk.X)

        # SENSORS > Door frame
        door_frame = tk.LabelFrame(sensors_frame, text='Door')
        door_frame.pack(side=tk.TOP, fill=tk.BOTH, pady=(8, 0))
        self.w_door = tk.Label(door_frame)

        self.w_door_opened = tk.Button(door_frame, text='open door',
                                       command=partial(self.send_event, event_name='door_opened'))
        self.w_door_closed = tk.Button(door_frame, text='close door',
                                       command=partial(self.send_event, event_name='door_closed'))

        self.w_door_opened.pack(side=tk.TOP, fill=tk.X)
        self.w_door_closed.pack(side=tk.TOP, fill=tk.X)

        # ACTUATORS frame
        right_frame = tk.LabelFrame(self, text='ACTUATORS')
        right_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # Display component
        display_frame = tk.LabelFrame(right_frame, text='Display')
        display_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_display = tk.Label(display_frame)
        self.w_display.pack(side=tk.TOP)

        # Lamp component
        lamp_frame = tk.LabelFrame(right_frame, text='Lamp')
        lamp_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_lamp = tk.Label(lamp_frame)
        self.w_lamp.pack(side=tk.TOP)

        # Heating component
        heating_frame = tk.LabelFrame(right_frame, text='Heating')
        heating_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_heating_power = tk.Label(heating_frame)
        self.w_heating_status = tk.Label(heating_frame)
        self.w_heating_power.pack(side=tk.TOP)
        self.w_heating_status.pack(side=tk.TOP)

        # Beeper component
        beep_frame = tk.LabelFrame(right_frame, text='Beeper')
        beep_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_beep = tk.Label(beep_frame)
        self.w_beep.pack(side=tk.TOP)

        # Turntable component
        turntable_frame = tk.LabelFrame(right_frame, text='Turntable')
        turntable_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_turntable = tk.Label(turntable_frame)
        self.w_turntable.pack(side=tk.TOP)

        # Oven controller statechart component
        controller_frame = tk.LabelFrame(self, text='Oven Controller')
        controller_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))
        # Microwave Controller Statechart status
        # statechart_frame = tk.LabelFrame(right_frame2, text='Controller')
        # statechart_frame.pack(side=tk.TOP, fill=tk.BOTH)

        states_frame = tk.LabelFrame(controller_frame, text='States')
        states_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_states = tk.Label(states_frame)
        self.w_states.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))

        variables_frame = tk.LabelFrame(controller_frame, text='Variables')
        variables_frame.pack(side=tk.TOP, fill=tk.BOTH, pady=(8, 0))
        self.w_timer = tk.Label(variables_frame)
        self.w_timer.pack(side=tk.BOTTOM, fill=tk.X)

        self.w_power = tk.Label(variables_frame)
        self.w_power.pack(side=tk.BOTTOM, fill=tk.X)

    def event_handler(self, event):
        name = event.name

        if name == 'lamp_switch_on':
            self.w_lamp['text'] = 'on'
        elif name == 'lamp_switch_off':
            self.w_lamp['text'] = 'off'
        elif name == 'display_set':
            self.w_display['text'] = event.text
        elif name == 'display_clear':
            self.w_display['text'] = ''
        elif name == 'heating_set_power':
            self.w_heating_power['text'] = event.power
        elif name == 'heating_on':
            self.w_heating_status['text'] = 'on'
        elif name == 'heating_off':
            self.w_heating_status['text'] = 'off'
        elif name == 'beep':
            self.w_beep['text'] = event.number
        elif name == 'turntable_start':
            self.w_turntable['text'] = 'on'
        elif name == 'turntable_stop':
            self.w_turntable['text'] = 'off'
        else:
            raise ValueError('Unknown event %s' % event)

    def send_event(self, event_name):
        self.interpreter.queue(Event(event_name))
        self.execute()

    def _quit(self):
        self.master.destroy()
示例#11
0
class MicrowaveApplication(tk.Frame):
    def __init__(self, master, statechart, contracts, properties):
        super().__init__(master)

        # Initialize widgets
        self.create_widgets()

        # Create a Stopwatch interpreter
        statechart = import_from_yaml(statechart)
        self.interpreter = Interpreter(statechart,
                                       ignore_contract=not contracts)

        # Bind interpreter events to the GUI
        self.interpreter.bind(self.event_handler)

        # Bind execution watchers
        self.watcher = ExecutionWatcher(self.interpreter)
        for prop in properties if properties else []:
            self.watcher.watch_with(import_from_yaml(prop), fails_fast=True)
        self.watcher.start()

        # Hide disabled widgets
        for widget_name in DISABLED_WIDGETS:
            widget = getattr(self, widget_name)
            widget.pack_forget()

        self.on_autotick()
        self.execute()

    def execute(self):
        try:
            print(self.interpreter.execute())
        except ContractError as e:
            messagebox.showerror(
                'Contract error!', e.__class__.__name__ + '\n\n' +
                'The following assertion does not hold in ' + str(e.obj) +
                ':\n' + e.condition + '\n\n' + 'Step: \n' + str(e.step))
            self.master.destroy()
            raise
        except AssertionError as e:
            messagebox.showerror('Unsatisfied property', e.args[0])
            self.master.destroy()
            raise
        except Exception as e:
            messagebox.showerror(
                'Fatal error',
                e.__class__.__name__ + ' was raised during the execution.\n' +
                'See console for the traceback.')
            self.master.destroy()
            raise

        # Update the widget that contains the list of active states.
        self.w_states['text'] = '\n'.join(self.interpreter.configuration)

        self.w_context['text'] = '\n'.join([
            '%s: %s' % (key, self.interpreter.context[key])
            for key in sorted(self.interpreter.context)
        ])

    def create_widgets(self):
        self.pack(fill=tk.BOTH)

        # Statechart status
        controller_frame = tk.LabelFrame(self, text='CONTROLLER')
        controller_frame.pack(side=tk.BOTTOM, fill=tk.X, padx=(8, 8))

        state_frame = tk.LabelFrame(controller_frame,
                                    text='Active configuration')
        state_frame.pack(side=tk.BOTTOM, fill=tk.X)

        self.w_states = tk.Label(state_frame)
        self.w_states.pack(side=tk.BOTTOM, fill=tk.X)

        context_frame = tk.LabelFrame(controller_frame, text='Context')
        context_frame.pack(side=tk.BOTTOM, fill=tk.X)

        self.w_context = tk.Label(context_frame)
        self.w_context.pack(side=tk.BOTTOM, fill=tk.X)

        #

        left_frame = tk.Frame(self)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH)

        # Input frame
        input_frame = tk.LabelFrame(left_frame, text='INPUT BUTTONS')
        input_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # Sensor frame
        sensors_frame = tk.LabelFrame(left_frame, text='ACTUATORS')
        sensors_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # Add buttons
        self.w_input_power_inc = tk.Button(input_frame,
                                           text='power +',
                                           command=partial(
                                               self.send_event,
                                               event_name='input_power_inc'))
        self.w_input_power_dec = tk.Button(input_frame,
                                           text='power -',
                                           command=partial(
                                               self.send_event,
                                               event_name='input_power_dec'))
        self.w_input_power_reset = tk.Button(
            input_frame,
            text='power 0',
            command=partial(self.send_event, event_name='input_power_reset'))

        self.w_input_timer_inc = tk.Button(input_frame,
                                           text='timer +',
                                           command=partial(
                                               self.send_event,
                                               event_name='input_timer_inc'))
        self.w_input_timer_dec = tk.Button(input_frame,
                                           text='timer -',
                                           command=partial(
                                               self.send_event,
                                               event_name='input_timer_dec'))
        self.w_input_timer_reset = tk.Button(
            input_frame,
            text='timer 0',
            command=partial(self.send_event, event_name='input_timer_reset'))

        self.w_input_cooking_start = tk.Button(
            input_frame,
            text='start',
            command=partial(self.send_event, event_name='input_cooking_start'))
        self.w_input_cooking_stop = tk.Button(
            input_frame,
            text='stop',
            command=partial(self.send_event, event_name='input_cooking_stop'))

        self.w_tick = tk.Button(sensors_frame,
                                text='tick',
                                command=partial(self.send_event,
                                                event_name='timer_tick'))
        self.v_autotick = tk.BooleanVar()
        self.v_autotick.set(True)
        self.w_autotick = tk.Checkbutton(sensors_frame,
                                         text='Auto-tick',
                                         var=self.v_autotick,
                                         command=self.on_autotick)

        self.w_item_placed = tk.Button(sensors_frame,
                                       text='place item',
                                       command=partial(
                                           self.send_event,
                                           event_name='item_placed'))
        self.w_item_removed = tk.Button(sensors_frame,
                                        text='remove item',
                                        command=partial(
                                            self.send_event,
                                            event_name='item_removed'))

        self.w_door_opened = tk.Button(sensors_frame,
                                       text='open door',
                                       command=partial(
                                           self.send_event,
                                           event_name='door_opened'))
        self.w_door_closed = tk.Button(sensors_frame,
                                       text='close door',
                                       command=partial(
                                           self.send_event,
                                           event_name='door_closed'))

        # Pack
        self.w_input_power_inc.pack(side=tk.TOP, fill=tk.X)
        self.w_input_power_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_input_power_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_input_timer_inc.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))
        self.w_input_timer_dec.pack(side=tk.TOP, fill=tk.X)
        self.w_input_timer_reset.pack(side=tk.TOP, fill=tk.X)

        self.w_input_cooking_start.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))
        self.w_input_cooking_stop.pack(side=tk.TOP, fill=tk.X)

        self.w_autotick.pack(side=tk.TOP, fill=tk.X)
        self.w_tick.pack(side=tk.TOP, fill=tk.X)

        self.w_item_placed.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))
        self.w_item_removed.pack(side=tk.TOP, fill=tk.X)

        self.w_door_opened.pack(side=tk.TOP, fill=tk.X, pady=(8, 0))
        self.w_door_closed.pack(side=tk.TOP, fill=tk.X)

        right_frame = tk.LabelFrame(self, text='COMPONENTS')
        right_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(8, 8))

        # Door component
        self.w_doorsensor_frame = tk.LabelFrame(right_frame, text='Door')
        self.w_doorsensor_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_doorsensor = tk.Label(self.w_doorsensor_frame)
        self.w_doorsensor.config(text='closed')
        self.w_doorsensor.pack(side=tk.TOP)

        # Weightsensor component
        self.w_weightsensor_frame = tk.LabelFrame(right_frame,
                                                  text='Weight sensor')
        self.w_weightsensor_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_weightsensor = tk.Label(self.w_weightsensor_frame)
        self.w_weightsensor.config(text='no item')
        self.w_weightsensor.pack(side=tk.TOP)

        # Display component
        self.w_display_frame = tk.LabelFrame(right_frame, text='Display')
        self.w_display_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_display = tk.Label(self.w_display_frame)
        self.w_display.pack(side=tk.TOP)

        # Lamp component
        self.w_lamp_frame = tk.LabelFrame(right_frame, text='Lamp')
        self.w_lamp_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_lamp = tk.Label(self.w_lamp_frame)
        self.w_lamp.pack(side=tk.TOP)

        # Heating component
        self.w_heating_frame = tk.LabelFrame(right_frame, text='Heating')
        self.w_heating_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_heating_power = tk.Label(self.w_heating_frame)
        self.w_heating_status = tk.Label(self.w_heating_frame)
        self.w_heating_power.pack(side=tk.TOP)
        self.w_heating_status.pack(side=tk.TOP)

        # Beeper component
        self.w_beep_frame = tk.LabelFrame(right_frame, text='Beeper')
        self.w_beep_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_beep = tk.Label(self.w_beep_frame)
        self.w_beep.pack(side=tk.TOP)

        # Turntable component
        self.w_turntable_frame = tk.LabelFrame(right_frame, text='Turntable')
        self.w_turntable_frame.pack(side=tk.TOP, fill=tk.BOTH)
        self.w_turntable = tk.Label(self.w_turntable_frame)
        self.w_turntable.pack(side=tk.TOP)

    def event_handler(self, event):
        name = event.name

        if name == 'lamp_switch_on':
            self.w_lamp['text'] = 'on'
        elif name == 'lamp_switch_off':
            self.w_lamp['text'] = 'off'
        elif name == 'display_set':
            self.w_display['text'] = event.text
        elif name == 'display_clear':
            self.w_display['text'] = ''
        elif name == 'heating_set_power':
            self.w_heating_power['text'] = event.power
        elif name == 'heating_on':
            self.w_heating_status['text'] = 'on'
        elif name == 'heating_off':
            self.w_heating_status['text'] = 'off'
        elif name == 'beep':
            self.w_beep['text'] = event.number
        elif name == 'turntable_start':
            self.w_turntable['text'] = 'on'
        elif name == 'turntable_stop':
            self.w_turntable['text'] = 'off'
        else:
            raise ValueError('Unknown event %s' % event)

    def on_autotick(self):
        if self.v_autotick.get():
            self.send_event('timer_tick')
            self.after(1000, self.on_autotick)

    def send_event(self, event_name):
        if event_name == 'item_placed':
            self.w_weightsensor.config(text='item detected')
        elif event_name == 'item_removed':
            self.w_weightsensor.config(text='no item')
        elif event_name == 'door_opened':
            self.w_doorsensor.config(text='open')
        elif event_name == 'door_closed':
            self.w_doorsensor.config(text='closed')

        self.interpreter.queue(Event(event_name))
        self.execute()

    def _quit(self):
        self.master.destroy()