fuyu-gpio-0.1.0.0: examples/03-monitor.hs
-- In this example we will learn how to monitor GPIO line status changes across processes using chip watching.
-- This example structures the application into modular helper blocks ('runApp', 'monitorApp', 'lineApp'),
-- serving as an intermediate modular phase before introducing resource management with 'Control.Monad.Managed'
-- in the next example (04-led-and-button.hs) to eliminate deeply nested brackets.
module Main where
-- High-level resource brackets & exception handling.
import Fuyu.GPIO
-- Qualified Domain Modules.
-- Same as Fuyu.GPIO.EdgeEvent I sugest an qualified import.
import qualified Fuyu.GPIO.Monitor as Monitor
-- Base & third-party libraries.
import Control.Concurrent (forkIO, threadDelay)
myChipPath :: FilePath
myChipPath = "/dev/gpiochip0"
targetOffset :: Offset
targetOffset = Offset 257
waitTimeoutNs :: Monitor.Timeout
waitTimeoutNs = Monitor.Nanoseconds 5000000000 -- 5 seconds
main :: IO ()
main = do
putStrLn "Starting line status event monitor..."
runApp
putStrLn "Line status event monitor completed successfully."
-- We could use some modular application blocks as the next ones to avoid
-- "super nested" functions. Personally I sugest to use this kind of organization
-- or use managed package (next example) for medium size programs.
-- 'runApp' centralizes worker threads and watchers organized in structured blocks.
runApp :: IO ()
runApp = do
putStrLn "Opening GPIO chip and starting line status watching..."
withChip myChipPath $ \chip -> do
-- Register the line watch in the kernel before any interaction
-- (required so the kernel starts queueing status events for targetOffset)
Monitor.withWatchLine chip targetOffset $ \_lineInfo -> do
_ <- forkIO $ lineApp chip
monitorApp chip
-- 'monitorApp' waits for status change events using 'waitEvent' and security token 'ReadyChip'
monitorApp :: Chip -> IO ()
monitorApp chip = do
putStrLn "Waiting for line status change event (timeout: 5s)..."
res <- Monitor.waitEvent chip waitTimeoutNs
case res of
-- Same pattern as 'Fuyu.GPIO.EdgeEvent.waitEvents'
Monitor.EventReady readyChip -> do
Monitor.withEvent readyChip $ \infoEvent -> do
-- In this case, we expect a 'Requested' info event type
eventType <- Monitor.eventType infoEvent
putStrLn ("Event received! " ++ show eventType)
Monitor.TimeoutResult -> putStrLn "Wait timed out (timeout)."
-- 'lineApp' simulates line interactions (requesting access to targetOffset) in a concurrent thread
lineApp :: Chip -> IO ()
lineApp chip = do
withSettings $ \settings -> do
setDirection settings DirAsIs
withConfig $ \config -> do
addSettings config [targetOffset] settings
withRequest chip Nothing config $ \request -> do
name <- chipName request
putStrLn ("Line request created successfully on chip: " ++ show name)
threadDelay 500000 -- Hold requested line briefly