úÎLGÆ5      !"#$%&'()*+,-./01234 Safe-Infered5HDLC-like control characters 6ZNet 2.5 API id constants 57896:;<=>?@ABCDEF57896:;<=>?@ABCDEF57896:;<=>?@ABCDEFportable experimental#David Joyner <david@joynerhome.net> Safe-Infered GWhen XBee ZNet 2.5 modules join the network they are assigned a 16-bit  address. Note that unlike " which is unique and static for a  given node, a node's NetworkAddress is dynamic and may change over  time. BAll XBee ZNet 2.5 modules are identified by a unique (and static)  64-bit address. AT6 command names. These are limited to two bytes, e.g. ND for  neightbor discovery. DAPI frame types. See Section 6 of the XBee ZNet 2.5 Product Manual  ( 8ftp://ftp1.digi.com/support/documentation/90000866_C.pdf) ( for frame type-specific documentation. + Construct a  CommandName". Beware that this function will G if ) the name is not exactly two bytes long. ,Deconstruct a  CommandName. - Construct an Address". Beware that this function will G if . the address is not exactly eight bytes long. .Deconstruct an Address. / Construct a NetworkAddress". Beware that this function will G if , the address is not exactly two bytes long. 0Deconstruct a NetworkAddress. 8  !"#$%&'()*+,-./0HIJKLMN1  !"#$%&'()*+,-./01*)('&%$#"! +,-./0 ) *)('&%$#"! +,-./0HIJKLMNportable experimental#David Joyner <david@joynerhome.net> Safe-Infered14 runs in the O monad.  DecoderState tracks the  decoder's in/:out-of frame state, current frame length, and other state  variables. 2 Serialize a 6, escape control characters, and wrap the result with $ framing bytes. Return an array of P suitable for transmission  to the XBee modem. ,Note that this function returns an array of P . Encoding 6 takes place in a piece-wise manner and for efficiency's sake the individual , bits are not concatenated to form a single P. Typically this is * a non-issue however if you need a single P representation of the  % you can always obtain it by calling Q. Here's an example that illustrates 2 usage as well as the  on-the-wire frame format:  ' import qualified Data.ByteString as B ' import Network.Protocol.ZigBee.ZNet25  import Text.Printf  M main = hexdump $ B.concat $ encode (ATCommand 0 (commandName "ND") B.empty)  6 hexdump = mapM_ (putStr . printf "%02x ") . B.unpack  This prints:   7e 00 04 08 00 4e 44 65  The leading 7e> byte is the frame delimiter. This is followed by the 16-bit C frame length (4 bytes in this case), that many bytes of data (the  serialized (& frame), and the final checksum byte. 3Initial state needed to run 4 in the O monad. 4 Decode a P in the O monad, reversing the 2 L process. Once a frame delimiter byte is found, the inner frame payload is 4 unescaped, the checksum is verified, and finally a  is deserialized. ;Note that this function may produce zero or more errors or  s depending  on the 15 and input byte string. Errors will be reported for  checksum errors and  deserialization failures. Here''s a slightly more complex example that 2s two separate frames,  runs each array of P s through decode and prints the result  after running the O monad:   import Control.Monad.State ' import qualified Data.ByteString as B ' import Network.Protocol.ZigBee.ZNet25  @ main = putStrLn $ show $ evalState (mapM decode bs) initDecode  where 7 bs = concat $ map encode [atndCommand, txRequest] : atndCommand = ATCommand 1 (commandName "ND") B.empty L txRequest = ZigBeeTransmitRequest 2 addr nwaddr 0 0 $ B.singleton 0x55 P addr = address $ B.pack [ 0xde, 0xad, 0xbe, 0xef, 0xba, 0xda, 0xba, 0xda ] 5 nwaddr = networkAddress $ B.pack [ 0x55, 0xaa ]  This prints:  { [[],[],[],[Right (ATCommand 1 "ND" "")],[],[],[],[Right (ZigBeeTransmitRequest 2 de:ad:be:ef:ba:da:ba:da 55:aa 0 0 "U")]] Note a few things:  Each call to 2# apparently produced four separate Ps.  This is a by-product of the 2$ implementation as described above.  decode2 was only able to produce a result once the final P  of each - was processed. In this case the result was  R . If an error had occurred, we'd see S T  instead. 1234123421341234portable experimental#David Joyner <david@joynerhome.net> Safe-Infered5  !"#$%&'()*+,-./01234U      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[Y\]L^_L^`Labczigbee-znet25-0.1$Network.Protocol.ZigBee.ZNet25.Frame&Network.Protocol.ZigBee.ZNet25.Encoder(Network.Protocol.ZigBee.ZNet25.ConstantsNetwork.Protocol.ZigBee.ZNet25XBeeSensorMaskTransmitRetryCountTransmitOptionsSourceEndpoint SourceAction SampleCountRemoteNetworkAddress RemoteAddressReceiveOptions ProfileIdParentNetworkAddressModemStatusByteManufacturerIdFrameIdDiscoveryStatusDigitalChannelMaskDestinationEndpointDeliveryStatus DeviceType CommandStatusCommandOptions ClusterIdBroadcastRadiusAnalogChannelMaskNetworkAddressAddress CommandNameFrameNodeIdentificationIndicatorXBeeSensorReadIndicatorZigBeeIODataSampleIndicatorZigBeeExplicitRxIndicatorZigBeeReceivePacketZigBeeTransmitStatus$ExplicitAddressingZigBeeCommandFrameZigBeeTransmitRequestRemoteCommandResponseRemoteCommandRequestATCommandResponseATCommandQueueParameterValue ATCommand ModemStatusApiIdNotImplemented commandName unCommandNameaddress unAddressnetworkAddressunNetworkAddress DecoderStateencode initDecodedecodectrlFrameDelimapiIdModemStatus ctrlEscapectrlXonctrlXoffapiIdATCommand!apiIdATCommandQueueParameterValueapiIdATCommandResponseapiIdRemoteCommandRequestapiIdRemoteCommandResponseapiIdZigBeeTransmitRequest)apiIdExplicitAddressingZigBeeCommandFrameapiIdZigBeeTransmitStatusapiIdZigBeeReceivePacketapiIdZigBeeExplicitRxIndicator apiIdZigBeeIODataSampleIndicatorapiIdXBeeSensorReadIndicator apiIdNodeIdentificationIndicatorbaseGHC.Errerror$fSerializeNetworkAddress$fShowNetworkAddress$fSerializeAddress $fShowAddress$fSerializeCommandName$fShowCommandName$fSerializeFrametransformers-0.3.0.0Control.Monad.Trans.State.LazyStatebytestring-0.9.2.1Data.ByteString.Internal ByteStringData.ByteStringconcat Data.EitherRightLeftGHC.BaseString