diff --git a/IPSLibrary/app/modules/IPSShadowing/IPSShadowing_Device.class.php b/IPSLibrary/app/modules/IPSShadowing/IPSShadowing_Device.class.php index 9e6292a..70adc0c 100644 --- a/IPSLibrary/app/modules/IPSShadowing/IPSShadowing_Device.class.php +++ b/IPSLibrary/app/modules/IPSShadowing/IPSShadowing_Device.class.php @@ -45,7 +45,7 @@ * @version * Version 2.50.1, 01.04.2012
*/ - class IPSShadowing_Device { + class IPSShadowing_Device extends CubicSplines { /** * @private @@ -88,7 +88,11 @@ private function SetVariableValue($variableIdent, $value) { if ($variableId === false) { throw new Exception('Variable '.$variableIdent.' could NOT be found for DeviceId='.$this->deviceId); } - SetValue($variableId, $value); + if ($variableIdent==c_Control_Movement) { + SetValueInteger($variableId, (int)$value); + } else { + SetValue($variableId, $value); + } } // ---------------------------------------------------------------------------------------------------------------------------- @@ -125,6 +129,7 @@ private function SetStatus() { public function MoveByCommand($command) { $componentParams = $this->GetPropertyValue(c_Property_Component); + // Execute Shutter Command if (IPSShadowing_BeforeActivateShutter($this->deviceId, $command)) { $component = IPSComponent::CreateObjectByParams($componentParams); switch ($command) { @@ -142,6 +147,13 @@ public function MoveByCommand($command) { default: } IPSShadowing_AfterActivateShutter($this->deviceId, $command); + + // Abort Processing in case of false result + } else { + SetValue(IPS_GetObjectIDByIdent(c_Control_StartTime, $this->deviceId),-1); + SetValue(IPS_GetObjectIDByIdent(c_Control_StepsToDo, $this->deviceId),""); + SetValue(IPS_GetObjectIDByIdent(c_Control_Step, $this->deviceId),-1); + $command = c_MovementId_Stop; } if ($this->GetVariableValue(c_Control_Movement) <> $command) { @@ -162,7 +174,8 @@ public function SyncStatus($status) { if ($this->GetVariableValue(c_Control_StepsToDo)=="") { IPSLogger_Inf(__file__, "Sync State=".$status." from Shutter '".IPS_GetName($this->deviceId)); $this->SetVariableValue(c_Control_Movement, $status); - } + $this->SetVariableValue(c_Control_ManualChange, true); + } $this->SetStatus(); } @@ -173,53 +186,17 @@ public function MoveByEvent($Level) { $this->GetVariableValue(c_Control_StepsToDo)=="") { IPSLogger_Inf(__file__, "Apply StateChange from Shutter '".IPS_GetName($this->deviceId)."', Level=".round($Level)); $shadowingType = $this->GetPropertyValue(c_Property_ShadowingType); - if ($Level <= 5) { - switch($shadowingType) { - case c_ShadowingType_Marquees: - $this->SetVariableValue(c_Control_Movement, c_MovementId_MovedIn); break; - default: - $this->SetVariableValue(c_Control_Movement, c_MovementId_Opened); break; - } - } else if ($Level >= 95) { - switch($shadowingType) { - case c_ShadowingType_Marquees: - $this->SetVariableValue(c_Control_Movement, c_MovementId_MovedOut); break; - case c_ShadowingType_Shutter: - $this->SetVariableValue(c_Control_Movement, c_MovementId_Closed); break; - default: - $this->SetVariableValue(c_Control_Movement, c_MovementId_Shadowing); break; - } - } else if ($Level > 45 and $Level < 55) { - switch($shadowingType) { - case c_ShadowingType_Marquees: - case c_ShadowingType_Shutter: - $this->SetVariableValue(c_Control_Movement, c_MovementId_50); break; - default: - $this->SetVariableValue(c_Control_Movement, c_MovementId_Stop); break; - } - } else if ($Level > 70 and $Level < 80) { - switch($shadowingType) { - case c_ShadowingType_Marquees: - case c_ShadowingType_Shutter: - $this->SetVariableValue(c_Control_Movement, c_MovementId_75); break; - default: - $this->SetVariableValue(c_Control_Movement, c_MovementId_Stop); break; - } - } else if ($Level > 85 and $Level < 95) { - switch($shadowingType) { - case c_ShadowingType_Shutter: - $this->SetVariableValue(c_Control_Movement, c_MovementId_90); break; - default: - $this->SetVariableValue(c_Control_Movement, c_MovementId_Stop); break; - } - } else { - $this->SetVariableValue(c_Control_Movement, c_MovementId_Stop); - } + + // Set Movement Value + $this->SetVariableValue(c_Control_Movement, $this->GetMovementByPositionSync($Level)); + + // Set manual Change Flag $this->SetVariableValue(c_Control_Position, $Level); if (!$this->GetVariableValue(c_Control_ManualChange) and $this->GetVariableValue(c_Control_Automatic)) { $this->SetVariableValue(c_Control_ManualChange, true); } + // Set Status $this->SetStatus(); } } @@ -282,51 +259,135 @@ public function MoveByProgram($ProgramId, $logMessage, $DimoutOption=null, $Trig IPSLogger_Err(__file__, "Unknown ProgramId $ProgramId, DeviceId=".$this->DeviceId); exit; } + if ($DoBeMoved<>$MovementStatus) { + // Check Program Delay + $lastProgramTime = $this->GetVariableValue(c_Control_ProgramTime); + $lastProgramMinutes = (time() - $lastProgramTime)/60; + if (defined('IPSSHADOWING_PROGRAM_DELAY') and $lastProgramMinutes < IPSSHADOWING_PROGRAM_DELAY ) { + return round(IPSSHADOWING_PROGRAM_DELAY-$lastProgramMinutes); + } if ($TriggeredByTemp and !$this->GetVariableValue(c_Control_TempChange)) { $this->SetVariableValue(c_Control_TempChange, true); - $this->SetVariableValue(c_Control_TempLastPos, $this->GetMovementIdByPosition()); + $this->SetVariableValue(c_Control_TempLastPos, $this->GetMovementLastPosition()); } + $this->SetVariableValue(c_Control_ProgramTime, time()); $this->SetVariableValue(c_Control_Movement, $DoBeMoved); $this->MoveByStatus(); IPSShadowing_LogMoveByProgram($this->deviceId, $ProgramId, $logMessage, $TriggeredByTemp); } + return 0; } // ---------------------------------------------------------------------------------------------------------------------------- - private function GetMovementIdByPosition() { - $shadowingType = $this->GetPropertyValue(c_Property_ShadowingType); - $currentMovementId = $this->GetVariableValue(c_Control_Movement); + private function GetMovementLastPosition() { + $lastMovment = $this->GetVariableValue(c_Control_Movement); $currentPosition = $this->GetVariableValue(c_Control_Position); - if ($currentMovementId<>c_MovementId_Stop) { - $lastPosition = $currentMovementId; - } elseif ($currentPosition<10) { - if ($shadowingType==c_ShadowingType_Marquees) { - $lastPosition = c_MovementId_MovedIn; - } else { - $lastPosition = c_MovementId_Opened; - } - } elseif ($currentPosition<30) { - $lastPosition = c_MovementId_25; - } elseif ($currentPosition<55) { - $lastPosition = c_MovementId_50; - } elseif ($currentPosition<80) { - $lastPosition = c_MovementId_75; - } elseif ($currentPosition<92) { - $lastPosition = c_MovementId_90; - } else { - if ($shadowingType==c_ShadowingType_Marquees) { - $lastPosition = c_MovementId_MovedOut; - } elseif ($shadowingType==c_ShadowingType_Shutter) { - $lastPosition = c_MovementId_Closed; - } else { - $lastPosition = c_MovementId_Shadowing; + if ($lastMovment==c_MovementId_Stop) { + $lastMovment = $this->GetMovementByPositionSync($currentPosition); + } + + return $lastMovment; + } + + // ---------------------------------------------------------------------------------------------------------------------------- + private function GetMovementByPosition($Level) { + $result = c_MovementId_Stop; + + $shadowingType = $this->GetPropertyValue(c_Property_ShadowingType); + if ($Level <= 5) { + switch($shadowingType) { + case c_ShadowingType_Marquees: $result = c_MovementId_MovedIn; break; + default: $result = c_MovementId_Opened; break; } + //} else if ($Level > 5 and $Level <= 30) { + } else if ($Level > 20 and $Level <= 30) { + switch($shadowingType) { + case c_ShadowingType_Marquees: + case c_ShadowingType_Shutter: $result = c_MovementId_25; break; + default: $result = c_MovementId_Opened; break; + } + //} else if ($Level > 30 and $Level <= 55) { + } else if ($Level > 45 and $Level <= 55) { + switch($shadowingType) { + case c_ShadowingType_Marquees: + case c_ShadowingType_Shutter: $result = c_MovementId_50; break; + default: $result = c_MovementId_Opened; break; + } + //} else if ($Level > 55 and $Level <= 80) { + } else if ($Level > 70 and $Level <= 80) { + switch($shadowingType) { + case c_ShadowingType_Marquees: + case c_ShadowingType_Shutter: $result = c_MovementId_75; break; + default: $result = c_MovementId_Stop; break; + } + //} else if ($Level > 80 and $Level <= 95) { + } else if ($Level > 85 and $Level <= 95) { + switch($shadowingType) { + case c_ShadowingType_Marquees: $result = c_MovementId_MovedOut;break; + case c_ShadowingType_Shutter: $result = c_MovementId_90; break; + default: $result = c_MovementId_Shadowing; + } + } else if ($Level >= 95) { + switch($shadowingType) { + case c_ShadowingType_Marquees: $result = c_MovementId_MovedOut;break; + case c_ShadowingType_Shutter: $result = c_MovementId_Closed; break; + default: $result = c_MovementId_Dimout; + } + } else { +// $result = c_MovementId_Stop; + $result = -100-(round($Level/5)*5); } - return $lastPosition; + + return $result ; } + // ---------------------------------------------------------------------------------------------------------------------------- + private function GetMovementByPositionSync($Level) { + $result = c_MovementId_Stop; + + $shadowingType = $this->GetPropertyValue(c_Property_ShadowingType); + if ($Level <= 5) { + switch($shadowingType) { + case c_ShadowingType_Marquees: $result = c_MovementId_MovedIn; break; + default: $result = c_MovementId_Opened; + } + } else if ($Level >= 95) { + switch($shadowingType) { + case c_ShadowingType_Marquees: $result = c_MovementId_MovedOut; break; + case c_ShadowingType_Shutter: $result = c_MovementId_Closed; break; + default: $result = c_MovementId_Shadowing; + } + } else if ($Level > 20 and $Level < 30) { + switch($shadowingType) { + case c_ShadowingType_Marquees: + case c_ShadowingType_Shutter: $result = c_MovementId_25; break; + default: $result = c_MovementId_Stop; + } + } else if ($Level > 45 and $Level < 55) { + switch($shadowingType) { + case c_ShadowingType_Marquees: + case c_ShadowingType_Shutter: $result = c_MovementId_50; break; + default: $result = c_MovementId_Stop; + } + } else if ($Level > 70 and $Level < 80) { + switch($shadowingType) { + case c_ShadowingType_Marquees: + case c_ShadowingType_Shutter: $result = c_MovementId_75; break; + default: $result = c_MovementId_Stop; + } + } else if ($Level > 85 and $Level < 95) { + switch($shadowingType) { + case c_ShadowingType_Shutter: $result = c_MovementId_90; break; + default: $result = c_MovementId_Stop; + } + } else { + $result = c_MovementId_Stop; + } + return $result ; + } + // ---------------------------------------------------------------------------------------------------------------------------- public function MoveByControl($Value) { if ($Value==c_MovementId_Space) { @@ -343,6 +404,35 @@ public function MoveByControl($Value) { } } + // ---------------------------------------------------------------------------------------------------------------------------- + public function MoveByLevel($level) { + $movement = $this->GetMovementByPosition($level); + if ($this->GetVariableValue(c_Control_StepsToDo)<>"") { + if (!$this->GetVariableValue(c_Control_ManualChange)) { + $this->SetVariableValue(c_Control_ManualChange, true); + } + $this->SetVariableValue(c_Control_Movement, c_MovementId_Stop); + $this->MoveByStatus(); + IPSShadowing_LogMoveByControl($this->deviceId); + } else if ($this->GetVariableValue(c_Control_Movement)==$movement) { + $this->SetVariableValue(c_Control_Position, $this->GetVariableValue(c_Control_Position)); + return; + } elseif ($movement<0) { + if (!$this->GetVariableValue(c_Control_ManualChange)) { + $this->SetVariableValue(c_Control_ManualChange, true); + } + $this->SetVariableValue(c_Control_Movement, $movement); + $this->MoveByStatus(); + IPSShadowing_LogMoveByControl($this->deviceId); + } else { + if (!$this->GetVariableValue(c_Control_ManualChange)) { + $this->SetVariableValue(c_Control_ManualChange, true); + } + $this->SetVariableValue(c_Control_Movement, $movement); + $this->MoveByStatus(); + IPSShadowing_LogMoveByControl($this->deviceId); + } + } // ---------------------------------------------------------------------------------------------------------------------------- private function AddNextStep(&$StepsToDo, $Command, $SecondsToDo, $Display, $SecondsTotal, $PercentagePosition) { @@ -358,30 +448,49 @@ private function AddNextStep(&$StepsToDo, $Command, $SecondsToDo, $Display, $Sec private function CalcNextSteps() { $DeviceName = IPS_GetIdent($this->deviceId); $DeviceConfig = get_ShadowingConfiguration(); - + $TimeTableOpening = $DeviceConfig[$DeviceName][c_Property_TimeOpening]; + $TimeTableClosing = $DeviceConfig[$DeviceName][c_Property_TimeClosing]; $Position = $this->GetVariableValue(c_Control_Position); $ToBeMoved = $this->GetVariableValue(c_Control_Movement); $StepsToDo = array(); + + $TimeTableOpening = $this->DoDrivingTimeCurve($DeviceConfig[$DeviceName][c_Property_TimeOpening]); + $TimeTableClosing = $this->DoDrivingTimeCurve($DeviceConfig[$DeviceName][c_Property_TimeClosing]); - if ($ToBeMoved==c_MovementId_Opened or $ToBeMoved==c_MovementId_Up) { - $SecTotal = $DeviceConfig[$DeviceName][c_Property_TimeOpening]; - $SecNullToPos = $SecTotal*$Position/100; - $SecPosTo100 = $SecTotal-$SecNullToPos; + if ($ToBeMoved==c_MovementId_Opened or $ToBeMoved==c_MovementId_Up) { + if (isset($TimeTableOpening[100])) { + $SecTotal = $this->GetInterpSecond($TimeTableOpening,0); + $SecPosTo100 = $this->GetInterpSecond($TimeTableOpening,$Position); + } else { + $SecTotal = $DeviceConfig[$DeviceName][c_Property_TimeOpening]; + $SecNullToPos = $SecTotal*$Position/100; + $SecPosTo100 = $SecTotal-$SecNullToPos; + } $this->AddNextStep($StepsToDo, c_MovementId_Up, $SecTotal-$SecPosTo100, null, $SecTotal, $SecPosTo100); $this->AddNextStep($StepsToDo, c_MovementId_Stop, $DeviceConfig[$DeviceName][c_Property_TimePause], 'Offen (Stop)', null, null); $this->AddNextStep($StepsToDo, c_MovementId_Opened, 1, null, null , null); } elseif ($ToBeMoved==c_MovementId_MovedIn or $ToBeMoved==c_MovementId_MovingIn) { - $SecTotal = $DeviceConfig[$DeviceName][c_Property_TimeOpening]; - $SecNullToPos = $SecTotal*$Position/100; - $SecPosTo100 = $SecTotal-$SecNullToPos; + if (isset($TimeTableOpening[100])) { + $SecTotal = $this->GetInterpSecond($TimeTableOpening,0); + $SecPosTo100 = $this->GetInterpSecond($TimeTableOpening,$Position); + } else { + $SecTotal = $DeviceConfig[$DeviceName][c_Property_TimeOpening]; + $SecNullToPos = $SecTotal*$Position/100; + $SecPosTo100 = $SecTotal-$SecNullToPos; + } $this->AddNextStep($StepsToDo, c_MovementId_MovingIn, $SecTotal-$SecPosTo100, null, $SecTotal, $SecPosTo100); $this->AddNextStep($StepsToDo, c_MovementId_Stop, $DeviceConfig[$DeviceName][c_Property_TimePause], 'Offen (Stop)', null, null); $this->AddNextStep($StepsToDo, c_MovementId_MovedIn, 1, null, null , null); } elseif ($ToBeMoved==c_MovementId_Shadowing or $ToBeMoved==c_MovementId_Down or $ToBeMoved==c_MovementId_Dimout or $ToBeMoved==c_MovementId_Closed or $ToBeMoved==c_MovementId_MovingOut or $ToBeMoved==c_MovementId_MovedOut) { - $SecTotal = $DeviceConfig[$DeviceName][c_Property_TimeClosing]; - $SecNullToPos = $SecTotal*$Position/100; + if (isset($TimeTableClosing[100])) { + $SecTotal = $this->GetInterpSecond($TimeTableClosing,100); + $SecNullToPos = $this->GetInterpSecond($TimeTableClosing,$Position); + } else { + $SecTotal = $DeviceConfig[$DeviceName][c_Property_TimeClosing]; + $SecNullToPos = $SecTotal*$Position/100; + } if ($ToBeMoved==c_MovementId_Dimout) { $this->AddNextStep($StepsToDo, c_MovementId_Down, $SecTotal-$SecNullToPos, null, $SecTotal, $SecNullToPos); $this->AddNextStep($StepsToDo, c_MovementId_Stop, $DeviceConfig[$DeviceName][c_Property_TimePause], 'Abdunkelung (Pause)', null, null); @@ -408,38 +517,83 @@ private function CalcNextSteps() { $this->AddNextStep($StepsToDo, c_MovementId_Stop, 1, "$Position%", null, null); $this->AddNextStep($StepsToDo, c_MovementId_Closed, 1, null, null, null); } - - } elseif ($ToBeMoved==c_MovementId_90 or$ToBeMoved==c_MovementId_75 or $ToBeMoved==c_MovementId_50 or $ToBeMoved==c_MovementId_25) { - $SecTotal = $DeviceConfig[$DeviceName][c_Property_TimeClosing]; - $ShadowingType = $DeviceConfig[$DeviceName][c_Property_ShadowingType]; - $SecNullToPos = $SecTotal*$Position/100; - $SecPosTo100 = $SecTotal-$SecNullToPos; + + } elseif ($ToBeMoved==c_MovementId_90 or $ToBeMoved==c_MovementId_75 or $ToBeMoved==c_MovementId_50 or $ToBeMoved==c_MovementId_25) { + $ShadowingType = $DeviceConfig[$DeviceName][c_Property_ShadowingType]; + $ToBeMovedValues = explode(",",",,,,90,75,50,25"); + if ($Position<$ToBeMovedValues[$ToBeMoved]) { + $RunTime = $TimeTableClosing; + $maxPostion = 100; + } else { + $RunTime = $TimeTableOpening; + $maxPostion = 0; + } + if (isset($RunTime[100])) { + $SecTotal = $this->GetInterpSecond($RunTime,$maxPostion); + $SecNullToPos = $this->GetInterpSecond($RunTime,$Position); + } else { + $SecTotal = $DeviceConfig[$DeviceName][c_Property_TimeClosing]; + $SecNullToPos = $SecTotal*$Position/100; + $SecPosTo100 = $SecTotal-$SecNullToPos; + } if ($ToBeMoved==c_MovementId_90) { - $SecNullToNew = $SecTotal*90/100; - $Position = 90; + $Position = 90; + if (isset($RunTime[100])) { + $SecNullToNew = $this->GetInterpSecond($RunTime,90); + } else { + $SecNullToNew = $SecTotal*90/100; + } } elseif ($ToBeMoved==c_MovementId_75) { - $SecNullToNew = $SecTotal*75/100; - $Position = 75; + $Position = 75; + if (isset($RunTime[100])) { + $SecNullToNew =$this->GetInterpSecond($RunTime,75); + } else { + $SecNullToNew = $SecTotal*75/100; + } } elseif ($ToBeMoved==c_MovementId_50) { - $SecNullToNew = $SecTotal*50/100; - $Position = 50; + $Position = 50; + if (isset($RunTime[100])) { + $SecNullToNew = $this->GetInterpSecond($RunTime,50); + } else { + $SecNullToNew = $SecTotal*50/100; + } } else { - $SecNullToNew = $SecTotal*25/100; - $Position = 25; - } - if ($SecNullToNew > $SecNullToPos) { - if ($ShadowingType==c_ShadowingType_Marquees) { - $this->AddNextStep($StepsToDo, c_MovementId_MovingOut, $SecNullToNew-$SecNullToPos, null, $SecTotal, $SecNullToPos); + $Position = 25; + if (isset($RunTime[100])) { + $SecNullToNew = $this->GetInterpSecond($RunTime,25); } else { - $this->AddNextStep($StepsToDo, c_MovementId_Down, $SecNullToNew-$SecNullToPos, null, $SecTotal, $SecNullToPos); + $SecNullToNew = $SecTotal*25/100; } - } elseif ($SecNullToNew < $SecNullToPos) { - if ($ShadowingType==c_ShadowingType_Marquees) { - $this->AddNextStep($StepsToDo, c_MovementId_MovingIn, $SecNullToPos-$SecNullToNew, null, $SecTotal, $SecPosTo100); + } + if (isset($RunTime[100])) { + if ($maxPostion==100) { + if ($ShadowingType==c_ShadowingType_Marquees) { + $this->AddNextStep($StepsToDo, c_MovementId_MovingOut, $SecNullToNew-$SecNullToPos, null, $SecTotal, $SecNullToPos); + } else { + $this->AddNextStep($StepsToDo, c_MovementId_Down, $SecNullToNew-$SecNullToPos, null, $SecTotal, $SecNullToPos); + } } else { - $this->AddNextStep($StepsToDo, c_MovementId_Up, $SecNullToPos-$SecNullToNew, null, $SecTotal, $SecPosTo100); + if ($ShadowingType==c_ShadowingType_Marquees) { + $this->AddNextStep($StepsToDo, c_MovementId_MovingIn, $SecNullToNew-$SecNullToPos, null, $SecTotal, $SecNullToPos); + } else { + $this->AddNextStep($StepsToDo, c_MovementId_Up, $SecNullToNew-$SecNullToPos, null, $SecTotal, $SecNullToPos); + } } } else { + if ($SecNullToNew > $SecNullToPos) { + if ($ShadowingType==c_ShadowingType_Marquees) { + $this->AddNextStep($StepsToDo, c_MovementId_MovingOut, $SecNullToNew-$SecNullToPos, null, $SecTotal, $SecNullToPos); + } else { + $this->AddNextStep($StepsToDo, c_MovementId_Down, $SecNullToNew-$SecNullToPos, null, $SecTotal, $SecNullToPos); + } + } elseif ($SecNullToNew < $SecNullToPos) { + if ($ShadowingType==c_ShadowingType_Marquees) { + $this->AddNextStep($StepsToDo, c_MovementId_MovingIn, $SecNullToPos-$SecNullToNew, null, $SecTotal, $SecPosTo100); + } else { + $this->AddNextStep($StepsToDo, c_MovementId_Up, $SecNullToPos-$SecNullToNew, null, $SecTotal, $SecPosTo100); + } + } else { + } } $this->AddNextStep($StepsToDo, c_MovementId_Stop, 1, "$Position%", null, null); $this->AddNextStep($StepsToDo, $ToBeMoved, 1, null, null, null); @@ -447,6 +601,44 @@ private function CalcNextSteps() { } elseif ($ToBeMoved==c_MovementId_Stop) { $this->AddNextStep($StepsToDo, c_MovementId_Stop, 1, null, null, null); + } elseif ($ToBeMoved<0) { + $ShadowingType = $DeviceConfig[$DeviceName][c_Property_ShadowingType]; + $ToBeMoved=(-1)*$ToBeMoved-100; + if ($Position<$ToBeMoved) { + $RunTime = $TimeTableClosing; + $maxPostion = 100; + } else { + $RunTime = $TimeTableOpening; + $maxPostion = 0; + } + if (isset($RunTime[100])) { + $SecTotal = $this->GetInterpSecond($RunTime,$maxPostion); + $SecNullToPos = $this->GetInterpSecond($RunTime,$Position); + $SecNullToNew = $this->GetInterpSecond($RunTime,$ToBeMoved); + } else { + $SecTotal = $DeviceConfig[$DeviceName][c_Property_TimeClosing]; + $SecNullToPos = $SecTotal*$Position/100; + $SecPosTo100 = $SecTotal-$SecNullToPos; + } + if (isset($RunTime[100])) { + if ($maxPostion==100) { + if ($ShadowingType==c_ShadowingType_Marquees) { + $this->AddNextStep($StepsToDo, c_MovementId_MovingOut, int($SecNullToNew-$SecNullToPos), null, $SecTotal, $SecNullToPos); + } else { + $this->AddNextStep($StepsToDo, c_MovementId_Down, int($SecNullToNew-$SecNullToPos), null, $SecTotal, $SecNullToPos); + } + } else { + if ($ShadowingType==c_ShadowingType_Marquees) { + $this->AddNextStep($StepsToDo, c_MovementId_MovingIn, int($SecNullToNew-$SecNullToPos), null, $SecTotal, $SecNullToPos); + } else { + $this->AddNextStep($StepsToDo, c_MovementId_Up, int($SecNullToNew-$SecNullToPos), null, $SecTotal, $SecNullToPos); + } + } + } + $moveDown=($maxPostion==0 ? false : true); + $Position = $this->GetInterpPosition($RunTime,int($SecNullToNew),$moveDown); + $this->AddNextStep($StepsToDo, c_MovementId_Stop, 1, "$Position%", null, null); + } else { throw new Exception ("Unknown MovementId $ToBeMoved, DeviceId=".$this->deviceId); exit; @@ -466,7 +658,10 @@ private function ExecuteNextStep() { if ($Step < count($NextStepsToDo)) { $Command = $NextStepsToDo[$Step]; $Time = $NextStepsToDo[$Step+1]; - IPSLogger_Trc(__file__, "Shadowing for Device '$DeviceName', Step $Step, Command=$Command, Time=$Time"); + $Display = $NextStepsToDo[$Step+2]; + $SecsTotal = $NextStepsToDo[$Step+3]; + $SecStepBegin = $NextStepsToDo[$Step+4]; + IPSLogger_Trc(__file__, "Shadowing for Device '$DeviceName', Step $Step, Command=$Command, Time=$Time, SecTotal=$SecsTotal, SecBegin=$SecStepBegin"); $this->MoveByCommand($Command); $this->SetVariableValue(c_Control_Step, $Step); @@ -483,9 +678,11 @@ private function ExecuteNextStep() { // ---------------------------------------------------------------------------------------------------------------------------- public function Refresh() { + $DeviceName = IPS_GetIdent($this->deviceId); $NextStepsToDo = Explode('|', $this->GetVariableValue(c_Control_StepsToDo)); $StepCount = count($NextStepsToDo); $Step = $this->GetVariableValue(c_Control_Step); + if ($StepCount >= ($Step+4) and $Step>=0) { $StartTime = $this->GetVariableValue(c_Control_StartTime); $SecsDone = time()-$StartTime; @@ -495,25 +692,46 @@ public function Refresh() { $SecStepBegin = $NextStepsToDo[$Step+4]; $Command = $NextStepsToDo[$Step]; + $DeviceConfig = get_ShadowingConfiguration(); + $TimeTableOpening = $this->DoDrivingTimeCurve($DeviceConfig[$DeviceName][c_Property_TimeOpening]); + $TimeTableClosing = $this->DoDrivingTimeCurve($DeviceConfig[$DeviceName][c_Property_TimeClosing]); + if ($SecsTotal <> null) { // SecTotal ... 100% // Begin+Done ... x% - $Position = round(($SecStepBegin+$SecsDone)*100/$SecsTotal); - if ($Command==c_MovementId_Up or $Command==c_MovementId_MovingIn) { - $Position = 100-$Position; + + if ($Command==c_MovementId_Down or $Command==c_MovementId_MovingOut) { + $TimeTable=$TimeTableClosing; + $moveDown=true; + } else { + $TimeTable=$TimeTableOpening; + $moveDown=false; + } + if (isset($TimeTable[100])) { + $Position = $this->GetInterpPosition($TimeTable,$SecStepBegin+$SecsDone,$moveDown); + } else { + $Position = round(($SecStepBegin+$SecsDone)*100/$SecsTotal); + if ($Command==c_MovementId_Up or $Command==c_MovementId_MovingIn) { + $Position = 100-$Position; + } + if ($Position>100) {$Position=100;} + if ($Position<0) {$Position=0;} } - if ($Position>100) {$Position=100;} - if ($Position<0) {$Position=0;} + $this->SetVariableValue(c_Control_Position, $Position); $SecsOpen = $SecsToDo-$SecsDone; if ($SecsOpen < 0) {$SecsOpen=0;} - $Display = "$Position% ($SecsOpen Sek)"; + $Display = "$Position% ($SecsDone Sek)"; } if ($Display!=null) { $this->SetVariableValue(c_Control_Display, $Display); } + if (function_exists('IPSShadowing_Refresh')) { + IPSShadowing_Refresh($this->deviceId, $StepCount, $Step, $Command, $SecsToDo, $SecsDone); + } + if ($SecsDone >= $SecsToDo) { $this->ExecuteNextStep(); } @@ -588,6 +806,8 @@ public function CheckPrograms($profileManager) { $shadowingByTemp = $profileManager->ShadowingByTemp($profileIdSun, $profileIdTemp, $tempIndoorPath); $openByTemp = $profileManager->OpenByTemp($profileIdSun, $profileIdTemp, $tempIndoorPath); $activationByWeather = $profileManager->ActivationByWeather($profileIdWeather); + $programInfo = ''; + $programDelay = false; // Reset Manual Change Flag @@ -604,20 +824,24 @@ public function CheckPrograms($profileManager) { $changeByTemp = GetValue(IPS_GetObjectIDByIdent(c_Control_TempChange, $this->deviceId)); $changeByUser = GetValue(IPS_GetObjectIDByIdent(c_Control_ManualChange, $this->deviceId)); + + $func_reflection = new ReflectionFunction('IPSShadowing_ProgramCustom'); + $paramCountCustom = $func_reflection->getNumberOfParameters(); // Check all Programs // -------------------------------------------------------------------------------- // Automatic Off ... if (!$automaticActive) { - $programInfo = 'Automatic Off'; + $programInfo = 'Keine Automatik'; // Activation by Wind/Rain } elseif ($activationByWeather and $programWeather<>c_ProgramId_Manual) { - $programInfo = 'Wetterprogramm'; - $this->MoveByProgram($programWeather, 'Wetterprogramm'); + $programInfo = 'Wetterprogramm'; + $programDelay = $this->MoveByProgram($programWeather, 'Wetterprogramm'); // Custom - } elseif (IPSShadowing_ProgramCustom($this->deviceId, $isDay, $programInfo)) { + } elseif ( ($paramCountCustom == 3 and IPSShadowing_ProgramCustom($this->deviceId, $isDay, $programInfo)) + or ($paramCountCustom == 2 and IPSShadowing_ProgramCustom($this->deviceId, $isDay))) { if ($programInfo=='') {$programInfo = 'CustomProgram';} // Action done in Custom Procedure @@ -627,30 +851,30 @@ public function CheckPrograms($profileManager) { // Present ... } elseif ($profileManager->GetPresent() and $programPresent==c_ProgramId_OpenedDay and $isDay) { - $programInfo = 'Anwesenheit (Tag)'; - $this->MoveByProgram($programPresent, 'Anwesenheitsprogramm'); + $programInfo = 'Anwesenheit (Tag)'; + $programDelay = $this->MoveByProgram($programPresent, 'Anwesenheitsprogramm'); } elseif ($profileManager->GetPresent() and $programPresent==c_ProgramId_OpenedNight and !$isDay) { - $programInfo = 'Anwesenheit (Nacht)'; - $this->MoveByProgram($programPresent, 'Anwesenheitsprogramm'); + $programInfo = 'Anwesenheit (Nacht)'; + $programDelay = $this->MoveByProgram($programPresent, 'Anwesenheitsprogramm'); } elseif ($profileManager->GetPresent() and $programPresent==c_ProgramId_Opened) { - $programInfo = 'Anwesenheit'; - $this->MoveByProgram($programPresent, 'Anwesenheitsprogramm'); + $programInfo = 'Anwesenheit'; + $programDelay = $this->MoveByProgram($programPresent, 'Anwesenheitsprogramm'); } elseif ($profileManager->GetPresent() and $programPresent==c_ProgramId_MovedOutTemp and $isDay and $closeByTemp) { - $programInfo = 'Anwesenheit (Temperatur)'; - $this->MoveByProgram($programPresent, 'Anwesenheitsprogramm (Beschattung bei Temp und Anwesenheit)'); + $programInfo = 'Anwesenheit (Temperatur)'; + $programDelay = $this->MoveByProgram($programPresent, 'Anwesenheitsprogramm (Beschattung bei Temp und Anwesenheit)'); // Temperature/Sun } elseif ($isDay and ($closeByTemp or $shadowingByTemp) and $programTemp<>c_ProgramId_Manual) { if ($closeByTemp) { - $programInfo = 'Temperatur'; - $this->MoveByProgram($programTemp, 'Temperaturprogramm', true/*DimoutOption*/, true/*TriggeredByTemp*/); + $programInfo = 'Temperatur'; + $programDelay = $this->MoveByProgram($programTemp, 'Temperaturprogramm', true/*DimoutOption*/, true/*TriggeredByTemp*/); } elseif ($changeByTemp) { - $programInfo = 'Temperatur (Warte Öffnen)'; + $programInfo = 'Temperatur (Warte Öffnen)'; } elseif ($shadowingByTemp) { - $programInfo = 'Temperatur (Beschattung)'; - $this->MoveByProgram($programTemp, 'Temperaturprogramm (Beschattung)', false/*DimoutOption*/, true/*TriggeredByTemp*/); + $programInfo = 'Temperatur (Beschattung)'; + $programDelay = $this->MoveByProgram($programTemp, 'Temperaturprogramm (Beschattung)', false/*DimoutOption*/, true/*TriggeredByTemp*/); } else { - $programInfo = 'Temperatur (Error)'; + $programInfo = 'Temperatur (Error)'; } // Day @@ -660,29 +884,151 @@ public function CheckPrograms($profileManager) { } elseif ($openByTemp and $changeByTemp) { SetValue(IPS_GetObjectIDByIdent(c_Control_TempChange, $this->deviceId), false); if ($programDay<>c_ProgramId_Manual) { - $programInfo = 'Temperatur Reset (Tag)'; - $this->MoveByProgram($programDay, 'Temperatur Reset (Tag)'); + $programInfo = 'Temperatur Reset (Tag)'; + $programDelay = $this->MoveByProgram($programDay, 'Temperatur Reset (Tag)'); } else { - $programInfo = 'Temperatur Reset (LastPosition)'; - $this->MoveByProgram(c_ProgramId_LastPosition, 'Temperatur Reset (LastPosition)'); + $programInfo = 'Temperatur Reset (LastPosition)'; + $programDelay = $this->MoveByProgram(c_ProgramId_LastPosition, 'Temperatur Reset (LastPosition)'); } } else { - $programInfo = 'Tagesprogramm'; - $this->MoveByProgram($programDay, 'Tagesprogramm'); + $programInfo = 'Tagesprogramm'; + $programDelay = $this->MoveByProgram($programDay, 'Tagesprogramm'); } // Night } else { - $programInfo = 'Nachtprogramm'; - $this->MoveByProgram($programNight, '"Nachtprogramm"'); + $programInfo = 'Nachtprogramm'; + $programDelay = $this->MoveByProgram($programNight, '"Nachtprogramm"'); } + + // Update ProfileInfos + if ($programDelay > 0) + $programInfo = 'Warte '.$programDelay.' Min '.$programInfo; $profileInfo = $profileManager->GetProfileInfo($profileIdBgnOfDay, $profileIdEndOfDay, $profileIdTemp, $tempIndoorPath); $deviceName = IPSShadowing_GetDeviceName($this->deviceId); echo "$deviceName -> $programInfo, $profileInfo \n"; SetValue(IPS_GetObjectIDByIdent(c_Control_ProfileInfo, $this->deviceId), $programInfo.', '.$profileInfo); } } + + /** + * @class CubicSplines + * + * Definiert ein IPSShadowing_Device Objekt + * Ergänzung: Interpolationskurve (CubicSplines) + * definierte xy-Koordinatensystem Postionen/Sekunden + * + * @author Günter Strassnigg + * Adapted from Code Article by Chris Cornutt on PHPDeveloper.org + * @version + * Version 1.00.1, 23.08.2015
+ */ + class CubicSplines { + + /** + * @private + * aCoords des Shadowing Device (Übergabe der Koordinaten) + * $aCrdX extrahierte x-Koordinaten (Splines) + * $aCrdY extrahierte y-Koordinaten (Splines) + * $aSplines berechnete Splines + */ + private $aCoords; + private $aCrdX; + private $aCrdY; + private $aSplines = array(); + + // ---------------------------------------------------------------------------------------------------------------------------- + protected function DoDrivingTimeCurve($aCoords) { + $this->aSplines = array(); + if (count($aCoords) < 4) { + return false; + } + $this->aCrdX = array(); + $this->aCrdY = array(); + $this->aCoords = array(); + ksort($aCoords); + $this->aCrdX = array_keys($aCoords); + $this->aCrdY = array_values($aCoords); + $this->buildSpline($this->aCrdX, $this->aCrdY, count($this->aCrdX)); + for ($x = 0; $x <= 100; ++$x) { + $this->aCoords[$x] = round($this->funcInterp($x), 1); + } + return $this->aCoords; + } + + // ---------------------------------------------------------------------------------------------------------------------------- + protected function GetInterpSecond($timetable,$position) { + return $timetable[round($position, 0)]; + } + + // ---------------------------------------------------------------------------------------------------------------------------- + protected function GetInterpPosition($timetable,$filter,$down=true) { + reset($timetable); + while (list($position, $seconds) = each($timetable)) { + if (($seconds>=$filter && $down) || + ($seconds<=$filter && !$down) || + ($position==100)) {break;} + } + return (int)$position; + } + + // ---------------------------------------------------------------------------------------------------------------------------- + private function buildSpline($x, $y, $n) { + for ($i = 0; $i < $n; ++$i) { + $this->aSplines[$i]['x'] = $x[$i]; + $this->aSplines[$i]['a'] = $y[$i]; + } + + $this->aSplines[0]['c'] = $this->aSplines[$n - 1]['c'] = 0; + $alpha[0] = $beta[0] = 0; + for ($i = 1; $i < $n - 1; ++$i) { + $h_i = $x[$i] - $x[$i - 1]; + $h_i1 = $x[$i + 1] - $x[$i]; + $A = $h_i; + $C = 2.0 * ($h_i + $h_i1); + $B = $h_i1; + $F = 6.0 * (($y[$i + 1] - $y[$i]) / $h_i1 - ($y[$i] - $y[$i - 1]) / $h_i); + $z = ($A * $alpha[$i - 1] + $C); + $alpha[$i] = - $B / $z; + $beta[$i] = ($F - $A * $beta[$i - 1]) / $z; + } + for ($i = $n - 2; $i > 0; --$i) { + $this->aSplines[$i]['c'] = $alpha[$i] * $this->aSplines[$i + 1]['c'] + $beta[$i]; + } + for ($i = $n - 1; $i > 0; --$i) { + $h_i = $x[$i] - $x[$i - 1]; + $this->aSplines[$i]['d'] = ($this->aSplines[$i]['c'] - $this->aSplines[$i - 1]['c']) / $h_i; + $this->aSplines[$i]['b'] = $h_i * (2.0 * $this->aSplines[$i]['c'] + $this->aSplines[$i - 1]['c']) / 6.0 + ($y[$i] - $y[$i - 1]) / $h_i; + } + } + + // ---------------------------------------------------------------------------------------------------------------------------- + private function funcInterp($x) { + $n = count($this->aSplines); + if ($x <= $this->aSplines[0]['x']) { + $s = $this->aSplines[1]; + } else { + if ($x >= $this->aSplines[$n - 1]['x']) { + $s = $this->aSplines[$n - 1]; + } else { + $i = 0; + $j = $n - 1; + while ($i + 1 < $j) { + $k = $i + ($j - $i) / 2; + if ($x <= $this->aSplines[$k]['x']) { + $j = $k; + } else { + $i = $k; + } + } + $s = $this->aSplines[$j]; + } + } + $dx = ($x - $s['x']); + return $s['a'] + ($s['b'] + ($s['c'] / 2.0 + $s['d'] * $dx / 6.0) * $dx) * $dx; + } + } /** @}*/ -?> \ No newline at end of file +?>