QuecManger 1.0.0
Release Notes: Enhanced Web App Architecture: - Optimized the structure for better scalability and maintainability. - Refined Data Fetching Logic: Improved the efficiency and reliability of data retrieval processes. - Optimized AT Terminal: Enhanced functionality for smoother interaction with AT commands. - Revamped UI/UX Design: Streamlined user interface and experience for improved accessibility and usability. New Features: - MTU Settings: Added customizable Maximum Transmission Unit (MTU) settings. - APN and IMEI Profiles: Introduced the ability to configure APN and IMEI profiles for better device management. - Persistent Cell Locking: Added native support for persistent cell locking, ensuring consistent network connections. - QuecWatch: Connection monitoring with auto reconnect and reboot settable Co-Authored-By: Russel Yasol <73575327+dr-dolomite@users.noreply.github.com>
This commit is contained in:
1
ipk-source/sdxpinn-quecmanager/CONTROL/conffiles
Executable file
1
ipk-source/sdxpinn-quecmanager/CONTROL/conffiles
Executable file
@@ -0,0 +1 @@
|
||||
/etc/quecManager.conf
|
||||
@@ -1,6 +1,7 @@
|
||||
Package: sdxpinn-quecmanager
|
||||
Version: 0.0.3
|
||||
Version: 1.0.0
|
||||
Architecture: aarch64_cortex-a53
|
||||
Maintainer: Russel Yasol dr-dolomite@github.com Cameron Thompson iamromulan@github.com
|
||||
Description: A custom web UI desgined to run alongside luci for Quectel RM55x modems
|
||||
Depends: libc sdxpinn-mount-fix atinout
|
||||
Conflicts: sdxpinn-quecmanager-beta
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/ash
|
||||
|
||||
mv /www/index.html /www/index.html.old
|
||||
mv /www/login.html /www/index.html
|
||||
cp /www/login.html /www/index.html
|
||||
exit 0
|
||||
|
||||
|
||||
4
ipk-source/sdxpinn-quecmanager/root/etc/quecManager.conf
Normal file
4
ipk-source/sdxpinn-quecmanager/root/etc/quecManager.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
AT_port = dev/smd11
|
||||
AT_port_custom = dev/smd7
|
||||
data_refresh_rate = 5000
|
||||
# end of config (don't remove this line)
|
||||
1
ipk-source/sdxpinn-quecmanager/root/www/404.html
Normal file
1
ipk-source/sdxpinn-quecmanager/root/www/404.html
Normal file
File diff suppressed because one or more lines are too long
1
ipk-source/sdxpinn-quecmanager/root/www/404/index.html
Normal file
1
ipk-source/sdxpinn-quecmanager/root/www/404/index.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7409],{66325:function(e,t,n){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_not-found/page",function(){return n(89094)}])},89094:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}}),n(88806);let i=n(20881);n(64149);let o={fontFamily:'system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',height:"100vh",textAlign:"center",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"},l={display:"inline-block"},r={display:"inline-block",margin:"0 20px 0 0",padding:"0 23px 0 0",fontSize:24,fontWeight:500,verticalAlign:"top",lineHeight:"49px"},d={fontSize:14,fontWeight:400,lineHeight:"49px",margin:0};function s(){return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("title",{children:"404: This page could not be found."}),(0,i.jsx)("div",{style:o,children:(0,i.jsxs)("div",{children:[(0,i.jsx)("style",{dangerouslySetInnerHTML:{__html:"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}),(0,i.jsx)("h1",{className:"next-error-h1",style:r,children:"404"}),(0,i.jsx)("div",{style:l,children:(0,i.jsx)("h2",{style:d,children:"This page could not be found."})})]})})]})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},function(e){e.O(0,[8985,5330,1744],function(){return e(e.s=66325)}),_N_E=e.O()}]);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1060],{89460:function(t,e,a){Promise.resolve().then(a.bind(a,27442))},27442:function(t,e,a){"use strict";a.r(e);var s=a(20881);a(64149);var n=a(27525),d=a(26509);e.default=t=>{let{children:e}=t,a=(0,n.usePathname)();return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("div",{className:"mx-auto grid w-full max-w-6xl gap-2",children:(0,s.jsx)("h1",{className:"text-3xl font-semibold",children:"Advanced Settings"})}),(0,s.jsxs)("div",{className:"mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]",children:[(0,s.jsxs)("nav",{className:"grid gap-4 text-sm text-muted-foreground","x-chunk":"dashboard-04-chunk-0",children:[(0,s.jsx)(d.default,{href:"/dashboard/advanced-settings/connectivity",className:"".concat("/dashboard/advanced-settings/connectivity/"===a?"font-semibold text-primary":"text-sm"),children:"Connectivity"}),(0,s.jsx)(d.default,{href:"/dashboard/advanced-settings/ttl-settings",className:"".concat("/dashboard/advanced-settings/ttl-settings/"===a?"font-semibold text-primary":"text-sm"),children:"TTL Settings"}),(0,s.jsx)(d.default,{href:"/dashboard/advanced-settings/mtu",className:"".concat("/dashboard/advanced-settings/mtu/"===a?"font-semibold text-primary":"text-sm"),children:"MTU Settings"}),(0,s.jsx)(d.default,{href:"/dashboard/advanced-settings/at-terminal",className:"".concat("/dashboard/advanced-settings/at-terminal/"===a?"font-semibold text-primary":"text-sm"),children:"AT Terminal"})]}),e]})]})}},27525:function(t,e,a){"use strict";var s=a(39886);a.o(s,"usePathname")&&a.d(e,{usePathname:function(){return s.usePathname}}),a.o(s,"useRouter")&&a.d(e,{useRouter:function(){return s.useRouter}})}},function(t){t.O(0,[6509,8985,5330,1744],function(){return t(t.s=89460)}),_N_E=t.O()}]);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1159],{37946:function(e,s,t){Promise.resolve().then(t.bind(t,78700))},78700:function(e,s,t){"use strict";t.r(s);var a=t(20881);t(64149);var l=t(27525),n=t(26509);s.default=e=>{let{children:s}=e,t=(0,l.usePathname)();return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("div",{className:"mx-auto grid w-full max-w-6xl gap-2",children:(0,a.jsx)("h1",{className:"text-3xl font-semibold",children:"Cellular Settings"})}),(0,a.jsxs)("div",{className:"mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]",children:[(0,a.jsxs)("nav",{className:"grid gap-4 text-sm text-muted-foreground","x-chunk":"dashboard-04-chunk-0",children:[(0,a.jsx)(n.default,{href:"/dashboard/cell-settings/basic-settings",className:"".concat("/dashboard/cell-settings/basic-settings/"===t?"font-semibold text-primary":"text-sm"),children:"Basic Settings"}),(0,a.jsx)(n.default,{href:"/dashboard/cell-settings/band-locking",className:"".concat("/dashboard/cell-settings/band-locking/"===t?"font-semibold text-primary":"text-sm"),children:"Band Locking"}),(0,a.jsx)(n.default,{href:"/dashboard/cell-settings/cell-locking",className:"".concat("/dashboard/cell-settings/cell-locking/"===t?"font-semibold text-primary":"text-sm"),children:"Cellular Locking"}),(0,a.jsx)(n.default,{href:"/dashboard/cell-settings/imei-mangling",className:"".concat("/dashboard/cell-settings/imei-mangling/"===t?"font-semibold text-primary":"text-sm"),children:"IMEI Mangling"}),(0,a.jsx)(n.default,{href:"/dashboard/cell-settings/sms",className:"".concat("/dashboard/cell-settings/sms/"===t?"font-semibold text-primary":"text-sm"),children:"SMS Inbox"})]}),s]})]})}},27525:function(e,s,t){"use strict";var a=t(39886);t.o(a,"usePathname")&&t.d(s,{usePathname:function(){return a.usePathname}}),t.o(a,"useRouter")&&t.d(s,{useRouter:function(){return a.useRouter}})}},function(e){e.O(0,[6509,8985,5330,1744],function(){return e(e.s=37946)}),_N_E=e.O()}]);
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[5342],{97017:function(e,t,a){Promise.resolve().then(a.bind(a,98496))},98496:function(e,t,a){"use strict";a.r(t);var s=a(20881);a(64149);var r=a(27525),n=a(26509);t.default=e=>{let{children:t}=e,a=(0,r.usePathname)();return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("div",{className:"mx-auto grid w-full max-w-6xl gap-2",children:(0,s.jsx)("h1",{className:"text-3xl font-semibold",children:"Experimental"})}),(0,s.jsxs)("div",{className:"mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]",children:[(0,s.jsx)("nav",{className:"grid gap-4 text-sm text-muted-foreground","x-chunk":"dashboard-04-chunk-0",children:(0,s.jsx)(n.default,{href:"/dashboard/experimental/quecwatch",className:"".concat("/dashboard/experimental/quecwatch/"===a?"font-semibold text-primary":"text-sm"),children:"QuecWatch"})}),t]})]})}},27525:function(e,t,a){"use strict";var s=a(39886);a.o(s,"usePathname")&&a.d(t,{usePathname:function(){return s.usePathname}}),a.o(s,"useRouter")&&a.d(t,{useRouter:function(){return s.useRouter}})}},function(e){e.O(0,[6509,8985,5330,1744],function(){return e(e.s=97017)}),_N_E=e.O()}]);
|
||||
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7387],{43682:function(){}},function(n){n.O(0,[8985,5330,1744],function(){return n(n.s=43682)}),_N_E=n.O()}]);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[813],{67238:function(e,t,s){Promise.resolve().then(s.bind(s,83746))},83746:function(e,t,s){"use strict";s.r(t);var a=s(20881);s(64149);var r=s(27525),n=s(26509);t.default=e=>{let{children:t}=e,s=(0,r.usePathname)();return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("div",{className:"mx-auto grid w-full max-w-6xl gap-2",children:(0,a.jsx)("h1",{className:"text-3xl font-semibold",children:"Settings"})}),(0,a.jsxs)("div",{className:"mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]",children:[(0,a.jsxs)("nav",{className:"grid gap-4 text-sm text-muted-foreground","x-chunk":"dashboard-04-chunk-0",children:[(0,a.jsx)(n.default,{href:"/dashboard/settings/general",className:"".concat("/dashboard/settings/general/"===s?"font-semibold text-primary":"text-sm"),children:"General"}),(0,a.jsx)(n.default,{href:"/dashboard/settings/security",className:"".concat("/dashboard/settings/security/"===s?"font-semibold text-primary":"text-sm"),children:"Security"})]}),t]})]})}},27525:function(e,t,s){"use strict";var a=s(39886);s.o(a,"usePathname")&&s.d(t,{usePathname:function(){return a.usePathname}}),s.o(a,"useRouter")&&s.d(t,{useRouter:function(){return a.useRouter}})}},function(e){e.O(0,[6509,8985,5330,1744],function(){return e(e.s=67238)}),_N_E=e.O()}]);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3197],{84773:function(a,t,h){h.d(t,{GWp:function(){return r}});var n=h(83111);function r(a){return(0,n.w_)({tag:"svg",attr:{fill:"currentColor",viewBox:"0 0 16 16"},child:[{tag:"path",attr:{d:"m11.646.44.897.896-1.703 1.703A1.5 1.5 0 0 0 10.5 3h-5A1.5 1.5 0 0 0 4 4.5v5.379l-2 2V1.5A1.5 1.5 0 0 1 3.5 0h7.086a1.5 1.5 0 0 1 1.06.44M8.5 5.378 9.879 4H8.5zM5 8.879 6.879 7H5zm6-1.758L9.121 9H11zm-3.5 3.5L6.121 12H7.5zM5.5 13q-.175 0-.34-.039L2.502 15.62c.265.236.615.38.998.38h9a1.5 1.5 0 0 0 1.5-1.5V4.121l-2 2V11.5a1.5 1.5 0 0 1-1.5 1.5zM5 4.5a.5.5 0 0 1 .5-.5h2v2H5zM8.5 10H11v1.5a.5.5 0 0 1-.5.5h-2zm6.354-8.146a.5.5 0 0 0-.708-.708l-13 13a.5.5 0 0 0 .708.708z"},child:[]}]})(a)}}}]);
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1744],{7137:function(e,n,t){Promise.resolve().then(t.t.bind(t,81013,23)),Promise.resolve().then(t.t.bind(t,78073,23)),Promise.resolve().then(t.t.bind(t,41626,23)),Promise.resolve().then(t.t.bind(t,16102,23)),Promise.resolve().then(t.t.bind(t,84262,23)),Promise.resolve().then(t.t.bind(t,22609,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[8985,5330],function(){return n(90039),n(7137)}),_N_E=e.O()}]);
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2888],{79452:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_app",function(){return u(84820)}])}},function(n){var _=function(_){return n(n.s=_)};n.O(0,[9774,179],function(){return _(79452),_(26699)}),_N_E=n.O()}]);
|
||||
@@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[4820],{17022:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_error",function(){return u(63936)}])}},function(n){n.O(0,[2888,9774,179],function(){return n(n.s=17022)}),_N_E=n.O()}]);
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(){"use strict";var e,t,n,r,o,u,i,c,f,a={},l={};function d(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={id:e,loaded:!1,exports:{}},r=!0;try{a[e].call(n.exports,n,n.exports,d),r=!1}finally{r&&delete l[e]}return n.loaded=!0,n.exports}d.m=a,e=[],d.O=function(t,n,r,o){if(n){o=o||0;for(var u=e.length;u>0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[n,r,o];return}for(var i=1/0,u=0;u<e.length;u++){for(var n=e[u][0],r=e[u][1],o=e[u][2],c=!0,f=0;f<n.length;f++)i>=o&&Object.keys(d.O).every(function(e){return d.O[e](n[f])})?n.splice(f--,1):(c=!1,o<i&&(i=o));if(c){e.splice(u--,1);var a=r();void 0!==a&&(t=a)}}return t},d.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return d.d(t,{a:t}),t},n=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},d.t=function(e,r){if(1&r&&(e=this(e)),8&r||"object"==typeof e&&e&&(4&r&&e.__esModule||16&r&&"function"==typeof e.then))return e;var o=Object.create(null);d.r(o);var u={};t=t||[null,n({}),n([]),n(n)];for(var i=2&r&&e;"object"==typeof i&&!~t.indexOf(i);i=n(i))Object.getOwnPropertyNames(i).forEach(function(t){u[t]=function(){return e[t]}});return u.default=function(){return e},d.d(o,u),o},d.d=function(e,t){for(var n in t)d.o(t,n)&&!d.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},d.f={},d.e=function(e){return Promise.all(Object.keys(d.f).reduce(function(t,n){return d.f[n](e,t),t},[]))},d.u=function(e){},d.miniCssF=function(e){},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r={},o="_N_E:",d.l=function(e,t,n,u){if(r[e]){r[e].push(t);return}if(void 0!==n)for(var i,c,f=document.getElementsByTagName("script"),a=0;a<f.length;a++){var l=f[a];if(l.getAttribute("src")==e||l.getAttribute("data-webpack")==o+n){i=l;break}}i||(c=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,d.nc&&i.setAttribute("nonce",d.nc),i.setAttribute("data-webpack",o+n),i.src=d.tu(e)),r[e]=[t];var s=function(t,n){i.onerror=i.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach(function(e){return e(n)}),t)return t(n)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=s.bind(null,i.onerror),i.onload=s.bind(null,i.onload),c&&document.head.appendChild(i)},d.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.nmd=function(e){return e.paths=[],e.children||(e.children=[]),e},d.tt=function(){return void 0===u&&(u={createScriptURL:function(e){return e}},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(u=trustedTypes.createPolicy("nextjs#bundler",u))),u},d.tu=function(e){return d.tt().createScriptURL(e)},d.p="/_next/",i={2272:0,736:0},d.f.j=function(e,t){var n=d.o(i,e)?i[e]:void 0;if(0!==n){if(n)t.push(n[2]);else if(/^(2272|736)$/.test(e))i[e]=0;else{var r=new Promise(function(t,r){n=i[e]=[t,r]});t.push(n[2]=r);var o=d.p+d.u(e),u=Error();d.l(o,function(t){if(d.o(i,e)&&(0!==(n=i[e])&&(i[e]=void 0),n)){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;u.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",u.name="ChunkLoadError",u.type=r,u.request=o,n[1](u)}},"chunk-"+e,e)}}},d.O.j=function(e){return 0===i[e]},c=function(e,t){var n,r,o=t[0],u=t[1],c=t[2],f=0;if(o.some(function(e){return 0!==i[e]})){for(n in u)d.o(u,n)&&(d.m[n]=u[n]);if(c)var a=c(d)}for(e&&e(t);f<o.length;f++)r=o[f],d.o(i,r)&&i[r]&&i[r][0](),i[r]=0;return d.O(a)},(f=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(c.bind(null,0)),f.push=c.bind(null,f.push.bind(f)),d.nc=void 0}();
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-185f70b36b33d607.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
||||
@@ -0,0 +1 @@
|
||||
self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
||||
@@ -1,328 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
|
||||
<!-- Logo -->
|
||||
<link rel="logo" href="favicon.ico" />
|
||||
|
||||
<link rel="stylesheet" href="css/bulma/bulma.scss" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.min.css" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.css" />
|
||||
<link rel="stylesheet" href="css/custom.css" />
|
||||
|
||||
<!-- Font awesome icons -->
|
||||
<script
|
||||
src="https://kit.fontawesome.com/b0caedfab3.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
<script src="js/styles/toggle-theme.js"></script>
|
||||
<script src="/js/styles/nav-burger.js"></script>
|
||||
<script src="/js/styles/modal-trigger.js"></script>
|
||||
<script src="/js/utils/reboot.js"></script>
|
||||
<script src="/js/utils/restart-connection.js"></script>
|
||||
<script defer src="/js/auth/auth.js"></script>
|
||||
<script src="/js/about/fetch-data.js"></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const savedTheme = localStorage.getItem("theme") || "theme-dark";
|
||||
document.documentElement.classList.add(savedTheme);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<title>QuecManager</title>
|
||||
</head>
|
||||
|
||||
<body class="body-margin">
|
||||
<nav class="navbar is-transparent">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
<img src="/assets/logo.png" alt="Logo" />
|
||||
<span class="title">QuecManager</span>
|
||||
</a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
data-target="navMenu"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navMenu" class="navbar-menu">
|
||||
<div class="navbar-start ml-6">
|
||||
<a class="navbar-item" href="/"> Home </a>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link"> Cellular </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/cell-settings.html"
|
||||
>Cell Settings</a
|
||||
>
|
||||
<a class="navbar-item" href="/bandlock.html"> Band Locking </a>
|
||||
<a class="navbar-item" href="/cell-locking.html">Cell Locking</a>
|
||||
<a class="navbar-item" href="/cell-scanner.html">Cell Scanner</a>
|
||||
<a class="navbar-item" href="/cell-sms.html"> Cell SMS </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link"> Advance </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/advance-settings.html">
|
||||
Advance Settings
|
||||
</a>
|
||||
<a class="navbar-item" href="#">Experimental Features</a>
|
||||
<a class="navbar-item" href="/cgi-bin/luci">OpenWRT Luci</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="navbar-item has-text-weight-bold" href="/about.html">
|
||||
About
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons is-flex-direction-column-mobile">
|
||||
<div class="control is-expanded-mobile">
|
||||
<div
|
||||
id="restartConnectionBtn"
|
||||
class="button is-link is-outlined is-fullwidth-mobile"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-arrows-rotate"></i>
|
||||
</span>
|
||||
<span>Restart Connection</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-flex is-mobile is-align-items-center">
|
||||
<div class="control">
|
||||
<div
|
||||
class="button is-warning is-outlined reboot-modal"
|
||||
data-target="reboot-modal"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-power-off"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-sun"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
id="logoutButton"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-right-from-bracket"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="column-margin">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid">
|
||||
<div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">Device Information</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<table class="table is-fullwidth is-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Modem Manufacturer</td>
|
||||
<th id="manufacturer">Fetching...</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Modem Model Name</td>
|
||||
<th id="model"></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Firmware Version</td>
|
||||
<th id="firmwareVersion"></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LTE Category</td>
|
||||
<th id="lteCategory"></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Phone Number</td>
|
||||
<th id="phoneNumber"></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IMSI</td>
|
||||
<th id="imsi"></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ICCID</td>
|
||||
<th id="iccid"></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IMEI</td>
|
||||
<th>
|
||||
<div class="field has-addons is-hidden-mobile">
|
||||
<div class="control">
|
||||
<input
|
||||
class="input has-text-weight-semibold"
|
||||
type="text"
|
||||
placeholder="IMEI Here"
|
||||
id="imeiInput"
|
||||
/>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-link" id="changeButton">Change</button>
|
||||
</div>
|
||||
</div>
|
||||
<span class="is-block-mobile is-hidden" id="imei">
|
||||
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LAN GATEWAY</td>
|
||||
<th id="lanIP">
|
||||
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>WWAN IPv4</td>
|
||||
<th id="IPv4">
|
||||
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>WWAN IPv6</td>
|
||||
<th style="word-break: break-all" id="IPv6">
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">About Us</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<p class="title">QuecManager</p>
|
||||
<p class="subtitle mt-2">
|
||||
Simple Admin began as part of the RGMII toolkit, offering
|
||||
users a basic GUI. However, with our fork and continued
|
||||
development, it has evolved to include more advanced
|
||||
features, making "simple" no longer an ideal name for the
|
||||
dashboard. Despite this shift, we remain committed to
|
||||
providing advanced functionality while maintaining an
|
||||
intuitive and user-friendly GUI.
|
||||
</p>
|
||||
|
||||
<p class="subtitle mt-6 has-text-weight-bold">Thanks to</p>
|
||||
<ul class="has-text-weight-semibold">
|
||||
<li>
|
||||
RGMII Toolkit and Documentation
|
||||
<a href="https://github.com/iamromulan" target="_blank"
|
||||
>iamromulan</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
Simple Admin 2.0 and QuecManager
|
||||
<a href="https://github.com/dr-dolomite" target="_blank"
|
||||
>dr-dolomite</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
SMS Feature
|
||||
<a href="https://github.com/snjzb" target="_blank"
|
||||
>snjzb</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
Original Simple Admin
|
||||
<a href="https://github.com/aesthernr" target="_blank"
|
||||
>aesthernr</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
Original Socat Bridge
|
||||
<a href="https://github.com/natecarlson" target="_blank"
|
||||
>natecarlson</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
Initial Original Simple Admin Fixes
|
||||
<a href="https://github.com/rbflurry/" target="_blank"
|
||||
>rbflurry</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
Wutang Clan
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="content has-text-centered">
|
||||
<p>
|
||||
<strong>
|
||||
<a href="https://github.com/iamromulan/quectel-rgmii-toolkit.git"
|
||||
>QuecManager</a
|
||||
></strong
|
||||
>
|
||||
version 1.0. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="reboot-modal" class="modal">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<section class="modal-card-body rounded-edge">
|
||||
<p class="subtitle" id="modal-message">
|
||||
Do not do any action while the modem is rebooting.
|
||||
</p>
|
||||
<div id="loading-content" style="display: none">
|
||||
<div class="custom-loader"></div>
|
||||
<div class="countdown-text">
|
||||
Rebooting... <span id="countdown">80</span>s
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons" id="modal-buttons">
|
||||
<button class="button is-warning" id="rebootModem">Reboot</button>
|
||||
<button class="button cancel" aria-label="close">Cancel</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,532 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
|
||||
<!-- Logo -->
|
||||
<link rel="simpleadmin-logo" href="favicon.ico" />
|
||||
|
||||
<link rel="stylesheet" href="css/bulma/bulma.scss" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.min.css" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.css" />
|
||||
<link rel="stylesheet" href="css/custom.css" />
|
||||
|
||||
<!-- Font awesome icons -->
|
||||
<script
|
||||
src="https://kit.fontawesome.com/b0caedfab3.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
<script src="js/styles/toggle-theme.js"></script>
|
||||
<script src="/js/styles/nav-burger.js"></script>
|
||||
<script src="/js/styles/modal-trigger.js"></script>
|
||||
<script src="/js/utils/reboot.js"></script>
|
||||
<script src="/js/utils/restart-connection.js"></script>
|
||||
<script defer src="/js/auth/auth.js"></script>
|
||||
<script src="/js/advance/at-terminal.js"></script>
|
||||
<script src="/js/advance/ttl-control.js"></script>
|
||||
<script src="/js/advance/fetch-current-settings.js"></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const savedTheme = localStorage.getItem("theme") || "theme-dark";
|
||||
document.documentElement.classList.add(savedTheme);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<title>QuecManager</title>
|
||||
</head>
|
||||
|
||||
<body class="body-margin">
|
||||
<nav class="navbar is-transparent">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
<img src="/assets/logo.png" alt="Logo" />
|
||||
<span class="title">QuecManager</span>
|
||||
</a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
data-target="navMenu"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navMenu" class="navbar-menu">
|
||||
<div class="navbar-start ml-6">
|
||||
<a class="navbar-item" href="/"> Home </a>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link"> Cellular </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/cell-settings.html"
|
||||
>Cell Settings</a
|
||||
>
|
||||
<a class="navbar-item" href="/bandlock.html"> Band Locking </a>
|
||||
<a class="navbar-item" href="/cell-locking.html">Cell Locking</a>
|
||||
<a class="navbar-item" href="/cell-scanner.html">Cell Scanner</a>
|
||||
<a class="navbar-item" href="/cell-sms.html"> Cell SMS </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link has-text-weight-bold"> Advance </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/advance-settings.html">
|
||||
Advance Settings
|
||||
</a>
|
||||
<a class="navbar-item" href="#">Experimental Features</a>
|
||||
<a class="navbar-item" href="/cgi-bin/luci">OpenWRT Luci</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="navbar-item" href="/about.html"> About </a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons is-flex-direction-column-mobile">
|
||||
<div class="control is-expanded-mobile">
|
||||
<div
|
||||
id="restartConnectionBtn"
|
||||
class="button is-link is-outlined is-fullwidth-mobile"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-arrows-rotate"></i>
|
||||
</span>
|
||||
<span>Restart Connection</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-flex is-mobile is-align-items-center">
|
||||
<div class="control">
|
||||
<div
|
||||
class="button is-warning is-outlined reboot-modal"
|
||||
data-target="reboot-modal"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-power-off"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-sun"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
id="logoutButton"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-right-from-bracket"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="column-margin">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="card-header-title">AT Command Terminal</p>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<form id="commandForm">
|
||||
<div class="field">
|
||||
<label class="label">Output</label>
|
||||
<div class="control">
|
||||
<textarea
|
||||
class="textarea"
|
||||
id="output"
|
||||
rows="10"
|
||||
readonly
|
||||
placeholder="AT command responses will appear here..."
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-hidden-touch">
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<div class="level-item">
|
||||
<label class="label">Command History</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
<div class="level-item">
|
||||
<button
|
||||
type="button"
|
||||
id="clearHistory"
|
||||
class="button is-small is-link has-text-white"
|
||||
>
|
||||
Clear All
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="command-history" id="commandHistory">
|
||||
<div class="no-history" id="noHistory">No commands yet</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
id="command"
|
||||
placeholder="Enter AT command (e.g., ATI)"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
<div class="control" style="position: relative">
|
||||
<button
|
||||
type="submit"
|
||||
class="button is-link"
|
||||
id="sendButton"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
</span>
|
||||
<span>Send</span>
|
||||
</button>
|
||||
<span id="cooldownTimer"></span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">Advance Settings</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-1-cols">
|
||||
<div class="grid is-gap-5">
|
||||
<div class="cell advanced-settings">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid">
|
||||
<div class="cell is-col-span-2 is-col-span-1-mobile">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label">IP Passthrough Mode</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="ip-passthrough-mode">
|
||||
<option value="placeholder" selected>
|
||||
Select IP Passthrough Mode
|
||||
</option>
|
||||
<option value="Disabled">Disabled</option>
|
||||
<option value="ETH Only">ETH Only</option>
|
||||
<option value="USB Only">USB Only</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-ethernet"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
This will reboot the device to apply changes.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
>Connected Devices MAC</label
|
||||
>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="connected-devices">
|
||||
<option selected>
|
||||
Select Device MAC
|
||||
</option>
|
||||
<!-- Populate the options here -->
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-laptop"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
Selecting a device first before enabling.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell advanced-settings">
|
||||
<div class="field">
|
||||
<label class="label">USB Modem Protocol</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="usb-modem-protocol">
|
||||
<option selected>
|
||||
Select USB Modem Protocol
|
||||
</option>
|
||||
<option value="RMNET">RMNET</option>
|
||||
<option value="ECM (Recommended)">
|
||||
ECM (Recommended)
|
||||
</option>
|
||||
<option value="MBIM">MBIM</option>
|
||||
<option value="RNDIS">RNDIS</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-network-wired"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
Selecting a mode will apply immediately. Requires
|
||||
reboot.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell advanced-settings">
|
||||
<div class="field">
|
||||
<label class="label">Onboard DNS Proxy Mode</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="dns-proxy-mode">
|
||||
<option selected>
|
||||
Select Onboard DNS Proxy
|
||||
</option>
|
||||
<option value="Enabled">Enabled</option>
|
||||
<option value="Disabled">Disabled</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-server"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
Selecting a mode will apply immediately.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="cell">
|
||||
<div class="fixed-grid has-2-cols">
|
||||
<div class="grid is-gap-3">
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">TTL State</label>
|
||||
<div class="control has-icons-right">
|
||||
<input
|
||||
class="input is-danger"
|
||||
placeholder="Disabled"
|
||||
disabled
|
||||
/>
|
||||
<span class="icon is-small is-right">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">TTL Value</label>
|
||||
<div class="control has-icons-right">
|
||||
<input
|
||||
class="input is-danger"
|
||||
placeholder="0"
|
||||
disabled
|
||||
/>
|
||||
<span class="icon is-small is-right">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-2">
|
||||
<div class="field">
|
||||
<label class="label">TTL Value to Set</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="number"
|
||||
placeholder="Custom TTL Value"
|
||||
value="bulma"
|
||||
/>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-wifi"></i>
|
||||
</span>
|
||||
</div>
|
||||
<p class="help is-success has-text-weight-semibold">
|
||||
Set the TTL Value to 0 to disable.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="cell">
|
||||
<div class="fixed-grid has-2-cols">
|
||||
<div class="grid is-gap-3">
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">TTL State</label>
|
||||
<div class="control has-icons-right">
|
||||
<input
|
||||
id="ttl-state"
|
||||
class="input is-warning has-text-weight-bold"
|
||||
placeholder="Disabled"
|
||||
disabled
|
||||
/>
|
||||
<span class="icon is-small is-right">
|
||||
<i
|
||||
class="fas fa-exclamation-triangle has-text-warning"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">Current TTL Value</label>
|
||||
<div class="control has-icons-right">
|
||||
<input
|
||||
id="ttl-current-value"
|
||||
class="input is-warning has-text-weight-bold has-text-white"
|
||||
placeholder="0"
|
||||
disabled
|
||||
/>
|
||||
<span class="icon is-small is-right">
|
||||
<i
|
||||
class="fas fa-exclamation-triangle has-text-warning"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-2">
|
||||
<div class="field">
|
||||
<label class="label">TTL Value to Set</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
id="ttl-set-value"
|
||||
class="input"
|
||||
type="number"
|
||||
placeholder="Custom TTL Value"
|
||||
/>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-wifi"></i>
|
||||
</span>
|
||||
</div>
|
||||
<p class="help is-success has-text-weight-semibold">
|
||||
Set the TTL Value to 0 to disable.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
id="ttl-submit"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Apply TTL Settings
|
||||
</a>
|
||||
<a
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="content">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid">
|
||||
<div class="cell">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>Information</span>
|
||||
</div>
|
||||
|
||||
<p class="block has-text-weight-semibold">
|
||||
Use AT custom commands only if you know what you are doing.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>Information</span>
|
||||
</div>
|
||||
|
||||
<p class="block has-text-weight-semibold">
|
||||
Selecting a mode will apply immediately and will also disconnect
|
||||
from the network.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="reboot-modal" class="modal">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<section class="modal-card-body rounded-edge">
|
||||
<p class="subtitle" id="modal-message">
|
||||
Do not do any action while the modem is rebooting.
|
||||
</p>
|
||||
<div id="loading-content" style="display: none">
|
||||
<div class="custom-loader"></div>
|
||||
<div class="countdown-text">
|
||||
Rebooting... <span id="countdown">90</span>s
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons" id="modal-buttons">
|
||||
<button class="button is-warning" id="rebootModem">Reboot</button>
|
||||
<button class="button cancel" aria-label="close">Cancel</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,680 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
|
||||
<!-- Logo -->
|
||||
<link rel="simpleadmin-logo" href="favicon.ico" />
|
||||
|
||||
<link rel="stylesheet" href="css/bulma/bulma.scss" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.min.css" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.css" />
|
||||
<link rel="stylesheet" href="css/custom.css" />
|
||||
|
||||
<!-- Font awesome icons -->
|
||||
<script
|
||||
src="https://kit.fontawesome.com/b0caedfab3.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
<script src="js/styles/toggle-theme.js"></script>
|
||||
<script src="/js/styles/nav-burger.js"></script>
|
||||
<script src="/js/styles/modal-trigger.js"></script>
|
||||
<script src="/js/utils/reboot.js"></script>
|
||||
<script src="/js/utils/restart-connection.js"></script>
|
||||
<script defer src="/js/auth/auth.js"></script>
|
||||
<script src="/js/band-locking/fetch-bands.js"></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const savedTheme = localStorage.getItem("theme") || "theme-dark";
|
||||
document.documentElement.classList.add(savedTheme);
|
||||
})();
|
||||
</script>
|
||||
<title>QuecManager</title>
|
||||
</head>
|
||||
|
||||
<body class="body-margin">
|
||||
<nav class="navbar is-transparent">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
<img src="/assets/logo.png" alt="Logo" />
|
||||
<span class="title">QuecManager</span>
|
||||
</a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
data-target="navMenu"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navMenu" class="navbar-menu">
|
||||
<div class="navbar-start ml-6">
|
||||
<a class="navbar-item" href="/"> Home </a>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link has-text-weight-bold"> Cellular </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/cell-settings.html"
|
||||
>Cell Settings</a
|
||||
>
|
||||
<a class="navbar-item" href="/bandlock.html"> Band Locking </a>
|
||||
<a class="navbar-item" href="/cell-locking.html">Cell Locking</a>
|
||||
<a class="navbar-item" href="/cell-scanner.html">Cell Scanner</a>
|
||||
<a class="navbar-item" href="/cell-sms.html"> Cell SMS </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link"> Advance </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/advance-settings.html">
|
||||
Advance Settings
|
||||
</a>
|
||||
<a class="navbar-item" href="#">Experimental Features</a>
|
||||
<a class="navbar-item" href="/cgi-bin/luci">OpenWRT Luci</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="navbar-item" href="/about.html"> About </a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons is-flex-direction-column-mobile">
|
||||
<div class="control is-expanded-mobile">
|
||||
<div
|
||||
id="restartConnectionBtn"
|
||||
class="button is-link is-outlined is-fullwidth-mobile"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-arrows-rotate"></i>
|
||||
</span>
|
||||
<span>Restart Connection</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-flex is-mobile is-align-items-center">
|
||||
<div class="control">
|
||||
<div
|
||||
class="button is-warning is-outlined reboot-modal"
|
||||
data-target="reboot-modal"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-power-off"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-sun"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
id="logoutButton"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-right-from-bracket"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="column-margin">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid is-gap-5">
|
||||
<div class="cell is-col-span-2 is-col-span-1-mobile">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">4G LTE Band Locking</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-5-cols has-3-cols-mobile">
|
||||
<div class="grid" id="lte_bands">
|
||||
<!-- LTE bands will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
id="lockLte"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Lock LTE Bands
|
||||
</a>
|
||||
<a
|
||||
id="uncheckLte"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Uncheck All
|
||||
</a>
|
||||
<a
|
||||
id="resetLte"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">5G-NR SA Band Locking</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-5-cols has-3-cols-mobile">
|
||||
<div class="grid" id="sa_bands">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
id="lockSa"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Lock SA Bands
|
||||
</a>
|
||||
<a
|
||||
id="uncheckSa"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Uncheck All
|
||||
</a>
|
||||
<a
|
||||
id="resetSa"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">5G-NR NSA Band Locking</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-5-cols has-3-cols-mobile">
|
||||
<div class="grid" id="nsa_bands">
|
||||
<!-- NSA bands will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
id="lockNsa"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Lock NSA Bands
|
||||
</a>
|
||||
<a
|
||||
id="uncheckNsa"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Uncheck All
|
||||
</a>
|
||||
<a
|
||||
id="resetNsa"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">5G-NR SA-DC Band Locking</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-5-cols has-3-cols-mobile">
|
||||
<div class="grid" id="sanrdc_bands">
|
||||
<!-- SA bands will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
id="lockSaDc"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Lock SA-DC Bands
|
||||
</a>
|
||||
<a
|
||||
id="uncheckSaDc"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Uncheck All
|
||||
</a>
|
||||
<a
|
||||
id="resetSaDc"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="content">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid">
|
||||
<div class="cell">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>Information</span>
|
||||
</div>
|
||||
|
||||
<p class="block has-text-weight-semibold">
|
||||
If problem persists after locking bands, please reboot the
|
||||
modem.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>Current Active Bands</span>
|
||||
</div>
|
||||
|
||||
<p class="block has-text-weight-semibold" id="currentBands"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="reboot-modal" class="modal">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<section class="modal-card-body rounded-edge">
|
||||
<p class="subtitle" id="modal-message">
|
||||
Do you want to reboot the device?
|
||||
</p>
|
||||
<div id="loading-content" style="display: none">
|
||||
<div class="custom-loader"></div>
|
||||
<div class="countdown-text">
|
||||
Rebooting... <span id="countdown">90</span>s
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons" id="modal-buttons">
|
||||
<button class="button is-warning" id="rebootModem">Reboot</button>
|
||||
<button class="button cancel" aria-label="close">Cancel</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <script>
|
||||
// Function to fetch current active bands and display them in the footer
|
||||
async function fetchCurrentBands() {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body: "command=" + encodeURIComponent("AT+QCAINFO"),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
// Extract active bands
|
||||
// Find the lines that contains "LTE BAND <band number>" or "NR5G BAND <band number>" and append them to the currentBands variable
|
||||
const lteBands = data.output.match(/LTE BAND ([0-9]+)/g) || [];
|
||||
const nrBands = data.output.match(/NR5G BAND ([0-9]+)/g) || [];
|
||||
// Combine the two arrays and join them with a comma
|
||||
if (lteBands.length === 0 && nrBands.length === 0) {
|
||||
document.getElementById("currentBands").textContent =
|
||||
"No active bands found";
|
||||
return;
|
||||
} else if (lteBands.length === 0) {
|
||||
document.getElementById("currentBands").textContent =
|
||||
nrBands.join(", ");
|
||||
return;
|
||||
} else if (nrBands.length === 0) {
|
||||
document.getElementById("currentBands").textContent =
|
||||
lteBands.join(", ");
|
||||
return;
|
||||
} else {
|
||||
document.getElementById("currentBands").textContent = [
|
||||
...lteBands,
|
||||
...nrBands,
|
||||
].join(", ");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching current bands:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to fetch supported bands via AT command and populate the checkboxes
|
||||
async function fetchSupportedBands() {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body:
|
||||
"command=" + encodeURIComponent('AT+QNWPREFCFG="policy_band"'),
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
const lteBandsMatch = data.output.match(/"lte_band",([0-9:]+)/);
|
||||
const nsaBandsMatch = data.output.match(/"nsa_nr5g_band",([0-9:]+)/);
|
||||
// const saBandsMatch = data.output.match(/"nr5g_band",([0-9:]+)/);
|
||||
const saDcBandsMatch = data.output.match(
|
||||
/"nrdc_nr5g_band",([0-9:]+)/
|
||||
);
|
||||
|
||||
if (lteBandsMatch) populateBands(lteBandsMatch[1], "#lte_bands");
|
||||
// if (saBandsMatch) populateBands(saBandsMatch[1], "#sa_bands");
|
||||
if (nsaBandsMatch) populateBands(nsaBandsMatch[1], "#nsa_bands");
|
||||
if (saDcBandsMatch) populateBands(saDcBandsMatch[1], "#sanrdc_bands");
|
||||
|
||||
fetchActiveBands();
|
||||
} catch (error) {
|
||||
console.error("Error fetching supported bands:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to fetch currently active bands and mark the checkboxes accordingly
|
||||
async function fetchActiveBands() {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body:
|
||||
"command=" +
|
||||
encodeURIComponent(
|
||||
'AT+QNWPREFCFG="lte_band";+QNWPREFCFG="nsa_nr5g_band";+QNWPREFCFG="nr5g_band";+QNWPREFCFG="nrdc_nr5g_band"'
|
||||
),
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
// Remove the first line of the output
|
||||
data.output = data.output.split("\n").slice(1).join("\n");
|
||||
|
||||
// Remove "OK" line
|
||||
data.output = data.output.replace("OK", "");
|
||||
|
||||
console.log(data.output);
|
||||
|
||||
// Extract active bands
|
||||
const activeLteBands = data.output
|
||||
.match(/"lte_band",([0-9:]+)/)[1]
|
||||
.split(":");
|
||||
const activeNsaBands = data.output
|
||||
.match(/"nsa_nr5g_band",([0-9:]+)/)[1]
|
||||
.split(":");
|
||||
// const activeSaBands = data.output
|
||||
// .match(/"nr5g_band",([0-9:]+)/)[1]
|
||||
// .split(":");
|
||||
// get the the second to the last line of the output and use it for active sa-dc bands
|
||||
const activeSaDcBandsLine = data.output
|
||||
.split("\n")[6]
|
||||
.match(/"nr5g_band",([0-9:]+)/)[1]
|
||||
.split(":");
|
||||
|
||||
// // Mark checkboxes as checked for active bands
|
||||
markActiveBands(activeLteBands, "#lte_bands");
|
||||
markActiveBands(activeNsaBands, "#nsa_bands");
|
||||
// markActiveBands(activeSaBands, "#sa_bands");
|
||||
markActiveBands(activeSaDcBandsLine, "#sanrdc_bands");
|
||||
|
||||
// Fetch current active bands and display them in the footer
|
||||
fetchCurrentBands();
|
||||
} catch (error) {
|
||||
console.error("Error fetching active bands:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to populate bands in the target element
|
||||
function populateBands(bandsString, targetId) {
|
||||
var bandsArray = bandsString.split(":");
|
||||
var html = "";
|
||||
|
||||
for (var i = 0; i < bandsArray.length; i++) {
|
||||
html += `<div class="cell">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" value="${bandsArray[i]}" /> B${bandsArray[i]}
|
||||
</label>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
document.querySelector(targetId).innerHTML = html;
|
||||
}
|
||||
|
||||
// Function to mark checkboxes as checked based on active bands
|
||||
function markActiveBands(activeBands, targetId) {
|
||||
const checkboxes = document.querySelectorAll(
|
||||
`${targetId} input[type="checkbox"]`
|
||||
);
|
||||
checkboxes.forEach((checkbox) => {
|
||||
if (activeBands.includes(checkbox.value)) {
|
||||
checkbox.setAttribute("checked", "checked");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to uncheck all checkboxes in the target element
|
||||
function uncheckAll(targetId) {
|
||||
const checkboxes = document.querySelectorAll(
|
||||
`${targetId} input[type="checkbox"]`
|
||||
);
|
||||
checkboxes.forEach((checkbox) => {
|
||||
checkbox.removeAttribute("checked");
|
||||
checkbox.checked = false; // Also update the state programmatically
|
||||
});
|
||||
}
|
||||
|
||||
// Event listeners for "Uncheck All" buttons
|
||||
document
|
||||
.getElementById("uncheckLte")
|
||||
.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
uncheckAll("#lte_bands");
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("uncheckNsa")
|
||||
.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
uncheckAll("#nsa_bands");
|
||||
});
|
||||
|
||||
// document
|
||||
// .getElementById("uncheckSa")
|
||||
// .addEventListener("click", function (event) {
|
||||
// event.preventDefault();
|
||||
// uncheckAll("#sa_bands");
|
||||
// });
|
||||
|
||||
document
|
||||
.getElementById("uncheckSaDc")
|
||||
.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
uncheckAll("#sanrdc_bands");
|
||||
});
|
||||
|
||||
// Locking the Bands
|
||||
// Function to get checked bands and generate AT command
|
||||
function getCheckedBandsCommand(targetId, commandType) {
|
||||
const checkboxes = document.querySelectorAll(
|
||||
`${targetId} input[type="checkbox"]:checked`
|
||||
);
|
||||
const checkedBands = Array.from(checkboxes)
|
||||
.map((cb) => cb.value)
|
||||
.sort((a, b) => a - b);
|
||||
|
||||
if (checkedBands.length === 0) {
|
||||
return null; // Return null if no bands are selected
|
||||
}
|
||||
|
||||
const bandString = checkedBands.join(":");
|
||||
return `AT+QNWPREFCFG="${commandType}",${bandString}`;
|
||||
}
|
||||
|
||||
// Function to send AT command via atinout
|
||||
async function sendATCommand(command) {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: `command=${encodeURIComponent(command)}`,
|
||||
});
|
||||
const data = await response.json();
|
||||
return data;
|
||||
|
||||
// refetch active bands after successful command
|
||||
fetchActiveBands();
|
||||
} catch (error) {
|
||||
console.error("Error sending AT command:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle band locking for a specific type
|
||||
async function lockBands(targetId, commandType) {
|
||||
const command = getCheckedBandsCommand(targetId, commandType);
|
||||
if (!command) {
|
||||
alert("Please select at least one band to lock.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await sendATCommand(command);
|
||||
alert(
|
||||
`Successfully locked ${commandType
|
||||
.split("_")[0]
|
||||
.toUpperCase()} bands`
|
||||
);
|
||||
} catch (error) {
|
||||
alert(`Failed to lock bands: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Event listeners for Lock buttons
|
||||
document
|
||||
.getElementById("lockLte")
|
||||
.addEventListener("click", () => lockBands("#lte_bands", "lte_band"));
|
||||
|
||||
document
|
||||
.getElementById("lockNsa")
|
||||
.addEventListener("click", () =>
|
||||
lockBands("#nsa_bands", "nsa_nr5g_band")
|
||||
);
|
||||
|
||||
document
|
||||
.getElementById("lockSa")
|
||||
.addEventListener("click", () => lockBands("#sa_bands", "nr5g_band"));
|
||||
|
||||
document
|
||||
.getElementById("lockSaDc")
|
||||
.addEventListener("click", () =>
|
||||
lockBands("#sanrdc_bands", "nrdc_nr5g_band")
|
||||
);
|
||||
|
||||
// Event listeners for Reset buttons
|
||||
|
||||
// Function to reset and check all checkboxes for a given band type
|
||||
function resetBands(targetId, bandType) {
|
||||
const checkboxes = document.querySelectorAll(
|
||||
`${targetId} input[type="checkbox"]`
|
||||
);
|
||||
let selectedBands = [];
|
||||
|
||||
// Check all checkboxes and gather their values
|
||||
checkboxes.forEach((checkbox) => {
|
||||
checkbox.setAttribute("checked", "checked");
|
||||
checkbox.checked = true;
|
||||
selectedBands.push(checkbox.value);
|
||||
});
|
||||
|
||||
// Create and send the AT command with all bands
|
||||
sendBandLockCommand(selectedBands, bandType);
|
||||
}
|
||||
|
||||
// Function to send the AT command to lock the bands
|
||||
async function sendBandLockCommand(bands, bandType) {
|
||||
// Join the selected bands with ":" separator for the AT command
|
||||
const bandString = bands.join(":");
|
||||
const command = `AT+QNWPREFCFG="${bandType}",${bandString}`;
|
||||
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body: "command=" + encodeURIComponent(command),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
console.log(
|
||||
`Band lock command for ${bandType} executed:`,
|
||||
data.output
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error sending band lock command for ${bandType}:`,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Event listeners for "Reset" buttons
|
||||
document
|
||||
.getElementById("resetLte")
|
||||
.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
resetBands("#lte_bands", "lte_band");
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("resetNsa")
|
||||
.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
resetBands("#nsa_bands", "nsa_nr5g_band");
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("resetSa")
|
||||
.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
resetBands("#sa_bands", "nr5g_band");
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("resetSaDc")
|
||||
.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
resetBands("#sanrdc_bands", "nrdc_nr5g_band");
|
||||
});
|
||||
|
||||
// Initial call to fetch supported bands on page load
|
||||
window.onload = fetchSupportedBands;
|
||||
</script> -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,450 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
|
||||
<!-- Logo -->
|
||||
<link rel="simpleadmin-logo" href="favicon.ico" />
|
||||
|
||||
<link rel="stylesheet" href="css/bulma/bulma.scss" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.min.css" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.css" />
|
||||
<link rel="stylesheet" href="css/custom.css" />
|
||||
|
||||
<!-- Font awesome icons -->
|
||||
<script
|
||||
src="https://kit.fontawesome.com/b0caedfab3.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
<script src="js/styles/toggle-theme.js"></script>
|
||||
<script src="/js/styles/nav-burger.js"></script>
|
||||
<script src="/js/styles/modal-trigger.js"></script>
|
||||
<script src="/js/utils/reboot.js"></script>
|
||||
<script src="/js/utils/restart-connection.js"></script>
|
||||
<script src="/js/cell-locking/cell-lock.js"></script>
|
||||
<script defer src="/js/auth/auth.js"></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const savedTheme = localStorage.getItem("theme") || "theme-dark";
|
||||
document.documentElement.classList.add(savedTheme);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<title>QuecManager</title>
|
||||
</head>
|
||||
|
||||
<body class="body-margin">
|
||||
<nav class="navbar is-transparent">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
<img src="/assets/logo.png" alt="Logo" />
|
||||
<span class="title">QuecManager</span>
|
||||
</a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
data-target="navMenu"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navMenu" class="navbar-menu">
|
||||
<div class="navbar-start ml-6">
|
||||
<a class="navbar-item" href="/"> Home </a>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link has-text-weight-bold"> Cellular </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/cell-settings.html"
|
||||
>Cell Settings</a
|
||||
>
|
||||
<a class="navbar-item" href="/bandlock.html"> Band Locking </a>
|
||||
<a class="navbar-item" href="/cell-locking.html">Cell Locking</a>
|
||||
<a class="navbar-item" href="/cell-scanner.html">Cell Scanner</a>
|
||||
<a class="navbar-item" href="/cell-sms.html"> Cell SMS </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link"> Advance </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/advance-settings.html">
|
||||
Advance Settings
|
||||
</a>
|
||||
<a class="navbar-item" href="#">Experimental Features</a>
|
||||
<a class="navbar-item" href="/cgi-bin/luci">OpenWRT Luci</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="navbar-item" href="/about.html"> About </a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons is-flex-direction-column-mobile">
|
||||
<div class="control is-expanded-mobile">
|
||||
<div
|
||||
id="restartConnectionBtn"
|
||||
class="button is-link is-outlined is-fullwidth-mobile"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-arrows-rotate"></i>
|
||||
</span>
|
||||
<span>Restart Connection</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-flex is-mobile is-align-items-center">
|
||||
<div class="control">
|
||||
<div
|
||||
class="button is-warning is-outlined reboot-modal"
|
||||
data-target="reboot-modal"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-power-off"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-sun"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
id="logoutButton"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-right-from-bracket"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="column-margin">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">4G LTE Cell Locking</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-2-cols">
|
||||
<div class="grid">
|
||||
<!-- Entry 1 Start -->
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">EARFCN 1</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="email"
|
||||
id="earfcn1"
|
||||
placeholder="EARFCN"
|
||||
/>
|
||||
<span class="icon is-left">
|
||||
<i class="fas fa-bolt"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">PCI 1</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="email"
|
||||
placeholder="PCI"
|
||||
id="pci1"
|
||||
/>
|
||||
<span class="icon is-left">
|
||||
<i class="fa-solid fa-signal"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Entry 1 End -->
|
||||
|
||||
<!-- Entry 2 Start -->
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">EARFCN 2</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="email"
|
||||
placeholder="EARFCN"
|
||||
id="earfcn2"
|
||||
/>
|
||||
<span class="icon is-left">
|
||||
<i class="fas fa-bolt"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">PCI 2</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="email"
|
||||
placeholder="PCI"
|
||||
id="pci2"
|
||||
/>
|
||||
<span class="icon is-left">
|
||||
<i class="fa-solid fa-signal"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Entry 2 End -->
|
||||
|
||||
<!-- Entry 3 Start -->
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">EARFCN 3</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="email"
|
||||
placeholder="EARFCN"
|
||||
id="earfcn3"
|
||||
/>
|
||||
<span class="icon is-left">
|
||||
<i class="fas fa-bolt"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">PCI 3</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="email"
|
||||
placeholder="PCI"
|
||||
id="pci3"
|
||||
/>
|
||||
<span class="icon is-left">
|
||||
<i class="fa-solid fa-signal"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Entry 3 End -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
href="#"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
id="saveLTE"
|
||||
>
|
||||
Lock LTE Cells
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="#"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
id="resetLTE"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">5G-NR SA Cell Locking</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-2-cols">
|
||||
<div class="grid">
|
||||
<!-- Entry 1 Start -->
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">NR ARFCN</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="email"
|
||||
placeholder="NR-ARFCN"
|
||||
id="nr-arfcn"
|
||||
/>
|
||||
<span class="icon is-left">
|
||||
<i class="fas fa-bolt"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">NR PCI</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="email"
|
||||
placeholder="NR PCI"
|
||||
id="nr-pci"
|
||||
/>
|
||||
<span class="icon is-left">
|
||||
<i class="fa-solid fa-signal"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Entry 1 End -->
|
||||
|
||||
<!-- Entry 2 Start -->
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">SCS</label>
|
||||
<div class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="scs">
|
||||
<option selected>Select SCS</option>
|
||||
<option value="15">15 kHz</option>
|
||||
<option value="30">30 kHz</option>
|
||||
<option value="60">60 kHz</option>
|
||||
<option value="120">120 kHz</option>
|
||||
<option value="240">240 kHz</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-left">
|
||||
<i class="fas fa-bolt"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">NR Band</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
class="input"
|
||||
type="email"
|
||||
placeholder="NR Band"
|
||||
id="nr-band"
|
||||
/>
|
||||
<span class="icon is-left">
|
||||
<i class="fa-solid fa-signal"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Entry 2 End -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
href="#"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
id="saveSA"
|
||||
>
|
||||
Lock SA Cells
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="#"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
id="resetSA"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="content">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid">
|
||||
<div class="cell">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>Information</span>
|
||||
</div>
|
||||
|
||||
<p class="block has-text-weight-semibold">
|
||||
Cell locking is an advance feature and may cause network
|
||||
interruptions. <br />
|
||||
Cell locking will also only work with the main band (PCC) if you
|
||||
are using carrier aggregation.
|
||||
<br />
|
||||
Proceed with caution.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>NR-5G Cell Locking</span>
|
||||
</div>
|
||||
|
||||
<p class="block has-text-weight-semibold">
|
||||
The NR-5G cell locking feature is only available on 5G-NR SA mode. <br />
|
||||
This will also change the preferred network mode to NR5G.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="reboot-modal" class="modal">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<section class="modal-card-body rounded-edge">
|
||||
<p class="subtitle" id="modal-message">
|
||||
Do you want to reboot the device?
|
||||
</p>
|
||||
<div id="loading-content" style="display: none">
|
||||
<div class="custom-loader"></div>
|
||||
<div class="countdown-text">
|
||||
Rebooting... <span id="countdown">90</span>s
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons" id="modal-buttons">
|
||||
<button class="button is-warning" id="rebootModem">Reboot</button>
|
||||
<button class="button cancel" aria-label="close">Cancel</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,312 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
|
||||
<!-- Logo -->
|
||||
<link rel="simpleadmin-logo" href="favicon.ico" />
|
||||
|
||||
<link rel="stylesheet" href="css/bulma/bulma.scss" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.min.css" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.css" />
|
||||
<link rel="stylesheet" href="css/custom.css" />
|
||||
|
||||
<!-- Font awesome icons -->
|
||||
<script
|
||||
src="https://kit.fontawesome.com/b0caedfab3.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
<script src="js/styles/toggle-theme.js"></script>
|
||||
<script src="/js/styles/nav-burger.js"></script>
|
||||
<script src="/js/styles/modal-trigger.js"></script>
|
||||
<script src="/js/utils/reboot.js"></script>
|
||||
<script src="/js/utils/restart-connection.js"></script>
|
||||
<script src="/js/cell-scanner/cell-scanner.js"></script>
|
||||
<script defer src="/js/auth/auth.js"></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const savedTheme = localStorage.getItem("theme") || "theme-dark";
|
||||
document.documentElement.classList.add(savedTheme);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<title>QuecManager</title>
|
||||
</head>
|
||||
|
||||
<body class="body-margin">
|
||||
<nav class="navbar is-transparent">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
<img src="/assets/logo.png" alt="Logo" />
|
||||
<span class="title">QuecManager</span>
|
||||
</a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
data-target="navMenu"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navMenu" class="navbar-menu">
|
||||
<div class="navbar-start ml-6">
|
||||
<a class="navbar-item" href="/"> Home </a>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link has-text-weight-bold"> Cellular </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/cell-settings.html"
|
||||
>Cell Settings</a
|
||||
>
|
||||
<a class="navbar-item" href="/bandlock.html"> Band Locking </a>
|
||||
<a class="navbar-item" href="/cell-locking.html">Cell Locking</a>
|
||||
<a class="navbar-item" href="/cell-scanner.html">Cell Scanner</a>
|
||||
<a class="navbar-item" href="/cell-sms.html"> Cell SMS </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link"> Advance </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/advance-settings.html">
|
||||
Advance Settings
|
||||
</a>
|
||||
<a class="navbar-item" href="#">Experimental Features</a>
|
||||
<a class="navbar-item" href="/cgi-bin/luci">OpenWRT Luci</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="navbar-item" href="/about.html"> About </a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons is-flex-direction-column-mobile">
|
||||
<div class="control is-expanded-mobile">
|
||||
<div
|
||||
id="restartConnectionBtn"
|
||||
class="button is-link is-outlined is-fullwidth-mobile"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-arrows-rotate"></i>
|
||||
</span>
|
||||
<span>Restart Connection</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-flex is-mobile is-align-items-center">
|
||||
<div class="control">
|
||||
<div
|
||||
class="button is-warning is-outlined reboot-modal"
|
||||
data-target="reboot-modal"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-power-off"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-sun"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
id="logoutButton"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-right-from-bracket"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="column-margin">
|
||||
<div class="fixed-grid has-1-cols">
|
||||
<div class="grid is-gap-5">
|
||||
<div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="card-header-title">
|
||||
Full Network Provider Cell Scanner
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<!-- <table class="table is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Network Provider</th>
|
||||
<th>Name</th>
|
||||
<th>EARFCN</th>
|
||||
<th>Bandwidth</th>
|
||||
<th>Physical ID</th>
|
||||
<th class="is-hidden-mobile">RSRP</th>
|
||||
<th class="is-hidden-mobile">RSRQ</th>
|
||||
<th class="is-hidden-mobile">SINR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="fullCellScanTableBody">
|
||||
<tr>
|
||||
<td>Smart</td>
|
||||
<td>B1</td>
|
||||
<td>150</td>
|
||||
<td>10</td>
|
||||
<td>623</td>
|
||||
<td class="is-hidden-mobile">
|
||||
<div class="tags has-addons">
|
||||
<span class="tag is-size-6">-103</span>
|
||||
<span class="tag is-danger is-size-6 has-text-white"
|
||||
>Poor</span
|
||||
>
|
||||
</div>
|
||||
</td>
|
||||
<td class="is-hidden-mobile">
|
||||
<div class="tags has-addons">
|
||||
<span class="tag is-size-6">-103</span>
|
||||
<span class="tag is-danger is-size-6 has-text-white"
|
||||
>Poor</span
|
||||
>
|
||||
</div>
|
||||
</td>
|
||||
<td class="is-hidden-mobile">
|
||||
<div class="tags has-addons">
|
||||
<span class="tag is-size-6">-5</span>
|
||||
<span class="tag is-danger is-size-6 has-text-white"
|
||||
>Poor</span
|
||||
>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table> -->
|
||||
<p>
|
||||
Still under development. Please check back later for updates.
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
href="#"
|
||||
id="startFullScanBtn"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Start Full Scan
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
id="resetFullScanBtn"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">Full Neighbour Cell Scanner</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<table class="table is-fullwidth" id="neighbourCellTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>EARFCN</th>
|
||||
<th>Physical ID</th>
|
||||
<th class="is-hidden-mobile">RSRP</th>
|
||||
<th class="is-hidden-mobile">RSRQ</th>
|
||||
<th class="is-hidden-mobile">RSSI</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="neighbourCellTableBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
href="#"
|
||||
id="startLTEScanBtn"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Start LTE Neighbourcell Scan
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
id="startNR5GScanBtn"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Start NR5G Neighbourcell Scan
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
id="resetScanBtn"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="content">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>Full Network Provider Cell Scanner</span>
|
||||
</div>
|
||||
<p class="block has-text-weight-semibold">
|
||||
This command is recommended to be used when there is no (U)SIM card.
|
||||
<br />
|
||||
This command does not apply to 5G cells in NSA mode.
|
||||
<br />
|
||||
Scanning will take a few minutes so please wait patiently.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="reboot-modal" class="modal">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<section class="modal-card-body rounded-edge">
|
||||
<p class="subtitle" id="modal-message">
|
||||
Do you want to reboot the device?
|
||||
</p>
|
||||
<div id="loading-content" style="display: none">
|
||||
<div class="custom-loader"></div>
|
||||
<div class="countdown-text">
|
||||
Rebooting... <span id="countdown">90</span>s
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons" id="modal-buttons">
|
||||
<button class="button is-warning" id="rebootModem">Reboot</button>
|
||||
<button class="button cancel" aria-label="close">Cancel</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,486 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
|
||||
<!-- Logo -->
|
||||
<link rel="simpleadmin-logo" href="favicon.ico" />
|
||||
|
||||
<link rel="stylesheet" href="css/bulma/bulma.scss" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.min.css" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.css" />
|
||||
<link rel="stylesheet" href="css/custom.css" />
|
||||
|
||||
<!-- Font awesome icons -->
|
||||
<script
|
||||
src="https://kit.fontawesome.com/b0caedfab3.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
<script src="js/styles/toggle-theme.js"></script>
|
||||
<script src="/js/styles/nav-burger.js"></script>
|
||||
<script src="/js/styles/modal-trigger.js"></script>
|
||||
<script src="/js/utils/reboot.js"></script>
|
||||
<script src="/js/utils/restart-connection.js"></script>
|
||||
<script src="/js/cell-settings/fetch-settings.js"></script>
|
||||
<script src="/js/cell-settings/apn-profile.js"></script>
|
||||
<script defer src="/js/auth/auth.js"></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const savedTheme = localStorage.getItem("theme") || "theme-dark";
|
||||
document.documentElement.classList.add(savedTheme);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<title>QuecManager</title>
|
||||
</head>
|
||||
|
||||
<body class="body-margin">
|
||||
<nav class="navbar is-transparent">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
<img src="/assets/logo.png" alt="Logo" />
|
||||
<span class="title">QuecManager</span>
|
||||
</a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
data-target="navMenu"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navMenu" class="navbar-menu">
|
||||
<div class="navbar-start ml-6">
|
||||
<a class="navbar-item" href="/"> Home </a>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link has-text-weight-bold"> Cellular </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/cell-settings.html"
|
||||
>Cell Settings</a
|
||||
>
|
||||
<a class="navbar-item" href="/bandlock.html"> Band Locking </a>
|
||||
<a class="navbar-item" href="/cell-locking.html">Cell Locking</a>
|
||||
<a class="navbar-item" href="/cell-scanner.html">Cell Scanner</a>
|
||||
<a class="navbar-item" href="/cell-sms.html"> Cell SMS </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link"> Advance </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/advance-settings.html">
|
||||
Advance Settings
|
||||
</a>
|
||||
<a class="navbar-item" href="#">Experimental Features</a>
|
||||
<a class="navbar-item" href="/cgi-bin/luci">OpenWRT Luci</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="navbar-item" href="/about.html"> About </a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons is-flex-direction-column-mobile">
|
||||
<div class="control is-expanded-mobile">
|
||||
<div
|
||||
id="restartConnectionBtn"
|
||||
class="button is-link is-outlined is-fullwidth-mobile"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-arrows-rotate"></i>
|
||||
</span>
|
||||
<span>Restart Connection</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-flex is-mobile is-align-items-center">
|
||||
<div class="control">
|
||||
<div
|
||||
class="button is-warning is-outlined reboot-modal"
|
||||
data-target="reboot-modal"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-power-off"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-sun"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
id="logoutButton"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-right-from-bracket"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="column-margin">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">Basic Cellular Settings</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid is-gap-5">
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">Current APN</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="Current APN Here"
|
||||
id="currentAPN"
|
||||
/>
|
||||
</div>
|
||||
<p class="help">
|
||||
Changing this will disable automatic APN.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">APN PDP Type</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="apnPDP">
|
||||
<option selected>Select APN PDP Type</option>
|
||||
<option value="IP">IPv4 Only</option>
|
||||
<option value="IPV6">IPv6 Only</option>
|
||||
<option value="IPV4V6">IPv4 and IPv6</option>
|
||||
<option value="PPP">P2P Protocol</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-globe"></i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">Preferred Network Mode</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="networkPreference">
|
||||
<option value="placeholder" selected>
|
||||
Select Preferred Network Mode
|
||||
</option>
|
||||
<option value="AUTO">Automatic</option>
|
||||
<option value="LTE">LTE Only</option>
|
||||
<option value="NR5G">5G SA Only</option>
|
||||
<option value="LTE:NR5G">5G NSA Only</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-signal"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
Selecting a mode will apply immediately.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">NR5G Mode Control</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="nr5gModeControl">
|
||||
<option selected>Select NR5G Mode Control</option>
|
||||
<option value="0">Enable NR5G SA and NSA</option>
|
||||
<option value="2">Enable SA Only</option>
|
||||
<option value="1">Enable NSA Only</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-podcast"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
Selecting a mode will apply immediately.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">U-SIM Slot Configuration</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="simSlot">
|
||||
<option value="">Select active SIM slot</option>
|
||||
<option value="1">SIM Slot 1</option>
|
||||
<option value="2">SIM Slot 2</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-sim-card" id="simCardIcon"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
Selecting a mode will apply immediately.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
href="#"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Save APN
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset APN
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<div class="card" id="apnProfileForm">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">APN and ICCID Based Locking</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-1-cols">
|
||||
<div class="grid is-gap-5">
|
||||
<div class="cell">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid is-gap-3">
|
||||
<div class="cell is-col-span-2-mobile">
|
||||
<div class="field">
|
||||
<label class="label">APN Profile 1</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="APN Here"
|
||||
id="apnProfile1"
|
||||
/>
|
||||
</div>
|
||||
<p class="help">
|
||||
This will override the current APN.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-2-mobile">
|
||||
<div class="field">
|
||||
<label class="label">APN PDP Type</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="apnPDPType1">
|
||||
<option selected>Select APN PDP Type</option>
|
||||
<option value="IP">IPv4 Only</option>
|
||||
<option value="IPV6">IPv6 Only</option>
|
||||
<option value="IPV4V6">IPv4 and IPv6</option>
|
||||
<option value="PPP">P2P Protocol</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-globe"></i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-2">
|
||||
<div class="field">
|
||||
<label class="label">ICCID Profile 1</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="ICCID Here"
|
||||
id="iccidProfile1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="fixed-grid has-2-cols">
|
||||
<div class="grid is-gap-3">
|
||||
<div class="cell is-col-span-2-mobile">
|
||||
<div class="field">
|
||||
<label class="label">APN Profile 2</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="APN Here"
|
||||
id="apnProfile2"
|
||||
/>
|
||||
</div>
|
||||
<p class="help">
|
||||
This will override the current APN.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-2-mobile">
|
||||
<div class="field">
|
||||
<label class="label">APN PDP Type</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="apnPDPType2">
|
||||
<option selected>Select APN PDP Type</option>
|
||||
<option value="IP">IPv4 Only</option>
|
||||
<option value="IPV6">IPv6 Only</option>
|
||||
<option value="IPV4V6">IPv4 and IPv6</option>
|
||||
<option value="PPP">P2P Protocol</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-globe"></i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-2">
|
||||
<div class="field">
|
||||
<label class="label">ICCID Profile 2</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="ICCID Here"
|
||||
id="iccidProfile2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
href="#"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
id="saveAPNProfile"
|
||||
>
|
||||
Save APN Profile
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
id="resetAPNProfile"
|
||||
>
|
||||
Reset APN Profile
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="content">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid">
|
||||
<div class="cell">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>Information</span>
|
||||
</div>
|
||||
|
||||
<p class="block has-text-weight-semibold">
|
||||
Changing APN disconnects and reconnects the network
|
||||
automatically.
|
||||
<br />
|
||||
If problem persists after changing settings, please reboot the
|
||||
modem.
|
||||
<br />
|
||||
Please use the settings with caution.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>Information</span>
|
||||
</div>
|
||||
|
||||
<p class="block has-text-weight-semibold">
|
||||
APN and ICCID Based Locking will use a stored APN profile based
|
||||
on the current SIM's ICCID.
|
||||
<br />
|
||||
Currently experimental.
|
||||
<br />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="reboot-modal" class="modal">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<section class="modal-card-body rounded-edge">
|
||||
<p class="subtitle" id="modal-message">
|
||||
Do you want to reboot the device?
|
||||
</p>
|
||||
<div id="loading-content" style="display: none">
|
||||
<div class="custom-loader"></div>
|
||||
<div class="countdown-text">
|
||||
Rebooting... <span id="countdown">90</span>s
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons" id="modal-buttons">
|
||||
<button class="button is-warning" id="rebootModem">Reboot</button>
|
||||
<button class="button cancel" aria-label="close">Cancel</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,286 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
|
||||
<!-- Logo -->
|
||||
<link rel="simpleadmin-logo" href="favicon.ico" />
|
||||
|
||||
<link rel="stylesheet" href="css/bulma/bulma.scss" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.min.css" />
|
||||
<link rel="stylesheet" href="css/bulma/css/bulma.css" />
|
||||
<link rel="stylesheet" href="css/custom.css" />
|
||||
|
||||
<!-- Font awesome icons -->
|
||||
<script
|
||||
src="https://kit.fontawesome.com/b0caedfab3.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
<script src="js/styles/toggle-theme.js"></script>
|
||||
<script src="/js/styles/nav-burger.js"></script>
|
||||
<script src="/js/styles/modal-trigger.js"></script>
|
||||
<script src="/js/utils/reboot.js"></script>
|
||||
<script src="/js/utils/restart-connection.js"></script>
|
||||
<script src="/js/cell-sms/sms-manager.js"></script>
|
||||
<script defer src="/js/auth/auth.js"></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const savedTheme = localStorage.getItem("theme") || "theme-dark";
|
||||
document.documentElement.classList.add(savedTheme);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<title>QuecManager</title>
|
||||
</head>
|
||||
|
||||
<body class="body-margin">
|
||||
<nav class="navbar is-transparent">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
<img src="/assets/logo.png" alt="Logo" />
|
||||
<span class="title">QuecManager</span>
|
||||
</a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
data-target="navMenu"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navMenu" class="navbar-menu">
|
||||
<div class="navbar-start ml-6">
|
||||
<a class="navbar-item" href="/"> Home </a>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link has-text-weight-bold"> Cellular </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/cell-settings.html"
|
||||
>Cell Settings</a
|
||||
>
|
||||
<a class="navbar-item" href="/bandlock.html"> Band Locking </a>
|
||||
<a class="navbar-item" href="/cell-locking.html">Cell Locking</a>
|
||||
<a class="navbar-item" href="/cell-scanner.html">Cell Scanner</a>
|
||||
<a class="navbar-item" href="/cell-sms.html"> Cell SMS </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link"> Advance </a>
|
||||
<div class="navbar-dropdown is-boxed">
|
||||
<a class="navbar-item" href="/advance-settings.html">
|
||||
Advance Settings
|
||||
</a>
|
||||
<a class="navbar-item" href="#">Experimental Features</a>
|
||||
<a class="navbar-item" href="/cgi-bin/luci">OpenWRT Luci</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="navbar-item" href="/about.html"> About </a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons is-flex-direction-column-mobile">
|
||||
<div class="control is-expanded-mobile">
|
||||
<div
|
||||
id="restartConnectionBtn"
|
||||
class="button is-link is-outlined is-fullwidth-mobile"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-arrows-rotate"></i>
|
||||
</span>
|
||||
<span>Restart Connection</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-flex is-mobile is-align-items-center">
|
||||
<div class="control">
|
||||
<div
|
||||
class="button is-warning is-outlined reboot-modal"
|
||||
data-target="reboot-modal"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-power-off"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-sun"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
<p class="control ml-2 is-mobile">
|
||||
<a
|
||||
href="#"
|
||||
class="button is-warning is-outlined js-theme-toggle"
|
||||
id="logoutButton"
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="fas fa-right-from-bracket"></i>
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="column-margin">
|
||||
<div class="fixed-grid has-1-cols">
|
||||
<div class="grid is-gap-5">
|
||||
<div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">SMS Inbox</div>
|
||||
</div>
|
||||
|
||||
<div class="card-content">
|
||||
<div
|
||||
class="fixed-grid has-1-cols"
|
||||
style="height: 450px; overflow-y: scroll"
|
||||
>
|
||||
<!-- This is where messages will be inserted -->
|
||||
<div id="sms-container" class="grid is-gap-4 is-fullwidth">
|
||||
<!-- Messages will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<a
|
||||
href="#"
|
||||
id="refresh-sms"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Refresh
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="#"
|
||||
id="delete-selected-sms"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Delete Selected
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-header-title">Send SMS</div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-5-cols has-1-cols-mobile">
|
||||
<div class="grid">
|
||||
<div class="cell is-col-span-1">
|
||||
<div class="field">
|
||||
<label class="label">Recipient's Phone Number</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
id="phone-number-input"
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="Input Phone Number"
|
||||
/>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-user"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-5 is-col-span-1-mobile">
|
||||
<div class="field">
|
||||
<label class="label">Message</label>
|
||||
<div class="control">
|
||||
<textarea
|
||||
id="message-input"
|
||||
class="textarea"
|
||||
placeholder="Enter your message here"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
href="#"
|
||||
id="send-sms"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Send SMS
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="#"
|
||||
id="reset-form"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="content">
|
||||
<div class="is-flex is-flex-direction-column is-align-items-center">
|
||||
<div class="has-text-centered">
|
||||
<div class="icon-text">
|
||||
<span class="icon has-text-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<span>Information</span>
|
||||
</div>
|
||||
|
||||
<p class="block has-text-weight-semibold">
|
||||
This is an experimental feature and may cause an error in some
|
||||
cases.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="reboot-modal" class="modal">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<section class="modal-card-body rounded-edge">
|
||||
<p class="subtitle" id="modal-message">
|
||||
Do you want to reboot the device?
|
||||
</p>
|
||||
<div id="loading-content" style="display: none">
|
||||
<div class="custom-loader"></div>
|
||||
<div class="countdown-text">
|
||||
Rebooting... <span id="countdown">90</span>s
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons" id="modal-buttons">
|
||||
<button class="button is-warning" id="rebootModem">Reboot</button>
|
||||
<button class="button cancel" aria-label="close">Cancel</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Define the lock file
|
||||
LOCK_FILE="/tmp/home_data.lock"
|
||||
|
||||
# Acquire the lock (wait if needed)
|
||||
exec 200>$LOCK_FILE
|
||||
flock -x 200
|
||||
|
||||
# Temporary files for input/output and AT port
|
||||
INPUT_FILE="/tmp/input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/output_$$.txt"
|
||||
AT_PORT="/dev/smd11"
|
||||
|
||||
# Debug file path
|
||||
DEBUG_FILE="/tmp/debug-json-result.txt"
|
||||
|
||||
# Function to escape JSON strings (handling quotes and newlines)
|
||||
escape_json() {
|
||||
# Escape newlines and double quotes
|
||||
echo "$1" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g'
|
||||
}
|
||||
|
||||
# Initialize JSON response array
|
||||
JSON_RESPONSE="["
|
||||
|
||||
# List of AT commands to run, one by one
|
||||
for COMMAND in 'AT+CGMI' 'AT+CGMM' 'AT+CGMR' 'AT+CNUM' 'AT+CIMI' 'AT+ICCID' 'AT+CGSN' 'AT+QMAP="LANIP"' 'AT+QMAP="WWAN"' 'AT+QGETCAPABILITY'; do
|
||||
# Write the command to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout
|
||||
atinout "$INPUT_FILE" "$AT_PORT" "$OUTPUT_FILE"
|
||||
|
||||
# Read the output from the output file
|
||||
OUTPUT=$(cat "$OUTPUT_FILE")
|
||||
|
||||
# Escape special characters for JSON (escape only output)
|
||||
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
|
||||
|
||||
# Append the response as an object to the JSON response array
|
||||
JSON_RESPONSE="${JSON_RESPONSE}{\"response\":\"$ESCAPED_OUTPUT\"},"
|
||||
done
|
||||
|
||||
# Remove the trailing comma and close the JSON array
|
||||
if [ "${JSON_RESPONSE: -1}" = "," ]; then
|
||||
JSON_RESPONSE="${JSON_RESPONSE%,}]"
|
||||
else
|
||||
JSON_RESPONSE="${JSON_RESPONSE}]"
|
||||
fi
|
||||
|
||||
# Write the JSON response to the debug file for troubleshooting
|
||||
echo "$JSON_RESPONSE" > "$DEBUG_FILE"
|
||||
|
||||
# Return the output as a valid JSON response
|
||||
echo "$JSON_RESPONSE"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$INPUT_FILE" "$OUTPUT_FILE"
|
||||
|
||||
# Release the lock
|
||||
flock -u 200
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Define the lock file
|
||||
LOCK_FILE="/tmp/home_data.lock"
|
||||
|
||||
# Acquire the lock (wait if needed)
|
||||
exec 200>$LOCK_FILE
|
||||
flock -x 200
|
||||
|
||||
# Temporary files for input/output and AT port
|
||||
INPUT_FILE="/tmp/input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/output_$$.txt"
|
||||
AT_PORT="/dev/smd11"
|
||||
|
||||
# Debug file path
|
||||
DEBUG_FILE="/tmp/debug-json-result.txt"
|
||||
|
||||
# Function to escape JSON strings (handling quotes and newlines)
|
||||
escape_json() {
|
||||
# Escape newlines and double quotes
|
||||
echo "$1" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g'
|
||||
}
|
||||
|
||||
# Initialize JSON response array
|
||||
JSON_RESPONSE="["
|
||||
|
||||
# List of AT commands to run, one by one
|
||||
for COMMAND in 'AT+QMAP="MPDN_RULE"' 'AT+QMAP="DHCPV4DNS"' 'AT+QCFG="usbnet"'; do
|
||||
# Write the command to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout
|
||||
atinout "$INPUT_FILE" "$AT_PORT" "$OUTPUT_FILE"
|
||||
|
||||
# Read the output from the output file
|
||||
OUTPUT=$(cat "$OUTPUT_FILE")
|
||||
|
||||
# Escape special characters for JSON (escape only output)
|
||||
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
|
||||
|
||||
# Append the response as an object to the JSON response array
|
||||
JSON_RESPONSE="${JSON_RESPONSE}{\"response\":\"$ESCAPED_OUTPUT\"},"
|
||||
done
|
||||
|
||||
# Remove the trailing comma and close the JSON array
|
||||
if [ "${JSON_RESPONSE: -1}" = "," ]; then
|
||||
JSON_RESPONSE="${JSON_RESPONSE%,}]"
|
||||
else
|
||||
JSON_RESPONSE="${JSON_RESPONSE}]"
|
||||
fi
|
||||
|
||||
# Write the JSON response to the debug file for troubleshooting
|
||||
echo "$JSON_RESPONSE" > "$DEBUG_FILE"
|
||||
|
||||
# Return the output as a valid JSON response
|
||||
echo "$JSON_RESPONSE"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$INPUT_FILE" "$OUTPUT_FILE"
|
||||
|
||||
# Release the lock
|
||||
flock -u 200
|
||||
26
ipk-source/sdxpinn-quecmanager/root/www/cgi-bin/advance/fetch_commands.sh
Executable file
26
ipk-source/sdxpinn-quecmanager/root/www/cgi-bin/advance/fetch_commands.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content type for JSON response
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Check if the file exists
|
||||
if [ -f "/etc/config/atcommands.user" ]; then
|
||||
# Start JSON object
|
||||
printf "{\n"
|
||||
awk -F';' '
|
||||
BEGIN { first = 1 }
|
||||
{
|
||||
gsub(/\r/, "", $0)
|
||||
if (!first) printf ",\n "
|
||||
else printf " "
|
||||
gsub(/"/, "\\\"", $1)
|
||||
gsub(/"/, "\\\"", $2)
|
||||
printf "\"%s\": \"%s\"", $1, $2
|
||||
first = 0
|
||||
}
|
||||
' /etc/config/atcommands.user
|
||||
printf "\n}"
|
||||
else
|
||||
echo '{"error": "No Data"}'
|
||||
fi
|
||||
90
ipk-source/sdxpinn-quecmanager/root/www/cgi-bin/advance/mtu.sh
Executable file
90
ipk-source/sdxpinn-quecmanager/root/www/cgi-bin/advance/mtu.sh
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/bin/sh
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
mtu_firewall_file="/etc/firewall.user.mtu"
|
||||
network_interface="rmnet_data0"
|
||||
lan_utils_script="/etc/data/lanUtils.sh"
|
||||
|
||||
get_current_mtu() {
|
||||
ip link show "$network_interface" | grep -o "mtu [0-9]*" | cut -d' ' -f2
|
||||
}
|
||||
|
||||
update_lanutils_mtu_config() {
|
||||
local action="$1"
|
||||
if [ "$action" = "add" ]; then
|
||||
# Add the MTU firewall file line if not already present
|
||||
if ! grep -q "local mtu_firewall_file=/etc/firewall.user.mtu" "$lan_utils_script"; then
|
||||
sed -i '/local ttl_firewall_file=\/etc\/firewall.user.ttl/a local mtu_firewall_file=/etc/firewall.user.mtu' "$lan_utils_script"
|
||||
fi
|
||||
elif [ "$action" = "remove" ]; then
|
||||
# Remove the MTU firewall file line if present
|
||||
sed -i '/local mtu_firewall_file=\/etc\/firewall.user.mtu/d' "$lan_utils_script"
|
||||
fi
|
||||
}
|
||||
|
||||
case "$REQUEST_METHOD" in
|
||||
GET)
|
||||
# Fetch current MTU
|
||||
current_mtu=$(get_current_mtu)
|
||||
current_mtu=${current_mtu:-1500}
|
||||
|
||||
# Check if custom MTU is configured
|
||||
if [ -f "$mtu_firewall_file" ]; then
|
||||
echo "{\"isEnabled\": true, \"currentValue\": $current_mtu}"
|
||||
else
|
||||
echo "{\"isEnabled\": false, \"currentValue\": $current_mtu}"
|
||||
fi
|
||||
;;
|
||||
|
||||
POST)
|
||||
read -r post_data
|
||||
mtu_value=$(echo "$post_data" | sed 's/mtu=//')
|
||||
|
||||
# Check for disable functionality
|
||||
if [ "$mtu_value" = "disable" ]; then
|
||||
# Remove the MTU configuration file
|
||||
rm -f "$mtu_firewall_file"
|
||||
|
||||
# Remove the MTU configuration line from lanUtils.sh
|
||||
update_lanutils_mtu_config "remove"
|
||||
|
||||
# Get the default MTU
|
||||
default_mtu=$(get_current_mtu)
|
||||
default_mtu=${default_mtu:-1500}
|
||||
|
||||
echo "{\"success\": true, \"message\": \"MTU configuration disabled\", \"currentValue\": $default_mtu}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Validate MTU input
|
||||
if ! [[ "$mtu_value" =~ ^[0-9]+$ ]]; then
|
||||
echo "{\"success\": false, \"error\": \"Invalid MTU value\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create firewall MTU configuration file with individual interface commands
|
||||
> "$mtu_firewall_file" # Clear the file
|
||||
for iface in $(ls /sys/class/net | grep '^rmnet_data'); do
|
||||
echo "ip link set $iface mtu $mtu_value" >> "$mtu_firewall_file"
|
||||
done
|
||||
|
||||
# Immediately apply MTU change
|
||||
for iface in $(ls /sys/class/net | grep '^rmnet_data'); do
|
||||
ip link set "$iface" mtu "$mtu_value"
|
||||
done
|
||||
|
||||
# Add the MTU configuration line to lanUtils.sh
|
||||
update_lanutils_mtu_config "add"
|
||||
|
||||
# Run lanUtils.sh to update network configuration
|
||||
if [ -f "$lan_utils_script" ]; then
|
||||
. "$lan_utils_script"
|
||||
fi
|
||||
|
||||
echo "{\"success\": true, \"message\": \"MTU configuration updated to $mtu_value\", \"currentValue\": $mtu_value}"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "{\"success\": false, \"error\": \"Invalid request method\"}"
|
||||
;;
|
||||
esac
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Define the lock file
|
||||
LOCK_FILE="/tmp/home_data.lock"
|
||||
|
||||
# Acquire the lock (wait if needed)
|
||||
exec 200>$LOCK_FILE
|
||||
flock -x 200
|
||||
|
||||
# Temporary files for input/output and AT port
|
||||
INPUT_FILE="/tmp/input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/output_$$.txt"
|
||||
AT_PORT="/dev/smd11"
|
||||
|
||||
# Debug file path
|
||||
DEBUG_FILE="/tmp/debug-json-result.txt"
|
||||
|
||||
# Function to escape JSON strings (handling quotes and newlines)
|
||||
escape_json() {
|
||||
# Escape newlines and double quotes
|
||||
echo "$1" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g'
|
||||
}
|
||||
|
||||
# Initialize JSON response array
|
||||
JSON_RESPONSE="["
|
||||
|
||||
# List of AT commands to run, one by one
|
||||
for COMMAND in 'AT+QMAP="MPDN_RULE"' 'AT+QMAP="DHCPV4DNS"' 'AT+QCFG="usbnet"'; do
|
||||
# Write the command to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout
|
||||
atinout "$INPUT_FILE" "$AT_PORT" "$OUTPUT_FILE"
|
||||
|
||||
# Read the output from the output file
|
||||
OUTPUT=$(cat "$OUTPUT_FILE")
|
||||
|
||||
# Escape special characters for JSON (escape only output)
|
||||
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
|
||||
|
||||
# Append the response as an object to the JSON response array
|
||||
JSON_RESPONSE="${JSON_RESPONSE}{\"response\":\"$ESCAPED_OUTPUT\"},"
|
||||
done
|
||||
|
||||
# Remove the trailing comma and close the JSON array
|
||||
if [ "${JSON_RESPONSE: -1}" = "," ]; then
|
||||
JSON_RESPONSE="${JSON_RESPONSE%,}]"
|
||||
else
|
||||
JSON_RESPONSE="${JSON_RESPONSE}]"
|
||||
fi
|
||||
|
||||
# Write the JSON response to the debug file for troubleshooting
|
||||
echo "$JSON_RESPONSE" > "$DEBUG_FILE"
|
||||
|
||||
# Return the output as a valid JSON response
|
||||
echo "$JSON_RESPONSE"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$INPUT_FILE" "$OUTPUT_FILE"
|
||||
|
||||
# Release the lock
|
||||
flock -u 200
|
||||
@@ -1,153 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Parse POST data
|
||||
read -r QUERY_STRING
|
||||
|
||||
# Function to urldecode
|
||||
urldecode() {
|
||||
echo -e "$(echo "$1" | sed 's/+/ /g;s/%\([0-9A-F][0-9A-F]\)/\\x\1/g')"
|
||||
}
|
||||
|
||||
# Extract values from POST data
|
||||
iccidProfile1=$(echo "$QUERY_STRING" | grep -o 'iccidProfile1=[^&]*' | cut -d= -f2)
|
||||
apnProfile1=$(echo "$QUERY_STRING" | grep -o 'apnProfile1=[^&]*' | cut -d= -f2)
|
||||
pdpType1=$(echo "$QUERY_STRING" | grep -o 'pdpType1=[^&]*' | cut -d= -f2)
|
||||
iccidProfile2=$(echo "$QUERY_STRING" | grep -o 'iccidProfile2=[^&]*' | cut -d= -f2)
|
||||
apnProfile2=$(echo "$QUERY_STRING" | grep -o 'apnProfile2=[^&]*' | cut -d= -f2)
|
||||
pdpType2=$(echo "$QUERY_STRING" | grep -o 'pdpType2=[^&]*' | cut -d= -f2)
|
||||
|
||||
# URL decode the values
|
||||
iccidProfile1=$(urldecode "$iccidProfile1")
|
||||
apnProfile1=$(urldecode "$apnProfile1")
|
||||
pdpType1=$(urldecode "$pdpType1")
|
||||
iccidProfile2=$(urldecode "$iccidProfile2")
|
||||
apnProfile2=$(urldecode "$apnProfile2")
|
||||
pdpType2=$(urldecode "$pdpType2")
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Validate required first profile
|
||||
if [ -z "$iccidProfile1" ] || [ -z "$apnProfile1" ] || [ -z "$pdpType1" ]; then
|
||||
echo '{"status": "error", "message": "Profile 1 is required"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create the directory structure
|
||||
mkdir -p /etc/quecmanager
|
||||
|
||||
# Create a configuration file to store APN profiles (as plain text)
|
||||
cat > /etc/quecmanager/apn_config.txt << EOF
|
||||
iccidProfile1=$iccidProfile1
|
||||
apnProfile1=$apnProfile1
|
||||
pdpType1=$pdpType1
|
||||
EOF
|
||||
|
||||
# Add second profile only if ICCID is provided
|
||||
if [ -n "$iccidProfile2" ]; then
|
||||
cat >> /etc/quecmanager/apn_config.txt << EOF
|
||||
iccidProfile2=$iccidProfile2
|
||||
apnProfile2=$apnProfile2
|
||||
pdpType2=$pdpType2
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Create the apnProfiles.sh script
|
||||
cat > /etc/quecmanager/apnProfiles.sh << 'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
# Function to read config values
|
||||
get_config_value() {
|
||||
local key=$1
|
||||
grep "^${key}=" /etc/quecmanager/apn_config.txt | cut -d'=' -f2
|
||||
}
|
||||
|
||||
# Read configuration
|
||||
iccidProfile1=$(get_config_value "iccidProfile1")
|
||||
apnProfile1=$(get_config_value "apnProfile1")
|
||||
pdpType1=$(get_config_value "pdpType1")
|
||||
iccidProfile2=$(get_config_value "iccidProfile2")
|
||||
apnProfile2=$(get_config_value "apnProfile2")
|
||||
pdpType2=$(get_config_value "pdpType2")
|
||||
|
||||
# Function to get current ICCID
|
||||
get_current_iccid() {
|
||||
local input_file="/tmp/inputICCID.txt"
|
||||
local output_file="/tmp/outputICCID.txt"
|
||||
|
||||
echo "AT+ICCID" > "$input_file"
|
||||
atinout "$input_file" /dev/smd11 "$output_file"
|
||||
|
||||
iccid=$(cat "$output_file" | grep "+ICCID:" | cut -d' ' -f2)
|
||||
|
||||
rm -f "$input_file" "$output_file"
|
||||
echo "$iccid"
|
||||
}
|
||||
|
||||
# Function to set APN
|
||||
set_apn() {
|
||||
local pdp_type="$1"
|
||||
local apn="$2"
|
||||
local input_file="/tmp/inputAPN.txt"
|
||||
local output_file="/tmp/outputAPN.txt"
|
||||
|
||||
echo "AT+CGDCONT=1,\"$pdp_type\",\"$apn\";+COPS=2;+COPS=0" > "$input_file"
|
||||
atinout "$input_file" /dev/smd11 "$output_file"
|
||||
|
||||
local result=$(cat "$output_file")
|
||||
rm -f "$input_file" "$output_file"
|
||||
|
||||
if echo "$result" | grep -q "OK"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get current ICCID
|
||||
current_iccid=$(get_current_iccid)
|
||||
success=false
|
||||
|
||||
# Check ICCID against profile 1 (required)
|
||||
if [ "$current_iccid" = "$iccidProfile1" ]; then
|
||||
if set_apn "$pdpType1" "$apnProfile1"; then
|
||||
success=true
|
||||
fi
|
||||
# Check ICCID against profile 2 (optional)
|
||||
elif [ -n "$iccidProfile2" ] && [ "$current_iccid" = "$iccidProfile2" ]; then
|
||||
if set_apn "$pdpType2" "$apnProfile2"; then
|
||||
success=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$success" = "true" ]; then
|
||||
echo "APN set successfully" > /tmp/apn_result.txt
|
||||
else
|
||||
echo "Failed to set APN" > /tmp/apn_result.txt
|
||||
fi
|
||||
EOF
|
||||
|
||||
# Make the script executable
|
||||
chmod +x /etc/quecmanager/apnProfiles.sh
|
||||
|
||||
# Add to rc.local if not already present
|
||||
if ! grep -q "/etc/quecmanager/apnProfiles.sh" /etc/rc.local; then
|
||||
sed -i '/^exit 0/i /etc/quecmanager/apnProfiles.sh' /etc/rc.local
|
||||
fi
|
||||
|
||||
# Run the script immediately
|
||||
/etc/quecmanager/apnProfiles.sh
|
||||
|
||||
# Check the result
|
||||
if [ -f /tmp/apn_result.txt ]; then
|
||||
result=$(cat /tmp/apn_result.txt)
|
||||
rm -f /tmp/apn_result.txt
|
||||
|
||||
if [ "$result" = "APN set successfully" ]; then
|
||||
echo '{"status": "success", "message": "APN profiles saved and applied successfully"}'
|
||||
else
|
||||
echo '{"status": "error", "message": "APN profiles saved but failed to apply"}'
|
||||
fi
|
||||
else
|
||||
echo '{"status": "error", "message": "Something went wrong while processing APN profiles"}'
|
||||
fi
|
||||
@@ -22,13 +22,48 @@ COMMAND=$(urldecode "$RAW_COMMAND")
|
||||
# Define unique input/output files and AT port
|
||||
INPUT_FILE="/tmp/custom_input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/custom_output_$$.txt"
|
||||
AT_PORT="/dev/smd7"
|
||||
|
||||
# Debug logging
|
||||
DEBUG_LOG="/tmp/debug.log"
|
||||
echo "Starting at_handler script at $(date)" > "$DEBUG_LOG"
|
||||
|
||||
CONFIG_FILE="/etc/quecManager.conf"
|
||||
# Check config file
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Config file not found: $CONFIG_FILE" >> "$DEBUG_LOG"
|
||||
echo '{"error": "Config file not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get AT_PORT with debug logging
|
||||
# Get AT_PORT with debug logging
|
||||
AT_PORT=$(head -n 2 "$CONFIG_FILE" | tail -n 1 | cut -d'=' -f2 | tr -d ' \n\r' | sed 's|^dev/||')
|
||||
echo "Raw config line: $(head -n 1 "$CONFIG_FILE")" >> "$DEBUG_LOG"
|
||||
echo "Extracted AT_PORT: '$AT_PORT'" >> "$DEBUG_LOG"
|
||||
|
||||
# List available devices for debugging
|
||||
ls -l /dev/smd* >> "$DEBUG_LOG" 2>&1
|
||||
|
||||
if [ -z "$AT_PORT" ]; then
|
||||
echo "AT_PORT is empty" >> "$DEBUG_LOG"
|
||||
echo '{"error": "Failed to read AT_PORT from config"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if AT_PORT exists
|
||||
if [ ! -c "/dev/$AT_PORT" ]; then
|
||||
echo "AT_PORT device not found: /dev/$AT_PORT" >> "$DEBUG_LOG"
|
||||
echo "Available smd devices:" >> "$DEBUG_LOG"
|
||||
ls -l /dev/smd* >> "$DEBUG_LOG" 2>&1
|
||||
echo '{"error": "AT_PORT device not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Write the command directly to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout
|
||||
atinout "$INPUT_FILE" "$AT_PORT" "$OUTPUT_FILE"
|
||||
atinout "$INPUT_FILE" "/dev/$AT_PORT" "$OUTPUT_FILE"
|
||||
|
||||
# Read the output from output.txt
|
||||
OUTPUT=$(cat "$OUTPUT_FILE")
|
||||
|
||||
@@ -7,6 +7,9 @@ echo ""
|
||||
# Read POST data
|
||||
read POST_DATA
|
||||
|
||||
# Debug log for generated hash
|
||||
DEBUG_LOG = "/tmp/auth.log"
|
||||
|
||||
# Extract the password from POST data (URL encoded)
|
||||
USER="root"
|
||||
INPUT_PASSWORD=$(echo "$POST_DATA" | sed -n 's/^.*password=\([^&]*\).*$/\1/p')
|
||||
@@ -14,9 +17,6 @@ INPUT_PASSWORD=$(echo "$POST_DATA" | sed -n 's/^.*password=\([^&]*\).*$/\1/p')
|
||||
# URL-decode the password (replace + with space and decode %XX)
|
||||
INPUT_PASSWORD=$(echo "$INPUT_PASSWORD" | sed 's/+/ /g;s/%\(..\)/\\x\1/g' | xargs -0 printf "%b")
|
||||
|
||||
# Log received password for debugging (remove in production)
|
||||
# echo "Received password: $INPUT_PASSWORD" >&2
|
||||
|
||||
# Extract the hashed password from /etc/shadow for the specified user
|
||||
USER_SHADOW_ENTRY=$(grep "^$USER:" /etc/shadow)
|
||||
|
||||
@@ -35,11 +35,11 @@ SALT=$(echo "$USER_HASH" | cut -d'$' -f3)
|
||||
GENERATED_HASH=$(echo "$INPUT_PASSWORD" | openssl passwd -1 -salt "$SALT" -stdin)
|
||||
|
||||
# Log generated hash for debugging
|
||||
echo "Generated hash: $GENERATED_HASH" >&2
|
||||
echo "Generated hash: $GENERATED_HASH" >> $DEBUG_LOG
|
||||
|
||||
# Compare the generated hash with the one in the shadow file
|
||||
if [ "$GENERATED_HASH" = "$USER_HASH" ]; then
|
||||
echo '{"state":"success", "hashed_password":"'"$GENERATED_HASH"'"}'
|
||||
echo '{"state":"success"}'
|
||||
else
|
||||
echo '{"state":"failed", "hashed_password":"'"$GENERATED_HASH"'"}'
|
||||
echo '{"state":"failed"}'
|
||||
fi
|
||||
|
||||
@@ -1,258 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Parse POST data
|
||||
read -r QUERY_STRING
|
||||
|
||||
# Function to urldecode
|
||||
urldecode() {
|
||||
echo -e "$(echo "$1" | sed 's/+/ /g;s/%\([0-9A-F][0-9A-F]\)/\\x\1/g')"
|
||||
}
|
||||
|
||||
# Function to send AT commands silently
|
||||
send_at_command() {
|
||||
echo "$1" | atinout - /dev/smd7 - >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Extract reset flags
|
||||
reset_lte=$(echo "$QUERY_STRING" | grep -o 'reset_lte=[^&]*' | cut -d= -f2)
|
||||
reset_5g=$(echo "$QUERY_STRING" | grep -o 'reset_5g=[^&]*' | cut -d= -f2)
|
||||
|
||||
# Extract LTE values from POST data
|
||||
earfcn1=$(echo "$QUERY_STRING" | grep -o 'earfcn1=[^&]*' | cut -d= -f2)
|
||||
pci1=$(echo "$QUERY_STRING" | grep -o 'pci1=[^&]*' | cut -d= -f2)
|
||||
earfcn2=$(echo "$QUERY_STRING" | grep -o 'earfcn2=[^&]*' | cut -d= -f2)
|
||||
pci2=$(echo "$QUERY_STRING" | grep -o 'pci2=[^&]*' | cut -d= -f2)
|
||||
earfcn3=$(echo "$QUERY_STRING" | grep -o 'earfcn3=[^&]*' | cut -d= -f2)
|
||||
pci3=$(echo "$QUERY_STRING" | grep -o 'pci3=[^&]*' | cut -d= -f2)
|
||||
|
||||
# Extract 5G-SA values from POST data
|
||||
nrarfcn=$(echo "$QUERY_STRING" | grep -o 'nrarfcn=[^&]*' | cut -d= -f2)
|
||||
nrpci=$(echo "$QUERY_STRING" | grep -o 'nrpci=[^&]*' | cut -d= -f2)
|
||||
scs=$(echo "$QUERY_STRING" | grep -o 'scs=[^&]*' | cut -d= -f2)
|
||||
band=$(echo "$QUERY_STRING" | grep -o 'band=[^&]*' | cut -d= -f2)
|
||||
|
||||
# URL decode all values
|
||||
reset_lte=$(urldecode "$reset_lte")
|
||||
reset_5g=$(urldecode "$reset_5g")
|
||||
earfcn1=$(urldecode "$earfcn1")
|
||||
pci1=$(urldecode "$pci1")
|
||||
earfcn2=$(urldecode "$earfcn2")
|
||||
pci2=$(urldecode "$pci2")
|
||||
earfcn3=$(urldecode "$earfcn3")
|
||||
pci3=$(urldecode "$pci3")
|
||||
nrarfcn=$(urldecode "$nrarfcn")
|
||||
nrpci=$(urldecode "$nrpci")
|
||||
scs=$(urldecode "$scs")
|
||||
band=$(urldecode "$band")
|
||||
|
||||
# Send Content-type header before any other output
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Handle reset requests
|
||||
if [ "$reset_lte" = "1" ] || [ "$reset_5g" = "1" ]; then
|
||||
# Remove configuration files
|
||||
rm -f /etc/quecmanager/cell_lock_config.txt
|
||||
rm -f /etc/quecmanager/apply_cell_lock.sh
|
||||
|
||||
# Remove from rc.local if present
|
||||
sed -i '/\/etc\/quecmanager\/apply_cell_lock.sh/d' /etc/rc.local
|
||||
|
||||
if [ "$reset_lte" = "1" ] && [ "$reset_5g" = "1" ]; then
|
||||
send_at_command "AT+QNWLOCK=\"common/4g\",0"
|
||||
send_at_command "AT+QNWLOCK=\"common/5g\",0"
|
||||
send_at_command "AT+QNWPREFCFG=\"mode_pref\",AUTO"
|
||||
sleep 1
|
||||
send_at_command "AT+COPS=2"
|
||||
sleep 1
|
||||
send_at_command "AT+COPS=0"
|
||||
echo '{"status": "success", "message": "All cell lock configurations removed"}'
|
||||
elif [ "$reset_lte" = "1" ]; then
|
||||
send_at_command "AT+QNWLOCK=\"common/4g\",0"
|
||||
sleep 1
|
||||
send_at_command "AT+COPS=2"
|
||||
sleep 1
|
||||
send_at_command "AT+COPS=0"
|
||||
echo '{"status": "success", "message": "LTE cell lock configuration removed"}'
|
||||
else
|
||||
send_at_command "AT+QNWLOCK=\"common/5g\",0"
|
||||
send_at_command "AT+QNWPREFCFG=\"mode_pref\",AUTO"
|
||||
sleep 1
|
||||
send_at_command "AT+COPS=2"
|
||||
sleep 1
|
||||
send_at_command "AT+COPS=0"
|
||||
echo '{"status": "success", "message": "5G cell lock configuration removed"}'
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Create the directory structure if it doesn't exist
|
||||
mkdir -p /etc/quecmanager /var/log/quecmanager
|
||||
|
||||
# Create a configuration file to store cell locking profiles
|
||||
cat >/etc/quecmanager/cell_lock_config.txt <<EOF
|
||||
# LTE Cell Locking Configuration
|
||||
earfcn1=$earfcn1
|
||||
pci1=$pci1
|
||||
earfcn2=$earfcn2
|
||||
pci2=$pci2
|
||||
earfcn3=$earfcn3
|
||||
pci3=$pci3
|
||||
|
||||
# 5G-SA Cell Locking Configuration
|
||||
nrarfcn=$nrarfcn
|
||||
nrpci=$nrpci
|
||||
scs=$scs
|
||||
band=$band
|
||||
EOF
|
||||
|
||||
# Create the apply_cell_lock.sh script
|
||||
cat >/etc/quecmanager/apply_cell_lock.sh <<'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
# Create log directory if it doesn't exist
|
||||
LOG_DIR="/var/log/quecmanager"
|
||||
mkdir -p "$LOG_DIR"
|
||||
DEBUG_LOG="$LOG_DIR/cell_lock_debug.log"
|
||||
|
||||
# Function to log messages
|
||||
log_message() {
|
||||
local message="$1"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "$timestamp - $message" >> "$DEBUG_LOG"
|
||||
}
|
||||
|
||||
# Verify required tools
|
||||
if ! command -v atinout >/dev/null 2>&1; then
|
||||
log_message "Error: atinout command not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -c "/dev/smd7" ]; then
|
||||
log_message "Error: Modem device /dev/smd7 not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to send AT commands
|
||||
send_at_command() {
|
||||
local command="$1"
|
||||
local description="$2"
|
||||
local retry_count=0
|
||||
local max_retries=3
|
||||
|
||||
log_message "Attempting to send command: $command ($description)"
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
echo "$command" | atinout - /dev/smd7 - > /tmp/at_response.txt 2>&1
|
||||
local result=$(cat /tmp/at_response.txt)
|
||||
|
||||
log_message "Attempt $((retry_count + 1)) - Response: $result"
|
||||
|
||||
if echo "$result" | grep -q "OK"; then
|
||||
log_message "Command successful: $description"
|
||||
return 0
|
||||
fi
|
||||
|
||||
retry_count=$((retry_count + 1))
|
||||
log_message "Command failed, retry $retry_count of $max_retries"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
log_message "Command failed after $max_retries retries: $description"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to apply cell lock configuration
|
||||
apply_cell_lock() {
|
||||
local config_file="/etc/quecmanager/cell_lock_config.txt"
|
||||
|
||||
if [ ! -f "$config_file" ]; then
|
||||
log_message "Configuration file not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Read configuration values
|
||||
. "$config_file"
|
||||
|
||||
# Test modem responsiveness
|
||||
if ! send_at_command "AT" "Testing modem responsiveness"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Apply LTE configuration if present
|
||||
if [ -n "$earfcn1" ] && [ -n "$pci1" ]; then
|
||||
if [ -n "$earfcn2" ] && [ -n "$pci2" ]; then
|
||||
if [ -n "$earfcn3" ] && [ -n "$pci3" ]; then
|
||||
send_at_command "AT+QNWLOCK=\"common/4g\",3,$earfcn1,$pci1,$earfcn2,$pci2,$earfcn3,$pci3" "Setting LTE lock (3 cells)"
|
||||
else
|
||||
send_at_command "AT+QNWLOCK=\"common/4g\",2,$earfcn1,$pci1,$earfcn2,$pci2" "Setting LTE lock (2 cells)"
|
||||
fi
|
||||
else
|
||||
send_at_command "AT+QNWLOCK=\"common/4g\",1,$earfcn1,$pci1" "Setting LTE lock (1 cell)"
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
if ! send_at_command "AT+COPS=2" "Network Disconnected"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
if ! send_at_command "AT+COPS=0" "Network Reconnected"; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Apply 5G configuration if present
|
||||
if [ -n "$nrpci" ] && [ -n "$nrarfcn" ] && [ -n "$scs" ] && [ -n "$band" ]; then
|
||||
|
||||
if ! send_at_command "AT+QNWPREFCFG=\"mode_pref\",NR5G" "Setting network to SA only"; then
|
||||
return 1
|
||||
fi
|
||||
sleep 1
|
||||
|
||||
if ! send_at_command "AT+QNWLOCK=\"common/5g\",$nrpci,$nrarfcn,$scs,$band" "Setting 5G lock"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
if ! send_at_command "AT+COPS=2" "Network Disconnected"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
if ! send_at_command "AT+COPS=0" "Network Reconnected"; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main execution
|
||||
log_message "Starting cell lock configuration"
|
||||
if apply_cell_lock; then
|
||||
log_message "Cell lock configuration applied successfully"
|
||||
exit 0
|
||||
else
|
||||
log_message "Failed to apply cell lock configuration"
|
||||
exit 1
|
||||
fi
|
||||
EOF
|
||||
|
||||
# Make the script executable
|
||||
chmod +x /etc/quecmanager/apply_cell_lock.sh
|
||||
|
||||
# Add to rc.local if not already present
|
||||
if ! grep -q "/etc/quecmanager/apply_cell_lock.sh" /etc/rc.local; then
|
||||
sed -i '/exit 0/i sleep 30\n\/etc\/quecmanager\/apply_cell_lock.sh' /etc/rc.local
|
||||
fi
|
||||
|
||||
# Run the script immediately
|
||||
/etc/quecmanager/apply_cell_lock.sh
|
||||
result=$?
|
||||
|
||||
if [ $result -eq 0 ]; then
|
||||
echo '{"status": "success", "message": "Cell lock configurations saved and applied successfully"}'
|
||||
else
|
||||
echo '{"status": "error", "message": "Cell lock configurations saved but failed to apply"}'
|
||||
fi
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
CONFIG_FILE="/etc/quecmanager/cell_lock_config.txt"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo '{"status": "error", "message": "No cell lock configurations found", "configurations": {}}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Function to read config values
|
||||
get_config_value() {
|
||||
local key=$1
|
||||
local value=$(grep "^$key=" "$CONFIG_FILE" | sed "s/^$key=//")
|
||||
# Remove any trailing whitespace or comments
|
||||
value=$(echo "$value" | sed 's/[[:space:]]*#.*$//' | sed 's/[[:space:]]*$//')
|
||||
echo "$value"
|
||||
}
|
||||
|
||||
# Read LTE configuration values
|
||||
earfcn1=$(get_config_value "earfcn1")
|
||||
pci1=$(get_config_value "pci1")
|
||||
earfcn2=$(get_config_value "earfcn2")
|
||||
pci2=$(get_config_value "pci2")
|
||||
earfcn3=$(get_config_value "earfcn3")
|
||||
pci3=$(get_config_value "pci3")
|
||||
|
||||
# Read 5G-SA configuration values
|
||||
nrarfcn=$(get_config_value "nrarfcn")
|
||||
nrpci=$(get_config_value "nrpci")
|
||||
scs=$(get_config_value "scs")
|
||||
band=$(get_config_value "band")
|
||||
|
||||
# Debug output to syslog
|
||||
logger "fetch-cell-lock: earfcn1=$earfcn1 pci1=$pci1 nrarfcn=$nrarfcn nrpci=$nrpci"
|
||||
|
||||
# Construct JSON response
|
||||
cat << EOF
|
||||
{
|
||||
"status": "success",
|
||||
"configurations": {
|
||||
"lte": {
|
||||
"earfcn1": "${earfcn1:-}",
|
||||
"pci1": "${pci1:-}",
|
||||
"earfcn2": "${earfcn2:-}",
|
||||
"pci2": "${pci2:-}",
|
||||
"earfcn3": "${earfcn3:-}",
|
||||
"pci3": "${pci3:-}"
|
||||
},
|
||||
"sa": {
|
||||
"nrarfcn": "${nrarfcn:-}",
|
||||
"nrpci": "${nrpci:-}",
|
||||
"scs": "${scs:-}",
|
||||
"band": "${band:-}"
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
@@ -1,120 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Enable debug logging
|
||||
# exec 1> >(logger -s -t $(basename $0)) 2>&1
|
||||
# Create log directory if it doesn't exist
|
||||
LOG_DIR="/var/log/quecmanager"
|
||||
mkdir -p "$LOG_DIR"
|
||||
DEBUG_LOG="$LOG_DIR/cell_lock_debug.log"
|
||||
|
||||
# Function to log messages
|
||||
log_message() {
|
||||
local message="$1"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "$timestamp - $message" >> "$DEBUG_LOG"
|
||||
}
|
||||
|
||||
# Verify required tools
|
||||
if ! command -v atinout >/dev/null 2>&1; then
|
||||
log_message "Error: atinout command not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -c "/dev/smd11" ]; then
|
||||
log_message "Error: Modem device /dev/smd11 not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to send AT commands
|
||||
send_at_command() {
|
||||
local command="$1"
|
||||
local description="$2"
|
||||
local retry_count=0
|
||||
local max_retries=3
|
||||
|
||||
log_message "Attempting to send command: $command ($description)"
|
||||
|
||||
while [ $retry_count -lt $max_retries ]; do
|
||||
echo "$command" | atinout - /dev/smd11 - > /tmp/at_response.txt 2>&1
|
||||
local result=$(cat /tmp/at_response.txt)
|
||||
|
||||
log_message "Attempt $((retry_count + 1)) - Response: $result"
|
||||
|
||||
if echo "$result" | grep -q "OK"; then
|
||||
log_message "Command successful: $description"
|
||||
return 0
|
||||
fi
|
||||
|
||||
retry_count=$((retry_count + 1))
|
||||
log_message "Command failed, retry $retry_count of $max_retries"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
log_message "Command failed after $max_retries retries: $description"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to apply cell lock configuration
|
||||
apply_cell_lock() {
|
||||
local config_file="/etc/quecmanager/cell_lock_config.txt"
|
||||
|
||||
if [ ! -f "$config_file" ]; then
|
||||
log_message "Configuration file not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Read configuration values
|
||||
. "$config_file"
|
||||
|
||||
# Test modem responsiveness
|
||||
if ! send_at_command "AT" "Testing modem responsiveness"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Apply LTE configuration if present
|
||||
if [ -n "$earfcn1" ] && [ -n "$pci1" ]; then
|
||||
if ! send_at_command "AT+CFUN=0" "Setting radio off"; then
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
|
||||
if [ -n "$earfcn2" ] && [ -n "$pci2" ]; then
|
||||
if [ -n "$earfcn3" ] && [ -n "$pci3" ]; then
|
||||
send_at_command "AT+QNWLOCK=\"common/4g\",3,$earfcn1,$pci1,$earfcn2,$pci2,$earfcn3,$pci3" "Setting LTE lock (3 cells)"
|
||||
else
|
||||
send_at_command "AT+QNWLOCK=\"common/4g\",2,$earfcn1,$pci1,$earfcn2,$pci2" "Setting LTE lock (2 cells)"
|
||||
fi
|
||||
else
|
||||
send_at_command "AT+QNWLOCK=\"common/4g\",1,$earfcn1,$pci1" "Setting LTE lock (1 cell)"
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
if ! send_at_command "AT+CFUN=1" "Setting radio on"; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Apply 5G configuration if present
|
||||
if [ -n "$nrpci" ] && [ -n "$nrarfcn" ] && [ -n "$scs" ] && [ -n "$band" ]; then
|
||||
if ! send_at_command "AT+CFUN=0" "Setting radio off"; then
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
if ! send_at_command "AT+QNWLOCK=\"common/5g\",$nrpci,$nrarfcn,$scs,$band" "Setting 5G lock"; then
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
if ! send_at_command "AT+CFUN=1" "Setting radio on"; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Main execution
|
||||
log_message "Starting cell lock configuration"
|
||||
if apply_cell_lock; then
|
||||
log_message "Cell lock configuration applied successfully"
|
||||
exit 0
|
||||
else
|
||||
log_message "Failed to apply cell lock configuration"
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Define the lock file
|
||||
LOCK_FILE="/tmp/home_data.lock"
|
||||
|
||||
# Acquire the lock (wait if needed)
|
||||
exec 200>$LOCK_FILE
|
||||
flock -x 200
|
||||
|
||||
# Temporary files for input/output and AT port
|
||||
INPUT_FILE="/tmp/input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/output_$$.txt"
|
||||
AT_PORT="/dev/smd11"
|
||||
|
||||
# Debug file path
|
||||
DEBUG_FILE="/tmp/debug-json-result.txt"
|
||||
|
||||
# Function to escape JSON strings (handling quotes and newlines)
|
||||
escape_json() {
|
||||
# Escape newlines and double quotes
|
||||
echo "$1" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g'
|
||||
}
|
||||
|
||||
# Initialize JSON response array
|
||||
JSON_RESPONSE="["
|
||||
|
||||
# List of AT commands to run, one by one
|
||||
for COMMAND in 'AT+CGDCONT?' 'AT+QNWPREFCFG="mode_pref"' 'AT+QNWPREFCFG="nr5g_disable_mode"'; do
|
||||
# Write the command to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout
|
||||
atinout "$INPUT_FILE" "$AT_PORT" "$OUTPUT_FILE"
|
||||
|
||||
# Read the output from the output file
|
||||
OUTPUT=$(cat "$OUTPUT_FILE")
|
||||
|
||||
# Escape special characters for JSON (escape only output)
|
||||
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
|
||||
|
||||
# Append the response as an object to the JSON response array
|
||||
JSON_RESPONSE="${JSON_RESPONSE}{\"response\":\"$ESCAPED_OUTPUT\"},"
|
||||
done
|
||||
|
||||
# Remove the trailing comma and close the JSON array
|
||||
if [ "${JSON_RESPONSE: -1}" = "," ]; then
|
||||
JSON_RESPONSE="${JSON_RESPONSE%,}]"
|
||||
else
|
||||
JSON_RESPONSE="${JSON_RESPONSE}]"
|
||||
fi
|
||||
|
||||
# Write the JSON response to the debug file for troubleshooting
|
||||
echo "$JSON_RESPONSE" > "$DEBUG_FILE"
|
||||
|
||||
# Return the output as a valid JSON response
|
||||
echo "$JSON_RESPONSE"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$INPUT_FILE" "$OUTPUT_FILE"
|
||||
|
||||
# Release the lock
|
||||
flock -u 200
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Initialize error flag
|
||||
has_error=false
|
||||
error_message=""
|
||||
|
||||
# Function to append to error message
|
||||
append_error() {
|
||||
if [ -z "$error_message" ]; then
|
||||
error_message="$1"
|
||||
else
|
||||
error_message="$error_message; $1"
|
||||
fi
|
||||
has_error=true
|
||||
}
|
||||
|
||||
# Remove the entire quecmanager directory
|
||||
if [ -d "/etc/quecmanager/apn_profile/" ]; then
|
||||
rm -rf /etc/quecmanager/apn_profile/
|
||||
if [ $? -ne 0 ]; then
|
||||
append_error "Failed to remove quecmanager directory"
|
||||
fi
|
||||
else
|
||||
append_error "quecmanager directory not found"
|
||||
fi
|
||||
|
||||
# Remove the line from rc.local
|
||||
if [ -f "/etc/rc.local" ]; then
|
||||
# Create a temporary file
|
||||
temp_file=$(mktemp)
|
||||
|
||||
# Remove the apnProfiles.sh line and copy to temp file
|
||||
sed '/\/etc\/quecmanager\/apnProfiles.sh/d' /etc/rc.local > "$temp_file"
|
||||
|
||||
# Check if sed command was successful
|
||||
if [ $? -eq 0 ]; then
|
||||
# Replace original file with modified version
|
||||
mv "$temp_file" /etc/rc.local
|
||||
if [ $? -ne 0 ]; then
|
||||
append_error "Failed to update rc.local"
|
||||
fi
|
||||
else
|
||||
append_error "Failed to modify rc.local"
|
||||
rm -f "$temp_file"
|
||||
fi
|
||||
else
|
||||
append_error "rc.local file not found"
|
||||
fi
|
||||
|
||||
# Remove temporary files that might have been created
|
||||
rm -f /tmp/apn_result.txt
|
||||
rm -f /tmp/debug.log
|
||||
rm -f /tmp/inputICCID.txt
|
||||
rm -f /tmp/outputICCID.txt
|
||||
rm -f /tmp/inputAPN.txt
|
||||
rm -f /tmp/outputAPN.txt
|
||||
|
||||
# Return appropriate JSON response
|
||||
if [ "$has_error" = true ]; then
|
||||
echo "{\"status\": \"error\", \"message\": \"$error_message\"}"
|
||||
else
|
||||
echo "{\"status\": \"success\", \"message\": \"APN profiles and configuration successfully removed\"}"
|
||||
fi
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
CONFIG_FILE="/etc/quecmanager/apn_profile/apn_config.txt"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "{}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Read the configuration file
|
||||
iccidProfile1=$(grep "^iccidProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
apnProfile1=$(grep "^apnProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
pdpType1=$(grep "^pdpType1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
iccidProfile2=$(grep "^iccidProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
apnProfile2=$(grep "^apnProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
pdpType2=$(grep "^pdpType2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
|
||||
# Build the JSON response
|
||||
echo "{"
|
||||
|
||||
# Add Profile 1 if it exists
|
||||
if [ -n "$iccidProfile1" ]; then
|
||||
echo " \"profile1\": {"
|
||||
echo " \"iccid\": \"$iccidProfile1\","
|
||||
echo " \"apn\": \"$apnProfile1\","
|
||||
echo " \"pdpType\": \"$pdpType1\""
|
||||
echo " }"
|
||||
|
||||
# Add comma if Profile 2 exists
|
||||
[ -n "$iccidProfile2" ] && echo " ,"
|
||||
fi
|
||||
|
||||
# Add Profile 2 if it exists
|
||||
if [ -n "$iccidProfile2" ]; then
|
||||
echo " \"profile2\": {"
|
||||
echo " \"iccid\": \"$iccidProfile2\","
|
||||
echo " \"apn\": \"$apnProfile2\","
|
||||
echo " \"pdpType\": \"$pdpType2\""
|
||||
echo " }"
|
||||
fi
|
||||
|
||||
echo "}"
|
||||
@@ -33,11 +33,12 @@ if [ -z "$iccidProfile1" ] || [ -z "$apnProfile1" ] || [ -z "$pdpType1" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create the directory structure
|
||||
mkdir -p /etc/quecmanager
|
||||
if [ ! -d /etc/quecmanager/apn_profile ]; then
|
||||
mkdir -p /etc/quecmanager/apn_profile
|
||||
fi
|
||||
|
||||
# Create a configuration file to store APN profiles (as plain text)
|
||||
cat > /etc/quecmanager/apn_config.txt << EOF
|
||||
cat > /etc/quecmanager/apn_profile/apn_config.txt << EOF
|
||||
iccidProfile1=$iccidProfile1
|
||||
apnProfile1=$apnProfile1
|
||||
pdpType1=$pdpType1
|
||||
@@ -45,7 +46,7 @@ EOF
|
||||
|
||||
# Add second profile only if ICCID is provided
|
||||
if [ -n "$iccidProfile2" ]; then
|
||||
cat >> /etc/quecmanager/apn_config.txt << EOF
|
||||
cat >> /etc/quecmanager/apn_profile/apn_config.txt << EOF
|
||||
iccidProfile2=$iccidProfile2
|
||||
apnProfile2=$apnProfile2
|
||||
pdpType2=$pdpType2
|
||||
@@ -53,13 +54,13 @@ EOF
|
||||
fi
|
||||
|
||||
# Create the apnProfiles.sh script
|
||||
cat > /etc/quecmanager/apnProfiles.sh << 'EOF'
|
||||
cat > /etc/quecmanager/apn_profile/apnProfiles.sh << 'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
# Function to read config values
|
||||
get_config_value() {
|
||||
local key=$1
|
||||
grep "^${key}=" /etc/quecmanager/apn_config.txt | cut -d'=' -f2
|
||||
grep "^${key}=" /etc/quecmanager/apn_profile/apn_config.txt | cut -d'=' -f2
|
||||
}
|
||||
|
||||
# Read configuration
|
||||
@@ -70,13 +71,48 @@ iccidProfile2=$(get_config_value "iccidProfile2")
|
||||
apnProfile2=$(get_config_value "apnProfile2")
|
||||
pdpType2=$(get_config_value "pdpType2")
|
||||
|
||||
# Debug logging
|
||||
DEBUG_LOG="/tmp/debug.log"
|
||||
echo "Starting script at $(date)" > "$DEBUG_LOG"
|
||||
|
||||
CONFIG_FILE="/etc/quecManager.conf"
|
||||
# Check config file
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Config file not found: $CONFIG_FILE" >> "$DEBUG_LOG"
|
||||
echo '{"error": "Config file not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get AT_PORT with debug logging
|
||||
AT_PORT=$(head -n 1 "$CONFIG_FILE" | cut -d'=' -f2 | tr -d ' \n\r' | sed 's|^dev/||')
|
||||
echo "Raw config line: $(head -n 1 "$CONFIG_FILE")" >> "$DEBUG_LOG"
|
||||
echo "Extracted AT_PORT: '$AT_PORT'" >> "$DEBUG_LOG"
|
||||
|
||||
# List available devices for debugging
|
||||
ls -l /dev/smd* >> "$DEBUG_LOG" 2>&1
|
||||
|
||||
if [ -z "$AT_PORT" ]; then
|
||||
echo "AT_PORT is empty" >> "$DEBUG_LOG"
|
||||
echo '{"error": "Failed to read AT_PORT from config"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if AT_PORT exists
|
||||
if [ ! -c "/dev/$AT_PORT" ]; then
|
||||
echo "AT_PORT device not found: /dev/$AT_PORT" >> "$DEBUG_LOG"
|
||||
echo "Available smd devices:" >> "$DEBUG_LOG"
|
||||
ls -l /dev/smd* >> "$DEBUG_LOG" 2>&1
|
||||
echo '{"error": "AT_PORT device not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to get current ICCID
|
||||
get_current_iccid() {
|
||||
local input_file="/tmp/inputICCID.txt"
|
||||
local output_file="/tmp/outputICCID.txt"
|
||||
|
||||
echo "AT+ICCID" > "$input_file"
|
||||
atinout "$input_file" /dev/smd11 "$output_file"
|
||||
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
|
||||
|
||||
iccid=$(cat "$output_file" | grep "+ICCID:" | cut -d' ' -f2)
|
||||
|
||||
@@ -92,7 +128,7 @@ set_apn() {
|
||||
local output_file="/tmp/outputAPN.txt"
|
||||
|
||||
echo "AT+CGDCONT=1,\"$pdp_type\",\"$apn\";+COPS=2;+COPS=0" > "$input_file"
|
||||
atinout "$input_file" /dev/smd11 "$output_file"
|
||||
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
|
||||
|
||||
local result=$(cat "$output_file")
|
||||
rm -f "$input_file" "$output_file"
|
||||
@@ -128,15 +164,15 @@ fi
|
||||
EOF
|
||||
|
||||
# Make the script executable
|
||||
chmod +x /etc/quecmanager/apnProfiles.sh
|
||||
chmod +x /etc/quecmanager/apn_profile/apnProfiles.sh
|
||||
|
||||
# Add to rc.local if not already present
|
||||
if ! grep -q "/etc/quecmanager/apnProfiles.sh" /etc/rc.local; then
|
||||
sed -i '/^exit 0/i /etc/quecmanager/apnProfiles.sh' /etc/rc.local
|
||||
if ! grep -q "/etc/quecmanager/apn_profile/apnProfiles.sh" /etc/rc.local; then
|
||||
sed -i '/^exit 0/i /etc/quecmanager/apn_profile/apnProfiles.sh' /etc/rc.local
|
||||
fi
|
||||
|
||||
# Run the script immediately
|
||||
/etc/quecmanager/apnProfiles.sh
|
||||
/etc/quecmanager/apn_profile/apnProfiles.sh
|
||||
|
||||
# Check the result
|
||||
if [ -f /tmp/apn_result.txt ]; then
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Define the lock file
|
||||
LOCK_FILE="/tmp/home_data.lock"
|
||||
|
||||
# Acquire the lock (wait if needed)
|
||||
exec 200>$LOCK_FILE
|
||||
flock -x 200
|
||||
|
||||
# Temporary files for input/output and AT port
|
||||
INPUT_FILE="/tmp/input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/output_$$.txt"
|
||||
AT_PORT="/dev/smd11"
|
||||
|
||||
# Debug file path
|
||||
DEBUG_FILE="/tmp/debug-json-result.txt"
|
||||
|
||||
# Function to escape JSON strings (handling quotes and newlines)
|
||||
escape_json() {
|
||||
# Escape newlines and double quotes
|
||||
echo "$1" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g'
|
||||
}
|
||||
|
||||
# Initialize JSON response array
|
||||
JSON_RESPONSE="["
|
||||
|
||||
# List of AT commands to run, one by one
|
||||
for COMMAND in 'AT+CGDCONT?' 'AT+QNWPREFCFG="mode_pref"' 'AT+QNWPREFCFG="nr5g_disable_mode"' 'AT+QUIMSLOT?'; do
|
||||
# Write the command to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout
|
||||
atinout "$INPUT_FILE" "$AT_PORT" "$OUTPUT_FILE"
|
||||
|
||||
# Read the output from the output file
|
||||
OUTPUT=$(cat "$OUTPUT_FILE")
|
||||
|
||||
# Escape special characters for JSON (escape only output)
|
||||
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
|
||||
|
||||
# Append the response as an object to the JSON response array
|
||||
JSON_RESPONSE="${JSON_RESPONSE}{\"response\":\"$ESCAPED_OUTPUT\"},"
|
||||
done
|
||||
|
||||
# Remove the trailing comma and close the JSON array
|
||||
if [ "${JSON_RESPONSE: -1}" = "," ]; then
|
||||
JSON_RESPONSE="${JSON_RESPONSE%,}]"
|
||||
else
|
||||
JSON_RESPONSE="${JSON_RESPONSE}]"
|
||||
fi
|
||||
|
||||
# Write the JSON response to the debug file for troubleshooting
|
||||
echo "$JSON_RESPONSE" > "$DEBUG_FILE"
|
||||
|
||||
# Return the output as a valid JSON response
|
||||
echo "$JSON_RESPONSE"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$INPUT_FILE" "$OUTPUT_FILE"
|
||||
|
||||
# Release the lock
|
||||
flock -u 200
|
||||
@@ -1,45 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
CONFIG_FILE="/etc/quecmanager/apn_config.txt"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo '{"status": "error", "message": "No APN profiles found", "profiles": {}}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Function to read config values
|
||||
get_config_value() {
|
||||
local key=$1
|
||||
local value=$(grep "^${key}=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
echo "$value"
|
||||
}
|
||||
|
||||
# Read all profile values
|
||||
iccidProfile1=$(get_config_value "iccidProfile1")
|
||||
apnProfile1=$(get_config_value "apnProfile1")
|
||||
pdpType1=$(get_config_value "pdpType1")
|
||||
iccidProfile2=$(get_config_value "iccidProfile2")
|
||||
apnProfile2=$(get_config_value "apnProfile2")
|
||||
pdpType2=$(get_config_value "pdpType2")
|
||||
|
||||
# Construct JSON response
|
||||
cat << EOF
|
||||
{
|
||||
"status": "success",
|
||||
"profiles": {
|
||||
"profile1": {
|
||||
"iccid": "${iccidProfile1:-}",
|
||||
"apn": "${apnProfile1:-}",
|
||||
"pdpType": "${pdpType1:-}"
|
||||
},
|
||||
"profile2": {
|
||||
"iccid": "${iccidProfile2:-}",
|
||||
"apn": "${apnProfile2:-}",
|
||||
"pdpType": "${pdpType2:-}"
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Initialize error flag
|
||||
has_error=false
|
||||
error_message=""
|
||||
|
||||
# Function to append to error message
|
||||
append_error() {
|
||||
if [ -z "$error_message" ]; then
|
||||
error_message="$1"
|
||||
else
|
||||
error_message="$error_message; $1"
|
||||
fi
|
||||
has_error=true
|
||||
}
|
||||
|
||||
# Remove the entire quecmanager directory
|
||||
if [ -d "/etc/quecmanager/imei_profile/" ]; then
|
||||
rm -rf /etc/quecmanager/imei_profile/
|
||||
if [ $? -ne 0 ]; then
|
||||
append_error "Failed to remove quecmanager directory"
|
||||
fi
|
||||
else
|
||||
append_error "quecmanager directory not found"
|
||||
fi
|
||||
|
||||
# Remove the line from rc.local
|
||||
if [ -f "/etc/rc.local" ]; then
|
||||
# Create a temporary file
|
||||
temp_file=$(mktemp)
|
||||
|
||||
# Remove the imeiProfiles.sh line and copy to temp file
|
||||
sed '/\/etc\/quecmanager\/imeiProfiles.sh/d' /etc/rc.local > "$temp_file"
|
||||
|
||||
# Check if sed command was successful
|
||||
if [ $? -eq 0 ]; then
|
||||
# Replace original file with modified version
|
||||
mv "$temp_file" /etc/rc.local
|
||||
if [ $? -ne 0 ]; then
|
||||
append_error "Failed to update rc.local"
|
||||
fi
|
||||
else
|
||||
append_error "Failed to modify rc.local"
|
||||
rm -f "$temp_file"
|
||||
fi
|
||||
else
|
||||
append_error "rc.local file not found"
|
||||
fi
|
||||
|
||||
# Remove temporary files that might have been created
|
||||
rm -f /tmp/imei_result.txt
|
||||
rm -f /tmp/debug.log
|
||||
rm -f /tmp/inputICCID.txt
|
||||
rm -f /tmp/outputICCID.txt
|
||||
rm -f /tmp/inputIMEI.txt
|
||||
rm -f /tmp/outputIMEI.txt
|
||||
|
||||
# Return appropriate JSON response
|
||||
if [ "$has_error" = true ]; then
|
||||
echo "{\"status\": \"error\", \"message\": \"$error_message\"}"
|
||||
else
|
||||
echo "{\"status\": \"success\", \"message\": \"IMEI profiles and configuration successfully removed\"}"
|
||||
fi
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
CONFIG_FILE="/etc/quecmanager/imei_profile/imei_config.txt"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "{}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Read the configuration file
|
||||
iccidProfile1=$(grep "^iccidProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
imeiProfile1=$(grep "^imeiProfile1=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
iccidProfile2=$(grep "^iccidProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
imeiProfile2=$(grep "^imeiProfile2=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
|
||||
# Build the JSON response
|
||||
echo "{"
|
||||
|
||||
# Add Profile 1 if it exists
|
||||
if [ -n "$iccidProfile1" ]; then
|
||||
echo " \"profile1\": {"
|
||||
echo " \"iccid\": \"$iccidProfile1\","
|
||||
echo " \"imei\": \"$imeiProfile1\""
|
||||
echo " }"
|
||||
# Add comma if Profile 2 exists
|
||||
[ -n "$iccidProfile2" ] && echo " ,"
|
||||
fi
|
||||
|
||||
# Add Profile 2 if it exists
|
||||
if [ -n "$iccidProfile2" ]; then
|
||||
echo " \"profile2\": {"
|
||||
echo " \"iccid\": \"$iccidProfile2\","
|
||||
echo " \"imei\": \"$imeiProfile2\""
|
||||
echo " }"
|
||||
fi
|
||||
|
||||
echo "}"
|
||||
@@ -0,0 +1,209 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Parse POST data
|
||||
read -r QUERY_STRING
|
||||
|
||||
# Function to urldecode
|
||||
urldecode() {
|
||||
echo -e "$(echo "$1" | sed 's/+/ /g;s/%\([0-9A-F][0-9A-F]\)/\\x\1/g')"
|
||||
}
|
||||
|
||||
# Extract values from POST data
|
||||
iccidProfile1=$(echo "$QUERY_STRING" | grep -o 'iccidProfile1=[^&]*' | cut -d= -f2)
|
||||
imeiProfile1=$(echo "$QUERY_STRING" | grep -o 'imeiProfile1=[^&]*' | cut -d= -f2)
|
||||
iccidProfile2=$(echo "$QUERY_STRING" | grep -o 'iccidProfile2=[^&]*' | cut -d= -f2)
|
||||
imeiProfile2=$(echo "$QUERY_STRING" | grep -o 'imeiProfile2=[^&]*' | cut -d= -f2)
|
||||
|
||||
# URL decode the values
|
||||
iccidProfile1=$(urldecode "$iccidProfile1")
|
||||
imeiProfile1=$(urldecode "$imeiProfile1")
|
||||
iccidProfile2=$(urldecode "$iccidProfile2")
|
||||
imeiProfile2=$(urldecode "$imeiProfile2")
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Validate required first profile
|
||||
if [ -z "$iccidProfile1" ] || [ -z "$imeiProfile1" ]; then
|
||||
echo '{"status": "error", "message": "Profile 1 is required"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check the directory if it exists, if not create it
|
||||
if [ ! -d /etc/quecmanager/imei_profile ]; then
|
||||
mkdir -p /etc/quecmanager/imei_profile
|
||||
fi
|
||||
|
||||
# Create a configuration file to store IMEI profiles
|
||||
cat >/etc/quecmanager/imei_profile/imei_config.txt <<EOF
|
||||
iccidProfile1=$iccidProfile1
|
||||
imeiProfile1=$imeiProfile1
|
||||
EOF
|
||||
|
||||
# Add second profile only if ICCID is provided
|
||||
if [ -n "$iccidProfile2" ]; then
|
||||
cat >>/etc/quecmanager/imei_profile/imei_config.txt <<EOF
|
||||
iccidProfile2=$iccidProfile2
|
||||
imeiProfile2=$imeiProfile2
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Create the imeiProfiles.sh script
|
||||
cat >/etc/quecmanager/imei_profile/imeiProfiles.sh <<'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
# Function to read config values
|
||||
get_config_value() {
|
||||
local key=$1
|
||||
grep "^${key}=" /etc/quecmanager/imei_profile/imei_config.txt | cut -d'=' -f2
|
||||
}
|
||||
|
||||
# Read configuration
|
||||
iccidProfile1=$(get_config_value "iccidProfile1")
|
||||
imeiProfile1=$(get_config_value "imeiProfile1")
|
||||
iccidProfile2=$(get_config_value "iccidProfile2")
|
||||
imeiProfile2=$(get_config_value "imeiProfile2")
|
||||
|
||||
# Debug logging
|
||||
DEBUG_LOG="/tmp/debug.log"
|
||||
echo "Starting IMEI profile script at $(date)" > "$DEBUG_LOG"
|
||||
|
||||
CONFIG_FILE="/etc/quecManager.conf"
|
||||
# Check config file
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Config file not found: $CONFIG_FILE" >> "$DEBUG_LOG"
|
||||
echo '{"error": "Config file not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get AT_PORT with debug logging
|
||||
AT_PORT=$(head -n 1 "$CONFIG_FILE" | cut -d'=' -f2 | tr -d ' \n\r' | sed 's|^dev/||')
|
||||
echo "Raw config line: $(head -n 1 "$CONFIG_FILE")" >> "$DEBUG_LOG"
|
||||
echo "Extracted AT_PORT: '$AT_PORT'" >> "$DEBUG_LOG"
|
||||
|
||||
if [ -z "$AT_PORT" ]; then
|
||||
echo "AT_PORT is empty" >> "$DEBUG_LOG"
|
||||
echo '{"error": "Failed to read AT_PORT from config"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if AT_PORT exists
|
||||
if [ ! -c "/dev/$AT_PORT" ]; then
|
||||
echo "AT_PORT device not found: /dev/$AT_PORT" >> "$DEBUG_LOG"
|
||||
echo '{"error": "AT_PORT device not found"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to get current ICCID
|
||||
get_current_iccid() {
|
||||
local input_file="/tmp/inputICCID.txt"
|
||||
local output_file="/tmp/outputICCID.txt"
|
||||
|
||||
echo "AT+ICCID" > "$input_file"
|
||||
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
|
||||
|
||||
iccid=$(cat "$output_file" | grep "+ICCID:" | cut -d' ' -f2)
|
||||
|
||||
rm -f "$input_file" "$output_file"
|
||||
echo "$iccid"
|
||||
}
|
||||
|
||||
# Function to get current IMEI
|
||||
get_current_imei() {
|
||||
local input_file="/tmp/inputCGSN.txt"
|
||||
local output_file="/tmp/outputCGSN.txt"
|
||||
|
||||
echo "AT+CGSN" > "$input_file"
|
||||
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
|
||||
|
||||
# Extract IMEI from the response, removing any whitespace or newlines
|
||||
imei=$(cat "$output_file" | grep -v "AT+CGSN" | grep -v "OK" | tr -d '\r\n[:space:]')
|
||||
|
||||
rm -f "$input_file" "$output_file"
|
||||
echo "$imei"
|
||||
}
|
||||
|
||||
# Function to set IMEI
|
||||
set_imei() {
|
||||
local imei="$1"
|
||||
local input_file="/tmp/inputIMEI.txt"
|
||||
local output_file="/tmp/outputIMEI.txt"
|
||||
|
||||
echo "AT+EGMR=1,7,\"$imei\";+QPOWD=1" > "$input_file"
|
||||
atinout "$input_file" "/dev/$AT_PORT" "$output_file"
|
||||
|
||||
local result=$(cat "$output_file")
|
||||
rm -f "$input_file" "$output_file"
|
||||
|
||||
if echo "$result" | grep -q "OK"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get current ICCID and IMEI
|
||||
current_iccid=$(get_current_iccid)
|
||||
current_imei=$(get_current_imei)
|
||||
success=false
|
||||
|
||||
echo "Current ICCID: $current_iccid" >> "$DEBUG_LOG"
|
||||
echo "Current IMEI: $current_imei" >> "$DEBUG_LOG"
|
||||
echo "Profile 1 - ICCID: $iccidProfile1, IMEI: $imeiProfile1" >> "$DEBUG_LOG"
|
||||
echo "Profile 2 - ICCID: $iccidProfile2, IMEI: $imeiProfile2" >> "$DEBUG_LOG"
|
||||
|
||||
# Check ICCID against profile 1 (required)
|
||||
if [ "$current_iccid" = "$iccidProfile1" ]; then
|
||||
if [ "$current_imei" != "$imeiProfile1" ]; then
|
||||
echo "ICCID matches profile 1, but IMEI needs updating" >> "$DEBUG_LOG"
|
||||
if set_imei "$imeiProfile1"; then
|
||||
success=true
|
||||
fi
|
||||
else
|
||||
echo "ICCID and IMEI already match profile 1, no action needed" >> "$DEBUG_LOG"
|
||||
success=true
|
||||
fi
|
||||
# Check ICCID against profile 2 (optional)
|
||||
elif [ -n "$iccidProfile2" ] && [ "$current_iccid" = "$iccidProfile2" ]; then
|
||||
if [ "$current_imei" != "$imeiProfile2" ]; then
|
||||
echo "ICCID matches profile 2, but IMEI needs updating" >> "$DEBUG_LOG"
|
||||
if set_imei "$imeiProfile2"; then
|
||||
success=true
|
||||
fi
|
||||
else
|
||||
echo "ICCID and IMEI already match profile 2, no action needed" >> "$DEBUG_LOG"
|
||||
success=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$success" = "true" ]; then
|
||||
echo "IMEI check/update completed successfully" > /tmp/imei_result.txt
|
||||
else
|
||||
echo "Failed to check/update IMEI" > /tmp/imei_result.txt
|
||||
fi
|
||||
EOF
|
||||
|
||||
# Make the script executable
|
||||
chmod +x /etc/quecmanager/imei_profile/imeiProfiles.sh
|
||||
|
||||
# Add to rc.local if not already present
|
||||
if ! grep -q "/etc/quecmanager/imei_profile/imeiProfiles.sh" /etc/rc.local; then
|
||||
sed -i '/^exit 0/i /etc/quecmanager/imei_profile/imeiProfiles.sh' /etc/rc.local
|
||||
fi
|
||||
|
||||
# Run the script immediately
|
||||
/etc/quecmanager/imei_profile/imeiProfiles.sh
|
||||
|
||||
# Check the result
|
||||
if [ -f /tmp/imei_result.txt ]; then
|
||||
result=$(cat /tmp/imei_result.txt)
|
||||
rm -f /tmp/imei_result.txt
|
||||
|
||||
if [ "$result" = "IMEI set successfully" ]; then
|
||||
echo '{"status": "success", "message": "IMEI profiles saved and applied successfully"}'
|
||||
else
|
||||
echo '{"status": "error", "message": "IMEI profiles saved but failed to apply"}'
|
||||
fi
|
||||
else
|
||||
echo '{"status": "error", "message": "Something went wrong while processing IMEI profiles"}'
|
||||
fi
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set the content type to JSON
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Ping 8.8.8.8 and capture the result
|
||||
if ping -c 1 8.8.8.8 > /dev/null 2>&1; then
|
||||
# Ping was successful
|
||||
echo '{"connection": "ACTIVE"}'
|
||||
else
|
||||
# Ping failed
|
||||
echo '{"connection": "INACTIVE"}'
|
||||
fi
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configuration and log directories
|
||||
CONFIG_DIR="/etc/quecmanager/quecwatch"
|
||||
QUECWATCH_SCRIPT="${CONFIG_DIR}/quecwatch.sh"
|
||||
RCLOCAL="/etc/rc.local"
|
||||
LOG_DIR="/tmp/log/quecwatch"
|
||||
DEBUG_LOG_FILE="${LOG_DIR}/debug.log"
|
||||
|
||||
# Log directory for cleaning process
|
||||
CLEANUP_LOG_FILE="${LOG_DIR}/cleanup.log"
|
||||
|
||||
# Ensure log directory exists
|
||||
mkdir -p "${LOG_DIR}"
|
||||
|
||||
# Function to log cleanup events
|
||||
log_cleanup() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "${CLEANUP_LOG_FILE}"
|
||||
}
|
||||
|
||||
# Default response headers
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Cleanup function
|
||||
cleanup_quecwatch() {
|
||||
# Start logging cleanup process
|
||||
log_cleanup "Starting QuecWatch cleanup process"
|
||||
|
||||
# Stop any running QuecWatch processes
|
||||
log_cleanup "Stopping QuecWatch processes"
|
||||
pkill -f "${QUECWATCH_SCRIPT}" >> "${CLEANUP_LOG_FILE}" 2>&1
|
||||
|
||||
# Remove QuecWatch script from rc.local
|
||||
if [ -f "${RCLOCAL}" ]; then
|
||||
log_cleanup "Removing QuecWatch entries from rc.local"
|
||||
sed -i '\|/etc/quecmanager/quecwatch/quecwatch.sh|d' "${RCLOCAL}" >> "${CLEANUP_LOG_FILE}" 2>&1
|
||||
fi
|
||||
|
||||
# Remove configuration directory
|
||||
if [ -d "${CONFIG_DIR}" ]; then
|
||||
log_cleanup "Removing configuration directory: ${CONFIG_DIR}"
|
||||
rm -rf "${CONFIG_DIR}" >> "${CLEANUP_LOG_FILE}" 2>&1
|
||||
fi
|
||||
|
||||
# Remove log directory
|
||||
if [ -d "${LOG_DIR}" ]; then
|
||||
log_cleanup "Removing log directory: ${LOG_DIR}"
|
||||
rm -rf "${LOG_DIR}" >> "${CLEANUP_LOG_FILE}" 2>&1
|
||||
fi
|
||||
|
||||
log_cleanup "QuecWatch cleanup completed successfully"
|
||||
|
||||
# Optional: Output JSON response
|
||||
echo '{"status": "success", "message": "QuecWatch disabled and removed"}'
|
||||
}
|
||||
|
||||
# Execute cleanup
|
||||
cleanup_quecwatch
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,356 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Read POST data
|
||||
read -r QUERY_STRING
|
||||
|
||||
# Function to urldecode
|
||||
urldecode() {
|
||||
echo -e "$(echo "$1" | sed 's/+/ /g;s/%\([0-9A-F][0-9A-F]\)/\\x\1/g')"
|
||||
}
|
||||
|
||||
# Configuration directory
|
||||
CONFIG_DIR="/etc/quecmanager/quecwatch"
|
||||
QUECWATCH_CONFIG="${CONFIG_DIR}/quecwatch.conf"
|
||||
QUECWATCH_SCRIPT="${CONFIG_DIR}/quecwatch.sh"
|
||||
RCLOCAL="/etc/rc.local"
|
||||
LOG_DIR="/tmp/log/quecwatch"
|
||||
DEBUG_LOG_FILE="${LOG_DIR}/debug.log"
|
||||
|
||||
# Ensure log directory exists
|
||||
mkdir -p "${LOG_DIR}"
|
||||
|
||||
# Extract values from POST data
|
||||
action=$(echo "$QUERY_STRING" | grep -o 'action=[^&]*' | cut -d= -f2)
|
||||
ping_target=$(echo "$QUERY_STRING" | grep -o 'ping_target=[^&]*' | cut -d= -f2)
|
||||
ping_interval=$(echo "$QUERY_STRING" | grep -o 'ping_interval=[^&]*' | cut -d= -f2)
|
||||
ping_failures=$(echo "$QUERY_STRING" | grep -o 'ping_failures=[^&]*' | cut -d= -f2)
|
||||
max_retries=$(echo "$QUERY_STRING" | grep -o 'max_retries=[^&]*' | cut -d= -f2)
|
||||
connection_refresh=$(echo "$QUERY_STRING" | grep -o 'connection_refresh=[^&]*' | cut -d= -f2)
|
||||
auto_sim_failover=$(echo "$QUERY_STRING" | grep -o 'auto_sim_failover=[^&]*' | cut -d= -f2)
|
||||
sim_failover_schedule=$(echo "$QUERY_STRING" | grep -o 'sim_failover_schedule=[^&]*' | cut -d= -f2)
|
||||
mobile_data_reconnect=$(echo "$QUERY_STRING" | grep -o 'mobile_data_reconnect=[^&]*' | cut -d= -f2)
|
||||
|
||||
# URL decode the values
|
||||
action=$(urldecode "$action")
|
||||
ping_target=$(urldecode "$ping_target")
|
||||
ping_interval=$(urldecode "$ping_interval")
|
||||
ping_failures=$(urldecode "$ping_failures")
|
||||
max_retries=$(urldecode "$max_retries")
|
||||
connection_refresh=$(urldecode "$connection_refresh")
|
||||
auto_sim_failover=$(urldecode "$auto_sim_failover")
|
||||
sim_failover_schedule=$(urldecode "$sim_failover_schedule")
|
||||
mobile_data_reconnect=$(urldecode "$mobile_data_reconnect")
|
||||
|
||||
# Default response headers
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Validate inputs
|
||||
if [ -z "$ping_target" ]; then
|
||||
echo '{"status": "error", "message": "Ping target is required"}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Initialize configuration function
|
||||
initialize_config() {
|
||||
# Create config directory if not exists
|
||||
mkdir -p "${CONFIG_DIR}"
|
||||
|
||||
# Write configuration with defaults and user-provided values
|
||||
cat >"${QUECWATCH_CONFIG}" <<EOL
|
||||
# QuecWatch Configuration File
|
||||
# Ping Target (IP or domain to ping)
|
||||
PING_TARGET=${ping_target}
|
||||
# Interval between ping checks (in seconds)
|
||||
PING_INTERVAL=${ping_interval:-30}
|
||||
# Number of consecutive ping failures before taking action
|
||||
PING_FAILURES=${ping_failures:-3}
|
||||
# Maximum number of retry attempts
|
||||
MAX_RETRIES=${max_retries:-5}
|
||||
# Current retry count (should start at 0)
|
||||
CURRENT_RETRIES=0
|
||||
# Enable/Disable Connection Refresh
|
||||
CONNECTION_REFRESH=${connection_refresh:-false}
|
||||
# Number of connection refresh attempts
|
||||
REFRESH_COUNT=${connection_refresh:+3}
|
||||
# Enable/Disable Auto SIM Failover
|
||||
AUTO_SIM_FAILOVER=${auto_sim_failover:-false}
|
||||
# Schedule for checking initial SIM (in minutes)
|
||||
# 0 means no scheduled check
|
||||
SIM_FAILOVER_SCHEDULE=${sim_failover_schedule:-0}
|
||||
# Enable/Disable Mobile Data Reconnect
|
||||
MOBILE_DATA_RECONNECT=${mobile_data_reconnect:-false}
|
||||
# Indicate that QuecWatch is enabled
|
||||
ENABLED=true
|
||||
EOL
|
||||
|
||||
chmod 644 "${QUECWATCH_CONFIG}"
|
||||
}
|
||||
|
||||
# Generate monitoring script function
|
||||
generate_monitoring_script() {
|
||||
cat >"${QUECWATCH_SCRIPT}" <<'EOL'
|
||||
#!/bin/sh
|
||||
|
||||
# Load configuration
|
||||
. /etc/quecmanager/quecwatch/quecwatch.conf
|
||||
|
||||
# Log directory
|
||||
LOG_DIR="/tmp/log/quecwatch"
|
||||
mkdir -p "${LOG_DIR}"
|
||||
|
||||
# Function to log events
|
||||
log_event() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "${LOG_DIR}/quecwatch.log"
|
||||
}
|
||||
|
||||
# Function to update retry count in config
|
||||
update_retry_count() {
|
||||
local new_retry_count=$1
|
||||
sed -i "s/CURRENT_RETRIES=[0-9]*/CURRENT_RETRIES=${new_retry_count}/" /etc/quecmanager/quecwatch/quecwatch.conf
|
||||
# Reload config to ensure latest values
|
||||
. /etc/quecmanager/quecwatch/quecwatch.conf
|
||||
}
|
||||
|
||||
# Function to switch SIM card
|
||||
switch_sim_card() {
|
||||
log_event "Attempting to switch SIM card"
|
||||
|
||||
# Create log directory if it doesn't exist
|
||||
mkdir -p /tmp/log/quecwatch
|
||||
|
||||
# Get current SIM slot using AT command
|
||||
echo AT+QUIMSLOT? | atinout - /dev/smd7 /tmp/log/quecwatch/current_sim.txt
|
||||
|
||||
# Extract numerical value from the output
|
||||
current_sim_slot=$(grep "+QUIMSLOT:" /tmp/log/quecwatch/current_sim.txt | awk '{print $2}')
|
||||
|
||||
# Toggle between SIM slots (assuming 2 SIM slots)
|
||||
if [ "${current_sim_slot}" = "1" ]; then
|
||||
new_sim_slot=2
|
||||
else
|
||||
new_sim_slot=1
|
||||
fi
|
||||
|
||||
# Explicitly set the new SIM slot
|
||||
log_event "Switching from SIM slot ${current_sim_slot} to SIM slot ${new_sim_slot}"
|
||||
|
||||
# Add your SIM switching command here
|
||||
# Example (adjust based on your modem's AT commands):
|
||||
echo "AT+QUIMSLOT=${new_sim_slot}" | atinout - /dev/smd7 -
|
||||
|
||||
# Update current_sim_slot with the new value
|
||||
current_sim_slot=${new_sim_slot}
|
||||
}
|
||||
|
||||
# Function to toggle mobile data
|
||||
toggle_mobile_data() {
|
||||
log_event "Toggling mobile data"
|
||||
# Use CFUN to restart mobile functionality
|
||||
echo AT+CFUN=0 | atinout - /dev/smd7 -
|
||||
#sleep 5
|
||||
echo AT+CFUN=1 | atinout - /dev/smd7 -
|
||||
}
|
||||
|
||||
# Function to perform connection recovery
|
||||
perform_connection_recovery() {
|
||||
local recovery_attempted=0
|
||||
|
||||
# 1. Try Connection Refresh first if enabled (when retry_trigger is 1)
|
||||
if [ "${CONNECTION_REFRESH}" = "true" ] && [ "${retry_trigger}" -eq 1 ] && [ "${REFRESH_COUNT}" -gt 0 ]; then
|
||||
log_event "Attempting connection refresh"
|
||||
echo AT+COPS=2 | atinout - /dev/smd7 -
|
||||
sleep 2
|
||||
echo AT+COPS=0 | atinout - /dev/smd7 -
|
||||
|
||||
# Verify connection after refresh
|
||||
if ping -c 3 ${PING_TARGET} > /dev/null 2>&1; then
|
||||
log_event "Connection refresh successful"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Decrement refresh count
|
||||
REFRESH_COUNT=$((REFRESH_COUNT - 1))
|
||||
sed -i "s/REFRESH_COUNT=.*/REFRESH_COUNT=${REFRESH_COUNT}/" /etc/quecmanager/quecwatch/quecwatch.conf
|
||||
recovery_attempted=1
|
||||
fi
|
||||
|
||||
# 2. Try Auto SIM Failover when retry_trigger is 2 (or 1 if Connection Refresh is disabled)
|
||||
local sim_failover_trigger=$((CONNECTION_REFRESH == "true" ? 2 : 1))
|
||||
if [ "${AUTO_SIM_FAILOVER}" = "true" ] && [ "${retry_trigger}" -eq ${sim_failover_trigger} ]; then
|
||||
log_event "Attempting SIM failover"
|
||||
|
||||
# Get current SIM slot
|
||||
echo AT+QUIMSLOT? | atinout - /dev/smd7 /tmp/log/quecwatch/current_sim.txt
|
||||
initial_sim_slot=$(grep "+QUIMSLOT:" /tmp/log/quecwatch/current_sim.txt | awk '{print $2}')
|
||||
|
||||
# Switch SIM card
|
||||
switch_sim_card
|
||||
|
||||
# Verify connection after SIM switch
|
||||
if ping -c 3 ${PING_TARGET} > /dev/null 2>&1; then
|
||||
log_event "SIM failover successful"
|
||||
return 0
|
||||
fi
|
||||
|
||||
recovery_attempted=1
|
||||
fi
|
||||
|
||||
# 3. Try Mobile Data Reconnect if enabled
|
||||
if [ "${MOBILE_DATA_RECONNECT}" = "true" ]; then
|
||||
log_event "Attempting mobile data reconnect"
|
||||
toggle_mobile_data
|
||||
|
||||
# Verify connection after mobile data toggle
|
||||
if ping -c 3 ${PING_TARGET} > /dev/null 2>&1; then
|
||||
log_event "Mobile data reconnect successful"
|
||||
return 0
|
||||
fi
|
||||
recovery_attempted=1
|
||||
fi
|
||||
|
||||
# 4. If no recovery methods worked or none were enabled, return failure
|
||||
if [ ${recovery_attempted} -eq 0 ]; then
|
||||
log_event "No recovery methods enabled"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
while true; do
|
||||
# Ping the target
|
||||
if ! ping -c ${PING_FAILURES} ${PING_TARGET} > /dev/null 2>&1; then
|
||||
failure_count=$((failure_count + 1))
|
||||
log_event "Ping failed. Failure count: ${failure_count}"
|
||||
|
||||
# Check if failure threshold is reached
|
||||
if [ ${failure_count} -ge ${PING_FAILURES} ]; then
|
||||
# Reset failure count
|
||||
failure_count=0
|
||||
retry_trigger=$((retry_trigger + 1))
|
||||
|
||||
# Update retry count in config
|
||||
update_retry_count ${retry_trigger}
|
||||
|
||||
log_event "Failure threshold reached. Retry trigger: ${retry_trigger}"
|
||||
|
||||
# Check if retry threshold is reached
|
||||
if [ ${retry_trigger} -ge ${MAX_RETRIES} ]; then
|
||||
log_event "Max retries exhausted. Removing QuecWatch."
|
||||
|
||||
# Remove the script from rc.local
|
||||
sed -i '\|/etc/quecmanager/quecwatch/quecwatch.sh|d' /etc/rc.local
|
||||
|
||||
# Perform final system reboot
|
||||
reboot
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Attempt connection recovery
|
||||
if perform_connection_recovery; then
|
||||
# Recovery successful
|
||||
log_event "Connection recovery successful"
|
||||
retry_trigger=0
|
||||
failure_count=0
|
||||
update_retry_count 0
|
||||
else
|
||||
# Recovery failed, choose recovery method based on configurations
|
||||
if [ "${MOBILE_DATA_RECONNECT}" = "true" ]; then
|
||||
log_event "Recovery failed. Attempting mobile data restart."
|
||||
toggle_mobile_data
|
||||
else
|
||||
log_event "Recovery failed. Rebooting system."
|
||||
reboot
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Reset failure count and retry trigger if connection is good
|
||||
failure_count=0
|
||||
retry_trigger=0
|
||||
update_retry_count 0
|
||||
|
||||
# Add success log message
|
||||
log_event "Modem is connected to the internet"
|
||||
|
||||
# Check if SIM Failover Scheduler is enabled and interval has passed
|
||||
if [ "${AUTO_SIM_FAILOVER}" = "true" ] && [ "${SIM_FAILOVER_SCHEDULE}" -gt 0 ]; then
|
||||
sim_failover_interval=$((sim_failover_interval + 1))
|
||||
|
||||
# Check if it's time to switch back to initial SIM
|
||||
if [ $((sim_failover_interval * ${PING_INTERVAL})) -ge $((${SIM_FAILOVER_SCHEDULE} * 60)) ]; then
|
||||
log_event "Checking initial SIM card"
|
||||
|
||||
# Only switch back if max retries were NOT exhausted
|
||||
if [ ${retry_trigger} -lt ${MAX_RETRIES} ]; then
|
||||
# Switch back to initial SIM
|
||||
echo AT+QUIMSLOT=${initial_sim_slot} | atinout - /dev/smd7 -
|
||||
|
||||
# Check connection on initial SIM
|
||||
if ping -c 3 ${PING_TARGET} > /dev/null 2>&1; then
|
||||
log_event "Initial SIM restored successfully"
|
||||
current_sim_slot=${initial_sim_slot}
|
||||
# Reset retry trigger when switching back
|
||||
retry_trigger=0
|
||||
failure_count=0
|
||||
update_retry_count 0
|
||||
else
|
||||
log_event "Initial SIM still not working. Remaining on failover SIM."
|
||||
fi
|
||||
|
||||
# Reset interval counter
|
||||
sim_failover_interval=0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Wait for specified interval before next check
|
||||
sleep ${PING_INTERVAL}
|
||||
done
|
||||
EOL
|
||||
|
||||
chmod +x "${QUECWATCH_SCRIPT}"
|
||||
|
||||
# Run the script
|
||||
"${QUECWATCH_SCRIPT}" &
|
||||
}
|
||||
|
||||
# Enable QuecWatch
|
||||
enable_quecwatch() {
|
||||
# Initialize configuration
|
||||
initialize_config
|
||||
|
||||
# Generate monitoring script
|
||||
generate_monitoring_script
|
||||
|
||||
# Add to rc.local if not already present
|
||||
if ! grep -q "${QUECWATCH_SCRIPT}" "${RCLOCAL}"; then
|
||||
[ -f "${RCLOCAL}" ] || touch "${RCLOCAL}"
|
||||
chmod +x "${RCLOCAL}"
|
||||
sed -i '$i'"${QUECWATCH_SCRIPT} &" "${RCLOCAL}"
|
||||
fi
|
||||
|
||||
# Output success JSON
|
||||
echo '{"status": "success", "message": "QuecWatch enabled", "config": "'${QUECWATCH_CONFIG}'"}'
|
||||
}
|
||||
|
||||
# Log debug information
|
||||
{
|
||||
echo "Timestamp: $(date)"
|
||||
echo "Script Path: $0"
|
||||
echo "Ping Target: $ping_target"
|
||||
echo "Ping Interval: $ping_interval"
|
||||
echo "Ping Failures: $ping_failures"
|
||||
echo "Max Retries: $max_retries"
|
||||
echo "Connection Refresh: $connection_refresh"
|
||||
echo "Auto SIM Failover: $auto_sim_failover"
|
||||
echo "SIM Failover Schedule: $sim_failover_schedule"
|
||||
echo "Mobile Data Reconnect: $mobile_data_reconnect"
|
||||
} >>"$DEBUG_LOG_FILE" 2>&1
|
||||
|
||||
# Enable QuecWatch
|
||||
enable_quecwatch
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set headers for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Configuration file path
|
||||
CONFIG_FILE="/etc/quecmanager/quecwatch/quecwatch.conf"
|
||||
|
||||
# Check if configuration file exists
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo '{"status": "inactive", "message": "QuecWatch is not configured"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Function to safely get config value
|
||||
get_config_value() {
|
||||
grep "^$1=" "$CONFIG_FILE" | cut -d'=' -f2
|
||||
}
|
||||
|
||||
# Check if QuecWatch is enabled
|
||||
enabled=$(get_config_value "ENABLED")
|
||||
if [ "$enabled" != "true" ]; then
|
||||
echo '{"status": "inactive", "message": "QuecWatch is disabled"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Fetch configuration values
|
||||
ping_target=$(get_config_value "PING_TARGET")
|
||||
ping_interval=$(get_config_value "PING_INTERVAL")
|
||||
ping_failures=$(get_config_value "PING_FAILURES")
|
||||
max_retries=$(get_config_value "MAX_RETRIES")
|
||||
current_retries=$(get_config_value "CURRENT_RETRIES")
|
||||
connection_refresh=$(get_config_value "CONNECTION_REFRESH")
|
||||
refresh_count=$(get_config_value "REFRESH_COUNT")
|
||||
|
||||
# New configuration options
|
||||
mobile_data_reconnect=$(get_config_value "MOBILE_DATA_RECONNECT")
|
||||
auto_sim_failover=$(get_config_value "AUTO_SIM_FAILOVER")
|
||||
sim_failover_schedule=$(get_config_value "SIM_FAILOVER_SCHEDULE")
|
||||
|
||||
# Default values if not set
|
||||
mobile_data_reconnect=${mobile_data_reconnect:-false}
|
||||
auto_sim_failover=${auto_sim_failover:-false}
|
||||
sim_failover_schedule=${sim_failover_schedule:-30}
|
||||
|
||||
# Check monitoring script existence
|
||||
QUECWATCH_SCRIPT="/etc/quecmanager/quecwatch/quecwatch.sh"
|
||||
if [ ! -f "$QUECWATCH_SCRIPT" ]; then
|
||||
echo '{"status": "error", "message": "Monitoring script is missing"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check log file for recent activity
|
||||
LOG_FILE="/tmp/log/quecwatch/quecwatch.log"
|
||||
last_log=""
|
||||
if [ -f "$LOG_FILE" ]; then
|
||||
last_log=$(tail -n 1 "$LOG_FILE")
|
||||
fi
|
||||
|
||||
# Prepare JSON response
|
||||
cat <<EOF
|
||||
{
|
||||
"status": "active",
|
||||
"config": {
|
||||
"pingTarget": "${ping_target}",
|
||||
"pingInterval": ${ping_interval},
|
||||
"pingFailures": ${ping_failures},
|
||||
"maxRetries": ${max_retries},
|
||||
"currentRetries": ${current_retries},
|
||||
"connectionRefresh": ${connection_refresh},
|
||||
"refreshCount": ${refresh_count:-0},
|
||||
"mobileDataReconnect": ${mobile_data_reconnect},
|
||||
"autoSimFailover": ${auto_sim_failover},
|
||||
"simFailoverSchedule": ${sim_failover_schedule}
|
||||
},
|
||||
"lastActivity": "${last_log}"
|
||||
}
|
||||
EOF
|
||||
@@ -1,45 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
CONFIG_FILE="/etc/quecmanager/apn_config.txt"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo '{"status": "error", "message": "No APN profiles found", "profiles": {}}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Function to read config values
|
||||
get_config_value() {
|
||||
local key=$1
|
||||
local value=$(grep "^${key}=" "$CONFIG_FILE" | cut -d'=' -f2)
|
||||
echo "$value"
|
||||
}
|
||||
|
||||
# Read all profile values
|
||||
iccidProfile1=$(get_config_value "iccidProfile1")
|
||||
apnProfile1=$(get_config_value "apnProfile1")
|
||||
pdpType1=$(get_config_value "pdpType1")
|
||||
iccidProfile2=$(get_config_value "iccidProfile2")
|
||||
apnProfile2=$(get_config_value "apnProfile2")
|
||||
pdpType2=$(get_config_value "pdpType2")
|
||||
|
||||
# Construct JSON response
|
||||
cat << EOF
|
||||
{
|
||||
"status": "success",
|
||||
"profiles": {
|
||||
"profile1": {
|
||||
"iccid": "${iccidProfile1:-}",
|
||||
"apn": "${apnProfile1:-}",
|
||||
"pdpType": "${pdpType1:-}"
|
||||
},
|
||||
"profile2": {
|
||||
"iccid": "${iccidProfile2:-}",
|
||||
"apn": "${apnProfile2:-}",
|
||||
"pdpType": "${pdpType2:-}"
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
141
ipk-source/sdxpinn-quecmanager/root/www/cgi-bin/fetch_data.sh
Executable file
141
ipk-source/sdxpinn-quecmanager/root/www/cgi-bin/fetch_data.sh
Executable file
@@ -0,0 +1,141 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Function to output error in JSON format
|
||||
output_error() {
|
||||
echo "{\"error\": \"$1\"}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Define command sets
|
||||
define_command_sets() {
|
||||
COMMAND_SET_1='AT+QUIMSLOT? AT+CNUM AT+COPS? AT+CIMI AT+ICCID AT+CGSN AT+CPIN? AT+CGDCONT? AT+CREG? AT+CFUN? AT+QENG="servingcell" AT+QTEMP AT+CGCONTRDP AT+QCAINFO AT+QRSRP AT+QMAP="WWAN" AT+C5GREG=2;+C5GREG? AT+CGREG=2;+CGREG? AT+QRSRQ AT+QSINR'
|
||||
|
||||
COMMAND_SET_2='AT+CGDCONT? AT+CGCONTRDP AT+QNWPREFCFG="mode_pref" AT+QNWPREFCFG="nr5g_disable_mode" AT+QUIMSLOT?'
|
||||
|
||||
COMMAND_SET_3='AT+CGMI AT+CGMM AT+QGMR AT+CNUM AT+CIMI AT+ICCID AT+CGSN AT+QMAP="LANIP" AT+QMAP="WWAN" AT+QGETCAPABILITY'
|
||||
|
||||
COMMAND_SET_4='AT+QMAP="MPDN_RULE" AT+QMAP="DHCPV4DNS" AT+QCFG="usbnet"'
|
||||
|
||||
COMMAND_SET_5='AT+QRSRP AT+QRSRQ AT+QSINR AT+QCAINFO AT+QSPN'
|
||||
|
||||
COMMAND_SET_6='AT+CEREG=2;+CEREG? AT+C5GREG=2;+C5GREG? AT+CPIN? AT+CGDCONT? AT+CGCONTRDP AT+QMAP="WWAN" AT+QRSRP AT+QTEMP AT+QNETRC?'
|
||||
}
|
||||
|
||||
# Define the lock file
|
||||
LOCK_FILE="/tmp/home_data.lock"
|
||||
|
||||
# Acquire the lock (wait if needed)
|
||||
exec 200>$LOCK_FILE
|
||||
flock -x 200 || output_error "Unable to acquire lock"
|
||||
|
||||
# Temporary files for input/output and AT port
|
||||
INPUT_FILE="/tmp/input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/output_$$.txt"
|
||||
|
||||
# Debug logging
|
||||
DEBUG_LOG="/tmp/debug.log"
|
||||
echo "Starting script at $(date)" > "$DEBUG_LOG"
|
||||
|
||||
CONFIG_FILE="/etc/quecManager.conf"
|
||||
# Check config file
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Config file not found: $CONFIG_FILE" >> "$DEBUG_LOG"
|
||||
output_error "Config file not found"
|
||||
fi
|
||||
|
||||
# Get AT_PORT with debug logging
|
||||
AT_PORT=$(head -n 1 "$CONFIG_FILE" | cut -d'=' -f2 | tr -d ' \n\r' | sed 's|^dev/||')
|
||||
echo "Raw config line: $(head -n 1 "$CONFIG_FILE")" >> "$DEBUG_LOG"
|
||||
echo "Extracted AT_PORT: '$AT_PORT'" >> "$DEBUG_LOG"
|
||||
|
||||
if [ -z "$AT_PORT" ]; then
|
||||
echo "AT_PORT is empty" >> "$DEBUG_LOG"
|
||||
output_error "Failed to read AT_PORT from config"
|
||||
fi
|
||||
|
||||
# Check if AT_PORT exists
|
||||
if [ ! -c "/dev/$AT_PORT" ]; then
|
||||
echo "AT_PORT device not found: /dev/$AT_PORT" >> "$DEBUG_LOG"
|
||||
echo "Available smd devices:" >> "$DEBUG_LOG"
|
||||
ls -l /dev/smd* >> "$DEBUG_LOG" 2>&1
|
||||
output_error "AT_PORT device not found"
|
||||
fi
|
||||
|
||||
# Function to escape JSON strings (handling quotes and newlines)
|
||||
escape_json() {
|
||||
echo "$1" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g'
|
||||
}
|
||||
|
||||
# Function to process AT commands
|
||||
process_commands() {
|
||||
local commands="$1"
|
||||
local json_response="["
|
||||
|
||||
for cmd in $commands; do
|
||||
echo "Processing command: $cmd" >> "$DEBUG_LOG"
|
||||
|
||||
# Write the command to the input file
|
||||
echo "$cmd" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout with full path to device
|
||||
if ! atinout "$INPUT_FILE" "/dev/$AT_PORT" "$OUTPUT_FILE" 2>> "$DEBUG_LOG"; then
|
||||
echo "Command failed: $cmd" >> "$DEBUG_LOG"
|
||||
OUTPUT="Error executing command"
|
||||
elif [ ! -f "$OUTPUT_FILE" ]; then
|
||||
echo "Output file not created for command: $cmd" >> "$DEBUG_LOG"
|
||||
OUTPUT="No output file"
|
||||
else
|
||||
OUTPUT=$(cat "$OUTPUT_FILE" 2>> "$DEBUG_LOG" || echo "Error reading output")
|
||||
echo "Command output: $OUTPUT" >> "$DEBUG_LOG"
|
||||
fi
|
||||
|
||||
# Escape special characters for JSON
|
||||
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
|
||||
|
||||
# Append the response
|
||||
json_response="${json_response}{\"response\":\"$ESCAPED_OUTPUT\"},"
|
||||
done
|
||||
|
||||
# Remove the trailing comma and close the JSON array
|
||||
if [ "${json_response: -1}" = "," ]; then
|
||||
json_response="${json_response%,}]"
|
||||
else
|
||||
json_response="${json_response}]"
|
||||
fi
|
||||
|
||||
echo "$json_response"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
define_command_sets
|
||||
|
||||
# Get command set from query string
|
||||
COMMAND_SET=$(echo "$QUERY_STRING" | grep -o 'set=[1-6]' | cut -d'=' -f2)
|
||||
|
||||
# Select the appropriate command set
|
||||
case "$COMMAND_SET" in
|
||||
1) COMMANDS="$COMMAND_SET_1";;
|
||||
2) COMMANDS="$COMMAND_SET_2";;
|
||||
3) COMMANDS="$COMMAND_SET_3";;
|
||||
4) COMMANDS="$COMMAND_SET_4";;
|
||||
5) COMMANDS="$COMMAND_SET_5";;
|
||||
6) COMMANDS="$COMMAND_SET_6";;
|
||||
*) COMMANDS="$COMMAND_SET_1";; # Default to set 1 if no valid set specified
|
||||
esac
|
||||
|
||||
# Process the selected commands and output the response
|
||||
JSON_RESPONSE=$(process_commands "$COMMANDS")
|
||||
echo "$JSON_RESPONSE" >> "$DEBUG_LOG"
|
||||
echo "$JSON_RESPONSE"
|
||||
|
||||
# Clean up temporary files
|
||||
rm -f "$INPUT_FILE" "$OUTPUT_FILE"
|
||||
|
||||
# Release the lock
|
||||
flock -u 200
|
||||
|
||||
echo "Script completed at $(date)" >> "$DEBUG_LOG"
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/bin/sh
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Create a temporary file to store the processed data
|
||||
temp_file=$(mktemp)
|
||||
|
||||
# Process ARP entries and store in temporary file
|
||||
arp -a | while IFS= read -r line; do
|
||||
if [ -n "$line" ]; then
|
||||
# Extract hostname (or IP if hostname is "?"), IP, and MAC
|
||||
hostname=$(echo "$line" | awk '{print $1}')
|
||||
ip=$(echo "$line" | awk -F '[()]' '{print $2}')
|
||||
mac=$(echo "$line" | awk '{print $4}')
|
||||
|
||||
# Skip entries without valid MAC addresses
|
||||
if [ "$mac" = "<incomplete>" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# If hostname is "?", use the IP address instead
|
||||
if [ "$hostname" = "?" ]; then
|
||||
hostname="$ip"
|
||||
fi
|
||||
|
||||
# Store each entry in the temp file
|
||||
echo "$hostname:$ip:$mac" >> "$temp_file"
|
||||
fi
|
||||
done
|
||||
|
||||
# Initialize JSON array
|
||||
echo -n "["
|
||||
|
||||
# Process the temporary file to create JSON
|
||||
first=true
|
||||
while IFS=: read -r hostname ip mac; do
|
||||
if [ "$first" = true ]; then
|
||||
first=false
|
||||
else
|
||||
echo -n ","
|
||||
fi
|
||||
echo -n "{\"hostname\":\"$hostname\",\"ip\":\"$ip\",\"mac\":\"$mac\"}"
|
||||
done < "$temp_file"
|
||||
|
||||
# Close the JSON array
|
||||
echo "]"
|
||||
|
||||
# Clean up
|
||||
rm -f "$temp_file"
|
||||
@@ -4,8 +4,8 @@
|
||||
echo "Content-Type: application/json"
|
||||
echo ""
|
||||
|
||||
# Ping 8.8.8.8 and capture the result
|
||||
if ping -c 1 8.8.8.8 > /dev/null 2>&1; then
|
||||
# Ping 8.8.8.8 with 5 packets and capture the result
|
||||
if ping -c 5 8.8.8.8 > /dev/null 2>&1; then
|
||||
# Ping was successful
|
||||
echo '{"connection": "ACTIVE"}'
|
||||
else
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Define the lock file
|
||||
LOCK_FILE="/tmp/home_data.lock"
|
||||
|
||||
# Acquire the lock (wait if needed)
|
||||
exec 200>$LOCK_FILE
|
||||
flock -x 200
|
||||
|
||||
# Temporary files for input/output and AT port
|
||||
INPUT_FILE="/tmp/input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/output_$$.txt"
|
||||
AT_PORT="/dev/smd11"
|
||||
|
||||
# Debug file path
|
||||
DEBUG_FILE="/tmp/debug-json-result.txt"
|
||||
|
||||
# Function to escape JSON strings (handling quotes and newlines)
|
||||
escape_json() {
|
||||
# Escape newlines and double quotes
|
||||
echo "$1" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g'
|
||||
}
|
||||
|
||||
# Initialize JSON response array
|
||||
JSON_RESPONSE="["
|
||||
|
||||
# List of AT commands to run, one by one
|
||||
for COMMAND in "AT+QUIMSLOT?" "AT+CNUM" "AT+COPS?" "AT+CIMI" "AT+ICCID" "AT+CGSN" "AT+CPIN?" "AT+CGDCONT?" "AT+CREG?" "AT+CFUN?" "AT+QENG=\"servingcell\"" "AT+QTEMP" "AT+CGCONTRDP" "AT+QCAINFO" "AT+QRSRP" 'AT+QMAP="WWAN"'; do
|
||||
# Write the command to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout
|
||||
atinout "$INPUT_FILE" "$AT_PORT" "$OUTPUT_FILE"
|
||||
|
||||
# Read the output from the output file
|
||||
OUTPUT=$(cat "$OUTPUT_FILE")
|
||||
|
||||
# Escape special characters for JSON (escape only output)
|
||||
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
|
||||
|
||||
# Append the response as an object to the JSON response array
|
||||
JSON_RESPONSE="${JSON_RESPONSE}{\"response\":\"$ESCAPED_OUTPUT\"},"
|
||||
done
|
||||
|
||||
# Remove the trailing comma and close the JSON array
|
||||
if [ "${JSON_RESPONSE: -1}" = "," ]; then
|
||||
JSON_RESPONSE="${JSON_RESPONSE%,}]"
|
||||
else
|
||||
JSON_RESPONSE="${JSON_RESPONSE}]"
|
||||
fi
|
||||
|
||||
# Write the JSON response to the debug file for troubleshooting
|
||||
echo "$JSON_RESPONSE" > "$DEBUG_FILE"
|
||||
|
||||
# Return the output as a valid JSON response
|
||||
echo "$JSON_RESPONSE"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$INPUT_FILE" "$OUTPUT_FILE"
|
||||
|
||||
# Release the lock
|
||||
flock -u 200
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Get RX and TX bytes from ifconfig eth0
|
||||
data=$(ifconfig eth0 | grep "RX bytes")
|
||||
|
||||
# Extract download (RX) and upload (TX) values using awk
|
||||
download=$(echo $data | awk '{print $2}' | cut -d':' -f2)
|
||||
upload=$(echo $data | awk '{print $6}' | cut -d':' -f2)
|
||||
|
||||
# Return JSON response
|
||||
echo "{"
|
||||
echo " \"download\": \"$download\","
|
||||
echo " \"upload\": \"$upload\""
|
||||
echo "}"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user