Fork of my original MQTTGateway

Dependencies:   mbed-http

Files at this revision

API Documentation at this revision

Comitter:
vpcola
Date:
Sat Apr 08 14:43:14 2017 +0000
Commit message:
Initial commit

Changed in this revision

DownloadFile.cpp Show annotated file Show diff for this revision Revisions of this file
DownloadFile.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/FP/FP.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTConnect.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTConnectClient.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTConnectServer.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTDeserializePublish.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTPacket.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTPacket.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTPublish.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTSerializePublish.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTSubscribe.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTSubscribeClient.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTSubscribeServer.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTUnsubscribe.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTUnsubscribeClient.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTUnsubscribeServer.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/StackTrace.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/samples/publish-subscribe.txt Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/samples/simple-publish.txt Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/test/test1.txt Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTSManager.cpp Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTSManager.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTThreadedClient.cpp Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTThreadedClient.h Show annotated file Show diff for this revision Revisions of this file
NTPClient/NTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
NTPClient/NTPClient.h Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
Sensor.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/802_Frames.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/802_Frames.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/ApiFrame.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/ApiFrame.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/AtCmdFrame.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/AtCmdFrame.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IO.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSample802.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSample802.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSampleDM.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSampleDM.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSampleZB.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSampleZB.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Utils/Debug.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Utils/Utils.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Utils/Utils.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/Addresses.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/AtCommands.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/RadioConfig.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/XBee.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/XBee.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee802/XBee802.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee802/XBee802.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeDM/XBeeDM.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeDM/XBeeDM.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeLib.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeZB/XBeeZB.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeZB/XBeeZB.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XbeeMonitor.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XbeeMonitor.h Show annotated file Show diff for this revision Revisions of this file
config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/COMMIT_EDITMSG Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/08/9aa4faf066ddefa6bc0d01299ed49bd71084d1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/0c/5ae545f0b266388e47de8bd706c786d485c072 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/0c/77697463c204aa53467a8b7c6286c31b973792 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/0d/c426db510ec4f4c73bc14a75a9de181dae6868 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/0e/924fc9504c5fc4425adf30f7ad85a9fe0bf4fd Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/10/0eb67f6eeb7460798f95f873ddcae32a8351fb Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/15/3045d3887fcebc76e82914138658e28909cc27 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/15/a293e5d2fffb7c16297ca58e726ad492b7bf34 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/19/f6f960eb5519fcdb734d9a2e80410f647d04b5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/1b/01547f94c5552694a1930da954b2b7e8da1b0e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/1b/44cc5b9087fa700d29a7f1db48931b6300c35e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/1d/8ffaa66c2d016d8c178199016ebe139856747e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/22/0970a75eb458de640e38c7e828b2ba8df91609 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/24/d353af5e8cdcaccc11029ab3e8434a197429fa Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/25/b70564bc258cd7587f910879cb94645229170e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/2f/55ecfeb118a73bf8bb60ab39e41056ea7c6d0f Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/30/1381a684281af9da36a455d57477d9a390a445 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/32/57c0301a578f652c3b0657cbdcf0250cdc5e9c Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/34/54ed73977760f2225f2b0b270ef1dbaf4803d7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/37/93db5dfd5198501ebc68ecc7f0504a349f94a5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/39/5e3cd97d052c82c51bd63616ea0c4085f45b8b Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/3a/1c91cf64d117ae96314093920547c11ed4d383 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/3a/5abc3fe130697448aca19177aa3f16f7004c62 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/3b/a9f999525e8f002c7cf5287ecae64a0aeec4e1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/3e/fe7f33ae0768cec61cd9d6548100ffb4410a72 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/42/4ae3367662881a6b866594e66388dfbe52d0bb Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/43/f40bcc5c52a70f4103a1bacd35f7174fdac8f7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/45/cfc786f2e75ef5309c2854805d6d2ce80099a8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/49/1a3bac7f0f38ea74c31da2aa2526caee85b279 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/4a/b5b17c065d256e2debf9d2e3b637e87d70026e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/4f/9a5e30a4f3874754a919746b617c053e8b4d92 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/4f/c50217275c7fba4d8fd73bce2c8b3ea0b361a3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/53/8e08c93dcc43b769d6a726f9072ace0aeb8bd4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/53/8fa834d808c87aafad8d80127152d3239a31dc Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/57/4b1793787ca4916a0c612b5ddef4e15489288a Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/57/cea69ad98a66e7ef1417aea9335b2f00d71116 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/59/3b4d82760aae5f2917c5ffbcb402dff05271e5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/5a/733bd2750342660d9021bfc9b3583ca8c62668 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/5b/9cb8cea4a11b0ab974c991b527c9b79fceae75 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/5d/3d0e811967c9c6f33a710aa076e8b8b77defcf Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/5e/4887274fd6836189c01b70e285f277611f5f3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/61/9c1c17362546bdf3353a800c11f233a7b72667 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/63/bda56ba519dff1fbe82947624c4c4bada62a9d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/67/2acbfe9df9289ca9fb342ab410b8d5493c5b3a Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/67/d50bbba064b284ec7710e217f0f689c4ed1d78 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/67/db7cbdf804b235c8d3dc51ad5663de67de16ac Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/68/ee82789079b8a48165e7e6e5066b5d1005eed3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/6e/09ffca24c3167f6f723c486d8f1081812cc556 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/6f/b5842becaefd360f57916a587b5a0ffdc45ff0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/70/e399a0adb32a4e02d3f2056fe7d9ae31d57642 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/72/3542653307ea78efb2d8b91fc1f69e6d567574 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/73/2661d17a0fae8c97f0be83b806fee80a3747ea Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/7a/3ee2bd184ca8dc4d8c49a4522b41a7b89f8d66 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/81/9375ab99e86e6efad0037fb9cff4e6af7223a8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/83/d2cd6dc0dd26e72cda79e89b289b29a66c7988 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/84/1ff5b5ec24ff027d27a6310cedfb6155556544 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/86/e02b59351d6a9a0d7e24bf4f70d3ab0f4c5b20 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/89/60c27a28435820cca76958a2d83008022b0a3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/89/a75a6da3be993d2e5aa3c7d0319cd6fab45824 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/91/1f2ef98edaac9b09407b5c318591a923d1a784 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/91/dc650f5ab8eaf00b5aca3385e5c9ede505cfd4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/93/1a0a5600917e7417b35ac2e4f25943fb930b98 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/93/8f7f2f726027ab3fda9c83e6934898816a0579 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/9d/233c35352ff61aa11ad4c818e901e0306934e0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/9f/567936d77b8c2bbd7ea5098c468d8f3358d310 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/a0/45def3617364e04e5654c512d863108ee699f0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/a2/483c9ba7dcaefc56b311488e530f376dfcc521 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/a8/31423401dcec34451fc60dd3cb52d4b6bc210e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/a9/13964341394430cd3997c6f2950f93ba1d75c8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ab/96de702ba89e0ca322756726404ea6f96558e4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ae/123517e7c3743ef983ad88f9da3d7808930da2 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ae/9cc8adaa8fbb00061c04cd3c24055043c0489b Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/b8/9589db944f6c58d39808147f6749c0a96a0cc2 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/b9/34a4600d3166ffc8b7359c3d5478b07040701a Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/bb/44bf51b776018d2ae3ea4e2e3aa380eed15e31 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/c2/b63f8793187dfd8e4264149540e21fccb12b9a Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/c8/e294486870313e4d4daa7d7a0b76e4a79af386 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/c9/352112681d09e7af0fc996552c7e7d1656edca Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/cb/933fb19cda0a733a64d6b71d271fb6bdaf9e6d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ce/6cb88c4d7c1a85d8b00c0ccf9fba76ccf5d7d6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ce/95fc4ab9f28413df4d1fa2e30c13d62c468d54 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ce/a47621759ff67ffa4b191809c364943f9db1f3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d1/85bc59084cd7da4ea47470add793b304569c3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d2/6ab233dacac50f47ece4493b16311d45e1bb58 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d3/503403331d10000e1d061fe189c17f215d4e89 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d3/ab1936ef685518aeb35cf67e31465cffb25021 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d5/964336e2d7f627d0706902ad22acbf00bdcc50 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d5/ab2018616c4823c472bd3b71698eb00437383d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/dd/245e4b056ea2e4001e97e3bb329307e2da7adc Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e2/c6d1de117c2917df101208c066337e50fde2e5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e3/8c0cbab2fadf0f00c34eef2b4e593cdfa0f9f6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e5/119192cfc8c687fec99ab9c9c9fe8dca954524 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e6/1ba698f31f71693451e91f68bb2035706695b7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e7/925a2477ce8f61e73235ff25725b55046840c9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e8/b993a80e25977e8b2184415f6e8da1718c7a5e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ef/6c33a08523753da6a63b2818aba5b7d7d46ca1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/f5/6d654e0cc15325c291c707e0e13edbc1fb947f Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/f7/7df055e7907a3d9d3c4d77a578c0980d6b1466 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/fb/cc0ac33e944eb71feb80a1c40bf1baf5b2b61f Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/fb/eec5274508773d0f37c6893e794accf39e32f1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/fc/c6be1d2b7c64f0c2232d7559cd5e49bcb45171 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.gitignore Show annotated file Show diff for this revision Revisions of this file
easy-connect/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/.msub Show annotated file Show diff for this revision Revisions of this file
easy-connect/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/objects/pack/pack-cb9e3e95d81b3cf553d3174ae4ccbca538c03c13.idx Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/objects/pack/pack-cb9e3e95d81b3cf553d3174ae4ccbca538c03c13.pack Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.gitignore Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/LICENSE Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/module.json Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/source/AT86RFReg.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/source/at24mac.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/source/at24mac.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/easy-connect.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/07/bcb9b245abc132562d04eda40e8a19f1597603 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/09/3cbfaa677ad0f1a8b2e9e71e5eb3c9b59e5c6c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/16/80c8292e1addcea4defbe1d2469c4106964e89 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/18/7bb094d5f1910589e4bd343db0ce1fa0868c5f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/19/6587025cf513267b3951ed7ae861f6b5887854 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/19/99dae3ef80f9c4cb363ee01d9696dca1e4ad61 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/1c/f9de7a21e429683d2eb0b66fe432ed62076940 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/1d/a853686baeb82ad49a3096a35a6039e3784d0f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/1f/ebc6b296641ca1db45adc9dbeb6cd07a0c826f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/1f/fb7d341d8e640475216fbe547a27a414b6da8c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/22/3dd241b1fc8f44dd138118cf6fec74cd1a9bc0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/28/42cffee5a2e5ced2dd2be10ebef3706f615b42 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/29/cc547a20c724f7bc42b054348b67bbeaed6b19 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/29/d63ae2ee0a233e2fbd9577cdddc7661bb783d1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2b/043ceb297fac4e61b9692b067dc0aa687e908e Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2b/ac3dde128ea49dfedcf71a634d278a4d183721 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2c/b42275ecb72337156ccc82bd4b294c76478cc8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2d/4c36ef2e6528e1c8327babe5bedd834d6e558d Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2e/9e58d448e915e171348d6fcc3881e007359e87 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/35/4b47b19c9e48a6d2cc99bfb84838355ff8e59b Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/36/dcaec219088ae255ccd1b63a6bd213ea08b43a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/37/084b5e2bef8a8997323b0afb3d664c5143a7ed Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/3b/6d076031a93285f075bf9342b24b64db0e6082 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/40/050a429b64dacc27067d0c6f5ec1aa9858cedd Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/45/0cc128865ffb90b5cbfe5af193621644024fa7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/4a/3f18ae22a0402db6001e0b2145f79693c66a7f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/4e/d87bf7fe37d5ba0de6c4e78868f604a82f8ecb Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/58/8eb441e386da562bc0b29358186a0414b2eb21 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/58/e9a0ed3ecc7e05ddf9578c6153c2a4882e8484 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/60/7744089602deb46784e2f5d7bd815837f65a1f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/63/6af254ddfee68e83cd550e5184e253efa469a0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/63/da515ed94f2f08c3adf90b51458c4891e61347 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/69/aa3c94dc3fbc0fa13e539c0e958d787d17c8a6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/6f/c14e3cc6a40c322c8e5c4d8a2e9da552537027 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/71/cc5953f21d106855490b4ff1b08472472c3a3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/72/02907f786dec6fedf5618a1df556ebf15679c1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/74/b05f50b0d7e5e40753dceb5b55f44776572277 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/76/27ac0bc2f5d7e79d81861e328d7a44757e81d0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/77/d37a0a4d1dcf2348571c8407560f6786e4daf3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/83/1e027303af67fcf6df5adb872b801f6449ee3b Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/83/76fae074f632e3ca81ce6dfc91944c3cb11847 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/85/42c211a5de5eeccef8a9a9997f9321ba6d880c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/85/92c80138ba308aa332f6a427cfd97ac6eb3329 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/85/fbaf1da3ed19b09195fcb4138178b5f0f4c2c4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/86/45716bafafd88b0d67b2c3d12b8b8e4bf46a0a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/86/ed47c8bf40c86fdc569c7e678a8944f5e01c2a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8a/21294bb1073d2d6804235b6bc6af2fb2d08ce6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8a/ae3bd490162291eef8d92f0b169b9b8fd706a6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8b/3302ea06c0f2d012f20563700f48c7d75d4b3c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8d/1823c75c461e49fa7dc8f7cd0bc3a4eb980ef6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8e/0c9a889667fd3a837894a1cace2d8196a691a6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8f/231b0645ab4e7081eccc0b3a1bf366c70634e7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8f/2bc9cd442ea21d44a52c8bab55333c6941fb17 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/90/10cd39078cc91486da1d08547eb05660362c2c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/94/d0e46f45972aac11ae428b5cc64fe8a4ee6d27 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/95/3bb50291cd5a3100d0e45b128a5d266235e24a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/95/9c04625282673ad11f65ffd55ed8f97a1a0cea Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/98/2da6743ef487d0d0947cb5fc1f0b305ff310d3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/9d/54161261715aa62843752a37a092b48db56c27 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/a0/9061bb1823bd9c729a46cf3b2cd121063a5af1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/a3/b83979ec8272d283fb1a2ad25c9b9e74d9e0cf Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/a8/b5125912fe6450dcca33fa357ad7b5870cbeab Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/a8/d252d67bcbf06bbeb53aff60cb01f96136ef92 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/aa/bf2bfd8ad215d2080613cfe16a1ade42b65525 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/ad/baed3a1a00735f51ba1e24c38d552a80acd3b8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/b8/8add7ec5d94cae6d187ada1bcb5ab545eb846e Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/bb/8182f41bb5512e916d29be1c734aa9f1f19d2f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/c2/09d637a05d23a7390c41c594867e66cd7a2b61 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/c3/0ea2129fa524f9352ef4ec7388986fe0a3513f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/cc/460d8d2e1456b3734b3792da65ced4a132800f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/cc/760c5cfd58ef1044951e299f3ade8b9693ca1c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/cd/1bf66c5d69ec983c6dee28fc1e321f9f6467ec Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/d6/fc3baf28fbcb8e58792079af68bcc9c23e1dce Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/d9/141ca34383010414da53f1ca1b9e63f02d1c9c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/d9/566bd8f78b611da45730ac75e7a07eca493a03 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/da/dd0c5ed6c6246b0a1d800e832cf49b5ac008ea Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/db/de089f2f8ca06714f1f9c94212a5cb6d2aad02 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/dc/37b65ca877d969aa492f348626df6e1b0b1df0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/dd/16c394cb04f4bbad0e8d2103e5a33ff0e24bf5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/de/b0b90a3ec974c3b1634155711cdd74ed498d2e Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/e2/1cfb7dc779c8f4eb259d1d2beeb13fd1d18a68 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/e2/f0dc5443e5a1d9c7ad96f98202c93749158758 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/e4/2e2eeb911f57571bf2708fa7a9136f5bb677bb Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/e4/c54243acb2e7a28d0913dee7ebbe369311e8b3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/ed/2c98d0a9878f01b5a9996497223be7e1361fac Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/ee/fdaba7a9dee8e0b7db8b369517b7fe43258fbd Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/f0/bec599b1539dd61af8ccca0e7a640176f6709f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/f1/c3f75ad0a80184aa30155e298f07f373a75263 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/f3/e3d6d5476b159f82b07d3dec0220e1047bd9b0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/f9/7b41d3f75717a383be2c0410acb3137a725563 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/fc/0f1633de1d2b92aacc30e8cbee920f8e495b7f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/fd/612d3304a70f928496e13f3a54aba553b0dd9f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.msub Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/08/2f11ce298302a41ff877eed55ec226b944c24d Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/26/9f14532b98442669c50383782cbce1c67aced5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/27/80390d5b3a7ed7a95478fc61b1a8632b843d1b Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/4d/677496a85bcdfd5a2d8bd5260f36d92bec09a5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/52/f9e7d0c92be3026ed8e2d929f5a2f3af5c7216 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/7d/0e42380917cbd4e2b474ba5771a7e15215e74c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/80/0d8517da4d091eb52094a1cac0a66903aed59a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/93/e4cb7ebd99ce690370a168ac831cacea4034a9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/98/76baf6df887b76b6cb5da0a2e9bec41146001b Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/ac/0e4a88ca41a9de0f9d03f1d6b75ac2ba0b4ccc Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/e2/3cc82f00dee6d8a91d5fd2bbdf6f4b548a0ffe Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/f3/e3d6d5476b159f82b07d3dec0220e1047bd9b0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/ATParser.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/ATParser.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/Buffer/MyBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/Buffer/MyBuffer.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedPrint.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedSerial.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedSerial.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ESP8266.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ESP8266.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266Interface.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266Interface.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/02/865db7ef99ebab8b7ed5e1b5c19180d7001e2f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/0a/8554f3274c0bd641370e7847051bacfdeb8a66 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/0c/1a2859120b36fac35ce950bd266d04e3ed8507 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/0e/4cf3ee99953ca19984fe31ffe0644f6ab37f04 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/0f/a954a6c35d007da7c03f62ecc17f21f75652de Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/18/40de743f199fc7f402ff7bd3c56ccc58954c16 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/19/a06dee5ede2f7c27cce52cfb328e6006576c98 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/20/8d0295c1411f67259867fd86272a9dfe43cc3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/22/04c03fb0924bc71c988a1ce9a52d5db7e803c9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/2d/75557d97f1cae0d34baf502dcfcbd07ce45343 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/2e/9215af72d17010b1fd609eadb351a035386cf9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/31/b76e128c01acb9372970af3c0d4da92ba0ff3f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/3d/16f39f0b355ed14d158a5ad2ef66c345fd2669 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/40/97116916be1b04358ba3e84569012380657836 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/42/6961ba19e931271a202d1a43173b19976a45c4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/43/cb369dc7aa155af93995bb358bd259f891dda5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/4b/0221132ba0f8fb5cadb2609a9d7f8c2abc1e51 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/4e/1413bd42d39b48bd0547d8814d9d70529dabad Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/51/0214274c3a49819284e615389d631ca912ce15 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/55/8982806e80b6ece3193ff27e41a449277f853c Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/55/8ecca761792e7c80d03a5c0e99e47d49aadde3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/55/ed7949e6509ddcfe671046dc8e6bc6453fb767 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/59/48bc25260f0f636066c51c7a270d468f0583ce Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/5d/6da427b48ef68de41fac9f2478d7a05675c3b0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/62/0e5785b8fddff70d89319c3927eb08a1a9fad9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/63/037691d31e5413017548618fabfc13ea00962e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/65/e678ec229fe585dede1e6d6ceb2d29fcfc62f1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/67/83dfd110a5b808c5e1a5c09af0ba4b4818a75d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/70/ce9021485641775f9581928f71ef06450f418e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/71/f0db96a14bcfad5c51286ba67aec53a3674224 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/72/e873f0923bc4e89240029f43e9cb23ab674010 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/74/71c50c837b4b85d8f283182a23459d31793416 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/75/db2c976f25deba71e83141e88207472f633cfd Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/76/f34a69bbb943fe6f7fa00a011d7030e3383bf3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/79/a446a98e48485c9f91edf7bdb1d12167e3b7fc Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/7b/9a0ec7821de45f92ec0383eec2f02ea74932ff Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/7b/caf35e20fdcb92e43d2aa23903f041411e958c Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/84/fa8c082c87a2c4e4362605979e4e89c0e931c7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/85/8335a2b2b1b7b003319143c879b6783c18e4cb Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/8e/cf5b680ac9e4c2e8720a48324efbf1b1bd86f3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/90/b3c4025c969b2faa63f286c4571356b159a1a5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/95/0e428af5013a721584e45d71b45421d40158bc Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/95/26bfc5c480d5eab26293f158095da3dcde9a0e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/97/2c8c3de8a2a362d1dcb91e345dd7c5522e9305 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/97/421f5031567f4fc597d9a56e029c23f00caa13 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/97/df0e645d35bdd2071ab3c147eff48d500dde44 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a2/42e35bcea673ac39310b463fa06311bdca17de Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a2/8948345dfbd89719c60b765a9837ffbd434a2e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a4/ac803efe4c6b4adecb1c9b56c16be1f7802c66 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a5/6963aed6bef9d940e8d5708e06be2d71d929c8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a8/6dff3733344fb6369a5aaba25773f56042ff18 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/aa/5667ef467392729cf49612b8da3e8ecbab9120 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/aa/927dde7777cbb59654ea4f643e2eafd9d24db3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/ac/c25aa610ae854f7243fcce0205ab7b15be972d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/af/b0b546ecdd51f44169a66d906c5b65c2039da1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b1/ddea7d63ddbdc6e2ca59af6316f71ee8f9e70d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b3/a7d6982e43c7ba5a1db261e467571b36215683 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b5/90d12182647706581b143c94012c1462d619b8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b9/7c819a0e740b7f717b2981f75fe380827a1692 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b9/b1382eb53ac73320f1c20b2986a440c49722a6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/bc/5fe10fd97e239e5a26019580bf7c84e08cd97d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/c3/0d737b6eb86ea642f9ff66603945d3ee045ebf Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/c3/f2caeea01d744dee5e4e7640bfcfcd8b47075e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/c6/d6bc4cdb6628a5a9989fab8bc8e8cd9fd28168 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/c9/bad045a769d69d9709505db2db43c5c59da62d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/ca/29a807256ea38445915c68d57eadff7c2f4331 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/ca/56cae6cae0f6ddd60baaa8a92e87599d32831f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/cc/4b9cb12a800bdcf4b9f125230c28bbff6d32dd Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/cc/964c3d20a90fac64f7e640fbdcecc105fd5970 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/cc/f8ef134d4bd64a643af9f5d52802484df0caa9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/cd/38b72090af7baac8c9ccfb76709ea8eacad749 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d3/e76502e4bc7bcc0a7d1c77182353b54018b6f6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d5/04c2085fdd21e130930f01f2d9b393d88a8398 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d5/806d6ebede85680f75302f3fdad97a0050fb73 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d6/583d3fcffde81ccd638d1a801d564f90d59b89 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d7/8395e8087d68381c9476391fae880c1c76300f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d8/810e105d7d35315aa708ec51d821156cad45e9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/dc/169501b60ceb8f89ae8ddc1c6c261820f40c44 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/dc/321419e543344fd18d7facb378c2f3b82f63e8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/dc/9eef5f8e370a525df1c7ed24d0125e3c2d75ab Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/de/d8678fad855d8ca6b669dd448e03404ca6fc9f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/e1/e674c8b81f384254d415dcf6e42805a8eaad3a Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/eb/6f2c8e201c9f8228bcecd525415fb534129e1b Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/eb/99aed8db609de6df1874113d7ca16be82782d5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/ee/8495c80d204ddf972bf5f61d4f6e8ecac88261 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f3/2a5c3737a70dc828a90f140cf398ee9fbf176e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f4/32c6962076588227064fa4761bea534a62fbdf Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f5/710629b84db1290f7d4f8417fa638e896e3ae4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f5/f8b5f7d280ff8b10fd0ef96b3f739e5aca02ab Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f6/fbfc172fc798d2f1c15a49fadae84ed3f6b3c6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/fb/aec7f29a4a5fbc785378a235a9a866cc0d50ef Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/fc/1e7ca40846577040c56df52889ba212e0c24ae Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.gitignore Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/LICENSE Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/module.json Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/MCR20Drv.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/MCR20Drv.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/MCR20Overwrites.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/MCR20Reg.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/XcvrSpi.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-54cd72b06384ef3c69fe7a53d28e1b53ffe0b4ce.idx Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-54cd72b06384ef3c69fe7a53d28e1b53ffe0b4ce.pack Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.gitignore Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/NanostackRfPhySpirit1.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/SimpleSpirit1.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/contiki-conf.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/hw-config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/ip64-conf.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/platform-conf.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/radio.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1-config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1-const.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/stm32l-spirit1-config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/Release_Notes.html Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/MCU_Interface.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Aes.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Calibration.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Commands.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Csma.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_DirectRF.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_General.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Gpio.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Irq.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_LinearFifo.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Management.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktBasic.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktCommon.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktMbus.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktStack.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Qi.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Radio.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Regs.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Timer.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Types.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Aes.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Calibration.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Commands.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Csma.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_DirectRF.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_General.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Gpio.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Irq.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_LinearFifo.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Management.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktBasic.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktCommon.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktMbus.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktStack.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Qi.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Radio.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Timer.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Types.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/X-NUCLEO-IDS01Ax/radio_gpio.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/X-NUCLEO-IDS01Ax/radio_shield_config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/radio_spi.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/NanostackRfPhySpirit1.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/SimpleSpirit1.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/radio_spi.h Show annotated file Show diff for this revision Revisions of this file
jsmn/LICENSE Show annotated file Show diff for this revision Revisions of this file
jsmn/README.md Show annotated file Show diff for this revision Revisions of this file
jsmn/RadioCfg.cpp Show annotated file Show diff for this revision Revisions of this file
jsmn/RadioCfg.h Show annotated file Show diff for this revision Revisions of this file
jsmn/WeatherInfo.cpp Show annotated file Show diff for this revision Revisions of this file
jsmn/WeatherInfo.h Show annotated file Show diff for this revision Revisions of this file
jsmn/jsmn.c Show annotated file Show diff for this revision Revisions of this file
jsmn/jsmn.h Show annotated file Show diff for this revision Revisions of this file
jsmn/library.json Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-http.lib Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
mbed_settings.py Show annotated file Show diff for this revision Revisions of this file
mbedtls_entropy_config.h Show annotated file Show diff for this revision Revisions of this file
sd-driver.lib Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/objects/pack/pack-3818907d42dc76a69d2f1576b67ec166057798d1.idx Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/objects/pack/pack-3818907d42dc76a69d2f1576b67ec166057798d1.pack Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.meta Show annotated file Show diff for this revision Revisions of this file
sd-driver/README.md Show annotated file Show diff for this revision Revisions of this file
sd-driver/config/mbed_app.json Show annotated file Show diff for this revision Revisions of this file
sd-driver/docs/pics/sd_driver_k64_with_ci_test_shield.jpg Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/TESTS/examples/example1/example1.cpp Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/TESTS/filesystem/basic/basic.cpp Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/TESTS/filesystem/fopen/fopen.cpp Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/sd/SDBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/sd/SDBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/test/fsfat_debug.h Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/test/fsfat_test.c Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/test/fsfat_test.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r a1734fe1ec4b DownloadFile.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DownloadFile.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,149 @@
+#include "DownloadFile.h"
+#include "https_request.h"
+
+void dump_response(HttpResponse* res) 
+{
+    mbedtls_printf("\r\nStatus: %d - %s\r\n", res->get_status_code(), res->get_status_message().c_str());
+
+    mbedtls_printf("Headers:\r\n");
+    for (size_t ix = 0; ix < res->get_headers_length(); ix++) {
+        mbedtls_printf("\t%s: %s\r\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str());
+    }
+    mbedtls_printf("\nBody (%d bytes):\r\n\r\n%s\r\n", res->get_body_length(), res->get_body_as_string().c_str());
+}
+
+static unsigned int base64enc_len(const char *str) 
+{
+   return (((strlen(str)-1)/3)+1)<<2;
+}
+
+static void base64enc(const char *input, unsigned int length, char *output) 
+{
+   static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+   unsigned int c, c1, c2, c3;
+   for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
+     c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
+     c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
+     c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
+
+     c = ((c1 & 0xFC) >> 2);
+     output[j+0] = base64[c];
+     c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
+     output[j+1] = base64[c];
+     c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
+     output[j+2] = (length>i+1)?base64[c]:'=';
+     c = (c3 & 0x3F);
+     output[j+3] = (length>i+2)?base64[c]:'=';
+   }
+   output[(((length-1)/3)+1)<<2] = '\0';
+}
+
+static string encode(const string& str)
+{
+    char* out = new char[ base64enc_len(str.c_str()) ];
+    base64enc(str.c_str(), str.length(), out);
+    string res(out);
+    delete[] out;
+    return res;
+}
+
+void DownloadFile::basic_auth(const char * user, const char * password)
+{
+    authstr = user;
+    authstr += ":";
+    authstr += password;
+    printf("Auth Str : %s\r\n", authstr.c_str());
+
+    std::string base64str = encode(authstr);
+    printf("Base64 conversion : %s\r\n", base64str.c_str());
+    
+    authstr = "Basic " + base64str;
+    printf("Authorization: %s\r\n", authstr.c_str()); 
+}
+        
+HttpResponse* DownloadFile::get_file(const char * url)
+{
+    if (url == NULL) 
+        return NULL;
+
+    if(get_req != NULL) 
+        delete get_req;
+        
+    HttpResponse* get_res;
+    Callback<void(const char *at, size_t length)> aBodyCallback = NULL;
+    
+    if (fp != NULL)
+        aBodyCallback = mbed::callback(this, &DownloadFile::body_callback);
+    
+    if (useSSL)
+    {                
+        get_req_ssl = new HttpsRequest(network, 
+                pem, HTTP_GET, 
+                url,
+                aBodyCallback);
+                
+        if (!authstr.empty())
+            get_req_ssl->set_header("Authorization", authstr.c_str());
+            
+        get_req_ssl->set_debug(true);
+        
+        get_res = get_req_ssl->send();
+        
+    }
+    else
+    {
+        get_req = new HttpRequest(network, 
+                HTTP_GET, 
+                url,
+                aBodyCallback);
+    
+        if (!authstr.empty())
+            get_req->set_header("Authorization", authstr.c_str());
+            
+        get_res = get_req->send();        
+    }
+    
+    if (!get_res) {
+            printf("HttpRequest failed (error code %d)\r\n", get_req->get_error());
+            return NULL;
+    }
+    
+    //dump_response(get_res);
+
+    return get_res;    
+}
+
+std::string DownloadFile::get_file_content()
+{
+    size_t numread;
+    
+    if (fp == NULL) 
+        return "";
+        
+    // plain old c ..
+    // Determine file size
+    fseek(fp, 0, SEEK_END);
+    size_t size = ftell(fp);
+
+    char* dummy = new char[(sizeof(char) * size) + 1];
+
+    rewind(fp);
+    numread = fread(dummy, sizeof(char), size, fp);
+    // Make sure its NULL terminanted
+    dummy[numread] = 0;
+
+    // create a return string
+    std::string retstr = std::string((const char *) dummy);
+
+    delete[] dummy;
+
+    return retstr;
+}
+
+void DownloadFile::body_callback(const char* data, size_t data_len)
+{
+    // do something with the data
+    if (fp != NULL) {
+        size_written += fwrite((const void *) data, sizeof(char), data_len, fp);
+    }
+}
diff -r 000000000000 -r a1734fe1ec4b DownloadFile.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DownloadFile.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,80 @@
+#ifndef _DOWNLOAD_FILE_H_
+#define _DOWNLOAD_FILE_H_
+
+#include <stdio.h>
+#include <string>
+#include "mbed.h"
+#include "rtos.h"
+#include "NetworkInterface.h"
+#include "https_request.h"
+#include "http_request.h"
+
+class DownloadFile
+{
+    public:
+        DownloadFile(NetworkInterface* nw, const char * file = NULL, const char * capem = NULL)
+            :network(nw), 
+            filename(file), 
+            pem(capem), 
+            useSSL(capem != NULL), 
+            fp(NULL), 
+            size_written(0), 
+            get_req_ssl(NULL),
+            get_req(NULL)
+        {
+            if (filename)
+            {
+                fp = fopen(file, "w+");
+                if (fp != NULL)
+                    printf("File open successfull!\r\n");
+            }
+        }
+        
+        virtual ~DownloadFile()
+        {
+            if (fp != NULL) 
+                fclose(fp);
+            
+            // HttpsRequest destructor also free's up
+            // the HttpsResult ... so it must be consumed
+            // before this class goes out of scope
+            if(get_req)
+                delete get_req;
+            if(get_req_ssl)
+                delete get_req_ssl;
+        }
+ 
+        HttpResponse* get_file(const char * url);
+        
+        std::string get_file_content();
+        
+        const char * get_filename()
+        {
+            return filename;
+        }
+            
+        size_t get_written_size() {
+            return size_written;
+        }
+        
+        void basic_auth(const char * user, const char * password);
+
+        
+    protected:
+        void body_callback(const char* data, size_t data_len);
+        
+    private:
+        NetworkInterface* network;
+        const char * filename;
+        const char * pem; 
+        bool useSSL;
+        FILE * fp;
+        size_t size_written;
+        std::string authstr;
+        
+        HttpsRequest* get_req_ssl;
+        HttpRequest* get_req;
+};
+
+#endif
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/FP/FP.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/FP/FP.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,212 @@
+/**
+ * @file    FP.h
+ * @brief   Core Utility - Templated Function Pointer Class
+ * @author  sam grove
+ * @version 1.1
+ * @see     http://mbed.org/users/sam_grove/code/FP/
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FP_H
+#define FP_H
+
+/** Example using the FP Class with global functions
+ * @code
+ *  #include "mbed.h"
+ *  #include "FP.h"
+ *
+ *  FP<void,bool>fp;
+ *  DigitalOut myled(LED1);
+ *
+ *  void handler(bool value)
+ *  {
+ *      myled = value;
+ *      return;
+ *  }
+ *
+ *  int main()
+ *  {
+ *      fp.attach(&handler);
+ *
+ *      while(1)
+ *      {
+ *          fp(1);
+ *          wait(0.2);
+ *          fp(0);
+ *          wait(0.2);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/** Example using the FP Class with different class member functions
+ * @code
+ *  #include "mbed.h"
+ *  #include "FP.h"
+ *
+ *  FP<void,bool>fp;
+ *  DigitalOut myled(LED4);
+ *
+ *  class Wrapper
+ *  {
+ *  public:
+ *      Wrapper(){}
+ *
+ *      void handler(bool value)
+ *      {
+ *          myled = value;
+ *          return;
+ *      }
+ *  };
+ *
+ *  int main()
+ *  {
+ *      Wrapper wrapped;
+ *      fp.attach(&wrapped, &Wrapper::handler);
+ *
+ *      while(1)
+ *      {
+ *          fp(1);
+ *          wait(0.2);
+ *          fp(0);
+ *          wait(0.2);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/** Example using the FP Class with member FP and member function
+* @code
+*  #include "mbed.h"
+*  #include "FP.h"
+*
+*  DigitalOut myled(LED2);
+*
+*  class Wrapper
+*  {
+*  public:
+*      Wrapper()
+*      {
+*          fp.attach(this, &Wrapper::handler);
+*      }
+*
+*      void handler(bool value)
+*      {
+*          myled = value;
+*          return;
+*      }
+*
+*      FP<void,bool>fp;
+*  };
+*
+*  int main()
+*  {
+*      Wrapper wrapped;
+*
+*      while(1)
+*      {
+*          wrapped.fp(1);
+*          wait(0.2);
+*          wrapped.fp(0);
+*          wait(0.2);
+*      }
+*  }
+* @endcode
+*/
+
+/**
+ *  @class FP
+ *  @brief API for managing Function Pointers
+ */
+template<class retT, class argT>
+class FP
+{
+public:
+    /** Create the FP object - only one callback can be attached to the object, that is
+     *  a member function or a global function, not both at the same time
+     */
+    FP()
+    {
+        obj_callback = 0;
+        c_callback = 0;
+    }
+
+    /** Add a callback function to the object
+     *  @param item - Address of the initialized object
+     *  @param member - Address of the member function (dont forget the scope that the function is defined in)
+     */
+    template<class T>
+    void attach(T *item, retT (T::*method)(argT))
+    {
+        obj_callback = (FPtrDummy *)(item);
+        method_callback = (retT (FPtrDummy::*)(argT))(method);
+        return;
+    }
+
+    /** Add a callback function to the object
+     *  @param function - The address of a globally defined function
+     */
+    void attach(retT (*function)(argT))
+    {
+        c_callback = function;
+    }
+
+    /** Invoke the function attached to the class
+     *  @param arg - An argument that is passed into the function handler that is called
+     *  @return The return from the function hanlder called by this class
+     */
+    retT operator()(argT arg) const
+    {
+        if( 0 != c_callback ) {
+            return obj_callback ? (obj_callback->*method_callback)(arg) : (*c_callback)(arg);
+        }
+        return (retT)0;
+    }
+
+    /** Determine if an callback is currently hooked
+     *  @return 1 if a method is hooked, 0 otherwise
+     */
+    bool attached()
+    {
+        return obj_callback || c_callback;
+    }
+
+    /** Release a function from the callback hook
+     */
+    void detach()
+    {
+        obj_callback = 0;
+        c_callback = 0;
+    }
+
+private:
+
+    // empty type used for casting
+    class FPtrDummy;
+
+    FPtrDummy *obj_callback;
+
+    /**
+     *  @union Funciton
+     *  @brief Member or global callback function
+     */
+    union {
+        retT (*c_callback)(argT);                   /*!< Footprint for a global function */
+        retT (FPtrDummy::*method_callback)(argT);   /*!< Footprint for a member function */
+    };
+};
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTConnect.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTConnect.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - add connack return code definitions 
+ *******************************************************************************/
+
+#ifndef MQTTCONNECT_H_
+#define MQTTCONNECT_H_
+
+enum connack_return_codes
+{
+	MQTT_CONNECTION_ACCEPTED = 0,
+	MQTT_UNNACCEPTABLE_PROTOCOL = 1,
+	MQTT_CLIENTID_REJECTED = 2,
+	MQTT_SERVER_UNAVAILABLE = 3,
+	MQTT_BAD_USERNAME_OR_PASSWORD = 4,
+	MQTT_NOT_AUTHORIZED = 5,
+};
+	
+
+typedef union
+{
+	unsigned char all;	/**< all connect flags */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int username : 1;			/**< 3.1 user name */
+		unsigned int password : 1; 			/**< 3.1 password */
+		unsigned int willRetain : 1;		/**< will retain setting */
+		unsigned int willQoS : 2;				/**< will QoS value */
+		unsigned int will : 1;			    /**< will flag */
+		unsigned int cleansession : 1;	  /**< clean session flag */
+		unsigned int : 1;	  	          /**< unused */
+	} bits;
+#else
+	struct
+	{
+		unsigned int : 1;	     					/**< unused */
+		unsigned int cleansession : 1;	  /**< cleansession flag */
+		unsigned int will : 1;			    /**< will flag */
+		unsigned int willQoS : 2;				/**< will QoS value */
+		unsigned int willRetain : 1;		/**< will retain setting */
+		unsigned int password : 1; 			/**< 3.1 password */
+		unsigned int username : 1;			/**< 3.1 user name */
+	} bits;
+#endif
+} MQTTConnectFlags;	/**< connect flags byte */
+
+
+
+/**
+ * Defines the MQTT "Last Will and Testament" (LWT) settings for
+ * the connect packet.
+ */
+typedef struct
+{
+	/** The eyecatcher for this structure.  must be MQTW. */
+	char struct_id[4];
+	/** The version number of this structure.  Must be 0 */
+	int struct_version;
+	/** The LWT topic to which the LWT message will be published. */
+	MQTTString topicName;
+	/** The LWT payload. */
+	MQTTString message;
+	/**
+      * The retained flag for the LWT message (see MQTTAsync_message.retained).
+      */
+	unsigned char retained;
+	/**
+      * The quality of service setting for the LWT message (see
+      * MQTTAsync_message.qos and @ref qos).
+      */
+	char qos;
+} MQTTPacket_willOptions;
+
+
+#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
+
+
+typedef struct
+{
+	/** The eyecatcher for this structure.  must be MQTC. */
+	char struct_id[4];
+	/** The version number of this structure.  Must be 0 */
+	int struct_version;
+	/** Version of MQTT to be used.  3 = 3.1 4 = 3.1.1
+	  */
+	unsigned char MQTTVersion;
+	MQTTString clientID;
+	unsigned short keepAliveInterval;
+	unsigned char cleansession;
+	unsigned char willFlag;
+	MQTTPacket_willOptions will;
+	MQTTString username;
+	MQTTString password;
+} MQTTPacket_connectData;
+
+typedef union
+{
+	unsigned char all;	/**< all connack flags */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int sessionpresent : 1;    /**< session present flag */
+		unsigned int : y;	  	          /**< unused */
+	} bits;
+#else
+	struct
+	{
+		unsigned int : 7;	     			/**< unused */
+		unsigned int sessionpresent : 1;    /**< session present flag */
+	} bits;
+#endif
+} MQTTConnackFlags;	/**< connack flags byte */
+
+#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \
+		MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }
+
+int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options);
+int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len);
+
+int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent);
+int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen);
+
+int MQTTSerialize_disconnect(unsigned char* buf, int buflen);
+int MQTTSerialize_pingreq(unsigned char* buf, int buflen);
+
+#endif /* MQTTCONNECT_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTConnectClient.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTConnectClient.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+  * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
+  * @param options the options to be used to build the connect packet
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_connectLength(MQTTPacket_connectData* options)
+{
+	int len = 0;
+
+	FUNC_ENTRY;
+
+	if (options->MQTTVersion == 3)
+		len = 12; /* variable depending on MQTT or MQIsdp */
+	else if (options->MQTTVersion == 4)
+		len = 10;
+
+	len += MQTTstrlen(options->clientID)+2;
+	if (options->willFlag)
+		len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2;
+	if (options->username.cstring || options->username.lenstring.data)
+		len += MQTTstrlen(options->username)+2;
+	if (options->password.cstring || options->password.lenstring.data)
+		len += MQTTstrlen(options->password)+2;
+
+	FUNC_EXIT_RC(len);
+	return len;
+}
+
+
+/**
+  * Serializes the connect options into the buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param len the length in bytes of the supplied buffer
+  * @param options the options to be used to build the connect packet
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options)
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	MQTTConnectFlags flags = {0};
+	int len = 0;
+	int rc = -1;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.byte = 0;
+	header.bits.type = CONNECT;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
+
+	if (options->MQTTVersion == 4)
+	{
+		writeCString(&ptr, "MQTT");
+		writeChar(&ptr, (char) 4);
+	}
+	else
+	{
+		writeCString(&ptr, "MQIsdp");
+		writeChar(&ptr, (char) 3);
+	}
+
+	flags.all = 0;
+	flags.bits.cleansession = options->cleansession;
+	flags.bits.will = (options->willFlag) ? 1 : 0;
+	if (flags.bits.will)
+	{
+		flags.bits.willQoS = options->will.qos;
+		flags.bits.willRetain = options->will.retained;
+	}
+
+	if (options->username.cstring || options->username.lenstring.data)
+		flags.bits.username = 1;
+	if (options->password.cstring || options->password.lenstring.data)
+		flags.bits.password = 1;
+
+	writeChar(&ptr, flags.all);
+	writeInt(&ptr, options->keepAliveInterval);
+	writeMQTTString(&ptr, options->clientID);
+	if (options->willFlag)
+	{
+		writeMQTTString(&ptr, options->will.topicName);
+		writeMQTTString(&ptr, options->will.message);
+	}
+	if (flags.bits.username)
+		writeMQTTString(&ptr, options->username);
+	if (flags.bits.password)
+		writeMQTTString(&ptr, options->password);
+
+	rc = ptr - buf;
+
+	exit: FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Deserializes the supplied (wire) buffer into connack data - return code
+  * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
+  * @param connack_rc returned integer value of the connack return code
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param len the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen;
+	MQTTConnackFlags flags = {0};
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != CONNACK)
+		goto exit;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+	if (enddata - curdata < 2)
+		goto exit;
+
+	flags.all = readChar(&curdata);
+	*sessionPresent = flags.bits.sessionpresent;
+	*connack_rc = readChar(&curdata);
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+  * @param packettype the message type
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype)
+{
+	MQTTHeader header = {0};
+	int rc = -1;
+	unsigned char *ptr = buf;
+
+	FUNC_ENTRY;
+	if (buflen < 2)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = packettype;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_disconnect(unsigned char* buf, int buflen)
+{
+	return MQTTSerialize_zero(buf, buflen, DISCONNECT);
+}
+
+
+/**
+  * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_pingreq(unsigned char* buf, int buflen)
+{
+	return MQTTSerialize_zero(buf, buflen, PINGREQ);
+}
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTConnectServer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTConnectServer.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+#include <string.h>
+
+#define min(a, b) ((a < b) ? a : b)
+
+
+/**
+  * Validates MQTT protocol name and version combinations
+  * @param protocol the MQTT protocol name as an MQTTString
+  * @param version the MQTT protocol version number, as in the connect packet
+  * @return correct MQTT combination?  1 is true, 0 is false
+  */
+int MQTTPacket_checkVersion(MQTTString* protocol, int version)
+{
+	int rc = 0;
+
+	if (version == 3 && memcmp(protocol->lenstring.data, "MQIdsp",
+			min(6, protocol->lenstring.len)) == 0)
+		rc = 1;
+	else if (version == 4 && memcmp(protocol->lenstring.data, "MQTT",
+			min(4, protocol->lenstring.len)) == 0)
+		rc = 1;
+	return rc;
+}
+
+
+/**
+  * Deserializes the supplied (wire) buffer into connect data structure
+  * @param data the connect data structure to be filled out
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param len the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len)
+{
+	MQTTHeader header = {0};
+	MQTTConnectFlags flags = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = &buf[len];
+	int rc = 0;
+	MQTTString Protocol;
+	int version;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != CONNECT)
+		goto exit;
+
+	curdata += MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */
+
+	if (!readMQTTLenString(&Protocol, &curdata, enddata) ||
+		enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */
+		goto exit;
+
+	version = (int)readChar(&curdata); /* Protocol version */
+	/* If we don't recognize the protocol version, we don't parse the connect packet on the
+	 * basis that we don't know what the format will be.
+	 */
+	if (MQTTPacket_checkVersion(&Protocol, version))
+	{
+		flags.all = readChar(&curdata);
+		data->cleansession = flags.bits.cleansession;
+		data->keepAliveInterval = readInt(&curdata);
+		if (!readMQTTLenString(&data->clientID, &curdata, enddata))
+			goto exit;
+		if (flags.bits.will)
+		{
+			data->willFlag = 1;
+			data->will.qos = flags.bits.willQoS;
+			data->will.retained = flags.bits.willRetain;
+			if (!readMQTTLenString(&data->will.topicName, &curdata, enddata) ||
+				  !readMQTTLenString(&data->will.message, &curdata, enddata))
+				goto exit;
+		}
+		if (flags.bits.username)
+		{
+			if (enddata - curdata < 3 || !readMQTTLenString(&data->username, &curdata, enddata))
+				goto exit; /* username flag set, but no username supplied - invalid */
+			if (flags.bits.password &&
+				(enddata - curdata < 3 || !readMQTTLenString(&data->password, &curdata, enddata)))
+				goto exit; /* password flag set, but no password supplied - invalid */
+		}
+		else if (flags.bits.password)
+			goto exit; /* password flag set without username - invalid */
+		rc = 1;
+	}
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes the connack packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param connack_rc the integer connack return code to be used 
+  * @param sessionPresent the MQTT 3.1.1 sessionPresent flag
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent)
+{
+	MQTTHeader header = {0};
+	int rc = 0;
+	unsigned char *ptr = buf;
+	MQTTConnackFlags flags = {0};
+
+	FUNC_ENTRY;
+	if (buflen < 2)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = CONNACK;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+
+	flags.all = 0;
+	flags.bits.sessionpresent = sessionPresent;
+	writeChar(&ptr, flags.all); 
+	writeChar(&ptr, connack_rc);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTDeserializePublish.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTDeserializePublish.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+#include <string.h>
+
+#define min(a, b) ((a < b) ? 1 : 0)
+
+/**
+  * Deserializes the supplied (wire) buffer into publish data
+  * @param dup returned integer - the MQTT dup flag
+  * @param qos returned integer - the MQTT QoS value
+  * @param retained returned integer - the MQTT retained flag
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param topicName returned MQTTString - the MQTT topic in the publish
+  * @param payload returned byte buffer - the MQTT publish payload
+  * @param payloadlen returned integer - the length of the MQTT payload
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success
+  */
+int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
+		unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != PUBLISH)
+		goto exit;
+	*dup = header.bits.dup;
+	*qos = header.bits.qos;
+	*retained = header.bits.retain;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	if (!readMQTTLenString(topicName, &curdata, enddata) ||
+		enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */
+		goto exit;
+
+	if (*qos > 0)
+		*packetid = readInt(&curdata);
+
+	*payloadlen = enddata - curdata;
+	*payload = curdata;
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Deserializes the supplied (wire) buffer into an ack
+  * @param packettype returned integer - the MQTT packet type
+  * @param dup returned integer - the MQTT dup flag
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	*dup = header.bits.dup;
+	*packettype = header.bits.type;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	if (enddata - curdata < 2)
+		goto exit;
+	*packetid = readInt(&curdata);
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTPacket.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTPacket.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,453 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+
+#include <string.h>
+
+/**
+ * Encodes the message length according to the MQTT algorithm
+ * @param buf the buffer into which the encoded data is written
+ * @param length the length to be encoded
+ * @return the number of bytes written to buffer
+ */
+int MQTTPacket_encode(unsigned char* buf, int length)
+{
+	int rc = 0;
+
+	FUNC_ENTRY;
+	do
+	{
+		char d = length % 128;
+		length /= 128;
+		/* if there are more digits to encode, set the top bit of this digit */
+		if (length > 0)
+			d |= 0x80;
+		buf[rc++] = d;
+	} while (length > 0);
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+ * Decodes the message length according to the MQTT algorithm
+ * @param getcharfn pointer to function to read the next character from the data source
+ * @param value the decoded length returned
+ * @return the number of bytes read from the socket
+ */
+int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value)
+{
+	unsigned char c;
+	int multiplier = 1;
+	int len = 0;
+#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
+
+	FUNC_ENTRY;
+	*value = 0;
+	do
+	{
+		int rc = MQTTPACKET_READ_ERROR;
+
+		if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+		{
+			rc = MQTTPACKET_READ_ERROR;	/* bad data */
+			goto exit;
+		}
+		rc = (*getcharfn)(&c, 1);
+		if (rc != 1)
+			goto exit;
+		*value += (c & 127) * multiplier;
+		multiplier *= 128;
+	} while ((c & 128) != 0);
+exit:
+	FUNC_EXIT_RC(len);
+	return len;
+}
+
+
+int MQTTPacket_len(int rem_len)
+{
+	rem_len += 1; /* header byte */
+
+	/* now remaining_length field */
+	if (rem_len < 128)
+		rem_len += 1;
+	else if (rem_len < 16384)
+		rem_len += 2;
+	else if (rem_len < 2097151)
+		rem_len += 3;
+	else
+		rem_len += 4;
+	return rem_len;
+}
+
+
+static unsigned char* bufptr;
+
+int bufchar(unsigned char* c, int count)
+{
+	int i;
+
+	for (i = 0; i < count; ++i)
+		*c = *bufptr++;
+	return count;
+}
+
+
+int MQTTPacket_decodeBuf(unsigned char* buf, int* value)
+{
+	bufptr = buf;
+	return MQTTPacket_decode(bufchar, value);
+}
+
+
+/**
+ * Calculates an integer from two bytes read from the input buffer
+ * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
+ * @return the integer value calculated
+ */
+int readInt(unsigned char** pptr)
+{
+	unsigned char* ptr = *pptr;
+	int len = 256*(*ptr) + (*(ptr+1));
+	*pptr += 2;
+	return len;
+}
+
+
+/**
+ * Reads one character from the input buffer.
+ * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
+ * @return the character read
+ */
+char readChar(unsigned char** pptr)
+{
+	char c = **pptr;
+	(*pptr)++;
+	return c;
+}
+
+
+/**
+ * Writes one character to an output buffer.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param c the character to write
+ */
+void writeChar(unsigned char** pptr, char c)
+{
+	**pptr = c;
+	(*pptr)++;
+}
+
+
+/**
+ * Writes an integer as 2 bytes to an output buffer.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param anInt the integer to write
+ */
+void writeInt(unsigned char** pptr, int anInt)
+{
+	**pptr = (unsigned char)(anInt / 256);
+	(*pptr)++;
+	**pptr = (unsigned char)(anInt % 256);
+	(*pptr)++;
+}
+
+
+/**
+ * Writes a "UTF" string to an output buffer.  Converts C string to length-delimited.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param string the C string to write
+ */
+void writeCString(unsigned char** pptr, const char* string)
+{
+	int len = strlen(string);
+	writeInt(pptr, len);
+	memcpy(*pptr, string, len);
+	*pptr += len;
+}
+
+
+int getLenStringLen(char* ptr)
+{
+	int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
+	return len;
+}
+
+
+void writeMQTTString(unsigned char** pptr, MQTTString mqttstring)
+{
+	if (mqttstring.lenstring.len > 0)
+	{
+		writeInt(pptr, mqttstring.lenstring.len);
+		memcpy(*pptr, mqttstring.lenstring.data, mqttstring.lenstring.len);
+		*pptr += mqttstring.lenstring.len;
+	}
+	else if (mqttstring.cstring)
+		writeCString(pptr, mqttstring.cstring);
+	else
+		writeInt(pptr, 0);
+}
+
+
+/**
+ * @param mqttstring the MQTTString structure into which the data is to be read
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param enddata pointer to the end of the data: do not read beyond
+ * @return 1 if successful, 0 if not
+ */
+int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata)
+{
+	int rc = 0;
+
+	FUNC_ENTRY;
+	/* the first two bytes are the length of the string */
+	if (enddata - (*pptr) > 1) /* enough length to read the integer? */
+	{
+		mqttstring->lenstring.len = readInt(pptr); /* increments pptr to point past length */
+		if (&(*pptr)[mqttstring->lenstring.len] <= enddata)
+		{
+			mqttstring->lenstring.data = (char*)*pptr;
+			*pptr += mqttstring->lenstring.len;
+			rc = 1;
+		}
+	}
+	mqttstring->cstring = NULL;
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+ * Return the length of the MQTTstring - C string if there is one, otherwise the length delimited string
+ * @param mqttstring the string to return the length of
+ * @return the length of the string
+ */
+int MQTTstrlen(MQTTString mqttstring)
+{
+	int rc = 0;
+
+	if (mqttstring.cstring)
+		rc = strlen(mqttstring.cstring);
+	else
+		rc = mqttstring.lenstring.len;
+	return rc;
+}
+
+
+/**
+ * Compares an MQTTString to a C string
+ * @param a the MQTTString to compare
+ * @param bptr the C string to compare
+ * @return boolean - equal or not
+ */
+int MQTTPacket_equals(MQTTString* a, char* bptr)
+{
+	int alen = 0,
+		blen = 0;
+	char *aptr;
+	
+	if (a->cstring)
+	{
+		aptr = a->cstring;
+		alen = strlen(a->cstring);
+	}
+	else
+	{
+		aptr = a->lenstring.data;
+		alen = a->lenstring.len;
+	}
+	blen = strlen(bptr);
+	
+	return (alen == blen) && (strncmp(aptr, bptr, alen) == 0);
+}
+
+
+/**
+ * Helper function to read packet data from some source into a buffer
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param getfn pointer to a function which will read any number of bytes from the needed source
+ * @return integer MQTT packet type, or -1 on error
+ */
+int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int))
+{
+	int rc = -1;
+	MQTTHeader header = {0};
+	int len = 0;
+	int rem_len = 0;
+
+	/* 1. read the header byte.  This has the packet type in it */
+	if ((*getfn)(buf, 1) != 1)
+		goto exit;
+
+	len = 1;
+	/* 2. read the remaining length.  This is variable in itself */
+	MQTTPacket_decode(getfn, &rem_len);
+	len += MQTTPacket_encode(buf + 1, rem_len); /* put the original remaining length back into the buffer */
+
+	/* 3. read the rest of the buffer using a callback to supply the rest of the data */
+	if ((*getfn)(buf + len, rem_len) != rem_len)
+		goto exit;
+
+	header.byte = buf[0];
+	rc = header.bits.type;
+exit:
+	return rc;
+}
+
+
+const char* MQTTPacket_names[] =
+{
+	"RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL",
+	"PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK",
+	"PINGREQ", "PINGRESP", "DISCONNECT"
+};
+
+
+char* MQTTPacket_toString(char* strbuf, int strbuflen, unsigned char* buf, int buflen)
+{
+	int index = 0;
+	int rem_length = 0;
+	MQTTHeader header = {0};
+	int strindex = 0;
+
+	header.byte = buf[index++];
+	index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
+
+	switch (header.bits.type)
+	{
+	case CONNECT:
+	{
+		MQTTPacket_connectData data;
+		if (MQTTDeserialize_connect(&data, buf, buflen) == 1)
+		{
+			strindex = snprintf(strbuf, strbuflen,
+				"CONNECT MQTT version %d, client id %.*s, clean session %d, keep alive %hd",
+				(int)data.MQTTVersion, data.clientID.lenstring.len, data.clientID.lenstring.data,
+				(int)data.cleansession, data.keepAliveInterval);
+			if (data.willFlag)
+				strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+				", will QoS %d, will retain %d, will topic %.*s, will message %.*s",
+				data.will.qos, data.will.retained,
+				data.will.topicName.lenstring.len, data.will.topicName.lenstring.data,
+				data.will.message.lenstring.len, data.will.message.lenstring.data);
+			if (data.username.lenstring.data && data.username.lenstring.len > 0)
+			{
+				printf("user name\n");
+				strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+				", user name %.*s", data.username.lenstring.len, data.username.lenstring.data);
+			}
+			if (data.password.lenstring.data && data.password.lenstring.len > 0)
+				strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+				", password %.*s", data.password.lenstring.len, data.password.lenstring.data);
+		}
+	}
+	break;
+	case CONNACK:
+	{
+		unsigned char sessionPresent, connack_rc;
+		if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+			"CONNACK session present %d, rc %d", sessionPresent, connack_rc);
+	}
+	break;
+	case PUBLISH:
+	{
+		unsigned char dup, retained, *payload;
+		unsigned short packetid;
+		int qos, payloadlen;
+		MQTTString topicName = MQTTString_initializer;
+		if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
+				&payload, &payloadlen, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"PUBLISH dup %d, QoS %d, retained %d, packet id %d, topic %.*s, payload length %d, payload %.*s",
+				dup, qos, retained, packetid,
+				(topicName.lenstring.len < 20) ? topicName.lenstring.len : 20, topicName.lenstring.data,
+				payloadlen, (payloadlen < 20) ? payloadlen : 20, payload);
+	}
+	break;
+	case PUBACK:
+	case PUBREC:
+	case PUBREL:
+	case PUBCOMP:
+	{
+		unsigned char packettype, dup;
+		unsigned short packetid;
+		if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"%s dup %d, packet id %d",
+				MQTTPacket_names[packettype], dup, packetid);
+	}
+	break;
+	case SUBSCRIBE:
+	{
+		unsigned char dup;
+		unsigned short packetid;
+		int maxcount = 1, count = 0;
+		MQTTString topicFilters[1];
+		int requestedQoSs[1];
+		if (MQTTDeserialize_subscribe(&dup, &packetid, maxcount, &count,
+				topicFilters, requestedQoSs, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"SUBSCRIBE dup %d, packet id %d count %d topic %.*s qos %d",
+				dup, packetid, count,
+				topicFilters[0].lenstring.len, topicFilters[0].lenstring.data,
+				requestedQoSs[0]);
+	}
+	break;
+	case SUBACK:
+	{
+		unsigned short packetid;
+		int maxcount = 1, count = 0;
+		int grantedQoSs[1];
+		if (MQTTDeserialize_suback(&packetid, maxcount, &count, grantedQoSs, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"SUBACK packet id %d count %d granted qos %d",
+				packetid, count, grantedQoSs[0]);
+	}
+	break;
+	case UNSUBSCRIBE:
+	{
+		unsigned char dup;
+		unsigned short packetid;
+		int maxcount = 1, count = 0;
+		MQTTString topicFilters[1];
+		if (MQTTDeserialize_unsubscribe(&dup, &packetid, maxcount, &count, topicFilters, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"UNSUBSCRIBE dup %d, packet id %d count %d topic %.*s",
+				dup, packetid, count,
+				topicFilters[0].lenstring.len, topicFilters[0].lenstring.data);
+	}
+	break;
+	case UNSUBACK:
+	{
+		unsigned short packetid;
+		if (MQTTDeserialize_unsuback(&packetid, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"UNSUBACK packet id %d", packetid);
+	}
+	break;
+	case PINGREQ:
+	case PINGRESP:
+	case DISCONNECT:
+		strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
+		break;
+	}
+	return strbuf;
+}
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTPacket.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTPacket.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef MQTTPACKET_H_
+#define MQTTPACKET_H_
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+enum errors
+{
+	MQTTPACKET_BUFFER_TOO_SHORT = -2,
+	MQTTPACKET_READ_ERROR = -1,
+	MQTTPACKET_READ_COMPLETE,
+};
+
+enum msgTypes
+{
+	CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
+	PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
+	PINGREQ, PINGRESP, DISCONNECT
+};
+
+/**
+ * Bitfields for the MQTT header byte.
+ */
+typedef union
+{
+	unsigned char byte;	                /**< the whole byte */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int type : 4;			/**< message type nibble */
+		unsigned int dup : 1;				/**< DUP flag bit */
+		unsigned int qos : 2;				/**< QoS value, 0, 1 or 2 */
+		unsigned int retain : 1;		/**< retained flag bit */
+	} bits;
+#else
+	struct
+	{
+		unsigned int retain : 1;		/**< retained flag bit */
+		unsigned int qos : 2;				/**< QoS value, 0, 1 or 2 */
+		unsigned int dup : 1;				/**< DUP flag bit */
+		unsigned int type : 4;			/**< message type nibble */
+	} bits;
+#endif
+} MQTTHeader;
+
+typedef struct
+{
+	int len;
+	char* data;
+} MQTTLenString;
+
+typedef struct
+{
+	char* cstring;
+	MQTTLenString lenstring;
+} MQTTString;
+
+#define MQTTString_initializer {NULL, {0, NULL}}
+
+int MQTTstrlen(MQTTString mqttstring);
+
+#include "MQTTConnect.h"
+#include "MQTTPublish.h"
+#include "MQTTSubscribe.h"
+#include "MQTTUnsubscribe.h"
+
+int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid);
+int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen);
+
+int MQTTPacket_len(int rem_len);
+int MQTTPacket_equals(MQTTString* a, char* b);
+
+int MQTTPacket_encode(unsigned char* buf, int length);
+int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value);
+int MQTTPacket_decodeBuf(unsigned char* buf, int* value);
+
+int readInt(unsigned char** pptr);
+char readChar(unsigned char** pptr);
+void writeChar(unsigned char** pptr, char c);
+void writeInt(unsigned char** pptr, int anInt);
+int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata);
+void writeCString(unsigned char** pptr, const char* string);
+void writeMQTTString(unsigned char** pptr, MQTTString mqttstring);
+
+int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int));
+
+char* MQTTPacket_toString(char* strbuf, int strbuflen, unsigned char* buf, int buflen);
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+
+#endif /* MQTTPACKET_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTPublish.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTPublish.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef MQTTPUBLISH_H_
+#define MQTTPUBLISH_H_
+
+int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
+		MQTTString topicName, unsigned char* payload, int payloadlen);
+
+int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
+		unsigned char** payload, int* payloadlen, unsigned char* buf, int len);
+
+int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid);
+int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid);
+int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid);
+
+#endif /* MQTTPUBLISH_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTSerializePublish.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTSerializePublish.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+  * Determines the length of the MQTT publish packet that would be produced using the supplied parameters
+  * @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0)
+  * @param topicName the topic name to be used in the publish  
+  * @param payloadlen the length of the payload to be sent
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_publishLength(int qos, MQTTString topicName, int payloadlen)
+{
+	int len = 0;
+
+	len += 2 + MQTTstrlen(topicName) + payloadlen;
+	if (qos > 0)
+		len += 2; /* packetid */
+	return len;
+}
+
+
+/**
+  * Serializes the supplied publish data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param dup integer - the MQTT dup flag
+  * @param qos integer - the MQTT QoS value
+  * @param retained integer - the MQTT retained flag
+  * @param packetid integer - the MQTT packet identifier
+  * @param topicName MQTTString - the MQTT topic in the publish
+  * @param payload byte buffer - the MQTT publish payload
+  * @param payloadlen integer - the length of the MQTT payload
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
+		MQTTString topicName, unsigned char* payload, int payloadlen)
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	int rem_len = 0;
+	int rc = 0;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(rem_len = MQTTSerialize_publishLength(qos, topicName, payloadlen)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.bits.type = PUBLISH;
+	header.bits.dup = dup;
+	header.bits.qos = qos;
+	header.bits.retain = retained;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+	writeMQTTString(&ptr, topicName);
+
+	if (qos > 0)
+		writeInt(&ptr, packetid);
+
+	memcpy(ptr, payload, payloadlen);
+	ptr += payloadlen;
+
+	rc = ptr - buf;
+
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Serializes the ack packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param type the MQTT packet type
+  * @param dup the MQTT dup flag
+  * @param packetid the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char packettype, unsigned char dup, unsigned short packetid)
+{
+	MQTTHeader header = {0};
+	int rc = 0;
+	unsigned char *ptr = buf;
+
+	FUNC_ENTRY;
+	if (buflen < 4)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.bits.type = packettype;
+	header.bits.dup = dup;
+	header.bits.qos = 0;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+	writeInt(&ptr, packetid);
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes a puback packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid)
+{
+	return MQTTSerialize_ack(buf, buflen, PUBACK, packetid, 0);
+}
+
+
+/**
+  * Serializes a pubrel packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param dup integer - the MQTT dup flag
+  * @param packetid integer - the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid)
+{
+	return MQTTSerialize_ack(buf, buflen, PUBREL, packetid, dup);
+}
+
+
+/**
+  * Serializes a pubrel packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid)
+{
+	return MQTTSerialize_ack(buf, buflen, PUBCOMP, packetid, 0);
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTSubscribe.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTSubscribe.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef MQTTSUBSCRIBE_H_
+#define MQTTSUBSCRIBE_H_
+
+int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[], int requestedQoSs[]);
+
+int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid,
+		int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], unsigned char* buf, int len);
+
+int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs);
+
+int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int len);
+
+
+#endif /* MQTTSUBSCRIBE_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTSubscribeClient.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTSubscribeClient.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+  * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters
+  * @param count the number of topic filter strings in topicFilters
+  * @param topicFilters the array of topic filter strings to be used in the publish
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_subscribeLength(int count, MQTTString topicFilters[])
+{
+	int i;
+	int len = 2; /* packetid */
+
+	for (i = 0; i < count; ++i)
+		len += 2 + MQTTstrlen(topicFilters[i]) + 1; /* length + topic + req_qos */
+	return len;
+}
+
+
+/**
+  * Serializes the supplied subscribe data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied bufferr
+  * @param dup integer - the MQTT dup flag
+  * @param packetid integer - the MQTT packet identifier
+  * @param count - number of members in the topicFilters and reqQos arrays
+  * @param topicFilters - array of topic filter names
+  * @param requestedQoSs - array of requested QoS
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, int count,
+		MQTTString topicFilters[], int requestedQoSs[])
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	int rem_len = 0;
+	int rc = 0;
+	int i = 0;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(rem_len = MQTTSerialize_subscribeLength(count, topicFilters)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.byte = 0;
+	header.bits.type = SUBSCRIBE;
+	header.bits.dup = dup;
+	header.bits.qos = 1;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+	writeInt(&ptr, packetid);
+
+	for (i = 0; i < count; ++i)
+	{
+		writeMQTTString(&ptr, topicFilters[i]);
+		writeChar(&ptr, requestedQoSs[i]);
+	}
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Deserializes the supplied (wire) buffer into suback data
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param maxcount - the maximum number of members allowed in the grantedQoSs array
+  * @param count returned integer - number of members in the grantedQoSs array
+  * @param grantedQoSs returned array of integers - the granted qualities of service
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != SUBACK)
+		goto exit;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+	if (enddata - curdata < 2)
+		goto exit;
+
+	*packetid = readInt(&curdata);
+
+	*count = 0;
+	while (curdata < enddata)
+	{
+		if (*count > maxcount)
+		{
+			rc = -1;
+			goto exit;
+		}
+		grantedQoSs[(*count)++] = readChar(&curdata);
+	}
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTSubscribeServer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTSubscribeServer.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+  * Deserializes the supplied (wire) buffer into subscribe data
+  * @param dup integer returned - the MQTT dup flag
+  * @param packetid integer returned - the MQTT packet identifier
+  * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
+  * @param count - number of members in the topicFilters and requestedQoSs arrays
+  * @param topicFilters - array of topic filter names
+  * @param requestedQoSs - array of requested QoS
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
+	int requestedQoSs[], unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = -1;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != SUBSCRIBE)
+		goto exit;
+	*dup = header.bits.dup;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	*packetid = readInt(&curdata);
+
+	*count = 0;
+	while (curdata < enddata)
+	{
+		if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
+			goto exit;
+		if (curdata >= enddata) /* do we have enough data to read the req_qos version byte? */
+			goto exit;
+		requestedQoSs[*count] = readChar(&curdata);
+		(*count)++;
+	}
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes the supplied suback data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @param count - number of members in the grantedQoSs array
+  * @param grantedQoSs - array of granted QoS
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs)
+{
+	MQTTHeader header = {0};
+	int rc = -1;
+	unsigned char *ptr = buf;
+	int i;
+
+	FUNC_ENTRY;
+	if (buflen < 2 + count)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = SUBACK;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2 + count); /* write remaining length */
+
+	writeInt(&ptr, packetid);
+
+	for (i = 0; i < count; ++i)
+		writeChar(&ptr, grantedQoSs[i]);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTUnsubscribe.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTUnsubscribe.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef MQTTUNSUBSCRIBE_H_
+#define MQTTUNSUBSCRIBE_H_
+
+int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[]);
+
+int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int max_count, int* count, MQTTString topicFilters[],
+		unsigned char* buf, int len);
+
+int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid);
+
+int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int len);
+
+#endif /* MQTTUNSUBSCRIBE_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTUnsubscribeClient.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTUnsubscribeClient.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+  * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters
+  * @param count the number of topic filter strings in topicFilters
+  * @param topicFilters the array of topic filter strings to be used in the publish
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_unsubscribeLength(int count, MQTTString topicFilters[])
+{
+	int i;
+	int len = 2; /* packetid */
+
+	for (i = 0; i < count; ++i)
+		len += 2 + MQTTstrlen(topicFilters[i]); /* length + topic*/
+	return len;
+}
+
+
+/**
+  * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @param dup integer - the MQTT dup flag
+  * @param packetid integer - the MQTT packet identifier
+  * @param count - number of members in the topicFilters array
+  * @param topicFilters - array of topic filter names
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[])
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	int rem_len = 0;
+	int rc = -1;
+	int i = 0;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(rem_len = MQTTSerialize_unsubscribeLength(count, topicFilters)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.byte = 0;
+	header.bits.type = UNSUBSCRIBE;
+	header.bits.dup = dup;
+	header.bits.qos = 1;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+	writeInt(&ptr, packetid);
+
+	for (i = 0; i < count; ++i)
+		writeMQTTString(&ptr, topicFilters[i]);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Deserializes the supplied (wire) buffer into unsuback data
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen)
+{
+	unsigned char type = 0;
+	unsigned char dup = 0;
+	int rc = 0;
+
+	FUNC_ENTRY;
+	rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen);
+	if (type == UNSUBACK)
+		rc = 1;
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTUnsubscribeServer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTUnsubscribeServer.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+  * Deserializes the supplied (wire) buffer into unsubscribe data
+  * @param dup integer returned - the MQTT dup flag
+  * @param packetid integer returned - the MQTT packet identifier
+  * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
+  * @param count - number of members in the topicFilters and requestedQoSs arrays
+  * @param topicFilters - array of topic filter names
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
+		unsigned char* buf, int len)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != UNSUBSCRIBE)
+		goto exit;
+	*dup = header.bits.dup;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	*packetid = readInt(&curdata);
+
+	*count = 0;
+	while (curdata < enddata)
+	{
+		if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
+			goto exit;
+		(*count)++;
+	}
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes the supplied unsuback data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid)
+{
+	MQTTHeader header = {0};
+	int rc = 0;
+	unsigned char *ptr = buf;
+
+	FUNC_ENTRY;
+	if (buflen < 2)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = UNSUBACK;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+
+	writeInt(&ptr, packetid);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/StackTrace.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/StackTrace.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - fix for bug #434081
+ *******************************************************************************/
+
+#ifndef STACKTRACE_H_
+#define STACKTRACE_H_
+
+#include <stdio.h>
+#define NOSTACKTRACE 1
+
+#if defined(NOSTACKTRACE)
+#define FUNC_ENTRY
+#define FUNC_ENTRY_NOLOG
+#define FUNC_ENTRY_MED
+#define FUNC_ENTRY_MAX
+#define FUNC_EXIT
+#define FUNC_EXIT_NOLOG
+#define FUNC_EXIT_MED
+#define FUNC_EXIT_MAX
+#define FUNC_EXIT_RC(x)
+#define FUNC_EXIT_MED_RC(x)
+#define FUNC_EXIT_MAX_RC(x)
+
+#else
+
+#if defined(WIN32)
+#define inline __inline
+#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM)
+#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1)
+#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM)
+#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM)
+#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM)
+#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1)
+#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM)
+#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM)
+#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM)
+#else
+#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM)
+#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1)
+#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM)
+#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM)
+#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM)
+#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1)
+#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM)
+#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM)
+#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM)
+
+void StackTrace_entry(const char* name, int line, int trace);
+void StackTrace_exit(const char* name, int line, void* return_value, int trace);
+
+void StackTrace_printStack(FILE* dest);
+char* StackTrace_get(unsigned long);
+
+#endif
+
+#endif
+
+
+
+
+#endif /* STACKTRACE_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/samples/publish-subscribe.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/samples/publish-subscribe.txt	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,115 @@
+#include "MQTTPacket.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "EthernetInterface.h"
+
+
+TCPSocketConnection mysock; 
+
+int getdata(char* buf, int count)
+{
+    return mysock.receive(buf, (size_t)count);
+}
+
+int toStop = 0;
+
+
+int main()
+{
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+    int rc = 0;
+    char buf[200];
+    int buflen = sizeof(buf);
+    int msgid = 1;
+    MQTTString topicString = MQTTString_initializer;
+    int req_qos = 0;
+    char* payload = "mypayload";
+    int payloadlen = strlen(payload);
+    int len = 0;
+    EthernetInterface eth;
+    
+    eth.init(); //Use DHCP
+    eth.connect();
+
+    rc = mysock.connect("m2m.eclipse.org", 1883);
+
+    data.clientID.cstring = "SendReceive mbed MQTT ";
+    data.keepAliveInterval = 20;
+    data.cleansession = 1;
+
+    mysock.set_blocking(true, 1000);  /* 1 second Timeout */
+
+    len = MQTTSerialize_connect(buf, buflen, &data);
+    rc = mysock.send(buf, len);
+
+    /* wait for connack */
+    if (MQTTPacket_read(buf, buflen, getdata) == CONNACK)
+    {
+        int connack_rc;
+
+        if (MQTTDeserialize_connack(&connack_rc, buf, buflen) != 1 || connack_rc != 0)
+        {
+            printf("Unable to connect, return code %d\n", connack_rc);
+            goto exit;
+        }
+    }
+    else
+        goto exit;
+
+    /* subscribe */
+    topicString.cstring = "substopic";
+    len = MQTTSerialize_subscribe(buf, buflen, 0, msgid, 1, &topicString, &req_qos);
+
+    rc = mysock.send(buf, len);
+    if (MQTTPacket_read(buf, buflen, getdata) == SUBACK)    /* wait for suback */
+    {
+        int submsgid;
+        int subcount;
+        int granted_qos;
+
+        rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen);
+        if (granted_qos != 0)
+        {
+            printf("granted qos != 0, %d\n", granted_qos);
+            goto exit;
+        }
+    }
+    else
+        goto exit;
+
+    topicString.cstring = "pubtopic";
+    while (!toStop)
+    {
+        if (MQTTPacket_read(buf, buflen, getdata) == PUBLISH)
+        {
+            int dup;
+            int qos;
+            int retained;
+            int msgid;
+            int payloadlen_in;
+            char* payload_in;
+            int rc;
+            MQTTString receivedTopic;
+
+            rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,
+                    &payload_in, &payloadlen_in, buf, buflen);
+            printf("message arrived %.*s\n", payloadlen_in, payload_in);
+        }
+
+        printf("publishing reading\n");
+        len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, topicString, payload, payloadlen);
+        rc = mysock.send(buf, len);
+    }
+
+    printf("disconnecting\n");
+    len = MQTTSerialize_disconnect(buf, buflen);
+    rc = mysock.send(buf, len);
+
+exit:    
+    eth.disconnect();
+
+    return 0;
+}
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/samples/simple-publish.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/samples/simple-publish.txt	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "mbed.h"
+#include "EthernetInterface.h"
+#include "C12832_lcd.h"
+
+#include "MQTTPacket.h"
+
+DigitalOut myled(LED2);
+C12832_LCD lcd;
+
+int publish()
+{
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+    int rc = 0;
+    char buf[200];
+    int buflen = sizeof(buf);
+    TCPSocketConnection mysock; 
+    MQTTString topicString = MQTTString_initializer;
+    char* payload = "I'm alive!";
+    int payloadlen = strlen(payload);
+    int len = 0;
+    
+    mysock.connect("m2m.eclipse.org", 1883);
+          
+    data.clientID.cstring = "mbed test client - Ian Craggs";
+    data.keepAliveInterval = 20;
+    data.cleansession = 1;
+    data.MQTTVersion = 3;
+
+    len = MQTTSerialize_connect(buf, buflen, &data);
+
+    topicString.cstring = "mbed NXP LPC1768";
+    len += MQTTSerialize_publish(buf + len, buflen - len, 0, 0, 0, 0, topicString, payload, payloadlen);
+
+    len += MQTTSerialize_disconnect(buf + len, buflen - len);
+
+    rc = 0;
+    while (rc < len)
+    {
+        int rc1 = mysock.send(buf, len);
+        if (rc1 == -1)
+        {
+            lcd.printf("Send failed\n");
+            break;
+        }
+        else
+            rc += rc1;
+    }
+    if (rc == len)
+        lcd.printf("Send succeeded\n");
+    wait(0.2);
+
+    return 0;
+}
+
+int main()
+{
+    EthernetInterface eth;
+    eth.init(); //Use DHCP
+    eth.connect();
+    lcd.printf("IP Address is %s\n", eth.getIPAddress());
+    
+    while(1) 
+    {
+        myled = 1;
+        publish();
+        wait(0.2);
+        myled = 0;
+        publish();
+        wait(0.2);
+    }
+    
+    eth.disconnect();
+}
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/test/test1.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/test/test1.txt	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,631 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+
+#include "MQTTPacket.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#if !defined(_WINDOWS)
+	#include <sys/time.h>
+  	#include <sys/socket.h>
+	#include <unistd.h>
+  	#include <errno.h>
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#define MAXHOSTNAMELEN 256
+#define EAGAIN WSAEWOULDBLOCK
+#define EINTR WSAEINTR
+#define EINPROGRESS WSAEINPROGRESS
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define ENOTCONN WSAENOTCONN
+#define ECONNRESET WSAECONNRESET
+#endif
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+struct Options
+{
+	char* connection;         /**< connection to system under test. */
+	char** haconnections;
+	int hacount;
+	int verbose;
+	int test_no;
+} options =
+{
+	"tcp://m2m.eclipse.org:1883",
+	NULL,
+	0,
+	0,
+	0,
+};
+
+void usage()
+{
+
+}
+
+void getopts(int argc, char** argv)
+{
+	int count = 1;
+
+	while (count < argc)
+	{
+		if (strcmp(argv[count], "--test_no") == 0)
+		{
+			if (++count < argc)
+				options.test_no = atoi(argv[count]);
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--connection") == 0)
+		{
+			if (++count < argc)
+			{
+				options.connection = argv[count];
+				printf("\nSetting connection to %s\n", options.connection);
+			}
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--haconnections") == 0)
+		{
+			if (++count < argc)
+			{
+				char* tok = strtok(argv[count], " ");
+				options.hacount = 0;
+				options.haconnections = malloc(sizeof(char*) * 5);
+				while (tok)
+				{
+					options.haconnections[options.hacount] = malloc(strlen(tok) + 1);
+					strcpy(options.haconnections[options.hacount], tok);
+					options.hacount++;
+					tok = strtok(NULL, " ");
+				}
+			}
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--verbose") == 0)
+		{
+			options.verbose = 1;
+			printf("\nSetting verbose on\n");
+		}
+		count++;
+	}
+}
+
+
+#define LOGA_DEBUG 0
+#define LOGA_INFO 1
+#include <stdarg.h>
+#include <time.h>
+#include <sys/timeb.h>
+void MyLog(int LOGA_level, char* format, ...)
+{
+	static char msg_buf[256];
+	va_list args;
+	struct timeb ts;
+
+	struct tm *timeinfo;
+
+	if (LOGA_level == LOGA_DEBUG && options.verbose == 0)
+	  return;
+
+	ftime(&ts);
+	timeinfo = localtime(&ts.time);
+	strftime(msg_buf, 80, "%Y%m%d %H%M%S", timeinfo);
+
+	sprintf(&msg_buf[strlen(msg_buf)], ".%.3hu ", ts.millitm);
+
+	va_start(args, format);
+	vsnprintf(&msg_buf[strlen(msg_buf)], sizeof(msg_buf) - strlen(msg_buf), format, args);
+	va_end(args);
+
+	printf("%s\n", msg_buf);
+	fflush(stdout);
+}
+
+
+#if defined(WIN32) || defined(_WINDOWS)
+#define mqsleep(A) Sleep(1000*A)
+#define START_TIME_TYPE DWORD
+static DWORD start_time = 0;
+START_TIME_TYPE start_clock(void)
+{
+	return GetTickCount();
+}
+#elif defined(AIX)
+#define mqsleep sleep
+#define START_TIME_TYPE struct timespec
+START_TIME_TYPE start_clock(void)
+{
+	static struct timespec start;
+	clock_gettime(CLOCK_REALTIME, &start);
+	return start;
+}
+#else
+#define mqsleep sleep
+#define START_TIME_TYPE struct timeval
+/* TODO - unused - remove? static struct timeval start_time; */
+START_TIME_TYPE start_clock(void)
+{
+	struct timeval start_time;
+	gettimeofday(&start_time, NULL);
+	return start_time;
+}
+#endif
+
+
+#if defined(WIN32)
+long elapsed(START_TIME_TYPE start_time)
+{
+	return GetTickCount() - start_time;
+}
+#elif defined(AIX)
+#define assert(a)
+long elapsed(struct timespec start)
+{
+	struct timespec now, res;
+
+	clock_gettime(CLOCK_REALTIME, &now);
+	ntimersub(now, start, res);
+	return (res.tv_sec)*1000L + (res.tv_nsec)/1000000L;
+}
+#else
+long elapsed(START_TIME_TYPE start_time)
+{
+	struct timeval now, res;
+
+	gettimeofday(&now, NULL);
+	timersub(&now, &start_time, &res);
+	return (res.tv_sec)*1000 + (res.tv_usec)/1000;
+}
+#endif
+
+
+#define assert(a, b, c, d) myassert(__FILE__, __LINE__, a, b, c, d)
+#define assert1(a, b, c, d, e) myassert(__FILE__, __LINE__, a, b, c, d, e)
+
+int tests = 0;
+int failures = 0;
+FILE* xml;
+START_TIME_TYPE global_start_time;
+char output[3000];
+char* cur_output = output;
+
+
+void write_test_result()
+{
+	long duration = elapsed(global_start_time);
+
+	fprintf(xml, " time=\"%ld.%.3ld\" >\n", duration / 1000, duration % 1000);
+	if (cur_output != output)
+	{
+		fprintf(xml, "%s", output);
+		cur_output = output;
+	}
+	fprintf(xml, "</testcase>\n");
+}
+
+
+void myassert(char* filename, int lineno, char* description, int value, char* format, ...)
+{
+	++tests;
+	if (!value)
+	{
+		va_list args;
+
+		++failures;
+		printf("Assertion failed, file %s, line %d, description: %s\n", filename, lineno, description);
+
+		va_start(args, format);
+		vprintf(format, args);
+		va_end(args);
+
+		cur_output += sprintf(cur_output, "<failure type=\"%s\">file %s, line %d </failure>\n",
+                        description, filename, lineno);
+	}
+    else
+    	MyLog(LOGA_DEBUG, "Assertion succeeded, file %s, line %d, description: %s", filename, lineno, description);
+}
+
+#define min(a, b) ((a < b) ? a : b)
+
+int checkMQTTStrings(MQTTString a, MQTTString b)
+{
+	if (!a.lenstring.data)
+	{
+		a.lenstring.data = a.cstring;
+		if (a.cstring)
+			a.lenstring.len = strlen(a.cstring);
+	}
+	if (!b.lenstring.data)
+	{
+		b.lenstring.data = b.cstring;
+		if (b.cstring)
+			b.lenstring.len = strlen(b.cstring);
+	}
+	return memcmp(a.lenstring.data, b.lenstring.data, min(a.lenstring.len, b.lenstring.len)) == 0;
+}
+
+
+int checkConnectPackets(MQTTPacket_connectData* before, MQTTPacket_connectData* after)
+{
+	int rc = 0;
+	int start_failures = failures;
+
+	assert("struct_ids should be the same",
+			memcmp(before->struct_id, after->struct_id, 4) == 0, "struct_ids were different %.4s\n", after->struct_id);
+
+	assert("struct_versions should be the same",
+			before->struct_version == after->struct_version, "struct_versions were different\n", rc);
+
+	assert("MQTT versions should be the same",
+			before->MQTTVersion == after->MQTTVersion, "MQTT versions were different\n", rc);
+
+	assert("ClientIDs should be the same",
+			checkMQTTStrings(before->clientID, after->clientID), "ClientIDs were different\n", rc);
+
+	assert("keepAliveIntervals should be the same",
+			before->keepAliveInterval == after->keepAliveInterval, "keepAliveIntervals were different %d\n", after->keepAliveInterval);
+
+	assert("cleansessions should be the same",
+			before->cleansession == after->cleansession, "cleansessions were different\n", rc);
+
+	assert("willFlags should be the same",
+				before->willFlag == after->willFlag, "willFlags were different\n", rc);
+
+	if (before->willFlag)
+	{
+		assert("will struct_ids should be the same",
+				memcmp(before->will.struct_id, after->will.struct_id, 4) == 0, "will struct_ids were different %.4s\n", after->struct_id);
+
+		assert("will struct_versions should be the same",
+				before->will.struct_version == after->will.struct_version, "will struct_versions were different\n", rc);
+
+		assert("topic names should be the same",
+				checkMQTTStrings(before->will.topicName, after->will.topicName), "topic names were different\n", rc);
+
+		assert("messages should be the same",
+				checkMQTTStrings(before->will.message, after->will.message), "messages were different\n", rc);
+
+		assert("retained flags should be the same",
+					before->will.retained == after->will.retained, "retained flags were different\n", rc);
+
+		assert("will qos should be the same",
+					before->will.qos == after->will.qos, "will qos were different\n", rc);
+	}
+
+	assert("usernames should be the same",
+			checkMQTTStrings(before->clientID, after->clientID), "usernames were different\n", rc);
+	assert("passwords should be the same",
+			checkMQTTStrings(before->password, after->password), "passwords were different\n", rc);
+	return failures == start_failures;
+}
+
+int test1(struct Options options)
+{
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	MQTTPacket_connectData data_after = MQTTPacket_connectData_initializer;
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 1 - serialization of connect and back");
+
+	data.clientID.cstring = "me";
+
+	data.keepAliveInterval = 20;
+	data.cleansession = 1;
+	data.username.cstring = "testuser";
+	data.password.cstring = "testpassword";
+
+	data.willFlag = 1;
+	data.will.message.cstring = "will message";
+	data.will.qos = 1;
+	data.will.retained = 0;
+	data.will.topicName.cstring = "will topic";
+
+	rc = MQTTSerialize_connect(buf, buflen, &data);
+	assert("good rc from serialize connect", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_connect(&data_after, buf, buflen);
+	assert("good rc from deserialize connect", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	rc = checkConnectPackets(&data, &data_after);
+	assert("packets should be the same",  rc == 1, "packets were different\n", rc);
+
+/* exit: */
+	MyLog(LOGA_INFO, "TEST1: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int test2(struct Options options)
+{
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+
+	unsigned char dup = 0;
+	int qos = 2;
+	unsigned char retained = 0;
+	int msgid = 23;
+	MQTTString topicString = MQTTString_initializer;
+	char *payload = "kkhkhkjkj jkjjk jk jk ";
+	int payloadlen = strlen(payload);
+
+	unsigned char dup2 = 1;
+	int qos2 = 1;
+	unsigned char retained2 = 1;
+	int msgid2 = 3243;
+	MQTTString topicString2 = MQTTString_initializer;
+	char *payload2 = NULL;
+	int payloadlen2 = 0;
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 2 - serialization of publish and back");
+
+	topicString.cstring = "mytopic";
+	rc = MQTTSerialize_publish(buf, buflen, dup, qos, retained, msgid, topicString,
+			payload, payloadlen);
+	assert("good rc from serialize publish", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_publish(&dup2, &qos2, &retained2, &msgid2, &topicString2,
+			&payload2, &payloadlen2, buf, buflen);
+	assert("good rc from deserialize publish", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
+	assert("qoss should be the same", qos == qos2, "qoss were different %d\n", qos2);
+	assert("retaineds should be the same", retained == retained2, "retaineds were different %d\n", retained2);
+	assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
+
+	assert("topics should be the same",
+					checkMQTTStrings(topicString, topicString2), "topics were different %s\n", ""); //topicString2);
+
+	assert("payload lengths should be the same",
+				payloadlen == payloadlen2, "payload lengths were different %d\n", payloadlen2);
+
+	assert("payloads should be the same",
+						memcmp(payload, payload2, payloadlen) == 0, "payloads were different %s\n", "");
+
+/*exit:*/
+	MyLog(LOGA_INFO, "TEST2: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+
+int test3(struct Options options)
+{
+	int i = 0;
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+#define TOPIC_COUNT 2
+
+	int dup = 0;
+	int msgid = 23;
+	int count = TOPIC_COUNT;
+	MQTTString topicStrings[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
+	int req_qoss[TOPIC_COUNT] = {2, 1};
+
+	int dup2 = 1;
+	int msgid2 = 2223;
+	int count2 = 0;
+	MQTTString topicStrings2[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
+	int req_qoss2[TOPIC_COUNT] = {0, 0};
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 2 - serialization of subscribe and back");
+
+	topicStrings[0].cstring = "mytopic";
+	topicStrings[1].cstring = "mytopic2";
+	rc = MQTTSerialize_subscribe(buf, buflen, dup, msgid, count, topicStrings, req_qoss);
+	assert("good rc from serialize subscribe", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_subscribe(&dup2, &msgid2, 2, &count2, topicStrings2, req_qoss2, buf, buflen);
+	assert("good rc from deserialize subscribe", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
+	assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
+
+	assert("count should be the same", count == count2, "counts were different %d\n", count2);
+
+	for (i = 0; i < count2; ++i)
+	{
+		assert("topics should be the same",
+					checkMQTTStrings(topicStrings[i], topicStrings2[i]), "topics were different %s\n", "");
+
+		assert("qoss should be the same", req_qoss[i] == req_qoss2[i], "qoss were different %d\n", req_qoss2[i]);
+	}
+
+/*exit:*/
+	MyLog(LOGA_INFO, "TEST3: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int test4(struct Options options)
+{
+	int i = 0;
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+#define TOPIC_COUNT 2
+
+	int msgid = 23;
+	int count = TOPIC_COUNT;
+	int granted_qoss[TOPIC_COUNT] = {2, 1};
+;
+	int msgid2 = 2223;
+	int count2 = 0;
+	int granted_qoss2[TOPIC_COUNT] = {0, 0};
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 4 - serialization of suback and back");
+
+	rc = MQTTSerialize_suback(buf, buflen, msgid, count, granted_qoss);
+	assert("good rc from serialize suback", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_suback(&msgid2, 2, &count2, granted_qoss2, buf, buflen);
+	assert("good rc from deserialize suback", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
+
+	assert("count should be the same", count == count2, "counts were different %d\n", count2);
+
+	for (i = 0; i < count2; ++i)
+		assert("qoss should be the same", granted_qoss[i] == granted_qoss2[i], "qoss were different %d\n", granted_qoss2[i]);
+
+/* exit: */
+	MyLog(LOGA_INFO, "TEST4: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int test5(struct Options options)
+{
+	int i = 0;
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+#define TOPIC_COUNT 2
+
+	int dup = 0;
+	int msgid = 23;
+	int count = TOPIC_COUNT;
+	MQTTString topicStrings[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
+
+	int dup2 = 1;
+	int msgid2 = 2223;
+	int count2 = 0;
+	MQTTString topicStrings2[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 2 - serialization of unsubscribe and back");
+
+	topicStrings[0].cstring = "mytopic";
+	topicStrings[1].cstring = "mytopic2";
+	rc = MQTTSerialize_unsubscribe(buf, buflen, dup, msgid, count, topicStrings);
+	assert("good rc from serialize unsubscribe", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_unsubscribe(&dup2, &msgid2, 2, &count2, topicStrings2, buf, buflen);
+	assert("good rc from deserialize unsubscribe", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
+	assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
+
+	assert("count should be the same", count == count2, "counts were different %d\n", count2);
+
+	for (i = 0; i < count2; ++i)
+		assert("topics should be the same",
+					checkMQTTStrings(topicStrings[i], topicStrings2[i]), "topics were different %s\n", "");
+
+/* exit: */
+	MyLog(LOGA_INFO, "TEST5: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int test6(struct Options options)
+{
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+
+	int connack_rc = 77;
+
+	int connack_rc2 = 0;
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 2 - serialization of connack and back");
+
+	rc = MQTTSerialize_connack(buf, buflen, connack_rc);
+	assert("good rc from serialize connack", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_connack(&connack_rc2, buf, buflen);
+	assert("good rc from deserialize connack", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("dups should be the same", connack_rc == connack_rc2, "dups were different %d\n", connack_rc2);
+
+/* exit: */
+	MyLog(LOGA_INFO, "TEST6: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int main(int argc, char** argv)
+{
+	int rc = 0;
+ 	int (*tests[])() = {NULL, test1, test2, test3, test4, test5, test6};
+
+	xml = fopen("TEST-test1.xml", "w");
+	fprintf(xml, "<testsuite name=\"test1\" tests=\"%d\">\n", (int)(ARRAY_SIZE(tests) - 1));
+
+	getopts(argc, argv);
+
+ 	if (options.test_no == 0)
+	{ /* run all the tests */
+ 	   	for (options.test_no = 1; options.test_no < ARRAY_SIZE(tests); ++options.test_no)
+			rc += tests[options.test_no](options); /* return number of failures.  0 = test succeeded */
+	}
+	else
+ 	   	rc = tests[options.test_no](options); /* run just the selected test */
+
+ 	if (rc == 0)
+		MyLog(LOGA_INFO, "verdict pass");
+	else
+		MyLog(LOGA_INFO, "verdict fail");
+
+	fprintf(xml, "</testsuite>\n");
+	fclose(xml);
+	return rc;
+}
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTSManager.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTSManager.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,133 @@
+#include "MQTTSManager.h"
+#include "XbeeMonitor.h"
+#include "Utils.h"
+#include "jsmn.h"
+#include <string>
+
+using namespace MQTT;
+
+#define MQTTS_PORT  8883
+
+static const char * topic_update = "garden_update";
+static const char * topic_listen = "garden_status";
+static const char * hostname = "mqtt.mbedhacks.com";
+static const char * clientID = "mbed-sample";
+static const char * username = "mbedhacks";
+static const char * password = "qwer123";
+
+static MQTTThreadedClient * pmqtt = NULL;
+Thread mqttThd(osPriorityNormal, DEFAULT_STACK_SIZE * 2);
+RadioControlData postdata;
+static char tempbuff[100];
+
+static int jsoneq(const char * json, jsmntok_t * tok, const char * s)
+{
+    if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
+        strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
+            return 0;
+    }
+    return -1;    
+}
+
+void messageArrived(MessageData& md)
+{
+    int i, r;
+    
+    jsmn_parser p;
+    jsmntok_t t[100];
+        
+    Message &message = md.message;
+    printf("Arrived Callback 1 : qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
+    printf("Payload [%.*s]\r\n", message.payloadlen, (char*)message.payload);
+    
+    // handle payload
+    const char * jsonstring = std::string((const char *) message.payload, message.payloadlen).c_str();
+    
+    jsmn_init(&p);
+    r = jsmn_parse(&p, jsonstring, strlen(jsonstring), t, sizeof(t)/sizeof(t[0]));
+    
+    uint64_t radio_id = 0;
+    int sprinkler_pin = 1; // 0 - turn on sprinkler, 1 - off
+    
+    /* Top level element is an object */
+    if ((r > 0) && (t[0].type == JSMN_OBJECT)) 
+    { 
+        /* Loop over all tokens */
+        for (i = 1; i < r; i++)
+        {
+            if (jsoneq(jsonstring, &t[i], "radioid") == 0)
+            {
+                memset(tempbuff, 0, sizeof(tempbuff));                
+                strncpy(tempbuff, jsonstring + t[i+1].start, t[i+1].end - t[i+1].start);
+                radio_id = strtoull(&tempbuff[0], NULL, 0);
+                i++;                
+            }
+            else if (jsoneq(jsonstring, &t[i], "sprinkler") == 0)
+            {
+                memset(tempbuff, 0, sizeof(tempbuff));
+                strncpy(tempbuff, jsonstring + t[i+1].start, t[i+1].end - t[i+1].start);
+                sprinkler_pin = strtoul(&tempbuff[0], NULL, 0);
+                i++;
+            }
+            else
+            {
+                
+            }
+        }    
+    }
+    
+    // TODO: Send the values to the XBeeMonitor thread
+    printf("Radio ID: %llu\r\n", radio_id);
+    printf("Sprinkler Pin : %d\r\n", sprinkler_pin);
+    postdata.radioID = radio_id;
+    postdata.sprinkler_pin = sprinkler_pin;
+    postRadioControl(postdata);
+}
+
+int mqttsInit(NetworkInterface * net, const char * pem)
+{
+    pmqtt = new MQTTThreadedClient(net, pem);
+    if (pmqtt == NULL) 
+        return -1;
+    
+    MQTTPacket_connectData logindata = MQTTPacket_connectData_initializer;
+    logindata.MQTTVersion = 3;
+    logindata.clientID.cstring = (char *) clientID;
+    logindata.username.cstring = (char *) username;
+    logindata.password.cstring = (char *) password;
+    
+    pmqtt->setConnectionParameters(hostname, MQTTS_PORT, logindata);
+    pmqtt->addTopicHandler(topic_listen, messageArrived);
+    
+    return 0;
+}
+
+void postMQTTUpdate(SensorData &msg)
+{
+    // Serialize data to json string ...
+    if (pmqtt)
+    {
+        PubMessage message;
+        message.qos = QOS0;
+        message.id = 123;
+        
+        strcpy(&message.topic[0], topic_update);
+        size_t numbytes = snprintf(&message.payload[0], MAX_MQTT_PAYLOAD_SIZE,
+                "{\"radio\":%llu,\"status\":{\"sprinkler\":%d,\"humidity\":%d,\"temperature\":%.2f,\"luminance\":%d}}", 
+                msg.deviceaddr,
+                msg.sprinkler,
+                msg.humidity,
+                msg.temperature,
+                msg.luminance);
+        printf("[%s]\r\n", &message.payload[0]);
+        message.payloadlen = numbytes;
+        pmqtt->publish(message);
+    }
+}
+
+int runMQTTS()
+{
+    if ( pmqtt && (mqttThd.start(mbed::callback(pmqtt, &MQTTThreadedClient::startListener)) != osOK ) )
+        return -1;
+    return 0;
+}
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTSManager.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTSManager.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,13 @@
+#ifndef _MQTTS_MANAGER_H_
+#define _MQTTS_MANAGER_H_
+
+
+#include "MQTTThreadedClient.h"
+#include "Sensor.h"
+
+
+int mqttsInit(NetworkInterface * net, const char * pem);
+void postMQTTUpdate(SensorData &msg);
+int runMQTTS();
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTThreadedClient.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTThreadedClient.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,941 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "MQTTThreadedClient.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/error.h"
+
+#ifdef DEBUG
+#define DBG(fmt, args...)    printf(fmt, ## args)
+#else
+#define DBG(fmt, args...)    /* Don't do anything in release builds */
+#endif
+
+static MemoryPool<MQTT::PubMessage, 4> mpool;
+static Queue<MQTT::PubMessage, 4> mqueue;
+
+// SSL/TLS variables
+mbedtls_entropy_context _entropy;
+mbedtls_ctr_drbg_context _ctr_drbg;
+mbedtls_x509_crt _cacert;
+mbedtls_ssl_context _ssl;
+mbedtls_ssl_config _ssl_conf;    
+mbedtls_ssl_session saved_session;
+
+namespace MQTT {
+    
+/**
+ * Receive callback for mbed TLS
+ */
+static int ssl_recv(void *ctx, unsigned char *buf, size_t len)
+{
+    int recv = -1;
+    TCPSocket *socket = static_cast<TCPSocket *>(ctx);
+    socket->set_timeout(DEFAULT_SOCKET_TIMEOUT);
+    recv = socket->recv(buf, len);
+
+    if (NSAPI_ERROR_WOULD_BLOCK == recv) {
+        return MBEDTLS_ERR_SSL_WANT_READ;
+    } else if (recv < 0) {
+        return -1;
+    } else {
+        return recv;
+    }
+}
+
+/**
+ * Send callback for mbed TLS
+ */
+static int ssl_send(void *ctx, const unsigned char *buf, size_t len)
+{
+    int sent = -1;
+    TCPSocket *socket = static_cast<TCPSocket *>(ctx);
+    socket->set_timeout(DEFAULT_SOCKET_TIMEOUT);    
+    sent = socket->send(buf, len);
+
+    if(NSAPI_ERROR_WOULD_BLOCK == sent) {
+        return MBEDTLS_ERR_SSL_WANT_WRITE;
+    } else if (sent < 0) {
+        return -1;
+    } else {
+        return sent;
+    }
+}
+
+#if DEBUG_LEVEL > 0
+/**
+ * Debug callback for mbed TLS
+ * Just prints on the USB serial port
+ */
+static void my_debug(void *ctx, int level, const char *file, int line,
+                     const char *str)
+{
+    const char *p, *basename;
+    (void) ctx;
+
+    /* Extract basename from file */
+    for(p = basename = file; *p != '\0'; p++) {
+        if(*p == '/' || *p == '\\') {
+            basename = p + 1;
+        }
+    }
+
+    if (_debug) {
+        mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str);
+    }
+}
+
+/**
+ * Certificate verification callback for mbed TLS
+ * Here we only use it to display information on each cert in the chain
+ */
+static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
+{
+    const uint32_t buf_size = 1024;
+    char *buf = new char[buf_size];
+    (void) data;
+
+    if (_debug) mbedtls_printf("\nVerifying certificate at depth %d:\r\n", depth);
+    mbedtls_x509_crt_info(buf, buf_size - 1, "  ", crt);
+    if (_debug) mbedtls_printf("%s", buf);
+
+    if (*flags == 0)
+        if (_debug) mbedtls_printf("No verification issue for this certificate\r\n");
+        else {
+            mbedtls_x509_crt_verify_info(buf, buf_size, "  ! ", *flags);
+            if (_debug) mbedtls_printf("%s\n", buf);
+        }
+
+    delete[] buf;
+    return 0;
+}
+#endif
+
+
+void MQTTThreadedClient::setupTLS()    
+{
+        if (useTLS)
+        {
+            mbedtls_entropy_init(&_entropy);
+            mbedtls_ctr_drbg_init(&_ctr_drbg);
+            mbedtls_x509_crt_init(&_cacert);
+            mbedtls_ssl_init(&_ssl);
+            mbedtls_ssl_config_init(&_ssl_conf);        
+            memset( &saved_session, 0, sizeof( mbedtls_ssl_session ) );            
+        }    
+}
+
+void MQTTThreadedClient::freeTLS()
+{
+        if (useTLS)
+        {
+            mbedtls_entropy_free(&_entropy);
+            mbedtls_ctr_drbg_free(&_ctr_drbg);
+            mbedtls_x509_crt_free(&_cacert);
+            mbedtls_ssl_free(&_ssl);
+            mbedtls_ssl_config_free(&_ssl_conf);               
+        }    
+}
+
+int MQTTThreadedClient::initTLS()
+{
+        int ret;
+        
+        DBG("Initializing TLS ...\r\n");
+        DBG("mbedtls_ctr_drdbg_seed ...\r\n");
+        if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy,
+                          (const unsigned char *) DRBG_PERS,
+                          sizeof (DRBG_PERS))) != 0) {
+            mbedtls_printf("mbedtls_crt_drbg_init returned [%x]\r\n", ret);
+            _error = ret;
+            return -1;
+        }
+        DBG("mbedtls_x509_crt_parse ...\r\n");
+        if ((ret = mbedtls_x509_crt_parse(&_cacert, (const unsigned char *) ssl_ca_pem,
+                           strlen(ssl_ca_pem) + 1)) != 0) {
+            mbedtls_printf("mbedtls_x509_crt_parse returned [%x]\r\n", ret);
+            _error = ret;
+            return -1;
+        }
+
+        DBG("mbedtls_ssl_config_defaults ...\r\n");
+        if ((ret = mbedtls_ssl_config_defaults(&_ssl_conf,
+                        MBEDTLS_SSL_IS_CLIENT,
+                        MBEDTLS_SSL_TRANSPORT_STREAM,
+                        MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
+            mbedtls_printf("mbedtls_ssl_config_defaults returned [%x]\r\n", ret);
+            _error = ret;
+            return -1;
+        }
+
+        DBG("mbedtls_ssl_config_ca_chain ...\r\n");
+        mbedtls_ssl_conf_ca_chain(&_ssl_conf, &_cacert, NULL);
+        DBG("mbedtls_ssl_conf_rng ...\r\n");
+        mbedtls_ssl_conf_rng(&_ssl_conf, mbedtls_ctr_drbg_random, &_ctr_drbg);
+
+        /* It is possible to disable authentication by passing
+         * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
+         */
+        DBG("mbedtls_ssl_conf_authmode ...\r\n");         
+        mbedtls_ssl_conf_authmode(&_ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+
+#if DEBUG_LEVEL > 0
+        mbedtls_ssl_conf_verify(&_ssl_conf, my_verify, NULL);
+        mbedtls_ssl_conf_dbg(&_ssl_conf, my_debug, NULL);
+        mbedtls_debug_set_threshold(DEBUG_LEVEL);
+#endif
+
+        DBG("mbedtls_ssl_setup ...\r\n");         
+        if ((ret = mbedtls_ssl_setup(&_ssl, &_ssl_conf)) != 0) {
+            mbedtls_printf("mbedtls_ssl_setup returned [%x]\r\n", ret);
+            _error = ret;
+            return -1;
+        }
+        
+        return 0;
+}
+
+int MQTTThreadedClient::doTLSHandshake()
+{
+        int ret;
+        
+        /* Start the handshake, the rest will be done in onReceive() */
+        DBG("Starting the TLS handshake...\r\n");
+        ret = mbedtls_ssl_handshake(&_ssl);
+        if (ret < 0) 
+        {
+            if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
+                ret != MBEDTLS_ERR_SSL_WANT_WRITE) 
+                    mbedtls_printf("mbedtls_ssl_handshake returned [%x]\r\n", ret);
+            else 
+            {
+                // do not close the socket if timed out
+                ret = TIMEOUT;
+            }
+            return ret;
+        }
+
+        /* Handshake done, time to print info */
+        DBG("TLS connection to %s:%d established\r\n", 
+            host.c_str(), port);
+
+        const uint32_t buf_size = 1024;
+        char *buf = new char[buf_size];
+        mbedtls_x509_crt_info(buf, buf_size, "\r    ",
+                        mbedtls_ssl_get_peer_cert(&_ssl));
+                        
+        DBG("Server certificate:\r\n%s\r", buf);
+        // Verify server cert ...
+        uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl);
+        if( flags != 0 )
+        {
+            mbedtls_x509_crt_verify_info(buf, buf_size, "\r  ! ", flags);
+            DBG("Certificate verification failed:\r\n%s\r\r\n", buf);
+            // free server cert ... before error return
+            delete [] buf;
+            return -1;
+        }
+        
+        DBG("Certificate verification passed\r\n\r\n");
+        // delete server cert after verification
+        delete [] buf;
+        
+#if defined(MBEDTLS_SSL_CLI_C)        
+        // TODO: Save the session here for reconnect.
+        if( ( ret = mbedtls_ssl_get_session( &_ssl, &saved_session ) ) != 0 )
+        {
+            mbedtls_printf( "mbedtls_ssl_get_session returned -0x%x\n\n", -ret );
+            hasSavedSession = false;
+            return -1;
+        }  
+#endif        
+        DBG("Session saved for reconnect ...\r\n");     
+        hasSavedSession = true;
+        
+        return 0;
+}
+
+int MQTTThreadedClient::readBytesToBuffer(char * buffer, size_t size, int timeout)
+{
+    int rc;
+
+    if (tcpSocket == NULL)
+        return -1;
+
+    if (useTLS) 
+    {
+        // Do SSL/TLS read
+        rc = mbedtls_ssl_read(&_ssl, (unsigned char *) buffer, size);
+        if (MBEDTLS_ERR_SSL_WANT_READ == rc)
+            return TIMEOUT;
+        else
+            return rc;
+    } else {
+        // non-blocking socket ...
+        tcpSocket->set_timeout(timeout);
+        rc = tcpSocket->recv( (void *) buffer, size);
+
+        // return 0 bytes if timeout ...
+        if (NSAPI_ERROR_WOULD_BLOCK == rc)
+            return TIMEOUT;
+        else
+            return rc; // return the number of bytes received or error
+    }
+}
+
+int MQTTThreadedClient::sendBytesFromBuffer(char * buffer, size_t size, int timeout)
+{
+    int rc;
+    
+    if (tcpSocket == NULL)
+        return -1;
+    
+    if (useTLS) {
+        // Do SSL/TLS write
+        rc =  mbedtls_ssl_write(&_ssl, (const unsigned char *) buffer, size);
+        if (MBEDTLS_ERR_SSL_WANT_WRITE == rc)
+            return TIMEOUT;
+        else
+            return rc;
+    } else {
+
+        // set the write timeout
+        tcpSocket->set_timeout(timeout);
+        rc = tcpSocket->send(buffer, size);
+
+        if ( NSAPI_ERROR_WOULD_BLOCK == rc)
+            return TIMEOUT;
+        else
+            return rc;
+    }
+}
+
+int MQTTThreadedClient::readPacketLength(int* value)
+{
+    int rc = MQTTPACKET_READ_ERROR;
+    unsigned char c;
+    int multiplier = 1;
+    int len = 0;
+    const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
+
+    *value = 0;
+    do
+    {
+        if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+        {
+            rc = MQTTPACKET_READ_ERROR; /* bad data */
+            goto exit;
+        }
+        
+        rc = readBytesToBuffer((char *) &c, 1, DEFAULT_SOCKET_TIMEOUT);
+        if (rc != 1)
+        {
+            rc = MQTTPACKET_READ_ERROR;
+            goto exit;
+        }
+            
+        *value += (c & 127) * multiplier;
+        multiplier *= 128;
+    } while ((c & 128) != 0);
+    
+    rc = MQTTPACKET_READ_COMPLETE;
+        
+exit:
+    if (rc == MQTTPACKET_READ_ERROR )
+        len = -1;
+    
+    return len;
+}
+
+int MQTTThreadedClient::sendPacket(size_t length)
+{
+    int rc = FAILURE;
+    int sent = 0;
+
+    while (sent < length)
+    {
+        rc = sendBytesFromBuffer((char *) &sendbuf[sent], length - sent, DEFAULT_SOCKET_TIMEOUT);
+        if (rc < 0)  // there was an error writing the data
+            break;
+        sent += rc;
+    }
+    
+    if (sent == length)
+        rc = SUCCESS;
+    else
+        rc = FAILURE;
+        
+    return rc;
+}
+/**
+ * Reads the entire packet to readbuf and returns
+ * the type of packet when successful, otherwise
+ * a negative error code is returned.
+ **/
+int MQTTThreadedClient::readPacket()
+{
+    int rc = FAILURE;
+    MQTTHeader header = {0};
+    int len = 0;
+    int rem_len = 0;
+
+    /* 1. read the header byte.  This has the packet type in it */
+    if ( (rc = readBytesToBuffer((char *) &readbuf[0], 1, DEFAULT_SOCKET_TIMEOUT)) != 1)
+        goto exit;
+
+    len = 1;
+    /* 2. read the remaining length.  This is variable in itself */
+    if ( readPacketLength(&rem_len) < 0 )
+        goto exit;
+        
+    len += MQTTPacket_encode(readbuf + 1, rem_len); /* put the original remaining length into the buffer */
+
+    if (rem_len > (MAX_MQTT_PACKET_SIZE - len))
+    {
+        rc = BUFFER_OVERFLOW;
+        goto exit;
+    }
+
+    /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+    if (rem_len > 0 && (readBytesToBuffer((char *) (readbuf + len), rem_len, DEFAULT_SOCKET_TIMEOUT) != rem_len))
+        goto exit;
+
+    // Convert the header to type
+    // and update rc
+    header.byte = readbuf[0];
+    rc = header.bits.type;
+    
+exit:
+
+    return rc;    
+}
+
+/**
+ * Read until a specified packet type is received, or untill the specified
+ * timeout dropping packets along the way.
+ **/
+int MQTTThreadedClient::readUntil(int packetType, int timeout)
+{
+    int pType = FAILURE;
+    Timer timer;
+    
+    timer.start();
+    do {
+        pType = readPacket();
+        if (pType < 0)
+            break;
+            
+        if (timer.read_ms() > timeout)
+        {
+            pType = FAILURE;
+            break;
+        }
+    }while(pType != packetType);
+    
+    return pType;    
+}
+
+
+int MQTTThreadedClient::login()
+{
+    int rc = FAILURE;
+    int len = 0;
+
+    if (!isConnected)
+    {
+        DBG("Session not connected! \r\n");
+        return rc;
+    }
+        
+    // Copy the keepAliveInterval value to local
+    // MQTT specifies in seconds, we have to multiply that
+    // amount for our 32 bit timers which accepts ms.
+    keepAliveInterval = (connect_options.keepAliveInterval * 1000);
+    
+    DBG("Login with: \r\n");
+    DBG("\tUsername: [%s]\r\n", connect_options.username.cstring);
+    DBG("\tPassword: [%s]\r\n", connect_options.password.cstring);
+    
+    if ((len = MQTTSerialize_connect(sendbuf, MAX_MQTT_PACKET_SIZE, &connect_options)) <= 0)
+    {
+        DBG("Error serializing connect packet ...\r\n");
+        return rc;
+    }
+    if ((rc = sendPacket((size_t) len)) != SUCCESS)  // send the connect packet
+    {
+        DBG("Error sending the connect request packet ...\r\n");
+        return rc; 
+    }
+    
+    // Wait for the CONNACK 
+    if (readUntil(CONNACK, COMMAND_TIMEOUT) == CONNACK)
+    {
+        unsigned char connack_rc = 255;
+        bool sessionPresent = false;
+        DBG("Connection acknowledgement received ... deserializing respones ...\r\n");
+        if (MQTTDeserialize_connack((unsigned char*)&sessionPresent, &connack_rc, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+            rc = connack_rc;
+        else
+            rc = FAILURE;
+    }
+    else
+        rc = FAILURE;
+
+    if (rc == SUCCESS)
+    {
+        DBG("Connected!!! ... starting connection timers ...\r\n");
+        resetConnectionTimer();
+    }
+    
+    DBG("Returning with rc = %d\r\n", rc);
+    
+    return rc;    
+}
+
+
+void MQTTThreadedClient::disconnect()
+{
+    if (isConnected)
+    {
+        if( useTLS 
+            && ( mbedtls_ssl_session_reset( &_ssl ) != 0 )
+           )
+        {
+            DBG( "Session reset returned an error \r\n");
+        }        
+        
+        isConnected = false;
+        tcpSocket->close();      
+    }
+}
+
+int MQTTThreadedClient::connect()
+{
+    int ret = FAILURE;
+
+    if ((network == NULL) || (tcpSocket == NULL)
+        || host.empty())
+    {
+        DBG("Network settings not set! \r\n");
+        return ret;
+    }
+    
+    if (useTLS) 
+    {
+        if( ( ret = mbedtls_ssl_session_reset( &_ssl ) ) != 0 ) {
+            mbedtls_printf( " failed\n  ! mbedtls_ssl_session_reset returned -0x%x\n\n", -ret );
+            return ret;
+        }
+#if defined(MBEDTLS_SSL_CLI_C)
+        if ( hasSavedSession && (( ret = mbedtls_ssl_set_session( &_ssl, &saved_session ) ) != 0 )) {
+            mbedtls_printf( " failed\n  ! mbedtls_ssl_conf_session returned %d\n\n", ret );
+            return ret;
+        }
+#endif        
+    }
+        
+    tcpSocket->open(network);
+    if (useTLS)
+    {
+        DBG("mbedtls_ssl_set_hostname ...\r\n");         
+        mbedtls_ssl_set_hostname(&_ssl, host.c_str());
+        DBG("mbedtls_ssl_set_bio ...\r\n");         
+        mbedtls_ssl_set_bio(&_ssl, static_cast<void *>(tcpSocket),
+                                   ssl_send, ssl_recv, NULL );
+    }
+    
+    if (( ret = tcpSocket->connect(host.c_str(), port)) < 0 )
+    {
+         DBG("Error connecting to %s:%d with %d\r\n", host.c_str(), port, ret);
+         return ret;
+    }else
+         isConnected = true;
+    
+    if (useTLS) 
+    {
+        
+        if (doTLSHandshake() < 0)
+        {
+            DBG("TLS Handshake failed! \r\n");
+            return FAILURE;
+        }else
+            DBG("TLS Handshake complete!! \r\n");
+    }
+    
+    return login();
+}
+
+void MQTTThreadedClient::setConnectionParameters(const char * chost, uint16_t cport, MQTTPacket_connectData & options)
+{
+    // Copy the settings for reconnection
+    host = chost;
+    port = cport;
+    connect_options = options;    
+}
+
+int MQTTThreadedClient::publish(PubMessage& msg)
+{
+#if 0
+    int id = queue.call(mbed::callback(this, &MQTTThreadedClient::sendPublish), topic, message);
+    // TODO: handle id values when the function is called later
+    if (id == 0)
+        return FAILURE;
+    else
+        return SUCCESS;
+#endif
+    PubMessage *message = mpool.alloc();
+    // Simple copy
+    *message = msg;
+    
+    // Push the data to the thread
+    DBG("[Thread:%d] Pushing data to consumer thread ...\r\n", Thread::gettid());
+    mqueue.put(message);
+    
+    return SUCCESS;
+}
+
+int MQTTThreadedClient::sendPublish(PubMessage& message)
+{
+     MQTTString topicString = MQTTString_initializer;
+     
+     if (!isConnected) 
+     {
+        DBG("[Thread:%d] Not connected!!! ...\r\n", Thread::gettid());
+        return FAILURE;
+     }
+        
+     topicString.cstring = (char*) &message.topic[0];
+     int len = MQTTSerialize_publish(sendbuf, MAX_MQTT_PACKET_SIZE, 0, message.qos, false, message.id,
+              topicString, (unsigned char*) &message.payload[0], (int) message.payloadlen);
+     if (len <= 0)
+     {
+         DBG("[Thread:%d]Failed serializing message ...\r\n", Thread::gettid());
+         return FAILURE;
+     }
+     
+     if (sendPacket(len) == SUCCESS)
+     {
+         DBG("[Thread:%d]Successfully sent publish packet to server ...\r\n", Thread::gettid());
+         return SUCCESS;
+     }
+    
+    DBG("[Thread:%d]Failed to send publish packet to server ...\r\n", Thread::gettid());
+    return FAILURE;
+}
+
+void MQTTThreadedClient::addTopicHandler(const char * topicstr, void (*function)(MessageData &))
+{
+    // Push the subscription into the map ...
+    FP<void,MessageData &> fp;
+    fp.attach(function);
+    
+    topicCBMap.insert(std::pair<std::string, FP<void,MessageData &> >(std::string(topicstr),fp));    
+} 
+
+int MQTTThreadedClient::processSubscriptions()
+{
+    int numsubscribed = 0;
+    
+    if (!isConnected) 
+    {
+            DBG("Session not connected!!\r\n");
+            return 0;
+    }
+    
+    DBG("Processing subscribed topics ....\r\n");
+    
+    std::map<std::string, FP<void, MessageData &> >::iterator it;
+    for(it = topicCBMap.begin(); it != topicCBMap.end(); it++) 
+    {
+        int rc = FAILURE;
+        int len = 0;
+        //TODO: We only subscribe to QoS = 0 for now
+        QoS qos = QOS0;
+
+        MQTTString topic = {(char*)it->first.c_str(), {0, 0}};
+        DBG("Subscribing to topic [%s]\r\n", topic.cstring);
+
+
+        len = MQTTSerialize_subscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic, (int*)&qos);
+        if (len <= 0) {
+            DBG("Error serializing subscribe packet ...\r\n");
+            continue;
+        }
+
+        if ((rc = sendPacket(len)) != SUCCESS) {
+            DBG("Error sending subscribe packet [%d]\r\n", rc);
+            continue;
+        }
+
+        DBG("Waiting for subscription ack ...\r\n");
+        // Wait for SUBACK, dropping packets read along the way ...
+        if (readUntil(SUBACK, COMMAND_TIMEOUT) == SUBACK) { // wait for suback
+            int count = 0, grantedQoS = -1;
+            unsigned short mypacketid;
+            if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+                rc = grantedQoS; // 0, 1, 2 or 0x80
+            // For as long as we do not get 0x80 ..
+            if (rc != 0x80) 
+            {
+                // Reset connection timers here ...
+                resetConnectionTimer();
+                DBG("Successfully subscribed to %s ...\r\n", it->first.c_str());
+                numsubscribed++;
+            } else {
+                DBG("Failed to subscribe to topic %s ... (not authorized?)\r\n", it->first.c_str());
+            }
+        } else 
+            DBG("Failed to subscribe to topic %s (ack not received) ...\r\n", it->first.c_str());
+    } // end for loop
+    
+    return numsubscribed;    
+}
+
+bool MQTTThreadedClient::isTopicMatched(char* topicFilter, MQTTString& topicName)
+{
+    char* curf = topicFilter;
+    char* curn = topicName.lenstring.data;
+    char* curn_end = curn + topicName.lenstring.len;
+
+    while (*curf && curn < curn_end)
+    {
+        if (*curn == '/' && *curf != '/')
+            break;
+        if (*curf != '+' && *curf != '#' && *curf != *curn)
+            break;
+        if (*curf == '+')
+        {   // skip until we meet the next separator, or end of string
+            char* nextpos = curn + 1;
+            while (nextpos < curn_end && *nextpos != '/')
+                nextpos = ++curn + 1;
+        }
+        else if (*curf == '#')
+            curn = curn_end - 1;    // skip until end of string
+        curf++;
+        curn++;
+    };
+
+    return (curn == curn_end) && (*curf == '\0');
+}
+
+int MQTTThreadedClient::handlePublishMsg()
+{
+    MQTTString topicName = MQTTString_initializer;
+    Message msg;
+    int intQoS;
+    DBG("[Thread:%d]Deserializing publish message ...\r\n", Thread::gettid());
+    if (MQTTDeserialize_publish((unsigned char*)&msg.dup, 
+            &intQoS, 
+            (unsigned char*)&msg.retained, 
+            (unsigned short*)&msg.id, 
+            &topicName,
+            (unsigned char**)&msg.payload, 
+            (int*)&msg.payloadlen, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+    {
+        DBG("[Thread:%d]Error deserializing published message ...\r\n", Thread::gettid());
+        return -1;
+    }
+
+    std::string topic;
+    if (topicName.lenstring.len > 0)
+    {
+        topic = std::string((const char *) topicName.lenstring.data, (size_t) topicName.lenstring.len);
+    }else
+        topic = (const char *) topicName.cstring;
+    
+    DBG("[Thread:%d]Got message for topic [%s], QoS [%d] ...\r\n", Thread::gettid(), topic.c_str(), intQoS);
+    
+    msg.qos = (QoS) intQoS;
+
+    
+    // Call the handlers for each topic 
+    if (topicCBMap.find(topic) != topicCBMap.end())
+    {
+        // Call the callback function 
+        if (topicCBMap[topic].attached())
+        {
+            DBG("[Thread:%d]Invoking function handler for topic ...\r\n", Thread::gettid());
+            MessageData md(topicName, msg);            
+            topicCBMap[topic](md);
+            
+            return 1;
+        }
+    }
+    
+    // TODO: depending on the QoS
+    // we send data to the server = PUBACK or PUBREC
+    switch(intQoS)
+    {
+        case QOS0:
+            // We send back nothing ...
+            break;
+        case QOS1:
+            // TODO: implement
+            break;
+        case QOS2:
+            // TODO: implement
+            break;
+        default:
+            break;
+    }
+    
+    return 0;
+}
+
+void MQTTThreadedClient::resetConnectionTimer()
+{
+    if (keepAliveInterval > 0)
+    {
+        comTimer.reset();
+        comTimer.start();
+    }
+}
+
+bool MQTTThreadedClient::hasConnectionTimedOut()
+{
+    if (keepAliveInterval > 0 ) {
+        // Check connection timer
+        if (comTimer.read_ms() > keepAliveInterval)
+            return true;
+        else
+            return false;
+    }
+
+    return false;
+}
+        
+void MQTTThreadedClient::sendPingRequest()
+{
+    int len = MQTTSerialize_pingreq(sendbuf, MAX_MQTT_PACKET_SIZE);
+    if (len > 0 && (sendPacket(len) == SUCCESS)) // send the ping packet
+    {
+        printf("MQTT Ping request sent successfully ...\r\n");
+    }
+}
+
+void MQTTThreadedClient::startListener()
+{
+    int pType;
+    int numsubs;
+    // Continuesly listens for packets and dispatch
+    // message handlers ...
+    if (useTLS)
+    {
+        initTLS();
+    }
+            
+    while(true)
+    {
+
+        // Attempt to reconnect and login
+        if ( connect() < 0 )
+        {
+            disconnect();
+            // Wait for a few secs and reconnect ...
+            Thread::wait(6000);
+            continue;
+        }
+        
+        numsubs = processSubscriptions();
+        DBG("Subscribed %d topics ...\r\n", numsubs);
+         
+        // loop read    
+        while(true) 
+        {
+            pType = readPacket();
+            switch(pType) 
+            {
+                case TIMEOUT:
+                    // No data available from the network ...
+                    break;
+                case FAILURE:
+                    {
+                        DBG("readPacket returned failure \r\n");
+                        goto reconnect;
+                    }
+                case BUFFER_OVERFLOW: 
+                    {
+                        // TODO: Network error, do we disconnect and reconnect?
+                        DBG("[Thread:%d]Failure or buffer overflow problem ... \r\n", Thread::gettid());
+                        MBED_ASSERT(false);
+                    }
+                    break;
+                /**
+                *  The rest of the return codes below (all positive) is about MQTT
+                 * response codes
+                 **/
+                case CONNACK:
+                case PUBACK:
+                case SUBACK:
+                    break;
+                case PUBLISH: 
+                    {
+                        DBG("[Thread:%d]Publish received!....\r\n", Thread::gettid());
+                        // We receive data from the MQTT server ..
+                        if (handlePublishMsg() < 0) {
+                            DBG("[Thread:%d]Error handling PUBLISH message ... \r\n", Thread::gettid());
+                            break;
+                        }
+                    }
+                    break;
+                case PINGRESP: 
+                    {
+                        printf("MQTT Got ping response ...\r\n");
+                        resetConnectionTimer();
+                    }
+                    break;
+                default:
+                    DBG("[Thread:%d]Unknown/Not handled message from server pType[%d]\r\n", Thread::gettid(), pType);
+            }
+
+            // Check if its time to send a keepAlive packet
+            if (hasConnectionTimedOut()) {
+                // Queue the ping request so that other
+                // pending operations queued above will go first
+                queue.call(this, &MQTTThreadedClient::sendPingRequest);
+            }
+
+            // Check if we have messages on the message queue
+            osEvent evt = mqueue.get(10);
+            if (evt.status == osEventMessage) {
+
+                DBG("[Thread:%d]Got message to publish! ... \r\n", Thread::gettid());
+
+                // Unpack the message
+                PubMessage * message = (PubMessage *)evt.value.p;
+
+                // Send the packet, do not queue the call
+                // like the ping above ..
+                if ( sendPublish(*message) == SUCCESS) {
+                    // Reset timers if we have been able to send successfully
+                    resetConnectionTimer();
+                } else {
+                    // Disconnected?
+                    goto reconnect;
+                }
+
+                // Free the message from mempool  after using
+                mpool.free(message);
+            }
+
+            // Dispatch any queued events ...
+            queue.dispatch(100);
+        } // end while loop
+
+reconnect:
+        // reconnect?
+        DBG("Client disconnected!! ... retrying ...\r\n");
+        disconnect();
+        
+    };
+}
+
+void MQTTThreadedClient::stopListener()
+{
+    // TODO: Set a signal/flag that the running thread 
+    // will check if its ok to stop ...
+}
+
+}
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTThreadedClient.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTThreadedClient.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,197 @@
+#ifndef _MQTT_THREADED_CLIENT_H_
+#define _MQTT_THREADED_CLIENT_H_
+
+#include "mbed.h"
+#include "rtos.h"
+#include "MQTTPacket.h"
+#include "NetworkInterface.h"
+#include "FP.h"
+#include "config.h"
+
+#include <cstdio>
+#include <string>
+#include <map>
+
+//#define MQTT_DEBUG 1
+
+
+#define COMMAND_TIMEOUT 5000
+#define DEFAULT_SOCKET_TIMEOUT 1000
+#define MAX_MQTT_PACKET_SIZE 500
+#define MAX_MQTT_PAYLOAD_SIZE 300
+
+namespace MQTT
+{
+    
+typedef enum { QOS0, QOS1, QOS2 } QoS;
+
+// all failure return codes must be negative
+typedef enum { BUFFER_OVERFLOW = -3, TIMEOUT = -2, FAILURE = -1, SUCCESS = 0 } returnCode;
+
+
+typedef struct
+{
+    QoS qos;
+    bool retained;
+    bool dup;
+    unsigned short id;
+    void *payload;
+    size_t payloadlen;
+}Message, *pMessage;
+
+// TODO:
+// Merge this struct with the one above, in order to use the same
+// data structure for sending and receiving. I need to simplify
+// the PubMessage to not contain pointers like the one above.
+typedef struct
+{
+    char topic[100];
+    QoS qos;
+    unsigned short id;
+    size_t payloadlen;
+    char payload[MAX_MQTT_PAYLOAD_SIZE];
+}PubMessage, *pPubMessage;
+
+struct MessageData
+{
+    MessageData(MQTTString &aTopicName, Message &aMessage)  : message(aMessage), topicName(aTopicName)
+    { }
+    Message &message;
+    MQTTString &topicName;
+};
+
+class PacketId
+{
+public:
+    PacketId()
+    {
+        next = 0;
+    }
+
+    int getNext()
+    {
+        return next = (next == MAX_PACKET_ID) ? 1 : ++next;
+    }
+
+private:
+    static const int MAX_PACKET_ID = 65535;
+    int next;
+};
+
+
+
+class MQTTThreadedClient
+{
+public:
+    MQTTThreadedClient(NetworkInterface * aNetwork, const char * pem = NULL)
+        : network(aNetwork),
+          ssl_ca_pem(pem),
+          port((pem != NULL) ? 8883 : 1883),
+          queue(32 * EVENTS_EVENT_SIZE),
+          isConnected(false),          
+          hasSavedSession(false),
+          useTLS(pem != NULL)
+    {
+        DRBG_PERS = "mbed TLS MQTT client";
+        tcpSocket = new TCPSocket();
+        setupTLS();
+    }
+    
+    ~MQTTThreadedClient()
+    {
+        // TODO: signal the thread to shutdown
+        freeTLS();
+           
+        if (isConnected)
+            disconnect();
+                
+    }
+    /** 
+     *  Sets the connection parameters. Must be called before running the startListener as a thread.
+     *
+     *  @param host - pointer to the host where the MQTT server is running
+     *  @param port - the port number to connect, 1883 for non secure connections, 8883 for 
+     *                secure connections
+     *  @param options - the connect data used for logging into the MQTT server.
+     */
+    void setConnectionParameters(const char * host, uint16_t port, MQTTPacket_connectData & options);
+    int publish(PubMessage& message);
+    
+    void addTopicHandler(const char * topic, void (*function)(MessageData &));
+    template<typename T>
+    void addTopicHandler(const char * topic, T *object, void (T::*member)(MessageData &))
+    {
+        FP<void,MessageData &> fp;
+        fp.attach(object, member);
+
+        topicCBMap.insert(std::pair<std::string, FP<void,MessageData &> >(std::string(topic),fp));  
+    }
+    
+    // TODO: Add unsubscribe functionality.
+    
+    // Start the listener thread and start polling 
+    // MQTT server.
+    void startListener();
+    // Stop the listerner thread and closes connection
+    void stopListener();
+
+protected:
+
+    int handlePublishMsg();
+    void disconnect();  
+    int connect();      
+
+
+private:
+    NetworkInterface * network;
+    const char * ssl_ca_pem;
+    TCPSocket * tcpSocket;
+    PacketId packetid;
+    const char *DRBG_PERS;
+    nsapi_error_t _error;    
+    // Connection options
+    std::string host;
+    uint16_t port;
+    MQTTPacket_connectData connect_options;
+    // Event queue
+    EventQueue queue;
+    bool isConnected;
+    bool hasSavedSession;    
+
+    // TODO: Because I'm using a map, I can only have one handler
+    // for each topic (one that's mapped to the topic string).
+    // Attaching another handler on the same topic is not possible.
+    // In the future, use a vector instead of maps to allow multiple
+    // handlers for the same topic.
+    std::map<std::string, FP<void, MessageData &> > topicCBMap;
+    
+    unsigned char sendbuf[MAX_MQTT_PACKET_SIZE];
+    unsigned char readbuf[MAX_MQTT_PACKET_SIZE];
+
+    unsigned int keepAliveInterval;
+    Timer comTimer;
+
+    // SSL/TLS functions
+    bool useTLS;
+    void setupTLS();
+    int initTLS();    
+    void freeTLS();
+    int doTLSHandshake();
+    
+    int processSubscriptions();
+    int readPacket();
+    int sendPacket(size_t length);
+    int readPacketLength(int* value);
+    int readUntil(int packetType, int timeout);
+    int readBytesToBuffer(char * buffer, size_t size, int timeout);
+    int sendBytesFromBuffer(char * buffer, size_t size, int timeout);
+    bool isTopicMatched(char* topic, MQTTString& topicName);
+    int  sendPublish(PubMessage& message);
+    void resetConnectionTimer();
+    void sendPingRequest();
+    bool hasConnectionTimedOut();
+    int login();
+};
+
+}
+#endif
diff -r 000000000000 -r a1734fe1ec4b NTPClient/NTPClient.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NTPClient/NTPClient.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,185 @@
+/* NTPClient.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//Debug is disabled by default
+#if 0
+//Enable debug
+#define __DEBUG__
+#include <cstdio>
+#define DBG(x, ...) std::printf("[NTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 
+#define WARN(x, ...) std::printf("[NTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 
+#define ERR(x, ...) std::printf("[NTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 
+
+#else
+//Disable debug
+#define DBG(x, ...) 
+#define WARN(x, ...)
+#define ERR(x, ...) 
+
+#endif
+#include "NetworkInterface.h"
+#include "NTPClient.h"
+
+#include "UDPSocket.h"
+
+#include "mbed.h" //time() and set_time()
+
+#define NTP_PORT 123
+#define NTP_CLIENT_PORT 0 //Random port
+#define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900)
+
+/*NTPClient::NTPClient() : m_sock()
+{
+
+}*/
+
+NTPClient::NTPClient(NetworkInterface * _m_intf, int utcOffset) 
+    : m_intf(_m_intf),
+    utc_offset(utcOffset)
+{
+}
+
+#ifdef htons
+#undef htons
+#endif /* htons */
+#ifdef htonl
+#undef htonl
+#endif /* htonl */
+#ifdef ntohs
+#undef ntohs
+#endif /* ntohs */
+#ifdef ntohl
+#undef ntohl
+#endif /* ntohl */
+
+
+#if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__))
+
+#define htons(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+#define ntohs(x) htons(x)
+#define htonl(x) ((((x) & 0xff) << 24) | \
+                     (((x) & 0xff00) << 8) | \
+                     (((x) & 0xff0000UL) >> 8) | \
+                     (((x) & 0xff000000UL) >> 24))
+#define ntohl(x) htonl(x)
+
+#else
+
+#define htons(x)  (x)
+#define htonl(x)  (x)
+#define ntohl(x)  (x)
+#define ntohs(x)  (x)
+
+#endif 
+
+
+NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout)
+{
+#ifdef __DEBUG__
+  time_t ctTime;
+  ctTime = time(NULL);
+  set_time(ctTime);
+  DBG("Time is set to (UTC): %s", ctime(&ctTime));
+#endif
+
+    
+  SocketAddress address(0, port);
+  int r = m_intf->gethostbyname(host, &address);  
+  if (r) {
+        printf("error: 'gethostbyname(\"%s\")' failed with code %d\r\n", host, r);
+  } else if (!address) {
+        printf("error: 'gethostbyname(\"%s\")' returned null IP address\r\n", host);
+  }  
+  //printf ("address: %s\n\r",address.get_ip_address());
+   
+  //Create & bind socket
+  if (m_sock.open(m_intf) < 0) printf ("ERROR sock open \n\r");  
+  m_sock.set_timeout(timeout);  
+
+  struct NTPPacket pkt;  
+  memset (&pkt, 0, sizeof(NTPPacket));   
+
+  //Now ping the server and wait for response
+  DBG("Ping");
+  //Prepare NTP Packet:
+  pkt.li = 0; //Leap Indicator : No warning
+  pkt.vn = 4; //Version Number : 4
+  pkt.mode = 3; //Client mode
+  pkt.stratum = 0; //Not relevant here
+  pkt.poll = 0; //Not significant as well
+  pkt.precision = 0; //Neither this one is
+
+  int ret = m_sock.sendto(address, (char*)&pkt, sizeof(NTPPacket) ); 
+  if (ret < 0 )
+  {
+    ERR("Could not send packet %d", ret);
+    m_sock.close();
+    return NTP_CONN;
+  }
+
+  //Read response
+  DBG("Pong");
+
+  ret = m_sock.recvfrom(&address, (char*)&pkt, sizeof(NTPPacket) );  // LICIO
+  if(ret < 0)
+  {
+    ERR("Could not receive packet %d", ret);
+    m_sock.close();
+    return NTP_CONN;
+  }
+
+  if(ret < sizeof(NTPPacket)) //TODO: Accept chunks
+  {
+    ERR("Receive packet size does not match");
+    m_sock.close();
+    return NTP_PRTCL;
+  }
+
+  if( pkt.stratum == 0)  //Kiss of death message : Not good !
+  {
+    ERR("Kissed to death!");
+    m_sock.close();
+    return NTP_PRTCL;
+  }
+
+  //Correct Endianness
+  pkt.refTm_s = ntohl( pkt.refTm_s ); 
+  pkt.refTm_f = ntohl( pkt.refTm_f );
+  pkt.origTm_s = ntohl( pkt.origTm_s );
+  pkt.origTm_f = ntohl( pkt.origTm_f );
+  pkt.rxTm_s = ntohl( pkt.rxTm_s );
+  pkt.rxTm_f = ntohl( pkt.rxTm_f );
+  pkt.txTm_s = ntohl( pkt.txTm_s );
+  pkt.txTm_f = ntohl( pkt.txTm_f );
+
+  // see RFC 4330 p.13
+  int timeoffset = utc_offset * 60 * 60;  
+  time_t txTm = (time_t)((pkt.txTm_s - NTP_TIMESTAMP_DELTA) + timeoffset);  
+
+  set_time(txTm); 
+
+#ifdef __DEBUG__
+  ctTime = time(NULL);
+  DBG("Time is now (UTC): %s", ctime(&ctTime));
+#endif
+  m_sock.close();
+
+  return NTP_OK;
+}
+
diff -r 000000000000 -r a1734fe1ec4b NTPClient/NTPClient.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NTPClient/NTPClient.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,98 @@
+/* NTPClient.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** \file
+NTP Client header file
+*/
+
+#ifndef NTPCLIENT_H_
+#define NTPCLIENT_H_
+
+#include <stdint.h>
+#include "UDPSocket.h"
+
+#define NTP_DEFAULT_PORT 123
+#define NTP_DEFAULT_TIMEOUT 4000
+
+///NTP client results
+enum NTPResult
+{
+  NTP_DNS, ///<Could not resolve name
+  NTP_PRTCL, ///<Protocol error
+  NTP_TIMEOUT, ///<Connection timeout
+  NTP_CONN, ///<Connection error
+  NTP_OK = 0, ///<Success
+};
+
+/** NTP Client to update the mbed's RTC using a remote time server
+*
+*/
+class NTPClient
+{
+public:
+  /**
+  Instantiate the NTP client
+  */
+ // NTPClient();
+  NTPClient(NetworkInterface * _m_intf, int utcOffset = 0);
+  /**Get current time (blocking)
+  Update the time using the server host
+  Blocks until completion
+  @param host NTP server IPv4 address or hostname (will be resolved via DNS)
+  @param port port to use; defaults to 123
+  @param timeout waiting timeout in ms (osWaitForever for blocking function, not recommended)
+  @return 0 on success, NTP error code (<0) on failure
+  */
+  NTPResult setTime(const char* host, uint16_t port = NTP_DEFAULT_PORT, uint32_t timeout = NTP_DEFAULT_TIMEOUT); 
+
+private:
+  struct NTPPacket //See RFC 4330 for Simple NTP
+  {
+    //WARN: We are in LE! Network is BE!
+    //LSb first
+    unsigned mode : 3;
+    unsigned vn : 3;
+    unsigned li : 2;
+
+    uint8_t stratum;
+    uint8_t poll;
+    uint8_t precision;
+    //32 bits header
+
+    uint32_t rootDelay;
+    uint32_t rootDispersion;
+    uint32_t refId;
+
+    uint32_t refTm_s;
+    uint32_t refTm_f;
+    uint32_t origTm_s;
+    uint32_t origTm_f;
+    uint32_t rxTm_s;
+    uint32_t rxTm_f;
+    uint32_t txTm_s;
+    uint32_t txTm_f;
+  } __attribute__ ((packed));
+  
+  NetworkInterface * m_intf;  // WiFi interface 
+  int utc_offset; 
+  UDPSocket m_sock;
+};
+
+
+#endif /* NTPCLIENT_H_ */
diff -r 000000000000 -r a1734fe1ec4b README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+# MQTTGateway
diff -r 000000000000 -r a1734fe1ec4b Sensor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sensor.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,41 @@
+#ifndef _SENSOR_H_
+#define _SENSOR_H_
+
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string>
+#include "Utils.h"
+
+// Keep SensorData a POD type
+typedef struct _SensorData
+{
+    uint64_t deviceaddr;
+       
+    uint16_t humidity;
+    float temperature;
+    uint16_t luminance;
+    // Relay value (negative logic)
+    // true = off
+    // false = on
+    bool  sprinkler;
+
+    
+    void debug()
+    {
+        printf("Channel id (lo): [%lX]\r\n", UINT64_HI32(deviceaddr));
+        printf("Channel id (hi): [%lX]\r\n", UINT64_LO32(deviceaddr));
+        printf("Humidity : [%d]\r\n", humidity);
+        printf("Temperature : [%.2f]\r\n", temperature);
+        printf("Luminance : [%d]\r\n", luminance);
+    }    
+} SensorData;
+
+typedef struct _SensorInfo
+{
+    int id;
+    std::string name;
+} SensorInfo;
+
+   
+#endif
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "DigiLogger.h"
+
+#include <stdarg.h>
+
+using namespace DigiLog;
+
+LogLevel DigiLogger::_log_level;
+
+DigiLogger* DigiLogger::current_logger;
+
+/* Base Class constructor */
+DigiLogger::DigiLogger()
+{
+    _log_level = LogLevelNone;
+
+    current_logger = NULL;
+}
+
+/* Class destructor */
+DigiLogger::~DigiLogger()
+{
+    current_logger = NULL;
+}
+
+void DigiLogger::set_level(LogLevel log_level)
+{
+    _log_level = log_level;
+}
+
+LogLevel DigiLogger::get_level()
+{
+    return _log_level;
+}
+
+void DigiLogger::log_format(LogLevel log_level, const char *format, ...)
+{
+    static char buffer[DEBUG_BUFFER_LEN];
+    va_list argp;
+
+    if (current_logger == NULL) {
+        return;
+    }
+
+    if (_log_level < log_level) {
+        return;
+    }
+
+    va_start(argp, format);
+    vsnprintf(buffer, DEBUG_BUFFER_LEN, format, argp);
+    va_end(argp);
+
+    current_logger->log_buffer(buffer);
+}
+
+void DigiLogger::log_buffer(char const * const buffer)
+{
+    (void)(buffer);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DIGI_LOGGER_H_)
+#define __DIGI_LOGGER_H_
+
+#include <cstdlib>
+#include <stdio.h>
+
+/**
+ * @defgroup LogLevel
+ * @{
+ */
+/**
+ * Library Logging level.
+ */
+enum LogLevel {
+    LogLevelNone,      /** Level None */
+    LogLevelError,     /** Level Error */
+    LogLevelWarning,   /** Level Warning */
+    LogLevelInfo,      /** Level Info */
+    LogLevelDebug,     /** Level Debug */
+    LogLevelFrameData, /** Level Frame Data */
+    LogLevelAll        /** Level All */
+};
+/**
+ * @}
+ */
+
+#define DEBUG_BUFFER_LEN    200
+
+namespace DigiLog {
+
+class DigiLogger
+{
+    protected:
+
+        /** module log level */
+        static LogLevel _log_level;
+
+        static DigiLogger* current_logger;
+
+        /* Not implemented for base class */
+        virtual void log_buffer(char const * const buffer);
+
+    public:
+
+        /** Class constructor */
+        DigiLogger();
+
+        /** Class destructor */
+        virtual ~DigiLogger();
+
+        /** set_level - set logging level.
+         *
+         *  @param log_level desired overall logging level
+         */
+        static void set_level(LogLevel log_level);
+
+        /** get_level - get logging level.
+         *
+         *  @returns current overall logging level
+         */
+        static LogLevel get_level();
+
+        /** log_format - logs a printf-like message.
+         *
+         *  @param log_level logging level
+         *  @param format ... printf-like message
+         */
+        static void log_format(LogLevel log_level, const char *format, ...);
+
+};
+
+}   /* namespace DigiLog */
+
+#endif /* defined(__DIGI_LOGGER_H_) */
+
+
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "DigiLoggerMbedSerial.h"
+
+using namespace DigiLog;
+
+Serial *DigiLoggerMbedSerial::_log_serial;
+
+/* Class constructor when using a serial port as logging channel */
+DigiLoggerMbedSerial::DigiLoggerMbedSerial(Serial * log_serial, LogLevel log_level)
+{
+    _log_serial = log_serial;
+
+    _log_level = log_level;
+
+    DigiLogger::current_logger = this;
+}
+
+/* Class destructor */
+DigiLoggerMbedSerial::~DigiLoggerMbedSerial()
+{
+    _log_serial = NULL;
+    DigiLogger::current_logger = NULL;
+}
+
+void DigiLoggerMbedSerial::log_buffer(char const * const buffer)
+{
+    if (_log_serial == NULL) {
+        return;
+    }
+
+    _log_serial->printf("%s", buffer);
+    fflush(*_log_serial);
+}
+
+
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DIGI_LOGGER_MBED_SERIAL_H_)
+#define __DIGI_LOGGER_MBED_SERIAL_H_
+
+#include "mbed.h"
+#include "DigiLogger.h"
+
+namespace DigiLog {
+
+class DigiLoggerMbedSerial : public DigiLogger
+{
+    protected:
+
+        /** serial port for debugging */
+        static Serial *_log_serial;
+
+        /** log_buffer - logs a buffer through the configured serial port.
+         *
+         *  @param buffer ... buffer to log
+         */
+        virtual void log_buffer(char const * const buffer);
+
+    public:
+
+        /** Class constructor */
+        DigiLoggerMbedSerial(Serial * log_serial, LogLevel log_level = LogLevelInfo);
+
+        /** Class destructor */
+        virtual ~DigiLoggerMbedSerial();
+};
+
+}   /* namespace DigiLog */
+
+#endif /* defined(__DIGI_LOGGER_MBED_SERIAL_H_) */
+
+
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FrameBuffer.h"
+#include "Utils/Debug.h"
+
+#if !(defined AVOID_DISABLE_IRQS)
+#define disable_irq() __disable_irq()
+#define enable_irq() __enable_irq()
+#else
+#define disable_irq()
+#define enable_irq()
+#endif
+
+FrameBuffer::FrameBuffer(uint8_t size, uint16_t max_payload_len) : _size(size), _head(0), _tail(0), _dropped_frames(0)
+{
+    _frm_buf = new buf_element_t[_size];
+
+    assert(_frm_buf != NULL);
+
+    for (int i = 0; i < _size; i++) {
+        _frm_buf[i].frame = new ApiFrame(max_payload_len - 1);
+        _frm_buf[i].status = FrameStatusFree;
+    }
+}
+
+FrameBuffer::~FrameBuffer()
+{
+    for (int i = 0; i < _size; i++) {
+        delete _frm_buf[i].frame;
+    }
+
+    delete _frm_buf;
+}
+
+ApiFrame *FrameBuffer::get_next_free_frame(void)
+{
+    uint8_t i = _head;
+    ApiFrame *ret = NULL;
+
+    do {
+        if (_frm_buf[i].status == FrameStatusFree || _frm_buf[i].status == FrameStatusComplete) {
+            if (_frm_buf[i].status == FrameStatusComplete) {
+                _dropped_frames++;
+            }
+            _frm_buf[i].status = FrameStatusAssigned;
+            ret = _frm_buf[i].frame;
+            _head = ++i % _size;
+            break;
+        }
+        i++;
+        i = i % _size;
+    } while (i != _head);
+
+    return ret;
+}
+
+bool FrameBuffer::complete_frame(ApiFrame *frame)
+{
+    bool ret = false;
+
+    for (int i = 0; i < _size; i++) {
+        if (_frm_buf[i].frame == frame) {
+            _frm_buf[i].status = FrameStatusComplete;
+            ret = true;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+ApiFrame *FrameBuffer::get_next_complete_frame(void)
+{
+    uint8_t i = _tail;
+    ApiFrame *ret = NULL;
+
+    do {
+        disable_irq();
+        if (_frm_buf[i].status == FrameStatusComplete) {
+            _frm_buf[i].status = FrameStatusAssigned;
+            enable_irq();
+            ret = _frm_buf[i].frame;
+            _tail = ++i % _size;
+            break;
+        }
+        enable_irq();
+        i++;
+        i = i % _size;
+    } while (i != _tail);
+
+    return ret;
+}
+
+bool FrameBuffer::free_frame(ApiFrame *frame)
+{
+    bool ret = false;
+
+    for (int i = 0; i < _size; i++) {
+        if (_frm_buf[i].frame == frame) {
+            _frm_buf[i].status = FrameStatusFree;
+            ret = true;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+uint32_t FrameBuffer::get_dropped_frames_count(void)
+{
+    const uint32_t dropped_frames = _dropped_frames;
+
+    _dropped_frames = 0;
+
+    return dropped_frames;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FRAME_BUFFER_H_)
+#define __FRAME_BUFFER_H_
+
+#include "config.h"
+#include "mbed.h"
+#include "Frames/ApiFrame.h"
+
+#if FRAME_BUFFER_SIZE > 255
+# error "FRAME_BUFFER_SIZE must be lower than 256"
+#endif
+
+typedef struct element {
+    ApiFrame    *frame;
+    uint8_t     status;
+} buf_element_t;
+
+/**
+ *  @class FrameBuffer
+ *  @brief storage class for incoming frames
+ */
+class FrameBuffer
+{
+    public:
+        /** Constructor */
+        FrameBuffer(uint8_t size, uint16_t max_payload_len);
+
+        FrameBuffer(const FrameBuffer& other); /* Intentionally not implemented */
+        /** Destructor */
+        ~FrameBuffer();
+
+        /** get_next_free_frame returns the next free frame
+         *
+         * @returns a pointer to the next free frame */
+        ApiFrame *get_next_free_frame();
+
+        /** complete_frame sets the status of the frame to complete once the
+         *                      data has been set in the buffer.
+         *
+         * @param pointer to the buffer we want to set as complete
+         * @returns true on success, false otherwise
+         */
+        bool complete_frame(ApiFrame *frame);
+
+        /** free_frame makes the frame available to be reused in future
+         *
+         * @param frame to release */
+        bool free_frame(ApiFrame *frame);
+
+        /** get_next_complete_frame returns the pointer to the next complete frame
+         *
+         * @returns the pointer to the selected buffer
+         */
+        ApiFrame *get_next_complete_frame();
+
+        /** get_dropped_frames_count returns the number of dropped frames since latest call to this method
+         *
+         * @returns the number of dropped frames since latest call to this method
+         */
+        uint32_t get_dropped_frames_count();
+
+protected:
+
+        /** frame status */
+        enum FrameStatus {
+            FrameStatusFree = 0,   /**< Free */
+            FrameStatusAssigned,   /**< Assigned */
+            FrameStatusComplete    /**< Complete */
+        };
+
+        /** buffer array */
+        buf_element_t   * _frm_buf;
+
+        uint8_t          _size;
+        
+
+        /** head frame index */
+        uint8_t         _head;
+
+        /** tail frame index for application */
+        uint8_t         _tail;
+
+        /** dropped frames */
+        uint32_t        _dropped_frames;
+};
+
+#endif /* __FRAME_BUFFER_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,208 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FrameHandlers/FH_AtCmdResp.h"
+#include "Frames/ApiFrame.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_AtCmdResp::FH_AtCmdResp() :
+    FrameHandler(ApiFrame::AtCmdResp), at_cmd_resp_cb(NULL)
+{
+}
+
+FH_AtCmdResp::FH_AtCmdResp(ApiFrame::ApiFrameType type) :
+    FrameHandler(type), at_cmd_resp_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_AtCmdResp::~FH_AtCmdResp()
+{
+}
+
+void FH_AtCmdResp::register_at_cmd_resp_cb(at_cmd_resp_cb_t function)
+{
+    at_cmd_resp_cb = function;
+}
+
+void FH_AtCmdResp::unregister_at_cmd_resp_cb()
+{
+    at_cmd_resp_cb = NULL;
+}
+
+void FH_AtCmdResp::process_frame_data(const ApiFrame * const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (at_cmd_resp_cb == NULL) {
+        return;
+    }
+
+    at_cmd_resp_cb(frame->get_data(), frame->get_data_len());
+}
+
+
+/** Class constructor */
+FH_NodeDiscoveryZB::FH_NodeDiscoveryZB() :
+    FH_AtCmdResp(ApiFrame::AtCmdResp), node_discovery_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_NodeDiscoveryZB::~FH_NodeDiscoveryZB()
+{
+}
+
+void FH_NodeDiscoveryZB::register_node_discovery_cb(node_discovery_zb_cb_t function)
+{
+    node_discovery_cb = function;
+}
+
+void FH_NodeDiscoveryZB::unregister_node_discovery_cb()
+{
+    node_discovery_cb = NULL;
+}
+
+
+void FH_NodeDiscoveryZB::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (node_discovery_cb == NULL) {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_CMD_LOW_OFFSET) != 'N' ||
+        frame->get_data_at(ATCMD_RESP_CMD_HIGH_OFFSET) != 'D') {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_STATUS_OFFSET) != AtCmdFrame::AtCmdRespOk) {
+        return;
+    }
+
+    const uint8_t * const data = frame->get_data(); /* The data payload we get here is the full AT command response payload, excluding the frameid. Keep that in mind for the offsets */
+    const uint16_t addr16 = UINT16(data[ATCMD_RESP_NW_ADDR_H_OFFSET], data[ATCMD_RESP_NW_ADDR_L_OFFSET]);
+    const uint64_t addr64 = addr64_from_uint8_t(&data[ATCMD_RESP_SH_ADDR_L_OFFSET]);
+    const char * const node_id = (const char *)&data[ATCMD_RESP_NI_OFFSET];
+    RemoteXBeeZB remote = RemoteXBeeZB(addr64, addr16);
+
+    node_discovery_cb(remote, node_id);
+}
+
+
+
+/** Class constructor */
+FH_NodeDiscovery802::FH_NodeDiscovery802() :
+    FH_AtCmdResp(ApiFrame::AtCmdResp), node_discovery_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_NodeDiscovery802::~FH_NodeDiscovery802()
+{
+}
+
+void FH_NodeDiscovery802::register_node_discovery_cb(node_discovery_802_cb_t function)
+{
+    node_discovery_cb = function;
+}
+
+void FH_NodeDiscovery802::unregister_node_discovery_cb()
+{
+    node_discovery_cb = NULL;
+}
+
+
+void FH_NodeDiscovery802::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (node_discovery_cb == NULL) {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_CMD_LOW_OFFSET) != 'N' ||
+        frame->get_data_at(ATCMD_RESP_CMD_HIGH_OFFSET) != 'D') {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_STATUS_OFFSET) != AtCmdFrame::AtCmdRespOk) {
+        return;
+    }
+
+    const uint16_t min_atnd_response_with_data = sizeof (uint16_t) + sizeof(uint64_t);
+    if (frame->get_data_len() < min_atnd_response_with_data) {
+        /* Do not process the ATND "OK" response */
+        return;
+    }
+
+    const uint8_t * const data = frame->get_data();
+    const uint16_t addr16 = UINT16(data[ATCMD_RESP_NW_ADDR_H_OFFSET], data[ATCMD_RESP_NW_ADDR_L_OFFSET]);
+    const uint64_t addr64 = addr64_from_uint8_t(&data[ATCMD_RESP_SH_ADDR_L_OFFSET]);
+#if 0
+    const uint8_t signal_strength = data[ATCMD_802_RESP_SIGN_STR_OFFSET];
+#endif
+    const RemoteXBee802 remote = RemoteXBee802(addr64, addr16);
+    const char * const nodeid = (const char *)(&data[ATCMD_802_RESP_NI_OFFSET]);
+
+    node_discovery_cb(remote, nodeid);
+}
+
+/** Class constructor */
+FH_NodeDiscoveryDM::FH_NodeDiscoveryDM() :
+    FH_AtCmdResp(ApiFrame::AtCmdResp), node_discovery_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_NodeDiscoveryDM::~FH_NodeDiscoveryDM()
+{
+}
+
+void FH_NodeDiscoveryDM::register_node_discovery_cb(node_discovery_dm_cb_t function)
+{
+    node_discovery_cb = function;
+}
+
+void FH_NodeDiscoveryDM::unregister_node_discovery_cb()
+{
+    node_discovery_cb = NULL;
+}
+
+
+void FH_NodeDiscoveryDM::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (node_discovery_cb == NULL) {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_CMD_LOW_OFFSET) != 'N' ||
+        frame->get_data_at(ATCMD_RESP_CMD_HIGH_OFFSET) != 'D') {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_STATUS_OFFSET) != AtCmdFrame::AtCmdRespOk) {
+        return;
+    }
+
+    const uint8_t * const data = frame->get_data(); /* The data payload we get here is the full AT command response payload, excluding the frameid. Keep that in mind for the offsets */
+    const uint64_t addr64 = addr64_from_uint8_t(&data[ATCMD_RESP_SH_ADDR_L_OFFSET]);
+    const char * const node_id = (const char *)&data[ATCMD_RESP_NI_OFFSET];
+    RemoteXBeeDM remote = RemoteXBeeDM(addr64);
+
+    node_discovery_cb(remote, node_id);
+}
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_AT_CMD_RESP_H_)
+#define __FH_AT_CMD_RESP_H_
+
+#include "FrameHandler.h"
+#include "XBee/XBee.h"
+
+namespace XBeeLib {
+typedef void (*at_cmd_resp_cb_t)(const uint8_t * data, uint16_t len);
+
+class FH_AtCmdResp : public FrameHandler
+{
+    private:
+        /** Callback function, invoked (if registered) when an at command response packet is received */
+        at_cmd_resp_cb_t at_cmd_resp_cb;
+
+    public:
+
+        /** Class constructor */
+        FH_AtCmdResp();
+
+        /** Class constructor */
+        FH_AtCmdResp(ApiFrame::ApiFrameType type);
+
+
+        /** Class destructor */
+        virtual ~FH_AtCmdResp();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_at_cmd_resp_cb(at_cmd_resp_cb_t function);
+
+        virtual void unregister_at_cmd_resp_cb();
+};
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** Node Discovery Response callback type declaration for ZigBee
+  * @param remote discovered remote node.
+  * @param node_id Node Identifier (NI parameter) of remote.
+  */
+typedef void (*node_discovery_zb_cb_t)(const RemoteXBeeZB& remote, char const * const node_id);
+/**
+ * @}
+ */
+
+class FH_NodeDiscoveryZB : public FH_AtCmdResp
+{
+    private:
+        /** Callback function, invoked (if registered) when an at command response packet is received */
+        node_discovery_zb_cb_t node_discovery_cb;
+
+    public:
+
+        /** Class constructor */
+        FH_NodeDiscoveryZB();
+
+        /** Class destructor */
+        virtual ~FH_NodeDiscoveryZB();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_node_discovery_cb(node_discovery_zb_cb_t function);
+
+        virtual void unregister_node_discovery_cb();
+};
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** Node Discovery Response callback type declaration for ZigBee
+  * @param remote discovered remote node.
+  * @param node_id Node Identifier (NI parameter) of remote.
+  */
+typedef void (*node_discovery_dm_cb_t)(const RemoteXBeeDM& remote, char const * const node_id);
+/**
+ * @}
+ */
+
+class FH_NodeDiscoveryDM : public FH_AtCmdResp
+{
+    private:
+        /** Callback function, invoked (if registered) when an at command response packet is received */
+        node_discovery_dm_cb_t node_discovery_cb;
+
+    public:
+
+        /** Class constructor */
+        FH_NodeDiscoveryDM();
+
+        /** Class destructor */
+        virtual ~FH_NodeDiscoveryDM();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_node_discovery_cb(node_discovery_dm_cb_t function);
+
+        virtual void unregister_node_discovery_cb();
+};
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** Node Discovery Response callback type declaration for 802.15.4
+  * @param remote discovered remote node.
+  * @param node_id Node Identifier (NI parameter) of remote.
+  */
+typedef void (*node_discovery_802_cb_t)(const RemoteXBee802& remote, char const * const node_id);
+/**
+ * @}
+ */
+
+class FH_NodeDiscovery802 : public FH_AtCmdResp
+{
+    private:
+        /** Callback function, invoked (if registered) when an at command response packet is received */
+        node_discovery_802_cb_t node_discovery_cb;
+
+    public:
+
+        /** Class constructor */
+        FH_NodeDiscovery802();
+
+        /** Class destructor */
+        virtual ~FH_NodeDiscovery802();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_node_discovery_cb(node_discovery_802_cb_t function);
+
+        virtual void unregister_node_discovery_cb();
+};
+
+} /* namespace XBeeLib */
+
+#endif /* __FH_AT_CMD_RESP_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_IoDataSampe64b802::FH_IoDataSampe64b802() : FrameHandler(ApiFrame::Io64Bit),
+    io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampe64b802::~FH_IoDataSampe64b802()
+{
+
+}
+
+void FH_IoDataSampe64b802::register_io_data_cb(io_data_cb_802_t function)
+{
+    io_data_cb = function;
+}
+
+void FH_IoDataSampe64b802::unregister_io_data_cb()
+{
+    io_data_cb = NULL;
+}
+
+#define IO_SAMPLE_64_802_DATA_OFFSET        10
+
+void FH_IoDataSampe64b802::process_frame_data(const ApiFrame *const frame)
+{
+    const uint8_t * const datap = frame->get_data();
+
+    /* The caller checks that the type matches, so no need to check it here again */
+    if (io_data_cb == NULL) {
+        return;
+    }
+
+    /* We got an IO packet, decode it... */
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const RemoteXBee802 sender = RemoteXBee802(sender64);
+    const IOSample802 ioSample = IOSample802(&datap[IO_SAMPLE_64_802_DATA_OFFSET], frame->get_data_len() - IO_SAMPLE_64_802_DATA_OFFSET);
+
+    io_data_cb(sender, ioSample);
+}
+
+/** Class constructor */
+FH_IoDataSampe16b802::FH_IoDataSampe16b802() : FrameHandler(ApiFrame::Io16Bit),
+    io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampe16b802::~FH_IoDataSampe16b802()
+{
+}
+
+void FH_IoDataSampe16b802::register_io_data_cb(io_data_cb_802_t function)
+{
+    io_data_cb = function;
+}
+
+void FH_IoDataSampe16b802::unregister_io_data_cb()
+{
+    io_data_cb = NULL;
+}
+
+#define IO_SAMPLE_16_802_ADDR16_MSB_OFFSET  0
+#define IO_SAMPLE_16_802_ADDR16_LSB_OFFSET  1
+#define IO_SAMPLE_16_802_DATA_OFFSET        4
+
+void FH_IoDataSampe16b802::process_frame_data(const ApiFrame *const frame)
+{
+    const uint8_t * const datap = frame->get_data();;
+
+    /* The caller checks that the type matches, so no need to check it here again */
+    if (io_data_cb == NULL) {
+        return;
+    }
+
+    /* We got an IO packet, decode it... */
+    const uint16_t sender16 = ADDR16(datap[IO_SAMPLE_16_802_ADDR16_MSB_OFFSET], datap[IO_SAMPLE_16_802_ADDR16_LSB_OFFSET]);
+    const RemoteXBee802 sender = RemoteXBee802(sender16);
+
+    const IOSample802 ioSample = IOSample802(&datap[IO_SAMPLE_16_802_DATA_OFFSET], frame->get_data_len() - IO_SAMPLE_16_802_DATA_OFFSET);
+
+    io_data_cb(sender, ioSample);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_IO_DATA_SAMPLE_802_H_)
+#define __FH_IO_DATA_SAMPLE_802_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+class IOSample802;
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** IO Data Sample reception (802.15.4 modules) callback type declaration
+  * @param remote the remote module that sent the data
+  * @param sample_data a referece to an @ref IOSample802 that can be queried for the IoLines' values
+  */
+typedef void (*io_data_cb_802_t)(const RemoteXBee802& remote, const IOSample802& sample_data);
+/**
+ * @}
+ */
+
+
+class FH_IoDataSampe64b802 : public FrameHandler
+{
+    public:
+        /** Class constructor */
+        FH_IoDataSampe64b802();
+
+        /** Class destructor */
+        virtual ~FH_IoDataSampe64b802();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        void register_io_data_cb(io_data_cb_802_t function);
+        void unregister_io_data_cb();
+
+    private:
+        /** Callback function, invoked if registered */
+        io_data_cb_802_t io_data_cb;
+
+};
+
+class FH_IoDataSampe16b802 : public FrameHandler
+{
+    public:
+        /** Class constructor */
+        FH_IoDataSampe16b802();
+
+        /** Class destructor */
+        virtual ~FH_IoDataSampe16b802();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        void register_io_data_cb(io_data_cb_802_t function);
+
+        void unregister_io_data_cb();
+
+    private:
+        /** Callback function, invoked if registered */
+        io_data_cb_802_t io_data_cb;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_IO_DATA_SAMPLE_802_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_IoDataSampeDM::FH_IoDataSampeDM() : FrameHandler(ApiFrame::IoSampleRxZBDM),
+    io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampeDM::~FH_IoDataSampeDM()
+{
+}
+
+void FH_IoDataSampeDM::register_io_data_cb(io_data_cb_dm_t function)
+{
+    io_data_cb = function;
+}
+
+void FH_IoDataSampeDM::unregister_io_data_cb()
+{
+    io_data_cb = NULL;
+}
+
+/* DM RX packet offsets */
+#define DM_IO_SAMPLE_DATA_OFFSET            11
+
+void FH_IoDataSampeDM::process_frame_data(const ApiFrame *const frame)
+{
+    const uint8_t * const datap = frame->get_data();;
+
+    /* The caller checks that the type matches, so no need to check it here again */
+    if (io_data_cb == NULL) {
+        return;
+    }
+
+    /* We got an IO packet, decode it... */
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const RemoteXBeeDM sender = RemoteXBeeDM(sender64);
+    const IOSampleDM ioSample = IOSampleDM(&datap[DM_IO_SAMPLE_DATA_OFFSET], frame->get_data_len() - DM_IO_SAMPLE_DATA_OFFSET);
+
+    io_data_cb(sender, ioSample);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_IO_DATA_SAMPLE_DM_H_)
+#define __FH_IO_DATA_SAMPLE_DM_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+class IOSampleDM;
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** IO Data Sample reception (ZigBee modules) callback type declaration
+  * @param remote the remote module that sent the data
+  * @param sample_data a referece to an @ref IOSampleDM that can be queried for the IoLines' values
+  */
+typedef void (*io_data_cb_dm_t)(const RemoteXBeeDM& remote, const IOSampleDM& sample_data);
+/**
+ * @}
+ */
+
+class FH_IoDataSampeDM : public FrameHandler
+{
+    public:
+        /** Class constructor */
+        FH_IoDataSampeDM();
+
+        /** Class destructor */
+        virtual ~FH_IoDataSampeDM();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        void register_io_data_cb(io_data_cb_dm_t function);
+
+        void unregister_io_data_cb();
+
+    private:
+        /** Callback function, invoked if registered */
+        io_data_cb_dm_t io_data_cb;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_IO_DATA_SAMPLE_DM_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_IoDataSampeZB::FH_IoDataSampeZB() : FrameHandler(ApiFrame::IoSampleRxZBDM),
+    io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampeZB::~FH_IoDataSampeZB()
+{
+}
+
+void FH_IoDataSampeZB::register_io_data_cb(io_data_cb_zb_t function)
+{
+    io_data_cb = function;
+}
+
+void FH_IoDataSampeZB::unregister_io_data_cb()
+{
+    io_data_cb = NULL;
+}
+
+/* ZB RX packet offsets */
+#define ZB_IO_SAMPLE_ADDR16_MSB_OFFSET      8
+#define ZB_IO_SAMPLE_ADDR16_LSB_OFFSET      9
+#define ZB_IO_SAMPLE_DATA_OFFSET            11
+
+void FH_IoDataSampeZB::process_frame_data(const ApiFrame *const frame)
+{
+    const uint8_t * const datap = frame->get_data();;
+
+    /* The caller checks that the type matches, so no need to check it here again */
+    if (io_data_cb == NULL) {
+        return;
+    }
+
+    /* We got an IO packet, decode it... */
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const uint16_t sender16 = ADDR16(datap[ZB_IO_SAMPLE_ADDR16_MSB_OFFSET], datap[ZB_IO_SAMPLE_ADDR16_LSB_OFFSET]);
+    const RemoteXBeeZB sender = RemoteXBeeZB(sender64, sender16);
+    const IOSampleZB ioSample = IOSampleZB(&datap[ZB_IO_SAMPLE_DATA_OFFSET], frame->get_data_len() - ZB_IO_SAMPLE_DATA_OFFSET);
+
+    io_data_cb(sender, ioSample);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_IO_DATA_SAMPLE_ZB_H_)
+#define __FH_IO_DATA_SAMPLE_ZB_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+class IOSampleZB;
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** IO Data Sample reception (ZigBee modules) callback type declaration
+  * @param remote the remote module that sent the data
+  * @param sample_data a referece to an @ref IOSampleZB that can be queried for the IoLines' values
+  */
+typedef void (*io_data_cb_zb_t)(const RemoteXBeeZB& remote, const IOSampleZB& sample_data);
+/**
+ * @}
+ */
+
+class FH_IoDataSampeZB : public FrameHandler
+{
+    public:
+        /** Class constructor */
+        FH_IoDataSampeZB();
+
+        /** Class destructor */
+        virtual ~FH_IoDataSampeZB();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        void register_io_data_cb(io_data_cb_zb_t function);
+
+        void unregister_io_data_cb();
+
+    private:
+        /** Callback function, invoked if registered */
+        io_data_cb_zb_t io_data_cb;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_IO_DATA_SAMPLE_ZB_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FH_ModemStatus.h"
+
+/** Class constructor */
+FH_ModemStatus::FH_ModemStatus() : FrameHandler(ApiFrame::AtModemStatus), modem_status_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_ModemStatus::~FH_ModemStatus()
+{
+}
+
+void FH_ModemStatus::register_modem_status_cb(modem_status_cb_t function)
+{
+    modem_status_cb = function;
+}
+
+void FH_ModemStatus::unregister_modem_status_cb(void)
+{
+    modem_status_cb = NULL;
+}
+
+void FH_ModemStatus::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (modem_status_cb == NULL) {
+        return;
+    }
+
+    modem_status_cb((AtCmdFrame::ModemStatus)frame->get_data_at(0));
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_MODEM_STATUS_H_)
+#define __FH_MODEM_STATUS_H_
+
+#include "Frames/AtCmdFrame.h"
+#include "FrameHandler.h"
+
+typedef void (*modem_status_cb_t)(AtCmdFrame::ModemStatus status);
+
+class FH_ModemStatus : public FrameHandler
+{
+    private:
+        /** Callback function, invoked (if registered) when a modem status packet is received */
+        modem_status_cb_t modem_status_cb;
+
+    public:
+        /** Class constructor */
+        FH_ModemStatus();
+
+        /** Class destructor */
+        virtual ~FH_ModemStatus();
+
+         /** Method called by the stack to process the modem status frame data
+
+             \param frame pointer pointing to api frame that must be processed */
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_modem_status_cb(modem_status_cb_t function);
+
+        virtual void unregister_modem_status_cb(void);
+};
+
+#endif /* __FH_MODEM_STATUS_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,108 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FH_RxPacket802.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_RxPacket64b802::FH_RxPacket64b802() : FrameHandler(ApiFrame::RxPacket64Bit),
+    receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacket64b802::~FH_RxPacket64b802()
+{
+}
+
+void FH_RxPacket64b802::register_receive_cb(receive_802_cb_t function)
+{
+    receive_cb = function;
+}
+
+void FH_RxPacket64b802::unregister_receive_cb(void)
+{
+    receive_cb = NULL;
+}
+
+/* 802.15.4 RX packet offsets */
+#define RX_802_RSSI_OFFSET          8
+#define RX_802_OPTIONS_OFFSET       9
+#define RX_802_DATA_OFFSET          10
+#define RX_802_OVERHEAD             (8+1+1)
+
+#define BROADCAST_PACKET            0x02
+
+void FH_RxPacket64b802::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (receive_cb == NULL) {
+        return;
+    }
+
+    /* We got a rx packet, decode it... */
+    const uint8_t *datap = frame->get_data();
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const uint8_t rx_options = datap[RX_802_OPTIONS_OFFSET];
+    const RemoteXBee802 sender = RemoteXBee802(sender64);
+
+    receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[RX_802_DATA_OFFSET], frame->get_data_len() - RX_802_OVERHEAD);
+}
+
+
+/** Class constructor */
+FH_RxPacket16b802::FH_RxPacket16b802() : FrameHandler(ApiFrame::RxPacket16Bit),
+    receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacket16b802::~FH_RxPacket16b802()
+{
+}
+
+void FH_RxPacket16b802::register_receive_cb(receive_802_cb_t function)
+{
+    receive_cb = function;
+}
+
+void FH_RxPacket16b802::unregister_receive_cb(void)
+{
+    receive_cb = NULL;
+}
+
+/* 802.15.4 RX packet offsets */
+#define RX_802_ADDR16_MSB_OFFSET    0
+#define RX_802_ADDR16_LSB_OFFSET    1
+#define RX_802_RSSI_OFFSET2         2
+#define RX_802_OPTIONS_OFFSET2      3
+#define RX_802_DATA_OFFSET2         4
+#define RX_802_OVERHEAD2            (2+1+1)
+
+void FH_RxPacket16b802::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (receive_cb == NULL) {
+        return;
+    }
+
+    /* We got a rx packet, decode it... */
+    const uint8_t *datap = frame->get_data();
+    const uint16_t sender16 = ADDR16(datap[RX_802_ADDR16_MSB_OFFSET], datap[RX_802_ADDR16_LSB_OFFSET]);
+    const uint8_t rx_options = datap[RX_802_OPTIONS_OFFSET2];
+    const RemoteXBee802 sender = RemoteXBee802(sender16);
+
+    receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[RX_802_DATA_OFFSET2], frame->get_data_len() - RX_802_OVERHEAD2);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_RX_PACKET_802_H_)
+#define __FH_RX_PACKET_802_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** receive callback type declaration
+  * @param remote the remote module that sent the data
+  * @param broadcast a boolean to tell if the message was broadcast (true) or unicast (false)
+  * @param data a pointer to data sent by @b remote.
+  * @param len length (in bytes) of @b data buffer
+  */
+typedef void (*receive_802_cb_t)(const RemoteXBee802& remote, bool broadcast, const uint8_t *const data, uint16_t len);
+/**
+ * @}
+ */
+
+class FH_RxPacket64b802 : public FrameHandler
+{
+    private:
+        /** Callback function, invoked if registered */
+        receive_802_cb_t receive_cb;
+
+    public:
+        /** Class constructor */
+        FH_RxPacket64b802();
+
+        /** Class destructor */
+        virtual ~FH_RxPacket64b802();
+
+        virtual void process_frame_data(const ApiFrame* const frame);
+
+        virtual void register_receive_cb(receive_802_cb_t function);
+
+        virtual void unregister_receive_cb();
+};
+
+class FH_RxPacket16b802 : public FrameHandler
+{
+    private:
+        /** Callback function, invoked if registered */
+        receive_802_cb_t receive_cb;
+
+    public:
+        /** Class constructor */
+        FH_RxPacket16b802();
+
+        /** Class destructor */
+        virtual ~FH_RxPacket16b802();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_receive_cb(receive_802_cb_t function);
+
+        virtual void unregister_receive_cb();
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_RX_PACKET_802_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FH_RxPacketDM.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_RxPacketDM::FH_RxPacketDM() : FrameHandler(ApiFrame::RxPacketAO0), receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacketDM::~FH_RxPacketDM()
+{
+}
+
+void FH_RxPacketDM::register_receive_cb(receive_dm_cb_t function)
+{
+    receive_cb = function;
+}
+
+void FH_RxPacketDM::unregister_receive_cb(void)
+{
+    receive_cb = NULL;
+}
+
+/* DM RX packet offsets */
+#define DM_RX_OPTIONS_OFFSET        10
+#define DM_RX_DATA_OFFSET           11
+#define DM_RX_OVERHEAD              (8+2+1)
+
+#define BROADCAST_PACKET            0x02
+
+void FH_RxPacketDM::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (receive_cb == NULL) {
+        return;
+    }
+
+    /* We got a rx packet, decode it... */
+    const uint8_t *datap = frame->get_data();
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const uint8_t rx_options = datap[DM_RX_OPTIONS_OFFSET];
+    const RemoteXBeeDM sender = RemoteXBeeDM(sender64);
+
+    receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[DM_RX_DATA_OFFSET], frame->get_data_len() - DM_RX_OVERHEAD);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_RX_PACKET_DM_H_)
+#define __FH_RX_PACKET_DM_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** receive callback type declaration
+  * @param remote the remote module that sent the data
+  * @param broadcast a boolean to tell if the message was broadcast (true) or unicast (false)
+  * @param data a pointer to data sent by @b remote.
+  * @param len length (in bytes) of @b data buffer
+  */
+typedef void (*receive_dm_cb_t)(const RemoteXBeeDM& remote, bool broadcast, const uint8_t *const data, uint16_t len);
+/**
+ * @}
+ */
+
+class FH_RxPacketDM : public FrameHandler
+{
+    private:
+        /** Callback function, invoked if registered */
+        receive_dm_cb_t receive_cb;
+
+    public:
+        /** Class constructor */
+        FH_RxPacketDM();
+
+        /** Class destructor */
+        virtual ~FH_RxPacketDM();
+
+        /** Method called by the stack to process the modem status frame data
+
+            \param frame pointer pointing to api frame that must be processed */
+        virtual void process_frame_data(const ApiFrame* const frame);
+
+        void register_receive_cb(receive_dm_cb_t function);
+
+        void unregister_receive_cb();
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_RX_PACKET_DM_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FH_RxPacketZB.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_RxPacketZB::FH_RxPacketZB() : FrameHandler(ApiFrame::RxPacketAO0), receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacketZB::~FH_RxPacketZB()
+{
+}
+
+void FH_RxPacketZB::register_receive_cb(receive_zb_cb_t function)
+{
+    receive_cb = function;
+}
+
+void FH_RxPacketZB::unregister_receive_cb(void)
+{
+    receive_cb = NULL;
+}
+
+/* ZB RX packet offsets */
+#define ZB_RX_ADDR16_MSB_OFFSET     8
+#define ZB_RX_ADDR16_LSB_OFFSET     9
+#define ZB_RX_OPTIONS_OFFSET        10
+#define ZB_RX_DATA_OFFSET           11
+#define ZB_RX_OVERHEAD              (8+2+1)
+
+#define BROADCAST_PACKET            0x02
+
+void FH_RxPacketZB::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (receive_cb == NULL) {
+        return;
+    }
+
+    /* We got a rx packet, decode it... */
+    const uint8_t *datap = frame->get_data();
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const uint16_t sender16 = ADDR16(datap[ZB_RX_ADDR16_MSB_OFFSET], datap[ZB_RX_ADDR16_LSB_OFFSET]);
+    const uint8_t rx_options = datap[ZB_RX_OPTIONS_OFFSET];
+    const RemoteXBeeZB sender = RemoteXBeeZB(sender64, sender16);
+
+    receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[ZB_RX_DATA_OFFSET], frame->get_data_len() - ZB_RX_OVERHEAD);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_RX_PACKET_ZB_H_)
+#define __FH_RX_PACKET_ZB_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** receive callback type declaration
+  * @param remote the remote module that sent the data
+  * @param broadcast a boolean to tell if the message was broadcast (true) or unicast (false)
+  * @param data a pointer to data sent by @b remote.
+  * @param len length (in bytes) of @b data buffer
+  */
+typedef void (*receive_zb_cb_t)(const RemoteXBeeZB& remote, bool broadcast, const uint8_t *const data, uint16_t len);
+/**
+ * @}
+ */
+
+class FH_RxPacketZB : public FrameHandler
+{
+    private:
+        /** Callback function, invoked if registered */
+        receive_zb_cb_t receive_cb;
+
+    public:
+        /** Class constructor */
+        FH_RxPacketZB();
+
+        /** Class destructor */
+        virtual ~FH_RxPacketZB();
+
+        /** Method called by the stack to process the modem status frame data
+
+            \param frame pointer pointing to api frame that must be processed */
+        virtual void process_frame_data(const ApiFrame* const frame);
+
+        void register_receive_cb(receive_zb_cb_t function);
+
+        void unregister_receive_cb();
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_RX_PACKET_ZB_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FrameHandler.h"
+
+FrameHandler::FrameHandler(ApiFrame::ApiFrameType t) : _type(t)
+{
+}
+
+FrameHandler::~FrameHandler()
+{
+}
+
+ApiFrame::ApiFrameType FrameHandler::get_type() const
+{
+    return _type;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FRAME_HANDLER_H_)
+#define __FRAME_HANDLER_H_
+
+#include "Frames/ApiFrame.h"
+
+/** Class for the frame handlers */
+class FrameHandler
+{
+    friend class ApiFrame;
+
+    public:
+        /** Class constructor
+         *
+         * @param type frame type handled by this frame handler
+         */
+        FrameHandler(ApiFrame::ApiFrameType type);
+
+        FrameHandler(const FrameHandler& other); /* Intentionally not implemented */
+        /** Class destructor */
+        virtual ~FrameHandler();
+
+        /** get_type returns the type of frames handled by this handler
+         *
+         * @returns the frame type handled by the handler
+         */
+        ApiFrame::ApiFrameType get_type() const;
+
+        /** process_frame_data method called by the library to process the
+         *                     the incoming frames if the type matches.
+         *
+         * @param frame pointer pointing to the api frame that must be processed
+         */
+        virtual void process_frame_data(const ApiFrame *const frame) = 0;
+
+    protected:
+        /** frame type handled by this handler */
+        ApiFrame::ApiFrameType   _type;
+};
+
+#endif /* defined(__FRAME_HANDLER_H_) */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/802_Frames.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/802_Frames.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "802_Frames.h"
+
+#define FRAME_ID_LEN              1
+#define ADDR64_LEN                8
+#define ADDR16_LEN                2
+#define OPTIONS_LEN               1
+#define TX_REQUEST_OVERHEAD       (FRAME_ID_LEN + ADDR64_LEN + OPTIONS_LEN)
+#define TX_REQUEST_OVERHEAD2      (FRAME_ID_LEN + ADDR16_LEN + OPTIONS_LEN)
+
+/** Class constructor */
+TxFrame802::TxFrame802(uint64_t addr, uint8_t tx_options,
+                const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[TX_REQUEST_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the tx options byte
+     * and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = tx_options;
+
+    if (len) {
+        memcpy(&frame_data[10], data, len);
+    }
+
+    set_api_frame(TxReq64Bit, frame_data, TX_REQUEST_OVERHEAD + len);
+}
+
+/** Class constructor */
+TxFrame802::TxFrame802(uint16_t addr16, uint8_t tx_options,
+                const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[TX_REQUEST_OVERHEAD2 + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 16bit remote address, the tx options byte
+     * and the frame data */
+
+    frame_data[0] = _frame_id;
+    frame_data[1] = (uint8_t)(addr16 >> 8);
+    frame_data[2] = (uint8_t)addr16;
+    frame_data[3] = tx_options;
+
+    if (len) {
+        memcpy(&frame_data[4], data, len);
+    }
+
+    set_api_frame(TxReq16Bit, frame_data, TX_REQUEST_OVERHEAD2 + len);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/802_Frames.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/802_Frames.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__802_FRAMES_H_)
+#define __802_FRAMES_H_
+
+#include "ApiFrame.h"
+
+class TxFrame802 : public ApiFrame
+{
+    public:
+        /** Class constructor */
+        TxFrame802(uint64_t addr, uint8_t tx_options, const uint8_t *const data, uint16_t len);
+        TxFrame802(uint16_t addr16, uint8_t tx_options, const uint8_t *const data, uint16_t len);
+
+    protected:
+};
+
+#endif /* __802_FRAMES_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/ApiFrame.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/ApiFrame.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,132 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "mbed.h"
+#include "XBee/XBee.h"
+#include "ApiFrame.h"
+
+using namespace XBeeLib;
+
+uint8_t ApiFrame::last_frame_id = 0;
+
+ApiFrame::ApiFrame(void)
+{
+    this->_type = Invalid;
+    this->_data = NULL;
+    this->_data_frame_len = 0;
+    this->_alloc_data = false;
+    _frame_id = get_next_frame_id();
+}
+
+ApiFrame::ApiFrame(uint16_t len)
+{
+    this->_type = Invalid;
+    this->_data = new uint8_t[len];
+    this->_alloc_data = true;
+    this->_data_frame_len = len;
+    this->_frame_id = get_next_frame_id();
+}
+
+uint8_t ApiFrame::get_next_frame_id(void)
+{
+    last_frame_id++;
+    if (last_frame_id == 0) {
+        last_frame_id++;
+    }
+
+    return last_frame_id;
+}
+
+ApiFrame::ApiFrame(ApiFrameType type, const uint8_t *data, uint16_t len)
+{
+    this->_data = NULL;
+    set_api_frame(type, data, len);
+}
+
+void ApiFrame::set_api_frame(ApiFrameType type, const uint8_t *data, uint16_t len)
+{
+    this->_type = type;
+    this->_data_frame_len = len;
+    if (this->_data) {
+        delete _data;
+    }
+    this->_data = new uint8_t[len];
+    this->_alloc_data = true;
+    assert(this->_data != NULL);
+    memcpy((void *)this->_data, data, len);
+}
+
+ApiFrame::~ApiFrame()
+{
+    if (this->_data != NULL && this->_alloc_data) {
+        delete[] this->_data;
+    }
+}
+
+void ApiFrame::dump(void) const
+{
+#if defined(ENABLE_LOGGING)
+    digi_log(LogLevelFrameData, "API frame: type %02x, len %d\r\n", this->_type, this->_data_frame_len);
+    for (int i = 0; i < this->_data_frame_len; i++)
+        digi_log(LogLevelFrameData, "%02x ", this->_data[i]);
+    digi_log(LogLevelFrameData, "\r\n");
+#endif
+}
+
+void ApiFrame::dump_if(ApiFrameType type)
+{
+    if (_type != type) {
+        return;
+    }
+    dump();
+}
+
+ApiFrame::ApiFrameType ApiFrame::get_frame_type() const
+{
+    return _type;
+}
+
+void ApiFrame::set_frame_type(ApiFrameType type)
+{
+    _type = type;
+}
+
+uint16_t ApiFrame::get_data_len() const
+{
+    return _data_frame_len;
+}
+
+void ApiFrame::set_data_len(uint16_t len)
+{
+    _data_frame_len = len;
+}
+
+const uint8_t *ApiFrame::get_data() const
+{
+    return _data;
+}
+
+uint8_t ApiFrame::get_data_at(uint16_t index) const
+{
+    return *(_data + index);
+}
+
+void ApiFrame::set_data(uint8_t d, uint16_t index)
+{
+    *(_data + index) = d;
+}
+
+/* Returns the frame_id of this frame */
+uint8_t ApiFrame::get_frame_id() const
+{
+    return _frame_id;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/ApiFrame.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/ApiFrame.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,177 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__API_FRAME_H_)
+#define __API_FRAME_H_
+
+#include "XBee/Addresses.h"
+
+/** Class for XBee API frames */
+class ApiFrame
+{
+    /** Static variable that contains the last frame ID value assigned */
+    static uint8_t      last_frame_id;
+
+        public:
+        /** List of API frames. Note that not all frames are supported by all radios */
+        enum ApiFrameType {
+
+            TxReq64Bit      = 0x00,     /**< TxReq64Bit: Only for 802.15.4 modules */
+            TxReq16Bit      = 0x01,     /**< TxReq16Bit: Only for 802.15.4 modules */
+            AtCmd           = 0x08,     /**< AtCmd */
+            AtCmdQueuePV    = 0x09,     /**< AtCmdQueuePV */
+            TxReqZBDM       = 0x10,     /**< TxReqZBDM: Only for ZigBee and DigiMesh modules */
+            ExpAddrCmd      = 0x11,     /**< ExpAddrCmd: Only for ZigBee modules and DigiMesh */
+            RemoteCmdReq    = 0x17,     /**< RemoteCmdReq */
+            CreateSrcRoute  = 0x21,     /**< CreateSrcRoute */
+            RxPacket64Bit   = 0x80,     /**< RxPacket64Bit: Only for 802.15.4 modules */
+            RxPacket16Bit   = 0x81,     /**< RxPacket16Bit: Only for 802.15.4 modules */
+            Io64Bit         = 0x82,     /**< Io64Bit: Only for 802.15.4 modules */
+            Io16Bit         = 0x83,     /**< Io16Bit */
+            AtCmdResp       = 0x88,     /**< AtCmdResp */
+            TxStatus        = 0x89,     /**< TxStatus */
+            AtModemStatus   = 0x8A,     /**< AtModemStatus */
+            TxStatusZBDM    = 0x8B,     /**< TxStatusZBDM: Only for ZigBee and DigiMesh modules */
+            RouteInfo       = 0x8D,     /**< RouteInfo: Only for DigiMesh modules */
+            AggregateAddr   = 0x8E,     /**< AggregateAddr: Only for DigiMesh modules */
+            RxPacketAO0     = 0x90,     /**< RxPacketAO0: Only for ZigBee and DigiMesh modules */
+            RxPacketAO1     = 0x91,     /**< RxPacketAO1: Only for ZigBee and DigiMesh modules */
+            IoSampleRxZBDM  = 0x92,     /**< IoSampleRxZBDM: Only for ZigBee and DigiMesh modules */
+            SensorRxIndAO0  = 0x94,     /**< SensorRxIndAO0: Only for ZigBee modules */
+            NodeIdentIndAO0 = 0x95,     /**< NodeIdentIndAO0: Only for ZigBee and DigiMesh modules */
+            RemoteCmdResp   = 0x97,     /**< RemoteCmdResp */
+            OtaFwUpStatus   = 0xA0,     /**< OtaFwUpStatus */
+            RouteRecInd     = 0xA1,     /**< RouteRecInd */
+            Many2OneRRInd   = 0xA3,     /**< Many2OneRRInd */
+            Invalid         = ~0,       /**< Invalid */
+        };
+
+        /** Default constructor */
+        ApiFrame();
+
+        /** Constructor
+         *
+         * @param len length of the API frame (will allocate len bytes).
+         */
+        ApiFrame(uint16_t len);
+
+        /** Constructor
+         *
+         * @param type frame type of this api frame.
+         * @param data pointer to frame data payload.
+         * @param len length of the payload.
+         */
+        ApiFrame(ApiFrameType type, const uint8_t *data, uint16_t len);
+
+        /** Destructor */
+        ~ApiFrame();
+
+        ApiFrame(const ApiFrame& other); /* Intentionally not implemented */
+
+        /** get_frame_type gets the type of the frame
+         *
+         * @returns the type of this frame.
+         */
+        ApiFrameType get_frame_type() const;
+
+        /** dump dumps the information of this frame */
+        void dump() const;
+
+        /** dump_if dumps the information of the frame if the frame type matches
+         *          with the parameter.
+         *
+         * @param type dump the frame info/data if the frame type matches with type.
+         */
+        void dump_if(ApiFrameType type);
+
+
+        /** set_frame_type sets the type of the frame to type.
+         *
+         * @param type the type we want to set on the frame.
+         */
+        void set_frame_type(ApiFrameType type);
+
+        /** get_data_len gets the length of the frame data payload.
+         *
+         * @returns the length of the data payload.
+         */
+        uint16_t get_data_len() const;
+
+        /** set_data_len sets the length of the frame data payload.
+         *
+         * @param len the length of the data payload will be set on this frame.
+         */
+        void set_data_len(uint16_t len);
+
+        /** get_data returns a pointer to the frame data payload.
+         *
+         * @returns a pointer to the frame data payload.
+         */
+        const uint8_t *get_data() const;
+
+        /** get_data_at returns the byte at index offset.
+         *
+         * @param index offset of the byte we want to get.
+         * @returns the byte at index offset.
+         */
+        uint8_t get_data_at(uint16_t index) const;
+
+        /** set_data sets data byte at the specified index or offset.
+         *
+         * @param data byte that will be set at index position.
+         * @param index offset of the byte we want to set.
+         */
+        void set_data(uint8_t data, uint16_t index);
+
+        /** get_frame_id returns the frame id of this frame.
+         *
+         * @returns the frame id of this frame.
+         */
+        uint8_t get_frame_id() const;
+
+        static uint8_t get_current_frame_id()
+        {
+            return last_frame_id;
+        }
+
+    protected:
+        /** Type of this frame */
+        ApiFrameType        _type;
+
+        /** length of the payload, excluding the frame type */
+        uint16_t            _data_frame_len;
+
+        /** pointer to the frame data */
+        uint8_t             *_data;
+
+        /** True if the constructor allocates the data. Needed to delete it on the destructor */
+        bool                _alloc_data;
+
+        /** Frame ID of this frame */
+        uint8_t             _frame_id;
+
+        /** get_next_frame_id - returns the next frame ID secuentially, skipping the value 0
+         *
+         *  @returns the next frame ID that should be assigned to a frame
+         */
+        uint8_t get_next_frame_id();
+
+        /** set_api_frame sets several members
+         *
+         * @param type frame type of this api frame.
+         * @param data pointer to frame data payload.
+         * @param len length of the payload.
+         */
+        void set_api_frame(ApiFrameType type, const uint8_t *data, uint16_t len);
+};
+
+#endif /* __API_FRAME_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/AtCmdFrame.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/AtCmdFrame.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "mbed.h"
+#include "Utils/Debug.h"
+#include "AtCmdFrame.h"
+
+#define AT_CMD_LEN              2
+#define AT_CMD_ID_LEN           1
+
+void AtCmdFrame::build_at_cmd_frame(const char *cmd, const uint8_t *cmd_params, uint8_t payload_len, bool reverse)
+{
+    uint8_t frame_data[AT_CMD_LEN + AT_CMD_ID_LEN + payload_len];
+
+    frame_data[0] = _frame_id;
+    frame_data[1] = cmd[0];
+    frame_data[2] = cmd[1];
+    if (payload_len) {
+        if (reverse) {
+            rmemcpy(&frame_data[3], cmd_params, payload_len);
+        } else {
+            memcpy(&frame_data[3], cmd_params, payload_len);
+        }
+    }
+
+    set_api_frame(AtCmd, frame_data, AT_CMD_LEN + AT_CMD_ID_LEN + payload_len);
+}
+
+AtCmdFrame::AtCmdFrame(const char * const cmd, uint32_t cmd_param)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    uint8_t len;
+    if (cmd_param <= 0xFF) {
+        len = 1;
+    } else if (cmd_param <= 0xFFFF) {
+        len = 2;
+    } else if (cmd_param <= 0xFFFFFF) {
+        len = 3;
+    } else {
+        len = 4;
+    }
+    build_at_cmd_frame(cmd, (uint8_t *)&cmd_param, len);
+}
+
+AtCmdFrame::AtCmdFrame(const char * const cmd, const uint8_t * cmd_param, uint16_t param_len)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_frame(cmd, cmd_param, param_len, false);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote, const char * const cmd, uint32_t cmd_param)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(remote, ADDR16_UNKNOWN, cmd, (uint8_t *)&cmd_param, 4);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote, const char * const cmd, const uint8_t * cmd_param, uint16_t param_len)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(remote, ADDR16_UNKNOWN, cmd, cmd_param, param_len, false);
+}
+
+AtCmdFrame::AtCmdFrame(uint16_t remote, const char * const cmd, uint32_t cmd_param)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(ADDR64_UNASSIGNED, remote, cmd, (uint8_t *)&cmd_param, 4);
+}
+
+AtCmdFrame::AtCmdFrame(uint16_t remote, const char * const cmd, const uint8_t * cmd_param, uint16_t param_len)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(ADDR64_UNASSIGNED, remote, cmd, cmd_param, param_len, false);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd, uint32_t cmd_param)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(remote64, remote16, cmd, (uint8_t *)&cmd_param, 4);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd,
+                           const uint8_t * cmd_param, uint16_t param_len)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(remote64, remote16, cmd, cmd_param, param_len, false);
+}
+
+#define FRAME_ID_LEN              1
+#define ADDR64_LEN                8
+#define ADDR16_LEN                2
+#define OPTIONS_LEN               1
+#define AT_CMD_LEN                2
+#define REM_AT_CMD_OVERHEAD       (FRAME_ID_LEN + ADDR64_LEN + \
+                                   ADDR16_LEN + OPTIONS_LEN + \
+                                   AT_CMD_LEN)
+
+void AtCmdFrame::build_at_cmd_remote_frame(uint64_t remote64, uint16_t remote16,
+                const char *const cmd, const uint8_t *const cmd_params, uint8_t params_len, bool reverse)
+{
+    uint8_t frame_data[REM_AT_CMD_OVERHEAD + params_len];
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     *  the options byte, the command and the command params */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&remote64, sizeof remote64);
+    frame_data[9] = (uint8_t)(remote16 >> 8);
+    frame_data[10] = (uint8_t)remote16;
+    frame_data[11] = 0x02; /* TODO Options */
+    frame_data[12] = cmd[0];
+    frame_data[13] = cmd[1];
+
+    if (params_len) {
+        if (reverse) {
+            rmemcpy(&frame_data[14], cmd_params, params_len);
+        } else {
+            memcpy(&frame_data[14], cmd_params, params_len);
+        }
+    }
+
+    set_api_frame(RemoteCmdReq, frame_data, REM_AT_CMD_OVERHEAD + params_len);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/AtCmdFrame.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/AtCmdFrame.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,168 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__AT_CMD_FRAME_H_)
+#define __AT_CMD_FRAME_H_
+
+#include "ApiFrame.h"
+
+#define REM_AT_CMD_RESP_FRM_ID_OFFSET   0
+#define REM_AT_CMD_RESP_STATUS_OFFSET   13
+#define REM_AT_CMD_RESP_CMD_DATA_OFFSET 14
+#define REM_AT_CMD_RESP_OVERHEAD        14 /* ID + ADDR64 + ADDR16 + CMD + status */
+
+#define ATCMD_RESP_FRAME_ID_OFFSET      0
+#define ATCMD_RESP_CMD_LOW_OFFSET       1
+#define ATCMD_RESP_CMD_HIGH_OFFSET      2
+#define ATCMD_RESP_STATUS_OFFSET        3
+#define ATCMD_RESP_DATA_OFFSET          4
+#define ATCMD_RESP_NW_ADDR_H_OFFSET     4
+#define ATCMD_RESP_NW_ADDR_L_OFFSET     5
+#define ATCMD_RESP_SH_ADDR_L_OFFSET     6
+#define ATCMD_RESP_SH_ADDR_H_OFFSET     10
+#define ATCMD_RESP_NI_OFFSET            14
+
+#define ATCMD_RESP_OVERHEAD             4 /* ID + CMD + status */
+
+#define ATCMD_802_RESP_SIGN_STR_OFFSET  14
+#define ATCMD_802_RESP_NI_OFFSET        15
+
+#define MAX_NI_PARAM_LEN                20
+
+/** Class for the AT command api frames. Derived from ApiFrame */
+class AtCmdFrame : public ApiFrame
+{
+    public:
+
+        /**
+         * AtCmdResp
+         */
+        enum AtCmdResp {
+            AtCmdRespOk             = 0,     /**< Ok */
+            AtCmdRespError          = 1,     /**< Error */
+            AtCmdRespInvalidCmd     = 2,     /**< Invalid Command */
+            AtCmdRespInvalidParam   = 3,     /**< Invalid Parameter */
+            AtCmdRespTxFailure      = 4,     /**< Tx Failure */
+            AtCmdRespLenMismatch    = 0xfd,  /**< Length Mismatch (Error generated by the library) */
+            AtCmdRespInvalidAddr    = 0xfe,  /**< Invalid Address (Error generated by the library) */
+            AtCmdRespTimeout        = 0xff,   /**< Timeout (Error generated by the library) */
+        };
+
+        /**
+         * ModemStatus
+         */
+        enum ModemStatus {
+            HwReset         = 0,     /**< Hardware reset */
+            WdReset         = 1,     /**< Watchdog timer reset */
+            JoinedNW        = 2,     /**< Joined network (routers and end devices) */
+            Disassociated   = 3,     /**< Disassociated */
+            SyncLost        = 4,     /**< Synchronization Lost */
+            CoordRealign    = 5,     /**< Coordinator realignment */
+            CoordStarted    = 6,     /**< Coordinator started */
+            NwSecKeyUpdated = 7,     /**< Network security key was updated */
+            NwWokeUp        = 0x0B,  /**< NwWokeUp */
+            NwToSleep       = 0x0C,  /**< NwToSleep */
+            VccExceeded     = 0x0D,  /**< VccExceeded: PRO S2B only? */
+            ModConfChangeJoinInProg = 0x11, /**< Modem configuration changed while join in progress */
+        };
+
+        /** Class constructor
+         *
+         * @param cmd at command of the frame
+         * @param cmd_param command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(const char * const cmd, const uint32_t cmd_param);
+
+        /** Class constructor
+         *
+         * @param cmd at command of the frame
+         * @param cmd_param pointer to command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+        /** Class constructor
+         *
+         * @param remote 64 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param command parameter
+         */
+        AtCmdFrame(uint64_t remote, const char * const cmd, uint32_t cmd_param);
+
+        /** Class constructor
+         *
+         * @param remote 64 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param pointer to command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(uint64_t remote, const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+        /** Class constructor
+         *
+         * @param remote 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param command parameter
+         */
+        AtCmdFrame(uint16_t remote, const char * const cmd, uint32_t cmd_param);
+
+        /** Class constructor
+         *
+         * @param remote 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param pointer to command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(uint16_t remote, const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+        /** Class constructor
+         *
+         * @param remote 64 bit address of the remote device where we want to run the command
+         * @param remote 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param command parameter
+         */
+        AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd, uint32_t cmd_param);
+
+        /** Class constructor
+         *
+         * @param remote 64 bit address of the remote device where we want to run the command
+         * @param remote 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param pointer to command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+    protected:
+        /** build_at_cmd_frame method used by the constructors to create the at command frame
+         *
+         * @param cmd at command of the frame
+         * @param cmd_params pointer to command parameter
+         * @param param_len length of the command param
+         */
+        void build_at_cmd_frame(const char *cmd, const uint8_t *cmd_params, uint8_t payload_len, bool reverse = true);
+
+        /** build_at_cmd_remote_frame method used by the constructors to create the at command frame
+         *
+         * @param remote64 64 bit address of the remote device where we want to run the command
+         * @param remote16 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_params pointer to command parameter
+         * @param param_len length of the command param
+         */
+        void build_at_cmd_remote_frame(uint64_t remote64, uint16_t remote16,
+                const char *const cmd, const uint8_t *const cmd_params, uint8_t payload_len, bool reverse = true);
+};
+
+#endif /* __AT_CMD_FRAME_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "DigiMeshFrames.h"
+
+#define FRAME_ID_LEN              1
+#define ADDR64_LEN                8
+#define ADDR16_LEN                2
+#define BROADCAST_RADIOUS_LEN     1
+#define OPTIONS_LEN               1
+#define TX_REQUEST_OVERHEAD       (FRAME_ID_LEN + ADDR64_LEN + \
+                                   ADDR16_LEN + BROADCAST_RADIOUS_LEN + \
+                                   OPTIONS_LEN)
+#define SOURCE_EP_LEN             1
+#define DEST_EP_LEN               1
+#define CLUSTER_ID_LEN            2
+#define PROFILE_ID_LEN            2
+
+#define EXP_ADDR_OVERHEAD         (TX_REQUEST_OVERHEAD + SOURCE_EP_LEN + \
+                                   DEST_EP_LEN + CLUSTER_ID_LEN + \
+                                   PROFILE_ID_LEN)
+
+/** Class constructor */
+TxFrameDM::TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad, uint8_t tx_opt,
+                const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[TX_REQUEST_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = broadcast_rad;
+    frame_data[12] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[13], data, len);
+    }
+
+    set_api_frame(TxReqZBDM, frame_data, TX_REQUEST_OVERHEAD + len);
+}
+
+/** Class constructor */
+TxFrameDM::TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[EXP_ADDR_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the end point source and destination addresses, the cluster and profile IDs,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = source_ep;
+    frame_data[12] = dest_ep;
+    frame_data[13] = (uint8_t)(cluster_id >> 8);
+    frame_data[14] = (uint8_t)cluster_id;
+    frame_data[15] = (uint8_t)(profile_id >> 8);
+    frame_data[16] = (uint8_t)profile_id;
+    frame_data[17] = broadcast_rad;
+    frame_data[18] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[19], data, len);
+    }
+
+    set_api_frame(ExpAddrCmd, frame_data, EXP_ADDR_OVERHEAD + len);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DIGIMESH_FRAME_H_)
+#define __DIGIMESH_FRAME_H_
+
+#include "ApiFrame.h"
+
+class TxFrameDM : public ApiFrame
+{
+    public:
+        /** Class constructor */
+        TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad,
+                    uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+
+        /** Class constructor */
+        TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+};
+
+#endif /* __DIGIMESH_FRAME_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "ZigbeeFrames.h"
+
+#define FRAME_ID_LEN              1
+#define ADDR64_LEN                8
+#define ADDR16_LEN                2
+#define BROADCAST_RADIOUS_LEN     1
+#define OPTIONS_LEN               1
+#define TX_REQUEST_OVERHEAD       (FRAME_ID_LEN + ADDR64_LEN + \
+                                   ADDR16_LEN + BROADCAST_RADIOUS_LEN + \
+                                   OPTIONS_LEN)
+#define SOURCE_EP_LEN             1
+#define DEST_EP_LEN               1
+#define CLUSTER_ID_LEN            2
+#define PROFILE_ID_LEN            2
+
+#define EXP_ADDR_OVERHEAD         (TX_REQUEST_OVERHEAD + SOURCE_EP_LEN + \
+                                   DEST_EP_LEN + CLUSTER_ID_LEN + \
+                                   PROFILE_ID_LEN)
+
+/** Class constructor */
+TxFrameZB::TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad, uint8_t tx_opt,
+                const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[TX_REQUEST_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = broadcast_rad;
+    frame_data[12] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[13], data, len);
+    }
+
+    set_api_frame(TxReqZBDM, frame_data, TX_REQUEST_OVERHEAD + len);
+}
+
+/** Class constructor */
+TxFrameZB::TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[EXP_ADDR_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the end point source and destination addresses, the cluster and profile IDs,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = source_ep;
+    frame_data[12] = dest_ep;
+    frame_data[13] = (uint8_t)(cluster_id >> 8);
+    frame_data[14] = (uint8_t)cluster_id;
+    frame_data[15] = (uint8_t)(profile_id >> 8);
+    frame_data[16] = (uint8_t)profile_id;
+    frame_data[17] = broadcast_rad;
+    frame_data[18] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[19], data, len);
+    }
+
+    set_api_frame(ExpAddrCmd, frame_data, EXP_ADDR_OVERHEAD + len);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__ZIGBEE_FRAME_H_)
+#define __ZIGBEE_FRAME_H_
+
+#include "ApiFrame.h"
+
+class TxFrameZB : public ApiFrame
+{
+    public:
+        /** Class constructor */
+        TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad,
+                    uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+
+        /** Class constructor */
+        TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+};
+
+#endif /* __ZIGBEE_FRAME_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IO.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IO.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef __IO_H_
+#define __IO_H_
+
+#define DR_PWM_MAX_VAL      0x3FF
+
+namespace XBeeLib {
+
+/**
+ * @defgroup IoMode
+ * @{
+ */
+/**
+ * IoMode
+ */
+enum IoMode {
+    Disabled         = 0,  /**< Disabled */
+    SpecialFunc      = 1,  /**< Special Function */
+    Adc              = 2,  /**< Adc */
+    Pwm              = 2,  /**< Pwm */
+    DigitalInput     = 3,  /**< Digital Input */
+    DigitalOutLow    = 4,  /**< Digital Out Low */
+    DigitalOutHigh   = 5,  /**< Digital Out High */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup DioVal
+ * @{
+ */
+/**
+ * DioVal
+ */
+enum DioVal {
+    Low     = 0,      /**< Low Value */
+    High    = 1,      /**< High Value */
+};
+/**
+ * @}
+ */
+
+}   /* namespace XBeeLib */
+
+
+#endif /* __IO_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSample802.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSample802.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "IO/IOSample802.h"
+#include "Utils/Debug.h"
+
+#define IO_SAMPLE_802_DIGITAL_INPUTS_MASK   0x01FF
+#define IO_SAMPLE_802_DIGITAL_INPUTS_COUNT  9
+#define IO_SAMPLE_802_MIN_SIZE              (2 + 2)
+
+using namespace XBeeLib;
+
+IOSample802::IOSample802(const uint8_t* const raw_data, size_t size)
+{
+    if (raw_data == NULL || size == 0) {
+        _channel_mask = 0;
+        return;
+    }
+    assert(size >= IO_SAMPLE_802_MIN_SIZE);
+    assert(size <= sizeof _sampled_data);
+
+    _channel_mask = UINT16(raw_data[1], raw_data[2]);
+    _sampled_data_size = size - 3;
+    memcpy(&_sampled_data[0], &raw_data[3], _sampled_data_size);
+}
+
+IOSample802::~IOSample802()
+{
+
+}
+
+RadioStatus IOSample802::get_dio(XBee802::IoLine line, DioVal* const dio_value) const
+{
+    if (line > XBee802::DI8) {
+        digi_log(LogLevelError, "get_dio: Pin %d not supported as IO\r\n", line);
+        return Failure;
+    }
+
+    const uint16_t mask = 1 << line;
+    if (mask & _channel_mask) {
+        const uint8_t digital_channels = get_dio_channels();
+
+        *dio_value = digital_channels & mask ? High : Low;
+        return Success;
+    }
+    return Failure;
+}
+
+RadioStatus IOSample802::get_adc(XBee802::IoLine line, uint16_t* const val) const
+{
+    if (line > XBee802::DIO5_AD5) {
+        digi_log(LogLevelError, "get_adc: Pin %d not supported as ADC\r\n", line);
+        return Failure;
+    }
+    const uint8_t analog_mask = _channel_mask >> IO_SAMPLE_802_DIGITAL_INPUTS_COUNT;
+    const uint8_t line_mask = 1 << line;
+    const bool adc_present = line_mask & analog_mask;
+    if (!adc_present) {
+        return Failure;
+    }
+
+    uint8_t analog_data_idx = dio_channels_present() == 0 ? 0 : 2;
+    uint8_t line_sample = 0;
+
+    while (analog_data_idx < _sampled_data_size) {
+        if (analog_mask & (1 << line_sample)) {
+            if (line_sample == line) {
+                /* Write the analog value */
+                *val = UINT16(_sampled_data[analog_data_idx], _sampled_data[analog_data_idx + 1]);
+                break;
+            }
+            analog_data_idx += 2;
+        }
+        line_sample++;
+    }
+
+    return Success;
+}
+
+inline bool IOSample802::dio_channels_present(void) const
+{
+    return _channel_mask & IO_SAMPLE_802_DIGITAL_INPUTS_MASK;
+}
+
+inline uint8_t IOSample802::get_dio_channels(void) const
+{
+    if (dio_channels_present()) {
+        return UINT16(_sampled_data[0], _sampled_data[1]);
+    } else {
+        return 0;
+    }
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSample802.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSample802.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef _IO_IOSAMPLE802_H_
+#define _IO_IOSAMPLE802_H_
+
+#define MAX_IO_SAMPLE_802_LEN   100 //(2 + 2 * 20)
+
+namespace XBeeLib {
+
+/** Class to handle the incoming IO Data Samples in 802.15.4 modules */
+class IOSample802 {
+    public:
+        /** Class constructor
+         *  @param raw_data The IO Sample data, as returned by an "IS" command response or in the Io16Bit (0x83) or Io64Bit (0x82) frames
+         *  @param size size (in bytes) of raw_data
+         */
+        IOSample802(const uint8_t* const raw_data = NULL, size_t size = 0);
+
+        /** Class destructor */
+        ~IOSample802();
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(XBee802::IoLine line, DioVal* const dio_value) const;
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from the ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(XBee802::IoLine line, uint16_t* const val) const;
+
+        /** is_valid - checks if the IOSample802 object has at least one DIO or ADC sample.
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid()
+        {
+            return _channel_mask != 0;
+        }
+
+    protected:
+        uint16_t _channel_mask;
+        uint8_t _sampled_data[MAX_IO_SAMPLE_802_LEN];
+        uint8_t _sampled_data_size;
+
+        inline bool dio_channels_present(void) const;
+        inline uint8_t get_dio_channels(void) const;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* _IO_IOSAMPLE802_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSampleDM.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSampleDM.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "IO/IOSampleDM.h"
+
+#define IO_SAMPLE_DM_MIN_SIZE              (2 + 1 + 2)
+
+using namespace XBeeLib;
+
+IOSampleDM::IOSampleDM(const uint8_t* const raw_data, size_t size)
+{
+    if (raw_data == NULL || size == 0) {
+        _digital_mask = 0;
+        _analog_mask = 0;
+        return;
+    }
+    assert(size >= IO_SAMPLE_DM_MIN_SIZE);
+    assert(size <= sizeof _sampled_data);
+
+    _digital_mask = UINT16(raw_data[1], raw_data[2]);
+    _analog_mask = raw_data[3];
+    _sampled_data_size = size - 4;
+    memcpy(&_sampled_data[0], &raw_data[4], _sampled_data_size);
+}
+
+IOSampleDM::~IOSampleDM()
+{
+
+}
+
+RadioStatus IOSampleDM::get_dio(XBeeDM::IoLine line, DioVal* const dio_value) const
+{
+    const uint16_t mask = 1 << line;
+    if (mask & _digital_mask) {
+        const uint16_t digital_channels = get_digital_channels();
+
+        *dio_value = digital_channels & mask ? High : Low;
+        return Success;
+    }
+    return Failure;
+}
+
+RadioStatus IOSampleDM::get_adc(XBeeDM::IoLine line, uint16_t* const val) const
+{
+    const uint8_t line_mask = 1 << line;
+    const bool adc_present = line_mask & _analog_mask;
+    if (!adc_present) {
+        return Failure;
+    }
+
+    uint8_t analog_data_idx = _digital_mask == 0 ? 0 : 2;
+    uint8_t line_sample = 0;
+
+    while (analog_data_idx < _sampled_data_size) {
+        if (_analog_mask & (1 << line_sample)) {
+            if (line_sample == line) {
+                /* Write the analog value */
+                *val = UINT16(_sampled_data[analog_data_idx], _sampled_data[analog_data_idx + 1]);
+                break;
+            }
+            analog_data_idx += 2;
+        }
+        line_sample++;
+    }
+
+    return Success;
+}
+
+inline uint16_t IOSampleDM::get_digital_channels(void) const
+{
+    if (_digital_mask == 0) {
+        return 0;
+    }
+    return UINT16(_sampled_data[0], _sampled_data[1]);
+}
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSampleDM.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSampleDM.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef _IO_IOSAMPLEDM_H_
+#define _IO_IOSAMPLEDM_H_
+
+#define MAX_IO_SAMPLE_DM_LEN   (2 + 2 * 5)
+
+namespace XBeeLib {
+
+/** Class to handle the incoming IO Data Samples in ZigBee modules */
+class IOSampleDM {
+    public:
+        /** Class constructor
+         *  @param raw_data The IO Sample data, as returned by an "IS" command response or in the IoSampleRxZBDM (0x92) frames
+         *  @param size size (in bytes) of raw_data.
+         */
+        IOSampleDM(const uint8_t* const raw_data = NULL, size_t size = 0);
+
+        /** Class destructor */
+        ~IOSampleDM();
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(XBeeDM::IoLine line, DioVal* const dio_value) const;
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from the ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(XBeeDM::IoLine line, uint16_t* const val) const;
+
+        /** is_valid - checks if the IOSampleDM object has at least one DIO or ADC sample.
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid()
+        {
+            return _digital_mask != 0 || _analog_mask != 0;
+        }
+
+    protected:
+        uint16_t _digital_mask;
+        uint8_t _analog_mask;
+        uint8_t _sampled_data[MAX_IO_SAMPLE_DM_LEN];
+        uint8_t _sampled_data_size;
+
+        inline uint16_t get_digital_channels(void) const;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* _IO_IOSAMPLEDM_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSampleZB.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSampleZB.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "IO/IOSampleZB.h"
+
+#define IO_SAMPLE_ZB_MIN_SIZE              (2 + 1 + 2)
+
+using namespace XBeeLib;
+
+IOSampleZB::IOSampleZB(const uint8_t* const raw_data, size_t size)
+{
+    if (raw_data == NULL || size == 0) {
+        _digital_mask = 0;
+        _analog_mask = 0;
+        return;
+    }
+    assert(size >= IO_SAMPLE_ZB_MIN_SIZE);
+    assert(size <= sizeof _sampled_data);
+
+    _digital_mask = UINT16(raw_data[1], raw_data[2]);
+    _analog_mask = raw_data[3];
+    _sampled_data_size = size - 4;
+    memcpy(&_sampled_data[0], &raw_data[4], _sampled_data_size);
+}
+
+IOSampleZB::~IOSampleZB()
+{
+
+}
+
+RadioStatus IOSampleZB::get_dio(XBeeZB::IoLine line, DioVal* const dio_value) const
+{
+    const uint16_t mask = 1 << line;
+    if (mask & _digital_mask) {
+        const uint16_t digital_channels = get_digital_channels();
+
+        *dio_value = digital_channels & mask ? High : Low;
+        return Success;
+    }
+    return Failure;
+}
+
+RadioStatus IOSampleZB::get_adc(XBeeZB::IoLine line, uint16_t* const val) const
+{
+    const uint8_t line_mask = 1 << line;
+    const bool adc_present = line_mask & _analog_mask;
+    if (!adc_present) {
+        return Failure;
+    }
+
+    uint8_t analog_data_idx = _digital_mask == 0 ? 0 : 2;
+    uint8_t line_sample = 0;
+
+    while (analog_data_idx < _sampled_data_size) {
+        if (_analog_mask & (1 << line_sample)) {
+            if (line_sample == line) {
+                /* Write the analog value */
+                *val = UINT16(_sampled_data[analog_data_idx], _sampled_data[analog_data_idx + 1]);
+                break;
+            }
+            analog_data_idx += 2;
+        }
+        line_sample++;
+    }
+
+    return Success;
+}
+
+inline uint16_t IOSampleZB::get_digital_channels(void) const
+{
+    if (_digital_mask == 0) {
+        return 0;
+    }
+    return UINT16(_sampled_data[0], _sampled_data[1]);
+}
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSampleZB.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSampleZB.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef _IO_IOSAMPLEZB_H_
+#define _IO_IOSAMPLEZB_H_
+
+#define MAX_IO_SAMPLE_ZB_LEN   (2 + 2 * 5)
+
+namespace XBeeLib {
+
+/** Class to handle the incoming IO Data Samples in ZigBee modules */
+class IOSampleZB {
+    public:
+        /** Class constructor
+         *  @param raw_data The IO Sample data, as returned by an "IS" command response or in the IoSampleRxZBDM (0x92) frames
+         *  @param size size (in bytes) of raw_data.
+         */
+        IOSampleZB(const uint8_t* const raw_data = NULL, size_t size = 0);
+
+        /** Class destructor */
+        ~IOSampleZB();
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(XBeeZB::IoLine line, DioVal* const dio_value) const;
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from the ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(XBeeZB::IoLine line, uint16_t* const val) const;
+
+        /** is_valid - checks if the IOSampleZB object has at least one DIO or ADC sample.
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid()
+        {
+            return _digital_mask != 0 || _analog_mask != 0;
+        }
+
+    protected:
+        uint16_t _digital_mask;
+        uint8_t _analog_mask;
+        uint8_t _sampled_data[MAX_IO_SAMPLE_ZB_LEN];
+        uint8_t _sampled_data_size;
+
+        inline uint16_t get_digital_channels(void) const;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* _IO_IOSAMPLEZB_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "RemoteXBee.h"
+
+using namespace XBeeLib;
+
+RemoteXBee::RemoteXBee()
+{
+    _dev_addr64 = ADDR64_UNASSIGNED;
+    _dev_addr16 = ADDR16_UNKNOWN;
+}
+
+RemoteXBee::RemoteXBee(uint64_t remote64) : _dev_addr64(remote64)
+{
+    _dev_addr16 = ADDR16_UNKNOWN;
+}
+
+RemoteXBee::~RemoteXBee()
+{
+}
+
+uint64_t RemoteXBee::get_addr64() const
+{
+    return _dev_addr64;
+}
+
+uint16_t RemoteXBee::get_addr16() const
+{
+    return _dev_addr16;
+}
+
+RemoteXBee802::RemoteXBee802() : RemoteXBee()
+{
+}
+
+RemoteXBee802::RemoteXBee802(uint64_t remote64) : RemoteXBee(remote64)
+{
+}
+
+RemoteXBee802::RemoteXBee802(uint16_t remote16) : RemoteXBee()
+{
+    _dev_addr16 = remote16;
+}
+
+RemoteXBee802::RemoteXBee802(uint64_t remote64, uint16_t remote16) : RemoteXBee(remote64)
+{
+    _dev_addr16 = remote16;
+}
+
+RemoteXBee802::~RemoteXBee802()
+{
+}
+
+RemoteXBeeZB::RemoteXBeeZB() : RemoteXBee()
+{
+}
+
+RemoteXBeeZB::RemoteXBeeZB(uint64_t remote64) : RemoteXBee(remote64)
+{
+}
+
+RemoteXBeeZB::RemoteXBeeZB(uint64_t remote64, uint16_t remote16) : RemoteXBee(remote64)
+{
+    _dev_addr16 = remote16;
+}
+
+RemoteXBeeZB::~RemoteXBeeZB()
+{
+}
+
+RemoteXBeeDM::RemoteXBeeDM() : RemoteXBee()
+{
+}
+
+RemoteXBeeDM::RemoteXBeeDM(uint64_t remote64) : RemoteXBee(remote64)
+{
+}
+
+RemoteXBeeDM::~RemoteXBeeDM()
+{
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,182 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__XBEE_REMOTE_H_)
+#define __XBEE_REMOTE_H_
+
+#include "XBee/Addresses.h"
+
+namespace XBeeLib {
+
+/** Class for Remote XBee modules. Not to be used directly. */
+class RemoteXBee
+{
+    public:
+
+         /** Default Class constructor for a remote device (connected wirelessly). No address set.
+         */
+        RemoteXBee();
+
+        /** Class constructor for a remote device (connected wirelessly) using 64bit addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         */
+        RemoteXBee(uint64_t remote64);
+
+        /** Class destructor */
+        ~RemoteXBee();
+
+        /** get_addr64 - returns the 64bit address of the remote device
+         *
+         *  @returns the 64bit address of the remote device
+         */
+        uint64_t get_addr64() const;
+
+        /** get_addr16 - returns the 16bit address of the remote device
+         *
+         *  @returns the 16bit address of the remote device
+         */
+        uint16_t get_addr16() const;
+
+        /** operator == overload so the object can be compared to equal */
+        inline bool operator == (const RemoteXBee &b) const
+        {
+            return ((b._dev_addr16 == _dev_addr16) &&
+                    (b._dev_addr64 == _dev_addr64));
+        }
+
+        /** operator != overload so the object can be compared to not equal */
+        inline bool operator != (const RemoteXBee &b) const
+        {
+            return !(this == &b);
+        }
+
+        /** is_valid_addr16b - checks if the RemoteXBee object has a valid 16b address
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid_addr16b() const
+        {
+            return (_dev_addr16 != ADDR16_UNKNOWN);
+        }
+
+        /** is_valid_addr64b - checks if the RemoteXBee object has a valid 64b address
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid_addr64b() const
+        {
+            return !(_dev_addr64 == ADDR64_UNASSIGNED);
+        }
+
+
+    protected:
+        /** Remote Device 64 bit address */
+        uint64_t      _dev_addr64;
+
+        /** Remote Device 16 bit address */
+        uint16_t    _dev_addr16;
+};
+
+class FH_NodeDiscovery802;
+/** Class for 802.15.4 Remote XBee modules */
+class RemoteXBee802 : public RemoteXBee
+{
+    public:
+
+         /** Default Class constructor for a 802.15.4 remote device (connected wirelessly). No address set.
+         */
+        RemoteXBee802();
+
+        /** Class constructor for a 802.15.4 remote device (connected wirelessly) using 64bit addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         */
+        RemoteXBee802(uint64_t remote64);
+
+        /** Class constructor for a 802.15.4 remote device (connected wirelessly) using 16bit addressing
+         * @param remote16 the 16-bit address (ATMY parameter) of the remote XBee module
+         */
+        RemoteXBee802(uint16_t remote16);
+
+        /** Class destructor */
+        ~RemoteXBee802();
+
+        inline bool is_valid(void)
+        {
+            return is_valid_addr64b() || is_valid_addr16b();
+        }
+
+    protected:
+
+        friend FH_NodeDiscovery802;
+        friend class XBee802;
+
+        /** Class constructor for a 802.15.4 remote device (connected wirelessly) for which both the 64-bit and 16-bit addresses are known.
+         * This constructor is only used by FH_NodeDiscovery802 class.
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         * @param remote16 the 16-bit address (ATMY parameter) of the remote XBee module
+         */
+        RemoteXBee802(uint64_t remote64, uint16_t remote16);
+};
+
+/** Class for ZigBee Remote XBee modules */
+class RemoteXBeeZB : public RemoteXBee
+{
+    public:
+
+         /** Default Class constructor for a ZigBee remote device (connected wirelessly). No address set.
+         */
+        RemoteXBeeZB();
+
+       /** Class constructor for a ZigBee remote device (connected wirelessly) using 64bit addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         */
+        RemoteXBeeZB(uint64_t remote64);
+
+        /** Class constructor for a ZigBee remote device (connected wirelessly) using 64bit and 16b addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         * @param remote16 the 16-bit address (ATMY parameter) of the remote XBee module
+         */
+        RemoteXBeeZB(uint64_t remote64, uint16_t remote16);
+
+        /** Class destructor */
+        ~RemoteXBeeZB();
+
+        inline bool is_valid(void)
+        {
+            return is_valid_addr64b();
+        }
+};
+
+/** Class for DigiMesh Remote XBee modules */
+class RemoteXBeeDM : public RemoteXBee
+{
+    public:
+
+         /** Default Class constructor for a DigiMesh remote device (connected wirelessly). No address set.
+         */
+        RemoteXBeeDM();
+
+       /** Class constructor for a DigiMesh remote device (connected wirelessly) using 64bit addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         */
+        RemoteXBeeDM(uint64_t remote64);
+
+        /** Class destructor */
+        ~RemoteXBeeDM();
+
+        inline bool is_valid(void)
+        {
+            return is_valid_addr64b();
+        }
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* defined(__XBEE_REMOTE_H_) */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Utils/Debug.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Utils/Debug.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DEBUG_H_)
+#define __DEBUG_H_
+
+#include "config.h"
+
+#if defined(ENABLE_LOGGING)
+
+#include "DigiLogger.h"
+
+#define digi_log(...)  DigiLog::DigiLogger::log_format(__VA_ARGS__);
+#else
+#define digi_log(...)  do {} while(0)
+#endif
+
+#if defined(ENABLE_ASSERTIONS)
+#include "mbed.h"
+#if !(defined assert)
+#define assert(expr)            if (!(expr)) {                                      \
+                                    digi_log(LogLevelNone, "Assertion failed: %s, file %s, line %d\n", \
+                                         #expr, __FILE__, __LINE__);                \
+                                    mbed_die();                                     \
+                                }
+#endif
+#else
+#define assert(expr)
+#endif
+
+#endif /* __DEBUG_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Utils/Utils.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Utils/Utils.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "Utils.h"
+#include <string.h>
+
+void rmemcpy(uint8_t * const dest, const uint8_t * const src, uint16_t bytes)
+{
+    uint8_t *destp = dest + bytes - 1;
+    uint8_t *srcp = (uint8_t *)src;
+
+    while (destp >= dest)
+        *destp-- = *srcp++;
+}
+
+uint64_t addr64_from_uint8_t(const uint8_t * const data, bool big_endian = true)
+{
+    int64_t addr64;
+    if (big_endian) {
+        rmemcpy((uint8_t *)&addr64, data, 8);
+    } else {
+        memcpy((uint8_t *)&addr64, data, 8);
+    }
+    return addr64;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Utils/Utils.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Utils/Utils.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__XB_UTILS_H_)
+#define __XB_UTILS_H_
+
+#include <stdint.h>
+
+/** Buils an uint16_t out of 2 single bytes */
+#define UINT16(msb,lsb)     (uint16_t)(((msb) << 8) | (lsb))
+/** Buils an uint64_t out of 2 uint32_t */
+#define UINT64(msb,lsb)     (uint64_t)(((uint64_t)(msb) << 32) | (lsb))
+
+#define UINT64_HI32(u64)     (uint32_t)((u64) >> 32)
+#define UINT64_LO32(u64)     (uint32_t)((u64) & 0xFFFFFFFF)
+
+#define UNUSED_PARAMETER(a)  ((void)(a))
+
+/** rmemcpy - like memcpy but copies the bytes in reverse order
+ *
+ *  @param dest pointer with the destination address
+ *  @param src pointer with the source address
+ *  @param bytes number of bytes that will be copied
+ */
+void rmemcpy(uint8_t * const dest, const uint8_t * const src, uint16_t bytes);
+
+#endif /* __XB_UTILS_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/Addresses.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/Addresses.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef __ADDRESSES_H_
+#define __ADDRESSES_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#include "Utils/Utils.h"
+
+/* Some commonly used addresses */
+#define ADDR64_BROADCAST         ((uint64_t)0x000000000000FFFF)
+#define ADDR64_COORDINATOR       ((uint64_t)0x0000000000000000)
+#define ADDR64_UNASSIGNED        ((uint64_t)0xFFFFFFFFFFFFFFFF)
+
+#define ADDR16_UNKNOWN           ((uint16_t)0xFFFE)
+#define ADDR16_BROADCAST         ((uint16_t)0xFFFF)
+
+/** Macro used to create a 16bit data type from 2 bytes */
+#define ADDR16(msb,lsb)             UINT16(msb,lsb)
+
+uint64_t addr64_from_uint8_t(const uint8_t * const data, bool big_endian = true);
+
+#endif /* __ADDRESSES_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/AtCommands.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/AtCommands.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,144 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+
+#define GET_CMD_RESP(fr, radio_location)    (radio_location == RadioRemote ? fr->get_data_at(REM_AT_CMD_RESP_STATUS_OFFSET) \
+                                                                   : fr->get_data_at(ATCMD_RESP_STATUS_OFFSET))
+
+#define GET_DATA_LEN(fr, radio_location)    (radio_location == RadioRemote ? (fr->get_data_len() - REM_AT_CMD_RESP_OVERHEAD) \
+                                                                   : (fr->get_data_len() - ATCMD_RESP_OVERHEAD))
+
+#define GET_DATA_OFF(radio_location)        (radio_location == RadioRemote ? REM_AT_CMD_RESP_CMD_DATA_OFFSET \
+                                                                   : ATCMD_RESP_DATA_OFFSET)
+
+using namespace XBeeLib;
+
+/** Method that sends an AT command to the module and waits for the command response.
+ *  @returns the AT command response */
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame,
+     uint8_t *const buf, uint16_t *const len, RadioLocation radio_location, bool reverse)
+{
+    AtCmdFrame::AtCmdResp resp = AtCmdFrame::AtCmdRespTimeout;
+    ApiFrame *resp_frame;
+    ApiFrame::ApiFrameType expected_type =
+            (frame->get_frame_type() == ApiFrame::AtCmd) ?
+            ApiFrame::AtCmdResp : ApiFrame::RemoteCmdResp;
+
+    send_api_frame(frame);
+
+    /* Wait for the AT command response packet */
+    resp_frame = get_this_api_frame(frame->get_frame_id(), expected_type);
+    if (resp_frame == NULL) {
+        return resp;
+    }
+
+    resp = (AtCmdFrame::AtCmdResp)GET_CMD_RESP(resp_frame, radio_location);
+    if (resp == AtCmdFrame::AtCmdRespOk) {
+        if (buf != NULL && len != NULL) {
+
+            /* Copy the command response data */
+            uint16_t new_len = GET_DATA_LEN(resp_frame, radio_location);
+
+            *len = (*len < new_len) ? *len : new_len;
+
+            /* rmemcpy makes the endian change */
+            if (reverse) {
+                rmemcpy(buf, resp_frame->get_data() + GET_DATA_OFF(radio_location), *len);
+            } else {
+                memcpy(buf, resp_frame->get_data() + GET_DATA_OFF(radio_location), *len);
+            }
+        }
+    } else {
+        digi_log(LogLevelWarning, "send_at_cmd bad response: 0x%x\r\n", resp);
+    }
+
+    /* Once processed, remove the frame from the buffer */
+    _framebuf_syncr.free_frame(resp_frame);
+    return resp;
+}
+
+/** Method that sends an AT command to the module and waits for the command response.
+ *  @returns the AT command response */
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame)
+{
+    return send_at_cmd(frame, NULL, NULL);
+}
+
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame, uint8_t *data)
+{
+    uint16_t len = sizeof *data;
+    AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(frame, data, &len);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len != sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame, uint16_t *data)
+{
+    uint16_t len = sizeof *data;
+    AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(frame, (uint8_t *)data, &len);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len != sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame, uint32_t *data)
+{
+    uint16_t len = sizeof *data;
+    AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(frame, (uint8_t *)data, &len);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len != sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::get_param(const char * const param, uint32_t * const data)
+{
+    uint16_t len = sizeof *data;
+    AtCmdFrame cmd_frame = AtCmdFrame(param);
+
+    *data = 0; /* Set to zero, send_at_cmd() only writes the necessary bytes, so if only 1 is written all the remaining 3 should be 0. */
+    AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::set_param(const char * const param, uint32_t data)
+{
+    AtCmdFrame cmd_frame = AtCmdFrame(param, data);
+    return send_at_cmd(&cmd_frame, NULL, NULL);
+}
+
+AtCmdFrame::AtCmdResp XBee::set_param(const char * const param, const uint8_t * data, uint16_t len)
+{
+    AtCmdFrame cmd_frame = AtCmdFrame(param, data, len);
+    return send_at_cmd(&cmd_frame, NULL, NULL);
+}
+
+AtCmdFrame::AtCmdResp XBee::get_param(const char * const param, uint8_t * const data, uint16_t * const len)
+{
+    AtCmdFrame cmd_frame = AtCmdFrame(param);
+    return send_at_cmd(&cmd_frame, data, len, RadioLocal, false);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/RadioConfig.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/RadioConfig.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,366 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "Frames/ApiFrame.h"
+
+using namespace XBeeLib;
+
+RadioStatus XBee::write_config(void)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("WR");
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee::set_power_level(uint8_t  level)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    if (level > 4) {
+        return Failure;
+    }
+
+    cmdresp = set_param("PL", level);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBee::get_power_level(uint8_t * const  level)
+{
+    if (level == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("PL", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *level = var32;
+    return Success;
+}
+
+RadioStatus XBee::software_reset(void)
+{
+    volatile uint16_t * const rst_cnt_p = &_wd_reset_cnt;
+    const uint16_t init_rst_cnt = *rst_cnt_p;
+
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("FR");
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "software_reset failed!\r\n");
+        return Failure;
+    }
+
+    return wait_for_module_to_reset(rst_cnt_p, init_rst_cnt);
+}
+
+RadioStatus XBee::set_node_identifier(const char * const node_id)
+{
+    if (node_id == NULL) {
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+    const size_t str_len = strlen(node_id);
+
+    if(str_len > 20 || str_len < 1) {
+        return Failure;
+    }
+
+    cmdresp = set_param("NI", (const uint8_t *)node_id, str_len);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee::get_node_identifier(char * const node_id)
+{
+    if (node_id == NULL) {
+        return Failure;
+    }
+
+    uint16_t max_ni_length = 20;
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = get_param("NI", (uint8_t *)node_id, &max_ni_length);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    node_id[max_ni_length] = '\0';
+    return Success;
+}
+
+RadioStatus XBee::enable_network_encryption(bool enable)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("EE", enable);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+RadioStatus XBee::set_network_encryption_key(const uint8_t * const key, const uint16_t length)
+{
+    if (key == NULL || length == 0 || length > 16) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("KY", key, length);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+uint16_t XBee::get_hw_version() const
+{
+    return _hw_version;
+}
+
+uint16_t XBee::get_fw_version() const
+{
+    return _fw_version;
+}
+
+void XBee::set_tx_options(uint8_t options)
+{
+    _tx_options = options;
+}
+
+uint8_t XBee::get_tx_options() const
+{
+    return _tx_options;
+}
+
+RadioStatus XBee::start_node_discovery()
+{
+    RadioStatus status;
+    uint16_t nd_timeout;
+
+    status = get_node_discovery_timeout(&nd_timeout);
+    if (status != Success) {
+	    return status;
+    }
+
+    _nd_timeout = nd_timeout;
+
+    _nd_timer.start();
+
+    AtCmdFrame cmd_frame = AtCmdFrame("ND");
+    send_api_frame(&cmd_frame);
+
+    return Success;
+}
+
+bool XBee::is_node_discovery_in_progress()
+{
+    const int nd_timer = _nd_timer.read_ms();
+
+    if (nd_timer == 0)
+        return false;
+
+    if (nd_timer > _nd_timeout) {
+        _nd_timer.stop();
+        _nd_timer.reset();
+    }
+
+    return true;
+}
+
+void XBee::_get_remote_node_by_id(const char * const node_id, uint64_t * const addr64, uint16_t * const addr16)
+{
+    *addr64 = ADDR64_UNASSIGNED;
+    *addr16 = ADDR16_UNKNOWN;
+    if (node_id == NULL) {
+        return;
+    }
+    const size_t node_id_len = strlen(node_id);
+    if (node_id_len == 0 || node_id_len > MAX_NI_PARAM_LEN) {
+        return;
+    }
+
+    const uint16_t old_timeout = _timeout_ms;
+
+    RadioStatus status;
+    uint16_t nd_timeout;
+	bool wait_for_complete_timeout;
+
+    status = get_node_discovery_timeout(&nd_timeout, &wait_for_complete_timeout);
+    if (status != Success) {
+	    return;
+    }
+	_timeout_ms = nd_timeout;
+
+    Timer nd_timer = Timer();
+
+    nd_timer.start();
+
+    AtCmdFrame atnd_frame = AtCmdFrame("ND", (const uint8_t *)node_id, strlen(node_id));
+    const uint8_t frame_id = atnd_frame.get_frame_id();
+    _node_by_ni_frame_id = frame_id;
+    send_api_frame(&atnd_frame);
+
+    ApiFrame * const resp_frame = get_this_api_frame(frame_id, ApiFrame::AtCmdResp);
+    _timeout_ms = old_timeout;
+
+    _node_by_ni_frame_id = 0;
+
+    if (resp_frame == NULL) {
+        digi_log(LogLevelWarning, "_get_remote_node_by_id: timeout when waiting for ATND response");
+        return;
+    }
+
+    if (resp_frame->get_data_len() < sizeof (uint16_t) + sizeof (uint64_t)) {
+        /* In 802.15.4 this might be the OK or Timeout message with no information */
+        digi_log(LogLevelInfo, "_get_remote_node_by_id: node not found\r\n", __FUNCTION__, node_id);
+        _framebuf_syncr.free_frame(resp_frame);
+        return;
+    }
+
+    const AtCmdFrame::AtCmdResp resp = (AtCmdFrame::AtCmdResp)resp_frame->get_data_at(ATCMD_RESP_STATUS_OFFSET);
+    if (resp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelWarning, "_get_remote_node_by_id: send_at_cmd bad response: 0x%x\r\n", resp);
+        _framebuf_syncr.free_frame(resp_frame);
+        return;
+    }
+
+    rmemcpy((uint8_t *)addr16, resp_frame->get_data() + ATCMD_RESP_DATA_OFFSET, sizeof *addr16);
+    rmemcpy((uint8_t *)addr64, resp_frame->get_data() + ATCMD_RESP_DATA_OFFSET + sizeof *addr16, sizeof *addr64);
+    _framebuf_syncr.free_frame(resp_frame);
+
+    if (wait_for_complete_timeout) {
+        while (nd_timer.read_ms() < nd_timeout) {
+            wait_ms(10);
+        }
+    }
+
+    return;
+}
+
+RadioStatus XBee::config_node_discovery(uint16_t backoff_ms, uint8_t options)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("NT", (uint8_t)(backoff_ms / 100));
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    cmdresp = set_param("NO", (uint8_t)options);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    cmdresp = set_param("AC");
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBee::get_config_node_discovery(uint16_t * const backoff_ms, uint8_t * const options)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+
+    cmdresp = get_param("NT", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *backoff_ms = var32;
+
+    cmdresp = get_param("NO", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *options = var32;
+    return Success;
+}
+
+RadioStatus XBee::_get_iosample(const RemoteXBee& remote, uint8_t * const io_sample, uint16_t * const len)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    /* Force a sample read */
+    cmdresp = get_param(remote, "IS", io_sample, len);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "_get_iosample error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBee::config_io_sample_destination(const RemoteXBee& remote, const RemoteXBee& destination)
+{
+    uint32_t dh;
+    uint32_t dl;
+
+    if (destination.is_valid_addr64b()) {
+        const uint64_t dest64 = destination.get_addr64();
+        dh = (uint32_t)((dest64 >> 32) & 0xFFFFFFFF);
+        dl = (uint32_t)((dest64 & 0xFFFFFFFF));
+    } else if (destination.is_valid_addr16b()) {
+        const uint16_t destAddr16 = destination.get_addr16();
+        dh = 0;
+        dl = destAddr16;
+    } else {
+        digi_log(LogLevelError, "send_io_sample_to: Invalid destination");
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param(remote, "DH", dh);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "send_io_sample_to error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    cmdresp = set_param(remote, "DL", dl);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "send_io_sample_to error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBee::set_io_sample_rate(const RemoteXBee& remote, const float seconds)
+{
+    const float max_seconds = 65.535;
+
+    if (seconds > max_seconds) {
+        digi_log(LogLevelError, "XBee::set_io_sample_rate error seconds rate exceeds maximum %d:\r\n", max_seconds);
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+    const uint16_t milliseconds = seconds * 1000;
+
+    cmdresp = set_param(remote, "IR", milliseconds);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "XBee::set_io_sample_rate error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/XBee.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/XBee.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,880 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "FrameHandlers/FH_ModemStatus.h"
+
+/* States for the state machine that processes incoming data on the serial port */
+#define WAITING_FOR_START_FRAME (0)
+#define WAITING_FOR_LENGTH_MSB  (1)
+#define WAITING_FOR_LENGTH_LSB  (2)
+#define WAITING_FOR_PAYLOAD     (3)
+#define WAITING_FOR_CHECKSUM    (4)
+
+#define IS_API2()               (_mode == ModeAPI2)
+#define IS_API_MODE()           (_mode == ModeAPI1 || _mode == ModeAPI2)
+
+using namespace XBeeLib;
+
+#if defined(FRAME_BUFFER_SIZE_SYNCR)
+#if FRAME_BUFFER_SIZE_SYNCR < 2
+#error "FRAME_BUFFER_SIZE_SYNCR must be at least 2"
+#endif
+#else
+#define FRAME_BUFFER_SIZE_SYNCR     1
+#endif
+
+#define MAX_FRAME_PAYLOAD_LEN_SYNCR (1  /* type */         + 1  /* id */       + 2 /* at cmd*/    + 1 /* status */    + 2 /* MY sender */ + \
+                                     8  /* 64b sender */   + 20 /* max id */   + 1 /* null ter */ + 2 /* MY parent */ + 1  /* dev type */ + \
+                                     1  /* source event */ + 2  /* prof. id */ + 2 /* man. id */)
+
+FrameBuffer XBee::_framebuf_app(FRAME_BUFFER_SIZE, MAX_FRAME_PAYLOAD_LEN);
+FrameBuffer XBee::_framebuf_syncr(FRAME_BUFFER_SIZE_SYNCR, MAX_FRAME_PAYLOAD_LEN_SYNCR);
+
+#if defined(DEVICE_SERIAL_FC)
+bool XBee::check_radio_flow_control()
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t value;
+
+    if (_serial_flow_type == SerialBase::RTSCTS || _serial_flow_type == SerialBase::CTS) {
+        cmdresp = get_param("D7", &value);
+        if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+            digi_log(LogLevelError, "Could not read CTS configuration. Error %d\r\n", cmdresp);
+            return false;
+        } else if (value != 1) {
+            digi_log(LogLevelError, "Bad CTS configuration. Radio 'D7' param is %d and should be 1\r\n", value);
+            return false;
+        }
+    }
+
+    if (_serial_flow_type == SerialBase::RTSCTS || _serial_flow_type == SerialBase::RTS) {
+        cmdresp = get_param("D6", &value);
+        if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+            digi_log(LogLevelError, "Could not read RTS configuration. Error %d\r\n", cmdresp);
+            return false;
+        } else if (value != 1) {
+            digi_log(LogLevelError, "Bad RTS configuration. Radio 'D6' param is %d and should be 1\r\n", value);
+            return false;
+        }
+    }
+
+    return true;
+}
+#endif
+
+/* Class constructor */
+XBee::XBee(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
+    _mode(ModeUnknown), _hw_version(0), _fw_version(0), _timeout_ms(SYNC_OPS_TIMEOUT_MS), _dev_addr64(ADDR64_UNASSIGNED),
+    _reset(NULL), _tx_options(0), _hw_reset_cnt(0), _wd_reset_cnt(0), _modem_status_handler(NULL), _modem_status(AtCmdFrame::HwReset), _initializing(true), _node_by_ni_frame_id(0)
+{
+
+    if (reset != NC) {
+        _reset = new DigitalOut(reset, 1);
+    }
+
+    _uart = new RawSerial(tx, rx);
+    _uart->baud(baud);
+
+    _serial_flow_type = SerialBase::Disabled;
+#if defined(DEVICE_SERIAL_FC)
+    if (rts != NC && cts != NC) {
+        _serial_flow_type = SerialBase::RTSCTS;
+        _uart->set_flow_control(_serial_flow_type, rts, cts);
+    } else if (rts != NC && cts == NC) {
+        _serial_flow_type = SerialBase::RTS;
+        _uart->set_flow_control(_serial_flow_type, rts);
+    } else if (rts == NC && cts != NC) {
+        _serial_flow_type = SerialBase::CTS;
+        _uart->set_flow_control(_serial_flow_type, cts);
+    }
+#endif
+    /* Enable the reception of bytes on the serial interface by providing a cb */
+    _uart->attach(this, &XBee::uart_read_cb, Serial::RxIrq);
+
+    for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
+        _fhandlers[i] = NULL;
+    }
+}
+
+/* Class destructor */
+XBee::~XBee()
+{
+    unregister_modem_status_cb();
+
+    if (_uart != NULL) {
+        delete _uart;
+    }
+    if (_reset != NULL) {
+        delete _reset;
+    }
+}
+
+#include <inttypes.h>
+
+RadioStatus XBee::init(void)
+{
+    AtCmdFrame::AtCmdResp cmd_resp;
+    uint32_t var32;
+
+    _initializing = true;
+
+    const unsigned int max_reset_retries = 3;
+    RadioStatus reset_status;
+    for (unsigned int i = 0; i < max_reset_retries; i++) {
+        reset_status = device_reset();
+        if (reset_status == Success) {
+            break;
+        }
+    }
+    if (reset_status != Success) {
+        return reset_status;
+    }
+
+    /* Check if radio is in API1 or API2 _mode */
+    cmd_resp = get_param("AP", &var32);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    _mode = (RadioMode)var32;
+
+    /* Read the device unique 64b address */
+    uint32_t serialn_high, serialn_low;
+    cmd_resp = get_param("SH", &serialn_high);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    cmd_resp = get_param("SL", &serialn_low);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    _dev_addr64 = ((uint64_t)serialn_high << 32) | serialn_low;
+
+    /* Read some important parameters */
+    cmd_resp = get_param("HV", &var32);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    _hw_version = var32;
+
+    cmd_resp = get_param("VR", &var32);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    _fw_version = var32;
+
+    digi_log(LogLevelInfo, "mode:   %02x\r\n", (uint8_t)_mode);
+    digi_log(LogLevelInfo, "HV:     %04x\r\n", _hw_version);
+    digi_log(LogLevelInfo, "VR:     %04x\r\n", _fw_version);
+    digi_log(LogLevelInfo, "ADDR64: %08x:%08x\r\n", UINT64_HI32(_dev_addr64), UINT64_LO32(_dev_addr64));
+
+#if defined(DEVICE_SERIAL_FC)
+    bool valid_radio_fc = check_radio_flow_control();
+    assert(valid_radio_fc == true);
+#endif
+
+    _initializing = false;
+    if (_modem_status_handler != NULL) {
+        const ApiFrame frame = ApiFrame(ApiFrame::AtModemStatus, (uint8_t *)&_modem_status, sizeof(_modem_status));
+        _modem_status_handler->process_frame_data(&frame);
+    }
+
+    return Success;
+}
+
+uint64_t XBee::get_addr64() const
+{
+    return _dev_addr64;
+}
+
+RadioStatus XBee::hardware_reset()
+{
+    if (_reset != NULL) {
+        volatile uint16_t * const rst_cnt_p = &_hw_reset_cnt;
+        const uint16_t init_rst_cnt = *rst_cnt_p;
+        *_reset = 0;
+        wait_ms(10);
+        *_reset = 1;
+        return wait_for_module_to_reset(rst_cnt_p, init_rst_cnt);
+    }
+
+    return Failure;
+}
+
+RadioStatus XBee::device_reset()
+{
+    if (hardware_reset() == Success) {
+        return Success;
+    }
+
+    return software_reset();
+}
+
+RadioStatus XBee::wait_for_module_to_reset(volatile uint16_t *rst_cnt_p, uint16_t init_rst_cnt)
+{
+    Timer timer = Timer();
+    timer.start();
+
+    while (*rst_cnt_p == init_rst_cnt && timer.read_ms() < RESET_TIMEOUT_MS) {
+        wait_ms(100);
+    }
+
+    if (*rst_cnt_p == init_rst_cnt) {
+        digi_log(LogLevelWarning, "Reset Timeout\r\n");
+        return Failure;
+    }
+    return Success;
+}
+
+/** Callback function called when data is received on the serial port */
+void XBee::uart_read_cb(void)
+{
+    static uint8_t rxstate = WAITING_FOR_START_FRAME;
+    static uint16_t framelen = 0;
+    static uint16_t bytes_read;
+    static uint8_t chksum;
+    static ApiFrame *frame = NULL;
+    static bool last_byte_escaped = false;
+    static FrameBuffer * framebuf = NULL;
+
+    while (_uart->readable()) {
+        uint8_t data = _uart->getc();
+
+        if (IS_API2() && rxstate != WAITING_FOR_START_FRAME) {
+            if (last_byte_escaped) {
+                data = data ^ DR_ESCAPE_XOR_BYTE;
+                last_byte_escaped = false;
+            } else if (data == DR_ESCAPE_BYTE) {
+                last_byte_escaped = true;
+                continue;
+            }
+        }
+
+        switch (rxstate) {
+            case WAITING_FOR_START_FRAME:
+                if (data == DR_START_OF_FRAME) {
+                    rxstate = WAITING_FOR_LENGTH_MSB;
+                }
+                break;
+
+            case WAITING_FOR_LENGTH_MSB:
+                framelen = data << 8;
+                rxstate = WAITING_FOR_LENGTH_LSB;
+                break;
+
+            case WAITING_FOR_LENGTH_LSB:
+                framelen |= data;
+                rxstate = WAITING_FOR_PAYLOAD;
+                bytes_read = 0;
+                chksum = 0;
+                /* Sanity check that the frame is smaller than... */
+                if (framelen > MAX_FRAME_PAYLOAD_LEN) {
+                    digi_log(LogLevelDebug, "framelen=%d too long\r\n", framelen);
+                    digi_log(LogLevelWarning, "Frame dropped, frame too long. Increase MAX_FRAME_PAYLOAD_LEN define\r\n");
+                    rxstate = WAITING_FOR_START_FRAME;
+                }
+                break;
+
+            case WAITING_FOR_PAYLOAD:
+                #define CACHED_SIZE 3
+                static uint8_t frame_cached[CACHED_SIZE];
+
+                if (framelen <= CACHED_SIZE) {
+                    if (!bytes_read) {
+                        const ApiFrame::ApiFrameType frame_type = (ApiFrame::ApiFrameType)data;
+                        switch (frame_type)
+                        {
+                            case ApiFrame::AtCmdResp:
+                            case ApiFrame::RemoteCmdResp:
+                            case ApiFrame::TxStatusZBDM:
+                            case ApiFrame::TxStatus:
+                                framebuf = &_framebuf_syncr;
+                                break;
+
+                            case ApiFrame::RxPacket64Bit:
+                            case ApiFrame::RxPacket16Bit:
+                            case ApiFrame::Io64Bit:
+                            case ApiFrame::Io16Bit:
+                            case ApiFrame::AtModemStatus:
+                            case ApiFrame::RxPacketAO0:
+                            case ApiFrame::IoSampleRxZBDM:
+                                framebuf = &_framebuf_app;
+                                break;
+
+                            case ApiFrame::RxPacketAO1:
+                            case ApiFrame::SensorRxIndAO0:
+                            case ApiFrame::NodeIdentIndAO0:
+                            case ApiFrame::OtaFwUpStatus:
+                            case ApiFrame::RouteRecInd:
+                            case ApiFrame::Many2OneRRInd:
+                            case ApiFrame::TxReq64Bit:
+                            case ApiFrame::TxReq16Bit:
+                            case ApiFrame::AtCmd:
+                            case ApiFrame::AtCmdQueuePV:
+                            case ApiFrame::TxReqZBDM:
+                            case ApiFrame::ExpAddrCmd:
+                            case ApiFrame::RemoteCmdReq:
+                            case ApiFrame::CreateSrcRoute:
+                            case ApiFrame::Invalid:
+                            case ApiFrame::RouteInfo:
+                            case ApiFrame::AggregateAddr:
+                                framebuf = NULL;
+                                break;
+                        }
+
+                        if (framebuf == NULL) {
+                            digi_log(LogLevelWarning, "Discarding not supported frame type %02x\r\n", frame_type);
+                            rxstate = WAITING_FOR_START_FRAME;
+                        } else {
+                            frame = framebuf->get_next_free_frame();
+                            if (frame == NULL) {
+                                /* It's not possible to achive this condition as we discard older frames and only one frame can be used by syncr. commands */
+                                assert(frame != NULL);
+                                rxstate = WAITING_FOR_START_FRAME;
+                            } else {
+                                frame->set_data_len(framelen - 1);
+                            }
+
+                            frame->set_frame_type(frame_type);
+                        }
+                    } else {
+                        frame->set_data(data, bytes_read - 1);
+                    }
+                    chksum += data;
+                    bytes_read++;
+                    if (bytes_read == framelen) {
+                        rxstate = WAITING_FOR_CHECKSUM;
+                    }
+                    break;
+                }
+
+
+                if (bytes_read < CACHED_SIZE) {
+                    frame_cached[bytes_read] = data;
+                }
+                else if (bytes_read == CACHED_SIZE) {
+                    const ApiFrame::ApiFrameType frame_type = (ApiFrame::ApiFrameType)frame_cached[0];
+                    switch (frame_type)
+                    {
+                        case ApiFrame::RemoteCmdResp:
+                        case ApiFrame::TxStatusZBDM:
+                        case ApiFrame::TxStatus:
+                            framebuf = &_framebuf_syncr;
+                            break;
+
+                        case ApiFrame::AtCmdResp:
+                            if ((frame_cached[1] != _node_by_ni_frame_id ) && (frame_cached[2] == 'N') && (data == 'D'))
+                            {
+                                framebuf = &_framebuf_app;
+                            } else {
+                                framebuf = &_framebuf_syncr;
+                            }
+                            break;
+
+                        case ApiFrame::RxPacket64Bit:
+                        case ApiFrame::RxPacket16Bit:
+                        case ApiFrame::Io64Bit:
+                        case ApiFrame::Io16Bit:
+                        case ApiFrame::AtModemStatus:
+                        case ApiFrame::RxPacketAO0:
+                        case ApiFrame::IoSampleRxZBDM:
+                            framebuf = &_framebuf_app;
+                            break;
+
+                        case ApiFrame::RxPacketAO1:
+                        case ApiFrame::SensorRxIndAO0:
+                        case ApiFrame::NodeIdentIndAO0:
+                        case ApiFrame::OtaFwUpStatus:
+                        case ApiFrame::RouteRecInd:
+                        case ApiFrame::Many2OneRRInd:
+                        case ApiFrame::TxReq64Bit:
+                        case ApiFrame::TxReq16Bit:
+                        case ApiFrame::AtCmd:
+                        case ApiFrame::AtCmdQueuePV:
+                        case ApiFrame::TxReqZBDM:
+                        case ApiFrame::ExpAddrCmd:
+                        case ApiFrame::RemoteCmdReq:
+                        case ApiFrame::CreateSrcRoute:
+                        case ApiFrame::Invalid:
+                        case ApiFrame::RouteInfo:
+                        case ApiFrame::AggregateAddr:
+                            framebuf = NULL;
+                            break;
+                    }
+
+                    if (framebuf == NULL) {
+                        digi_log(LogLevelWarning, "Discarding not supported frame type %02x\r\n", frame_type);
+                        rxstate = WAITING_FOR_START_FRAME;
+                    } else {
+                        frame = framebuf->get_next_free_frame();
+                        if (frame == NULL) {
+                            /* It's not possible to achive this condition as we discard older frames and only one frame can be used by syncr. commands */
+                            assert(frame != NULL);
+                            rxstate = WAITING_FOR_START_FRAME;
+                        } else {
+                            frame->set_data_len(framelen - 1);
+                        }
+
+                        frame->set_frame_type(frame_type);
+                        frame->set_data(frame_cached[1], 0);
+                        frame->set_data(frame_cached[2], 1);
+                        frame->set_data(data, 2);
+                    }
+                } else {
+                    frame->set_data(data, bytes_read - 1);
+                }
+                chksum += data;
+                bytes_read++;
+                if (bytes_read == framelen) {
+                    rxstate = WAITING_FOR_CHECKSUM;
+                }
+                break;
+
+            case WAITING_FOR_CHECKSUM:
+                chksum += data;
+                if (chksum == 0xFF) {
+                    /* We got a valid frame!! */
+                    frame->dump();
+
+                    /* If its a _modem status frame, process it to update the status info of the library.
+                     * The frame is also queued to allow processing it other handlers registered.
+                     * Note that radio_status_update() has to be fast to minimize the impact of processing
+                     * the funcion here */
+                    if (frame->get_frame_type() == ApiFrame::AtModemStatus) {
+                        radio_status_update((AtCmdFrame::ModemStatus)frame->get_data_at(0));
+                        if (_initializing) {
+                            framebuf->free_frame(frame);
+                        } else {
+                            framebuf->complete_frame(frame);
+                        }
+                    } else {
+                        framebuf->complete_frame(frame);
+                        /* Note, the frame will be released elsewhere, once it has been processed */
+                    }
+                } else {
+                    framebuf->free_frame(frame);
+                    digi_log(LogLevelWarning, "Checksum error, got %02x, %02x\r\n", data, chksum);
+                }
+                /* Intentional fall-through */
+            default:
+                rxstate = WAITING_FOR_START_FRAME;
+                break;
+        }
+    }
+    /* TODO, signal the thread processing incoming frames */
+}
+
+/* This is a pure virtual function, but exists here because its called from this class to
+ * to update the status of the object, and can be called before the construction of the
+ * object has been completed and the virtual functions filled */
+void XBee::radio_status_update(AtCmdFrame::ModemStatus modem_status)
+{
+    UNUSED_PARAMETER(modem_status);
+}
+
+void XBee::set_timeout(uint16_t timeout_ms)
+{
+    this->_timeout_ms = timeout_ms;
+}
+
+uint16_t XBee::get_timeout(void) const
+{
+    return _timeout_ms;
+}
+
+ApiFrame * XBee::get_this_api_frame(uint8_t id, ApiFrame::ApiFrameType type,
+                                          ApiFrame::ApiFrameType type2)
+{
+    Timer timer = Timer();
+    timer.start();
+
+    while (timer.read_ms() < _timeout_ms) {
+        ApiFrame * frame = _framebuf_syncr.get_next_complete_frame();
+        if (frame == NULL) {
+            wait_ms(10);
+            continue;
+        }
+
+        if ((frame->get_frame_type() != type) &&
+            (frame->get_frame_type() != type2)) {
+            _framebuf_syncr.complete_frame(frame);
+            wait_ms(1);
+            continue;
+        }
+
+        if (frame->get_data_at(ATCMD_RESP_FRAME_ID_OFFSET) != id) {
+            _framebuf_syncr.complete_frame(frame);
+            wait_ms(1);
+            continue;
+        }
+
+        /* frame found */
+        return frame;
+    }
+
+    digi_log(LogLevelWarning, "Frame type: %02x, id: %02x, timeout\r\n", (uint8_t)type, id);
+
+    return NULL;
+}
+
+void XBee::send_byte_escaping_if(uint8_t data)
+{
+    if (IS_API2()) {
+        switch (data) {
+            case DR_START_OF_FRAME:
+            case DR_ESCAPE_BYTE:
+            case DR_XON_BYTE:
+            case DR_XOFF_BYTE:
+                _uart->putc(DR_ESCAPE_BYTE);
+                _uart->putc(data ^ DR_ESCAPE_XOR_BYTE);
+                break;
+            default:
+                _uart->putc(data);
+        }
+    } else {
+        _uart->putc(data);
+    }
+}
+
+void XBee::send_api_frame(ApiFrame *frame)
+{
+    uint8_t chksum;
+    const uint8_t *data;
+    uint16_t bytes_sent = 0, frame_len;
+
+    frame->dump();
+
+    frame_len = 1 + frame->get_data_len(); /* frame type + frame payload */
+    data = frame->get_data();
+
+    /* Send the start of frame delimiter */
+    _uart->putc(DR_START_OF_FRAME);
+
+    /* Now the length */
+    send_byte_escaping_if((uint8_t)(frame_len >> 8));
+    send_byte_escaping_if((uint8_t)frame_len);
+
+    /* Send the Frame type and then the payload */
+    chksum = (uint8_t)frame->get_frame_type();
+    send_byte_escaping_if(chksum);
+    bytes_sent++;
+
+    /* And now, send the packet payload */
+    while (bytes_sent++ < frame_len) {
+        chksum += *data;
+        send_byte_escaping_if(*data++);
+    }
+
+    /* And finally send the checksum */
+    send_byte_escaping_if(~chksum);
+}
+
+RadioStatus XBee::register_frame_handler(FrameHandler *const handler)
+{
+    if (handler != NULL) {
+        for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
+            if (_fhandlers[i] != NULL) {
+                continue;
+            }
+            _fhandlers[i] = handler;
+            return Success;
+        }
+    }
+
+    digi_log(LogLevelError, "No more Frame Handlers available. Increase MAX_FRAME_HANDLERS define\r\n");
+
+    return Failure;
+}
+
+RadioStatus XBee::unregister_frame_handler(FrameHandler *const handler)
+{
+    int i;
+
+    if (handler != NULL) {
+        for (i = 0; i < MAX_FRAME_HANDLERS; i++) {
+            if (_fhandlers[i] == handler) {
+                break;
+            }
+        }
+
+        if (i == MAX_FRAME_HANDLERS) {
+            return Failure;
+        }
+
+        do {
+            if (i == MAX_FRAME_HANDLERS - 1) {
+                _fhandlers[i] = NULL;
+            } else {
+                _fhandlers[i] = _fhandlers[i + 1];
+            }
+        } while (++i < MAX_FRAME_HANDLERS);
+    }
+
+    return Success;
+}
+
+XBee::RadioProtocol XBee::get_radio_protocol(void) const
+{
+    enum HardwareVersion {
+#ifdef EXTRA_XBEE_PROTOCOLS
+        X09_009 = 0x01,
+        X09_019 = 0x02,
+        XH9_009 = 0x03,
+        XH9_019 = 0x04,
+        X24_009 = 0x05,
+        X24_019 = 0x06,
+        X09_001 = 0x07,
+        XH9_001 = 0x08,
+        X08_004 = 0x09,
+        XC09_009 = 0x0A,
+        XC09_038 = 0x0B,
+        X24_038 = 0x0C,
+        X09_009_TX = 0x0D,
+        X09_019_TX = 0x0E,
+        XH9_009_TX = 0x0F,
+        XH9_019_TX = 0x10,
+        X09_001_TX = 0x11,
+        XH9_001_TX = 0x12,
+        XT09B_XXX = 0x13,
+        XT09_XXX = 0x14,
+        XC08_009 = 0x15,
+        XC08_038 = 0x16,
+#endif
+        XB24_AXX_XX = 0x17,
+        XBP24_AXX_XX = 0x18,
+        XB24_BXIX_XXX = 0x19,
+        XBP24_BXIX_XXX = 0x1A,
+#ifdef EXTRA_XBEE_PROTOCOLS
+        XBP09_DXIX_XXX = 0x1B,
+        XBP09_XCXX_XXX = 0x1C,
+        XBP08_DXXX_XXX = 0x1D,
+#endif
+        XBP24B = 0x1E,
+#ifdef EXTRA_XBEE_PROTOCOLS
+        XB24_WF = 0x1F,
+        AMBER_MBUS = 0x20,
+#endif
+        XBP24C = 0x21,
+        XB24C = 0x22,
+#ifdef EXTRA_XBEE_PROTOCOLS
+        XSC_GEN3 = 0x23,
+        SRD_868_GEN3 = 0x24,
+        ABANDONATED = 0x25,
+        SMT_900LP = 0x26,
+        WIFI_ATHEROS = 0x27,
+        SMT_WIFI_ATHEROS = 0x28,
+        SMT_475LP = 0x29,
+        XBEE_CELL_TH = 0x2A,
+        XLR_MODULE = 0x2B,
+        XB900HP_NZ = 0x2C,
+        XBP24C_TH_DIP = 0x2D,
+        XB24C_TH_DIP = 0x2E,
+        XLR_BASEBOARD = 0x2F,
+        XBP24C_S2C_SMT = 0x30
+#endif
+    };
+    const bool fw_4_bytes_len = _fw_version > 0x0FFF && _fw_version < 0xFFFF;
+    const uint8_t fw_nibble_3 = (_fw_version >> (4 * 3)) & 0x000F;
+    const uint8_t fw_nibble_1 = (_fw_version >> (4 * 1)) & 0x000F;
+    const uint8_t fw_nibble_0 = (_fw_version >> (4 * 0)) & 0x000F;
+    const uint8_t hw_version_msb = _hw_version >> 8;
+
+    if (hw_version_msb == XB24_AXX_XX || hw_version_msb == XBP24_AXX_XX) {
+#ifdef EXTRA_XBEE_PROTOCOLS
+        if (fw_4_bytes_len && fw_nibble_3 == 8) {
+            return DigiMesh;
+        }
+        return Raw_802_15_4;
+#else
+        if (!(fw_4_bytes_len && fw_nibble_3 == 8)) {
+            return Raw_802_15_4;
+        }
+#endif
+    } else if (hw_version_msb == XB24_BXIX_XXX || hw_version_msb == XBP24_BXIX_XXX) {
+        if (fw_4_bytes_len && ((fw_nibble_3 == 1 && fw_nibble_1 == 2 && fw_nibble_0 == 0) || fw_nibble_3 == 2)) {
+            return ZigBee;
+        }
+#ifdef EXTRA_XBEE_PROTOCOLS
+        if (fw_4_bytes_len && fw_nibble_3 == 3) {
+            return SmartEnergy;
+        }
+        return ZNet;
+    } else if (hw_version_msb == XBP09_DXIX_XXX) {
+        if (fw_4_bytes_len && (fw_nibble_3 == 8 || fw_nibble_1 == 8))  {
+            return DigiMesh;
+        }
+        return DigiPoint;
+    } else if (hw_version_msb == XBP08_DXXX_XXX) {
+        return DigiPoint;
+#endif
+    } else if (hw_version_msb == XBP24B) {
+#ifdef EXTRA_XBEE_PROTOCOLS
+        if (fw_4_bytes_len && fw_nibble_3 == 3) {
+            return SmartEnergy;
+        }
+        return ZigBee;
+#else
+        if (!(fw_4_bytes_len && fw_nibble_3 == 3)) {
+            return ZigBee;
+        }
+#endif
+#ifdef EXTRA_XBEE_PROTOCOLS
+    } else if (hw_version_msb == XB24_WF || hw_version_msb == WIFI_ATHEROS || hw_version_msb == SMT_WIFI_ATHEROS) {
+        return XBeeWiFi;
+#endif
+    } else if (hw_version_msb == XBP24C || hw_version_msb == XB24C) {
+        if (fw_4_bytes_len && fw_nibble_3 == 2) {
+            return Raw_802_15_4;
+        }
+#ifdef EXTRA_XBEE_PROTOCOLS
+        if (fw_4_bytes_len && fw_nibble_3 == 5) {
+            return SmartEnergy;
+        }
+        return ZigBee;
+#else
+        if (!(fw_4_bytes_len && fw_nibble_3 == 5)) {
+            return ZigBee;
+        }
+#endif
+#ifdef EXTRA_XBEE_PROTOCOLS
+    } else if (hw_version_msb == XSC_GEN3 || hw_version_msb == SRD_868_GEN3) {
+        if (fw_4_bytes_len && fw_nibble_3 == 8) {
+            return DigiMesh;
+        } else if (fw_4_bytes_len && fw_nibble_3 == 1) {
+            return DigiPoint;
+        }
+        return None;
+    } else if (hw_version_msb == XBEE_CELL_TH) {
+        return None;
+    } else if (hw_version_msb == XLR_MODULE) {
+        return None;
+    } else if (hw_version_msb == XLR_BASEBOARD) {
+        return None;
+    } else if (hw_version_msb == XB900HP_NZ) {
+        return DigiPoint;
+    } else if (hw_version_msb == XBP24C_TH_DIP || hw_version_msb == XB24C_TH_DIP || hw_version_msb == XBP24C_S2C_SMT) {
+        if (fw_4_bytes_len && fw_nibble_3 == 9) {
+            return DigiMesh;
+        }
+        if (fw_4_bytes_len && fw_nibble_3 == 5) {
+            return SmartEnergy;
+        }
+        if (fw_4_bytes_len && fw_nibble_3 == 2) {
+            return Raw_802_15_4;
+        }
+        return ZigBee;
+    }
+#else
+    }
+#endif
+
+    return None;
+}
+
+#define TX_STATUS_OFFSET_ZB     4
+#define TX_STATUS_OFFSET_802    1
+
+TxStatus XBee::send_data(ApiFrame *frame)
+{
+    TxStatus resp = TxStatusTimeout;
+    ApiFrame *resp_frame;
+
+    send_api_frame(frame);
+
+    /* Wait for the transmit status response packet */
+    resp_frame = get_this_api_frame(frame->get_frame_id(),
+                    ApiFrame::TxStatusZBDM, ApiFrame::TxStatus);
+    if (resp_frame == NULL) {
+        return resp;
+    }
+
+    uint8_t index = resp_frame->get_frame_type() == ApiFrame::TxStatusZBDM ?
+            TX_STATUS_OFFSET_ZB : TX_STATUS_OFFSET_802;
+
+    resp = (TxStatus)resp_frame->get_data_at(index);
+
+    /* Once processed, remove the frame from the buffer */
+    _framebuf_syncr.free_frame(resp_frame);
+
+    return resp;
+}
+
+TxStatus XBee::send_data_broadcast(const uint8_t *const data, uint16_t len, bool syncr)
+{
+    const RemoteXBee remoteDevice = RemoteXBee(ADDR64_BROADCAST);
+    return send_data(remoteDevice, data, len, syncr);
+}
+
+uint32_t XBee::process_rx_frames()
+{
+    ApiFrame *frame = NULL;
+
+    while ((frame = _framebuf_app.get_next_complete_frame()) != NULL) {
+        for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
+
+            if (_fhandlers[i] == NULL) {
+                /* No more handlers, break here */
+                break;
+            }
+
+            /* Check if frame and handler match, if not... go for the next one */
+            if (frame->get_frame_type() != _fhandlers[i]->get_type()) {
+                continue;
+            }
+
+            _fhandlers[i]->process_frame_data(frame);
+        }
+
+        /* Once processed, remove the frame from the buffer */
+        _framebuf_app.free_frame(frame);
+    }
+
+    const uint32_t dropped_frames = _framebuf_app.get_dropped_frames_count();
+    if (dropped_frames != 0) {
+        digi_log(LogLevelWarning, "process_rx_frames: %d frames dropped!!!\r\n", dropped_frames);
+    }
+
+    return dropped_frames;
+}
+
+void XBee::register_modem_status_cb(modem_status_cb_t function)
+{
+    if (_modem_status_handler == NULL) {
+        _modem_status_handler = new FH_ModemStatus();
+        register_frame_handler(_modem_status_handler);
+    }
+    _modem_status_handler->register_modem_status_cb(function);
+}
+
+void XBee::unregister_modem_status_cb()
+{
+    if (_modem_status_handler != NULL) {
+        _modem_status_handler->unregister_modem_status_cb();
+        unregister_frame_handler(_modem_status_handler);
+        delete _modem_status_handler;
+        _modem_status_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+int XBee::get_AI(void)
+{
+    uint32_t atai;
+    const AtCmdFrame::AtCmdResp status = get_param("AI", &atai);
+
+    if (status != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "get_association_indication() failed with %d\r\n", status);
+        return -1;
+    }
+    return atai;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/XBee.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/XBee.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,714 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DIGI_RADIO_H_)
+#define __DIGI_RADIO_H_
+
+#include <stdint.h>
+#include "config.h"
+#include "Utils/Debug.h"
+#include "Frames/AtCmdFrame.h"
+#include "FrameHandlers/FrameHandler.h"
+#include "FrameHandlers/FH_ModemStatus.h"
+#include "FrameBuffer/FrameBuffer.h"
+#include "Addresses.h"
+#include "RemoteXBee/RemoteXBee.h"
+#include "IO/IO.h"
+
+#define MAX_FRAME_HANDLERS      4
+#define RESET_TIMEOUT_MS        5000
+
+#define DR_API_FRAME_OVERHEAD   4       /* Start of frame + frame len + checksum */
+#define DR_MIN_API_FRAME_LEN    4
+#define DR_START_OF_FRAME       0x7E
+#define DR_ESCAPE_BYTE          0x7D
+#define DR_XON_BYTE             0x11
+#define DR_XOFF_BYTE            0x13
+#define DR_ESCAPE_XOR_BYTE      0x20
+
+/* TODO, verify these flags work in all modules */
+#define DISABLE_RETRIES_AND_ROUTE_REPAIR    0x01
+#define ENABLE_APS_ENCRYPTION               0x20
+#define USE_EXTENDED_TX_TIMEOUT             0x40
+
+namespace XBeeLib {
+
+/**
+ * @defgroup RadioStatus
+ * @{
+ */
+/**
+ * RadioStatus
+ */
+enum RadioStatus {
+    Success         = 0,    /**< Success */
+    Failure         = -1,   /**< Failure */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup TxStatus
+ * @{
+ */
+/**
+ * TxStatus
+ */
+enum TxStatus {
+    TxStatusSuccess            = 0,     /**< Success */
+    TxStatusAckFail            = 1,     /**< MAC ACK Failure */
+    TxStatusCCAFail            = 2,     /**< CCA Failure */
+    TxStatusInvDestEP          = 0x15,  /**< Invalid destination endpoint */
+    TxStatusNwAckFail          = 0x21,  /**< Network ACK Failure */
+    TxStatusNotJoinNw          = 0x22,  /**< Not Joined to Network */
+    TxStatusSelfAddr           = 0x23,  /**< Self-addressed */
+    TxStatusAddrNotFound       = 0x24,  /**< Address Not Found */
+    TxStatusRouteNotFound      = 0x25,  /**< Route Not Found */
+    TxStatusBroadSrcFail2Heard = 0x26,  /**< Broadcast source failed to hear a neighbor relay the message */
+    TxStatusInvBindTableIdx    = 0x2B,  /**< Invalid binding table index */
+    TxStatusResourceError      = 0x2C,  /**< Resource error lack of free buffers, timers, etc. */
+    TxStatusAttBroadcWithAPS   = 0x2D,  /**< Attempted broadcast with APS transmission */
+    TxStatusAttUnicWithAPSEE0  = 0x2E,  /**< Attempted unicast with APS transmission, but EE=0 */
+    TxStatusResourceError2     = 0x31,  /**< TxStatusResourceError2 */
+    TxStatusInternalError      = 0x32,  /**< Resource error lack of free buffers, timers, etc. */
+    TxStatusPayloadTooLarge    = 0x74,  /**< Data payload too large */
+    TxStatusIndirectMsgUnReq   = 0x75,  /**< Indirect message unrequested */
+    TxStatusInvalidAddr        = 0xfe,  /**< Invalid Address (Error generated by the library) */
+    TxStatusTimeout            = 0xff,  /**< Timeout (Error generated by the library) */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup RadioLocation
+ * @{
+ */
+/**
+ * RadioLocation
+ */
+enum RadioLocation {
+    RadioLocal     = 0,     /**< Local Radio */
+    RadioRemote    = 1,     /**< Remote Radio */
+};
+/**
+ * @}
+ */
+
+/** Parent Class for XBee modules, not to be directly used */
+class XBee
+{
+    private:
+    /** wait_for_module_to_reset - waits until a Modem Status packet with a reset status
+     * is received, or the timeout expires.
+     *
+     *  @returns
+     *     Success if a Modem Status was received,
+     *     Failure otherwise
+     */
+    RadioStatus wait_for_module_to_reset(volatile uint16_t *rst_cnt_p, uint16_t init_rst_cnt);
+
+    protected:
+    /** buffer to store the received frames */
+    static FrameBuffer _framebuf_app;
+    static FrameBuffer _framebuf_syncr;
+
+    public:
+
+        /**
+         * RadioMode
+         */
+        enum RadioMode {
+            ModeUnknown     = 0,  /**< Unknown */
+            ModeAPI1        = 1,  /**< API1 */
+            ModeAPI2        = 2,  /**< API2 */
+            ModeTransparent = 3,  /**< Transparent */
+            ModeBootloader  = 4,  /**< Bootloader */
+        };
+
+        /** Class constructor
+         * @param tx the TX pin of the UART that will interface the XBee module
+         * @param rx the RX pin of the UART that will interface the XBee module
+         * @param reset the pin to which the XBee's reset line is attached to, use NC if not available
+         * @param rts the RTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param cts the CTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param baud the baudrate for the UART that will interface the XBee module. Note that the module has to be already configured
+         * to this baud rate (ATBD parameter). By default it is configured to 9600 bps
+         * */
+        XBee(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);
+
+        XBee(const XBee& other); /* Intentionally not implemented */
+        /** Class destructor */
+        virtual ~XBee();
+
+        /** init-  initializes object
+         * This function must be called just after creating the object so it initializes internal data.
+         * @returns
+         *         Success if the module has been properly initialized and is ready to process data.
+         *         Failure otherwise.
+         */
+        RadioStatus init();
+
+        /** get_addr64 - returns the 64bit address of the local device
+         *
+         *  @returns the 64bit address of the local device
+         */
+        uint64_t get_addr64() const;
+
+        /** hardware_reset - performs a hardware reset. The reset GPIO must have
+         * been provided to the constructor
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus hardware_reset();
+
+        /** software_reset - performs a firmware reset
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus software_reset();
+
+        /** device_reset - performs a hardware reset if there is a GPIO connected to the
+         * reset line of the device. Otherwise, performs a firmware reset.
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+#if defined(UNIT_TEST)
+        virtual
+#endif
+        RadioStatus device_reset();
+
+        /** set_tx_options - sets the transmit options byte, used with the transmit frames.
+         *                   Valid flags are:
+         *                       - DISABLE_RETRIES_AND_ROUTE_REPAIR
+         *                       - ENABLE_APS_ENCRYPTION
+         *                       - USE_EXTENDED_TX_TIMEOUT
+         *
+         *  @param options variable with the option flags
+         */
+        void set_tx_options(uint8_t options);
+
+        /** get_tx_options - returns the tx options byte configured in the library.
+         *
+         *  @returns the tx options byte configured in the library.
+         */
+        uint8_t get_tx_options() const;
+
+        /************************ Configuration member methods *************************/
+        /** write_config - write settings to non volatile memory
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus write_config();
+
+        /** config_io_sample_destination - configures to which node a remote module will send its IO Samples to.
+         * @Note: this will modify 'remote' DH and DL parameters, if the remote node is configured in transparent mode this could lead to unwanted behavior.
+         * Consult the module's reference manual for more information.
+         *
+         *  @param remote remote device that will be sending the IO Samples
+         *  @param destination remote device that will be receiving the IO Samples sent by 'remote'
+         *  @returns the result of the data transfer
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus config_io_sample_destination(const RemoteXBee& remote, const RemoteXBee& destination);
+
+        /** set_io_sample_rate - configures how often the IO Samples should be sent to the destination (see @ref send_io_sample_to).
+         *
+         *  @param remote remote device that will be sending the IO Samples
+         *  @param seconds the IO Sample sending rate in seconds (granularity is of 1 millisecond). Maximum is 65.535 seconds.
+         *  @returns the result of the data transfer
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_io_sample_rate(const RemoteXBee& remote, float seconds);
+
+        /** set_power_level - sets the power level at which the radio will transmit
+         *
+         *  @param level power level at which the radio will transmit
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_power_level(uint8_t level);
+
+        /** get_power_level - reads the power level configured in the radio
+         *
+         *  @param level pointer where the read power level will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_power_level(uint8_t * const level);
+
+        /** get_hw_version - gets the hardware version of the radio
+         *
+         *  @returns the hardware version of the radio
+         */
+        uint16_t get_hw_version() const;
+
+        /** get_fw_version - gets the firmware version of the radio
+         *
+         *  @returns the firmware version of the radio
+         */
+        uint16_t get_fw_version() const;
+
+        /** set_node_identifier - configures the Node Identifier string
+         *
+         *  @param node_id NULL-terminated string with the Node Identifier that will be set on the module. Up to 20 characters length (21 with NULL-terminator).
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_node_identifier(const char * const node_id);
+
+        /** get_node_identifier - reads the configured Node Identifier string
+         *
+         *  @param node_id Pointer to where to store the read Node Identifier, it must point to a buffer with at least 21-bytes length.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_node_identifier(char * const node_id);
+
+        /** enable_network_encryption - Enable network encryption.
+         *
+         *  @param enable whether to enable this feature or not
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus enable_network_encryption(bool enable);
+
+        /** set_network_encryption_key - Sets the 128-bit AES key used for encryption and decryption. Setting it to 0 will cause the coordinator to transmit the network key in the clear to joining devices, and will cause joining devices to acquire the network key in the clear when joining.
+         *  It is not recommended to set the key programmatically, because it could be read through the raw serial port bits.
+         *  @param key pointer to the 128-bit AES key
+         *  @param length size of the buffer pointed by 'key'
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_network_encryption_key(const uint8_t * const key, const uint16_t length);
+
+        /** start_node_discovery - starts a node discovery operation. The responses
+         * have to be processes on the callback function that have to be registered
+         * for that purpose.
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus start_node_discovery();
+
+        /** is_node_discovery_in_progress - checks if node discovery is in progress.
+         *  @returns true if node discovery is in progress, false otherwise
+         */
+        bool is_node_discovery_in_progress();
+
+#define XBEEZB_ND_OPTION_APPEND_DD          (1 << 0)
+#define XBEEZB_ND_OPTION_SELF_RESPONSE      (1 << 1)
+#define XBEE802_ND_OPTION_SELF_RESPONSE     (1 << 0)
+#define XBEEDM_ND_OPTION_APPEND_DD          (1 << 0)
+#define XBEEDM_ND_OPTION_SELF_RESPONSE      (1 << 1)
+#define XBEEDM_ND_OPTION_INCLUDE_RSSI       (1 << 2)
+
+        /** config_node_discovery - configures the node discovery operation
+         *
+         *  @param backoff_ms max allowed time for devices in the network to answer
+         *                    to the Node Discovery request
+         *  @param  options node discovery options (flags)
+         *              XBEE802_ND_OPTION_SELF_RESPONSE - to allow the module self responding (802.15.4 only)
+         *              XBEEZB_ND_OPTION_SELF_RESPONSE - to allow the module self responding (ZigBee only)
+         *              XBEEZB_ND_OPTION_APPEND_DD - to append the DD value to the response (ZigBee only)
+         *              XBEEDM_ND_OPTION_INCLUDE_RSSI - to include RSSI information in response (DigiMesh only)
+         *              XBEEDM_ND_OPTION_SELF_RESPONSE - to allow the module self responding (DigiMesh only)
+         *              XBEEDM_ND_OPTION_APPEND_DD - to append the DD value to the response (DigiMesh only)
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+         RadioStatus config_node_discovery(uint16_t backoff_ms, uint8_t options = 0);
+
+         /** get_config_node_discovery - reads the configuration of the node discovery
+          * settings
+          *
+          *  @param backoff_ms pointer where the configured node discovery back-off time value will be stored
+          *  @param  options pointer whre the node discovery options (flags) will be saved
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+         RadioStatus get_config_node_discovery(uint16_t * const backoff_ms, uint8_t * const options);
+
+        /** set_timeout - sets the timeout in ms, used by sync methods
+         *
+         *  @param timeout_ms new timeout in ms
+         */
+        void set_timeout(uint16_t timeout_ms);
+
+        /** get_timeout - gets the timeout in ms configured in the library. This value
+         *                is used in sync commands
+         *
+         *  @returns the configured timeout value in ms
+         */
+        uint16_t get_timeout() const;
+
+        /* ... */
+
+        /*********************** send_data member methods ************************/
+        /** send_data - sends data to a remote device
+         *
+         *  @param remote remote device
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        virtual TxStatus send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr = true) = 0;
+
+        /** send_data_broadcast - sends data to all devices in the network, using the broadcast address.
+         *
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus send_data_broadcast(const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** set_param - sets a parameter in the local radio by sending an AT command and waiting for the response.
+         *
+         *  @param param parameter to be set.
+         *  @param data the parameter value (4 bytes) to be set.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp set_param(const char * const param, uint32_t data);
+
+        /** set_param - sets a parameter in the local radio by sending an AT command and waiting for the response.
+         *
+         *  @param param parameter to be set.
+         *  @param data the parameter value byte array (len bytes) to be set.
+         *  @param len number of bytes of the parameter value.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp set_param(const char * const param, const uint8_t * data = NULL, uint16_t len = 0);
+
+        /** get_param - gets a parameter from the local radio by sending an AT command and waiting for the response.
+         *
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (4 bytes) will be stored.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp get_param(const char * const param, uint32_t * const data);
+
+        /** get_param - gets a parameter from the local radio by sending an AT command and waiting for the response.
+         *
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param value will be stored.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp get_param(const char * const param, uint8_t * const data, uint16_t * const len);
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value (4 bytes) to be set.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, uint32_t data) = 0;
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value byte array (len bytes) to be set.
+         *  @param len number of bytes of the parameter value.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data = NULL, uint16_t len = 0) = 0;
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (4 bytes) will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data) = 0;
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param value will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len) = 0;
+
+        /** process_rx_frames - method that processes the frames queued in the reception
+         *                      buffer. Calls the process_frame_data method of the frame
+         *                      handlers registered
+         *
+         *  @returns Number of dropped frames since latest call to this method.
+         */
+        uint32_t process_rx_frames();
+
+        /** register_modem_status_cb - registers the callback function that will be called
+         * when a Modem Status packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_modem_status_cb(modem_status_cb_t function);
+
+        /** unregister_modem_status_cb - removes the Modem Status reception callback */
+        void unregister_modem_status_cb();
+
+    protected:
+
+#define EXTRA_XBEE_PROTOCOLS
+
+        enum RadioProtocol {
+            None,
+            ZigBee,
+            Raw_802_15_4,
+#ifdef EXTRA_XBEE_PROTOCOLS
+            XBeeWiFi,
+            DigiMesh,
+            SmartEnergy,
+            DigiPoint,
+            ZNet,
+#endif
+        };
+        /** send_byte_escaping_if - sends a byte, through the serial interface, to
+         * the radio, escaping the byte if the working mode of the radio is API2.
+         *
+         *  @param line PWM line being set
+         *  @param data the byte that will be send to radio
+         */
+        void send_byte_escaping_if(uint8_t data);
+
+        /** uart_read_cb - serial interface callback, called when data is received on
+         * the serial port. The function parses the incoming data and, when a good
+         * frame is detected, saves it in the frame list
+         */
+        void uart_read_cb();
+
+        /** get_this_api_frame - searches in the FrameBuffer for an incoming frame
+         *                       with frameid equal to id and frame type equal to type
+         *                       or type2. If after timeout the frame hast not been found,
+         *                       returns.
+         *
+         *  @param id id of the frame we are looking for.
+         *  @param type tye type we expect the frame to be.
+         *  @param type2 alternative valid type, if provided.
+         *  @returns a pointer to the frame found in the FrameBuffer or a null pointer if
+         *           the frame has not been found and the timeout expired.
+         */
+        ApiFrame * get_this_api_frame(uint8_t id, ApiFrame::ApiFrameType type,
+                    ApiFrame::ApiFrameType type2 = ApiFrame::Invalid);
+
+        /** send_api_frame - method to send, over the serial port, an API frame
+         *
+         * @param frame pointer to the frame that will be sent.
+         */
+#if defined(UNIT_TEST)
+        virtual
+#endif
+        void send_api_frame(ApiFrame *frame);
+
+        /** update_radio_status - method called when a modem status frame is received
+         *  to update the internal status variables of the library.
+         *  @note This is not a pure virtual function because it can be called while
+         *        the object is being constructed and we need the implementation of the
+         *        base class.
+         *
+         *  @param status byte with the status received in the modem status frame
+         */
+        virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);
+
+        /** Method used internaly by the derived classes to transmit data to
+         * remote nodes, waiting for the answer from the device
+         *
+         *  @param frame frame that will be sent to the radio (have to be a
+         *         proper transmit frame
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus send_data(ApiFrame *frame);
+
+        /** send_at_cmd - sends an AT command to the radio and waits for the response.
+         *
+         *  @param frame api frame with the command and command params.
+         *  @param buf pointer where the param response (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param response will be stored.
+         *  @param radio_location radio location, either RadioLocal or RadioRemote.
+         *  @param reverse reverse the byte ordering of the response saved in buf.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame,
+                    uint8_t *const buf, uint16_t *const len, RadioLocation radio_location = RadioLocal, bool reverse = true);
+
+        /* send_at_cmd - methods used internally by other methods */
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame);
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint8_t *data);
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint16_t *data);
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint32_t *data);
+
+        /** register_frame_handler - registers an object to handle incoming frames from
+         *                           the radio.
+         *  @note For any type of frame more than one handler can be registered and all
+         *        of them are called, sequentially, when a frame of that type arrives.
+         *
+         *  @param handler pointer to the frame handler object
+         *  @returns the result of the registration
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus register_frame_handler(FrameHandler *const handler);
+
+        /** unregister_frame_handler - removes a previously registered frame handler
+         *
+         *  @param handler pointer to the frame handler object
+         *  @returns the result of the unregister operation
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus unregister_frame_handler(FrameHandler *const handler);
+
+        /** get_radio_protocol - returns the RF protocol that the connected module uses
+         *                       based on its firmware and hardware versions
+         *
+         *  @returns a RadioProtocol enum.
+         */
+        RadioProtocol get_radio_protocol(void) const;
+
+        /** _get_iosample - forces an io_sample read (reads all digital and analog inputs)
+         *
+         *  @param remote remote device
+         *  @param io_sample buffer where the io_sample response is copied
+         *  @param len pointer where the length of the io_sample response is stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus _get_iosample(const RemoteXBee& remote, uint8_t * const io_sample, uint16_t * const len);
+
+        void _get_remote_node_by_id(const char * const node_id, uint64_t * addr64, uint16_t * addr16);
+
+        /** check_radio_flow_control - checks that the radio has the CTS "D7" and RTS "D6" pins configured
+         *                       according to the serial hardware flow control selected by the user
+         *
+         *  @returns true if check success.
+         */
+        bool check_radio_flow_control();
+
+        /** get_AI - reads the AI parameter.
+         *
+         *  @returns
+         *      -1 if an error occurred when reading AI.
+         *      0-0xFF the AI value.
+         */
+        int get_AI(void);
+
+        /** get_node_discovery_timeout - gets the node discovery timeout
+          *
+          *  @param timeout_ms pointer where the node discovery timeout value will be stored
+          *  @param wait_for_complete_timeout pointer where the function will store if the operator
+          *                                   has to wait for the complete nd timeout after issuing 
+          *                                   a directed nd request
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms) = 0;
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout) = 0;
+
+        /** serial hardware flow control selected by the user (RTSCTS, RTS,CTS) */
+        SerialBase::Flow _serial_flow_type;
+
+        /** Operating mode of the module (API1, API2,...) */
+        RadioMode   _mode;
+
+        /** Hardware version value of the radio */
+        uint16_t    _hw_version;
+
+        /** Firmware version value of the radio */
+        uint16_t    _fw_version;
+
+        /** Timeout in ms for sync operations (when we wait for a response) */
+        uint16_t    _timeout_ms;
+
+        /** Device 64 bit address (SH, SL) */
+        uint64_t      _dev_addr64;
+
+        /** Serial Interface, use RawSerial as we dont use the streams */
+        RawSerial   *_uart;
+
+        /** IO connected to the radio reset line */
+        DigitalOut  *_reset;
+
+        /** Transmit options byte */
+        uint8_t     _tx_options;
+
+        /** Array of frame handler pointers. We use an array instead of a vector or other
+         *  data structure to save memory and avoid dynamic memory allocation, to avoid
+         *  memory fragmentation */
+        FrameHandler *_fhandlers[MAX_FRAME_HANDLERS];
+
+        /** Hardware reset counter, automatically updated by the library */
+        volatile uint16_t    _hw_reset_cnt;
+
+        /** Watchdog reset counter, automatically updated by the library */
+        volatile uint16_t    _wd_reset_cnt;
+
+        /** Frame handler used for the Modem Status packets. Automatically registered when a callback
+         *  function is registered */
+        FH_ModemStatus  *_modem_status_handler;
+
+        /** Latest modem status received */
+        AtCmdFrame::ModemStatus _modem_status;
+
+        /** Library is initializing */
+        bool _initializing;
+
+        /** Timer used for node discovery */
+        Timer _nd_timer;
+
+        /** node discovery timeout */
+        int _nd_timeout;
+
+        /** If a _get_remote_node_by_id() is in progress, this keeps the expected frame id */
+        uint8_t _node_by_ni_frame_id;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* defined(__DIGI_RADIO_H_) */
+
+
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee802/XBee802.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee802/XBee802.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,615 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+#include "XBee802.h"
+#include "IO/IOSample802.h"
+#include "Frames/802_Frames.h"
+#include "FrameHandlers/FH_ModemStatus.h"
+
+using namespace XBeeLib;
+
+/* Class constructor */
+XBee802::XBee802(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
+        XBee(tx, rx, reset, rts, cts, baud),
+        _nd_handler(NULL), _rx_64b_handler(NULL), _rx_16b_handler(NULL),
+        _io_data_64b_handler(NULL), _io_data_16b_handler(NULL)
+{
+
+}
+
+/* Class destructor */
+XBee802::~XBee802()
+{
+    unregister_node_discovery_cb();
+    unregister_receive_cb();
+    unregister_io_sample_cb();
+}
+
+RadioStatus XBee802::init()
+{
+    RadioStatus retval = XBee::init();
+    uint16_t addr16;
+    RadioStatus error = get_network_address(&addr16);
+    if (error == Success) {
+        digi_log(LogLevelInfo, "ADDR16: %04x\r\n", addr16);
+    } else {
+        digi_log(LogLevelInfo, "ADDR16: UNKNOWN\r\n");
+    }
+
+    const RadioProtocol radioProtocol = get_radio_protocol();
+    if (radioProtocol != Raw_802_15_4) {
+        digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", Raw_802_15_4, radioProtocol);
+        retval = Failure;
+    }
+    assert(radioProtocol == Raw_802_15_4);
+
+    return retval;
+}
+
+RadioStatus XBee802::set_channel(uint8_t  channel)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    /* Pro and Non-Pro modules have different channels available. The at 
+       command will return an error if the selected channel is not available */
+    cmdresp = set_param("CH", channel);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee802::get_channel(uint8_t * const  channel)
+{
+    if (channel == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("CH", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *channel = var32;
+    return Success;
+}
+
+RadioStatus XBee802::set_panid(uint16_t  panid)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("ID", panid);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee802::get_panid(uint16_t * const  panid)
+{
+    if (panid == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("ID", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *panid = var32;
+    return Success;
+}
+
+RadioStatus XBee802::get_network_address(uint16_t * const  addr16)
+{
+    if (addr16 == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("MY", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *addr16 = var32;
+    return Success;
+}
+
+RadioStatus XBee802::set_network_address(uint16_t  addr16)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("MY", addr16);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee802::get_node_discovery_timeout(uint16_t * const timeout_ms)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+
+    cmdresp = get_param("NT", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *timeout_ms = (uint16_t)var32;
+
+    /* No N? command available for this protocol. Add a fix 1s guard time */
+    *timeout_ms += 1000;
+
+    return Success;
+}
+
+RadioStatus XBee802::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout)
+{
+    const RadioStatus status = get_node_discovery_timeout(timeout_ms);
+
+    /* This protocol requires to wait for the complete timeout before attempting
+       to execute other commands */
+    *wait_for_complete_timeout = true;
+
+    return status;
+}
+
+void XBee802::radio_status_update(AtCmdFrame::ModemStatus modem_status)
+{
+    /* Update the radio status variables */
+    if (modem_status == AtCmdFrame::HwReset) {
+        _hw_reset_cnt++;
+    } else if (modem_status == AtCmdFrame::WdReset) {
+        _wd_reset_cnt++;
+    }
+
+    _modem_status = modem_status;
+
+    digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status);
+}
+
+TxStatus XBee802::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr)
+{
+    if (remote.is_valid_addr64b()) {
+        const uint64_t remote64 =  remote.get_addr64();
+
+        digi_log(LogLevelDebug, "send_data ADDR64: %08x:%08x\r\n", UINT64_HI32(remote64), UINT64_LO32(remote64));
+
+        TxFrame802 frame = TxFrame802(remote64, _tx_options, data, len);
+
+        if (syncr) {
+            return send_data(&frame);
+        } else {
+            frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+            send_api_frame(&frame);
+            return TxStatusSuccess;
+        }
+    }
+
+    if (remote.is_valid_addr16b()) {
+        const uint16_t remote16 = remote.get_addr16();
+
+        digi_log(LogLevelDebug, "send_data ADDR16: %04x\r\n", remote16);
+
+        TxFrame802 frame = TxFrame802(remote16, _tx_options, data, len);
+
+        if (syncr) {
+            return send_data(&frame);
+        } else {
+            frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+            send_api_frame(&frame);
+            return TxStatusSuccess;
+        }
+    }
+
+    return TxStatusInvalidAddr;
+}
+
+XBee802::AssocStatus XBee802::get_assoc_status(void)
+{
+    return (AssocStatus)get_AI();
+}
+
+RemoteXBee802 XBee802::get_remote_node_by_id(const char * const node_id)
+{
+    uint64_t addr64;
+    uint16_t addr16;
+
+    _get_remote_node_by_id(node_id, &addr64, &addr16);
+    return RemoteXBee802(addr64, addr16);
+}
+
+void XBee802::register_node_discovery_cb(node_discovery_802_cb_t function)
+{
+    if (_nd_handler == NULL) {
+        _nd_handler = new FH_NodeDiscovery802();
+        register_frame_handler(_nd_handler);
+    }
+    _nd_handler->register_node_discovery_cb(function);
+}
+
+void XBee802::unregister_node_discovery_cb()
+{
+    if (_nd_handler != NULL) {
+        _nd_handler->unregister_node_discovery_cb();
+        unregister_frame_handler(_nd_handler);
+        delete _nd_handler;
+        _nd_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+void XBee802::register_receive_cb(receive_802_cb_t function)
+{
+    if (_rx_64b_handler == NULL) {
+        _rx_64b_handler = new FH_RxPacket64b802();
+        register_frame_handler(_rx_64b_handler);
+    }
+    _rx_64b_handler->register_receive_cb(function);
+
+    if (_rx_16b_handler == NULL) {
+        _rx_16b_handler = new FH_RxPacket16b802();
+        register_frame_handler(_rx_16b_handler);
+    }
+    _rx_16b_handler->register_receive_cb(function);
+}
+
+void XBee802::unregister_receive_cb()
+{
+    if (_rx_64b_handler != NULL) {
+        _rx_64b_handler->unregister_rec