kopia lustrzana https://github.com/botheredbybees/kilnController
Updated to 0.5sec update interval and fixed jerky progress bar
rodzic
9b3d801b56
commit
b8429275d2
26
oven.py
26
oven.py
|
@ -20,7 +20,7 @@ class Oven (threading.Thread):
|
|||
self.temp_sensor = TempSensor(self)
|
||||
self.temp_sensor.start()
|
||||
self.start()
|
||||
|
||||
|
||||
def reset(self):
|
||||
self.profile = None
|
||||
self.start_time = 0
|
||||
|
@ -29,7 +29,7 @@ class Oven (threading.Thread):
|
|||
self.target = 0
|
||||
self.power = 0.0
|
||||
self.state = Oven.STATE_IDLE
|
||||
|
||||
|
||||
def run_profile(self, profile):
|
||||
log.info("Running profile %s"%profile.name)
|
||||
self.profile = profile
|
||||
|
@ -47,14 +47,14 @@ class Oven (threading.Thread):
|
|||
self.runtime = (datetime.datetime.now() - self.start_time).total_seconds()
|
||||
log.info("running at %.1f deg C (Target: %.1f) , power %.2f (%.1fs/%.0f)"%(self.temp_sensor.temperature,self.target,self.power,self.runtime,self.totaltime))
|
||||
self.target = self.profile.get_target_temperature(self.runtime)
|
||||
|
||||
|
||||
if self.temp_sensor.temperature < self.target:
|
||||
self.power = 1.0
|
||||
else:
|
||||
self.power = 0.0
|
||||
if self.runtime >= self.totaltime:
|
||||
self.reset()
|
||||
time.sleep(1)
|
||||
time.sleep(0.5)
|
||||
|
||||
def get_state(self):
|
||||
state = {
|
||||
|
@ -71,10 +71,10 @@ class TempSensor(threading.Thread):
|
|||
def __init__(self,oven):
|
||||
threading.Thread.__init__(self)
|
||||
self.daemon = True
|
||||
|
||||
|
||||
self.temperature = 0
|
||||
self.oven = oven
|
||||
|
||||
|
||||
if not sensor_dummy:
|
||||
cs_pin = 27
|
||||
clock_pin = 22
|
||||
|
@ -90,31 +90,31 @@ class TempSensor(threading.Thread):
|
|||
time_delta = (20.0 - self.temperature)/40
|
||||
power_delta = 8.0*self.oven.power
|
||||
self.temperature += (time_delta+power_delta)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
class Profile():
|
||||
def __init__(self,json_data):
|
||||
obj = json.loads(json_data)
|
||||
self.name = obj["name"]
|
||||
self.data = sorted(obj["data"])
|
||||
|
||||
|
||||
def get_duration(self):
|
||||
return max([t for (t,x) in self.data])
|
||||
|
||||
|
||||
def get_target_temperature(self,time):
|
||||
if time > self.get_duration():
|
||||
return 0
|
||||
|
||||
|
||||
prev_point = None
|
||||
next_point = None
|
||||
|
||||
|
||||
for i in range(len(self.data)):
|
||||
if time < self.data[i][0]:
|
||||
prev_point = self.data[i-1]
|
||||
next_point = self.data[i]
|
||||
break
|
||||
|
||||
|
||||
incl = float(next_point[1] - prev_point[1]) / float(next_point[0] - prev_point[0])
|
||||
temp = prev_point[1] + (time - prev_point[0]) * incl
|
||||
return temp
|
||||
|
|
|
@ -7,7 +7,7 @@ class OvenWatcher(threading.Thread):
|
|||
self.observers = []
|
||||
threading.Thread.__init__(self)
|
||||
self.daemon = True
|
||||
|
||||
|
||||
self.oven = oven
|
||||
self.start()
|
||||
|
||||
|
@ -15,11 +15,11 @@ class OvenWatcher(threading.Thread):
|
|||
while True:
|
||||
oven_state = self.oven.get_state()
|
||||
self.notifyAll(oven_state)
|
||||
time.sleep(1)
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
def addObserver(self,observer):
|
||||
self.observers.append(observer)
|
||||
|
||||
|
||||
def notifyAll(self,message):
|
||||
message_json = json.dumps(message)
|
||||
log.debug("sending to %d clients: %s"%(len(self.observers),message_json))
|
||||
|
|
|
@ -4,7 +4,7 @@ function updateProgress(percentage){
|
|||
if(state=="RUNNING") {
|
||||
if(percentage > 100) percentage = 100;
|
||||
$('#progressBar').css('width', percentage+'%');
|
||||
if(percentage>=5) $('#progressBar').html(percentage+'%');
|
||||
if(percentage>=5) $('#progressBar').html(parseInt(percentage)+'%');
|
||||
} else {
|
||||
$('#progressBar').css('width', 0+'%');
|
||||
$('#progressBar').html('');
|
||||
|
@ -347,3 +347,190 @@ function update_profile(id) {
|
|||
textColor: '#E0E0E0',
|
||||
maskColor: 'rgba(255,255,255,0.3)'
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
function getHCOptions() {
|
||||
|
||||
var options =
|
||||
{
|
||||
title: { text: '' },
|
||||
xAxis: {
|
||||
title: { text: 'Time (s)' },
|
||||
type: 'integer',
|
||||
tickPixelInterval: 60
|
||||
},
|
||||
yAxis: {
|
||||
title: { text: 'Temperature (\xB0C)' },
|
||||
tickInterval: 25,
|
||||
min: 0,
|
||||
max: 300
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function() {
|
||||
return Highcharts.numberFormat(this.y, 0);
|
||||
}
|
||||
},
|
||||
chart: {
|
||||
type: 'line',
|
||||
renderTo: 'graph_container',
|
||||
animation: true,
|
||||
zoomType: 'x',
|
||||
marginTop: 30,
|
||||
marginRight: 30,
|
||||
events: {
|
||||
load: function() {
|
||||
var series = this.series[1];
|
||||
|
||||
|
||||
ws_status.onmessage = function(e)
|
||||
{
|
||||
x = JSON.parse(e.data);
|
||||
|
||||
if(state!="EDIT")
|
||||
{
|
||||
state = x.state;
|
||||
}
|
||||
|
||||
$('#state').html(state);
|
||||
|
||||
updateProgress(parseFloat(x.runtime)/parseFloat(x.totaltime)*100);
|
||||
|
||||
$('#act_temp').html(Highcharts.numberFormat(x.temperature, 0) + ' \xB0C');
|
||||
$('#power').css("background-color", (x.power > 0.5 ? "#75890c" : "#1F1E1A") );
|
||||
|
||||
|
||||
if (x.target == 0)
|
||||
{
|
||||
$('#target_temp').html('OFF');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#target_temp').html(Highcharts.numberFormat(x.target, 0) + ' \xB0C');
|
||||
}
|
||||
//console.log (e.data);
|
||||
//console.log('Percent finished:' + perc);
|
||||
|
||||
if(state!="EDIT")
|
||||
{
|
||||
|
||||
if(state=="RUNNING")
|
||||
{
|
||||
$("#nav_start").hide();
|
||||
$("#nav_stop").show();
|
||||
series.addPoint([x.runtime, x.temperature], true, false);
|
||||
|
||||
left = parseInt(x.totaltime-x.runtime);
|
||||
var minutes = Math.floor(left / 60);
|
||||
var seconds = left - minutes * 60;
|
||||
$('#eta').html(minutes+':'+ (seconds < 10 ? "0" : "") + seconds);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#nav_start").show();
|
||||
$("#nav_stop").hide();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
var socket = io.connect('http://10.1.1.110:8080');
|
||||
socket.on('sample', function (sample) {
|
||||
// when a sample arrives we plot it
|
||||
series.addPoint([sample.x, sample.y], true, false);
|
||||
$('#act_temp').html(Highcharts.numberFormat(sample.y, 0) + ' \xB0C');
|
||||
|
||||
|
||||
});
|
||||
|
||||
socket.on('error', function () {
|
||||
|
||||
$(document).trigger("add-alerts", [
|
||||
{
|
||||
'message': "No communication to control server",
|
||||
'priority': 'error'
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
})
|
||||
|
||||
// Called when the connection to the server is opened.
|
||||
socket.onopen = function () {
|
||||
alert("Connection with server open.");
|
||||
};
|
||||
|
||||
// Called when the connection to the server is closed.
|
||||
socket.onclose = function () {
|
||||
alert("Connection with server closed; Maybe the server wasn't found, it shut down or you're behind a firewall/proxy.");
|
||||
};
|
||||
*/
|
||||
}
|
||||
},
|
||||
resetZoomButton: {
|
||||
position: {
|
||||
align: 'right',
|
||||
verticalAlign: 'top'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
plotOptions: {
|
||||
series: {
|
||||
cursor: 'all-scroll',
|
||||
point: {
|
||||
events: {
|
||||
/*
|
||||
drag: function (e) {
|
||||
$('#drag').html('Dragging <b>' + this.series.name + '</b>, <b>' + this.category + '</b> to <b>' + Highcharts.numberFormat(e.newY, 0) + '</b>');
|
||||
},
|
||||
drop: function () {
|
||||
$('#drop').html('In <b>' + this.series.name + '</b>, <b>' + this.category + '</b> was set to <b>' + Highcharts.numberFormat(this.y, 0) + '</b>');
|
||||
}*/
|
||||
}
|
||||
},
|
||||
stickyTracking: false
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
credits: {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
series: [{
|
||||
name: 'Ref',
|
||||
data: [
|
||||
[1, 25 ],
|
||||
[70, 150 ],
|
||||
[180, 183 ],
|
||||
[210, 230 ],
|
||||
[240, 183 ],
|
||||
[300, 25 ]
|
||||
],
|
||||
draggableX: false,
|
||||
draggableY: false,
|
||||
dragMinY: 0,
|
||||
dragMaxY: 250,
|
||||
marker: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Act',
|
||||
data: [
|
||||
[0,0]
|
||||
],
|
||||
marker: {
|
||||
enabled: false
|
||||
}
|
||||
}]
|
||||
|
||||
};
|
||||
|
||||
return (options);
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
<div class="container">
|
||||
|
||||
<!-- Static navbar -->
|
||||
<div id="main_status">
|
||||
<div class="pull-left" style="margin: 14px">
|
||||
<span id="act_temp" class="display" style="color: #75890c">25 °C</span>
|
||||
|
@ -41,7 +40,6 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /Static navbar -->
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
|
@ -73,9 +71,7 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
</div> <!-- /container -->
|
||||
|
||||
|
||||
</div><!-- /container -->
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
|
@ -104,8 +100,7 @@
|
|||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
|
||||
<script>
|
||||
<script>
|
||||
|
||||
var state = "IDLE";
|
||||
var graph;
|
||||
|
@ -211,9 +206,6 @@ ws_storage.onopen = function()
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$("#e2").select2({
|
||||
placeholder: "Temperature Curve",
|
||||
allowClear: false
|
||||
|
@ -230,9 +222,6 @@ $("#e2").on("change", function(e) {
|
|||
var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$(function() {
|
||||
Highcharts.setOptions({
|
||||
global: {
|
||||
|
@ -240,189 +229,7 @@ $(function() {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
var options =
|
||||
{
|
||||
title: { text: '' },
|
||||
xAxis: {
|
||||
title: { text: 'Time (s)' },
|
||||
type: 'integer',
|
||||
tickPixelInterval: 60
|
||||
},
|
||||
yAxis: {
|
||||
title: { text: 'Temperature (\xB0C)' },
|
||||
tickInterval: 25,
|
||||
min: 0,
|
||||
max: 300
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function() {
|
||||
return Highcharts.numberFormat(this.y, 0);
|
||||
}
|
||||
},
|
||||
chart: {
|
||||
type: 'line',
|
||||
renderTo: 'graph_container',
|
||||
animation: true,
|
||||
zoomType: 'x',
|
||||
marginTop: 30,
|
||||
marginRight: 30,
|
||||
events: {
|
||||
load: function() {
|
||||
var series = this.series[1];
|
||||
|
||||
|
||||
ws_status.onmessage = function(e)
|
||||
{
|
||||
x = JSON.parse(e.data);
|
||||
|
||||
if(state!="EDIT")
|
||||
{
|
||||
state = x.state;
|
||||
}
|
||||
|
||||
$('#state').html(state);
|
||||
|
||||
updateProgress(parseInt(parseFloat(x.runtime)/parseFloat(x.totaltime)*100));
|
||||
|
||||
$('#act_temp').html(Highcharts.numberFormat(x.temperature, 0) + ' \xB0C');
|
||||
$('#power').css("background-color", (x.power > 0.5 ? "#75890c" : "#1F1E1A") );
|
||||
|
||||
|
||||
if (x.target == 0)
|
||||
{
|
||||
$('#target_temp').html('OFF');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#target_temp').html(Highcharts.numberFormat(x.target, 0) + ' \xB0C');
|
||||
}
|
||||
//console.log (e.data);
|
||||
//console.log('Percent finished:' + perc);
|
||||
|
||||
if(state!="EDIT")
|
||||
{
|
||||
|
||||
if(state=="RUNNING")
|
||||
{
|
||||
$("#nav_start").hide();
|
||||
$("#nav_stop").show();
|
||||
series.addPoint([x.runtime, x.temperature], true, false);
|
||||
|
||||
left = parseInt(x.totaltime-x.runtime);
|
||||
var minutes = Math.floor(left / 60);
|
||||
var seconds = left - minutes * 60;
|
||||
$('#eta').html(minutes+':'+ (seconds < 10 ? "0" : "") + seconds);
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#nav_start").show();
|
||||
$("#nav_stop").hide();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
var socket = io.connect('http://10.1.1.110:8080');
|
||||
socket.on('sample', function (sample) {
|
||||
// when a sample arrives we plot it
|
||||
series.addPoint([sample.x, sample.y], true, false);
|
||||
$('#act_temp').html(Highcharts.numberFormat(sample.y, 0) + ' \xB0C');
|
||||
|
||||
|
||||
});
|
||||
|
||||
socket.on('error', function () {
|
||||
|
||||
$(document).trigger("add-alerts", [
|
||||
{
|
||||
'message': "No communication to control server",
|
||||
'priority': 'error'
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
})
|
||||
|
||||
// Called when the connection to the server is opened.
|
||||
socket.onopen = function () {
|
||||
alert("Connection with server open.");
|
||||
};
|
||||
|
||||
// Called when the connection to the server is closed.
|
||||
socket.onclose = function () {
|
||||
alert("Connection with server closed; Maybe the server wasn't found, it shut down or you're behind a firewall/proxy.");
|
||||
};
|
||||
*/
|
||||
}
|
||||
},
|
||||
resetZoomButton: {
|
||||
position: {
|
||||
align: 'right',
|
||||
verticalAlign: 'top'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
plotOptions: {
|
||||
series: {
|
||||
cursor: 'all-scroll',
|
||||
point: {
|
||||
events: {
|
||||
/*
|
||||
drag: function (e) {
|
||||
$('#drag').html('Dragging <b>' + this.series.name + '</b>, <b>' + this.category + '</b> to <b>' + Highcharts.numberFormat(e.newY, 0) + '</b>');
|
||||
},
|
||||
drop: function () {
|
||||
$('#drop').html('In <b>' + this.series.name + '</b>, <b>' + this.category + '</b> was set to <b>' + Highcharts.numberFormat(this.y, 0) + '</b>');
|
||||
}*/
|
||||
}
|
||||
},
|
||||
stickyTracking: false
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
credits: {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
series: [{
|
||||
name: 'Ref',
|
||||
data: [
|
||||
[1, 25 ],
|
||||
[70, 150 ],
|
||||
[180, 183 ],
|
||||
[210, 230 ],
|
||||
[240, 183 ],
|
||||
[300, 25 ]
|
||||
],
|
||||
draggableX: false,
|
||||
draggableY: false,
|
||||
dragMinY: 0,
|
||||
dragMaxY: 250,
|
||||
marker: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Act',
|
||||
data: [
|
||||
[0,0]
|
||||
],
|
||||
marker: {
|
||||
enabled: false
|
||||
}
|
||||
}]
|
||||
|
||||
};
|
||||
|
||||
graph = new Highcharts.Chart(options);
|
||||
graph = new Highcharts.Chart(getHCOptions());
|
||||
|
||||
|
||||
});
|
||||
|
|
Ładowanie…
Reference in New Issue