From 13731198f3960665eb563d1f5935c915ceca3419 Mon Sep 17 00:00:00 2001
From: Torben Petersen <petersen@ibr.cs.tu-bs.de>
Date: Mon, 7 Jan 2019 13:11:07 +0100
Subject: [PATCH] Adds new class to emulate temperature flow

---
 modules/chambercontroller.py                  |   2 +-
 util/__pycache__/chamber_flow.cpython-36.pyc  | Bin 0 -> 3448 bytes
 .../temp_flow_controller.cpython-36.pyc       | Bin 0 -> 3445 bytes
 util/temp_flow_controller.py                  | 105 ++++++++++++++++++
 4 files changed, 106 insertions(+), 1 deletion(-)
 create mode 100644 util/__pycache__/chamber_flow.cpython-36.pyc
 create mode 100644 util/__pycache__/temp_flow_controller.cpython-36.pyc
 create mode 100644 util/temp_flow_controller.py

diff --git a/modules/chambercontroller.py b/modules/chambercontroller.py
index ebc2cee..65a2248 100644
--- a/modules/chambercontroller.py
+++ b/modules/chambercontroller.py
@@ -445,7 +445,7 @@ class ChamberController(Module):
                         logger.debug( "target: {} ambient: {} chamber: {}".format( self.target_temp, self.ambient_temp, self.chamber_temp ) )
                         start = time.time()
                         # When the controller sets the the temp to none, this might throw an exception
-                        self.control_tick_pid(protocol)
+                        self.control_tick_pid(protocol) #temp is set here
                         diff = time.time() - start
                         if diff < 1.0:
                             time.sleep(1.0 - diff)
diff --git a/util/__pycache__/chamber_flow.cpython-36.pyc b/util/__pycache__/chamber_flow.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c33378854085a1dac1156e0590cb0563f25c534d
GIT binary patch
literal 3448
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
PtlDE2{&4l(u-X3sX<0J9

literal 0
HcmV?d00001

diff --git a/util/__pycache__/temp_flow_controller.cpython-36.pyc b/util/__pycache__/temp_flow_controller.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..67055a2928df8f85035fd89920d37c0d93033bfa
GIT binary patch
literal 3445
zcmaJ@TW=f372eqkxui&$lIU9@J4~7sp;1$D?6yJcwsIUMbsH;!OIPhC>0-4r;zi3{
zYIYb~Ed3H1MNz<jpZe54(3hgWXP*k>NiY2Ye(HB-Ny!rAP}(zRXU@!?%bf3=+tq6M
z)!o})-KiPIcgAZ!8~i4o^zR_t;4Cr*Y+!np=56qf=V-p*74%s2ih6WC7o!=KhGnnJ
zjL!^iar?Q!?V0H<i3)f2P5D=`G&8)as1BBA1~Yhp7rEQDybHX<%X|r3jaR%Ctgng-
zq9#^m7Npqkjb`--`WRbHmO1TjM65!3UHp!f{u^e5;W2J_CTCFE^lWZHVH?Ui!n%x4
zUN*d<aG^#?lm|<^C@O>M%)pAvOD{}snG|_$K&1+=Vyy9HegWeOukjU(tNc1&<Mrpv
zTjLkIj9=O_`DK0u?{)qbU+34rUF54!xslbC7>@kCD0$+CNvvcNMMA!Eqfmu6!w+tC
zbN%1loHPIZ^_=<h=A@AJ)Q7h=Ce8+(;jM+eV7M#fYv=f#rs<W!s1I-WeePAmNCdH;
ziZtyfaY#O)pM!_^`*_k0$kZAbQv?;^xU0;8#TjN0q_5aBTRBr3YlSPujA1P98*&??
zJ19}O;<_qxbFf76bjr+}F@(o}t=3k?_+<6VB=(0;An1y(8-IC*|7OK=R5I#^+12~M
zx%cqn_9MU3ez@I!bg%RHQQPl)vHjqFR!Ef`hsrCA<53Xqd&N<37$pJEtYA0IRy+3|
zeb(;0zAtk=X@B0im#vX=gbdVJ3SWvK><Mg2h02_f?8hoA>?Lv-sHT(IsfhNnLhi53
z9j8L_Kn0mKOuLy)=lsi%b@=DigN<Q74LAC`a-)|F#l}b|AyW}=bo&a?NY$?3H`8QK
zJqe`P7^{AyV{|sot<hmtKJmvT@_!k`U=>zlbyhJaZ=H8PS|@vsgGd3i@aQ0}f>Fqd
z0RlH;$00Dca{qHEpTw~U6@{Q_$|~gLGDy>w7l=pB8*&9CGi9i4&dEiZs^aq}M_k8L
zYJwPS^3I#IJrNJ-w$bm@ty{+gDNL$PNo`|ba+6yx%=zuHw<h(u&Vo16afmClH;$qs
z`Z7}9I!Mx{r48{)>3BB{Wgp2<pjGFrP0n5vbW?d5i)U@4aLm8+HkMPJBg|!Q4#ZqK
z)Gojl8p$>th!4TQ7UU9g2sQyj@F-*lx29}na+^CZ0AN^i1_cdxlq-d;i91i{MSe><
zQ(gsWGWi1<iaJVJaWvkI`e`q#EV5_o-ov&mLd3HvSL71d%%R+uh_#OI8m7*g?jk9C
z3gCNKoE!cwn_N3LrVH7vQ+AW>+U^FJDKK{5l63{^VJjjVyTl(`$+n=5R?dDB^wnH9
zuc-P%k&M+@{VtM_k8IUSE^@g^%2JpOL<tFV<6L#m-6|P&eR`Zh<Y2nr+JJvxO&eg!
zT7EIVMJ~Z0Q?4ua%u?nQ&;|;_0D+%By?$oqw^IU64Sxr%9pfc?`tj6y$>d9%YF<Ua
zef#hZg&mKruRTC@P@Ea*x60+nTDYqQ&K{I<37Xk4;&t0l<^8h!4+GpXL!r{r%Abtb
z{G$PR2l7artC*#EwKS+K-tngO<%NA)Za@9Es`5fUGc!LizWyh`-Q`8>hdztF+$C<x
zruJOtpPr}lOO}50y;@(-wTAt@@6(&Ua`Nq|nZGmR;D0;D!S+sGNJ?9iYn`5GP@vOB
zAZ2ja2!mKPc10sjV)3?)YgX($c-a2pac5HNK(H}~{+|QzCiOHDV${G@q6(A>q%cp9
z=r&9W{l+gbc|<VWT+YgW2%@oQOPNT|*$bjnWL6~NtPqSwBIdFLG1(wO_gE5SoPcSz
z@;h<3n*@?Sh*2Npc%)E9aJfB4E08%dh`VBrPnn|)%F24J1F<x-qa+z+tbaBYs*Ci~
z6=efoO*cU(1?bO4^;l)gW|@_liKM`2*4Z-tXtsjNvW%5{t)kazdhHGPed=Sc))&1=
ziyy`<l)zS)w$%9MZrbAF=u6<v5oOXToTmw$R=T@D|KJ1bagnH}0v_UBqvHUWh@e}*
z{Tvgi(=dIalqRN6w4ganDP2zL!|8sgX=e5)kt!?gBi2FG|3)-jNySPR1&y6vaSq;+
z>W`%QE3bffW%9e9sz9PI(1@AYy#y`D9TNEoiBuNtRvZk)+4$7-)<q#fueF0MDHT|Q
z6<Ez&)$T8|$$RIb)!E%mAf+vDVYj4$B5xC+%GA7+xxP;t_<mOQ{b9n#5%Cq@KNts5
zzLHz5uPR+@`9mTEnUe5&j=-a!mw1Kyx>rQEm4y33c}rcP$Zl<;?g@^4l)J1!2fRb%
z10p{oLLJg;gdkN~Ak<`}<Y>B}`CkRzxMaGnYq_>-mkYJ`wImre4EnL}&%50pE&AX0
z7tD=KT?>y~oOeW3vC~}hYGg!fc%W1(Z{j?gUh;0{7ZCDRP9)}KQ(nWoyg}qH5nVS+
zst3H_{kWUEh}4%Kfn+wd>badirpcQ`T12!1&apjn@8)6o6=gw6rMrUuF3;48wfxwH
K6I^{EZ1#VCBQl2o

literal 0
HcmV?d00001

diff --git a/util/temp_flow_controller.py b/util/temp_flow_controller.py
new file mode 100644
index 0000000..7ba85a5
--- /dev/null
+++ b/util/temp_flow_controller.py
@@ -0,0 +1,105 @@
+
+
+#!/usr/bin/env python3
+
+import paho.mqtt.client as paho
+import paho.mqtt.publish as publish
+import time
+import socket
+import struct
+from threading import Event
+
+
+class temp_flow_controller:
+    CHAMBER_NAME = "lctc-c01"
+    TARGET_TEMPERATURE = 10.0
+    DELTA = 0.5
+    TIMEOUT = 120.0
+    CHAMBER_TEMPERATURE_TOPIC = "sht21/"+CHAMBER_NAME+"/temp"
+    temperature_reached = Event() #set event flag to false
+    client = paho.Client(client_id="chamber_controller_" + socket.gethostname(), clean_session=True)
+
+    def on_message(self, client, userdata, msg):
+        if msg.topic == self.CHAMBER_TEMPERATURE_TOPIC:
+            temp, = struct.unpack("d", msg.payload)
+            if abs( temp - self.TARGET_TEMPERATURE ) < self.DELTA:
+                self.temperature_reached.set() #set the event flag to true
+        else:
+            print("[on_message] {} {}".format(msg.payload, msg.topic) )
+
+    def on_disconnect(self, client, userdata, rc):
+        print("[on_disconnect] {}".format( rc ))
+
+    def on_connect(self, client, userdata, flags, rc):
+        print("connected sucessfull")
+        client.subscribe(self.CHAMBER_TEMPERATURE_TOPIC, qos=2)
+
+    def set_temp(self,temp):
+        self.client.publish("chamber/"+self.CHAMBER_NAME+"/temp", struct.pack("d", temp), qos=2)
+        self.temperature_reached.clear() #Set Event flag to false and Block until set is called
+
+    def wait_for_temp_reached(self, timeout = None):
+        if(timeout != None):
+            temperature_reached.wait(timeout)
+        else:
+            temperature_reached.wait()
+
+    def set_temp_flow(self, temps, sleepTimes=[0], loop=False):
+        if temps == None:
+            raise ValueError('The temps array cant be none!')
+        if loop == None:
+            loop = false
+        if len(sleepTimes) < len(temps):
+            while len(sleepTimes) < len(temps):
+                sleepTimes.append(0)         
+
+        while loop:
+            self.TARGET_TEMPERATURE = temps[0]
+            try:
+                self.set_temp( self.TARGET_TEMPERATURE )
+                # Wait until temperature has been reached
+                if not self.temperature_reached.wait(): #wait until flag is set or TIMEOUT
+                    print("TIMEOUT")
+                else:
+                    print("Temp reached: {}".format(self.TARGET_TEMPERATURE))
+            except KeyboardInterrupt:
+                set_temp( None )
+            print("sleep for {} seconds".format(sleepTimes[0]))
+            time.sleep(sleepTimes[0])
+
+            if len(temps) > 1:
+                for i in range(1,len(temps)):
+                    print("i = {}".format(i))
+                    time.sleep(10)
+                    self.TARGET_TEMPERATURE = temps[i]
+                    try:
+                        self.set_temp( self.TARGET_TEMPERATURE )
+                        # Wait until temperature has been reached
+                        if not self.temperature_reached.wait(): #wait until flag is set or TIMEOUT
+                            print("TIMEOUT")
+                        else:
+                            print("Temp reached: {}".format( self.TARGET_TEMPERATURE))
+                    except KeyboardInterrupt:
+                        set_temp( None )
+                    print("sleep for {} seconds".format(sleepTimes[i]))
+                    time.sleep(sleepTimes[i])
+
+    def start_connection(self, host = "lctc-c01.dyn.ibr.cs.tu-bs.de", port=1883, keepalive=5, chamber_name = "lctc-c01"):
+        self.CHAMBER_NAME = chamber_name
+        self.CHAMBER_TEMPERATURE_TOPIC = "sht21/"+self.CHAMBER_NAME+"/temp"
+
+        self.client.connect( host, port=port, keepalive=keepalive )
+        self.client.on_connect = self.on_connect
+        self.client.on_message = self.on_message
+        self.client.on_disconnect = self.on_disconnect
+        self.client.loop_start()
+
+
+if __name__ == "__main__":
+    flow = temp_flow_controller()
+    flow.start_connection()
+    temps = [11.0, 12.0, 13.0]  #temp Points that should be reached
+    sleepTimes = [2, 8, 25]     #sleepTimes for each targetTemp
+    loop = True                 #repeat again
+    flow.set_temp_flow(temps, sleepTimes, loop)
+
-- 
GitLab