2015-02-01 9 views
0

이 내용을 제대로 설명하지 않은 경우 제 질문을 수정하는 데 도움이됩니다. 내 질문은 Java 타이머와 관련이 있거나 일반적인 문제 해결과 관련 될 수 있습니다.자바 타이머를 사용하여 마지막 작업을 제외한 모든 작업을 빨리 종료하는 방법

독자 여러분, OpenHAB이 무엇인지, OpenHAB 규칙이 무엇인지, MQTT가하는 일을 이해할 필요가 없습니다. 하지만 어쨌든 내 질문의 현장을 설정하기 위해이 용어를 사용할 것입니다.

OpenHAB에는 MQTT 주제에 게시 된 메시지에 응답하는 규칙이 있습니다. 빛 조광기를 작동 시키면 MQTT 메시지가 브로커로 전송됩니다. 각 메시지는 OpenHAB 규칙을 실행하여 빛의 현재 값을 읽고 1을 뺀 다음 다시 씁니다.

(따라서 정확한 비율로 디밍에서 빛을 방지) 다른 스레드에서 동시에 발생하지 않는 규칙을 보장하기 위해, 나의 동료는이 같은 lock.lock를 추가 추천 :

rule "ArduinoBedroomVector" 
    when 
     Item Bedroomvector received update 
    then 
     lock.lock() 
     try { 
      // rules here 
      var Number lightcircuit1level = BedroomCeilingLight.state as DecimalType 
      switch(Bedroomvector.state) { 
      case "light_1_up" : { 
       lightcircuit1level = lightcircuit1level + 3 
       if(lightcircuit1level>100) lightcircuit1level = 100 
       sendCommand(BedroomCeilingLight, lightcircuit1level); 
      } 
      case "light_1_down" : { 
       lightcircuit1level = lightcircuit1level -3 
       if(lightcircuit1level<0) lightcircuit1level = 0 
       sendCommand(BedroomCeilingLight, lightcircuit1level); 
      } 
      } 
     } 
     finally { 
      lock.unlock() 
     } 
    end 

그리고 이것은 치료를했습니다.

이제 내 액추에이터는 "다운"메시지를 놓치지 않습니다.

액츄에이터가 각 개별 메시지 (433MHz RF 전송 이상에서 실행될 때마다 각 RF 메시지 메시지가 전송되기까지 0.5 초 걸린다)에 약간의 시간이 걸리기 때문에 액추에이터에 대한 디밍 명령이 대기열에 있습니다.

그래서 규칙이 마지막으로 실행되었는지 확인하기위한 방법을 소개해야합니다. 0.6 초. 그렇다면 값을 증가 시키되 명령을 보내지 마십시오. 그렇지 않으면 값을 증가시키고 마지막으로 명령을 보냅니다.

예를 들어 이것은 빛을 계속해서 위아래로 흐리게 표시 할 수 있으며 정지하지 않는 한 빛의 레벨은 변경되지 않습니다. 그런 다음 조도 조절을 중단하기로 결정하자마자 밝기 레벨이 확정되고 설정됩니다.

레벨을 지속적으로 변경할 수있는 타이밍 "규칙"이 더 좋지만 최신 레벨이 무엇인지에 따라 0.5 초마다 조명 수준 만 설정하는 것이 좋습니다.

나는이 규칙이 실행될 때 확인되는 타이머를 만드는 경우에 불과하지만 타이머를 만들고 확인해야 할 때 머리를 쓸 수 없다고 확신합니다. 이것은 아마 많은 사람들에게 분명한 사실입니다.

답변

0

너무 열심히해서는 안되며, 눈에 띄지 않습니다.

내 접근 방식은 가장 최근에 실행 한 규칙의 타임 스탬프를 유지하고 sendCommand를 호출하기 전에 if 문을 추가하여 최소한 0.6 초가 경과했는지 확인하는 것입니다.

그러나, 명령의 마지막 수신이 .6 초가 지나기 전에 새로운 값이 전송되지 않으므로 마지막 값이 게시되도록 타이머를 설정해야하는 한 가지 경우가 있습니다. 타이머가 설정되었지만 아직 실행되지 않은 상태에서 새 명령을 받으면 타이머가 지워지지 않도록 정리해야합니다. 엣지 케이스가 엉망입니다.

var lastExec = now.millis 
var Timer timer = null 

rule "ArduinoBedroomVector" 
when 
    Item Bedroomvector received update 
then 
    lock.lock() 
    try { 
     // rules here 
     var Number lightcircuit1level = BedroomCeilingLight.state as DecimalType 
     switch(Bedroomvector.state) { 
     case "light_1_up" : { 
      lightcircuit1level = lightcircuit1level + 3 
      if(lightcircuit1level>100) lightcircuit1level = 100 
      // Wait to send the new value 
     } 
     case "light_1_down" : { 
      lightcircuit1level = lightcircuit1level -3 
      if(lightcircuit1level<0) lightcircuit1level = 0 
      // wait to send the new value 
     } 
     } 

     // if more than .6 seconds have passed since the last time the value was sent 
     if((now.millis - lastExec) > 600){ 
     // cancel the timer if one is already set 
     if(timer != null) { 
      timer.cancel 
      timer = null 
     } 
     sendCommand(BedroomCeilingLight, lightcircuit1level) 
     lastExec = now.millis 
     } 
     // its too soon to send the update, set a timer 
     else { 
     // cancel the timer if one is already set 
     if(timer != null) { 
      timer.cancel 
      timer = null 
     } 
     // set a timer to go off in what is left of the .6 secs since the last update 
     var t = now.plusMillis(600) - lastExec 
     timer = createTimer(now.plusMillis(t), [| 
      sendCommand(BedroomCeilingLight, lightcircuit1level) 
      lastExec = now.millis 
      // beware, there could be a race condition here as the timer 
      // will execute outside of the lock. If the rule executes 
      // at the same time as the timer the most recent value of 
      // lastExec may be overwritten with an older value. It should 
      // happen very rarely though and may not be a problem. 
     ] 
     } 
    } 
    finally { 
     lock.unlock() 
    } 
end