summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Network/EBus/Layer2.hs94
-rw-r--r--ebus.cabal3
-rw-r--r--exec/ebus-dump-layer2.hs39
3 files changed, 67 insertions, 69 deletions
diff --git a/Network/EBus/Layer2.hs b/Network/EBus/Layer2.hs
index c4f1d47..b194ee6 100644
--- a/Network/EBus/Layer2.hs
+++ b/Network/EBus/Layer2.hs
@@ -1,56 +1,10 @@
-module Network.EBus.Layer2 where
+module Network.EBus.Layer2(
+ ebusParserLayer2,
+ EbusPacket) where
-import Control.Applicative
-import Data.Attoparsec
-import Data.Attoparsec.Enumerator (iterParser)
-import Data.Attoparsec.Combinator as C
-import Data.ByteString (ByteString)
-import Data.Enumerator
-import Data.Enumerator.Binary (enumHandle)
+import Control.Applicative ((<|>))
+import Data.Attoparsec (anyWord8, count, skipMany, try, Parser, word8)
import Data.Word (Word8)
-import System.IO (hSetBinaryMode,stdin)
-
--- ebus :: Parser EbusPacket
--- ebus = do{ skipMany1 $ char '\xaa'
--- ; source <- anyChar
--- ; destination <- anyChar
--- ; primaryCommand <- anyChar
--- ; secondaryCommand <- anyChar
--- ; payloadLength <- anyChar
--- ; payload <- count (fromEnum payloadLength) ebusPayload
--- ; followup <-
--- if destination == '\xfe' then
--- -- Broadcast - no further data
--- do{ crc <- anyChar
--- ; syn <- char '\xaa'
--- ; return "broadcast"
--- <|> fail "Failed to parse Broadcast Packet"
--- }
--- else
--- try( -- Master-Master - no further data
--- do{ crc <- anyChar
--- ; ack <- char '\x00' -- ACK OK
--- ; syn <- char '\xaa'
--- ; return "master-master"
--- })
--- <|>
--- try( -- Master Slave
--- do{ crc <- anyChar
--- ; ack <- char '\x00'
--- ; payloadSlaveLength <- anyChar
--- ; payloadSlave <- count (fromEnum payloadSlaveLength) ebusPayload
--- ; crcSlave <- anyChar
--- ; ackSlave <- char '\x00'
--- ; synSlave <- char '\xaa'
--- ; return "master-slave"
--- })
--- <|> fail "Failed to parse Master-Master/Master-Slave Packet"
--- ; return $ EbusPacket
--- source destination
--- primaryCommand secondaryCommand
--- payloadLength followup []
--- }
-
-- | Ebus Layer2 Constants
ebusConstant :: String -> Word8
@@ -75,11 +29,11 @@ data EbusPacket = EbusPacket {
ebusPacketDestination :: Word8,
ebusPacketPrimaryCommand :: Word8,
ebusPacketSecondaryCommand :: Word8,
- ebusPacketPayloadLength :: Word8,
ebusPacketPayload :: [Word8],
ebusPacketPayloadSlave :: Maybe [Word8]
} deriving (Show)
+-- | Ebus Binary Escape Sequences for payload data
parserPayload :: Parser Word8
parserPayload = do{ word8 $ ebusConstant "ESCAPE"
; word8 $ ebusConstant "ESCAPE_ESCAPE"
@@ -91,21 +45,25 @@ parserPayload = do{ word8 $ ebusConstant "ESCAPE"
<|>
anyWord8;
-parser :: Parser EbusPacket
-parser = do{
- C.skipMany $ word8 $ ebusConstant "SYN"
+-- | Parse one Ebus Packet, skips leading SYNs
+ebusParserLayer2 :: Parser EbusPacket
+ebusParserLayer2 = do{
+ skipMany $ word8 $ ebusConstant "SYN"
; source <- anyWord8
; destination <- anyWord8
; primaryCommand <- anyWord8
; secondaryCommand <- anyWord8
; payloadLength <- anyWord8
- ; payload <- C.count (fromIntegral payloadLength) parserPayload
+ ; payload <- count (fromIntegral payloadLength) parserPayload
; followup <-
if destination == 0xfe then
-- Broadcast
do{ crc <- anyWord8
; {- syn -} word8 $ ebusConstant "SYN"
- ; return (EbusBroadcast, crc, Nothing)}
+ ; if True then -- CHECK CRC
+ return $ EbusPacket EbusMasterMaster source destination primaryCommand secondaryCommand payload Nothing
+ else
+ fail "Broadcast: CRC Check failed"}
<|>
fail "Failed to parse Broadcast Paket"
else
@@ -114,25 +72,27 @@ parser = do{
do{ crc <- anyWord8
; {- ack -} word8 $ ebusConstant "ACK"
; {- syn -} word8 $ ebusConstant "SYN"
- ; return (EbusMasterMaster, crc, Nothing)})
+ ; if True then -- CHECK CRC
+ return $ EbusPacket EbusMasterMaster source destination primaryCommand secondaryCommand payload Nothing
+ else
+ fail "Master-Master: CRC Check failed"})
<|>
-- Master Slave
try(
do{ crc <- anyWord8
; {- ack -} word8 $ ebusConstant "ACK"
; payloadSlaveLength <- anyWord8
- ; payloadSlave <- C.count (fromIntegral payloadSlaveLength) parserPayload
+ ; payloadSlave <- count (fromIntegral payloadSlaveLength) parserPayload
; crcSlave <- anyWord8
; {- ackSlave -} word8 $ ebusConstant "ACK"
; {- synSlave -} word8 $ ebusConstant "SYN"
- ; return (EbusMasterSlave, crc, (Just (payloadSlave, crcSlave)))})
+ ; if True then -- Check CRC
+ return $ EbusPacket EbusMasterSlave source destination primaryCommand secondaryCommand payload (Just payloadSlave)
+ else
+ fail "Master-Slave: CRC Check failed"})
+
<|>
fail "Failed to parse Master-Master/Master-Slave Packet"
- ; do {
- if True then --CHECK CRC
- return $ EbusPacket EbusMasterMaster source destination primaryCommand secondaryCommand payloadLength payload (Just [])
- else
- fail "CRC Check failed"}
+ ; return followup
<|> fail "Failed to parse packet"
- }
-
+ } \ No newline at end of file
diff --git a/ebus.cabal b/ebus.cabal
index ae04534..80aea75 100644
--- a/ebus.cabal
+++ b/ebus.cabal
@@ -32,4 +32,5 @@ Test-Suite test-network-ebus
Executable ebus-dump-layer2
Main-Is: exec/ebus-dump-layer2.hs
- Build-Depends: base >=4 && < 5, ebus
+ Build-Depends: base >=4 && < 5, ebus,
+ bytestring, attoparsec >= 0.10.1.1, attoparsec-enumerator >= 0.3, enumerator >= 0.4.18
diff --git a/exec/ebus-dump-layer2.hs b/exec/ebus-dump-layer2.hs
index 84d72e2..c8fd1b5 100644
--- a/exec/ebus-dump-layer2.hs
+++ b/exec/ebus-dump-layer2.hs
@@ -1,4 +1,41 @@
module Main(main) where
+
+import Network.EBus.Layer2
+import Data.Enumerator (Enumerator, Iteratee, run, ($$))
+import Data.Enumerator.Binary (enumHandle)
+import System.IO (hSetBinaryMode,stdin)
+import Data.ByteString (ByteString)
+import Data.Attoparsec.Enumerator (iterParser)
main = do
- print "Hello ebus-dump-layer"
+ -- * Select binary mode (True) or text mode (False) on a open handle. (See also openBinaryFile.)
+ hSetBinaryMode stdin True
+ -- * run
+ -- Run an iteratee until it finishes, and return either the final value (if it succeeded) or the error (if it failed).
+ -- * run_
+ -- Like run, except errors are converted to exceptions and thrown. Primarily useful for small scripts or other simple cases.
+
+ loop 100
+
+loop :: Int -> IO()
+loop 0 = do
+ print "finished"
+loop n = do
+ readAndDumpPacket
+ loop (n - 1)
+
+readAndDumpPacket :: IO()
+readAndDumpPacket = do
+ maybePacket <- run( enumSource $$ runParser )
+ case maybePacket of
+ Right result -> print result
+ Left error -> print error
+
+
+enumSource :: Enumerator ByteString IO a
+enumSource = enumHandle 1 stdin
+
+runParser :: Iteratee ByteString IO EbusPacket
+runParser = do
+ p <- iterParser ebusParserLayer2
+ return p