rice: Add rice cooker dep graph.

This commit is contained in:
William Floyd 2018-06-22 20:53:28 -04:00
parent 5cd898dc34
commit 918f083f7f
Signed by untrusted user who does not match committer: william
GPG key ID: B3EEEDD81893CAF9
4 changed files with 551 additions and 22 deletions

View file

@ -2,6 +2,16 @@
title: "Smart Rice Cooker Conversion" title: "Smart Rice Cooker Conversion"
date: "2018-06-18" date: "2018-06-18"
author: "William Floyd" author: "William Floyd"
categories: [
"Development",
"Hardware",
"Software"
]
tags: [
"Arduino",
"Rice Cooker",
"Aliexpress"
]
--- ---
The "why" isn't important (read "doesn't exist"), but I want to take a regular old "dumb" rice cooker, and convert it into a "smart" rice cooker. The "why" isn't important (read "doesn't exist"), but I want to take a regular old "dumb" rice cooker, and convert it into a "smart" rice cooker.
@ -14,7 +24,7 @@ Main list of things:
- [Rice cooker](http://ali.onl/128Y) ($26.40 + $3.16 S&H - The star of the show.) - [Rice cooker](http://ali.onl/128Y) ($26.40 + $3.16 S&H - The star of the show.)
- [Thermistors](http://ali.onl/128Q) ($2.97 - 100pcs, for temperature readings) - [Thermistors](http://ali.onl/128Q) ($2.97 - 100pcs, for temperature readings)
- [NodeMCU](http://ali.onl/128R) ($2.47 - To, hopefully, allow me to Wifi control the whole thing) - [NodeMCU](http://ali.onl/128R) ($2.47 - To, hopefully, allow me to WiFi control the whole thing)
- [Relay](http://ali.onl/128V) ($0.76 - To switch power on and off.) - [Relay](http://ali.onl/128V) ($0.76 - To switch power on and off.)
- [ESP8266 Relay](http://ali.onl/128T) ($2.91 + $0.14 S&H - Alternative to the NodeMCU + Relay pairing I'm planning on using) - [ESP8266 Relay](http://ali.onl/128T) ($2.91 + $0.14 S&H - Alternative to the NodeMCU + Relay pairing I'm planning on using)
@ -24,29 +34,59 @@ Ideally, I will have the rice cooker serve an API, which my Orange Pi will bounc
For now though, I am away from home, working, so I can't do anything on this for at least another 2 weeks, probably 3. For now though, I am away from home, working, so I can't do anything on this for at least another 2 weeks, probably 3.
Many of my parts have arrived (rice cooker, thermistors, relay, and NodeMCU), so once I get home, I can hit the ground running. Many of my parts have arrived (rice cooker, thermistors, relay, and NodeMCU), so once I get home, I can hit the ground running.
# Thoughts
## Heating
The contents of the rice cooker should be considered when heating/cooling, as they will absorb the heat and thermal lag will be an issue.
If possible, look into either weighing the contents for a rough approximation (hard/complicated) or use recipe provided portion sizes to calculate the thermal capacity of the contents (water, mainly).
# API # API
I tentatively (with no real experience designing them) plan on my API being the following. I tentatively (with no real experience designing them) plan on my API being something like the following.
*Italicized* = Description *Italicized* = Description
**Bolded** = Final endpoints
- /sensor - /sensor/temperature - *Returns temperature*
- /temperature - /action/light/kill - *Stops all light activity*
- *Returns temperature* - /action/light/set - *Change lighting mode, with optional duration*
- /action - /action/temperature/kill - *Stops all heating/cooling, lets the cooker cool to room temperature alone*
- *Contains all physical heating/cooling/moving actions* - /action/temperature/set - *Heat/cool to given temperature, then hold. Should allow setting a target heat/cool rate. Should allow setting a hold duration*
- /temperature - /routine/cook/list - *List known cooking routines (proxy to `/settings/cook/recipe/list`)*
- *Contains all temperature related actions* - /routine/cook/start - *Start a routine*
- **/kill** - /routine/cook/kill - *Kill any current running routine*
- *Stops all cooking, lets the cooker cool to room temperature* - /routine/cook/schedule/list - *List any scheduled routines*
- **/change** - /routine/cook/schedule/set - *Submit/modify/delete a scheduled routine*
- *Heat/cool to given temperature, then hold* - /settings/lighting/list - *List lighting modes*
- *Should allow setting a target heat/cool rate* - /settings/lighting/set - *Submit/modify/delete a lighting mode*
- *Should allow setting a hold duration* - /settings/cook/warm/temperature - *Set post-cook warming temperature*
- /routine - /settings/cook/warm/set - *Turn post-cook warming on/off*
- /cook - /settings/cook/warm/duration - *Determine post-cook warming duration*
- **/list** - /settings/cook/recipe/list - *List known cooking routines*
- *List known cooking routines* - /settings/cook/recipe/set - *Submit/modify/delete a cooking routine*
- **/start**
- *Start a routine, optionally at a scheduled time* # Cooking schedule definition specifications
Directives are distinct actions to be taken.
They include:
### Sleep
Just wait for given duration, or until a given condition is met.
### Heat
Heat for a given duration, or until a given condition is met.
### Cool
If I someday choose to use a fan, this should be an active feature.
Instead, it's the same as `Sleep` for now.
### Temperature
Heat/cool to given temperature, optionally at a given rate of change (may be difficult for cooling if no fan is included).
This should just be a proxy directive to `Heat`, `Cool`, and `Sleep`.
For now that should work, but in due course, with tuning and benchmarks, this should run cooling at a variable rate.
Heating should be fine be fine with fairly large PWM, as the thermal lag I expect to be significant, and we want to try to hit our deadline as quickly as possible.
# Dep Graph
<img src="connections.svg">

10
src/build.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/bash
sed -e 's/\[depend_value\]/[color=blue]/' \
-e 's/\[proxy_value\]/\[color=deepskyblue\]/' \
-e 's/\[proxy_function\]/\[color=dodgerblue\]/' \
-e 's/\[documented\]/\[fillcolor=darkolivegreen1\]/' \
-e 's/\[done\]/\[fillcolor=chartreuse\]/' \
-e 's/\[depend_function\]/\[color=cornflowerblue\]/' connections.dot | fdp -Ln5 -Tsvg > '../static/connections.svg'
exit

173
src/connections.dot Normal file
View file

@ -0,0 +1,173 @@
digraph {
overlap=false
center=true
splines=true
sep="0.05"
node [style=filled, shape=record, color="black" fillcolor="tomato" ]
subgraph cluster_key {
node [fillcolor="none"]
subgraph cluster_doc {
"Done"[done]
"Documented"[documented]
"Undocumented"[fillcolor="tomato"]
}
subgraph cluster_sub {
"Depend on value"
"Proxy to value"
"Depend on function"
}
"Depend on value" -> "Node"[depend_value]
"Proxy to value" -> "Node"[proxy_value]
"Depend on function" -> "Node"[depend_function]
label="Key"
}
subgraph cluster_directives {
"Sleep"
"Heat"
"Cool"
"Temperature"
label="Directives"
}
subgraph cluster_api {
subgraph cluster_action {
subgraph cluster_light {
"/api/action/light/kill"[label="kill"]
"/api/action/light/set"[label="set"]
label="light"
}
subgraph cluster_temperature {
"/api/action/temperature/kill"[label="kill"]
"/api/action/temperature/set"[label="set"]
label="temperature"
}
label="action"
}
subgraph cluster_sensor {
"/api/sensor/temperature"[label="temperature"]
label="sensor"
}
subgraph cluster_routine {
subgraph cluster_routine_cook {
"/api/routine/cook/list"[label="list"]
"/api/routine/cook/start"[label="start"]
"/api/routine/cook/kill"[label="kill"]
subgraph cluster_schedule {
"/api/routine/cook/schedule/list"[label="list"]
"/api/routine/cook/schedule/set"[label="set"]
label="schedule"
}
label="cook"
}
label="routine"
}
subgraph cluster_settings {
subgraph cluster_lighting {
"/api/settings/lighting/list"[label="list"]
"/api/settings/lighting/set"[label="set"]
label="lighting"
}
subgraph cluster_settings_cook {
subgraph cluster_warm {
"/api/settings/cook/warm/temperature"[label="temperature"]
"/api/settings/cook/warm/set"[label="set"]
"/api/settings/cook/warm/duration"[label="duration"]
label="warm"
}
subgraph cluster_recipe {
"/api/settings/cook/recipe/list"[label="list"]
"/api/settings/cook/recipe/set"[label="set"]
label="recipe"
}
label="cook"
}
label="settings"
}
label="api"
}
"Temperature" -> { "Heat" "Cool" "Sleep" }[depend_function]
"/api/routine/cook/list" -> "/api/settings/cook/recipe/list"[proxy_value]
// Description checklist ///////////////////////////////////////////////////////
"/api/sensor/temperature"[documented]
"/api/action/light/kill"[documented]
"/api/action/light/set"[documented]
"/api/action/temperature/kill"[documented]
"/api/action/temperature/set"[documented]
"/api/routine/cook/list"[documented]
"/api/routine/cook/start"[documented]
"/api/routine/cook/kill"[documented]
"/api/routine/cook/schedule/list"[documented]
"/api/routine/cook/schedule/set"[documented]
"/api/settings/lighting/list"[documented]
"/api/settings/lighting/set"[documented]
"/api/settings/cook/warm/temperature"[documented]
"/api/settings/cook/warm/set"[documented]
"/api/settings/cook/warm/duration"[documented]
"/api/settings/cook/recipe/list"[documented]
"/api/settings/cook/recipe/set"[documented]
"Temperature"[documented]
"Heat"[documented]
"Cool"[documented]
"Sleep"[documented]
////////////////////////////////////////////////////////////////////////////////
}

306
static/connections.svg Normal file
View file

@ -0,0 +1,306 @@
<?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: %3 Pages: 1 -->
<svg width="1361pt" height="1103pt"
viewBox="0.00 0.00 1361.00 1103.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 1099)">
<title>%3</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-1099 1357,-1099 1357,4 -4,4"/>
<g id="clust1" class="cluster">
<title>cluster_key</title>
<polygon fill="none" stroke="#000000" points="895.7381,-840.1409 895.7381,-1095.1409 1352.7381,-1095.1409 1352.7381,-840.1409 895.7381,-840.1409"/>
<text text-anchor="middle" x="1124.2381" y="-1079.9409" font-family="Times,serif" font-size="14.00" fill="#000000">Key</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_doc</title>
<polygon fill="none" stroke="#000000" points="1123.4762,-947.7818 1123.4762,-1063.7818 1344.4762,-1063.7818 1344.4762,-947.7818 1123.4762,-947.7818"/>
</g>
<g id="clust3" class="cluster">
<title>cluster_sub</title>
<polygon fill="none" stroke="#000000" points="903.7866,-847.6918 903.7866,-993.6918 1080.7866,-993.6918 1080.7866,-847.6918 903.7866,-847.6918"/>
</g>
<g id="clust4" class="cluster">
<title>cluster_directives</title>
<polygon fill="none" stroke="#000000" points="616.2381,-839.6409 616.2381,-1023.6409 812.2381,-1023.6409 812.2381,-839.6409 616.2381,-839.6409"/>
<text text-anchor="middle" x="714.2381" y="-1008.4409" font-family="Times,serif" font-size="14.00" fill="#000000">Directives</text>
</g>
<g id="clust5" class="cluster">
<title>cluster_api</title>
<polygon fill="none" stroke="#000000" points=".2381,-.1409 .2381,-761.1409 840.2381,-761.1409 840.2381,-.1409 .2381,-.1409"/>
<text text-anchor="middle" x="420.2381" y="-745.9409" font-family="Times,serif" font-size="14.00" fill="#000000">api</text>
</g>
<g id="clust6" class="cluster">
<title>cluster_action</title>
<polygon fill="none" stroke="#000000" points="536.4762,-502.7818 536.4762,-682.7818 832.4762,-682.7818 832.4762,-502.7818 536.4762,-502.7818"/>
<text text-anchor="middle" x="684.4762" y="-667.5818" font-family="Times,serif" font-size="14.00" fill="#000000">action</text>
</g>
<g id="clust7" class="cluster">
<title>cluster_light</title>
<polygon fill="none" stroke="#000000" points="694.7144,-510.4227 694.7144,-636.4227 824.7144,-636.4227 824.7144,-510.4227 694.7144,-510.4227"/>
<text text-anchor="middle" x="759.7144" y="-621.2227" font-family="Times,serif" font-size="14.00" fill="#000000">light</text>
</g>
<g id="clust8" class="cluster">
<title>cluster_temperature</title>
<polygon fill="none" stroke="#000000" points="544.7144,-525.4227 544.7144,-651.4227 674.7144,-651.4227 674.7144,-525.4227 544.7144,-525.4227"/>
<text text-anchor="middle" x="609.7144" y="-636.2227" font-family="Times,serif" font-size="14.00" fill="#000000">temperature</text>
</g>
<g id="clust9" class="cluster">
<title>cluster_sensor</title>
<polygon fill="none" stroke="#000000" points="73.9762,-502.7818 73.9762,-578.7818 196.9762,-578.7818 196.9762,-502.7818 73.9762,-502.7818"/>
<text text-anchor="middle" x="135.4762" y="-563.5818" font-family="Times,serif" font-size="14.00" fill="#000000">sensor</text>
</g>
<g id="clust10" class="cluster">
<title>cluster_routine</title>
<polygon fill="none" stroke="#000000" points="239.4762,-503.2818 239.4762,-730.2818 469.4762,-730.2818 469.4762,-503.2818 239.4762,-503.2818"/>
<text text-anchor="middle" x="354.4762" y="-715.0818" font-family="Times,serif" font-size="14.00" fill="#000000">routine</text>
</g>
<g id="clust11" class="cluster">
<title>cluster_routine_cook</title>
<polygon fill="none" stroke="#000000" points="247.7144,-510.9227 247.7144,-698.9227 461.7144,-698.9227 461.7144,-510.9227 247.7144,-510.9227"/>
<text text-anchor="middle" x="354.7144" y="-683.7227" font-family="Times,serif" font-size="14.00" fill="#000000">cook</text>
</g>
<g id="clust12" class="cluster">
<title>cluster_schedule</title>
<polygon fill="none" stroke="#000000" points="255.9525,-526.5636 255.9525,-652.5636 385.9525,-652.5636 385.9525,-526.5636 255.9525,-526.5636"/>
<text text-anchor="middle" x="320.9525" y="-637.3636" font-family="Times,serif" font-size="14.00" fill="#000000">schedule</text>
</g>
<g id="clust13" class="cluster">
<title>cluster_settings</title>
<polygon fill="none" stroke="#000000" points="8.4762,-7.7818 8.4762,-443.7818 546.4762,-443.7818 546.4762,-7.7818 8.4762,-7.7818"/>
<text text-anchor="middle" x="277.4762" y="-428.5818" font-family="Times,serif" font-size="14.00" fill="#000000">settings</text>
</g>
<g id="clust14" class="cluster">
<title>cluster_lighting</title>
<polygon fill="none" stroke="#000000" points="408.7144,-15.4227 408.7144,-141.4227 538.7144,-141.4227 538.7144,-15.4227 408.7144,-15.4227"/>
<text text-anchor="middle" x="473.7144" y="-126.2227" font-family="Times,serif" font-size="14.00" fill="#000000">lighting</text>
</g>
<g id="clust15" class="cluster">
<title>cluster_settings_cook</title>
<polygon fill="none" stroke="#000000" points="16.7144,-71.9227 16.7144,-412.9227 354.7144,-412.9227 354.7144,-71.9227 16.7144,-71.9227"/>
<text text-anchor="middle" x="185.7144" y="-397.7227" font-family="Times,serif" font-size="14.00" fill="#000000">cook</text>
</g>
<g id="clust16" class="cluster">
<title>cluster_warm</title>
<polygon fill="none" stroke="#000000" points="24.4525,-79.5636 24.4525,-221.5636 201.4525,-221.5636 201.4525,-79.5636 24.4525,-79.5636"/>
<text text-anchor="middle" x="112.9525" y="-206.3636" font-family="Times,serif" font-size="14.00" fill="#000000">warm</text>
</g>
<g id="clust17" class="cluster">
<title>cluster_recipe</title>
<polygon fill="none" stroke="#000000" points="216.9525,-255.5636 216.9525,-381.5636 346.9525,-381.5636 346.9525,-255.5636 216.9525,-255.5636"/>
<text text-anchor="middle" x="281.9525" y="-366.3636" font-family="Times,serif" font-size="14.00" fill="#000000">recipe</text>
</g>
<!-- Done -->
<g id="node1" class="node">
<title>Done</title>
<polygon fill="#7fff00" stroke="#000000" points="1159.7144,-1019.4227 1159.7144,-1055.4227 1213.7144,-1055.4227 1213.7144,-1019.4227 1159.7144,-1019.4227"/>
<text text-anchor="middle" x="1186.7144" y="-1033.7227" font-family="Times,serif" font-size="14.00" fill="#000000">Done</text>
</g>
<!-- Documented -->
<g id="node2" class="node">
<title>Documented</title>
<polygon fill="#caff70" stroke="#000000" points="1229.2144,-1005.4227 1229.2144,-1041.4227 1336.2144,-1041.4227 1336.2144,-1005.4227 1229.2144,-1005.4227"/>
<text text-anchor="middle" x="1282.7144" y="-1019.7227" font-family="Times,serif" font-size="14.00" fill="#000000">Documented</text>
</g>
<!-- Undocumented -->
<g id="node3" class="node">
<title>Undocumented</title>
<polygon fill="#ff6347" stroke="#000000" points="1131.7144,-956.4227 1131.7144,-992.4227 1257.7144,-992.4227 1257.7144,-956.4227 1131.7144,-956.4227"/>
<text text-anchor="middle" x="1194.7144" y="-970.7227" font-family="Times,serif" font-size="14.00" fill="#000000">Undocumented</text>
</g>
<!-- Depend on value -->
<g id="node4" class="node">
<title>Depend on value</title>
<polygon fill="transparent" stroke="#000000" points="937.0548,-949.3938 937.0548,-985.3938 1073.0548,-985.3938 1073.0548,-949.3938 937.0548,-949.3938"/>
<text text-anchor="middle" x="1005.0548" y="-963.6938" font-family="Times,serif" font-size="14.00" fill="#000000">Depend on value</text>
</g>
<!-- Node -->
<g id="node7" class="node">
<title>Node</title>
<polygon fill="transparent" stroke="#000000" points="1088.799,-884.1636 1088.799,-920.1636 1143.799,-920.1636 1143.799,-884.1636 1088.799,-884.1636"/>
<text text-anchor="middle" x="1116.299" y="-898.4636" font-family="Times,serif" font-size="14.00" fill="#000000">Node</text>
</g>
<!-- Depend on value&#45;&gt;Node -->
<g id="edge1" class="edge">
<title>Depend on value&#45;&gt;Node</title>
<path fill="none" stroke="#0000ff" d="M1036.0425,-949.2236C1049.5434,-941.3071 1065.4707,-931.9678 1079.5628,-923.7046"/>
<polygon fill="#0000ff" stroke="#0000ff" points="1081.6584,-926.5332 1088.5144,-918.4557 1078.1176,-920.4947 1081.6584,-926.5332"/>
</g>
<!-- Proxy to value -->
<g id="node5" class="node">
<title>Proxy to value</title>
<polygon fill="transparent" stroke="#000000" points="922.7255,-904.3893 922.7255,-940.3893 1041.7255,-940.3893 1041.7255,-904.3893 922.7255,-904.3893"/>
<text text-anchor="middle" x="982.2255" y="-918.6893" font-family="Times,serif" font-size="14.00" fill="#000000">Proxy to value</text>
</g>
<!-- Proxy to value&#45;&gt;Node -->
<g id="edge2" class="edge">
<title>Proxy to value&#45;&gt;Node</title>
<path fill="none" stroke="#00bfff" d="M1041.8129,-913.4002C1054.3426,-911.5101 1067.2237,-909.5669 1078.6762,-907.8392"/>
<polygon fill="#00bfff" stroke="#00bfff" points="1079.3751,-911.2735 1088.7411,-906.3209 1078.3309,-904.3518 1079.3751,-911.2735"/>
</g>
<!-- Depend on function -->
<g id="node6" class="node">
<title>Depend on function</title>
<polygon fill="transparent" stroke="#000000" points="911.9052,-855.7921 911.9052,-891.7921 1068.9052,-891.7921 1068.9052,-855.7921 911.9052,-855.7921"/>
<text text-anchor="middle" x="990.4052" y="-870.0921" font-family="Times,serif" font-size="14.00" fill="#000000">Depend on function</text>
</g>
<!-- Depend on function&#45;&gt;Node -->
<g id="edge3" class="edge">
<title>Depend on function&#45;&gt;Node</title>
<path fill="none" stroke="#6495ed" d="M1069.0626,-891.5184C1072.4331,-892.278 1075.7394,-893.0231 1078.9394,-893.7442"/>
<polygon fill="#6495ed" stroke="#6495ed" points="1078.2216,-897.1702 1088.7465,-895.9544 1079.7606,-890.3414 1078.2216,-897.1702"/>
</g>
<!-- Sleep -->
<g id="node8" class="node">
<title>Sleep</title>
<polygon fill="#caff70" stroke="#000000" points="708.4762,-938.2818 708.4762,-974.2818 764.4762,-974.2818 764.4762,-938.2818 708.4762,-938.2818"/>
<text text-anchor="middle" x="736.4762" y="-952.5818" font-family="Times,serif" font-size="14.00" fill="#000000">Sleep</text>
</g>
<!-- Heat -->
<g id="node9" class="node">
<title>Heat</title>
<polygon fill="#caff70" stroke="#000000" points="750.4762,-848.2818 750.4762,-884.2818 804.4762,-884.2818 804.4762,-848.2818 750.4762,-848.2818"/>
<text text-anchor="middle" x="777.4762" y="-862.5818" font-family="Times,serif" font-size="14.00" fill="#000000">Heat</text>
</g>
<!-- Cool -->
<g id="node10" class="node">
<title>Cool</title>
<polygon fill="#caff70" stroke="#000000" points="642.4762,-956.2818 642.4762,-992.2818 696.4762,-992.2818 696.4762,-956.2818 642.4762,-956.2818"/>
<text text-anchor="middle" x="669.4762" y="-970.5818" font-family="Times,serif" font-size="14.00" fill="#000000">Cool</text>
</g>
<!-- Temperature -->
<g id="node11" class="node">
<title>Temperature</title>
<polygon fill="#caff70" stroke="#000000" points="624.4762,-890.2818 624.4762,-926.2818 734.4762,-926.2818 734.4762,-890.2818 624.4762,-890.2818"/>
<text text-anchor="middle" x="679.4762" y="-904.5818" font-family="Times,serif" font-size="14.00" fill="#000000">Temperature</text>
</g>
<!-- Temperature&#45;&gt;Sleep -->
<g id="edge4" class="edge">
<title>Temperature&#45;&gt;Sleep</title>
<path fill="none" stroke="#6495ed" d="M701.0255,-926.4285C703.0116,-928.1011 705.0458,-929.814 707.086,-931.5321"/>
<polygon fill="#6495ed" stroke="#6495ed" points="704.9929,-934.3452 714.8965,-938.1094 709.5019,-928.9908 704.9929,-934.3452"/>
</g>
<!-- Temperature&#45;&gt;Heat -->
<g id="edge5" class="edge">
<title>Temperature&#45;&gt;Heat</title>
<path fill="none" stroke="#6495ed" d="M721.6058,-890.2262C728.0062,-887.4832 734.5662,-884.6718 740.8371,-881.9843"/>
<polygon fill="#6495ed" stroke="#6495ed" points="742.5764,-885.0468 750.3892,-877.8905 739.819,-878.6128 742.5764,-885.0468"/>
</g>
<!-- Temperature&#45;&gt;Cool -->
<g id="edge6" class="edge">
<title>Temperature&#45;&gt;Cool</title>
<path fill="none" stroke="#6495ed" d="M676.7437,-926.3166C675.8177,-932.428 674.7601,-939.4083 673.7438,-946.1161"/>
<polygon fill="#6495ed" stroke="#6495ed" points="670.2431,-945.8573 672.2055,-956.2688 677.1641,-946.906 670.2431,-945.8573"/>
</g>
<!-- /api/action/light/kill -->
<g id="node12" class="node">
<title>/api/action/light/kill</title>
<polygon fill="#caff70" stroke="#000000" points="702.9525,-519.0636 702.9525,-555.0636 756.9525,-555.0636 756.9525,-519.0636 702.9525,-519.0636"/>
<text text-anchor="middle" x="729.9525" y="-533.3636" font-family="Times,serif" font-size="14.00" fill="#000000">kill</text>
</g>
<!-- /api/action/light/set -->
<g id="node13" class="node">
<title>/api/action/light/set</title>
<polygon fill="#caff70" stroke="#000000" points="762.9525,-569.0636 762.9525,-605.0636 816.9525,-605.0636 816.9525,-569.0636 762.9525,-569.0636"/>
<text text-anchor="middle" x="789.9525" y="-583.3636" font-family="Times,serif" font-size="14.00" fill="#000000">set</text>
</g>
<!-- /api/action/temperature/kill -->
<g id="node14" class="node">
<title>/api/action/temperature/kill</title>
<polygon fill="#caff70" stroke="#000000" points="552.9525,-534.0636 552.9525,-570.0636 606.9525,-570.0636 606.9525,-534.0636 552.9525,-534.0636"/>
<text text-anchor="middle" x="579.9525" y="-548.3636" font-family="Times,serif" font-size="14.00" fill="#000000">kill</text>
</g>
<!-- /api/action/temperature/set -->
<g id="node15" class="node">
<title>/api/action/temperature/set</title>
<polygon fill="#caff70" stroke="#000000" points="612.9525,-584.0636 612.9525,-620.0636 666.9525,-620.0636 666.9525,-584.0636 612.9525,-584.0636"/>
<text text-anchor="middle" x="639.9525" y="-598.3636" font-family="Times,serif" font-size="14.00" fill="#000000">set</text>
</g>
<!-- /api/sensor/temperature -->
<g id="node16" class="node">
<title>/api/sensor/temperature</title>
<polygon fill="#caff70" stroke="#000000" points="81.7144,-511.4227 81.7144,-547.4227 188.7144,-547.4227 188.7144,-511.4227 81.7144,-511.4227"/>
<text text-anchor="middle" x="135.2144" y="-525.7227" font-family="Times,serif" font-size="14.00" fill="#000000">temperature</text>
</g>
<!-- /api/routine/cook/list -->
<g id="node17" class="node">
<title>/api/routine/cook/list</title>
<polygon fill="#caff70" stroke="#000000" points="399.9525,-519.5636 399.9525,-555.5636 453.9525,-555.5636 453.9525,-519.5636 399.9525,-519.5636"/>
<text text-anchor="middle" x="426.9525" y="-533.8636" font-family="Times,serif" font-size="14.00" fill="#000000">list</text>
</g>
<!-- /api/settings/cook/recipe/list -->
<g id="node27" class="node">
<title>/api/settings/cook/recipe/list</title>
<polygon fill="#caff70" stroke="#000000" points="225.1906,-264.2044 225.1906,-300.2044 279.1906,-300.2044 279.1906,-264.2044 225.1906,-264.2044"/>
<text text-anchor="middle" x="252.1906" y="-278.5044" font-family="Times,serif" font-size="14.00" fill="#000000">list</text>
</g>
<!-- /api/routine/cook/list&#45;&gt;/api/settings/cook/recipe/list -->
<g id="edge7" class="edge">
<title>/api/routine/cook/list&#45;&gt;/api/settings/cook/recipe/list</title>
<path fill="none" stroke="#00bfff" d="M410.9237,-519.4619C382.8616,-487.1925 324.0271,-416.9087 284.1106,-350.9244 276.1888,-337.8293 268.8747,-322.4433 263.252,-309.5534"/>
<polygon fill="#00bfff" stroke="#00bfff" points="266.4349,-308.0944 259.3,-300.2622 259.9934,-310.8343 266.4349,-308.0944"/>
</g>
<!-- /api/routine/cook/start -->
<g id="node18" class="node">
<title>/api/routine/cook/start</title>
<polygon fill="#caff70" stroke="#000000" points="399.9525,-575.5636 399.9525,-611.5636 453.9525,-611.5636 453.9525,-575.5636 399.9525,-575.5636"/>
<text text-anchor="middle" x="426.9525" y="-589.8636" font-family="Times,serif" font-size="14.00" fill="#000000">start</text>
</g>
<!-- /api/routine/cook/kill -->
<g id="node19" class="node">
<title>/api/routine/cook/kill</title>
<polygon fill="#caff70" stroke="#000000" points="399.9525,-631.5636 399.9525,-667.5636 453.9525,-667.5636 453.9525,-631.5636 399.9525,-631.5636"/>
<text text-anchor="middle" x="426.9525" y="-645.8636" font-family="Times,serif" font-size="14.00" fill="#000000">kill</text>
</g>
<!-- /api/routine/cook/schedule/list -->
<g id="node20" class="node">
<title>/api/routine/cook/schedule/list</title>
<polygon fill="#caff70" stroke="#000000" points="324.1906,-585.2044 324.1906,-621.2044 378.1906,-621.2044 378.1906,-585.2044 324.1906,-585.2044"/>
<text text-anchor="middle" x="351.1906" y="-599.5044" font-family="Times,serif" font-size="14.00" fill="#000000">list</text>
</g>
<!-- /api/routine/cook/schedule/set -->
<g id="node21" class="node">
<title>/api/routine/cook/schedule/set</title>
<polygon fill="#caff70" stroke="#000000" points="264.1906,-535.2044 264.1906,-571.2044 318.1906,-571.2044 318.1906,-535.2044 264.1906,-535.2044"/>
<text text-anchor="middle" x="291.1906" y="-549.5044" font-family="Times,serif" font-size="14.00" fill="#000000">set</text>
</g>
<!-- /api/settings/lighting/list -->
<g id="node22" class="node">
<title>/api/settings/lighting/list</title>
<polygon fill="#caff70" stroke="#000000" points="476.9525,-74.0636 476.9525,-110.0636 530.9525,-110.0636 530.9525,-74.0636 476.9525,-74.0636"/>
<text text-anchor="middle" x="503.9525" y="-88.3636" font-family="Times,serif" font-size="14.00" fill="#000000">list</text>
</g>
<!-- /api/settings/lighting/set -->
<g id="node23" class="node">
<title>/api/settings/lighting/set</title>
<polygon fill="#caff70" stroke="#000000" points="416.9525,-24.0636 416.9525,-60.0636 470.9525,-60.0636 470.9525,-24.0636 416.9525,-24.0636"/>
<text text-anchor="middle" x="443.9525" y="-38.3636" font-family="Times,serif" font-size="14.00" fill="#000000">set</text>
</g>
<!-- /api/settings/cook/warm/temperature -->
<g id="node24" class="node">
<title>/api/settings/cook/warm/temperature</title>
<polygon fill="#caff70" stroke="#000000" points="32.1906,-88.2044 32.1906,-124.2044 139.1906,-124.2044 139.1906,-88.2044 32.1906,-88.2044"/>
<text text-anchor="middle" x="85.6906" y="-102.5044" font-family="Times,serif" font-size="14.00" fill="#000000">temperature</text>
</g>
<!-- /api/settings/cook/warm/set -->
<g id="node25" class="node">
<title>/api/settings/cook/warm/set</title>
<polygon fill="#caff70" stroke="#000000" points="50.6906,-154.2044 50.6906,-190.2044 104.6906,-190.2044 104.6906,-154.2044 50.6906,-154.2044"/>
<text text-anchor="middle" x="77.6906" y="-168.5044" font-family="Times,serif" font-size="14.00" fill="#000000">set</text>
</g>
<!-- /api/settings/cook/warm/duration -->
<g id="node26" class="node">
<title>/api/settings/cook/warm/duration</title>
<polygon fill="#caff70" stroke="#000000" points="116.1906,-136.2044 116.1906,-172.2044 193.1906,-172.2044 193.1906,-136.2044 116.1906,-136.2044"/>
<text text-anchor="middle" x="154.6906" y="-150.5044" font-family="Times,serif" font-size="14.00" fill="#000000">duration</text>
</g>
<!-- /api/settings/cook/recipe/set -->
<g id="node28" class="node">
<title>/api/settings/cook/recipe/set</title>
<polygon fill="#caff70" stroke="#000000" points="285.1906,-314.2044 285.1906,-350.2044 339.1906,-350.2044 339.1906,-314.2044 285.1906,-314.2044"/>
<text text-anchor="middle" x="312.1906" y="-328.5044" font-family="Times,serif" font-size="14.00" fill="#000000">set</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB