kopia lustrzana https://github.com/botheredbybees/kilnController
simulation basics
rodzic
95ee68f7d1
commit
50dc207fdf
42
oven.py
42
oven.py
|
@ -28,14 +28,18 @@ class Oven (threading.Thread):
|
|||
STATE_IDLE = "IDLE"
|
||||
STATE_RUNNING = "RUNNING"
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self,simulate = False,time_step=0.5):
|
||||
threading.Thread.__init__(self)
|
||||
self.daemon = True
|
||||
self.simulate = simulate
|
||||
self.time_step = time_step
|
||||
self.reset()
|
||||
if simulate:
|
||||
self.temp_sensor = TempSensorSimulate(self,0.5,self.time_step)
|
||||
if sensor_available:
|
||||
self.temp_sensor = TempSensorReal()
|
||||
self.temp_sensor = TempSensorReal(self.time_step)
|
||||
else:
|
||||
self.temp_sensor = TempSensorSimulate(self)
|
||||
self.temp_sensor = TempSensorSimulate(self,self.time_step,self.time_step)
|
||||
self.temp_sensor.start()
|
||||
self.start()
|
||||
|
||||
|
@ -68,7 +72,10 @@ class Oven (threading.Thread):
|
|||
self.door = self.get_door_state()
|
||||
|
||||
if self.state == Oven.STATE_RUNNING:
|
||||
self.runtime = (datetime.datetime.now() - self.start_time).total_seconds()
|
||||
if self.simulate:
|
||||
self.runtime += 0.5
|
||||
else:
|
||||
self.runtime = (datetime.datetime.now() - self.start_time).total_seconds()
|
||||
log.info("running at %.1f deg C (Target: %.1f) , heat %.2f, cool %.2f, air %.2f, door %s (%.1fs/%.0f)"%(self.temp_sensor.temperature,self.target,self.heat,self.cool,self.air,self.door,self.runtime,self.totaltime))
|
||||
self.target = self.profile.get_target_temperature(self.runtime)
|
||||
pid = self.pid.compute(self.target, self.temp_sensor.temperature)
|
||||
|
@ -92,7 +99,9 @@ class Oven (threading.Thread):
|
|||
|
||||
if self.runtime >= self.totaltime:
|
||||
self.reset()
|
||||
time.sleep(0.5)
|
||||
|
||||
time.sleep(self.time_step)
|
||||
|
||||
|
||||
def set_heat(self,value):
|
||||
if value:
|
||||
|
@ -146,18 +155,18 @@ class Oven (threading.Thread):
|
|||
|
||||
|
||||
class TempSensor(threading.Thread):
|
||||
def __init__(self):
|
||||
def __init__(self,time_step):
|
||||
threading.Thread.__init__(self)
|
||||
self.daemon = True
|
||||
self.temperature = 0
|
||||
self.time_step = 0.5
|
||||
|
||||
self.time_step = time_step
|
||||
|
||||
class TempSensorReal(TempSensor):
|
||||
def __init__(self):
|
||||
TempSensor.__init__(self)
|
||||
self.thermocouple = MAX31855(config.gpio_sensor_cs,
|
||||
config.gpio_sensor_clock,
|
||||
config.gpio_sensor_data,
|
||||
def __init__(self,time_step):
|
||||
TempSensor.__init__(self,time_step)
|
||||
self.thermocouple = MAX31855(config.gpio_sensor_cs,
|
||||
config.gpio_sensor_clock,
|
||||
config.gpio_sensor_data,
|
||||
"c"
|
||||
)
|
||||
|
||||
|
@ -167,9 +176,10 @@ class TempSensorReal(TempSensor):
|
|||
time.sleep(self.time_step)
|
||||
|
||||
class TempSensorSimulate(TempSensor):
|
||||
def __init__(self,oven):
|
||||
TempSensor.__init__(self)
|
||||
def __init__(self,oven,time_step,sleep_time):
|
||||
TempSensor.__init__(self,time_step)
|
||||
self.oven = oven
|
||||
self.sleep_time = sleep_time
|
||||
|
||||
def run(self):
|
||||
t_env = 25.0 #deg C
|
||||
|
@ -214,7 +224,7 @@ class TempSensorSimulate(TempSensor):
|
|||
print "-> %dW heater: %.0f -> %dW oven: %.0f -> %dW env"%(int(p_heat * self.oven.heat),t_h,int(p_ho),t,int(p_env))
|
||||
self.temperature = t
|
||||
|
||||
time.sleep(self.time_step)
|
||||
time.sleep(self.sleep_time)
|
||||
|
||||
class Profile():
|
||||
def __init__(self,json_data):
|
||||
|
|
|
@ -27,7 +27,7 @@ class OvenWatcher(threading.Thread):
|
|||
self.recording = False
|
||||
self.notify_all(oven_state)
|
||||
self.log_skip_counter = (self.log_skip_counter +1)%20
|
||||
time.sleep(0.5)
|
||||
time.sleep(self.oven.time_step)
|
||||
|
||||
def record(self, profile):
|
||||
self.last_profile = profile
|
||||
|
|
|
@ -34,6 +34,8 @@ def send_static(filename):
|
|||
def get_websocket_from_request():
|
||||
env = bottle.request.environ;
|
||||
wsock = env.get('wsgi.websocket')
|
||||
print wsock.path
|
||||
print wsock.origin
|
||||
if not wsock:
|
||||
abort(400, 'Expected WebSocket request.')
|
||||
return wsock
|
||||
|
@ -45,7 +47,6 @@ def handle_control():
|
|||
while True:
|
||||
try:
|
||||
message = wsock.receive()
|
||||
wsock.send("Your message was: %r" % message)
|
||||
log.info("Received (control): %s"% message)
|
||||
msgdict = json.loads(message)
|
||||
if msgdict.get("cmd") == "RUN":
|
||||
|
@ -56,6 +57,17 @@ def handle_control():
|
|||
profile = Profile(profile_json)
|
||||
oven.run_profile(profile)
|
||||
ovenWatcher.record(profile)
|
||||
elif msgdict.get("cmd") == "SIMULATE":
|
||||
log.info("SIMULATE command received")
|
||||
profile_obj = msgdict.get('profile')
|
||||
if profile_obj:
|
||||
profile_json = json.dumps(profile_obj)
|
||||
profile = Profile(profile_json)
|
||||
simulated_oven = Oven(simulate=True,time_step=0.05)
|
||||
simulation_watcher = OvenWatcher(simulated_oven)
|
||||
simulation_watcher.add_observer(wsock)
|
||||
#simulated_oven.run_profile(profile)
|
||||
#simulation_watcher.record(profile)
|
||||
elif msgdict.get("cmd") == "STOP":
|
||||
log.info("Stop command received")
|
||||
oven.abort_run()
|
||||
|
|
|
@ -104,6 +104,21 @@ function runTask()
|
|||
|
||||
}
|
||||
|
||||
function runTaskSimulation()
|
||||
{
|
||||
var cmd =
|
||||
{
|
||||
"cmd": "SIMULATE",
|
||||
"profile": profiles[selected_profile]
|
||||
}
|
||||
|
||||
graph.live.data = [];
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ] , getOptions());
|
||||
|
||||
ws_control.send(JSON.stringify(cmd));
|
||||
|
||||
}
|
||||
|
||||
|
||||
function abortTask()
|
||||
{
|
||||
|
@ -438,13 +453,18 @@ $(document).ready(function()
|
|||
|
||||
ws_control.onopen = function()
|
||||
{
|
||||
ws_control.onmessage = function(e)
|
||||
{
|
||||
console.log (e.data);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
ws_control.onmessage = function(e)
|
||||
{
|
||||
//Data from Simulation
|
||||
console.log (e.data);
|
||||
x = JSON.parse(e.data);
|
||||
graph.live.data.push([x.runtime, x.temperature]);
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ] , getOptions());
|
||||
|
||||
}
|
||||
|
||||
// Storage Socket ///////////////////////////////
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
<div id="btn_controls" class="pull-right" style="margin-top: 3px">
|
||||
<div id="nav_start" class="btn-group" style="display:none">
|
||||
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#jobSummaryModal">Simulate</button>
|
||||
<button type="button" class="btn btn-default" onclick="runTaskSimulation();">Simulate</button>
|
||||
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#jobSummaryModal"><span class="glyphicon glyphicon-play"></span> Start</button>
|
||||
</div>
|
||||
<button id="nav_stop" type="button" class="btn btn-danger" onclick="abortTask()" style="display:none" ><span class="glyphicon glyphicon-stop"></span> Stop</button>
|
||||
|
|
Ładowanie…
Reference in New Issue