From 6bda360afaca968bcc83a1ea56c29e84d36ad9d3 Mon Sep 17 00:00:00 2001
From: Brennan Miller-Klugman <millerklugmanb@wit.edu>
Date: Mon, 4 Oct 2021 15:43:38 -0400
Subject: [PATCH 1/2] Created working persistant queue

---
 src/database/app.py                           |  67 ++++
 .../queueController.cpython-38.pyc            | Bin 0 -> 9385 bytes
 ...eController.cpython-38.pyc:Zone.Identifier |   3 +
 src/database/controllers/queueController.py   | 340 ++++++++++++++++++
 .../queueController.py:Zone.Identifier        |   3 +
 src/database/databases/queue.db               | Bin 0 -> 57344 bytes
 .../databases/queue.db:Zone.Identifier        |   3 +
 src/database/templates/dataViewer.html        | 236 ++++++++++++
 src/database/templates/settings.html          | 142 ++++++++
 src/message_queue_node.py                     |  24 ++
 src/packet_dispatch_node.py                   |   6 +-
 11 files changed, 823 insertions(+), 1 deletion(-)
 create mode 100755 src/database/app.py
 create mode 100644 src/database/controllers/__pycache__/queueController.cpython-38.pyc
 create mode 100644 src/database/controllers/__pycache__/queueController.cpython-38.pyc:Zone.Identifier
 create mode 100755 src/database/controllers/queueController.py
 create mode 100644 src/database/controllers/queueController.py:Zone.Identifier
 create mode 100644 src/database/databases/queue.db
 create mode 100644 src/database/databases/queue.db:Zone.Identifier
 create mode 100644 src/database/templates/dataViewer.html
 create mode 100644 src/database/templates/settings.html

diff --git a/src/database/app.py b/src/database/app.py
new file mode 100755
index 00000000..47763cda
--- /dev/null
+++ b/src/database/app.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+from controllers.queueController import *
+from flask import Flask, render_template, jsonify, request, redirect, url_for
+
+import rospkg
+import os
+
+import rospy
+
+rospack = rospkg.RosPack()
+
+UPLOAD_FOLDER = os.path.join(rospack.get_path('helpful_tools'), 'src/uploadedFiles')
+ALLOWED_EXTENSIONS = {'txt', 'py'}
+
+app = Flask(__name__)
+global commandEnter
+global PythonEnter
+
+app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
+def allowed_file(filename):
+    return '.' in filename and \
+           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
+
+@app.route("/", methods=["GET", "POST"])
+def dataViewer(): #dataviewer is the main page of the web application            
+    return render_template("dataViewer.html") #display templates/dataViewer template
+
+@app.route("/settings", methods=["GET", "POST"])
+def settings(): #dataviewer is the main page of the web application   
+    if request.method == "POST": #on post send form data to either commandEnterInterface or pythonController nodes
+        try:
+            if(request.form.get('confirm' )== "on"):
+                Queue.resetTable()
+        except:
+            print("Error: Invalid Entry")
+    return render_template("settings.html") #display templates/dataViewer template
+
+@app.route("/update", methods=['POST']) #update endpoint used to fresh database on a timeout
+def update():
+
+    data = queueDB.returnTable()
+
+    formatData = []
+
+    for command in data: #format data as dict which will be sent as a JSON
+        formatCommand = {"id": command.identifier, "message_raw": command.message_raw, "message_type": command.message_type,
+                         "posistion": command.posistion, "direction": command.direction}
+        formatData.append(formatCommand)
+    return jsonify(formatData)
+
+
+if __name__ == '__main__':
+    #Clean temp file directory
+    for file in os.listdir(UPLOAD_FOLDER):
+        os.remove(os.path.join(UPLOAD_FOLDER, file))
+
+    #DANGER
+    #This is test code used to reset databases, only to be used in test env
+    #Queue.drop_table()
+    
+    #Queue.drop_table()
+
+    queueDB = Queue()
+    #Start flask application 
+    app.run(host='0.0.0.0', port=8000)
+
+
diff --git a/src/database/controllers/__pycache__/queueController.cpython-38.pyc b/src/database/controllers/__pycache__/queueController.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1717650b59a16cd55e5a3fc6dd390ca4543af134
GIT binary patch
literal 9385
zcmcIqOK%+4m9AG;S3lUKNRbj{$tuaRt#%yIm`o-!iN~V{^{^v#6p4<V$~Zm6zL#W^
z{o<`^$!d_Eg}e&{WHoDQ$@T2!7t9aHs#XC87{Hk2ECwS4P`-2O(OpdvG7zL1bsu#f
zb<erqdE8U|`OHjN!}T9u{KntArfL60mC4IS<vQ-5s%x6igx=A*ny2YhHadFO@C+`S
z9kXkB7MHC~VU5}g9ow@xFM37J9nV2-cS_x|SLVKjPQ|Op;z9ML=FLcZyLK=uXAb5>
z@ue=Dmxgyr&dXEJb#LLWCQ73GttQIy^mEf&M7<)as8{78>Px84h#KlOuAf1DR?MM3
z$Mv(QpAz$^&vSiQo)Zf@#_x6I$c2Nq<dR&LXXTkq>!q%1a_PC|otMi<FUYe<-<D^P
zUX<q#+?Paq;jvaf{T=bCu18kb?n>m&F9u<|-}5^t7jO3a9qIQ_)IVq-J=K*#;BU%i
ztKWMfRVbBLR{fyqxBA^~FuEA1){5{$f87scRtQ#hhjJ*diS-t}Yw|KtxsE$HheT?g
zE;P>ojk+*Eqw(DEOkrY`R#du)DIfHO>>QZ{TN+O?H!+DcJxk~qYK&^x&}$E5=r`(x
z$Z0lvepfb|QMuXd_QkM6<!ZCJJM=qAiy_vr&j~SynyO-UPF_7)+3I)Y%DR%hp5I$(
z`Qc8x*L)hR5cy+va5bG^1sn@iztfQ_;m57)!L`A&$fBh!;T3^_#L-m^S)*<#hhAHv
zgdon3$4iMzGt^K-vWPn!PxT|L%J}^mn3nQen#AuHx@XBkQnIsBF)KM)zf$(BoIR^#
zrE1nXBWuZgvsq~_E1k+ljAx$Do-JgvoX$#%S!qeUCoEC;R`<>bTNJ<5ytBd)CFIMZ
zEGo#)iK>`E{+6hTS>)%%oH&L2f|wTz$ln&H#Uk>HVo97q?uxTw8Tln~PP~QuvN$g;
zAb&@^EiNLzB3y9^`Mct>cnA4=;)-||`TLB|_oKou3FB*r;9_ss=`>me@ISq1FGvO5
z!X0cN89fTM1O278s(p2HA57o3_YC#np0QWhHg-()VQ3y$!XP2uE#p}sxQEo<(|0U&
zkK4?+4ebr|u)okAL!jyRYY5L{?MqJU*65o}88&<J>#&(hZqW4!gw1fv?={!kVc;qm
z4plF3!!7AjS2yYEwtM`HrPqDh4!2z2#R#|6ANE2wnTWc?{eppPwKv*QxC387x}Y5z
zqjRh6fP{)0e(DMtgiT)v1wAsV=i9=5-|hHnQ-0|7`tFAEH@mVI`lOBOMKueyMRp)N
zvK2-a%@Y+MYlCN=)9G&txjx*C7C>76X)`x8s&r&;Gu&cY>&3{z6dPVOXpdwQQcE20
zs*}r#ssq2Z1GcrGZCc)ZYfH9vno9buEq}e;X@}1u^NHW_s*`M;5J{58=<=KS4m%a=
zJ<T%os%{xIqpTbHoKC52;HQtSGODh<d9oHM!So_2r<>vCq5y#D8Q^OB#-6@sY#Tq(
z_VwNBUaTa41V(^j+SqpB4g>6B*iUwvQR272?Z5?xQ+x!9URpPKYt$)}6)7M*AUzfp
zcs6yGo@csKF?UMY%U01Ekc!hx%c$yAV>BC+ob@=Fva1-CqihM3fi7X}7z%U=bAm!^
z^jRtaCs0Y04SN9~ml5bDL`&GZXW+-6-EzZc1IdKn`EHv0s1ho_7j)ZUC`G~sugI^H
z>R3k1<kr+6X0Rh;T0le@ztKX>j$FSMnTYhFvW1&B`#cKqMjsfVwrxUVK#Lq$Z0_TY
zzO7`p|3p5B4f*6|!?r?ZT|Xs15&53m7GMequyXqwsQt?CG!6@iM8>0{!qY9OWK<sa
zjf(PX*&2rO&`1EmBd4)2lUvUhARr)BshN)MyiUo_^~oWE)NF?JFHs>x2xA}QuWDbN
z+c)>jZJiZol}h_MQnc<?NsY1szPxYkS=&GkQ1cN=1z{#7+kirStnGdz4Dvxnk0FN*
zD9B@YhnA!IlT;>jsP874v6XR_K;*Js{q8lc#vLdodyViFM9x69`-;>|HQjZ_94SDS
zvZw@aYe0J?qS>^I?2)<>^#b$St3eM!MLtZX@)q;;2aoTrVF{7h4K|MjW-U+ZS9o`D
z8i{6Dx}`fnrmZ^=SjOn-OiN90=Pv^3gBILQb-%sQPk0?12UG|wfT`LtV5l;yTkuMK
zloGzMxWeO$b(9MN)FnzjpyVAS^%$I9B^f|$nTF`8BdgiLNOrU|b95%A{z#vb8Su9l
z9cp{}w*DLzJ_KYrH?~b-2=fKxmD)mMyTH<Gv-ARpb*nL&zjyo5ZFlv?s>_9YH*P;#
ztLy3qL`pF#06V=fGTI`M&fx$KsEld8j6OM<%L&bp=V_9QU0?0oxb^b^5z6w2t#<U$
zOrnnB)|@1gHat-giAhC7(qxW49`pzI<wnllBr1qJkq$L=`$6c!*bXK9fqr-Fj<5!9
zsEc^#q0W#$LP0Y9kSJh<X{M`BT8^xqbjdC1?jp&lQH^v3Z$@E4m41SW9<?{OP9i~Z
z+le$Z>h?4&X^Wy+$liTF2tUQf`C(u2o+$#&G>uNWfDsyFB5~Y_w<v9Dk#<ZkDrZ!Z
z{e+Q#FCcV)&In;Hwyozn<<H~&imB!Odi8mXrM1Mwxf{b?i+r<5$&9<WzMCF<SU{h>
z59cx+7Vl=}Ap*M>u#Suue}f9cH8O)xkuUbF)At4YX)$<X_d@*;9lgxp9s}W8e!btI
ze~e_Pt-05uL}}$a<(Nfa&Hzo`8k>|W`(_A(0yeQJAx0?+p1awEsfjJ^ZgTQee~&?#
z^7#i;qEyW^mH$-z6i+-W@SjMW^T=mPh)QTCx63Q+(z#-K<7eV!Ka834977W)%F*Yc
znNzcw>y@L84wQ5%xkW?&6Um--puL19I-~7F3+-FN+%JRx1)IoobUxX$x6K_}okwoL
zWZK(>{o?NVJxf^Nz&D|t^j$(<d%L(-#8aGFgbpXHu*)UP?S%HWvj>1-K1URU{i2|2
zy*qe&X%E2?Xv5>?`F%DImvZwI$Mdk6F24Hsh7iZ1vjry}4o(i6WIW*LlE#TSO)gYJ
zy^l1qHei4d5E+J>{dR8?R)kgP$7o{%5|sx1pdFA9L?zKyIGLb$SXO^WJxIJ_d!5;F
ziY!Ehz7lW;c`CN)WQ!s@UYuG%rCy31redO>BL`->$xgt#H0f;`;ILmwxF-)gswI6N
zVx`a<5S(;r$B2f56Br&3<?k>wAQ);UP9QjgkVPlU?!^A5;ouZv#J@i|#d6}6PCiZb
zO*&<Ztp!bqi~N3aXc=aIKw$!AHegl+%$y0Bl>m!U0<#ieRz$6^Uk1#I46|=1;88+b
zaj(oUa~Nh0V1^RlQDK<jz>N7Sq5!~IfRO#d0od*{*veC28_)J{GzUQI>~bkLTX}l6
z7;@?pkfz4SQU65s>qzR(6lT;7YPyLeDpIIuu(KJJ`DDQnsmR`vKEZ=HR<Fid;Vuoi
zha?WRVF)(Qn;DOyYAGH_yPbhVeM%$w1ojz~eoo2MS*+p@2C^sEX#6|cgF8sR2OMHh
z{J&E^1{6u#=u~WqCf<;<xdy!mH=|>Gbb;Sq!+8~_)NPX-qh0LBW9`rwee%H?d|LNT
zVt78tj;W#@3_AWZKAb)wTxSj;$#p946iv&VX!Q|Z%%&$fp3p(9+x2^5nnBfM_BDUK
zBmam|0T~72&}crUZ?Z#<KyrzQNG8xhA$BU@{^+ACk7THD-ozOj0^17dXcb2{uGTZ{
z1@Cmc;^RDkN*ui5wf#3<5IX^8%K3@b+`@?K8Ry?aC3lWK9iO9<Qxi_qX`JBDc(rm@
zB4k8t-GX;R+tE(kl*CU<f<`IRS(D~s1efu;!`O&>MVf>l%NWfgleOso5KW{(=-@%h
z2|nmz%=IZRDMw$9@e~$Ly}8Vl)*I=fTr{8TVwDl8k|Fc=f6+1KuRfZK*D!9Zn~la=
z{pwV>HmZJ#&E1shPFr>atAePsh9hKLXG`)Sy`OA=nx}-cF~?C@Q+SKHU{(`u6k=0Q
z?@44np64`;AvcQ80jyoT*+A|NaVnI}-mtq4jY81{^?;IJP_j(PTa>&_34uV7lfxEB
z{fJ6GrsOA-{EU)+q~ty&4=H&}$r>eW?!Khbcn7&e!5#+iITQj?K@MVEZ~o!f{kpv5
zl%0}eJ2j`kKMSejTy=hkXDIQ!Elioa2-Mec2mg#@9N@-h4=W2T7o?qprHk1!N0yRj
z<*c<LOkp9!TO~gQ`HUzE2YF4DAi-re@N0_Dl?(P3@E~)oTvXV{*2p~~+r%~r_6QMo
zxIXdMjaRF%p0{z7eU?eS8~XzYxViY8(vh(v?b3%8;lk<8yzk7D4%h&tPRc4?tm;Uj
zQk%Zdgl)vI$Z;Utvui?np0_TI8Dy~pa#P5pRMJQURjS!ERCCygA;}$YIfwShwO~qK
zWBSA?o!1S`cs-hp102`V9yy66HJNFoH`xO9OZ0{|&s?lnn={Rih^+jg7^-0QgyvpI
z)^eiirnO}2`TiOb3j0^I08&6Hqd784T2E1QYkF-YJQZ5ol$KjcRyd{R8ui&J9ix6t
zv-13`MLeoz+pm5@Rf^y6?yKKYiA9&CcFd@;z!F#g4|hQN$bmbU39JFpvzhBHH03VZ
zzw5XI(rHtISAh80(nJb@LkfFN-}k&yB4Fi2z$&5$!E&M!+}+zx5ZVb&j-iYpa(tu{
z?!w(TYB(iV@xv44iY(jsLq;6ygn%?bm2xS$L<w{I9V%U+WXwgD0T^WpvGR+TX=`nC
zN&=dT8Ew}ldL2<9G~yQSU<nB;5OQTnZRjuP^E8g+u%V>nAO^e|+5mhX=?@h`V6<}$
zV3C(if_|991!u<bSrX$See|V5DIUnr=wrxH$!6qSBx=Z!A!=Bt=g0IME7v4LbTcvE
zUyju07y|)f0^Te@?`8sIW^TgrcxBTvbXYx6hP=`mSQ496VyS9T!j{>m63fqtqC?AF
zptaOcAkpDpEH>0eljSaA&2`+teI#SCNo>*N2if!^?S#!r#HW;qPdTwqmDoN-Gj}FG
zp(U1zXi6_CTex{|-Xu`!U(gehuz~FRN`fMm{h0Vccupi>Ik&98R0`BOCI-@ZS$9xY
zf|9&M@~-`i*1<~F#F-X;IZV=0el33u1oOh)jNlvN)ny32kYC+2ij~Y$I@aLy&J~(4
zhGC+=V;E8!{r{nhD0#D4zoZBSk&WmALL7?l=*@iH?WjTPTC3BB5>^Be&mKtmRLaQc
z2cAveU3WG;Ydh%oyfge2Hv7Ju{WC<_7^fC!aPd(;cnHVUqa!bUU5%`PA8tj~Hlh`t
z1HzhA_lm1Gn-6cS-ScXXck!WBt|tG!P!*b`z<>YXKRU#xA~yf5A(+Xem%N$SZ)&pB
z6huY%z(cuu)0^Fx6b3w~Wa<HxBA=yKZ^o8!44#aok@Io<H<3?>LjfJd@U;>@e5K+a
fN(h$JbmO&UI_6wq?q9Xv&Yh=U*`$zMtO))L_H<=A

literal 0
HcmV?d00001

diff --git a/src/database/controllers/__pycache__/queueController.cpython-38.pyc:Zone.Identifier b/src/database/controllers/__pycache__/queueController.cpython-38.pyc:Zone.Identifier
new file mode 100644
index 00000000..7ae860cb
--- /dev/null
+++ b/src/database/controllers/__pycache__/queueController.cpython-38.pyc:Zone.Identifier
@@ -0,0 +1,3 @@
+[ZoneTransfer]
+ZoneId=3
+ReferrerUrl=C:\Users\brenn\Downloads\ros_acomms-dev-dbQueue.zip
diff --git a/src/database/controllers/queueController.py b/src/database/controllers/queueController.py
new file mode 100755
index 00000000..46478a02
--- /dev/null
+++ b/src/database/controllers/queueController.py
@@ -0,0 +1,340 @@
+#!/usr/bin/env python3
+
+from time import time
+from typing import Optional
+from xmlrpc.client import Boolean
+from peewee import *
+import os
+import rospkg
+import json
+from rospy_message_converter import message_converter
+import rospy
+
+rospack = rospkg.RosPack()
+
+DB_PATH = os.path.join(rospack.get_path('ros_acomms'),
+                       'src/database/databases/queue.db')
+
+db = SqliteDatabase(DB_PATH)  # database location
+
+
+class BaseModel(Model):
+    class Meta:
+        database = db
+
+
+class Queue(BaseModel):  # database model
+
+    identifier = IntegerField(null=True)  # Unique ID
+    message_raw = TextField(null=True)
+    message_encoded = TextField(null=True)
+    message_type = TextField(null=True)
+    dest = IntegerField(null=True)
+    payload_bits = TextField(null=True)
+    length_bits = IntegerField(null=True)
+    posistion = IntegerField(null=True)  # Pos in queue (relative to topic)
+    fragmentation_tracker = TextField(null=True)
+    allow_fragmentation = BooleanField(null=True)
+    transmitted = BooleanField(null=True)  # Transmitted state
+    completed = BooleanField(null=True)  # Transmission completed
+    message_type = IntegerField(null=True)  # Corresponds to message table
+    direction = IntegerField(null=True)
+    sequence_number = IntegerField(null=True)
+    topic_name = TextField(null=True)
+    ros_pkg = TextField(null=True)
+    header = TextField(null=True)
+    def get_next_message_smaller_than_bits(self, size_in_bits, dest_address=None, packet_codec=None,
+                                           check_reachability=True):
+        '''get_next_message_smaller_than_bits returns the next message in the queue with a bit count smaller then the specified parameter'''
+
+        try:
+            for val in Queue.select():
+                next_message = None
+
+                if dest_address and (dest_address != val.dest):
+                    # Move on to check the next message
+                    rospy.logdebug("Disqualified: dest_address")
+                    continue
+                if not val.allow_fragmentation and val.length_bits > size_in_bits:
+                    rospy.logdebug("Disqualified: too large, no fragmentation")
+                    continue
+                break
+
+            return next_message
+
+        except:
+            return None
+
+    def bit_count(self):
+        '''bit_count is used to count bits across all messages'''
+
+        count = 0
+
+        for val in Queue.select():
+            count += val.length_bits
+
+        return count
+
+    def message_count(self):
+        '''message_count is used to count all unsent messages across every topic type'''
+
+        counter = 0
+        for val in Queue.select():
+            if (val.transmitted == False):
+                counter += 1
+        return counter
+
+    def removeMessage(self, idVal):
+        '''removeMessage is used to delete a message with an identifier of idVal'''
+
+        Queue.delete().where(
+            Queue.identifier == idVal).execute()
+
+    def getNextMessage(self):
+        '''getNextMessage is used to get the next message within a specific message type queue'''
+        lowestPriority = -1
+        lowestPriorityMSGType = None
+        for msg in Topics:
+            if(msg.priority > lowestPriority):
+                lowestPriority = msg.priority
+                lowestPriorityMSGType = msg.message_type
+
+        for val in Queue.select():
+            if(val.message_type == lowestPriorityMSGType):
+                if(val.completed == False):
+                    return val.message_encoded
+
+    def clearLifoMessages(self, messageType):
+        '''clearLifoMessages is used to delete all entries within a certain message type'''
+
+        Queue.delete().where(Queue.message_type == messageType).execute()
+
+    def markACK(self, messageVal):
+        print(messageVal.id)
+        print("HERE DAD HERE HAER")
+        Queue.update(completed = True).where(messageVal.id == Queue.identifier).execute()
+
+    def popLeft(self):
+        '''popLeft is used to delete the left most value from the queue'''
+
+        Queue.delete().where(Queue.identifier == 0).execute()
+
+    def popRight(self):
+        '''popRight is used to delete the right most value from the queue'''
+        Queue.delete().where(Queue.identifier == self.getLastIterator()).execute()
+
+    def updateTransmit(self, msg, transmitVal):
+        '''updateTransmit function is used to update a database entry's transmit value parameter'''
+        Queue.update(transmitted=transmitVal).where(
+            str(msg.payload_bits) == str(msg)).execute()
+
+    def updatePayload(self, msg, payloadbits):
+        '''updateTransmit function is used to update a database entry's transmit value parameter'''
+
+        for queue in Queue:
+            if(str(msg) == str(queue.message_raw)):
+                queue.payload_bits=payloadbits
+                queue.save()
+    
+    def addValue(self, message, msg_type):
+        '''Add function is used to create database entries to the queue'''
+
+        idVal = self.getLastIterator() + 1
+        order = None
+        countVal = -1
+
+        for val in Topics.select():
+            if (msg_type in val.message_name):
+                order = val.order
+                messagePointer = val.identifier
+
+        if(order == 'fifo'):
+            for val in Queue.select():
+                if (val.message_type == messagePointer):
+                    countVal += 1
+            
+            posistionVal = countVal + 1
+                    
+            Queue.create(identifier=idVal,
+                        message_raw=message,
+                        message_type=msg_type,
+                        posistion = posistionVal,
+                        direction = "Outgoing"
+                        )
+        else:
+            self.clearLifoMessages(messagePointer) #clear all messages within specified type
+            for val in Queue.select():
+                if (val.message_type == messagePointer):
+                    countVal += 1
+            posistionVal = countVal + 1
+ 
+            Queue.create(identifier=idVal,
+                        message_raw=message,
+                        message_type=messagePointer,
+                        posistion = posistionVal,
+                        direction = "Outgoing"
+
+                        )
+
+    def appendQueue(self, message, msg_type, ros_pkgVal, topic_nameVal,headerVal):
+        '''Add function is used to create database entries to the queue'''
+
+        idVal = self.getLastIterator() + 1
+        order = None
+        countVal = -1
+
+        for val in Topics.select():
+            if (msg_type in val.message_name):
+                order = val.order
+                messagePointer = val.identifier
+
+        if(order == 'fifo'):
+            for val in Queue.select():
+                if (val.message_type == messagePointer):
+                    countVal += 1
+            
+            posistionVal = countVal + 1
+                    
+            Queue.create(identifier=idVal,
+                        message_raw=message,
+                        message_type=msg_type,
+                        posistion = posistionVal,
+                        direction = "Outgoing",
+                        ros_pkg = ros_pkgVal,
+                        topic_name = topic_nameVal,
+                        header=headerVal
+                        )
+        else:
+            self.clearLifoMessages(messagePointer) #clear all messages within specified type
+            for val in Queue.select():
+                if (val.message_type == messagePointer):
+                    countVal += 1
+            posistionVal = countVal + 1
+ 
+            Queue.create(identifier=idVal,
+                        message_raw=message,
+                        message_type=messagePointer,
+                        posistion = posistionVal,
+                        direction = "Outgoing",
+                        ros_pkg = ros_pkgVal,
+                        topic_name = topic_nameVal,
+                        header=headerVal
+                        )
+
+    def displayTable(self):
+        '''*Test Function* used to display all values within the database'''
+
+        for command in Queue.select():
+            print(command.transmitted)
+
+    def returnTable(self):
+        '''Retruns contect of select() function'''
+
+        return Queue.select()
+
+    def getLastIterator(self):
+        '''Gets the highest iterator value in the database'''
+        highVal = -1
+        for val in Queue.select():
+            if(val.identifier > highVal):
+                highVal = val.identifier
+        return highVal
+
+    def resetTable(self):
+        Queue.delete().execute()
+
+
+class Topics(BaseModel):  # Gets created at yaml read
+    identifier = IntegerField()
+    message_type = IntegerField(null=True)
+    message_name = TextField(null=True)
+    priority = IntegerField(null=True)
+    is_active = BooleanField(null=True)
+    order = TextField(null=True)
+
+    def addEntry(self, message_nameVal, priorityVal, is_activeVal, orderVal):
+        '''addEntry function creates a table entry based on function parameters'''
+
+        Topics.create(identifier = self.getLastIterator() + 1, message_name=message_nameVal, priority=priorityVal,
+                      is_active=is_activeVal, order=orderVal)
+
+    def displayTable(self):
+        '''*Test Function* used to display all values within the database'''
+
+        for command in Topics.select():
+            print(command.message_name)
+
+    def getLastIterator(self):
+        '''Gets the highest iterator value in the database'''
+        highVal = 0
+        for val in Topics.select():
+            if(val.identifier > highVal):
+                highVal = val.identifier
+        return highVal
+
+class msgEvents(BaseModel):
+    identifier = IntegerField()
+    time = TimeField()
+    source = IntegerField()
+    dest = IntegerField()
+
+    def removeEntry(self, idVal):
+        '''removeEntry function removes a table entry based on the specified idVal'''
+
+        msgEvents.delete().where(
+            msgEvents.identifier == idVal).execute()
+
+    def addEntry(self, identifierVal, timeVal, sourceVal, destVal):
+        '''addEntry function creates a table entry based on function parameters'''
+
+        msgEvents.create(identifier=identifierVal, time=timeVal,
+                         source=sourceVal, dest=destVal)
+
+    def getLastIterator(self):
+        '''Gets the highest iterator value in the database'''
+
+        highVal = -1
+        for val in msgEvents.select():
+            if(val.identifier > highVal):
+                highVal = val.identifier
+        return highVal
+
+
+class Fragmentation(BaseModel):
+    identifier = IntegerField(null=True)
+    time = TimeField(null=True)
+    source = IntegerField(null=True)
+    dest = IntegerField(null=True)
+
+    def removeEntry(self, idVal):
+        '''removeEntry function removes a table entry based on the specified idVal'''
+
+        Fragmentation.delete().where(
+            Fragmentation.identifier == idVal).execute()
+
+    def addEntry(self, identifierVal, timeVal, sourceVal, destVal):
+        '''addEntry function creates a table entry based on function parameters'''
+
+        Fragmentation.create(identifier=identifierVal,
+                             time=timeVal, source=sourceVal, dest=destVal)
+
+    def getLastIterator(self):
+        '''Gets the highest iterator value in the database'''
+
+        highVal = -1
+        for val in Fragmentation.select():
+            if(val.identifier > highVal):
+                highVal = val.identifier
+        return highVal
+
+
+if __name__ == '__main__':
+    '''This script can be ran standalone to create DB tables and check that classes are properly working'''
+    #db.drop_tables([Queue, Fragmentation, msgEvents, Topics])
+    db.create_tables([Queue, Fragmentation, msgEvents, Topics])
+    queueDB = Queue()
+    fragmentationDB = Fragmentation()
+    msgEventsDB = msgEvents()
+    topicDB = Topics()
+
+    queueDB.displayTable()
diff --git a/src/database/controllers/queueController.py:Zone.Identifier b/src/database/controllers/queueController.py:Zone.Identifier
new file mode 100644
index 00000000..7ae860cb
--- /dev/null
+++ b/src/database/controllers/queueController.py:Zone.Identifier
@@ -0,0 +1,3 @@
+[ZoneTransfer]
+ZoneId=3
+ReferrerUrl=C:\Users\brenn\Downloads\ros_acomms-dev-dbQueue.zip
diff --git a/src/database/databases/queue.db b/src/database/databases/queue.db
new file mode 100644
index 0000000000000000000000000000000000000000..82f58f13e7a7db151df79521b25d51c180cd44b9
GIT binary patch
literal 57344
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

literal 0
HcmV?d00001

diff --git a/src/database/databases/queue.db:Zone.Identifier b/src/database/databases/queue.db:Zone.Identifier
new file mode 100644
index 00000000..7ae860cb
--- /dev/null
+++ b/src/database/databases/queue.db:Zone.Identifier
@@ -0,0 +1,3 @@
+[ZoneTransfer]
+ZoneId=3
+ReferrerUrl=C:\Users\brenn\Downloads\ros_acomms-dev-dbQueue.zip
diff --git a/src/database/templates/dataViewer.html b/src/database/templates/dataViewer.html
new file mode 100644
index 00000000..fa0a79fe
--- /dev/null
+++ b/src/database/templates/dataViewer.html
@@ -0,0 +1,236 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
+    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
+
+    <style>
+        div.fixed {
+            position: fixed;
+            left: 0;
+            bottom: 0;
+            width: 100%;
+        }
+        
+        .ButtonClass {
+            font-size: 16px;
+            width: 10%;
+            background-color: #5865f2;
+            color: white;
+            border: none;
+            float: right;
+            position: absolute;
+            right: 0;
+            bottom: 0;
+        }
+        
+        .form-select {
+            color: black;
+            height: 10vh;
+            width: 20%;
+            float: right;
+            position: absolute;
+            left: 0;
+            bottom: 0;
+        }
+    </style>
+    <title></title>
+</head>
+
+<body>
+    <style>
+        body {
+            background-color: #23272a;
+            overflow: hidden;
+            margin: 0;
+            padding: 0;
+            height: 100%;
+            width: 100%;
+            font-family: Arial, Helvetica, sans-serif;
+        }
+        
+        .navbar {
+            overflow: hidden;
+            background-color: #2c2f33;
+        }
+        
+        .navbar a {
+            float: left;
+            font-size: 16px;
+            color: white;
+            text-align: center;
+            padding: 14px 16px;
+            text-decoration: none;
+        }
+        
+        .dropdown {
+            float: left;
+            overflow: hidden;
+        }
+        
+        .dropdown .dropbtn {
+            font-size: 16px;
+            border: none;
+            outline: none;
+            color: white;
+            padding: 14px 16px;
+            background-color: inherit;
+            font-family: inherit;
+            margin: 0;
+        }
+        
+        .navbar a:hover,
+        .dropdown:hover .dropbtn {
+            background-color: #5865f2;
+        }
+        
+        .dropdown-content {
+            display: none;
+            position: absolute;
+            background-color: #f9f9f9;
+            width: 120px;
+            box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
+            z-index: 1;
+        }
+        
+        .dropdown-content a {
+            float: none;
+            color: black;
+            padding: 12px 16px;
+            text-decoration: none;
+            display: block;
+            text-align: left;
+        }
+        
+        .dropdown-content a:hover {
+            background-color: #ddd;
+        }
+        
+        .dropdown:hover .dropdown-content {
+            display: block;
+        }
+        
+        .test {
+            height: 100vh;
+        }
+        
+        a:link {
+            text-decoration: none;
+        }
+        
+        a:visited {
+            text-decoration: none;
+        }
+        
+        #table-wrapper {
+            position: relative;
+        }
+        
+        #table-scroll {
+            height: 95vh;
+            overflow: auto;
+            margin-top: 20px;
+        }
+        
+        #table-wrapper table {
+            width: 100%;
+        }
+        
+        #table-wrapper table * {
+            color: white;
+        }
+        
+        #table-wrapper table thead th .text {
+            position: absolute;
+            top: -20px;
+            z-index: 2;
+            height: 20px;
+            width: 35%;
+        }
+        
+        th,
+        td {
+            text-align: left;
+        }
+        
+        tr:nth-child(even) {
+            background-color: #2c2f33;
+        }
+        
+        input:focus {
+            outline: none !important;
+        }
+    </style>
+
+    <div class="navbar">
+        <a href="#">Home</a>
+        <a href="/settings" style="float:right"><i class="fa fa-cog"></i></a>
+
+
+    </div>
+    <div id="table-wrapper">
+        <div id="table-scroll">
+            <table id="myTable">
+                <thead>
+                    <tr>
+                        <th>ID</th>
+                        <th>Raw Message</th>
+                        <th>Message Type</th>
+                        <th>Queue Position</th>
+                        <th>Direction</th>
+                    </tr>
+                </thead>
+                <tbody></tbody>
+            </table>
+        </div>
+    </div>
+    <script>
+        setInterval(function() {
+            $.ajax({
+                url: "/update",
+                type: "POST",
+                success: function(response) {
+                    console.log(response);
+                    for (commands in response) {
+                        try {
+                            var table = document.getElementById("myTable");
+                            var x = table.rows[response[commands].id + 1].cells[0];
+
+                            var updateVal = response[commands].id + 1;
+                            table.rows[updateVal].cells[0].innerHTML = response[commands].id;
+                            table.rows[updateVal].cells[1].innerHTML = response[commands].message_raw;
+                            table.rows[updateVal].cells[2].innerHTML = response[commands].message_type;
+                            table.rows[updateVal].cells[3].innerHTML = response[commands].posistion;
+                            table.rows[updateVal].cells[4].innerHTML = response[commands].direction;
+
+                        } catch (error) {
+                            var table = document.getElementById("myTable");
+                            var row = table.insertRow(
+                                document.getElementById("myTable").rows.length
+                            );
+                            var id = row.insertCell(0);
+                            var message_raw = row.insertCell(1);
+                            var message_type = row.insertCell(2);
+                            var posistion = row.insertCell(3);
+                            var direction = row.insertCell(4);
+
+                            id.innerHTML = response[commands].id;
+                            message_raw.innerHTML = response[commands].message_raw;
+                            message_type.innerHTML = response[commands].message_type;
+                            posistion.innerHTML = response[commands].posistion;
+                            direction.innerHTML = response[commands].direction;
+                        }
+                    }
+                },
+                error: function(error) {
+                    console.log(error);
+                },
+            });
+        }, 1000);
+    </script>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/src/database/templates/settings.html b/src/database/templates/settings.html
new file mode 100644
index 00000000..b1e32332
--- /dev/null
+++ b/src/database/templates/settings.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
+    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
+    <title></title>
+</head>
+
+<body>
+    <style>
+        body {
+            background-color: #23272a;
+            overflow: hidden;
+            margin: 0;
+            padding: 0;
+            height: 100%;
+            width: 100%;
+            font-family: Arial, Helvetica, sans-serif;
+        }
+        
+        .navbar {
+            overflow: hidden;
+            background-color: #2c2f33;
+        }
+        
+        .navbar a {
+            float: left;
+            font-size: 16px;
+            color: white;
+            text-align: center;
+            padding: 14px 16px;
+            text-decoration: none;
+        }
+        
+        .dropdown {
+            float: left;
+            overflow: hidden;
+        }
+        
+        .dropdown .dropbtn {
+            font-size: 16px;
+            border: none;
+            outline: none;
+            color: white;
+            padding: 14px 16px;
+            background-color: inherit;
+            font-family: inherit;
+            margin: 0;
+        }
+        
+        .navbar a:hover,
+        .dropdown:hover .dropbtn {
+            background-color: #5865f2;
+        }
+        
+        .dropdown-content {
+            display: none;
+            position: absolute;
+            background-color: #f9f9f9;
+            width: 120px;
+            box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
+            z-index: 1;
+        }
+        
+        .dropdown-content a {
+            float: none;
+            color: black;
+            padding: 12px 16px;
+            text-decoration: none;
+            display: block;
+            text-align: left;
+        }
+        
+        .dropdown-content a:hover {
+            background-color: #ddd;
+        }
+        
+        .dropdown:hover .dropdown-content {
+            display: block;
+        }
+        
+        .test {
+            height: 100vh;
+        }
+        
+        a:link {
+            text-decoration: none;
+        }
+        
+        a:visited {
+            text-decoration: none;
+        }
+        
+        hr.solid {
+            border-top: 1px solid #999;
+            width: 50%;
+            position: relative;
+        }
+        
+        .ButtonClass {
+            font-size: 16px;
+            width: 10%;
+            background-color: #5865f2;
+            color: white;
+            border: none;
+            float: right;
+            position: relative;
+            right: 0;
+            bottom: 0;
+        }
+    </style>
+
+    <div class="navbar">
+        <a href="/">Home</a>
+        <a href="/settings" style="float:right"><i class="fa fa-cog"></i></a>
+
+    </div>
+    <h2 class="h3 mb-4 page-title" style="color:white; position:relative; left:25%;">Settings</h2>
+    <hr class="solid">
+
+    <h5 class="mb-0 mt-5" style="color:white; position:relative; left:25%;">Reset Database</h5>
+    <div class="card" style="background-color:#2c2f33; position: relative; top: 5%; left: 25%; width: 50%; text-align: left;color:white;font-size: 16;">
+        <div class="card-body">
+            <br></bt> <b>Warning:</b> This option will delete all database data<br>
+            <div class="form-check">
+                <form enctype="multipart/form-data" method="post" action="#">
+                    <label class="form-check-label" for="flexCheckDefault" style="font-size: 16px;">
+                        <br>Are you sure you want to continue?
+                      </label>
+                    <input class="form-check-input" type="checkbox" name="confirm" id="flexCheckDefault" />
+
+                    <input type="submit" value="Submit" class="ButtonClass" style="position:absolute; height: 100%" />
+                </form>
+
+            </div>
+        </div>
+    </div>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/src/message_queue_node.py b/src/message_queue_node.py
index 452b7b76..0e7e201f 100755
--- a/src/message_queue_node.py
+++ b/src/message_queue_node.py
@@ -21,6 +21,8 @@ from fragmentation_tracker import FragmentationTracker, FragmentationStartHeader
 from field_codecs import RosMessageCodec
 from acomms_codecs.ros_packet_codec import RosPacketCodec
 from acomms_codecs.packet_codecs import packet_codecs
+from rospy_message_converter import json_message_converter
+from database.controllers.queueController import *
 
 #TODO: move this
 from packet_dispatch_node import DecoderListEntry
@@ -120,6 +122,7 @@ class MessageQueue(object):
         self.message_codec = message_codec
         self.allow_fragmentation = allow_fragmentation
         self.is_active = is_active
+        self.queueDB = Queue()
 
         self._last_tx_time = datetime.utcnow()
         self._queue = deque(maxlen=maxsize)
@@ -152,6 +155,7 @@ class MessageQueue(object):
                                        is_active = self.is_active
                                        )
 
+        self.queueDB.updatePayload(message,encoded_bits)
         if self.order == 'fifo':
             if len(self._queue) < self._queue.maxlen:
                 # drop this message if the queue is full.
@@ -173,6 +177,7 @@ class MessageQueue(object):
         # type: (QueuedMessage) -> None
         if queued_message in self._queue:
             queued_message.transmitted = True
+            self.queueDB.updateTransmit(queued_message, True)
             self._last_tx_time = datetime.utcnow()
             if (not self.ack_next_hop) and (not self.ack_end_to_end):
                 self._queue.remove(queued_message)
@@ -236,6 +241,9 @@ class MessageQueueNode(object):
         self.topic_queue = {}
         self.topic_headers = {}
 
+        self.queueDB = Queue()
+        self.topicDB = Topics()
+
         self.destination_reachable = {}
         self.dest_sequence_num = defaultdict(lambda: 1)
 
@@ -305,6 +313,7 @@ class MessageQueueNode(object):
                                          is_active=message_codec_params.get('is_active', True),
                                          message_codec=message_codec,
                                          )
+                self.topicDB.addEntry(ros_type_name, message_codec_params.get('priority', self.default_priority), message_codec_params.get('is_active', True), message_codec_params['queue_order'])
                 self.topic_queue[actual_topic_name] = new_queue
                 rospy.Subscriber(actual_topic_name,
                                  AnyMsg,
@@ -324,6 +333,16 @@ class MessageQueueNode(object):
 
         # Subscribe to ACK message to update queues
         rospy.Subscriber("from_acomms/encoded_ack", EncodedAck, self.on_ack_received)
+        table = self.queueDB.returnTable()
+        
+        for entries in table:
+            if(entries.transmitted != True):
+                namespace = entries.ros_pkg + entries.topic_name
+
+                message = json_message_converter.convert_json_to_ros_message(namespace, entries.message_raw)
+
+                self.topic_queue[entries.topic_name].append(message)
+                self.update_queue_status()
 
         rospy.loginfo("Message Queue started")
         self.spin()
@@ -374,8 +393,13 @@ class MessageQueueNode(object):
         # Check if incoming msg topic name matches any of the active queue topic names
         if topic_name in self.queue_active_names:
             rospy.logdebug("TOPIC: {} in active queue list, appending msg".format(topic_name))
+            json_str = json_message_converter.convert_ros_message_to_json(msg)
+            self.queueDB.appendQueue(json_str, msg_type, connection_header[0], topic_name, connection_header)
+
             self.topic_queue[topic_name].append(msg)
             self.update_queue_status()
+
+
         else:
             rospy.logdebug("TOPIC: {} not in active queue list, skipping msg".format(topic_name))
 
diff --git a/src/packet_dispatch_node.py b/src/packet_dispatch_node.py
index 4ef881f9..7f05a2ea 100755
--- a/src/packet_dispatch_node.py
+++ b/src/packet_dispatch_node.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python3
 
 from typing import List, Tuple
+from database.controllers.queueController import Queue
 
 import rospy
 import roslib.message
@@ -74,7 +75,7 @@ class DecoderListEntry:
 class PacketDispatchNode(object):
     def __init__(self):
         rospy.init_node('packet_dispatch')
-
+        self.queueDB = Queue()
         packet_codec_param = rospy.get_param('~packet_codecs')
         self.decoder_list = []
         for packet_codec in packet_codec_param:
@@ -114,6 +115,7 @@ class PacketDispatchNode(object):
         rospy.spin()
 
     def on_packet_rx(self, received_packet: ReceivedPacket):
+
         rospy.loginfo("Got incoming packet")
         # Decide what to do with the incoming packet, based on the match criteria
         matching_codecs = [d.packet_codec for d in self.decoder_list if d.does_packet_match(received_packet)]
@@ -128,6 +130,7 @@ class PacketDispatchNode(object):
                 rospy.logwarn("Unrecognized packet decoder: {}".format(d))
 
     def decode_ros_acomms_packet(self, received_packet: ReceivedPacket, stripped_data: Tuple[bytes, bytes]):
+
         payload_bytes = stripped_data[0] + stripped_data[1]
         payload_bits = ConstBitStream(bytes=payload_bytes)
 
@@ -143,6 +146,7 @@ class PacketDispatchNode(object):
                 id = payload_bits.read('uint:8')
                 ros_msg = self.message_codecs[id].decode(payload_bits)
                 self.message_publishers[id].publish(ros_msg)
+
         except KeyError:
             # We don't have a config entry that matches this ID
             rospy.loginfo("Unknown message ID ({}) received, unable to continue parsing packet".format(id))
-- 
GitLab


From 1ace02c6a48576651ca4a5b4146b26e0f265c3c7 Mon Sep 17 00:00:00 2001
From: Brennan Miller-Klugman <millerklugmanb@wit.edu>
Date: Mon, 4 Oct 2021 15:45:07 -0400
Subject: [PATCH 2/2] Refactored file structure

---
 .gitignore                                       |   1 +
 .../__pycache__/queueController.cpython-38.pyc   | Bin 9385 -> 0 bytes
 ...ueueController.cpython-38.pyc:Zone.Identifier |   3 ---
 .../queueController.py:Zone.Identifier           |   3 ---
 src/database/databases/queue.db:Zone.Identifier  |   3 ---
 5 files changed, 1 insertion(+), 9 deletions(-)
 delete mode 100644 src/database/controllers/__pycache__/queueController.cpython-38.pyc
 delete mode 100644 src/database/controllers/__pycache__/queueController.cpython-38.pyc:Zone.Identifier
 delete mode 100644 src/database/controllers/queueController.py:Zone.Identifier
 delete mode 100644 src/database/databases/queue.db:Zone.Identifier

diff --git a/.gitignore b/.gitignore
index e5ee6dab..9d2f2105 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@
 /src/acomms_codecs/field_codecs/__pycache__
 .vscode/settings.json
 .vscode/c_cpp_properties.json
+src/database/controllers/__pycache__/queueController.cpython-38.pyc:Zone.Identifier
diff --git a/src/database/controllers/__pycache__/queueController.cpython-38.pyc b/src/database/controllers/__pycache__/queueController.cpython-38.pyc
deleted file mode 100644
index 1717650b59a16cd55e5a3fc6dd390ca4543af134..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 9385
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

diff --git a/src/database/controllers/__pycache__/queueController.cpython-38.pyc:Zone.Identifier b/src/database/controllers/__pycache__/queueController.cpython-38.pyc:Zone.Identifier
deleted file mode 100644
index 7ae860cb..00000000
--- a/src/database/controllers/__pycache__/queueController.cpython-38.pyc:Zone.Identifier
+++ /dev/null
@@ -1,3 +0,0 @@
-[ZoneTransfer]
-ZoneId=3
-ReferrerUrl=C:\Users\brenn\Downloads\ros_acomms-dev-dbQueue.zip
diff --git a/src/database/controllers/queueController.py:Zone.Identifier b/src/database/controllers/queueController.py:Zone.Identifier
deleted file mode 100644
index 7ae860cb..00000000
--- a/src/database/controllers/queueController.py:Zone.Identifier
+++ /dev/null
@@ -1,3 +0,0 @@
-[ZoneTransfer]
-ZoneId=3
-ReferrerUrl=C:\Users\brenn\Downloads\ros_acomms-dev-dbQueue.zip
diff --git a/src/database/databases/queue.db:Zone.Identifier b/src/database/databases/queue.db:Zone.Identifier
deleted file mode 100644
index 7ae860cb..00000000
--- a/src/database/databases/queue.db:Zone.Identifier
+++ /dev/null
@@ -1,3 +0,0 @@
-[ZoneTransfer]
-ZoneId=3
-ReferrerUrl=C:\Users\brenn\Downloads\ros_acomms-dev-dbQueue.zip
-- 
GitLab