diff --git a/lib/local-db.js b/lib/local-db.js
index 894ea24..f62087d 100644
--- a/lib/local-db.js
+++ b/lib/local-db.js
@@ -23,13 +23,18 @@ function getConnection() { return db; }
 function initTables() {
     logger.verbose('Preparing database tables');
     db.serialize(function() {
-        db.run('CREATE TABLE IF NOT EXISTS sms( created TEXT, direction TEXT, imsi TEXT, partner TEXT, msg TEXT )');
+        db.run('CREATE TABLE IF NOT EXISTS ussd( created TEXT, created_date TEXT, direction TEXT, imsi TEXT, msg TEXT )');
+        db.run('CREATE INDEX IF NOT EXISTS idx_ussd_created ON ussd(created)');
+        db.run('CREATE INDEX IF NOT EXISTS idx_ussd_created_date_created ON ussd(created_date, created)');
+
+        db.run('CREATE TABLE IF NOT EXISTS sms( created TEXT, created_date TEXT, direction TEXT, imsi TEXT, partner TEXT, msg TEXT )');
         db.run('CREATE INDEX IF NOT EXISTS idx_sms_created ON sms(created)');
+        db.run('CREATE INDEX IF NOT EXISTS idx_sms_created_date_created ON sms(created_date, created)');
 
         db.run('CREATE TABLE IF NOT EXISTS pendingtrx ( created TEXT, created_date TEXT, trx_id TEXT, destination TEXT, product TEXT )');
         db.run('CREATE INDEX IF NOT EXISTS idx_pendingtrx_created ON pendingtrx(created)');
-        db.run('CREATE UNIQUE INDEX IF NOT EXISTS idx_pendingtrx_created_date ON pendingtrx(created_date, destination, product)');
         db.run('CREATE UNIQUE INDEX IF NOT EXISTS idx_pendingtrx_trx_id ON pendingtrx(trx_id)');
+        db.run('CREATE INDEX IF NOT EXISTS idx_pendingtrx_created_date ON pendingtrx(created_date, destination, product)');
     })
 }
 
@@ -37,11 +42,12 @@ function cleanup(max_days) {
     logger.info('Doing database cleanup');
 
     if (!max_days) {
-        max_days = 7;
+        max_days = 31;
     }
 
     const oldest = moment().add(-1 * max_days, 'days').format('YYYY-MM-DD');
     db.serialize(function() {
+        db.run('DELETE FROM ussd WHERE created < ?', oldest);
         db.run('DELETE FROM sms WHERE created < ?', oldest);
         db.run('DELETE FROM pendingtrx WHERE created_date < ?', oldest);
         db.run('VACUUM');
diff --git a/lib/modem-dashboard/index.js b/lib/modem-dashboard/index.js
new file mode 100644
index 0000000..cdf59fe
--- /dev/null
+++ b/lib/modem-dashboard/index.js
@@ -0,0 +1,64 @@
+"use strict";
+
+const express = require('express');
+const nunjucks = require('nunjucks');
+
+const config = require('komodo-sdk/config');
+const logger = require('komodo-sdk/logger');
+const matrix = require('komodo-sdk/matrix');
+
+
+const routerSms = require('./router-sms');
+const routerUssd = require('./router-ussd');
+
+const app = express();
+
+app.use(express.static(__dirname + '/public', {maxAge: 24 * 3600 * 1000}));
+
+nunjucks.configure(__dirname + '/views', {
+    autoescape: true,
+    noCache: true,
+    express: app
+});
+
+function modemSignal(req, res, next) {
+    const signal_strength = matrix && matrix.modem && matrix.modem.signal_strength ? matrix.modem.signal_strength : 0;
+    res.locals.signal_strength = signal_strength;
+
+    if (signal_strength < 2 || !signal_strength) {
+        res.locals.signal_strength_image = 'signal-0.png';
+        res.locals.signal_strength_title = 'No signal';
+    }
+    else if (signal_strength < 10) {
+        res.locals.signal_strength_image = 'signal-1.png';
+        res.locals.signal_strength_title = 'Marginal';
+    }
+    else if (signal_strength < 15) {
+        res.locals.signal_strength_image = 'signal-2.png';
+        res.locals.signal_strength_title = 'OK';
+    }
+    else if (signal_strength < 20) {
+        res.locals.signal_strength_image = 'signal-3.png';
+        res.locals.signal_strength_title = 'Good';
+    }
+    else {
+        res.locals.signal_strength_image = 'signal-4.png';
+        res.locals.signal_strength_title = 'Excelent';
+    }
+
+    next();
+}
+
+app.use(modemSignal);
+
+app.get('/', function(req, res, next) {
+    res.redirect('/sms');
+})
+
+app.use('/sms', routerSms);
+app.use('/ussd', routerUssd);
+
+const modem_dashboard_port = (config && config.modem_dashboard && config.modem_dashboard.port) ? config.modem_dashboard.port : 22765;
+app.listen(modem_dashboard_port, function () {
+    logger.info('Web control panel started', {listen_port: modem_dashboard_port});
+});
diff --git a/lib/modem-dashboard/public/ie10-viewport-bug-workaround.css b/lib/modem-dashboard/public/ie10-viewport-bug-workaround.css
new file mode 100644
index 0000000..4b9518e
--- /dev/null
+++ b/lib/modem-dashboard/public/ie10-viewport-bug-workaround.css
@@ -0,0 +1,13 @@
+/*!
+ * IE10 viewport hack for Surface/desktop Windows 8 bug
+ * Copyright 2014-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*
+ * See the Getting Started docs for more information:
+ * http://getbootstrap.com/getting-started/#support-ie10-width
+ */
+@-ms-viewport     { width: device-width; }
+@-o-viewport      { width: device-width; }
+@viewport         { width: device-width; }
diff --git a/lib/modem-dashboard/public/ie10-viewport-bug-workaround.js b/lib/modem-dashboard/public/ie10-viewport-bug-workaround.js
new file mode 100644
index 0000000..479a6eb
--- /dev/null
+++ b/lib/modem-dashboard/public/ie10-viewport-bug-workaround.js
@@ -0,0 +1,23 @@
+/*!
+ * IE10 viewport hack for Surface/desktop Windows 8 bug
+ * Copyright 2014-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+// See the Getting Started docs for more information:
+// http://getbootstrap.com/getting-started/#support-ie10-width
+
+(function () {
+  'use strict';
+
+  if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
+    var msViewportStyle = document.createElement('style')
+    msViewportStyle.appendChild(
+      document.createTextNode(
+        '@-ms-viewport{width:auto!important}'
+      )
+    )
+    document.querySelector('head').appendChild(msViewportStyle)
+  }
+
+})();
diff --git a/lib/modem-dashboard/public/img/signal-0.png b/lib/modem-dashboard/public/img/signal-0.png
new file mode 100644
index 0000000000000000000000000000000000000000..ddf4ba4f063cc1f56464dae9ff11e2090d843c4e
GIT binary patch
literal 953
zcmeAS@N?(olHy`uVBq!ia0vp^K0xfi!3HEZgiZ_qQY^(zo*^7SP{WbZ0pxQQctjR6
zFfd*PVaCrnryl|ZB}-f*N`mv#O3D+9QW?t2%k?tzvWt@w3sUv+i_&Mmvyoz8U^eq~
zaSW-L^LEyGZ;?Qm1NQm1r-lA%l;V)nnV>r12Gf7Ww~N~OTql)ye0U(&b0fK3FScpH
z<vUR-OrI61Hg*S=y}EQz$ks!mg|+dL)2T%_cA2bio}M}@W8b?Mx2L{mXPZ{}x%U2d
zyEng$^3xb{nq|uiJPxIPa#LZfDYNBZtUeGvo!Q_(W&+cWxVsZhro4FlTDa8A)YNrl
z$gkIb9z0N3yLRow-;vSL$#r#h6;-l3IQNM2zM5cgp!R`z=+~r*iW~3Vyt%QWq_nj4
z+T5p4pPr~abLPyAY15`9$jdkQvB&*8ZJN-%>R?%U`R%1kmpY4wX-&=1o6g-mpJA5F
zj*c^~4}?RT{gz+8_Sxq3?|%z9q9Y<U%=A%{2v7VUe_vn@W1P^8iu(HfvGMW!zBAtc
z1}dBFwY165zTw{D`DM8h4-_8+o6h|9t<2ioJbd$p-d<j70|SAwzwWQL#JN5d+u(b3
zNspn~{PVYqcGf5)Zr;3k+uF6dZ*GZSsodM;CHBK9p~=?Pwyd<&bkl~rcVlOtf4<gm
z*}~VMAyJLyEGZ_Yrjh4A|I^M%O+A{n`R0aiN(#FlW-ItH^m9%$GBHW9wz6_+?d|Qo
zSz;x7Z5ziN`%jS;56m_==gxlN+2^^p>y&5$@6Hv;k?R)~@l|-2M7lm$HF@GSLC=4I
z*O`th6&yS(@c8hN8`n8Lh<LPa@nu?kV7<iWt3C?@cAWnA&(i3m#AkbUIfhupT>llu
zkqpOXcwf84=-FdeD7xrS%L)TUEuRi9VHne6j`=$Gb3cAmT>Ji4deRIRrH?r!C0~9!
z7MpD`$bOsp?Y^}~(z8Zp?#rs0F0Gt_iB2IiChX|`XZs-J#Ls-g=Y?)}4#ge46MuK1
zcMy`P9hdh$`SPV?RfLY)|0s!!yu5o-l9Gkr*iNn7aQ5ukdnragqlAK2hP2)M-*<*{
zmr5(Ts~|>QDOnz`A!5~7K1m|^%;Fe5^EmIg=~s4{T6O-h{=M1sSxJ|kC#r8yoUq+(
w-~0EfLY?yuZ76!M-DF?T)cV^J%3c4NGxPr{gmv(H1G5=}r>mdKI$&%90L{F!IsgCw

literal 0
HcmV?d00001

diff --git a/lib/modem-dashboard/public/img/signal-1.png b/lib/modem-dashboard/public/img/signal-1.png
new file mode 100644
index 0000000000000000000000000000000000000000..e0a47af94f0fe08c6e7b6169e62533df83ebc634
GIT binary patch
literal 946
zcmeAS@N?(olHy`uVBq!ia0vp^K0xfi!3HEZgiZ_qQY^(zo*^7SP{WbZ0pxQQctjR6
zFfd*PVaCrnryl|ZB}-f*N`mv#O3D+9QW?t2%k?tzvWt@w3sUv+i_&Mmvyoz8VAl6^
zaSW-L^LEz$Y~ete1NP#{9^LjC+9FmViYyB~M1Jva(L4KKL4*#UnAH|%S0k$(J2;vy
z=T1{_dK++Ssh;TC$=%Ldw>VGa3Sw0}+Mv5|;j)9(e36GLAJxvzjt|-=Z^7~XQ|<lt
zzbAZus#ngi>}a2Lgi4xmrM3{W-EBRm19l&-rZMsrNX=kdcb$L9<xDnqcGt;g&z%d>
zn)=Vm-p0l!Jw5$JrJ1>TWK`6r`FafIjo%k7;^SoB!T)F3y7->HzF9>(a}G`NTFUhM
z+^t(tFD#!uf9~t<-d^9w@35X#|Nm2|4bHI}Yin!MN=v_9Xr1b%YHVmIC}PjMC9*(p
zR`&t*S6zN;laH0gKCZmCkRv)S&g^B$E&1@J-&W^yo@3Des9TefaYBTv^+ZeMy!4ps
zrkyT_<Ucb@So}&gZ)3J$v3VtS`R?6ZF>!Hev29zorf#~KbK$%Fr6qs0bhbCdz7l(C
z(RcD`(XybGG9EV$9cp^{>J`_ocigk~#J8$4*Bsn_;NQQx%^NogM%}n~Zyr$LvBEji
z-i0T=WV!cX^2KY{(qgXvUBBV$*V4%+Q<{!-H@s<D-)g~Vqvmkx#EFiVFJE$sm|0q8
zPCA)#;RaX1zZ2n!jkg_U9?M&lZlMNrKzM`ilSO^0`?*eAKG1!bD%!X@Oe<IE(VxZZ
zfA)z!Xqqdu_;6>zI>QH=6F4MhGahS<7krjIW97<~yRW>P?=0MJ@W1#0;{+~=YNyF3
znF?f{Pcl@~?z~tZ)4IYyQOl=;OL)<t78q0LY3u8Wlg~dlp7;Fjgd<0iHl{y*{P;fq
ztj$YXC6o1ntKTVfMl$i~_-tPyAgbol${CpGv?%Y__l97`=lfmf9G42@t`_}R<J+F+
ziEMP(d)4R9o(UaIGW>J<kVAF#?{hb9%-E_P5Z0QTpU;2f@yF|vW@K%(@_K7)r2S%=
z2$Fk{n3rBmt<(SDC-Ir%g!zo?QoUT(oque9Z{~frr3=+IR6ku^?l$lF+v7<a=O5b8
n^?tL-zNqQ-*9&C=|H!}f{H1X3tsXlte=&Hv`njxgN@xNA5}m41

literal 0
HcmV?d00001

diff --git a/lib/modem-dashboard/public/img/signal-2.png b/lib/modem-dashboard/public/img/signal-2.png
new file mode 100644
index 0000000000000000000000000000000000000000..9bd2fb75461f48f90502c3ac300cf105016e7b49
GIT binary patch
literal 924
zcmeAS@N?(olHy`uVBq!ia0vp^K0xfi!3HEZgiZ_qQY^(zo*^7SP{WbZ0pxQQctjR6
zFfd*PVaCrnryl|ZB}-f*N`mv#O3D+9QW?t2%k?tzvWt@w3sUv+i_&Mmvyoz8V3zcB
zaSW-L^LEz$Y~ete1NP$C9tY%2M7d;F2{Z+$aQ$VEnx0k=pd-f4%=a>2Vh^95Uekk;
z*{U4@)*`#EEL~JsRJdYVnMRP~B84Rp6NIF)qV_x&XepRiasSz^=~Ldb^YvAKuYLd9
z?n!OsbZdsosmFD7gf?4Nm<uu6-Sl%hp!eZu8WUfE&<w_P+ssmoB;DNIUFV)Xdp2<O
z)qlI}?CkusrgGi&UmCP9M(?+Nc;o8>)`3CnEzEbA>n;ZAfBLy+<@MKUIxkDCHoRN2
zZe82E<hr_hU%q|&^}B+fC+fqe_;n1?TU4w~Oj5$a!uVn$)`l5Ro;=y{qp`!KrtS-K
z*zGP&Dp8tfu<o_g`OkbVH!fY8bTY;0-wxYZ`+u!_Ao79f{*mLyj`?hj>h+oNyz*FS
ztZ@JFzlQf4Cmx<(R&8;B`M}~-qrZRurWF=$%uSS*mR6g7n)UAgM!vP-i8~o{E*ohc
zFZ9_MVbbfC9DhhmOw1=fKK{bq^DjSCiB8k`AbFpqy}kYHuU}OeiPqNE%OZ57ju-CQ
z71yfDy62d>@=PD8>!ts-b8>Ufrfj~s;G3_*wui5k`WX8;CKwqSCbF@yF}3>o`p$Gw
z61=jFXO8Wc$cP7O0n7KczliMf*voZVbwN|im5FP@6D^tdDDGL~`(V>lAL|aee}UI)
zjvE!6^Xt0!(B;PU+y|Tj{28-ZxelD?IG#QG<;$1WCiCYzUlxA&<9x$!2df2d4Q181
z4;0SfJ~m^HirfD}(M5+^Rv0L1`E+mz!<ZgZq^~<K57A1sJ-=J6v-4<@KX>b)?SK1j
zUOm)fD4w~me8Q0_jkVmDRW)5&IRg`&LS{@@(fu#>fy;rf>jnFhdsnpX?b)%v&w2V1
z0Z}!W5`o+2Cl$_;-|2DV&?9M$+lSm5!Vk@`Is5*^ng!lLNR}fpJ$76Fb$qba;F)4T
zR&h-B7VS3{pWeUm-)^}qw8WDOY%#J0FuQX0o8Drr<4Bg;SDg9h-hAQnpSQ^#7d-l(
Z%`N41Sj~@($-tb%;OXk;vd$@?2>={wmFNHf

literal 0
HcmV?d00001

diff --git a/lib/modem-dashboard/public/img/signal-3.png b/lib/modem-dashboard/public/img/signal-3.png
new file mode 100644
index 0000000000000000000000000000000000000000..83801cab4b44a48645863700b78e4870df594c0a
GIT binary patch
literal 910
zcmeAS@N?(olHy`uVBq!ia0vp^K0xfi!3HEZgiZ_qQY^(zo*^7SP{WbZ0pxQQctjR6
zFfd*PVaCrnryl|ZB}-f*N`mv#O3D+9QW?t2%k?tzvWt@w3sUv+i_&Mmvyoz8VCMF8
zaSW-L^LEyGZ;?Qm1NP^0ZnoAvkm8WjiJ0b)#QleTOLz5)02R-6F{>vBJ8a8dTvFw*
zI;-2sai;mfQ9ZZZ<$AI@7n@rga~v0_wCHrLy|jnVdxMYgx$Tm*yFdLsaKIpc-}~D8
z?X~gu-taW!Zhp+h_p-pU!uk?pP0`$z2H6MQr&)LkWM;7FnVUcPT-nyv<}%mU-#>Wu
z)qlI}jEtPjX7}Fl-x{?vXeEpOdZzHk@<mI&aWdawt-Bba@3nN&-CMUd1)h9bw6HWi
zGgGrj-q_f9+v?TYH;z{?INvzkb|*{Dg(*4p_4{LEV(yeDZjCzI*W25A)SpR`T~Dc4
z?1xA2rI#hQs^+EF-oG!N`1$i^v-#)QAD3nRd3C!<_y9MPu)Lfc(7e^1oS$p&1C<4@
z3^90SZBX&ya$h^+J7zoI$uD2N+*n*(ys>rd+O;>6HcFKJXOG$v=lWD?gXiTXJ%-z2
z^ln$}{TF{IEj>LK7y~!<p3nSPB|4Sq!^{IL>}+grPMz{fNxXggHc(-7vQPB&)hkjO
zud}427)idayf^RAwCU4x7Y1--$FrwM?=ySE@nM31=HkVRw{72U9&+Qyj~%|tFDK@5
zA9%?;zm<6%bM%qwj(LwJTv@#$hGEqSSJ_iQn}QEWFFGB?u4i>}OY4g#@};^3It=M|
zmdub*JGd{8slPGA<F-fv_m7zmDmKoXF=L1C<DZsBb2<C|^Xy=M;&e;yV$vpt9>eEr
zwz_)u{ClkB(#jc_=oB(TKvWIJoS<U9PEUg&yv5MJG5^1H!ftMB|HpfqTeu8cUQQBO
zbf{&8fufd=$0gVQd<8mBeqC=lUg&n|P@LMG_|pr$gF3i`VM;n)r=Jw*?T=B(dGLXE
zN_JxN0qsPe&ST{%eiu|VVYVSz3}mXj^V`o~q1{u-VAE;2&iE0Rb=M#3-;)iGmvrfQ
z0&PV$9oeGoZq^6*6Mbw8^m_0AEq?U--!eltk^j<4%J*ZIefi}D%sUL8u6{1-oD!M<
Dm86h>

literal 0
HcmV?d00001

diff --git a/lib/modem-dashboard/public/img/signal-4.png b/lib/modem-dashboard/public/img/signal-4.png
new file mode 100644
index 0000000000000000000000000000000000000000..2d090ffebca73c091d782c99a0b88da5104c397e
GIT binary patch
literal 889
zcmeAS@N?(olHy`uVBq!ia0vp^K0xfi!3HEZgiZ_qQY^(zo*^7SP{WbZ0pxQQctjR6
zFfd*PVaCrnryl|ZB}-f*N`mv#O3D+9QW?t2%k?tzvWt@w3sUv+i_&Mmvyoz8VEX3i
z;uumf=k2Wh*}{P`2kgVMJr2m5h;qrU3TV2Z$n}@~mfqP13nFy**ks-WOzc^w*Yw(#
z>rs$3%dRV`iwcVhS4=C@2nt-Juq0xFkW^OGp63&uTKHGrzqeIi^FF_f%=dS{?|rY`
z@%?EX;|#sqd5II{W;d5B+a6HA?a6V2b>A(Y1B`ym#Ro#`o%N<C*VM#ZiQE~p>|(~B
z(weNSt{gMzo%5sCx^0c(m0QPry|H}J5<X7$9sGZeh3j`6U6g4yTTScm;lm3{(@RTD
zi{!bvxtFb9uYcosb;60J>9sqVavpk@rKB8Lvu2IVt_^OB6VuYt4n2C_(8DS|aVJO3
zk?AE?bIsPhmOB5L&-KQoOOsAMEjqZv_EvapcmZ35W5T1!lP52WTd%Hm=CjS?UF$rT
z1|6Isf8fSNe``6u4-6kZ_@*T!90<{xdgG9pnVHYR01oT_%(7AI7ZowzIA*SSywGQ5
zh|$`x*A9oo#KnE<>+5gqJpb}TmFQHP53L7S+}+*J{`yswl4xyhy(~ma@_6B{U2(3e
z+<Vj%lqa8*xL*2QblbLVX`g=9MEq7$*!}Rek{?4q$3!Dr+gvtwcIVc!=g!S4v68*E
zjc1Pir^tv0Y8O=QIe)P^z9i1|sZoHl-m8dft5?inz9$fSP0b)t^)lb0>GfB(9@xec
zvte>lkp<_sQt1k&B~G`VHCi87&vM+mY4?`-^Vfcy`C+wozVXWcA0!faubHoN3Yj4w
zs^-$l8JGxXzT7(3!RONf)5J5z4}LqczbQ+co>5;uAwadwAa)X5mFKP(_nG}#W&Th5
zU~$bO>c;7o->)r7Jh_kz+W1#z=AyroyIXX1>eg-6&Ecs~?a{pSum23!E|u0528vof
z9bCeT4z(aLkL<lH&vcI~S&qp+xi7nS$00wZ|L6bZoH1Ox$U6u_HB4jD@6{LeJ_Ji#
l=6d7(_<POo+n0XWt6YEf=Exd{SHNt-;OXk;vd$@?2>{@ZhE)In

literal 0
HcmV?d00001

diff --git a/lib/modem-dashboard/public/starter-template.css b/lib/modem-dashboard/public/starter-template.css
new file mode 100644
index 0000000..dc15c49
--- /dev/null
+++ b/lib/modem-dashboard/public/starter-template.css
@@ -0,0 +1,7 @@
+body {
+  padding-top: 50px;
+}
+.starter-template {
+  padding: 40px 15px;
+  /* text-align: center; */
+}
diff --git a/lib/modem-dashboard/router-sms.js b/lib/modem-dashboard/router-sms.js
new file mode 100644
index 0000000..f7009da
--- /dev/null
+++ b/lib/modem-dashboard/router-sms.js
@@ -0,0 +1,35 @@
+"use strict";
+
+const moment = require('moment');
+const express = require('express');
+
+const localDb = require('../local-db');
+
+const router = express.Router();
+module.exports = router;
+
+function pageSmsIndex(req, res, next) {
+    res.render(
+        'sms.index.html',
+        {
+            page_title: 'Histori SMS'
+        }
+    )
+}
+
+function pageSmsDataTables(req, res, next) {
+    const db = localDb.getConnection();
+
+    const created_date = moment().format('YYYY-MM-DD');
+    const query = "SELECT rowid, * FROM sms WHERE created_date = ? ORDER BY created DESC, rowid DESC";
+    db.all(query, created_date, function (err, rows) {
+        if (err) {
+            res.end("Ada error: " + err);
+            return;
+        }
+        res.json({data: rows});
+    });
+}
+
+router.get('/', pageSmsIndex);
+router.get('/datatables', pageSmsDataTables);
diff --git a/lib/modem-dashboard/router-ussd.js b/lib/modem-dashboard/router-ussd.js
new file mode 100644
index 0000000..6cd346f
--- /dev/null
+++ b/lib/modem-dashboard/router-ussd.js
@@ -0,0 +1,35 @@
+"use strict";
+
+const moment = require('moment');
+const express = require('express');
+
+const localDb = require('../local-db');
+
+const router = express.Router();
+module.exports = router;
+
+function pageIndex(req, res, next) {
+    res.render(
+        'ussd.index.html',
+        {
+            page_title: 'Histori USSD'
+        }
+    )
+}
+
+function pageDataTables(req, res, next) {
+    const db = localDb.getConnection();
+
+    const created_date = moment().format('YYYY-MM-DD');
+    const query = "SELECT rowid, * FROM ussd WHERE created_date = ? ORDER BY created DESC, rowid DESC";
+    db.all(query, created_date, function (err, rows) {
+        if (err) {
+            res.end("Ada error: " + err);
+            return;
+        }
+        res.json({data: rows});
+    });
+}
+
+router.get('/', pageIndex);
+router.get('/datatables', pageDataTables);
diff --git a/lib/modem-dashboard/views/sms.index.html b/lib/modem-dashboard/views/sms.index.html
new file mode 100644
index 0000000..293d2af
--- /dev/null
+++ b/lib/modem-dashboard/views/sms.index.html
@@ -0,0 +1,55 @@
+{% extends "template.html" %}
+
+{% block head %}
+<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.18/css/dataTables.bootstrap.min.css">
+<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.js"></script>
+<script type="text/javascript" src="https://cdn.datatables.net/1.10.18/js/dataTables.bootstrap.min.js"></script>
+{% endblock %}
+
+{% block content %}
+
+<table id="smsHistory" class="display table table-hover table-striped">
+    <thead>
+        <tr>
+            <th>#</th>
+            <th>Tanggal</th>
+            <th>Arah</th>
+            <th>IMSI Modem</th>
+            <th>Dari/Ke</th>
+            <th>Pesan</th>
+        </tr>
+    </thead>
+    <tfoot>
+        <tr>
+            <th>#</th>
+            <th>Tanggal</th>
+            <th>Arah</th>
+            <th>IMSI Modem</th>
+            <th>Dari / Ke</th>
+            <th>Pesan</th>
+        </tr>
+    </tfoot>
+</table>
+
+<script>
+    $(document).ready(function() {
+        $('#smsHistory').DataTable( {
+            "ajax": "/sms/datatables",
+            "language": { "url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Indonesian.json" },
+            "columns": [
+                { "data": "rowid" },
+                { "data": "created" },
+                { "data": "direction" },
+                { "data": "imsi" },
+                { "data": "partner" },
+                { "data": "msg" }
+            ],
+            "order": [
+                [1, "desc"]
+            ],
+            "lengthMenu": [[50, 100, 200, -1], [50, 100, 200, "All"]]
+        } );
+    } );
+</script>
+
+{% endblock %}
diff --git a/lib/modem-dashboard/views/template.html b/lib/modem-dashboard/views/template.html
new file mode 100644
index 0000000..6ba9703
--- /dev/null
+++ b/lib/modem-dashboard/views/template.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
+
+    <meta name="description" content="">
+    <meta name="author" content="">
+    <link rel="icon" href="/favicon.ico">
+
+    <title>
+        {% if page_title %}
+        {{ page_title }}
+        -
+        {% endif %}
+        Modem Dashboard
+    </title>
+
+    <!-- Latest compiled and minified CSS -->
+    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
+
+    <!-- Optional theme -->
+    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
+
+
+
+    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
+    <link href="/ie10-viewport-bug-workaround.css" rel="stylesheet">
+
+    <!-- Custom styles for this template -->
+    <link href="starter-template.css" rel="stylesheet">
+
+    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+    <!--[if lt IE 9]>
+      <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
+      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+    <![endif]-->
+
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
+
+    {% block head %}
+    {% endblock %}
+  </head>
+
+  <body>
+
+    <nav class="navbar navbar-inverse navbar-fixed-top">
+      <div class="container">
+        <div class="navbar-header">
+          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
+            <span class="sr-only">Toggle navigation</span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="navbar-brand" href="/">Modem Dashboard</a>
+        </div>
+        <div id="navbar" class="collapse navbar-collapse">
+          <ul class="nav navbar-nav">
+            <li><a href="/sms">SMS</a></li>
+            <li><a href="/ussd">USSD</a></li>
+          </ul>
+        </div><!--/.nav-collapse -->
+      </div>
+    </nav>
+
+    <div class="container">
+
+      <div class="starter-template">
+
+        <div style="text-align: right;">
+            <img src="/img/{{ signal_strength_image }}" alt="Signal: {{ signal_strength_title }}" title="Signal: {{ signal_strength_title }} ({{ signal_strength }})">
+        </div>
+
+        {% if page_title%}
+        <h1> {{ page_title }} </h1>
+        {% endif %}
+
+        {% block content %}
+
+        &nbsp;
+
+        {% endblock %}
+
+      </div>
+
+    </div><!-- /.container -->
+
+
+    <!-- Bootstrap core JavaScript
+    ================================================== -->
+    <!-- Placed at the end of the document so the pages load faster -->
+    <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
+    <!-- Latest compiled and minified JavaScript -->
+    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
+
+    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
+    <script src="/ie10-viewport-bug-workaround.js"></script>
+  </body>
+</html>
diff --git a/lib/modem-dashboard/views/ussd.index.html b/lib/modem-dashboard/views/ussd.index.html
new file mode 100644
index 0000000..e84613b
--- /dev/null
+++ b/lib/modem-dashboard/views/ussd.index.html
@@ -0,0 +1,52 @@
+{% extends "template.html" %}
+
+{% block head %}
+<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.18/css/dataTables.bootstrap.min.css">
+<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.js"></script>
+<script type="text/javascript" src="https://cdn.datatables.net/1.10.18/js/dataTables.bootstrap.min.js"></script>
+{% endblock %}
+
+{% block content %}
+
+<table id="smsHistory" class="display table table-hover table-striped">
+    <thead>
+        <tr>
+            <th>#</th>
+            <th>Tanggal</th>
+            <th>Arah</th>
+            <th>IMSI Modem</th>
+            <th>Pesan</th>
+        </tr>
+    </thead>
+    <tfoot>
+        <tr>
+            <th>#</th>
+            <th>Tanggal</th>
+            <th>Arah</th>
+            <th>IMSI Modem</th>
+            <th>Pesan</th>
+        </tr>
+    </tfoot>
+</table>
+
+<script>
+    $(document).ready(function() {
+        $('#smsHistory').DataTable( {
+            "ajax": "/ussd/datatables",
+            "language": { "url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Indonesian.json" },
+            "columns": [
+                { "data": "rowid" },
+                { "data": "created" },
+                { "data": "direction" },
+                { "data": "imsi" },
+                { "data": "msg" }
+            ],
+            "order": [
+                [1, "desc"]
+            ],
+            "lengthMenu": [[50, 100, 200, -1], [50, 100, 200, "All"]]
+        } );
+    } );
+</script>
+
+{% endblock %}
diff --git a/lib/modem/index.js b/lib/modem/index.js
index 7eb2e89..3078693 100644
--- a/lib/modem/index.js
+++ b/lib/modem/index.js
@@ -43,7 +43,7 @@ class Modem extends EventEmitter {
         });
 
         this.port.on('open', function() {
-            self.disableEcho(function() {
+            self.resetModem(function() {
                 self.getIMSI(function() {
                     self.emit('open');
                     self.getSignalStrength(cb);
@@ -145,7 +145,7 @@ class Modem extends EventEmitter {
         this.emit('incoming sms', sms);
     }
 
-    disableEcho(cb) {
+    resetModem(cb) {
         const self = this;
 
         if (this.parser) { this.port.unpipe(this.parser)};
@@ -154,7 +154,7 @@ class Modem extends EventEmitter {
         parser.on('data', function(data) {
             const value = data.toString().replace(/^\s+/, '').replace(/\s+$/, '');
 
-            debugLog('PARSER-DISABLEECHO: echo disabled');
+            debugLog('PARSER-RESETMODEM: modem reseted');
 
             self.port.unpipe(parser);
             self.resetParserToDefault();
@@ -164,7 +164,7 @@ class Modem extends EventEmitter {
             }
         })
 
-        this.write('ATE0\r');
+        this.write('AT &F Z E0\r');
     }
 
     getIMSI(cb) {
diff --git a/lib/partner-mkios.js b/lib/partner-mkios.js
index 68fbb64..6bf239f 100644
--- a/lib/partner-mkios.js
+++ b/lib/partner-mkios.js
@@ -1,5 +1,7 @@
 "use strict";
 
+const moment = require('moment');
+
 const Modem = require('./modem');
 
 const pullgw = require('komodo-sdk/gateway/pull');
@@ -8,6 +10,8 @@ const config = require('komodo-sdk/config');
 const logger = require('komodo-sdk/logger');
 const matrix = require('komodo-sdk/matrix');
 
+const modemDashboard = require('./modem-dashboard');
+
 matrix.modem = {};
 matrix.not_ready = true;
 matrix.stock = {};
@@ -36,9 +40,9 @@ modem.on('imsi', function(imsi) {
 
 function onIncomingSMS(sms) {
     logger.info('Incoming SMS', {sms: sms});
-    db.run("INSERT INTO sms VALUES (?, 'IN', ?, ?, ?)", sms.created, matrix.modem.imsi, sms.sender, sms.msg, function(err) {
+    db.run("INSERT INTO sms VALUES (?, ?, 'IN', ?, ?, ?)", sms.created, moment(sms.created).format('YYYY-MM-DD'), matrix.modem.imsi, sms.sender, sms.msg, function(err) {
         if (err) {
-            logger.warn('Error inserting sms to local database');
+            logger.warn('Error inserting sms to local database', {err: err});
         }
     });
 
@@ -105,9 +109,16 @@ modem.on('signal strength', function(signal_strength) {
     logger.verbose('Signal strength: ' + signal_strength);
 })
 
-modem.on('ussd response', function(data) {
+function onUSSDResponse(data) {
     logger.verbose('Got USSD response', {response: data});
 
+    db.run("INSERT INTO ussd VALUES (?, ?, 'IN', ?, ?)", moment().format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD'), matrix.modem.imsi, data, function(err) {
+        if (err) {
+            logger.warn('Error inserting ussd response to local database', {err: err});
+        }
+    });
+
+
     if (!last_trx_id) return;
 
 
@@ -128,7 +139,9 @@ modem.on('ussd response', function(data) {
 
     updateStock(stock_name, stock_balance);
     last_trx_id = null;
-})
+}
+
+modem.on('ussd response', onUSSDResponse);
 
 
 logger.info('Opening MODEM');
@@ -212,7 +225,7 @@ function suspendPull(trx_id) {
             rc: '68',
             message: 'USSD timeout'
         })
-    }, Number(config.partner.modem.suspend_time_ms) || 30000)
+    }, Number(config.partner.modem.suspend_time_ms) || 20 * 1000 )
 }
 
 function deleteResumeHandler(trx_id) {
@@ -249,6 +262,11 @@ function buy(task) {
         const ussd_command = task.remote_product.split(',')[0].replace("<DESTINATION>", task.destination).replace("<PIN>", config.partner.pin);
         logger.verbose('Going to execute USSD', {trx_id: task.trx_id, destination: task.destination, product: task.product, ussd: ussd_command});
 
+        db.run("INSERT INTO ussd VALUES (?, ?, 'OUT', ?, ?)", moment().format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD'), matrix.modem.imsi, 'AT+CUSD=1,"' + ussd_command + '",15', function(err) {
+            if (err) {
+                logger.warn('Error inserting ussd command to local database', {err: err});
+            }
+        });
         modem.sendUSSD(ussd_command, function() {});
     })
 
diff --git a/lib/pending-archive.js b/lib/pending-archive.js
index 16a209b..b7ecad0 100644
--- a/lib/pending-archive.js
+++ b/lib/pending-archive.js
@@ -49,7 +49,7 @@ function get(destination, product, created_date, cb) {
     logger.verbose('PENDING-ARCHIVE: Trying to get trx from table', {destination: destination, product: product, created_date: created_date});
 
 
-    const query = "SELECT trx_id FROM pendingtrx WHERE created_date = ? AND destination = ? AND product = ? ";
+    const query = "SELECT trx_id FROM pendingtrx WHERE created_date = ? AND destination = ? AND product = ? ORDER BY created DESC LIMIT 1";
     db.get(query, created_date, destination, product, function (err, row) {
         if (err) {
             logger.warn('PENDING-ARCHIVE: Error retrieving', {destination: destination, product: product, created_date: created_date, err: err});
diff --git a/lib/sms-handler.js b/lib/sms-handler.js
index 7a31c2f..a070bc2 100644
--- a/lib/sms-handler.js
+++ b/lib/sms-handler.js
@@ -14,7 +14,7 @@ function isAllowedSender(sender) {
 function getDestination(msg) {
     const result = patternMatcher(msg, config.sms_parser.destination);
     if (result && typeof result === 'string') {
-        return result.replace(/^62/, '0');
+        return result.replace(/^62/, '0').replace(/^8/, '08');
     }
 }
 
diff --git a/package-lock.json b/package-lock.json
index 63b68a3..534bf43 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1267,11 +1267,6 @@
           "version": "5.1.1",
           "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
           "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
-        },
-        "statuses": {
-          "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
-          "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
         }
       }
     },
@@ -1392,11 +1387,6 @@
           "requires": {
             "ms": "2.0.0"
           }
-        },
-        "statuses": {
-          "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
-          "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
         }
       }
     },
@@ -2081,7 +2071,7 @@
         "depd": "1.1.2",
         "inherits": "2.0.3",
         "setprototypeof": "1.1.0",
-        "statuses": "1.5.0"
+        "statuses": "1.4.0"
       }
     },
     "http-signature": {
@@ -3540,11 +3530,6 @@
           "requires": {
             "ms": "2.0.0"
           }
-        },
-        "statuses": {
-          "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
-          "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
         }
       }
     },
@@ -4020,9 +4005,9 @@
       }
     },
     "statuses": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+      "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
     },
     "strftime": {
       "version": "0.10.0",
diff --git a/package.json b/package.json
index da06b9f..92d00c3 100644
--- a/package.json
+++ b/package.json
@@ -23,9 +23,11 @@
   "license": "SEE LICENSE IN LICENSE.txt",
   "dependencies": {
     "cron": "^1.3.0",
+    "express": "^4.16.3",
     "jsesc": "^2.5.1",
     "komodo-sdk": "git+http://gitlab.kodesumber.com/komodo/komodo-sdk.git",
     "moment": "^2.22.2",
+    "nunjucks": "^3.1.3",
     "serialport": "^6.2.2",
     "sqlite3": "^4.0.2"
   },
diff --git a/pid.txt b/pid.txt
index 42324a4..b606877 100644
--- a/pid.txt
+++ b/pid.txt
@@ -1 +1 @@
-28464
\ No newline at end of file
+6300
\ No newline at end of file