first working deployment
This commit is contained in:
parent
36fd834a55
commit
e2b64cf10c
23
config.py
23
config.py
@ -14,7 +14,7 @@ listening_ip = "0.0.0.0"
|
||||
listening_port = 8081
|
||||
|
||||
### Cost Estimate
|
||||
kwh_rate = 0.1319 # Rate in currency_type to calculate cost to run job
|
||||
kwh_rate = 0.10 # Rate in currency_type to calculate cost to run job
|
||||
currency_type = "$" # Currency Symbol to show when calculating cost to run job
|
||||
|
||||
########################################################################
|
||||
@ -27,20 +27,21 @@ currency_type = "$" # Currency Symbol to show when calculating cost to run j
|
||||
# can use whichever GPIO you prefer/have available.
|
||||
|
||||
### Outputs
|
||||
gpio_heat = 23 # Switches zero-cross solid-state-relay
|
||||
gpio_contactor = 23 # Contactor and Fan Enable
|
||||
gpio_heat = 24 # Switches zero-cross solid-state-relay
|
||||
|
||||
### Thermocouple Adapter selection:
|
||||
# max31855 - bitbang SPI interface
|
||||
# max31856 - bitbang SPI interface. must specify thermocouple_type.
|
||||
max31855 = 1
|
||||
max31856 = 0
|
||||
max31855 = 0
|
||||
max31856 = 1
|
||||
# see lib/max31856.py for other thermocouple_type, only applies to max31856
|
||||
thermocouple_type = MAX31856.MAX31856_S_TYPE
|
||||
thermocouple_type = MAX31856.MAX31856_K_TYPE
|
||||
|
||||
### Thermocouple Connection (using bitbang interfaces)
|
||||
gpio_sensor_cs = 27
|
||||
gpio_sensor_clock = 22
|
||||
gpio_sensor_data = 17
|
||||
gpio_sensor_cs = 5
|
||||
gpio_sensor_clock = 11
|
||||
gpio_sensor_data = 9
|
||||
gpio_sensor_di = 10 # only used with max31856
|
||||
|
||||
########################################################################
|
||||
@ -50,7 +51,7 @@ gpio_sensor_di = 10 # only used with max31856
|
||||
# Every N seconds a decision is made about switching the relay[s]
|
||||
# on & off and for how long. The thermocouple is read
|
||||
# temperature_average_samples times during and the average value is used.
|
||||
sensor_time_wait = 2
|
||||
sensor_time_wait = 5
|
||||
|
||||
|
||||
########################################################################
|
||||
@ -80,7 +81,7 @@ stop_integral_windup = True
|
||||
########################################################################
|
||||
#
|
||||
# Simulation parameters
|
||||
simulate = True
|
||||
simulate = False
|
||||
sim_t_env = 60.0 # deg C
|
||||
sim_c_heat = 100.0 # J/K heat capacity of heat element
|
||||
sim_c_oven = 5000.0 # J/K heat capacity of oven
|
||||
@ -98,7 +99,7 @@ sim_R_ho_air = 0.05 # K/W " with internal air circulation
|
||||
# If you change the temp_scale, all settings in this file are assumed to
|
||||
# be in that scale.
|
||||
|
||||
temp_scale = "f" # c = Celsius | f = Fahrenheit - Unit to display
|
||||
temp_scale = "c" # c = Celsius | f = Fahrenheit - Unit to display
|
||||
time_scale_slope = "h" # s = Seconds | m = Minutes | h = Hours - Slope displayed in temp_scale per time_scale_slope
|
||||
time_scale_profile = "m" # s = Seconds | m = Minutes | h = Hours - Enter and view target time in time_scale_profile
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
@ -46,6 +47,7 @@ def recordprofile(csvfile, targettemp):
|
||||
try:
|
||||
stage = 'heating'
|
||||
if not config.simulate:
|
||||
oven.output.GPIO.output(config.gpio_contactor, oven.output.GPIO.LOW) #ON
|
||||
oven.output.heat(1, tuning=True)
|
||||
|
||||
while True:
|
||||
@ -58,10 +60,13 @@ def recordprofile(csvfile, targettemp):
|
||||
if stage == 'heating':
|
||||
if temp >= targettemp:
|
||||
if not config.simulate:
|
||||
oven.output.heat(0)
|
||||
oven.output.GPIO.output(config.gpio_contactor, self.GPIO.HIGH) #OFF
|
||||
oven.output.cool(0)
|
||||
stage = 'cooling'
|
||||
|
||||
elif stage == 'cooling':
|
||||
oven.output.GPIO.output(config.gpio_contactor, self.GPIO.HIGH) #OFF
|
||||
oven.output.cool(0)
|
||||
if temp < targettemp:
|
||||
break
|
||||
|
||||
@ -73,7 +78,8 @@ def recordprofile(csvfile, targettemp):
|
||||
finally:
|
||||
# ensure we always shut the oven down!
|
||||
if not config.simulate:
|
||||
oven.output.heat(0)
|
||||
oven.output.GPIO.output(config.gpio_contactor, oven.output.GPIO.HIGH) #OFF
|
||||
oven.output.cool(0)
|
||||
|
||||
|
||||
def line(a, b, x):
|
||||
@ -87,7 +93,7 @@ def invline(a, b, y):
|
||||
def plot(xdata, ydata,
|
||||
tangent_min, tangent_max, tangent_slope, tangent_offset,
|
||||
lower_crossing_x, upper_crossing_x):
|
||||
from matplotlib import pyplot
|
||||
from matplotlib.pyplot import pyplot
|
||||
|
||||
minx = min(xdata)
|
||||
maxx = max(xdata)
|
||||
|
||||
42
kilnTest1.py
Normal file
42
kilnTest1.py
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
import board
|
||||
import digitalio
|
||||
import adafruit_max31856
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
|
||||
# Create sensor object, communicating over the board's default SPI bus
|
||||
spi = board.SPI()
|
||||
|
||||
# allocate a CS pin and set the direction
|
||||
cs = digitalio.DigitalInOut(board.D5)
|
||||
cs.direction = digitalio.Direction.OUTPUT
|
||||
|
||||
# create a thermocouple object with the above
|
||||
thermocouple = adafruit_max31856.MAX31856(spi, cs)
|
||||
|
||||
# print the temperature!
|
||||
print(thermocouple.temperature)
|
||||
|
||||
relay1 = 23
|
||||
relay2 = 24
|
||||
trigger1 = 20
|
||||
trigger2 = 21
|
||||
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(relay1, GPIO.OUT)
|
||||
GPIO.setup(relay2, GPIO.OUT)
|
||||
GPIO.setup(trigger1, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||||
GPIO.setup(trigger2, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||||
|
||||
while True:
|
||||
print(thermocouple.temperature)
|
||||
# print("RELAY ON")
|
||||
# GPIO.output(relay1, 0) #ON
|
||||
GPIO.output(relay1, 1) #OFF
|
||||
GPIO.output(relay2, 1)
|
||||
time.sleep(5)
|
||||
# print("RELAY OFF")
|
||||
# GPIO.output(relay1, 0)
|
||||
GPIO.output(relay2, 0)
|
||||
time.sleep(5)
|
||||
10
lib/oven.py
10
lib/oven.py
@ -20,6 +20,7 @@ class Output(object):
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setwarnings(False)
|
||||
GPIO.setup(config.gpio_heat, GPIO.OUT)
|
||||
GPIO.setup(config.gpio_contactor, GPIO.OUT)
|
||||
self.active = True
|
||||
self.GPIO = GPIO
|
||||
except:
|
||||
@ -38,6 +39,12 @@ class Output(object):
|
||||
self.GPIO.output(config.gpio_heat, self.GPIO.LOW)
|
||||
time.sleep(sleepfor)
|
||||
|
||||
def contactor_on(self):
|
||||
self.GPIO.output(config.gpio_contactor, self.GPIO.LOW) #ON
|
||||
|
||||
def contactor_off(self):
|
||||
self.GPIO.output(config.gpio_contactor, self.GPIO.HIGH) #OFF
|
||||
|
||||
# FIX - Board class needs to be completely removed
|
||||
class Board(object):
|
||||
def __init__(self):
|
||||
@ -182,6 +189,7 @@ class Oven(threading.Thread):
|
||||
self.target = 0
|
||||
self.heat = 0
|
||||
self.pid = PID(ki=config.pid_ki, kd=config.pid_kd, kp=config.pid_kp)
|
||||
self.output.contactor_off()
|
||||
|
||||
def run_profile(self, profile, startat=0):
|
||||
self.reset()
|
||||
@ -206,6 +214,7 @@ class Oven(threading.Thread):
|
||||
self.start_time = datetime.datetime.now()
|
||||
self.startat = startat * 60
|
||||
log.info("Starting")
|
||||
self.output.contactor_on()
|
||||
|
||||
def abort_run(self):
|
||||
self.reset()
|
||||
@ -391,6 +400,7 @@ class RealOven(Oven):
|
||||
|
||||
def reset(self):
|
||||
super().reset()
|
||||
# self.output.GPIO.output(config.gpio_contactor, self.GPIO.HIGH) #OFF
|
||||
self.output.cool(0)
|
||||
|
||||
def heat_then_cool(self):
|
||||
|
||||
398
public/assets/css/picoreflow_save.css
Normal file
398
public/assets/css/picoreflow_save.css
Normal file
@ -0,0 +1,398 @@
|
||||
@font-face{
|
||||
font-family: "Digi";
|
||||
src: url('/picoreflow/assets/fonts/digital-7-webfont.eot');
|
||||
src: local("Digital 7"),
|
||||
url('/picoreflow/assets/fonts/digital-7-webfont.woff') format("woff"),
|
||||
url('/picoreflow/assets/fonts/digital-7-webfont.ttf') format("truetype");
|
||||
}
|
||||
|
||||
@font-face{
|
||||
font-family: "Tables";
|
||||
src: url('/picoreflow/assets/fonts/tables.eot');
|
||||
src: local("Tables"),
|
||||
url('/picoreflow/assets/fonts/tables.woff') format("woff"),
|
||||
url('/picoreflow/assets/fonts/tables.ttf') format("truetype");
|
||||
}
|
||||
|
||||
body {
|
||||
background: #b9b6af;
|
||||
}
|
||||
|
||||
#status {
|
||||
margin-top: 15px;
|
||||
color: #d8d3c5;
|
||||
font-weight: normal;
|
||||
-webkit-border-radius: 7px;
|
||||
-moz-border-radius: 7px;
|
||||
border-radius: 7px;
|
||||
border: 1px solid #ddd;
|
||||
height: 80px;
|
||||
-moz-box-shadow: 0 0 1.1em 0 rgba(0,0,0,0.55);
|
||||
-webkit-box-shadow: 0 0 1.5em 0 rgba(0,0,0,0.55);
|
||||
box-shadow: 0 0 1.1em 0 rgba(0,0,0,0.55);
|
||||
}
|
||||
|
||||
.display {
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
padding-right: 5px;
|
||||
font-size: 40px;
|
||||
font-weight: normal;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
vertical-align: middle;
|
||||
color: #d8d3c5;
|
||||
border-color: #000000;
|
||||
}
|
||||
|
||||
.ds-panel {
|
||||
background: #3F3E3A url('/picoreflow/assets/images/panel_bg.png') repeat;
|
||||
-moz-box-shadow: inset 0 0 42px 0 #000;
|
||||
-webkit-box-shadow: inset 0 0 42px 0 #000;
|
||||
box-shadow: inset 0 0 42px 0 #000;
|
||||
}
|
||||
|
||||
.ds-title-panel {
|
||||
-webkit-border-top-left-radius: 6px;
|
||||
-webkit-border-top-right-radius: 6px;
|
||||
-moz-border-radius-topleft: 6px;
|
||||
-moz-border-radius-topright: 6px;
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
background-image: -webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));
|
||||
background-image: -webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);
|
||||
background-image: -moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);
|
||||
background-image: linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0);
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.ds-title {
|
||||
display: inline-block;
|
||||
font-size: 10px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
width: 100px;
|
||||
border-right: 1px solid #b9b6af;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
color: #8B8989;
|
||||
text-shadow: 1px 1px 0px rgba(255, 255, 255, 0.75);
|
||||
}
|
||||
|
||||
.ds-num {
|
||||
width: 100px;
|
||||
font-family: "Digi";
|
||||
border-right: 1px solid #b9b6af;
|
||||
white-space: nowrap;
|
||||
text-shadow: 0 0 25px rgba(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
.ds-input {
|
||||
color: #d8d3c5;
|
||||
font-family: "Digi";
|
||||
font-size: 24px;
|
||||
text-shadow: 0 0 12px rgba(0, 0, 0, 1);
|
||||
background: #3F3E3A url('/picoreflow/assets/images/panel_bg.png') repeat;
|
||||
-moz-box-shadow: inset 0 0 12px 0 #000;
|
||||
-webkit-box-shadow: inset 0 0 12px 0 #000;
|
||||
box-shadow: inset 0 0 12px 0 #000;
|
||||
text-align: right;
|
||||
padding: 0;
|
||||
padding-right: 7px;
|
||||
|
||||
}
|
||||
|
||||
.ds-unit {
|
||||
font-family: "Arial";
|
||||
font-size: 22px;
|
||||
vertical-align: top;
|
||||
line-height: 32px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.ds-led {
|
||||
font-family: "Tables";
|
||||
font-size: 38px;
|
||||
text-align: center;
|
||||
color: #1F1E1A;
|
||||
text-shadow: 0 0 5px #000, 0 0 5px #000;
|
||||
border-left: 1px solid #b9b6af;
|
||||
height: 40px;
|
||||
width: 42px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
.ds-led-hazard-active {
|
||||
color: rgb(255, 204, 0);
|
||||
background: -moz-radial-gradient(center, ellipse cover, rgba(242,195,67,1) 0%, rgba(241,218,54,0.26) 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(242,195,67,1)), color-stop(100%,rgba(241,218,54,0.26))); /* Chrome,Safari4+ */
|
||||
background: -webkit-radial-gradient(center, ellipse cover, rgba(242,195,67,1) 0%,rgba(241,218,54,0.26) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-radial-gradient(center, ellipse cover, rgba(242,195,67,1) 0%,rgba(241,218,54,0.26) 100%); /* Opera 12+ */
|
||||
background: -ms-radial-gradient(center, ellipse cover, rgba(242,195,67,1) 0%,rgba(241,218,54,0.26) 100%); /* IE10+ */
|
||||
background: radial-gradient(ellipse at center, rgba(242,195,67,1) 0%,rgba(241,218,54,0.26) 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ds-led-door-open {
|
||||
color: rgb(214, 42, 0);
|
||||
background: -moz-radial-gradient(center, ellipse cover, rgba(242,195,67,1) 0%, rgba(241,218,54,0.26) 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(242,195,67,1)), color-stop(100%,rgba(241,218,54,0.26))); /* Chrome,Safari4+ */
|
||||
background: -webkit-radial-gradient(center, ellipse cover, rgba(242,195,67,1) 0%,rgba(241,218,54,0.26) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-radial-gradient(center, ellipse cover, rgba(242,195,67,1) 0%,rgba(241,218,54,0.26) 100%); /* Opera 12+ */
|
||||
background: -ms-radial-gradient(center, ellipse cover, rgba(242,195,67,1) 0%,rgba(241,218,54,0.26) 100%); /* IE10+ */
|
||||
background: radial-gradient(ellipse at center, rgba(242,195,67,1) 0%,rgba(241,218,54,0.26) 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ds-led-cool-active {
|
||||
color: rgb(74, 159, 255);
|
||||
background: -moz-radial-gradient(center, ellipse cover, rgba(124,197,239,1) 0%, rgba(48,144,209,0.26) 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(124,197,239,1)), color-stop(100%,rgba(48,144,209,0.26))); /* Chrome,Safari4+ */
|
||||
background: -webkit-radial-gradient(center, ellipse cover, rgba(124,197,239,1) 0%,rgba(48,144,209,0.26) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-radial-gradient(center, ellipse cover, rgba(124,197,239,1) 0%,rgba(48,144,209,0.26) 100%); /* Opera 12+ */
|
||||
background: -ms-radial-gradient(center, ellipse cover, rgba(124,197,239,1) 0%,rgba(48,144,209,0.26) 100%); /* IE10+ */
|
||||
background: radial-gradient(ellipse at center, rgba(124,197,239,1) 0%,rgba(48,144,209,0.26) 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ds-led-heat-active {
|
||||
color: rgb(214, 42, 0);
|
||||
background: -moz-radial-gradient(center, ellipse cover, rgba(214,25,25,1) 0%, rgba(214,42,0,0.26) 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(214,25,25,1)), color-stop(100%,rgba(214,42,0,0.26))); /* Chrome,Safari4+ */
|
||||
background: -webkit-radial-gradient(center, ellipse cover, rgba(214,25,25,1) 0%,rgba(214,42,0,0.26) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-radial-gradient(center, ellipse cover, rgba(214,25,25,1) 0%,rgba(214,42,0,0.26) 100%); /* Opera 12+ */
|
||||
background: -ms-radial-gradient(center, ellipse cover, rgba(214,25,25,1) 0%,rgba(214,42,0,0.26) 100%); /* IE10+ */
|
||||
background: radial-gradient(ellipse at center, rgba(214,25,25,1) 0%,rgba(214,42,0,0.26) 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ds-led-air-active {
|
||||
color: rgb(240, 240, 240);
|
||||
background: -moz-radial-gradient(center, ellipse cover, rgba(221,221,221,1) 0%, rgba(221,221,221,0.26) 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(221,221,221,1)), color-stop(100%,rgba(221,221,221,0.26))); /* Chrome,Safari4+ */
|
||||
background: -webkit-radial-gradient(center, ellipse cover, rgba(221,221,221,1) 0%,rgba(221,221,221,0.26) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-radial-gradient(center, ellipse cover, rgba(221,221,221,1) 0%,rgba(221,221,221,0.26) 100%); /* Opera 12+ */
|
||||
background: -ms-radial-gradient(center, ellipse cover, rgba(221,221,221,1) 0%,rgba(221,221,221,0.26) 100%); /* IE10+ */
|
||||
background: radial-gradient(ellipse at center, rgba(221,221,221,1) 0%,rgba(221,221,221,0.26) 100%); /* W3C */
|
||||
}
|
||||
|
||||
.ds-trend {
|
||||
top: 0;
|
||||
text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.25), -1px -1px 0 rgba(0, 0, 0, 0.4);
|
||||
color: rgb(233, 233, 233);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.ds-target {
|
||||
color: #75890c;
|
||||
}
|
||||
|
||||
.ds-state {
|
||||
border: none;
|
||||
width: initial;
|
||||
text-align: center;
|
||||
width: 168px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ds-state {
|
||||
border: none;
|
||||
width: initial;
|
||||
text-align: center;
|
||||
width: 210px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ds-text {
|
||||
border: none;
|
||||
width: initial;
|
||||
font-family: sans-serif;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
background: #3f3e3a;
|
||||
border-color: #000000;
|
||||
border-top: 1px solid #b9b6af;
|
||||
margin: 0;
|
||||
-webkit-border-bottom-left-radius: 7px;
|
||||
-webkit-border-bottom-right-radius: 7px;
|
||||
-moz-border-radius-bottomleft: 7px;
|
||||
-moz-border-radius-bottomright: 7px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
background-color: #75890c;
|
||||
font-family: "Digi";
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
.panel-default {
|
||||
-webkit-border-radius: 7px;
|
||||
-moz-border-radius: 7px;
|
||||
border-radius: 7px;
|
||||
-moz-box-shadow: 0 0 1.1em 0 rgba(0,0,0,0.55);
|
||||
-webkit-box-shadow: 0 0 1.5em 0 rgba(0,0,0,0.55);
|
||||
box-shadow: 0 0 1.1em 0 rgba(0,0,0,0.55);
|
||||
margin-top: 15px;
|
||||
background: #3F3E3A url('/picoreflow/assets/images/panel_bg.png') repeat;
|
||||
}
|
||||
|
||||
.panel-heading {
|
||||
background: #fafafa url('/picoreflow/assets/images/page_bg.png') repeat-x;
|
||||
overflow: hidden;
|
||||
padding: 10px;
|
||||
-webkit-border-top-left-radius: 5px;
|
||||
-webkit-border-top-right-radius: 5px;
|
||||
-moz-border-radius-topleft: 5px;
|
||||
-moz-border-radius-topright: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
-moz-box-shadow: inset 0 0 42px 0 #000;
|
||||
-webkit-box-shadow: inset 0 0 42px 0 #000;
|
||||
box-shadow: inset 0 0 42px 0 #000;
|
||||
-webkit-border-bottom-left-radius: 7px;
|
||||
-webkit-border-bottom-right-radius: 7px;
|
||||
-moz-border-radius-bottomleft: 7px;
|
||||
-moz-border-radius-bottomright: 7px;
|
||||
background: rgba(0,0,0,0.2)
|
||||
}
|
||||
|
||||
#profile_selector {
|
||||
border: 1px solid rgb(194, 194, 194);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
background: rgb(229,229,229);
|
||||
background: -moz-linear-gradient(top, rgba(229,229,229,1) 0%, rgba(255,255,255,1) 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(229,229,229,1)), color-stop(100%,rgba(255,255,255,1)));
|
||||
background: -webkit-linear-gradient(top, rgba(229,229,229,1) 0%,rgba(255,255,255,1) 100%);
|
||||
background: -o-linear-gradient(top, rgba(229,229,229,1) 0%,rgba(255,255,255,1) 100%);
|
||||
background: -ms-linear-gradient(top, rgba(229,229,229,1) 0%,rgba(255,255,255,1) 100%);
|
||||
background: linear-gradient(to bottom, rgba(229,229,229,1) 0%,rgba(255,255,255,1) 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e5e5e5', endColorstr='#ffffff',GradientType=0 );
|
||||
padding: 5px;
|
||||
padding-bottom: 3px;
|
||||
padding-top: 3px;
|
||||
-moz-box-shadow: 0 0 1.1em 0 rgba(0,0,0,0.05),inset 0 0 9px 2px #000;
|
||||
-webkit-box-shadow: 0 0 1.5em 0 rgba(0,0,0,0.05),inset 0 0 0 0 #000;
|
||||
box-shadow: 0 0 1.1em 0 rgba(0,0,0,0.05),inset 0 0 0 0 #000;
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
position: relative;
|
||||
top: -3px;
|
||||
width: 190px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.select2-container .select2-choice {
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.graph {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
font-size: 14px;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
.edit-points {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.edit-points h3 {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.edit-points .row{
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background: rgb(164,179,87);
|
||||
background: -moz-linear-gradient(top, rgba(164,179,87,1) 0%, rgba(117,137,12,1) 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(164,179,87,1)), color-stop(100%,rgba(117,137,12,1)));
|
||||
background: -webkit-linear-gradient(top, rgba(164,179,87,1) 0%,rgba(117,137,12,1) 100%);
|
||||
background: -o-linear-gradient(top, rgba(164,179,87,1) 0%,rgba(117,137,12,1) 100%);
|
||||
background: -ms-linear-gradient(top, rgba(164,179,87,1) 0%,rgba(117,137,12,1) 100%);
|
||||
background: linear-gradient(to bottom, rgba(164,179,87,1) 0%,rgba(117,137,12,1) 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a4b357', endColorstr='#75890c',GradientType=0 );
|
||||
background-color: #75890c;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-image: linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.modal-body .table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.select2-container .select2-choice {
|
||||
height: 34px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.modal.fade.in {
|
||||
top: 10%;
|
||||
}
|
||||
|
||||
.alert {
|
||||
background-image: -webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));
|
||||
background-image: -webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);
|
||||
background-image: -moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);
|
||||
background-image: linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0);
|
||||
-moz-box-shadow: 0 0 1.1em 0 rgba(0,0,0,0.75);
|
||||
-webkit-box-shadow: 0 0 1.5em 0 rgba(0,0,0,0.75);
|
||||
box-shadow: 0 0 1.1em 0 rgba(0,0,0,0.75);
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
background: rgb(164,179,87);
|
||||
background: -moz-linear-gradient(top, rgba(164,179,87,1) 0%, rgba(117,137,12,1) 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(164,179,87,1)), color-stop(100%,rgba(117,137,12,1)));
|
||||
background: -webkit-linear-gradient(top, rgba(164,179,87,1) 0%,rgba(117,137,12,1) 100%);
|
||||
background: -o-linear-gradient(top, rgba(164,179,87,1) 0%,rgba(117,137,12,1) 100%);
|
||||
background: -ms-linear-gradient(top, rgba(164,179,87,1) 0%,rgba(117,137,12,1) 100%);
|
||||
background: linear-gradient(to bottom, rgba(164,179,87,1) 0%,rgba(117,137,12,1) 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a4b357', endColorstr='#75890c',GradientType=0 );
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.alert-error {
|
||||
background: rgb(206,57,20);
|
||||
background: -moz-linear-gradient(top, rgba(206,57,20,1) 0%, rgba(163,38,0,1) 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(206,57,20,1)), color-stop(100%,rgba(163,38,0,1)));
|
||||
background: -webkit-linear-gradient(top, rgba(206,57,20,1) 0%,rgba(163,38,0,1) 100%);
|
||||
background: -o-linear-gradient(top, rgba(206,57,20,1) 0%,rgba(163,38,0,1) 100%);
|
||||
background: -ms-linear-gradient(top, rgba(206,57,20,1) 0%,rgba(163,38,0,1) 100%);
|
||||
background: linear-gradient(to bottom, rgba(206,57,20,1) 0%,rgba(163,38,0,1) 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ce3914', endColorstr='#a32600',GradientType=0 );
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.modal-body td {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.table-responsive {
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
@ -11,8 +11,8 @@ var time_scale_slope = "s";
|
||||
var time_scale_profile = "s";
|
||||
var time_scale_long = "Seconds";
|
||||
var temp_scale_display = "C";
|
||||
var kwh_rate = 0.26;
|
||||
var currency_type = "EUR";
|
||||
var kwh_rate = 0.1;
|
||||
var currency_type = "$";
|
||||
|
||||
var protocol = 'ws:';
|
||||
if (window.location.protocol == 'https:') {
|
||||
@ -560,10 +560,7 @@ $(document).ready(function()
|
||||
|
||||
$('#act_temp').html(parseInt(x.temperature));
|
||||
|
||||
if (x.heat > 0.0) {
|
||||
setTimeout(function() { $('#heat').addClass("ds-led-heat-active") }, 0 )
|
||||
setTimeout(function() { $('#heat').removeClass("ds-led-heat-active") }, (x.heat*1000.0)-5)
|
||||
}
|
||||
if (x.heat > 0.0) { $('#heat').addClass("ds-led-heat-active"); } else { $('#heat').removeClass("ds-led-heat-active"); }
|
||||
if (x.cool > 0.5) { $('#cool').addClass("ds-led-cool-active"); } else { $('#cool').removeClass("ds-led-cool-active"); }
|
||||
if (x.air > 0.5) { $('#air').addClass("ds-led-air-active"); } else { $('#air').removeClass("ds-led-air-active"); }
|
||||
if (x.temperature > hazardTemp()) { $('#hazard').addClass("ds-led-hazard-active"); } else { $('#hazard').removeClass("ds-led-hazard-active"); }
|
||||
|
||||
710
public/assets/js/picoreflow_save.js
Normal file
710
public/assets/js/picoreflow_save.js
Normal file
@ -0,0 +1,710 @@
|
||||
var state = "IDLE";
|
||||
var state_last = "";
|
||||
var graph = [ 'profile', 'live'];
|
||||
var points = [];
|
||||
var profiles = [];
|
||||
var time_mode = 0;
|
||||
var selected_profile = 0;
|
||||
var selected_profile_name = 'cone-05-long-bisque.json';
|
||||
var temp_scale = "c";
|
||||
var time_scale_slope = "s";
|
||||
var time_scale_profile = "s";
|
||||
var time_scale_long = "Seconds";
|
||||
var temp_scale_display = "C";
|
||||
var kwh_rate = 0.26;
|
||||
var currency_type = "EUR";
|
||||
|
||||
var protocol = 'ws:';
|
||||
if (window.location.protocol == 'https:') {
|
||||
protocol = 'wss:';
|
||||
}
|
||||
var host = "" + protocol + "//" + window.location.hostname + ":" + window.location.port;
|
||||
var ws_status = new WebSocket(host+"/status");
|
||||
var ws_control = new WebSocket(host+"/control");
|
||||
var ws_config = new WebSocket(host+"/config");
|
||||
var ws_storage = new WebSocket(host+"/storage");
|
||||
|
||||
|
||||
if(window.webkitRequestAnimationFrame) window.requestAnimationFrame = window.webkitRequestAnimationFrame;
|
||||
|
||||
graph.profile =
|
||||
{
|
||||
label: "Profile",
|
||||
data: [],
|
||||
points: { show: false },
|
||||
color: "#75890c",
|
||||
draggable: false
|
||||
};
|
||||
|
||||
graph.live =
|
||||
{
|
||||
label: "Live",
|
||||
data: [],
|
||||
points: { show: false },
|
||||
color: "#d8d3c5",
|
||||
draggable: false
|
||||
};
|
||||
|
||||
|
||||
function updateProfile(id)
|
||||
{
|
||||
selected_profile = id;
|
||||
selected_profile_name = profiles[id].name;
|
||||
var job_seconds = profiles[id].data.length === 0 ? 0 : parseInt(profiles[id].data[profiles[id].data.length-1][0]);
|
||||
var kwh = (3850*job_seconds/3600/1000).toFixed(2);
|
||||
var cost = (kwh*kwh_rate).toFixed(2);
|
||||
var job_time = new Date(job_seconds * 1000).toISOString().substr(11, 8);
|
||||
$('#sel_prof').html(profiles[id].name);
|
||||
$('#sel_prof_eta').html(job_time);
|
||||
$('#sel_prof_cost').html(kwh + ' kWh ('+ currency_type +': '+ cost +')');
|
||||
graph.profile.data = profiles[id].data;
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ] , getOptions());
|
||||
}
|
||||
|
||||
function deleteProfile()
|
||||
{
|
||||
var profile = { "type": "profile", "data": "", "name": selected_profile_name };
|
||||
var delete_struct = { "cmd": "DELETE", "profile": profile };
|
||||
|
||||
var delete_cmd = JSON.stringify(delete_struct);
|
||||
console.log("Delete profile:" + selected_profile_name);
|
||||
|
||||
ws_storage.send(delete_cmd);
|
||||
|
||||
ws_storage.send('GET');
|
||||
selected_profile_name = profiles[0].name;
|
||||
|
||||
state="IDLE";
|
||||
$('#edit').hide();
|
||||
$('#profile_selector').show();
|
||||
$('#btn_controls').show();
|
||||
$('#status').slideDown();
|
||||
$('#profile_table').slideUp();
|
||||
$('#e2').select2('val', 0);
|
||||
graph.profile.points.show = false;
|
||||
graph.profile.draggable = false;
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ], getOptions());
|
||||
}
|
||||
|
||||
|
||||
function updateProgress(percentage)
|
||||
{
|
||||
if(state=="RUNNING")
|
||||
{
|
||||
if(percentage > 100) percentage = 100;
|
||||
$('#progressBar').css('width', percentage+'%');
|
||||
if(percentage>5) $('#progressBar').html(parseInt(percentage)+'%');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#progressBar').css('width', 0+'%');
|
||||
$('#progressBar').html('');
|
||||
}
|
||||
}
|
||||
|
||||
function updateProfileTable()
|
||||
{
|
||||
var dps = 0;
|
||||
var slope = "";
|
||||
var color = "";
|
||||
|
||||
var html = '<h3>Schedule Points</h3><div class="table-responsive" style="scroll: none"><table class="table table-striped">';
|
||||
html += '<tr><th style="width: 50px">#</th><th>Target Time in ' + time_scale_long+ '</th><th>Target Temperature in °'+temp_scale_display+'</th><th>Slope in °'+temp_scale_display+'/'+time_scale_slope+'</th><th></th></tr>';
|
||||
|
||||
for(var i=0; i<graph.profile.data.length;i++)
|
||||
{
|
||||
|
||||
if (i>=1) dps = ((graph.profile.data[i][1]-graph.profile.data[i-1][1])/(graph.profile.data[i][0]-graph.profile.data[i-1][0]) * 10) / 10;
|
||||
if (dps > 0) { slope = "up"; color="rgba(206, 5, 5, 1)"; } else
|
||||
if (dps < 0) { slope = "down"; color="rgba(23, 108, 204, 1)"; dps *= -1; } else
|
||||
if (dps == 0) { slope = "right"; color="grey"; }
|
||||
|
||||
html += '<tr><td><h4>' + (i+1) + '</h4></td>';
|
||||
html += '<td><input type="text" class="form-control" id="profiletable-0-'+i+'" value="'+ timeProfileFormatter(graph.profile.data[i][0],true) + '" style="width: 60px" /></td>';
|
||||
html += '<td><input type="text" class="form-control" id="profiletable-1-'+i+'" value="'+ graph.profile.data[i][1] + '" style="width: 60px" /></td>';
|
||||
html += '<td><div class="input-group"><span class="glyphicon glyphicon-circle-arrow-' + slope + ' input-group-addon ds-trend" style="background: '+color+'"></span><input type="text" class="form-control ds-input" readonly value="' + formatDPS(dps) + '" style="width: 100px" /></div></td>';
|
||||
html += '<td> </td></tr>';
|
||||
}
|
||||
|
||||
html += '</table></div>';
|
||||
|
||||
$('#profile_table').html(html);
|
||||
|
||||
//Link table to graph
|
||||
$(".form-control").change(function(e)
|
||||
{
|
||||
var id = $(this)[0].id; //e.currentTarget.attributes.id
|
||||
var value = parseInt($(this)[0].value);
|
||||
var fields = id.split("-");
|
||||
var col = parseInt(fields[1]);
|
||||
var row = parseInt(fields[2]);
|
||||
|
||||
if (graph.profile.data.length > 0) {
|
||||
if (col == 0) {
|
||||
graph.profile.data[row][col] = timeProfileFormatter(value,false);
|
||||
}
|
||||
else {
|
||||
graph.profile.data[row][col] = value;
|
||||
}
|
||||
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ], getOptions());
|
||||
}
|
||||
updateProfileTable();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function timeProfileFormatter(val, down) {
|
||||
var rval = val
|
||||
switch(time_scale_profile){
|
||||
case "m":
|
||||
if (down) {rval = val / 60;} else {rval = val * 60;}
|
||||
break;
|
||||
case "h":
|
||||
if (down) {rval = val / 3600;} else {rval = val * 3600;}
|
||||
break;
|
||||
}
|
||||
return Math.round(rval);
|
||||
}
|
||||
|
||||
function formatDPS(val) {
|
||||
var tval = val;
|
||||
if (time_scale_slope == "m") {
|
||||
tval = val * 60;
|
||||
}
|
||||
if (time_scale_slope == "h") {
|
||||
tval = (val * 60) * 60;
|
||||
}
|
||||
return Math.round(tval);
|
||||
}
|
||||
|
||||
function hazardTemp(){
|
||||
|
||||
if (temp_scale == "f") {
|
||||
return (1500 * 9 / 5) + 32
|
||||
}
|
||||
else {
|
||||
return 1500
|
||||
}
|
||||
}
|
||||
|
||||
function timeTickFormatter(val)
|
||||
{
|
||||
if (val < 1800)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
var hours = Math.floor(val / (3600));
|
||||
var div_min = val % (3600);
|
||||
var minutes = Math.floor(div_min / 60);
|
||||
|
||||
if (hours < 10) {hours = "0"+hours;}
|
||||
if (minutes < 10) {minutes = "0"+minutes;}
|
||||
|
||||
return hours+":"+minutes;
|
||||
}
|
||||
}
|
||||
|
||||
function runTask()
|
||||
{
|
||||
var cmd =
|
||||
{
|
||||
"cmd": "RUN",
|
||||
"profile": profiles[selected_profile]
|
||||
}
|
||||
|
||||
graph.live.data = [];
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ] , getOptions());
|
||||
|
||||
ws_control.send(JSON.stringify(cmd));
|
||||
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
var cmd = {"cmd": "STOP"};
|
||||
ws_control.send(JSON.stringify(cmd));
|
||||
}
|
||||
|
||||
function enterNewMode()
|
||||
{
|
||||
state="EDIT"
|
||||
$('#status').slideUp();
|
||||
$('#edit').show();
|
||||
$('#profile_selector').hide();
|
||||
$('#btn_controls').hide();
|
||||
$('#form_profile_name').attr('value', '');
|
||||
$('#form_profile_name').attr('placeholder', 'Please enter a name');
|
||||
graph.profile.points.show = true;
|
||||
graph.profile.draggable = true;
|
||||
graph.profile.data = [];
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ], getOptions());
|
||||
updateProfileTable();
|
||||
}
|
||||
|
||||
function enterEditMode()
|
||||
{
|
||||
state="EDIT"
|
||||
$('#status').slideUp();
|
||||
$('#edit').show();
|
||||
$('#profile_selector').hide();
|
||||
$('#btn_controls').hide();
|
||||
console.log(profiles);
|
||||
$('#form_profile_name').val(profiles[selected_profile].name);
|
||||
graph.profile.points.show = true;
|
||||
graph.profile.draggable = true;
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ], getOptions());
|
||||
updateProfileTable();
|
||||
}
|
||||
|
||||
function leaveEditMode()
|
||||
{
|
||||
selected_profile_name = $('#form_profile_name').val();
|
||||
ws_storage.send('GET');
|
||||
state="IDLE";
|
||||
$('#edit').hide();
|
||||
$('#profile_selector').show();
|
||||
$('#btn_controls').show();
|
||||
$('#status').slideDown();
|
||||
$('#profile_table').slideUp();
|
||||
graph.profile.points.show = false;
|
||||
graph.profile.draggable = false;
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ], getOptions());
|
||||
}
|
||||
|
||||
function newPoint()
|
||||
{
|
||||
if(graph.profile.data.length > 0)
|
||||
{
|
||||
var pointx = parseInt(graph.profile.data[graph.profile.data.length-1][0])+15;
|
||||
}
|
||||
else
|
||||
{
|
||||
var pointx = 0;
|
||||
}
|
||||
graph.profile.data.push([pointx, Math.floor((Math.random()*230)+25)]);
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ], getOptions());
|
||||
updateProfileTable();
|
||||
}
|
||||
|
||||
function delPoint()
|
||||
{
|
||||
graph.profile.data.splice(-1,1)
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ], getOptions());
|
||||
updateProfileTable();
|
||||
}
|
||||
|
||||
function toggleTable()
|
||||
{
|
||||
if($('#profile_table').css('display') == 'none')
|
||||
{
|
||||
$('#profile_table').slideDown();
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#profile_table').slideUp();
|
||||
}
|
||||
}
|
||||
|
||||
function saveProfile()
|
||||
{
|
||||
name = $('#form_profile_name').val();
|
||||
var rawdata = graph.plot.getData()[0].data
|
||||
var data = [];
|
||||
var last = -1;
|
||||
|
||||
for(var i=0; i<rawdata.length;i++)
|
||||
{
|
||||
if(rawdata[i][0] > last)
|
||||
{
|
||||
data.push([rawdata[i][0], rawdata[i][1]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$.bootstrapGrowl("<span class=\"glyphicon glyphicon-exclamation-sign\"></span> <b>ERROR 88:</b><br/>An oven is not a time-machine", {
|
||||
ele: 'body', // which element to append to
|
||||
type: 'alert', // (null, 'info', 'error', 'success')
|
||||
offset: {from: 'top', amount: 250}, // 'top', or 'bottom'
|
||||
align: 'center', // ('left', 'right', or 'center')
|
||||
width: 385, // (integer, or 'auto')
|
||||
delay: 5000,
|
||||
allow_dismiss: true,
|
||||
stackup_spacing: 10 // spacing between consecutively stacked growls.
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
last = rawdata[i][0];
|
||||
}
|
||||
|
||||
var profile = { "type": "profile", "data": data, "name": name }
|
||||
var put = { "cmd": "PUT", "profile": profile }
|
||||
|
||||
var put_cmd = JSON.stringify(put);
|
||||
|
||||
ws_storage.send(put_cmd);
|
||||
|
||||
leaveEditMode();
|
||||
}
|
||||
|
||||
function getOptions()
|
||||
{
|
||||
|
||||
var options =
|
||||
{
|
||||
|
||||
series:
|
||||
{
|
||||
lines:
|
||||
{
|
||||
show: true
|
||||
},
|
||||
|
||||
points:
|
||||
{
|
||||
show: true,
|
||||
radius: 5,
|
||||
symbol: "circle"
|
||||
},
|
||||
|
||||
shadowSize: 3
|
||||
|
||||
},
|
||||
|
||||
xaxis:
|
||||
{
|
||||
min: 0,
|
||||
tickColor: 'rgba(216, 211, 197, 0.2)',
|
||||
tickFormatter: timeTickFormatter,
|
||||
font:
|
||||
{
|
||||
size: 14,
|
||||
lineHeight: 14, weight: "normal",
|
||||
family: "Digi",
|
||||
variant: "small-caps",
|
||||
color: "rgba(216, 211, 197, 0.85)"
|
||||
}
|
||||
},
|
||||
|
||||
yaxis:
|
||||
{
|
||||
min: 0,
|
||||
tickDecimals: 0,
|
||||
draggable: false,
|
||||
tickColor: 'rgba(216, 211, 197, 0.2)',
|
||||
font:
|
||||
{
|
||||
size: 14,
|
||||
lineHeight: 14,
|
||||
weight: "normal",
|
||||
family: "Digi",
|
||||
variant: "small-caps",
|
||||
color: "rgba(216, 211, 197, 0.85)"
|
||||
}
|
||||
},
|
||||
|
||||
grid:
|
||||
{
|
||||
color: 'rgba(216, 211, 197, 0.55)',
|
||||
borderWidth: 1,
|
||||
labelMargin: 10,
|
||||
mouseActiveRadius: 50
|
||||
},
|
||||
|
||||
legend:
|
||||
{
|
||||
show: false
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
|
||||
if(!("WebSocket" in window))
|
||||
{
|
||||
$('#chatLog, input, button, #examples').fadeOut("fast");
|
||||
$('<p>Oh no, you need a browser that supports WebSockets. How about <a href="http://www.google.com/chrome">Google Chrome</a>?</p>').appendTo('#container');
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Status Socket ////////////////////////////////
|
||||
|
||||
ws_status.onopen = function()
|
||||
{
|
||||
console.log("Status Socket has been opened");
|
||||
|
||||
$.bootstrapGrowl("<span class=\"glyphicon glyphicon-exclamation-sign\"></span>Getting data from server",
|
||||
{
|
||||
ele: 'body', // which element to append to
|
||||
type: 'success', // (null, 'info', 'error', 'success')
|
||||
offset: {from: 'top', amount: 250}, // 'top', or 'bottom'
|
||||
align: 'center', // ('left', 'right', or 'center')
|
||||
width: 385, // (integer, or 'auto')
|
||||
delay: 2500,
|
||||
allow_dismiss: true,
|
||||
stackup_spacing: 10 // spacing between consecutively stacked growls.
|
||||
});
|
||||
};
|
||||
|
||||
ws_status.onclose = function()
|
||||
{
|
||||
$.bootstrapGrowl("<span class=\"glyphicon glyphicon-exclamation-sign\"></span> <b>ERROR 1:</b><br/>Status Websocket not available", {
|
||||
ele: 'body', // which element to append to
|
||||
type: 'error', // (null, 'info', 'error', 'success')
|
||||
offset: {from: 'top', amount: 250}, // 'top', or 'bottom'
|
||||
align: 'center', // ('left', 'right', or 'center')
|
||||
width: 385, // (integer, or 'auto')
|
||||
delay: 5000,
|
||||
allow_dismiss: true,
|
||||
stackup_spacing: 10 // spacing between consecutively stacked growls.
|
||||
});
|
||||
};
|
||||
|
||||
ws_status.onmessage = function(e)
|
||||
{
|
||||
console.log("received status data")
|
||||
console.log(e.data);
|
||||
|
||||
x = JSON.parse(e.data);
|
||||
if (x.type == "backlog")
|
||||
{
|
||||
if (x.profile)
|
||||
{
|
||||
selected_profile_name = x.profile.name;
|
||||
$.each(profiles, function(i,v) {
|
||||
if(v.name == x.profile.name) {
|
||||
updateProfile(i);
|
||||
$('#e2').select2('val', i);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.each(x.log, function(i,v) {
|
||||
graph.live.data.push([v.runtime, v.temperature]);
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ] , getOptions());
|
||||
});
|
||||
}
|
||||
|
||||
if(state!="EDIT")
|
||||
{
|
||||
state = x.state;
|
||||
|
||||
if (state!=state_last)
|
||||
{
|
||||
if(state_last == "RUNNING")
|
||||
{
|
||||
$('#target_temp').html('---');
|
||||
updateProgress(0);
|
||||
$.bootstrapGrowl("<span class=\"glyphicon glyphicon-exclamation-sign\"></span> <b>Run completed</b>", {
|
||||
ele: 'body', // which element to append to
|
||||
type: 'success', // (null, 'info', 'error', 'success')
|
||||
offset: {from: 'top', amount: 250}, // 'top', or 'bottom'
|
||||
align: 'center', // ('left', 'right', or 'center')
|
||||
width: 385, // (integer, or 'auto')
|
||||
delay: 0,
|
||||
allow_dismiss: true,
|
||||
stackup_spacing: 10 // spacing between consecutively stacked growls.
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(state=="RUNNING")
|
||||
{
|
||||
$("#nav_start").hide();
|
||||
$("#nav_stop").show();
|
||||
|
||||
graph.live.data.push([x.runtime, x.temperature]);
|
||||
graph.plot = $.plot("#graph_container", [ graph.profile, graph.live ] , getOptions());
|
||||
|
||||
left = parseInt(x.totaltime-x.runtime);
|
||||
eta = new Date(left * 1000).toISOString().substr(11, 8);
|
||||
|
||||
updateProgress(parseFloat(x.runtime)/parseFloat(x.totaltime)*100);
|
||||
$('#state').html('<span class="glyphicon glyphicon-time" style="font-size: 22px; font-weight: normal"></span><span style="font-family: Digi; font-size: 40px;">' + eta + '</span>');
|
||||
$('#target_temp').html(parseInt(x.target));
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#nav_start").show();
|
||||
$("#nav_stop").hide();
|
||||
$('#state').html('<p class="ds-text">'+state+'</p>');
|
||||
}
|
||||
|
||||
$('#act_temp').html(parseInt(x.temperature));
|
||||
|
||||
if (x.heat > 0.0) {
|
||||
setTimeout(function() { $('#heat').addClass("ds-led-heat-active") }, 0 )
|
||||
setTimeout(function() { $('#heat').removeClass("ds-led-heat-active") }, (x.heat*1000.0)-5)
|
||||
}
|
||||
if (x.cool > 0.5) { $('#cool').addClass("ds-led-cool-active"); } else { $('#cool').removeClass("ds-led-cool-active"); }
|
||||
if (x.air > 0.5) { $('#air').addClass("ds-led-air-active"); } else { $('#air').removeClass("ds-led-air-active"); }
|
||||
if (x.temperature > hazardTemp()) { $('#hazard').addClass("ds-led-hazard-active"); } else { $('#hazard').removeClass("ds-led-hazard-active"); }
|
||||
if ((x.door == "OPEN") || (x.door == "UNKNOWN")) { $('#door').addClass("ds-led-door-open"); } else { $('#door').removeClass("ds-led-door-open"); }
|
||||
|
||||
state_last = state;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Config Socket /////////////////////////////////
|
||||
|
||||
ws_config.onopen = function()
|
||||
{
|
||||
ws_config.send('GET');
|
||||
};
|
||||
|
||||
ws_config.onmessage = function(e)
|
||||
{
|
||||
console.log (e.data);
|
||||
x = JSON.parse(e.data);
|
||||
temp_scale = x.temp_scale;
|
||||
time_scale_slope = x.time_scale_slope;
|
||||
time_scale_profile = x.time_scale_profile;
|
||||
kwh_rate = x.kwh_rate;
|
||||
currency_type = x.currency_type;
|
||||
|
||||
if (temp_scale == "c") {temp_scale_display = "C";} else {temp_scale_display = "F";}
|
||||
|
||||
|
||||
$('#act_temp_scale').html('º'+temp_scale_display);
|
||||
$('#target_temp_scale').html('º'+temp_scale_display);
|
||||
|
||||
switch(time_scale_profile){
|
||||
case "s":
|
||||
time_scale_long = "Seconds";
|
||||
break;
|
||||
case "m":
|
||||
time_scale_long = "Minutes";
|
||||
break;
|
||||
case "h":
|
||||
time_scale_long = "Hours";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Control Socket ////////////////////////////////
|
||||
|
||||
ws_control.onopen = function()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
ws_control.onmessage = function(e)
|
||||
{
|
||||
//Data from Simulation
|
||||
console.log ("control socket has been opened")
|
||||
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 ///////////////////////////////
|
||||
|
||||
ws_storage.onopen = function()
|
||||
{
|
||||
ws_storage.send('GET');
|
||||
};
|
||||
|
||||
|
||||
ws_storage.onmessage = function(e)
|
||||
{
|
||||
message = JSON.parse(e.data);
|
||||
|
||||
if(message.resp)
|
||||
{
|
||||
if(message.resp == "FAIL")
|
||||
{
|
||||
if (confirm('Overwrite?'))
|
||||
{
|
||||
message.force=true;
|
||||
console.log("Sending: " + JSON.stringify(message));
|
||||
ws_storage.send(JSON.stringify(message));
|
||||
}
|
||||
else
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//the message is an array of profiles
|
||||
//FIXME: this should be better, maybe a {"profiles": ...} container?
|
||||
profiles = message;
|
||||
//delete old options in select
|
||||
$('#e2').find('option').remove().end();
|
||||
// check if current selected value is a valid profile name
|
||||
// if not, update with first available profile name
|
||||
var valid_profile_names = profiles.map(function(a) {return a.name;});
|
||||
if (
|
||||
valid_profile_names.length > 0 &&
|
||||
$.inArray(selected_profile_name, valid_profile_names) === -1
|
||||
) {
|
||||
selected_profile = 0;
|
||||
selected_profile_name = valid_profile_names[0];
|
||||
}
|
||||
|
||||
// fill select with new options from websocket
|
||||
for (var i=0; i<profiles.length; i++)
|
||||
{
|
||||
var profile = profiles[i];
|
||||
//console.log(profile.name);
|
||||
$('#e2').append('<option value="'+i+'">'+profile.name+'</option>');
|
||||
|
||||
if (profile.name == selected_profile_name)
|
||||
{
|
||||
selected_profile = i;
|
||||
$('#e2').select2('val', i);
|
||||
updateProfile(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$("#e2").select2(
|
||||
{
|
||||
placeholder: "Select Profile",
|
||||
allowClear: true,
|
||||
minimumResultsForSearch: -1
|
||||
});
|
||||
|
||||
|
||||
$("#e2").on("change", function(e)
|
||||
{
|
||||
updateProfile(e.val);
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
1
storage/profiles/B05 BQ1000 .json
Normal file
1
storage/profiles/B05 BQ1000 .json
Normal file
@ -0,0 +1 @@
|
||||
{"type": "profile", "data": [[0, 30], [2520, 120], [6120, 120], [23400, 945], [26700, 1000], [27600, 1000]], "name": "B05 BQ1000 "}
|
||||
1
storage/profiles/C6 drop and soak DF.json
Normal file
1
storage/profiles/C6 drop and soak DF.json
Normal file
@ -0,0 +1 @@
|
||||
{"type": "profile", "data": [[0, 30], [7200, 121], [16800, 121], [36000, 1148], [39360, 1204], [39960, 1204], [40380, 1148], [42180, 1148]], "name": "C6 drop and soak DF"}
|
||||
1
storage/profiles/lizzy .json
Normal file
1
storage/profiles/lizzy .json
Normal file
@ -0,0 +1 @@
|
||||
{"type": "profile", "data": [[0, 125], [240, 130], [360, 150], [2400, 600]], "name": "lizzy "}
|
||||
1
storage/profiles/marcTestRun (Low).json
Normal file
1
storage/profiles/marcTestRun (Low).json
Normal file
@ -0,0 +1 @@
|
||||
{"type": "profile", "data": [[0, 175], [300, 175], [600, 225], [900, 225], [1200, 250], [1500, 250]], "name": "marcTestRun (Low)"}
|
||||
36
tempTest1.py
Normal file
36
tempTest1.py
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
import board
|
||||
import digitalio
|
||||
import adafruit_max31856
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
|
||||
# Create sensor object, communicating over the board's default SPI bus
|
||||
spi = board.SPI()
|
||||
|
||||
# allocate a CS pin and set the direction
|
||||
cs = digitalio.DigitalInOut(board.D5)
|
||||
cs.direction = digitalio.Direction.OUTPUT
|
||||
|
||||
# create a thermocouple object with the above
|
||||
thermocouple = adafruit_max31856.MAX31856(spi, cs)
|
||||
|
||||
# print the temperature!
|
||||
print(thermocouple.temperature)
|
||||
|
||||
relay1 = 23
|
||||
relay2 = 24
|
||||
trigger1 = 20
|
||||
trigger2 = 21
|
||||
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(relay1, GPIO.OUT)
|
||||
GPIO.setup(relay2, GPIO.OUT)
|
||||
GPIO.setup(trigger1, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||||
GPIO.setup(trigger2, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||||
|
||||
GPIO.output(relay1, 1) #OFF
|
||||
|
||||
while True:
|
||||
print(thermocouple.temperature)
|
||||
time.sleep(5)
|
||||
Loading…
Reference in New Issue
Block a user