Debounce instead of delay
This commit is contained in:
+27
-4
@@ -28,6 +28,7 @@ module AFRP
|
|||||||
, rollup
|
, rollup
|
||||||
, sliding
|
, sliding
|
||||||
, fixed
|
, fixed
|
||||||
|
, debounce
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Category (Category(..), (>>>))
|
import Control.Category (Category(..), (>>>))
|
||||||
@@ -150,9 +151,9 @@ mapAccumRequest f x extract = go x
|
|||||||
let next = f t b a
|
let next = f t b a
|
||||||
in pure (extract next, go next)
|
in pure (extract next, go next)
|
||||||
|
|
||||||
data DelayState a = DelayState
|
data DelayState x a = DelayState
|
||||||
{ pending :: [(UTCTime, a)]
|
{ pending :: x
|
||||||
, output :: Event a
|
, output :: !(Event a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -178,6 +179,21 @@ delayEvent delay =
|
|||||||
_ ->
|
_ ->
|
||||||
DelayState queued Tick
|
DelayState queued Tick
|
||||||
|
|
||||||
|
debounce :: NominalDiffTime -> Mealy eff (Event a) (Event a)
|
||||||
|
debounce delay =
|
||||||
|
mapAccumRequest step initial output
|
||||||
|
where
|
||||||
|
initial = DelayState Nothing Tick
|
||||||
|
step req st input =
|
||||||
|
let now = requestTime req
|
||||||
|
held = case input of
|
||||||
|
Tick -> pending st
|
||||||
|
Event x -> Just (delay `addUTCTime` now, x)
|
||||||
|
in case held of
|
||||||
|
Just (due, x)
|
||||||
|
| due <= now -> DelayState Nothing (Event x)
|
||||||
|
_ -> DelayState held Tick
|
||||||
|
|
||||||
changes :: Eq a => Mealy eff a (Event a)
|
changes :: Eq a => Mealy eff a (Event a)
|
||||||
changes = mapAccum go Nothing (maybe Tick snd)
|
changes = mapAccum go Nothing (maybe Tick snd)
|
||||||
where
|
where
|
||||||
@@ -230,7 +246,14 @@ duration = mapAccumRequest go (Nothing @(UTCTime, NominalDiffTime)) (maybe 0 snd
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
rollup :: Int -> Int -> Mealy eff (Event a) (Event [a])
|
-- | Rollup, hold back bursty messages
|
||||||
|
--
|
||||||
|
-- Consider a case where you have a bursty set of data. You care to get an immediate response,
|
||||||
|
-- but don't want to spam the output
|
||||||
|
rollup
|
||||||
|
:: Int -- ^ How many items to pass through before burst protection
|
||||||
|
-> Int -- ` How many seconds to collect the bursty data
|
||||||
|
-> Mealy eff (Event a) (Event [a])
|
||||||
rollup limit seconds = mapAccumRequest go (Left Tick) (either id (\(_, _, _, ev) -> ev))
|
rollup limit seconds = mapAccumRequest go (Left Tick) (either id (\(_, _, _, ev) -> ev))
|
||||||
where
|
where
|
||||||
e a = Endo ([a] ++)
|
e a = Endo ([a] ++)
|
||||||
|
|||||||
@@ -133,8 +133,9 @@ waitFor n = duration >>> arr (> n) >>> edge
|
|||||||
|
|
||||||
delayedDoor :: HASS (Event Value) (Event DoorState)
|
delayedDoor :: HASS (Event Value) (Event DoorState)
|
||||||
delayedDoor = door
|
delayedDoor = door
|
||||||
>>> (AFRP.hold Open &&& AFRP.delayEvent 15)
|
>>> AFRP.debounce 15
|
||||||
>>> AFRP.sample
|
>>> AFRP.hold Open
|
||||||
|
>>> AFRP.changes
|
||||||
>>> traceEvent
|
>>> traceEvent
|
||||||
|
|
||||||
humidifierController :: HASS (Event Value) ()
|
humidifierController :: HASS (Event Value) ()
|
||||||
|
|||||||
Reference in New Issue
Block a user