Bladeren bron

Add microwave example

Joeri Exelmans 4 jaren geleden
bovenliggende
commit
fb78e8913d

+ 159 - 0
examples/microwave/GUI.py

@@ -0,0 +1,159 @@
+from tkinter import Frame, PhotoImage, Canvas
+from tkinter.constants import BOTH
+
+CANVAS_W = 520
+CANVAS_H = 348
+
+TIME_X0 = 412
+TIME_Y0 = 90
+TIME_X1 = 472
+TIME_Y1 = 106
+
+BUTTON_HEIGHT = 18
+BUTTON_X0 = 412
+BUTTON_X1 = 472
+
+START_X0 = BUTTON_X0
+START_Y0 = 234
+START_X1 = BUTTON_X1
+START_Y1 = START_Y0 + BUTTON_HEIGHT
+
+STOP_X0 = BUTTON_X0
+STOP_Y0 = 211
+STOP_X1 = BUTTON_X1
+STOP_Y1 = STOP_Y0 + BUTTON_HEIGHT
+
+INCTIME_X0 = BUTTON_X0
+INCTIME_Y0 = 188
+INCTIME_X1 = BUTTON_X1
+INCTIME_Y1 = INCTIME_Y0 + BUTTON_HEIGHT
+
+DOOR_X0 = 26
+DOOR_Y0 = 68
+DOOR_X1 = 379
+DOOR_Y1 = 285
+
+FONT_TIME = ("terminal", 14)
+
+class GUI(Frame):
+
+    def __init__(self, parent, send_event):
+        Frame.__init__(self, parent)
+        self.send_event = send_event
+
+        self.imgClosedOff = PhotoImage(file="./small_closed_off.png")
+        self.imgClosedOn = PhotoImage(file="./small_closed_on.png")
+        self.imgOpened = PhotoImage(file="./small_opened.png")
+
+        # state
+        self.doorOpened = False
+        self.running = False
+        
+        self.lastPressed = ""
+                
+        self.pack()
+        self.canvas = Canvas(master=self,
+                             takefocus=1,
+                             width=CANVAS_W, height=CANVAS_H,
+                             background="black")
+    
+        self.canvas.pack(fill=BOTH, expand=1)
+        self.canvas.focus_set()
+
+        self.background = self.canvas.create_image(0, 0, image=self.imgClosedOff, anchor="nw")
+
+        self.rects = [
+            (START_X0, START_X1, START_Y0, START_Y1, "START"),
+            (STOP_X0, STOP_X1, STOP_Y0, STOP_Y1, "STOP"),
+            (INCTIME_X0, INCTIME_X1, INCTIME_Y0, INCTIME_Y1, "INCTIME"),
+            (DOOR_X0, DOOR_X1, DOOR_Y0, DOOR_Y1, "DOOR"),
+        ]
+                        
+        # self.buttonStart = self.canvas.create_rectangle(START_X0, START_Y0, START_X1, START_Y1)
+        # self.buttonStop = self.canvas.create_rectangle(STOP_X0, STOP_Y0, STOP_X1, STOP_Y1)
+        # self.buttonIncTime = self.canvas.create_rectangle(INCTIME_X0, INCTIME_Y0, INCTIME_X1, INCTIME_Y1)
+        # self.buttonDoor = self.canvas.create_rectangle(DOOR_X0, DOOR_Y0, DOOR_X1, DOOR_Y1, fill='')
+
+        self.timeTag = self.canvas.create_text(
+            TIME_X1-16, TIME_Y0+7,
+            font=FONT_TIME, justify="center", fill="#0f0", text="0")
+
+        # self.timeTag = None
+        # self.setTime(0)
+
+        self.canvas.bind("<ButtonPress-1>", self.mouse1Click)
+        self.canvas.bind("<ButtonRelease-1>", self.mouse1Release)
+        
+        # self.b_playpause.focus_force()
+        parent.protocol("WM_DELETE_WINDOW", self.window_close)
+
+    def mouse1Click(self, event):
+
+        def handle(what):
+            if what == "START":
+                self.send_event("start")
+                self.lastPressed = "start"
+            elif what == "STOP":
+                self.send_event("stop")
+                self.lastPressed = "stop"
+            elif what == "INCTIME":
+                self.send_event("increase_time")
+                self.lastPressed = "increase_time"
+            elif what == "DOOR":
+                self.doorOpened = not self.doorOpened
+                self.refresh_background()
+                if self.doorOpened:
+                    self.send_event("door_opened")
+                else:
+                    self.send_event("door_closed")
+                self.lastPressed = ""
+            else:
+                self.lastPressed = ""
+
+        X = self.canvas.canvasx(event.x)
+        Y = self.canvas.canvasy(event.y)
+
+        for X0, X1, Y0, Y1, what in self.rects:
+            if X >= X0 and X <= X1 and Y >= Y0 and Y <= Y1:
+                handle(what)
+                break
+    
+    def mouse1Release(self, event):
+        if self.lastPressed == "start":
+            # self.send_event("releasedStart")
+            pass
+        elif self.lastPressed == "stop":
+            # self.send_event("releasedStop")
+            pass
+        elif self.lastPressed == "increase_time":
+            # self.send_event("releasedIncTime")
+            pass
+        self.lastPressed = ""
+
+    def refresh_background(self):
+        if self.doorOpened:
+            self.canvas.itemconfig(self.background, image=self.imgOpened)
+        else:
+            if self.running:
+                self.canvas.itemconfig(self.background, image=self.imgClosedOn)
+            else:
+                self.canvas.itemconfig(self.background, image=self.imgClosedOff)
+        print("refreshed")
+
+    def handle_event(self, event):
+        if event.name == "micro_on":
+            self.running = True
+            self.refresh_background()
+        elif event.name == "micro_off":
+            self.running = False
+            self.refresh_background()
+        elif event.name == "set_time":
+            self.setTime(event.params[0])
+                             
+    def setTime(self, time: int):
+        self.canvas.itemconfig(self.timeTag, text=str(time))
+
+    def window_close(self):
+        import sys
+        sys.exit(0)
+        self.send_event('GUIQuit')

+ 78 - 0
examples/microwave/model_microwave.xml

@@ -0,0 +1,78 @@
+<single_instance_cd>
+  <delta>1 ms</delta>
+  <statechart>
+    <semantics
+      big_step_maximality="take_many"
+      combo_step_maximality="take_one"
+      input_event_lifeline="first_combo_step"
+      hierarchical_priority="source_parent"
+      orthogonal_priority="explicit"
+      same_source_priority="explicit"
+      />
+    <datamodel>
+      time = 0;
+      checkStartTime = func {
+        if (time == 0) time = 30;
+      };
+    </datamodel>
+    <inport name="in">
+      <event name="start"/>
+      <event name="stop"/>
+      <event name="door_opened"/>
+      <event name="door_closed"/>
+    </inport>
+    <outport name="out">
+      <event name="micro_on"/>
+      <event name="micro_off"/>
+      <event name="set_time"/>
+    </outport>
+    <root>
+      <parallel id="P">
+        <state id="Main" initial="DoorClosed">
+          <state id="DoorClosed" initial="NotRunning">
+            <transition port="in" event="door_opened" target="../DoorOpen"/>
+            <state id="Running">
+              <onentry> <raise port="out" event="micro_on"/> </onentry>
+              <onexit> <raise port="out" event="micro_off"/> </onexit>
+              <transition port="in" event="stop" target="../NotRunning"/>
+              <transition after="1 s" target=".">
+                <code> time -= 1; </code>
+                <raise port="out" event="set_time">
+                  <param expr="time"/>
+                </raise>
+              </transition>
+              <transition cond="time == 0" target="../NotRunning"/>
+            </state>
+            <state id="NotRunning">
+              <transition port="in" event="start" target="../Running">
+                <code> checkStartTime(); </code>
+                <raise port="out" event="set_time">
+                  <param expr="time"/>
+                </raise>
+              </transition>
+              <transition port="in" event="stop" target=".">
+                <code> time = 0; </code>
+                <raise port="out" event="set_time">
+                  <param expr="time"/>
+                </raise>
+              </transition>
+            </state>
+          </state>
+          <state id="DoorOpen">
+            <transition port="in" event="door_closed" target="../DoorClosed"/>
+          </state>
+        </state>
+        <state id="TimeIncrease">
+          <state id="Default">
+            <transition port="in" event="increase_time" target=".">
+              <code> time += 10; </code>
+                <raise port="out" event="set_time">
+                  <param expr="time"/>
+                </raise>
+            </transition>
+          </state>
+        </state>
+      </parallel>
+    </root>
+  </statechart>
+</single_instance_cd>

+ 162 - 0
examples/microwave/model_microwave_priorities.svg

@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.40.1 (20161225.0304)
+ -->
+<!-- Title: priorities Pages: 1 -->
+<svg width="1107pt" height="397pt"
+ viewBox="0.00 0.00 1107.07 397.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 393)">
+<title>priorities</title>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-393 1103.075,-393 1103.075,4 -4,4"/>
+<!-- 1. stop / Running&#45;&gt;NotRunning -->
+<g id="node1" class="node">
+<title>1. stop / Running&#45;&gt;NotRunning</title>
+<ellipse fill="none" stroke="#000000" cx="124.139" cy="-299" rx="124.2781" ry="18"/>
+<text text-anchor="middle" x="124.139" y="-295.3" font-family="Times,serif" font-size="14.00" fill="#000000">1. stop / Running&#45;&gt;NotRunning</text>
+</g>
+<!-- 2. after(1 s) / Running&#45;&gt;Running -->
+<g id="node2" class="node">
+<title>2. after(1 s) / Running&#45;&gt;Running</title>
+<ellipse fill="none" stroke="#000000" cx="158.139" cy="-227" rx="128.0773" ry="18"/>
+<text text-anchor="middle" x="158.139" y="-223.3" font-family="Times,serif" font-size="14.00" fill="#000000">2. after(1 s) / Running&#45;&gt;Running</text>
+</g>
+<!-- 1. stop / Running&#45;&gt;NotRunning&#45;&gt;2. after(1 s) / Running&#45;&gt;Running -->
+<g id="edge1" class="edge">
+<title>1. stop / Running&#45;&gt;NotRunning&#45;&gt;2. after(1 s) / Running&#45;&gt;Running</title>
+<path fill="none" stroke="#00ff00" d="M132.7186,-280.8314C136.4748,-272.8771 140.9647,-263.369 145.1187,-254.5723"/>
+<polygon fill="#00ff00" stroke="#00ff00" points="148.3386,-255.9503 149.4438,-245.4133 142.0088,-252.9612 148.3386,-255.9503"/>
+</g>
+<!-- pseudo0 -->
+<g id="node7" class="node">
+<title>pseudo0</title>
+<ellipse fill="#c0c0c0" stroke="#000000" cx="425.139" cy="-86.5" rx="14.5" ry="14.5"/>
+</g>
+<!-- 1. stop / Running&#45;&gt;NotRunning&#45;&gt;pseudo0 -->
+<g id="edge10" class="edge">
+<title>1. stop / Running&#45;&gt;NotRunning&#45;&gt;pseudo0</title>
+<path fill="none" stroke="#0000ff" d="M68.4633,-282.8959C50.1322,-274.6546 31.7449,-262.5354 21.139,-245 -6.7381,-198.9088 29.6927,-164.2813 76.139,-137 131.5083,-104.4776 330.4824,-91.3456 400.5297,-87.6637"/>
+<polygon fill="#0000ff" stroke="#0000ff" points="400.8131,-91.154 410.6232,-87.1524 400.4589,-84.1629 400.8131,-91.154"/>
+</g>
+<!-- 3. [time == 0] / Running&#45;&gt;NotRunning -->
+<g id="node3" class="node">
+<title>3. [time == 0] / Running&#45;&gt;NotRunning</title>
+<ellipse fill="none" stroke="#000000" cx="246.139" cy="-155" rx="151.3732" ry="18"/>
+<text text-anchor="middle" x="246.139" y="-151.3" font-family="Times,serif" font-size="14.00" fill="#000000">3. [time == 0] / Running&#45;&gt;NotRunning</text>
+</g>
+<!-- 2. after(1 s) / Running&#45;&gt;Running&#45;&gt;3. [time == 0] / Running&#45;&gt;NotRunning -->
+<g id="edge2" class="edge">
+<title>2. after(1 s) / Running&#45;&gt;Running&#45;&gt;3. [time == 0] / Running&#45;&gt;NotRunning</title>
+<path fill="none" stroke="#00ff00" d="M179.8918,-209.2022C190.8919,-200.2021 204.4096,-189.1423 216.3593,-179.3652"/>
+<polygon fill="#00ff00" stroke="#00ff00" points="218.8082,-181.8838 224.3314,-172.8425 214.3755,-176.4661 218.8082,-181.8838"/>
+</g>
+<!-- 2. after(1 s) / Running&#45;&gt;Running&#45;&gt;pseudo0 -->
+<g id="edge11" class="edge">
+<title>2. after(1 s) / Running&#45;&gt;Running&#45;&gt;pseudo0</title>
+<path fill="none" stroke="#0000ff" d="M122.4744,-209.5829C108.4617,-200.7252 93.8953,-188.5127 86.139,-173 78.9836,-158.6892 75.692,-149.1186 86.139,-137 106.6953,-113.1546 324.9486,-94.2218 399.977,-88.3758"/>
+<polygon fill="#0000ff" stroke="#0000ff" points="400.6502,-91.8346 410.3532,-87.5801 400.1149,-84.8551 400.6502,-91.8346"/>
+</g>
+<!-- 3. [time == 0] / Running&#45;&gt;NotRunning&#45;&gt;pseudo0 -->
+<g id="edge12" class="edge">
+<title>3. [time == 0] / Running&#45;&gt;NotRunning&#45;&gt;pseudo0</title>
+<path fill="none" stroke="#0000ff" d="M291.3082,-137.7146C326.3898,-124.2895 373.6285,-106.2121 401.584,-95.5141"/>
+<polygon fill="#0000ff" stroke="#0000ff" points="403.2,-98.6433 411.2885,-91.8003 400.6981,-92.1056 403.2,-98.6433"/>
+</g>
+<!-- 4. start / NotRunning&#45;&gt;Running -->
+<g id="node4" class="node">
+<title>4. start / NotRunning&#45;&gt;Running</title>
+<ellipse fill="none" stroke="#000000" cx="466.139" cy="-299" rx="124.2781" ry="18"/>
+<text text-anchor="middle" x="466.139" y="-295.3" font-family="Times,serif" font-size="14.00" fill="#000000">4. start / NotRunning&#45;&gt;Running</text>
+</g>
+<!-- 5. stop / NotRunning&#45;&gt;NotRunning -->
+<g id="node5" class="node">
+<title>5. stop / NotRunning&#45;&gt;NotRunning</title>
+<ellipse fill="none" stroke="#000000" cx="590.139" cy="-227" rx="137.2758" ry="18"/>
+<text text-anchor="middle" x="590.139" y="-223.3" font-family="Times,serif" font-size="14.00" fill="#000000">5. stop / NotRunning&#45;&gt;NotRunning</text>
+</g>
+<!-- 4. start / NotRunning&#45;&gt;Running&#45;&gt;5. stop / NotRunning&#45;&gt;NotRunning -->
+<g id="edge3" class="edge">
+<title>4. start / NotRunning&#45;&gt;Running&#45;&gt;5. stop / NotRunning&#45;&gt;NotRunning</title>
+<path fill="none" stroke="#00ff00" d="M496.4728,-281.3868C512.8359,-271.8857 533.2216,-260.0488 550.7928,-249.8462"/>
+<polygon fill="#00ff00" stroke="#00ff00" points="552.7982,-252.7291 559.6886,-244.6809 549.2832,-246.6755 552.7982,-252.7291"/>
+</g>
+<!-- 4. start / NotRunning&#45;&gt;Running&#45;&gt;pseudo0 -->
+<g id="edge13" class="edge">
+<title>4. start / NotRunning&#45;&gt;Running&#45;&gt;pseudo0</title>
+<path fill="none" stroke="#0000ff" d="M457.352,-280.9206C452.7122,-270.6232 447.3328,-257.3489 444.139,-245 432.1582,-198.6769 427.6956,-142.7471 426.0597,-111.2359"/>
+<polygon fill="#0000ff" stroke="#0000ff" points="429.5522,-110.9907 425.5913,-101.1642 422.5597,-111.316 429.5522,-110.9907"/>
+</g>
+<!-- 5. stop / NotRunning&#45;&gt;NotRunning&#45;&gt;pseudo0 -->
+<g id="edge14" class="edge">
+<title>5. stop / NotRunning&#45;&gt;NotRunning&#45;&gt;pseudo0</title>
+<path fill="none" stroke="#0000ff" d="M569.2416,-209.2056C536.9015,-181.6675 475.2194,-129.1442 444.0986,-102.6444"/>
+<polygon fill="#0000ff" stroke="#0000ff" points="446.0639,-99.7209 436.1811,-95.9025 441.5257,-105.0505 446.0639,-99.7209"/>
+</g>
+<!-- 0. door_opened / DoorClosed&#45;&gt;DoorOpen -->
+<g id="node6" class="node">
+<title>0. door_opened / DoorClosed&#45;&gt;DoorOpen</title>
+<ellipse fill="none" stroke="#000000" cx="390.139" cy="-371" rx="161.3716" ry="18"/>
+<text text-anchor="middle" x="390.139" y="-367.3" font-family="Times,serif" font-size="14.00" fill="#000000">0. door_opened / DoorClosed&#45;&gt;DoorOpen</text>
+</g>
+<!-- 0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;1. stop / Running&#45;&gt;NotRunning -->
+<g id="edge4" class="edge">
+<title>0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;1. stop / Running&#45;&gt;NotRunning</title>
+<path fill="none" stroke="#ff0000" d="M328.4446,-354.3008C287.8086,-343.3015 234.5639,-328.8895 192.6187,-317.5359"/>
+<polygon fill="#ff0000" stroke="#ff0000" points="193.3279,-314.1019 182.7607,-314.8675 191.4989,-320.8588 193.3279,-314.1019"/>
+</g>
+<!-- 0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;2. after(1 s) / Running&#45;&gt;Running -->
+<g id="edge5" class="edge">
+<title>0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;2. after(1 s) / Running&#45;&gt;Running</title>
+<path fill="none" stroke="#ff0000" d="M357.7113,-353.1874C340.2362,-343.1839 318.5453,-330.1049 300.139,-317 279.8349,-302.5439 277.7356,-295.0361 257.139,-281 240.2122,-269.4648 220.5852,-258.3388 203.2924,-249.2141"/>
+<polygon fill="#ff0000" stroke="#ff0000" points="204.4445,-245.8683 193.9574,-244.3609 201.2155,-252.0791 204.4445,-245.8683"/>
+</g>
+<!-- 0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;3. [time == 0] / Running&#45;&gt;NotRunning -->
+<g id="edge6" class="edge">
+<title>0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;3. [time == 0] / Running&#45;&gt;NotRunning</title>
+<path fill="none" stroke="#ff0000" d="M366.5069,-353.0919C355.1208,-343.447 342.04,-330.7241 333.139,-317 305.4504,-274.3084 321.1961,-252.7065 295.139,-209 289.0838,-198.8434 280.924,-188.9095 273.0015,-180.3879"/>
+<polygon fill="#ff0000" stroke="#ff0000" points="275.3242,-177.7547 265.8597,-172.9931 270.2891,-182.6176 275.3242,-177.7547"/>
+</g>
+<!-- 0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;4. start / NotRunning&#45;&gt;Running -->
+<g id="edge7" class="edge">
+<title>0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;4. start / NotRunning&#45;&gt;Running</title>
+<path fill="none" stroke="#ff0000" d="M409.317,-352.8314C418.5679,-344.0673 429.8098,-333.4171 439.8448,-323.9103"/>
+<polygon fill="#ff0000" stroke="#ff0000" points="442.3779,-326.3317 447.2304,-316.9134 437.5637,-321.25 442.3779,-326.3317"/>
+</g>
+<!-- 0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;5. stop / NotRunning&#45;&gt;NotRunning -->
+<g id="edge8" class="edge">
+<title>0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;5. stop / NotRunning&#45;&gt;NotRunning</title>
+<path fill="none" stroke="#ff0000" d="M490.7619,-356.9051C537.2159,-348.1315 585.17,-335.0369 599.139,-317 612.6488,-299.5559 608.6175,-274.1484 602.2304,-254.774"/>
+<polygon fill="#ff0000" stroke="#ff0000" points="605.4758,-253.4576 598.7561,-245.2665 598.9011,-255.8603 605.4758,-253.4576"/>
+</g>
+<!-- 0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;pseudo0 -->
+<g id="edge9" class="edge">
+<title>0. door_opened / DoorClosed&#45;&gt;DoorOpen&#45;&gt;pseudo0</title>
+<path fill="none" stroke="#0000ff" d="M481.7967,-356.1512C524.2524,-347.5539 574.7813,-334.833 618.139,-317 674.9571,-293.6307 706.0686,-298.5742 736.139,-245 800.2935,-130.7008 534.0441,-96.399 449.8988,-88.5075"/>
+<polygon fill="#0000ff" stroke="#0000ff" points="449.9839,-85.0013 439.7125,-87.5994 449.3622,-91.9737 449.9839,-85.0013"/>
+</g>
+<!-- 7. increase_time / Default&#45;&gt;Default -->
+<g id="node9" class="node">
+<title>7. increase_time / Default&#45;&gt;Default</title>
+<ellipse fill="none" stroke="#000000" cx="425.139" cy="-18" rx="137.5759" ry="18"/>
+<text text-anchor="middle" x="425.139" y="-14.3" font-family="Times,serif" font-size="14.00" fill="#000000">7. increase_time / Default&#45;&gt;Default</text>
+</g>
+<!-- pseudo0&#45;&gt;7. increase_time / Default&#45;&gt;Default -->
+<g id="edge16" class="edge">
+<title>pseudo0&#45;&gt;7. increase_time / Default&#45;&gt;Default</title>
+<path fill="none" stroke="#0000ff" d="M425.139,-71.9729C425.139,-64.4645 425.139,-55.0377 425.139,-46.1722"/>
+<polygon fill="#0000ff" stroke="#0000ff" points="428.6391,-46.1713 425.139,-36.1713 421.6391,-46.1713 428.6391,-46.1713"/>
+</g>
+<!-- 6. door_closed / DoorOpen&#45;&gt;DoorClosed -->
+<g id="node8" class="node">
+<title>6. door_closed / DoorOpen&#45;&gt;DoorClosed</title>
+<ellipse fill="none" stroke="#000000" cx="941.139" cy="-155" rx="157.872" ry="18"/>
+<text text-anchor="middle" x="941.139" y="-151.3" font-family="Times,serif" font-size="14.00" fill="#000000">6. door_closed / DoorOpen&#45;&gt;DoorClosed</text>
+</g>
+<!-- 6. door_closed / DoorOpen&#45;&gt;DoorClosed&#45;&gt;pseudo0 -->
+<g id="edge15" class="edge">
+<title>6. door_closed / DoorOpen&#45;&gt;DoorClosed&#45;&gt;pseudo0</title>
+<path fill="none" stroke="#0000ff" d="M837.9589,-141.3026C715.3767,-125.0296 518.8014,-98.9339 449.9359,-89.7918"/>
+<polygon fill="#0000ff" stroke="#0000ff" points="450.0304,-86.2738 439.6568,-88.4273 449.1092,-93.2129 450.0304,-86.2738"/>
+</g>
+</g>
+</svg>

+ 29 - 0
examples/microwave/run.py

@@ -0,0 +1,29 @@
+from sccd.realtime.eventloop import *
+from sccd.realtime.tkinter import TkInterImplementation
+from sccd.cd.parser.xml import *
+import GUI
+import tkinter
+from tkinter.constants import NO
+
+if __name__ == '__main__':
+    cd = load_cd("model_microwave.xml")
+
+    def send_event(event: str):
+        eventloop.add_input_now(port="in", event_name=event)
+
+    tk = tkinter.Tk()
+    tk.withdraw()
+    topLevel = tkinter.Toplevel(tk)
+    topLevel.resizable(width=NO, height=NO)
+    topLevel.title("Microwave oven")
+    gui = GUI.GUI(topLevel, send_event)
+
+    def on_output(event):
+        if event.port == "out":
+            gui.handle_event(event)
+
+    controller = Controller(cd, output_callback=on_output)
+    eventloop = EventLoop(controller, TkInterImplementation(tk))
+
+    eventloop.start()
+    tk.mainloop()

BIN
examples/microwave/small_closed_off.png


BIN
examples/microwave/small_closed_on.png


BIN
examples/microwave/small_opened.png