Move rmr python api docs over.

Issue-ID: RIC-228
Change-Id: I37772a558a316b12e424f12ad3523cb0a048abe6
Signed-off-by: Tommy Carpenter <tc677g@att.com>
diff --git a/docs/conf.py b/docs/conf.py
index 974c309..5b443e9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,3 +1,12 @@
+import os
+import sys
 from docs_conf.conf import *
 
+sys.path.insert(0, os.path.abspath("../"))
+
+extensions = ["sphinx.ext.autodoc", "sphinx.ext.viewcode", "numpydoc"]
+
+# dont alphabetically order
+autodoc_member_order = "bysource"
+
 linkcheck_ignore = ["http://localhost.*", "http://127.0.0.1.*", "https://gerrit.o-ran-sc.org.*"]
diff --git a/docs/index.rst b/docs/index.rst
index 131716b..6ba4452 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -13,6 +13,7 @@
    overview.rst
    release-notes.rst
    installation-guide.rst
+   rmr_api.rst
 
 * :ref:`genindex`
 * :ref:`modindex`
diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt
index 09a0c1c..ff58333 100644
--- a/docs/requirements-docs.txt
+++ b/docs/requirements-docs.txt
@@ -3,3 +3,4 @@
 sphinxcontrib-httpdomain
 recommonmark
 lfdocs-conf
+numpydoc
diff --git a/docs/rmr_api.rst b/docs/rmr_api.rst
new file mode 100644
index 0000000..e3d5f0e
--- /dev/null
+++ b/docs/rmr_api.rst
@@ -0,0 +1,16 @@
+RMR
+====
+
+Overview
+--------
+The xapp framework repo includes a python submodule called `rmr`.
+This package (`ricxappframe.rmr`) is a CTYPES wrapper around the C rmr library.
+Most Xapp users will never use this package natively; however python apps that need access to the low level rmr API can use this package.
+Usage of this python package requires that you have the c rmr libraries installed.
+
+
+.. API
+.. ---
+
+.. .. automodule:: ricxappframe.rmr.rmr
+..   :members:
diff --git a/examples/rmr/README.md b/examples/rmr/README.md
new file mode 100644
index 0000000..671c9b1
--- /dev/null
+++ b/examples/rmr/README.md
@@ -0,0 +1,8 @@
+# Tests
+
+First, edit the `local.rt` file with your hostname.
+
+Start the receiver and the tester. Be sure to set `LD_LIBRARY_PATH` or your system equivelent to point to where the RMR .so files are. On my system (Arch Linux) they are as below. Also, `set -x` is fish shell notation, substitute for your shell.
+
+    set -x LD_LIBRARY_PATH /usr/local/lib/; set -x RMR_SEED_RT ./local.rt; python receive.py
+    set -x LD_LIBRARY_PATH /usr/local/lib/; set -x RMR_SEED_RT ./local.rt; python send.py
diff --git a/examples/rmr/local.rt b/examples/rmr/local.rt
new file mode 100644
index 0000000..84acffc
--- /dev/null
+++ b/examples/rmr/local.rt
@@ -0,0 +1,6 @@
+newrt|start
+rte|0|devarchwork:4560
+rte|1|devarchwork:4560
+rte|2|devarchwork:4560
+rte|99|devarchwork:4562
+newrt|end
diff --git a/examples/rmr/rcv_all.py b/examples/rmr/rcv_all.py
new file mode 100644
index 0000000..1db982f
--- /dev/null
+++ b/examples/rmr/rcv_all.py
@@ -0,0 +1,70 @@
+# vim: ts=4 sw=4 expandtab:
+# ==================================================================================
+#       Copyright (c) 2019 Nokia
+#       Copyright (c) 2018-2019 AT&T Intellectual Property.
+#
+#   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.
+# ==================================================================================
+
+#   Mnemonic:   rcv_all.py
+#   Abstract:   This example shows how to receive all queued messages into
+#               a bunch (an array of summaries).  RMR is initialised in multi-
+#               threaded call mode so that it will queue messages on a 2K ring
+#               and prevent the remote application(s) from blocking if we don't
+#               do timely receives.  Then we read 'bursts' of messages sleeping
+#               between reads to allow some message to pile up.
+#
+#               Because this programme does not send messages, there is no reason
+#               to wait for RMR to initialise a route table (no call to rmr_ready
+#               is needed.
+#
+#   Date:       26 September 2019
+#
+# ---------------------------------------------------------------------------------
+
+from rmr import rmr
+from rmr import helpers
+import time
+import sys
+import signal
+
+
+#    Ensure things terminate nicely
+#
+def signal_handler(sig, frame):
+    print('SIGINT received! Cleaning up rmr')
+    rmr.rmr_close(mrc)
+    print("Byeee")
+    sys.exit(0)
+
+listen_port = "4560".encode('utf-8')                                          # port RMR will listen on (RMR needs string, not value)
+mrc = rmr.rmr_init( listen_port, rmr.RMR_MAX_RCV_BYTES, rmr.RMRFL_MTCALL )    # put into multi-threaded call mode
+
+signal.signal(signal.SIGINT, signal_handler)    # cleanup on ctl-c
+
+while True:
+
+    # three calling options:
+    #mbunch = helpers.rmr_rcvall_msgs( mrc, [2, 4, 6] )     # get types 2, 4 and 6 only
+    #mbunch = helpers.rmr_rcvall_msgs( mrc, [2] )           # get types 2 only
+    mbunch = helpers.rmr_rcvall_msgs( mrc )                 # get all message types
+
+    if mbunch == None or  len( mbunch ) < 1:
+        print( "no messages" )
+    else:
+        print( "got %d messages" % len( mbunch ) )
+        for mb in mbunch:
+            print( "type=%d payload=%s" % (mb["message type"], mb["payload"] ) )
+
+    time.sleep( 1 )            # sleep to allow some to accumulate
+
diff --git a/examples/rmr/receive.py b/examples/rmr/receive.py
new file mode 100644
index 0000000..ae31309
--- /dev/null
+++ b/examples/rmr/receive.py
@@ -0,0 +1,54 @@
+# ==================================================================================
+#       Copyright (c) 2019 Nokia
+#       Copyright (c) 2018-2019 AT&T Intellectual Property.
+#
+#   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.
+# ==================================================================================
+from ricxappframe.rmr import rmr
+import time
+import sys
+import signal
+
+
+# Demonstrate NNG cleanup
+def signal_handler(sig, frame):
+    print("SIGINT received! Cleaning up rmr")
+    rmr.rmr_close(mrc)
+    print("Byeee")
+    sys.exit(0)
+
+
+# init rmr
+mrc = rmr.rmr_init("4560".encode("utf-8"), rmr.RMR_MAX_RCV_BYTES, 0x00)
+while rmr.rmr_ready(mrc) == 0:
+    time.sleep(1)
+    print("not yet ready")
+rmr.rmr_set_stimeout(mrc, 2)
+
+# capture ctrl-c
+signal.signal(signal.SIGINT, signal_handler)
+
+
+sbuf = None
+while True:
+    print("Waiting for a message, will timeout after 2000ms")
+    sbuf = rmr.rmr_torcv_msg(mrc, sbuf, 2000)
+    summary = rmr.message_summary(sbuf)
+    if summary["message state"] == 12:
+        print("Nothing received =(")
+    else:
+        print("Message received!: {}".format(summary))
+        val = b"message recieved OK yall!"
+        rmr.set_payload_and_length(val, sbuf)
+        sbuf = rmr.rmr_rts_msg(mrc, sbuf)
+    time.sleep(1)
diff --git a/examples/rmr/send.py b/examples/rmr/send.py
new file mode 100644
index 0000000..270d893
--- /dev/null
+++ b/examples/rmr/send.py
@@ -0,0 +1,66 @@
+# ==================================================================================
+#       Copyright (c) 2019 Nokia
+#       Copyright (c) 2018-2019 AT&T Intellectual Property.
+#
+#   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.
+# ==================================================================================
+import time
+import random
+import string
+import os
+import signal
+import sys
+from ricxappframe.rmr import rmr
+
+
+# Demonstrate NNG cleanup
+def signal_handler(sig, frame):
+    print("SIGINT received! Cleaning up rmr")
+    rmr.rmr_close(mrc)
+    print("Byeee")
+    sys.exit(0)
+
+
+# Init rmr
+mrc = rmr.rmr_init(b"4562", rmr.RMR_MAX_RCV_BYTES, 0x00)
+while rmr.rmr_ready(mrc) == 0:
+    time.sleep(1)
+    print("not yet ready")
+rmr.rmr_set_stimeout(mrc, 2)
+sbuf = rmr.rmr_alloc_msg(mrc, 256)
+
+# capture ctrl-c
+signal.signal(signal.SIGINT, signal_handler)
+
+while True:
+    # generate a random value between 1 and 256 bytes, then gen some random  bytes with several nulls thrown in
+    for val in [
+        "".join([random.choice(string.ascii_letters + string.digits) for n in range(random.randint(1, 256))]).encode("utf8"),
+        b"\x00" + os.urandom(4) + b"\x00" + os.urandom(4) + b"\x00",
+    ]:
+        rmr.set_payload_and_length(val, sbuf)
+        rmr.generate_and_set_transaction_id(sbuf)
+        sbuf.contents.state = 0
+        sbuf.contents.mtype = 0
+        print("Pre send summary: {}".format(rmr.message_summary(sbuf)))
+        sbuf = rmr.rmr_send_msg(mrc, sbuf)
+        print("Post send summary: {}".format(rmr.message_summary(sbuf)))
+        print("Waiting for return, will timeout after 2000ms")
+        sbuf = rmr.rmr_torcv_msg(mrc, sbuf, 2000)
+        summary = rmr.message_summary(sbuf)
+        if summary["message state"] == 12:
+            print("Nothing received yet")
+        else:
+            print("Ack Message received!: {}".format(summary))
+
+    time.sleep(1)
diff --git a/tox.ini b/tox.ini
index bfcc647..0a286bf 100644
--- a/tox.ini
+++ b/tox.ini
@@ -47,12 +47,15 @@
 whitelist_externals = echo
 skipsdist = true
 basepython = python3.8
+setenv =
+    LD_LIBRARY_PATH = /usr/local/lib/:/usr/local/lib64
 deps =
     sphinx
     sphinx-rtd-theme
     sphinxcontrib-httpdomain
     recommonmark
     lfdocs-conf
+    numpydoc
 commands =
     sphinx-build -W -b html -n -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/html
     echo "Generated docs available in {toxinidir}/docs/_build/html"
@@ -60,9 +63,12 @@
 [testenv:docs-linkcheck]
 skipsdist = true
 basepython = python3.8
+setenv =
+    LD_LIBRARY_PATH = /usr/local/lib/:/usr/local/lib64
 deps = sphinx
        sphinx-rtd-theme
        sphinxcontrib-httpdomain
        recommonmark
        lfdocs-conf
+       numpydoc
 commands = sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/linkcheck