2017-08-21 45 views
0

我在MIT APP Inventor中開發了一款簡單的應用程序,用於控制熱泵熱水器。NodeMcu Lua從服務器中的應用程序接收信息

應用程序爲每個按鈕發送一個不同的字符串,並且NodeMcu驗證按下了哪個按鈕,如下面的代碼中所示。

srv=net.createServer(net.TCP) 
srv:listen(80,function(conn) 

conn:on("receive", function(client,request) 
    local buf = "" 
    local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP") 
    if(method == nil)then 
     _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP") 
    end 
    local _GET = {} 
    if (vars ~= nil)then 
     for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do 
      _GET[k] = v 
     end 
    end 
    local _on,_off = "","" 

    if(_GET.pin == "ip")then 
     local ip=wifi.sta.getip() 
     local ler_ip=string.sub(ip,1,13) 
     dofile("novolcd.lua").cls() 
     dofile("novolcd.lua").lcdprint("IP="..ler_ip) 
    elseif(_GET.pin == "05a60")then 
     sp_temperaturas[5]=60 

    elseif(_GET.pin == "06a60")then 
     sp_temperaturas[6]=60 

    elseif(_GET.pin == "Ferias")then 
     dofile("novolcd.lua").cls() 
     dofile("novolcd.lua").lcdprint(" Modo ferias ") 
     modo_ferias() 

    elseif(_GET.pin == "Parar2")then 
     dofile("novolcd.lua").cls() 
     dofile("novolcd.lua").lcdprint(" Parar") 
    end 

end) 
conn:on("sent", function (c) c:close() end) 
    end) 

當按下按鈕「Ferias」時,系統通過調用函數modo_ferias()來啓動加熱過程。

 function aquecer() 

     local kp=100/10 
     local ki=5 
     local kd=5 
     local tempo_on=0 
     local tempo_off=0 
     i=0 
     local duty=0    
     erro=sp_temp-t_atual 
     soma_erro = soma_erro + erro/5; 
     dif_erro = (erro - erro_ant)/5; 
     erro_ant = erro; 
     print(erro.."   "..soma_erro.." "..dif_erro) 
     duty= kp * erro + soma_erro/ki + dif_erro * kd 
     print(duty) 

     tempo_on= duty *50 
     if (tempo_on > 5000) then 
      tempo_on = 5000 
     end 

     tempo_off = 5000 - tempo_on 

     repeat 
      i = i + 1 
      tmr.delay(1000) 
     until (i >= tempo_off)    

     gpio.write(8, gpio.HIGH) 

     repeat 
      i = i + 1  
      tmr.delay(1000)  
     until (i == 5000) 

     gpio.mode(8, gpio.INPUT) 

    end 

    function modo_ferias() 

     repeat    
      sair_ferias=0 
      pressao() 
      if (pressao_psi <=3) 
       sair_ferias=1 
      end 
      t_atual=ler_temperatura() 
      local int = string.format("%d", t_atual) -- parte inteira 
      local dec = string.format("%.1d", t_atual % 10000) -- parte decimal com uma casa 
      t_display = int .. "." .. dec 
      rtc() 
      dofile("novolcd.lua").cls() 
      dofile("novolcd.lua").lcdprint("Temp="..t_display.." ST="..sp_temp..data_horas) 
      sp_temp=40 
      local horas_ferias=hour 
      if(horas_ferias==0 or horas_ferias==1 or horas_ferias==2 or horas_ferias==3 or horas_ferias==4 or horas_ferias==5 or horas_ferias==6) then 
      sp_temp=70 
      end 
      if (sp_temp>t_atual) then 
       aquecer() 

      end 
     until (sair_ferias==1)  
    end 

這裏是我的問題出現的地方。如果我在按下「Ferias」按鈕後按下按鈕,NodeMcu將不會知道它,因爲程序處於加熱功能並且不驗證應用是否發送任何指令。

有什麼方法可以收聽應用程序命令並同時進行加熱過程嗎?

+0

問題是你的函數'aquecer()'不會放棄控制權。 'tmr.delay()'是一個繁忙的循環,沒有其他東西可以同時運行(比如你的TCP服務器)。您需要重寫代碼才能使用僅有一個主循環的事件。例如,讓TCP處理程序設置一個全局標誌來指示按下按鈕。當執行主循環時,全局標誌由主函數讀取。 – ktb

回答

0

有幾件事情

全局狀態

因爲程序是在加熱功能,如果應用程序sended任何指令

如果觸發命令不驗證通過按各個按鈕可以使而不是彼此獨立運行,那麼你需要某種形式的全局狀態t o確保他們不會干涉。

繁忙的循環

repeat 
    i = i + 1 
    tmr.delay(1000) 
until (i == 5000) 

This is a no-go與NodeMCU,因爲它本質上是一個一站式的世界繁忙的循環。此外,tmr.delayscheduled to be removed,因爲它經常被濫用。

任務發佈

node.task.post是「在不久的將來」可能的解決方案來執行計劃任務。你可以使用它來從on-receive回調中發佈任務,而不是同步執行它們。

+0

首先感謝您的幫助。 爲了真誠我試圖理解noed.task.post解決方案,但沒有退出。我不明白如何將服務器定義爲高優先級,以及如何關聯監聽部分和加熱部分。 便無法工作,這對聆聽音樂,同時在循環 I = I + 1 tmr.delay(1000) 直到(我== 5000) 例如把浣熊在這裏?我也嘗試使用tmr.alarm()來解決問題,但最初的問題發生。 有沒有辦法使用計時器返回到服務器4秒鐘,然後回到加熱? –

相關問題