This PR adds a software SPI implementation. Firstly this removes the
absolute necessity for spidev (#140), which also means when it's not
present things still work (effectively fixes #185), and also enables any
four pins to be used for SPI devices (which don't require the hardware
implementation).

The software implementation is simplistic but still supports clock
polarity and phase, select-high, and variable bits per word. However it
doesn't allow precise speeds to be implemented because it just wibbles
the clock as fast as it can (which being pure Python isn't actually that
fast).

Finally, because this PR involves creating a framework for "shared"
devices (like SPI devices with multiple channels), it made sense to bung
Energenie (#69) in as wells as this is a really simple shared device.
This commit is contained in:
Dave Jones
2016-02-12 22:55:41 +00:00
parent e09e21a42e
commit 759a6a58e6
48 changed files with 1996 additions and 1076 deletions

View File

@@ -4,235 +4,185 @@
<!-- Generated by graphviz version 2.36.0 (20140111.2315)
-->
<!-- Title: classes Pages: 1 -->
<svg width="808pt" height="332pt"
viewBox="0.00 0.00 808.00 332.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 328)">
<svg width="603pt" height="476pt"
viewBox="0.00 0.00 603.00 476.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 472)">
<title>classes</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-328 804,-328 804,4 -4,4"/>
<!-- AnalogInputDevice -->
<g id="node1" class="node"><title>AnalogInputDevice</title>
<polygon fill="#2980b9" stroke="#2980b9" points="608,-252 502,-252 502,-216 608,-216 608,-252"/>
<text text-anchor="middle" x="555" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">AnalogInputDevice</text>
<polygon fill="white" stroke="none" points="-4,4 -4,-472 599,-472 599,4 -4,4"/>
<!-- Device -->
<g id="node1" class="node"><title>Device</title>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="485,-468 431,-468 431,-432 485,-432 485,-468"/>
<text text-anchor="middle" x="458" y="-447.5" font-family="Sans" font-size="10.00" fill="#000000">Device</text>
</g>
<!-- CompositeDevice -->
<g id="node2" class="node"><title>CompositeDevice</title>
<polygon fill="#2980b9" stroke="#2980b9" points="279.5,-324 178.5,-324 178.5,-288 279.5,-288 279.5,-324"/>
<text text-anchor="middle" x="229" y="-303.5" font-family="Sans" font-size="10.00" fill="#ffffff">CompositeDevice</text>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="508.5,-396 407.5,-396 407.5,-360 508.5,-360 508.5,-396"/>
<text text-anchor="middle" x="458" y="-375.5" font-family="Sans" font-size="10.00" fill="#000000">CompositeDevice</text>
</g>
<!-- AnalogInputDevice&#45;&gt;CompositeDevice -->
<g id="edge1" class="edge"><title>AnalogInputDevice&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M502.26,-246.325C443.965,-258.842 350.25,-278.965 289.144,-292.086"/>
<polygon fill="black" stroke="black" points="288.296,-288.688 279.253,-294.209 289.765,-295.532 288.296,-288.688"/>
<!-- CompositeDevice&#45;&gt;Device -->
<g id="edge1" class="edge"><title>CompositeDevice&#45;&gt;Device</title>
<path fill="none" stroke="black" d="M458,-396.303C458,-404.017 458,-413.288 458,-421.888"/>
<polygon fill="black" stroke="black" points="454.5,-421.896 458,-431.896 461.5,-421.896 454.5,-421.896"/>
</g>
<!-- MCP3xxx -->
<g id="node3" class="node"><title>MCP3xxx</title>
<polygon fill="#2980b9" stroke="#2980b9" points="638.5,-180 579.5,-180 579.5,-144 638.5,-144 638.5,-180"/>
<text text-anchor="middle" x="609" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">MCP3xxx</text>
<!-- CompositeOutputDevice -->
<g id="node3" class="node"><title>CompositeOutputDevice</title>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="375,-324 241,-324 241,-288 375,-288 375,-324"/>
<text text-anchor="middle" x="308" y="-303.5" font-family="Sans" font-size="10.00" fill="#000000">CompositeOutputDevice</text>
</g>
<!-- MCP3xxx&#45;&gt;AnalogInputDevice -->
<g id="edge2" class="edge"><title>MCP3xxx&#45;&gt;AnalogInputDevice</title>
<path fill="none" stroke="black" d="M595.652,-180.303C589.243,-188.611 581.442,-198.723 574.394,-207.859"/>
<polygon fill="black" stroke="black" points="571.532,-205.84 568.195,-215.896 577.074,-210.116 571.532,-205.84"/>
<!-- CompositeOutputDevice&#45;&gt;CompositeDevice -->
<g id="edge2" class="edge"><title>CompositeOutputDevice&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M344.694,-324.124C365.018,-333.608 390.471,-345.487 412.102,-355.581"/>
<polygon fill="black" stroke="black" points="410.883,-358.874 421.425,-359.932 413.843,-352.531 410.883,-358.874"/>
</g>
<!-- MCP33xx -->
<g id="node4" class="node"><title>MCP33xx</title>
<polygon fill="#2980b9" stroke="#2980b9" points="480,-108 420,-108 420,-72 480,-72 480,-108"/>
<text text-anchor="middle" x="450" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">MCP33xx</text>
<!-- LEDCollection -->
<g id="node4" class="node"><title>LEDCollection</title>
<polygon fill="#9ec6e0" stroke="#9ec6e0" points="237,-252 155,-252 155,-216 237,-216 237,-252"/>
<text text-anchor="middle" x="196" y="-231.5" font-family="Sans" font-size="10.00" fill="#000000">LEDCollection</text>
</g>
<!-- MCP33xx&#45;&gt;MCP3xxx -->
<g id="edge3" class="edge"><title>MCP33xx&#45;&gt;MCP3xxx</title>
<path fill="none" stroke="black" d="M479.534,-104.002C505.081,-115.249 542.204,-131.593 570.154,-143.898"/>
<polygon fill="black" stroke="black" points="569.062,-147.241 579.624,-148.067 571.882,-140.835 569.062,-147.241"/>
</g>
<!-- MCP3004 -->
<g id="node5" class="node"><title>MCP3004</title>
<polygon fill="#2980b9" stroke="#2980b9" points="560,-108 498,-108 498,-72 560,-72 560,-108"/>
<text text-anchor="middle" x="529" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">MCP3004</text>
</g>
<!-- MCP3004&#45;&gt;MCP3xxx -->
<g id="edge4" class="edge"><title>MCP3004&#45;&gt;MCP3xxx</title>
<path fill="none" stroke="black" d="M548.775,-108.303C558.754,-117.035 571.011,-127.76 581.857,-137.25"/>
<polygon fill="black" stroke="black" points="579.622,-139.945 589.452,-143.896 584.231,-134.677 579.622,-139.945"/>
</g>
<!-- MCP3008 -->
<g id="node6" class="node"><title>MCP3008</title>
<polygon fill="#2980b9" stroke="#2980b9" points="640,-108 578,-108 578,-72 640,-72 640,-108"/>
<text text-anchor="middle" x="609" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">MCP3008</text>
</g>
<!-- MCP3008&#45;&gt;MCP3xxx -->
<g id="edge5" class="edge"><title>MCP3008&#45;&gt;MCP3xxx</title>
<path fill="none" stroke="black" d="M609,-108.303C609,-116.017 609,-125.288 609,-133.888"/>
<polygon fill="black" stroke="black" points="605.5,-133.896 609,-143.896 612.5,-133.896 605.5,-133.896"/>
</g>
<!-- MCP3204 -->
<g id="node7" class="node"><title>MCP3204</title>
<polygon fill="#2980b9" stroke="#2980b9" points="720,-108 658,-108 658,-72 720,-72 720,-108"/>
<text text-anchor="middle" x="689" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">MCP3204</text>
</g>
<!-- MCP3204&#45;&gt;MCP3xxx -->
<g id="edge6" class="edge"><title>MCP3204&#45;&gt;MCP3xxx</title>
<path fill="none" stroke="black" d="M669.225,-108.303C659.246,-117.035 646.989,-127.76 636.143,-137.25"/>
<polygon fill="black" stroke="black" points="633.769,-134.677 628.548,-143.896 638.378,-139.945 633.769,-134.677"/>
</g>
<!-- MCP3208 -->
<g id="node8" class="node"><title>MCP3208</title>
<polygon fill="#2980b9" stroke="#2980b9" points="800,-108 738,-108 738,-72 800,-72 800,-108"/>
<text text-anchor="middle" x="769" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">MCP3208</text>
</g>
<!-- MCP3208&#45;&gt;MCP3xxx -->
<g id="edge7" class="edge"><title>MCP3208&#45;&gt;MCP3xxx</title>
<path fill="none" stroke="black" d="M738.15,-104.497C712.4,-115.762 675.557,-131.881 647.808,-144.022"/>
<polygon fill="black" stroke="black" points="646.163,-140.921 638.405,-148.135 648.969,-147.334 646.163,-140.921"/>
</g>
<!-- MCP3301 -->
<g id="node9" class="node"><title>MCP3301</title>
<polygon fill="#2980b9" stroke="#2980b9" points="401,-36 339,-36 339,-0 401,-0 401,-36"/>
<text text-anchor="middle" x="370" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">MCP3301</text>
</g>
<!-- MCP3301&#45;&gt;MCP33xx -->
<g id="edge8" class="edge"><title>MCP3301&#45;&gt;MCP33xx</title>
<path fill="none" stroke="black" d="M389.775,-36.3034C399.754,-45.0345 412.011,-55.7595 422.857,-65.2497"/>
<polygon fill="black" stroke="black" points="420.622,-67.9446 430.452,-71.8957 425.231,-62.6766 420.622,-67.9446"/>
</g>
<!-- MCP3302 -->
<g id="node10" class="node"><title>MCP3302</title>
<polygon fill="#2980b9" stroke="#2980b9" points="481,-36 419,-36 419,-0 481,-0 481,-36"/>
<text text-anchor="middle" x="450" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">MCP3302</text>
</g>
<!-- MCP3302&#45;&gt;MCP33xx -->
<g id="edge9" class="edge"><title>MCP3302&#45;&gt;MCP33xx</title>
<path fill="none" stroke="black" d="M450,-36.3034C450,-44.0173 450,-53.2875 450,-61.8876"/>
<polygon fill="black" stroke="black" points="446.5,-61.8956 450,-71.8957 453.5,-61.8957 446.5,-61.8956"/>
</g>
<!-- MCP3304 -->
<g id="node11" class="node"><title>MCP3304</title>
<polygon fill="#2980b9" stroke="#2980b9" points="561,-36 499,-36 499,-0 561,-0 561,-36"/>
<text text-anchor="middle" x="530" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">MCP3304</text>
</g>
<!-- MCP3304&#45;&gt;MCP33xx -->
<g id="edge10" class="edge"><title>MCP3304&#45;&gt;MCP33xx</title>
<path fill="none" stroke="black" d="M510.225,-36.3034C500.246,-45.0345 487.989,-55.7595 477.143,-65.2497"/>
<polygon fill="black" stroke="black" points="474.769,-62.6766 469.548,-71.8957 479.378,-67.9446 474.769,-62.6766"/>
</g>
<!-- RGBLED -->
<g id="node12" class="node"><title>RGBLED</title>
<polygon fill="#2980b9" stroke="#2980b9" points="56,-252 0,-252 0,-216 56,-216 56,-252"/>
<text text-anchor="middle" x="28" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">RGBLED</text>
</g>
<!-- RGBLED&#45;&gt;CompositeDevice -->
<g id="edge11" class="edge"><title>RGBLED&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M55.7289,-248.167C58.8345,-249.514 61.9702,-250.819 65,-252 98.836,-265.187 137.45,-277.783 168.706,-287.384"/>
<polygon fill="black" stroke="black" points="167.994,-290.826 178.58,-290.393 170.035,-284.13 167.994,-290.826"/>
</g>
<!-- Motor -->
<g id="node13" class="node"><title>Motor</title>
<polygon fill="#2980b9" stroke="#2980b9" points="128,-252 74,-252 74,-216 128,-216 128,-252"/>
<text text-anchor="middle" x="101" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">Motor</text>
</g>
<!-- Motor&#45;&gt;CompositeDevice -->
<g id="edge12" class="edge"><title>Motor&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M128.146,-249.845C145.837,-259.52 169.228,-272.312 189.029,-283.141"/>
<polygon fill="black" stroke="black" points="187.388,-286.233 197.841,-287.96 190.747,-280.091 187.388,-286.233"/>
<!-- LEDCollection&#45;&gt;CompositeOutputDevice -->
<g id="edge3" class="edge"><title>LEDCollection&#45;&gt;CompositeOutputDevice</title>
<path fill="none" stroke="black" d="M223.398,-252.124C237.907,-261.192 255.916,-272.448 271.585,-282.241"/>
<polygon fill="black" stroke="black" points="270.161,-285.478 280.496,-287.81 273.871,-279.542 270.161,-285.478"/>
</g>
<!-- LEDBoard -->
<g id="node14" class="node"><title>LEDBoard</title>
<polygon fill="#2980b9" stroke="#2980b9" points="210,-252 146,-252 146,-216 210,-216 210,-252"/>
<text text-anchor="middle" x="178" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">LEDBoard</text>
<g id="node5" class="node"><title>LEDBoard</title>
<polygon fill="#2980b9" stroke="#2980b9" points="140,-180 76,-180 76,-144 140,-144 140,-180"/>
<text text-anchor="middle" x="108" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">LEDBoard</text>
</g>
<!-- LEDBoard&#45;&gt;CompositeDevice -->
<g id="edge13" class="edge"><title>LEDBoard&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M190.607,-252.303C196.597,-260.526 203.876,-270.517 210.479,-279.579"/>
<polygon fill="black" stroke="black" points="207.821,-281.874 216.538,-287.896 213.478,-277.752 207.821,-281.874"/>
<!-- LEDBoard&#45;&gt;LEDCollection -->
<g id="edge4" class="edge"><title>LEDBoard&#45;&gt;LEDCollection</title>
<path fill="none" stroke="black" d="M129.753,-180.303C140.836,-189.119 154.474,-199.968 166.49,-209.526"/>
<polygon fill="black" stroke="black" points="164.493,-212.41 174.497,-215.896 168.85,-206.931 164.493,-212.41"/>
</g>
<!-- LEDBarGraph -->
<g id="node6" class="node"><title>LEDBarGraph</title>
<polygon fill="#2980b9" stroke="#2980b9" points="243.5,-180 162.5,-180 162.5,-144 243.5,-144 243.5,-180"/>
<text text-anchor="middle" x="203" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">LEDBarGraph</text>
</g>
<!-- LEDBarGraph&#45;&gt;LEDCollection -->
<g id="edge5" class="edge"><title>LEDBarGraph&#45;&gt;LEDCollection</title>
<path fill="none" stroke="black" d="M201.27,-180.303C200.498,-188.017 199.571,-197.288 198.711,-205.888"/>
<polygon fill="black" stroke="black" points="195.223,-205.597 197.71,-215.896 202.188,-206.294 195.223,-205.597"/>
</g>
<!-- PiLiter -->
<g id="node15" class="node"><title>PiLiter</title>
<polygon fill="#2980b9" stroke="#2980b9" points="99,-180 45,-180 45,-144 99,-144 99,-180"/>
<text text-anchor="middle" x="72" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">PiLiter</text>
<g id="node7" class="node"><title>PiLiter</title>
<polygon fill="#2980b9" stroke="#2980b9" points="54,-108 0,-108 0,-72 54,-72 54,-108"/>
<text text-anchor="middle" x="27" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">PiLiter</text>
</g>
<!-- PiLiter&#45;&gt;LEDBoard -->
<g id="edge14" class="edge"><title>PiLiter&#45;&gt;LEDBoard</title>
<path fill="none" stroke="black" d="M97.9305,-180.124C111.662,-189.192 128.706,-200.448 143.536,-210.241"/>
<polygon fill="black" stroke="black" points="141.696,-213.22 151.97,-215.81 145.554,-207.379 141.696,-213.22"/>
<g id="edge6" class="edge"><title>PiLiter&#45;&gt;LEDBoard</title>
<path fill="none" stroke="black" d="M47.0225,-108.303C57.1256,-117.035 69.536,-127.76 80.5175,-137.25"/>
<polygon fill="black" stroke="black" points="78.3532,-140.005 88.2078,-143.896 82.9302,-134.709 78.3532,-140.005"/>
</g>
<!-- PiLiterBarGraph -->
<g id="node8" class="node"><title>PiLiterBarGraph</title>
<polygon fill="#2980b9" stroke="#2980b9" points="254,-108 162,-108 162,-72 254,-72 254,-108"/>
<text text-anchor="middle" x="208" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">PiLiterBarGraph</text>
</g>
<!-- PiLiterBarGraph&#45;&gt;LEDBarGraph -->
<g id="edge7" class="edge"><title>PiLiterBarGraph&#45;&gt;LEDBarGraph</title>
<path fill="none" stroke="black" d="M206.764,-108.303C206.213,-116.017 205.551,-125.288 204.937,-133.888"/>
<polygon fill="black" stroke="black" points="201.443,-133.672 204.222,-143.896 208.425,-134.17 201.443,-133.672"/>
</g>
<!-- TrafficLights -->
<g id="node16" class="node"><title>TrafficLights</title>
<polygon fill="#2980b9" stroke="#2980b9" points="189,-180 117,-180 117,-144 189,-144 189,-180"/>
<text text-anchor="middle" x="153" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficLights</text>
<g id="node9" class="node"><title>TrafficLights</title>
<polygon fill="#2980b9" stroke="#2980b9" points="144,-108 72,-108 72,-72 144,-72 144,-108"/>
<text text-anchor="middle" x="108" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficLights</text>
</g>
<!-- TrafficLights&#45;&gt;LEDBoard -->
<g id="edge15" class="edge"><title>TrafficLights&#45;&gt;LEDBoard</title>
<path fill="none" stroke="black" d="M159.18,-180.303C161.995,-188.187 165.391,-197.696 168.519,-206.454"/>
<polygon fill="black" stroke="black" points="165.232,-207.655 171.891,-215.896 171.824,-205.301 165.232,-207.655"/>
<g id="edge8" class="edge"><title>TrafficLights&#45;&gt;LEDBoard</title>
<path fill="none" stroke="black" d="M108,-108.303C108,-116.017 108,-125.288 108,-133.888"/>
<polygon fill="black" stroke="black" points="104.5,-133.896 108,-143.896 111.5,-133.896 104.5,-133.896"/>
</g>
<!-- PiTraffic -->
<g id="node17" class="node"><title>PiTraffic</title>
<polygon fill="#2980b9" stroke="#2980b9" points="180,-108 126,-108 126,-72 180,-72 180,-108"/>
<text text-anchor="middle" x="153" y="-87.5" font-family="Sans" font-size="10.00" fill="#ffffff">PiTraffic</text>
<g id="node10" class="node"><title>PiTraffic</title>
<polygon fill="#2980b9" stroke="#2980b9" points="135,-36 81,-36 81,-0 135,-0 135,-36"/>
<text text-anchor="middle" x="108" y="-15.5" font-family="Sans" font-size="10.00" fill="#ffffff">PiTraffic</text>
</g>
<!-- PiTraffic&#45;&gt;TrafficLights -->
<g id="edge16" class="edge"><title>PiTraffic&#45;&gt;TrafficLights</title>
<path fill="none" stroke="black" d="M153,-108.303C153,-116.017 153,-125.288 153,-133.888"/>
<polygon fill="black" stroke="black" points="149.5,-133.896 153,-143.896 156.5,-133.896 149.5,-133.896"/>
<g id="edge9" class="edge"><title>PiTraffic&#45;&gt;TrafficLights</title>
<path fill="none" stroke="black" d="M108,-36.3034C108,-44.0173 108,-53.2875 108,-61.8876"/>
<polygon fill="black" stroke="black" points="104.5,-61.8956 108,-71.8957 111.5,-61.8957 104.5,-61.8956"/>
</g>
<!-- TrafficLightsBuzzer -->
<g id="node18" class="node"><title>TrafficLightsBuzzer</title>
<polygon fill="#2980b9" stroke="#2980b9" points="333.5,-252 228.5,-252 228.5,-216 333.5,-216 333.5,-252"/>
<text text-anchor="middle" x="281" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficLightsBuzzer</text>
<g id="node11" class="node"><title>TrafficLightsBuzzer</title>
<polygon fill="#2980b9" stroke="#2980b9" points="360.5,-252 255.5,-252 255.5,-216 360.5,-216 360.5,-252"/>
<text text-anchor="middle" x="308" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficLightsBuzzer</text>
</g>
<!-- TrafficLightsBuzzer&#45;&gt;CompositeDevice -->
<g id="edge17" class="edge"><title>TrafficLightsBuzzer&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M268.146,-252.303C261.975,-260.611 254.463,-270.723 247.676,-279.859"/>
<polygon fill="black" stroke="black" points="244.86,-277.781 241.706,-287.896 250.479,-281.955 244.86,-277.781"/>
<!-- TrafficLightsBuzzer&#45;&gt;CompositeOutputDevice -->
<g id="edge10" class="edge"><title>TrafficLightsBuzzer&#45;&gt;CompositeOutputDevice</title>
<path fill="none" stroke="black" d="M308,-252.303C308,-260.017 308,-269.288 308,-277.888"/>
<polygon fill="black" stroke="black" points="304.5,-277.896 308,-287.896 311.5,-277.896 304.5,-277.896"/>
</g>
<!-- FishDish -->
<g id="node19" class="node"><title>FishDish</title>
<polygon fill="#2980b9" stroke="#2980b9" points="263,-180 207,-180 207,-144 263,-144 263,-180"/>
<text text-anchor="middle" x="235" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">FishDish</text>
<g id="node12" class="node"><title>FishDish</title>
<polygon fill="#2980b9" stroke="#2980b9" points="324,-180 268,-180 268,-144 324,-144 324,-180"/>
<text text-anchor="middle" x="296" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">FishDish</text>
</g>
<!-- FishDish&#45;&gt;TrafficLightsBuzzer -->
<g id="edge18" class="edge"><title>FishDish&#45;&gt;TrafficLightsBuzzer</title>
<path fill="none" stroke="black" d="M246.371,-180.303C251.718,-188.441 258.204,-198.311 264.111,-207.299"/>
<polygon fill="black" stroke="black" points="261.343,-209.461 269.76,-215.896 267.193,-205.616 261.343,-209.461"/>
<g id="edge11" class="edge"><title>FishDish&#45;&gt;TrafficLightsBuzzer</title>
<path fill="none" stroke="black" d="M298.966,-180.303C300.289,-188.017 301.878,-197.288 303.352,-205.888"/>
<polygon fill="black" stroke="black" points="299.928,-206.631 305.068,-215.896 306.828,-205.448 299.928,-206.631"/>
</g>
<!-- TrafficHat -->
<g id="node20" class="node"><title>TrafficHat</title>
<polygon fill="#2980b9" stroke="#2980b9" points="342.5,-180 281.5,-180 281.5,-144 342.5,-144 342.5,-180"/>
<text text-anchor="middle" x="312" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficHat</text>
<g id="node13" class="node"><title>TrafficHat</title>
<polygon fill="#2980b9" stroke="#2980b9" points="403.5,-180 342.5,-180 342.5,-144 403.5,-144 403.5,-180"/>
<text text-anchor="middle" x="373" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">TrafficHat</text>
</g>
<!-- TrafficHat&#45;&gt;TrafficLightsBuzzer -->
<g id="edge19" class="edge"><title>TrafficHat&#45;&gt;TrafficLightsBuzzer</title>
<path fill="none" stroke="black" d="M304.337,-180.303C300.808,-188.272 296.544,-197.9 292.631,-206.736"/>
<polygon fill="black" stroke="black" points="289.424,-205.335 288.575,-215.896 295.824,-208.169 289.424,-205.335"/>
<g id="edge12" class="edge"><title>TrafficHat&#45;&gt;TrafficLightsBuzzer</title>
<path fill="none" stroke="black" d="M356.933,-180.303C349.061,-188.78 339.445,-199.136 330.827,-208.417"/>
<polygon fill="black" stroke="black" points="328.122,-206.186 323.883,-215.896 333.252,-210.949 328.122,-206.186"/>
</g>
<!-- Robot -->
<g id="node21" class="node"><title>Robot</title>
<polygon fill="#2980b9" stroke="#2980b9" points="431,-252 377,-252 377,-216 431,-216 431,-252"/>
<text text-anchor="middle" x="404" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">Robot</text>
<g id="node14" class="node"><title>Robot</title>
<polygon fill="#2980b9" stroke="#2980b9" points="449,-324 395,-324 395,-288 449,-288 449,-324"/>
<text text-anchor="middle" x="422" y="-303.5" font-family="Sans" font-size="10.00" fill="#ffffff">Robot</text>
</g>
<!-- Robot&#45;&gt;CompositeDevice -->
<g id="edge20" class="edge"><title>Robot&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M376.656,-245.938C351.218,-256.113 312.631,-271.547 281.284,-284.087"/>
<polygon fill="black" stroke="black" points="279.795,-280.912 271.81,-287.876 282.394,-287.412 279.795,-280.912"/>
<g id="edge13" class="edge"><title>Robot&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M430.899,-324.303C434.997,-332.272 439.949,-341.9 444.493,-350.736"/>
<polygon fill="black" stroke="black" points="441.517,-352.604 449.203,-359.896 447.742,-349.402 441.517,-352.604"/>
</g>
<!-- RyanteckRobot -->
<g id="node22" class="node"><title>RyanteckRobot</title>
<polygon fill="#2980b9" stroke="#2980b9" points="447,-180 361,-180 361,-144 447,-144 447,-180"/>
<text text-anchor="middle" x="404" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">RyanteckRobot</text>
<g id="node15" class="node"><title>RyanteckRobot</title>
<polygon fill="#2980b9" stroke="#2980b9" points="465,-252 379,-252 379,-216 465,-216 465,-252"/>
<text text-anchor="middle" x="422" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">RyanteckRobot</text>
</g>
<!-- RyanteckRobot&#45;&gt;Robot -->
<g id="edge21" class="edge"><title>RyanteckRobot&#45;&gt;Robot</title>
<path fill="none" stroke="black" d="M404,-180.303C404,-188.017 404,-197.288 404,-205.888"/>
<polygon fill="black" stroke="black" points="400.5,-205.896 404,-215.896 407.5,-205.896 400.5,-205.896"/>
<g id="edge14" class="edge"><title>RyanteckRobot&#45;&gt;Robot</title>
<path fill="none" stroke="black" d="M422,-252.303C422,-260.017 422,-269.288 422,-277.888"/>
<polygon fill="black" stroke="black" points="418.5,-277.896 422,-287.896 425.5,-277.896 418.5,-277.896"/>
</g>
<!-- CamJamKitRobot -->
<g id="node23" class="node"><title>CamJamKitRobot</title>
<polygon fill="#2980b9" stroke="#2980b9" points="561,-180 465,-180 465,-144 561,-144 561,-180"/>
<text text-anchor="middle" x="513" y="-159.5" font-family="Sans" font-size="10.00" fill="#ffffff">CamJamKitRobot</text>
<g id="node16" class="node"><title>CamJamKitRobot</title>
<polygon fill="#2980b9" stroke="#2980b9" points="579,-252 483,-252 483,-216 579,-216 579,-252"/>
<text text-anchor="middle" x="531" y="-231.5" font-family="Sans" font-size="10.00" fill="#ffffff">CamJamKitRobot</text>
</g>
<!-- CamJamKitRobot&#45;&gt;Robot -->
<g id="edge22" class="edge"><title>CamJamKitRobot&#45;&gt;Robot</title>
<path fill="none" stroke="black" d="M486.336,-180.124C472.216,-189.192 454.689,-200.448 439.439,-210.241"/>
<polygon fill="black" stroke="black" points="437.29,-207.462 430.767,-215.81 441.073,-213.352 437.29,-207.462"/>
<g id="edge15" class="edge"><title>CamJamKitRobot&#45;&gt;Robot</title>
<path fill="none" stroke="black" d="M504.336,-252.124C490.216,-261.192 472.689,-272.448 457.439,-282.241"/>
<polygon fill="black" stroke="black" points="455.29,-279.462 448.767,-287.81 459.073,-285.352 455.29,-279.462"/>
</g>
<!-- RGBLED -->
<g id="node17" class="node"><title>RGBLED</title>
<polygon fill="#2980b9" stroke="#2980b9" points="523,-324 467,-324 467,-288 523,-288 523,-324"/>
<text text-anchor="middle" x="495" y="-303.5" font-family="Sans" font-size="10.00" fill="#ffffff">RGBLED</text>
</g>
<!-- RGBLED&#45;&gt;CompositeDevice -->
<g id="edge16" class="edge"><title>RGBLED&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M485.854,-324.303C481.597,-332.356 476.444,-342.106 471.734,-351.018"/>
<polygon fill="black" stroke="black" points="468.62,-349.419 467.041,-359.896 474.808,-352.69 468.62,-349.419"/>
</g>
<!-- Motor -->
<g id="node18" class="node"><title>Motor</title>
<polygon fill="#2980b9" stroke="#2980b9" points="595,-324 541,-324 541,-288 595,-288 595,-324"/>
<text text-anchor="middle" x="568" y="-303.5" font-family="Sans" font-size="10.00" fill="#ffffff">Motor</text>
</g>
<!-- Motor&#45;&gt;CompositeDevice -->
<g id="edge17" class="edge"><title>Motor&#45;&gt;CompositeDevice</title>
<path fill="none" stroke="black" d="M541.091,-324.124C526.842,-333.192 509.154,-344.448 493.764,-354.241"/>
<polygon fill="black" stroke="black" points="491.57,-351.489 485.012,-359.81 495.328,-357.394 491.57,-351.489"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB