├── favicon.ico ├── modules ├── pdf.png ├── sim.png ├── manuals │ └── SIM70x0_AT_107.pdf ├── at.json ├── at │ ├── at_x.js │ ├── at.js │ ├── ate1.js │ ├── at_shchead.js │ ├── at_shconn.js │ ├── at_shdisc.js │ ├── at_shcpara.js │ ├── ati.js │ ├── ate0.js │ ├── at_goi.js │ ├── at_gmm.js │ ├── at_gmi.js │ ├── at_cgmi.js │ ├── at_cgmm.js │ ├── at_gsn.js │ ├── at_ccoapterm.js │ ├── at_cfsinit.js │ ├── at_creboot.js │ ├── at_cgsn.js │ ├── at_gmr.js │ ├── at_cgmr.js │ ├── at_ccoapinit.js │ ├── at_cfsterm.js │ ├── at_cimi.js │ ├── at_ccid.js │ ├── at_ccoapurl.js │ ├── at_caclose.js │ ├── at_cgpaddr.js │ ├── at_shahead.js │ ├── at_shpara.js │ ├── at_shstate.js │ ├── at_cfsdfile.js │ ├── at_cmee.js │ ├── at_castate.js │ ├── at_cfsgfrs.js │ ├── at_cmgs.js │ ├── at_cgnspwr.js │ ├── at_cbandcfg.js │ ├── at_cmnb.js │ ├── at_cnmp.js │ ├── at_cmgd.js │ ├── at_shread.js │ ├── at_shssl.js │ ├── at_cgatt.js │ ├── at_cmgf.js │ ├── at_cfswfile.js │ ├── at_cpas.js │ ├── at_cgnapn.js │ ├── at_shreq.js │ ├── at_cbc.js │ ├── at_shconf.js │ ├── at_cclk.js │ ├── at_cgdcont.js │ ├── at_cgreg.js │ ├── at_clts.js │ ├── at_csq.js │ ├── at_cops.js │ ├── at_cncfg.js │ ├── at_creg.js │ ├── at_clck.js │ ├── at_cnact.js │ ├── at_cmgl.js │ ├── at_ccoappara.js │ ├── at_cgnsinf.js │ ├── at_cpin.js │ ├── at_csslcfg.js │ ├── at_cpsi.js │ ├── at_caserver.js │ ├── at_caopen.js │ ├── at_ccoapaction.js │ ├── at_curccfg.js │ └── at_ccoaphead.js └── sim7080 │ ├── info.json │ └── at.json ├── css ├── windows.css ├── tabs.css ├── page.css └── chat.css ├── index.html ├── js ├── tabCommands.js ├── pdf.js ├── tabs.js ├── tabGnss.js ├── settings.js ├── tabSim.js ├── tabModule.js ├── tabManual.js ├── tabSms.js ├── info.js ├── tabCoap.js ├── chat.js ├── atscripts.js ├── tabTcpUdp.js └── tabHttps.js └── README.md /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adrianotiger/simcomtester/main/favicon.ico -------------------------------------------------------------------------------- /modules/pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adrianotiger/simcomtester/main/modules/pdf.png -------------------------------------------------------------------------------- /modules/sim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adrianotiger/simcomtester/main/modules/sim.png -------------------------------------------------------------------------------- /modules/manuals/SIM70x0_AT_107.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Adrianotiger/simcomtester/main/modules/manuals/SIM70x0_AT_107.pdf -------------------------------------------------------------------------------- /modules/at.json: -------------------------------------------------------------------------------- 1 | [ 2 | "at", 3 | "ati", 4 | "ate0", 5 | "ate1", 6 | "at+gmi", 7 | "at+gmm", 8 | "at+goi", 9 | "at+gmr" 10 | ] 11 | -------------------------------------------------------------------------------- /modules/at/at_x.js: -------------------------------------------------------------------------------- 1 | let AT_X = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | super({ 6 | description: "Unknown Command", 7 | example: "-", 8 | cmd: "AT_X", 9 | doc: "" 10 | }); 11 | } 12 | }; -------------------------------------------------------------------------------- /modules/at/at.js: -------------------------------------------------------------------------------- 1 | let AT = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | super({ 6 | exe: true, 7 | description: "Echo Test Command", 8 | example: "+AT", 9 | cmd: "AT", 10 | doc: "2.2.1" 11 | }); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/at/ate1.js: -------------------------------------------------------------------------------- 1 | let ATE1 = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "Set echo on", 9 | cmd: "ATE1", 10 | doc: "2.2.3" 11 | }); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/at/at_shchead.js: -------------------------------------------------------------------------------- 1 | let AT_SHCHEAD = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "HTTP(S) Clear Head", 9 | cmd: "AT+SHCHEAD", 10 | doc: "13.2.9" 11 | }); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/at/at_shconn.js: -------------------------------------------------------------------------------- 1 | let AT_SHCONN = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "HTTP(S) Connection", 9 | cmd: "AT+SHCONN", 10 | doc: "13.2.3" 11 | }); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/at/at_shdisc.js: -------------------------------------------------------------------------------- 1 | let AT_SHDISC = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "Disconnect HTTP(S)", 9 | cmd: "AT+SHDISC", 10 | doc: "13.2.12" 11 | }); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/at/at_shcpara.js: -------------------------------------------------------------------------------- 1 | let AT_SHCPARA = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "HTTP(S) Clear Parameters", 9 | cmd: "AT+SHCPARA", 10 | doc: "13.2.7" 11 | }); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/sim7080/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "7080", 3 | "path" : "sim7080", 4 | "manual" : "SIM70x0_AT_107.pdf", 5 | "firmware" : 6 | { 7 | "base" : "1951B05SIM7080", 8 | "version": "1951B([0-9]{2})SIM70[7-9]0", 9 | "last" : "17" 10 | }, 11 | "simcom" : 12 | { 13 | "link" : "https://www.simcom.com/product/SIM7080G.html" 14 | } 15 | } -------------------------------------------------------------------------------- /modules/at/ati.js: -------------------------------------------------------------------------------- 1 | let ATI = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "Display Product Identification Information", 9 | example: "R1951.01", 10 | cmd: "ATI", 11 | doc: "2.2.5" 12 | }); 13 | } 14 | }; -------------------------------------------------------------------------------- /modules/at/ate0.js: -------------------------------------------------------------------------------- 1 | let ATE0 = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "Set echo off", 9 | cmd: "ATE0", 10 | doc: "2.2.3" 11 | });//false, false, true, false, "Set Echo Off", "", "ATE0", 1000); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/at/at_goi.js: -------------------------------------------------------------------------------- 1 | let AT_GOI = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Global Object Identification", 10 | example: "SIM7080", 11 | cmd: "AT+GOI", 12 | doc: "2.2.28" 13 | }); 14 | } 15 | }; -------------------------------------------------------------------------------- /modules/at/at_gmm.js: -------------------------------------------------------------------------------- 1 | let AT_GMM = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Request Model Identification", 10 | example: "SIMCOM_SIM7080G", 11 | cmd: "AT+GMM", 12 | doc: "2.2.26" 13 | }); 14 | } 15 | }; -------------------------------------------------------------------------------- /modules/at/at_gmi.js: -------------------------------------------------------------------------------- 1 | let AT_GMI = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Request Manufacturer Identification", 10 | example: "SIMCOM_Ltd", 11 | cmd: "AT+GMI", 12 | doc: "2.2.25" 13 | }); 14 | } 15 | }; -------------------------------------------------------------------------------- /modules/at/at_cgmi.js: -------------------------------------------------------------------------------- 1 | let AT_CGMI = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Request Manufacturer Identification (GMI)", 10 | example: "SIMCOM_Ltd", 11 | cmd: "AT+CGMI", 12 | doc: "3.2.1" 13 | }); 14 | } 15 | }; -------------------------------------------------------------------------------- /modules/at/at_cgmm.js: -------------------------------------------------------------------------------- 1 | let AT_CGMM = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Request Model Identification (GMM)", 10 | example: "SIMCOM_SIM7080G", 11 | cmd: "AT+CGMM", 12 | doc: "3.2.2" 13 | }); 14 | } 15 | }; -------------------------------------------------------------------------------- /modules/at/at_gsn.js: -------------------------------------------------------------------------------- 1 | let AT_GSN = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Request Product Serial Number Identification", 10 | example: "869951030006302", 11 | cmd: "AT+GSN", 12 | doc: "2.2.29" 13 | }); 14 | } 15 | }; -------------------------------------------------------------------------------- /modules/at/at_ccoapterm.js: -------------------------------------------------------------------------------- 1 | let AT_CCOAPTERM = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "Delete CoAP Object", 9 | cmd: "AT+CCOAPTERM", 10 | doc: "18.2.9" 11 | });//false, false, true, false, "Delete CoAP Object", "", "AT+CCOAPTERM", 1000); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/at/at_cfsinit.js: -------------------------------------------------------------------------------- 1 | let AT_CFSINIT = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "Get Flash Data Buffer", 9 | cmd: "AT+CFSINIT", 10 | doc: "9.2.1" 11 | }); //false, false, true, false, "Get Flash Data Buffer", "", "AT+CFSINIT", 1000); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/at/at_creboot.js: -------------------------------------------------------------------------------- 1 | let AT_CREBOOT = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Reboot Module", 10 | cmd: "AT+CREBOOT", 11 | doc: "5.2.46" 12 | }); //false, false, true, true, "Reboot Module", "", "AT+CREBOOT", 1000); 13 | } 14 | }; -------------------------------------------------------------------------------- /modules/at/at_cgsn.js: -------------------------------------------------------------------------------- 1 | let AT_CGSN = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Request Product Serial Number Identification (GSN)", 10 | example: "869951030006302", 11 | cmd: "AT+CGSN", 12 | doc: "3.2.4" 13 | }); 14 | } 15 | 16 | }; -------------------------------------------------------------------------------- /modules/at/at_gmr.js: -------------------------------------------------------------------------------- 1 | let AT_GMR = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Request TA Revision Identification of Software Release", 10 | example: "Revision:1351B05SIM7080G", 11 | cmd: "AT+GMR", 12 | doc: "2.2.27" 13 | }); 14 | } 15 | }; -------------------------------------------------------------------------------- /modules/at/at_cgmr.js: -------------------------------------------------------------------------------- 1 | let AT_CGMR = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Request TA Revision Identification of Software Release (GMR)", 10 | example: "Revision:1351B05SIM7080G", 11 | cmd: "AT+CGMR", 12 | doc: "3.2.3" 13 | }); 14 | } 15 | }; -------------------------------------------------------------------------------- /modules/at/at_ccoapinit.js: -------------------------------------------------------------------------------- 1 | let AT_CCOAPINIT = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Create CoAP Object", 10 | cmd: "AT+CCOAPINIT", 11 | doc: "18.2.2" 12 | }); //false, false, true, true, "Create CoAP Object", "", "AT+CCOAPINIT", 1000); 13 | } 14 | }; -------------------------------------------------------------------------------- /modules/at/at_cfsterm.js: -------------------------------------------------------------------------------- 1 | let AT_CFSTERM = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | description: "Free the Flash Buffer Allocated by CFSINIT", 9 | cmd: "AT+CFSTERM", 10 | doc: "9.2.8" 11 | }); //false, false, true, false, "Free the Flash Buffer Allocated by CFSINIT", "", "AT+CFSTERM", 1000); 12 | } 13 | }; -------------------------------------------------------------------------------- /modules/at/at_cimi.js: -------------------------------------------------------------------------------- 1 | let AT_CIMI = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Request International Mobile Subscriber Identity", 10 | example: "460113007570785", 11 | cmd: "AT+CIMI", 12 | doc: "3.2.6" 13 | });//false, false, true, true, "Request International Mobile Subscriber Identity", "460113007570785", "AT+CIMI", 1000); 14 | } 15 | }; -------------------------------------------------------------------------------- /modules/at/at_ccid.js: -------------------------------------------------------------------------------- 1 | let AT_CCID = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Integrated Circuit Card Identifier", 10 | example: "89861118231006965031", 11 | cmd: "AT+CCID", 12 | timeout: 2000, 13 | doc: "5.2.8" 14 | });//false, false, true, true, "Integrated Circuit Card Identifier", "89861118231006965031", "AT+CCID", 2000); 15 | } 16 | 17 | }; -------------------------------------------------------------------------------- /modules/at/at_ccoapurl.js: -------------------------------------------------------------------------------- 1 | let AT_CCOAPURL = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | write: true, 8 | test: true, 9 | description: "Configure CoAP URL", 10 | cmd: "AT+CCOAPURL", 11 | doc: "18.2.4" 12 | }); //false, true, false, true, "Configure CoAP URL", "", "AT+CCOAPURL", 1000); 13 | 14 | this.AddParam("url", "string", "scheme://host:port/uri"); 15 | 16 | this.AddWriteSendParam({url:null}); 17 | } 18 | }; -------------------------------------------------------------------------------- /modules/at/at_caclose.js: -------------------------------------------------------------------------------- 1 | let AT_CACLOSE = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | test: true, 8 | write: true, 9 | description: "Close TCP/UDP Connection", 10 | example: "AT+CACLOSE=1", 11 | cmd: "AT+CACLOSE", 12 | doc: "12.2.9" 13 | }); 14 | 15 | let enumId = []; 16 | for(var j=0;j<=12;j++) 17 | enumId.push(new ATEnum(j, "CID #" + j)); 18 | 19 | this.AddParam("cid", enumId, "Command identifier"); 20 | 21 | this.AddWriteSendParam({cid:null}); 22 | } 23 | 24 | }; -------------------------------------------------------------------------------- /modules/at/at_cgpaddr.js: -------------------------------------------------------------------------------- 1 | let AT_CGPADDR = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | write:true, 10 | description: "Show PDP Address", 11 | example: "+GPADDR: 1,128.191.1.2", 12 | cmd: "AT+CGPADDR", 13 | doc: "6.2.4" 14 | }); 15 | 16 | this.AddParam("cid", "number", "PDP context"); 17 | this.AddParam("PDP_addr", "string", "PDP IP Address"); 18 | 19 | this.AddWriteSendParam({cid:null}); 20 | this.AddExeAnswerParam({cid:null, PDP_addr:null}); 21 | } 22 | }; -------------------------------------------------------------------------------- /modules/at/at_shahead.js: -------------------------------------------------------------------------------- 1 | let AT_SHAHEAD = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Add Head", 11 | example: "+SHAHEAD: 0,0", 12 | cmd: "AT+SHAHEAD", 13 | doc: "13.2.5" 14 | }); 15 | 16 | this.AddParam("type", "string", "type"); 17 | this.AddParam("value", "string", "value"); 18 | 19 | this.AddReadAnswerParam({type:null, value:null}); 20 | 21 | this.AddWriteSendParam({type:null, value:null}); 22 | 23 | } 24 | }; -------------------------------------------------------------------------------- /modules/at/at_shpara.js: -------------------------------------------------------------------------------- 1 | let AT_SHPARA = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Set HTTP(S) Parameter", 11 | example: "+SHPARA: 64,64", 12 | cmd: "AT+SHPARA", 13 | doc: "13.2.6" 14 | }); 15 | 16 | this.AddParam("key", "string", "key"); 17 | this.AddParam("value", "string", "value"); 18 | 19 | this.AddReadAnswerParam({key:null, value:null}); 20 | 21 | this.AddWriteSendParam({key:null, value:null}); 22 | 23 | } 24 | }; -------------------------------------------------------------------------------- /modules/at/at_shstate.js: -------------------------------------------------------------------------------- 1 | let AT_SHSTATE = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | description: "Query HTTP(S) Connection Status", 9 | example: "+SHSTATE: 0", 10 | cmd: "AT+SHSTATE", 11 | doc: "13.2.8" 12 | }); 13 | 14 | let enumS = []; 15 | enumS.push(new ATEnum(0, "Expression HTTP(S) disconnect state")); 16 | enumS.push(new ATEnum(1, "Expression HTTP(S) connect state")); 17 | 18 | this.AddParam("status", enumS, "status"); 19 | 20 | this.AddReadAnswerParam({status:null}); 21 | } 22 | 23 | IsConnected() 24 | { 25 | const value = this.GetValue(); 26 | 27 | return (parseInt(value.status) == 1); 28 | } 29 | }; -------------------------------------------------------------------------------- /modules/at/at_cfsdfile.js: -------------------------------------------------------------------------------- 1 | let AT_CFSDFILE = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | write: true, 8 | description: "Delete the File from the Flash", 9 | cmd: "AT+CFSDFILE", 10 | doc: "9.2.4" 11 | }); //false, true, false, false, "Delete the File from the Flash", "", "AT+CFSDFILE", 1000); 12 | 13 | let enumI = []; 14 | enumI.push(new ATEnum(0, "/custapp/")); 15 | enumI.push(new ATEnum(1, "/fota/")); 16 | enumI.push(new ATEnum(2, "/datatx/")); 17 | enumI.push(new ATEnum(3, "/customer/")); 18 | 19 | this.AddParam("index", enumI, "directory index"); 20 | this.AddParam("filename", "string", "file name"); 21 | 22 | this.AddWriteSendParam({index:null, filename:null}); 23 | } 24 | }; -------------------------------------------------------------------------------- /modules/at/at_cmee.js: -------------------------------------------------------------------------------- 1 | let AT_CMEE = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Report Mobile Equipment Error", 11 | example: "+CMEE: 0", 12 | cmd: "AT+CMEE", 13 | doc: "3.2.8" 14 | }); //true, true, false, true, "Report Mobile Equipment Error", "+CMEE: 0", "AT+CMEE", 1000); 15 | 16 | let enumC = []; 17 | enumC.push(new ATEnum(0, "Disable")); 18 | enumC.push(new ATEnum(1, "Enable with numeric error code")); 19 | enumC.push(new ATEnum(2, "Enable with verbose error message")); 20 | this.AddParam("n", enumC, "error message"); 21 | 22 | this.AddReadAnswerParam({n:null}); 23 | this.AddWriteSendParam({n:null}); 24 | } 25 | }; -------------------------------------------------------------------------------- /modules/at/at_castate.js: -------------------------------------------------------------------------------- 1 | let AT_CASTATE = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | description: "Query TCP/UDP State", 9 | example: "AT+CASTATE?", 10 | cmd: "AT+CASTATE", 11 | doc: "12.2.8" 12 | }); 13 | 14 | let enumS = []; 15 | enumS.push(new ATEnum(0, "Closed")); 16 | enumS.push(new ATEnum(1, "Connected")); 17 | enumS.push(new ATEnum(1, "Listening")); 18 | 19 | 20 | let enumId = []; 21 | for(var j=0;j<=12;j++) 22 | enumId.push(new ATEnum(j, "CID #" + j)); 23 | 24 | this.AddParam("cid", enumId, "Command identifier"); 25 | this.AddParam("state", enumS, "ConnectionState");; 26 | 27 | this.AddReadAnswerParam({cid:null, state:null}); 28 | } 29 | 30 | }; -------------------------------------------------------------------------------- /modules/at/at_cfsgfrs.js: -------------------------------------------------------------------------------- 1 | let AT_CFSGFRS = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | description: "Get the Size of File System", 9 | cmd: "AT+CFSGFRS", 10 | doc: "9.2.7" 11 | }); 12 | 13 | this.AddParam("n", "number", "bytes"); 14 | 15 | this.AddReadAnswerParam({n:null}); 16 | } 17 | 18 | ShowChat(div) 19 | { 20 | super.ShowChat(div); 21 | 22 | const value = this.GetValue(); 23 | 24 | //if(this.GetRequestType() == "exe") 25 | { 26 | let freespace = value.n + " bytes"; 27 | if(value.n > 1024 * 1024 * 2) freespace = (parseInt(value.n / 1024 / 10.24) / 100) + " MB"; 28 | else if(value.n > 1024 * 5) freespace = parseInt(value.n / 1024) + " kB"; 29 | _CN("span", {}, ["free space: " + freespace], div); 30 | } 31 | } 32 | }; -------------------------------------------------------------------------------- /modules/at/at_cmgs.js: -------------------------------------------------------------------------------- 1 | let AT_CMGS = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | write: true, 8 | test: true, 9 | description: "Send SMS Messages", 10 | example: "+CMGS: 213", 11 | cmd: "AT+CMGS", 12 | timeout: 60000, 13 | doc: "4.2.5" 14 | });// true, true, false, true, "Enter/Read PIN", "+CPIN: READY", "AT+CPIN", 5000); 15 | 16 | this.AddParam("da", "string", "destination address"); 17 | this.AddParam("toda", "number", "toda"); 18 | 19 | this.AddParam("mr", "number", "message reference"); 20 | 21 | this.AddWriteSendParam({da:null}); 22 | this.AddWriteSendParam({da:null, toda:null}); 23 | 24 | this.AddWriteAnswerParam({mr:null}); 25 | } 26 | 27 | HoldUp(str) 28 | { 29 | if(str.trim().length < 2) return true; 30 | return false; 31 | } 32 | }; -------------------------------------------------------------------------------- /modules/at/at_cgnspwr.js: -------------------------------------------------------------------------------- 1 | let AT_CGNSPWR = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "GNSS Power Control", 11 | example: "+CGNSPWR: 0", 12 | cmd: "AT+CGNSPWR", 13 | doc: "8.2.1" 14 | }); 15 | 16 | let enumM = []; 17 | enumM.push(new ATEnum(0, "Turn off GNSS power supply")); 18 | enumM.push(new ATEnum(1, "Turn on GNSS power supply")); 19 | 20 | this.AddParam("mode", enumM, "mode"); 21 | 22 | this.AddWriteSendParam({mode:null}); 23 | 24 | this.AddReadAnswerParam({mode:null}); 25 | } 26 | 27 | ShowChat(div) 28 | { 29 | super.ShowChat(div); 30 | 31 | if(this.GetRequestType() == "read") 32 | { 33 | _CN("span", {}, [this.IsPowered() ? "ON" : "OFF"], div); 34 | } 35 | } 36 | 37 | IsPowered() 38 | { 39 | const value = this.GetValue(); 40 | return (parseInt(value.mode) == 1); 41 | } 42 | 43 | }; -------------------------------------------------------------------------------- /modules/at/at_cbandcfg.js: -------------------------------------------------------------------------------- 1 | let AT_CBANDCFG = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Configure CAT-M or NB-IOT Band", 11 | example: "+CBANDCFG: \"NB-IOT\",8,20", 12 | cmd: "AT+CBANDCFG", 13 | doc: "5.2.26" 14 | }); 15 | 16 | let enumMode = []; 17 | enumMode.push(new ATEnum("CAT-M", "CAT-M")); 18 | enumMode.push(new ATEnum("NB-IOT", "NB-IoT")); 19 | this.AddParam("mode", enumMode, "mode"); 20 | 21 | this.AddParam("band", "integer", "band"); 22 | for(var j=1;j<20;j++) this.AddParam("band" + j, "integer", "band"); 23 | 24 | let o = {mode:null, band:null}; 25 | let o0 = {...o}; 26 | this.AddReadAnswerParam(o0); 27 | this.AddWriteSendParam(o0); 28 | for(var j=1;j<20;j++) { 29 | o["band" + j] = null; 30 | let ox = {...o}; 31 | this.AddReadAnswerParam(ox); 32 | this.AddWriteSendParam(ox); 33 | } 34 | } 35 | }; -------------------------------------------------------------------------------- /modules/at/at_cmnb.js: -------------------------------------------------------------------------------- 1 | let AT_CMNB = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Preferred Selection between CAT-M and NB-IoT", 11 | example: "+CMNB: 2", 12 | cmd: "AT+CMNB", 13 | doc: "5.2.17" 14 | }); //true, true, false, true, "Preferred Selection between CAT-M and NB-IoT", "+CMNB: 2", "AT+CMNB", 1000); 15 | 16 | let enumMode = []; 17 | enumMode.push(new ATEnum(1, "CAT-M")); 18 | enumMode.push(new ATEnum(2, "NB-IoT")); 19 | enumMode.push(new ATEnum(3, "CAT-M and NB-IoT")); 20 | this.AddParam("mode", enumMode, "mode"); 21 | 22 | this.AddReadAnswerParam({mode:null}); 23 | 24 | this.AddWriteSendParam({mode:null}); 25 | } 26 | 27 | ShowChat(div) 28 | { 29 | super.ShowChat(div); 30 | 31 | const value = this.GetValue(); 32 | 33 | if(this.GetRequestType() == "read") 34 | { 35 | _CN("span", {}, [this.GetParam("mode").GetValue(value.mode)?.GetDescription()], div); 36 | } 37 | } 38 | }; -------------------------------------------------------------------------------- /modules/sim7080/at.json: -------------------------------------------------------------------------------- 1 | [ 2 | "at+clts", 3 | "at+castate", 4 | "at+caclose", 5 | "at+x", 6 | 7 | "at+caopen", 8 | "at+caserver", 9 | "at+cbandcfg", 10 | "at+cbc", 11 | "at+ccid", 12 | "at+cclk", 13 | "at+ccoapaction", 14 | "at+ccoaphead", 15 | "at+ccoapinit", 16 | "at+ccoappara", 17 | "at+ccoapterm", 18 | "at+ccoapurl", 19 | "at+cfsdfile", 20 | "at+cfsgfrs", 21 | "at+cfsinit", 22 | "at+cfsterm", 23 | "at+cfswfile", 24 | "at+cgatt", 25 | "at+cgdcont", 26 | "at+cgmi", 27 | "at+cgmm", 28 | "at+cgmr", 29 | "at+cgnapn", 30 | "at+cgnsinf", 31 | "at+cgnspwr", 32 | "at+cgpaddr", 33 | "at+cgreg", 34 | "at+cgsn", 35 | "at+cimi", 36 | "at+clck", 37 | "at+cmee", 38 | "at+cmgd", 39 | "at+cmgf", 40 | "at+cmgl", 41 | "at+cmgs", 42 | "at+cmnb", 43 | "at+cnact", 44 | "at+cncfg", 45 | "at+cnmp", 46 | "at+cops", 47 | "at+cpas", 48 | "at+cpin", 49 | "at+cpsi", 50 | "at+creboot", 51 | "at+creg", 52 | "at+csq", 53 | "at+csslcfg", 54 | "at+curccfg", 55 | "at+gsn", 56 | "at+shahead", 57 | "at+shchead", 58 | "at+shconf", 59 | "at+shconn", 60 | "at+shcpara", 61 | "at+shdisc", 62 | "at+shpara", 63 | "at+shread", 64 | "at+shreq", 65 | "at+shssl", 66 | "at+shstate" 67 | ] 68 | -------------------------------------------------------------------------------- /modules/at/at_cnmp.js: -------------------------------------------------------------------------------- 1 | let AT_CNMP = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Preferred Mode Selection", 11 | example: "+CNMP: 38", 12 | cmd: "AT+CNMP", 13 | doc: "5.2.16" 14 | }); //true, true, false, true, "Preferred Mode Selection", "+CNMP: 38", "AT+CNMP", 1000); 15 | 16 | let enumMode = []; 17 | enumMode.push(new ATEnum(2, "Automatic")); 18 | enumMode.push(new ATEnum(13, "GSM only")); 19 | enumMode.push(new ATEnum(38, "LTE only")); 20 | enumMode.push(new ATEnum(51, "GSM and LTE only")); 21 | this.AddParam("mode", enumMode, "mode"); 22 | 23 | //+CNMP: ((2-Automatic),(13-GSM Only),(38-LTE Only),(51-GSM And LTE Only)) 24 | 25 | this.AddReadAnswerParam({mode:null}); 26 | 27 | this.AddWriteSendParam({mode:null}); 28 | } 29 | 30 | ShowChat(div) 31 | { 32 | super.ShowChat(div); 33 | 34 | const value = this.GetValue(); 35 | 36 | if(this.GetRequestType() == "read") 37 | { 38 | _CN("span", {}, [this.GetParam("mode").GetValue(value.mode)?.GetDescription()], div); 39 | } 40 | } 41 | }; -------------------------------------------------------------------------------- /modules/at/at_cmgd.js: -------------------------------------------------------------------------------- 1 | let AT_CMGD = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | write: true, 8 | test: true, 9 | description: "Delete SMS Message", 10 | example: "+CMGD: (0,1,2),(0-4)", 11 | cmd: "AT+CMGD", 12 | timeout: 25000, 13 | doc: "4.2.1" 14 | });// true, true, false, true, "Enter/Read PIN", "+CPIN: READY", "AT+CPIN", 5000); 15 | 16 | let enumD = []; 17 | enumD.push(new ATEnum(0, "Delete message specified in index")); 18 | enumD.push(new ATEnum(1, "Delete all read messages from preferred messages")); 19 | enumD.push(new ATEnum(2, "Delete all read messages from preferred message storage and sent mobile originated messages")); 20 | enumD.push(new ATEnum(3, "Delete all read messages from preferred message storage, sent and unsent mobile originated message")); 21 | enumD.push(new ATEnum(4, "Delete all messages from preferred message storage")); 22 | 23 | this.AddParam("index", "number", "index"); 24 | this.AddParam("delflag", enumD, "delflag"); 25 | 26 | this.AddWriteSendParam({index:null}); 27 | this.AddWriteSendParam({index:null, delflag:null}); 28 | } 29 | 30 | 31 | }; -------------------------------------------------------------------------------- /modules/at/at_shread.js: -------------------------------------------------------------------------------- 1 | let AT_SHREAD = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | write: true, 8 | test: true, 9 | description: "Read Response Value", 10 | example: "+SHREAD: (0-307200),(1-307200)", 11 | cmd: "AT+SHREAD", 12 | doc: "13.2.11" 13 | }); 14 | 15 | this.AddParam("startaddress", "number", "start address"); 16 | this.AddParam("datalen", "number", "data length"); 17 | 18 | 19 | this.AddWriteSendParam({startaddress:null, datalen:null}); 20 | 21 | this.AddWriteAnswerParam({datalen:null}); 22 | } 23 | 24 | HoldUp(str) 25 | { 26 | if(str.indexOf("ERROR") >= 0 && str.indexOf("ERROR") < 10) return false; 27 | 28 | if(str.indexOf("OK") < 0) return true; 29 | if(str.indexOf("+SHREAD:") < 0) return true; 30 | 31 | const pos0 = str.indexOf("+SHREAD:") + 1; 32 | let pos1 = pos0; 33 | for(var j=pos0;j{ 35 | const p = this.GetParam(k); 36 | if(p.GetValue(value[k]) != null) 37 | { 38 | _CN("span", {}, [p.GetValue(value[k])?.GetDescription()], div); 39 | } 40 | else 41 | { 42 | _CN("span", {}, [k + ": " + value[k]], div); 43 | } 44 | }); 45 | } 46 | } 47 | 48 | GetApn() 49 | { 50 | const value = this.GetValue(); 51 | return value.apn.replace(/\"/g,''); 52 | } 53 | 54 | }; -------------------------------------------------------------------------------- /modules/at/at_shreq.js: -------------------------------------------------------------------------------- 1 | let AT_SHREQ = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Set Request Type", 11 | example: "+SHREQ: ,0", 12 | cmd: "AT+SHREQ", 13 | doc: "13.2.10" 14 | }); 15 | 16 | let enumT = []; 17 | enumT.push(new ATEnum(1, "GET")); 18 | enumT.push(new ATEnum(2, "PUT")); 19 | enumT.push(new ATEnum(3, "POST")); 20 | enumT.push(new ATEnum(4, "PATCH")); 21 | enumT.push(new ATEnum(5, "HEAD")); 22 | 23 | this.AddParam("type", enumT, "type"); 24 | this.AddParam("url", "string", "url"); 25 | this.AddParam("value", "string", "value"); 26 | this.AddParam("typestring", "string", "type"); 27 | this.AddParam("statuscode", "number", "status code"); 28 | this.AddParam("datalen", "number", "data length"); 29 | 30 | this.AddReadAnswerParam({url:null, type:null}); 31 | 32 | this.AddWriteSendParam({url:null, type:null}); 33 | 34 | this.AddWriteAnswerParam({typestring:null, statuscode:null, datalen:null}); 35 | 36 | } 37 | 38 | HoldUp(str) 39 | { 40 | if(str.indexOf("+SHREQ:") < 0) return true; 41 | return false; 42 | } 43 | 44 | GetStatusCode() 45 | { 46 | const value = this.GetValue(); 47 | return parseInt(value.statuscode); 48 | } 49 | 50 | GetDataLength() 51 | { 52 | const value = this.GetValue(); 53 | return parseInt(value.datalen); 54 | } 55 | }; -------------------------------------------------------------------------------- /css/windows.css: -------------------------------------------------------------------------------- 1 | .window 2 | { 3 | position: absolute; 4 | left: 50%; 5 | top: 50%; 6 | transform: translate(-50%, -50%); 7 | border-style: ridge; 8 | border-width: 2px; 9 | border-radius: 1vh; 10 | box-shadow: 0.2vh 0.2vh 1vh #005; 11 | font-family: sans-serif; 12 | } 13 | 14 | .loading 15 | { 16 | background: linear-gradient(to bottom, #fff, #ffa); 17 | font-size: 3vh; 18 | line-height: 3vh; 19 | min-height: 3vh; 20 | text-align: center; 21 | padding: 5vh; 22 | color: #005; 23 | z-index: 1000; 24 | } 25 | 26 | .singlecmd 27 | { 28 | display: inline-block; 29 | width: 12vw; 30 | height: 3vh; 31 | margin: 0.5vw; 32 | line-height: 3vh; 33 | border-bottom-style: dotted; 34 | border-bottom-width: 1px; 35 | border-bottom-color: #666; 36 | text-align: left; 37 | white-space: nowrap; 38 | } 39 | .singlecmd span 40 | { 41 | display: inline-block; 42 | max-width: 9vw; 43 | text-overflow: ellipsis; 44 | overflow: hidden; 45 | } 46 | 47 | 48 | .singlecmd button 49 | { 50 | height: 3vh; 51 | float: right; 52 | } 53 | 54 | .settingsgroup 55 | { 56 | margin: 1vh; 57 | width: 90%; 58 | background: #fff; 59 | border-radius: 1vh; 60 | box-shadow: 0vh 0vh 1vh #666; 61 | text-align: left; 62 | padding: min(1vh, 1vw); 63 | } 64 | 65 | .settingsgroup label 66 | { 67 | min-width: 20vw; 68 | padding-right: 1vw; 69 | } 70 | 71 | .settingsgroup input 72 | { 73 | min-width: 50%; 74 | } 75 | 76 | .tab table 77 | { 78 | width: 90%; 79 | box-shadow: 0px 0px 0.5vh 1px #005; 80 | margin:0 auto; 81 | text-align: center; 82 | } 83 | 84 | .tab tr:hover 85 | { 86 | background: #ffa; 87 | cursor: pointer; 88 | } 89 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SIM COM Tester - v0.6 (beta) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Loading...
32 | 33 | 34 | -------------------------------------------------------------------------------- /css/tabs.css: -------------------------------------------------------------------------------- 1 | .tab 2 | { 3 | position: absolute; 4 | height: 77vh; 5 | width: 41.8vw; 6 | margin: 0 auto; 7 | text-align: center; 8 | top: unset; 9 | bottom: 0.1vh; 10 | z-index: 1000; 11 | left: 0.1vw; 12 | overflow-x: hidden; 13 | overflow-y: auto; 14 | padding-bottom: 1vh; 15 | } 16 | 17 | .tabs 18 | { 19 | position: absolute; 20 | height: 85vh; 21 | width: 42vw; 22 | top: unset; 23 | bottom: 1vh; 24 | left: 1vh; 25 | } 26 | 27 | .tabs p 28 | { 29 | margin-bottom: 0.2vh; 30 | } 31 | 32 | .tabselect 33 | { 34 | position: absolute; 35 | height: 7vh; 36 | width: 9.5vw; 37 | top: 4vh; 38 | left: 2vw; 39 | font-size: min(1vw, 2vh); 40 | font-family: monospace; 41 | border-radius: 1vh; 42 | box-shadow: 0vh 0vh 0.2vh #00C; 43 | border-width: 2px; 44 | border-color: #000; 45 | border-style: ridge; 46 | text-align: center; 47 | background: linear-gradient(to bottom, #eef, #aaf); 48 | cursor:pointer; 49 | transition: all 0.3s ease-in-out; 50 | } 51 | 52 | .tabselect:hover 53 | { 54 | background: linear-gradient(to bottom, #ffe, #ffa); 55 | box-shadow: 0vh 0vh 1vh #00C; 56 | transform: translate(0vh, -1vh); 57 | } 58 | 59 | .manual 60 | { 61 | background: linear-gradient(to bottom, #cff, #fff, #dff); 62 | background-attachment: fixed; 63 | } 64 | 65 | .manual h1 66 | { 67 | background: linear-gradient(to bottom, #dff, #ff8, #dff); 68 | border-radius: 2vh; 69 | color: rgb(55, 29, 199); 70 | } 71 | 72 | .manual th 73 | { 74 | width: 20%; 75 | } 76 | 77 | .manual label 78 | { 79 | display: inline-block; 80 | min-width: 5vw; 81 | background: linear-gradient(to right, #ddd, #aaa, #ddd); 82 | font-family: monospace; 83 | text-align: center; 84 | } -------------------------------------------------------------------------------- /modules/at/at_cbc.js: -------------------------------------------------------------------------------- 1 | let AT_CBC = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Battery Charge", 10 | example: "+CBC: 0,62,3810", 11 | cmd: "AT+CBC", 12 | doc: "3.2.22" 13 | });// false, false, true, true, "Battery Charge", "+CBC: 0,62,3810", "AT+CBC", 1000); 14 | 15 | let enumBcs = []; 16 | enumBcs.push(new ATEnum(0, "ME is not charging")); 17 | enumBcs.push(new ATEnum(1, "ME is charging")); 18 | enumBcs.push(new ATEnum(2, "Charging has finished")); 19 | 20 | this.AddParam("bcs", enumBcs, "Charge status"); 21 | this.AddParam("bcl", "number", "Battery connection level"); 22 | this.AddParam("voltage", "number", "Battery voltage"); 23 | 24 | this.AddExeAnswerParam({bcs:null, bcl:null, voltage:null}); 25 | } 26 | 27 | ShowChat(div) 28 | { 29 | super.ShowChat(div); 30 | 31 | const value = this.GetValue(); 32 | 33 | if(this.GetRequestType() == "exe") 34 | { 35 | _CN("span", {}, [this.GetParam("bcs").GetValue(value.bcs)?.GetDescription()], div); 36 | _CN("span", {}, [TabChat.DrawGauge(0,100,parseInt(value.bcl)), "charge: " + value.bcl + "%"], div); 37 | _CN("span", {}, ["voltage: " + value.voltage + "mV"], div); 38 | } 39 | } 40 | 41 | GetChargeStatus(asDescription) 42 | { 43 | const value = this.GetValue(); 44 | return asDescription ? this.GetParam("bcs").GetValue(value.bcs).GetDescription() : this.GetParam("bcs").GetValue(value.bcs).GetValue(); 45 | } 46 | 47 | GetCharge() 48 | { 49 | const value = this.GetValue(); 50 | return value.bcl; 51 | } 52 | 53 | GetVoltage() 54 | { 55 | const value = this.GetValue(); 56 | return value.voltage; 57 | } 58 | }; -------------------------------------------------------------------------------- /modules/at/at_shconf.js: -------------------------------------------------------------------------------- 1 | let AT_SHCONF = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Set HTTP(S) Parameter", 11 | example: "+SHCONF: URL: 0.0.0.0:80", 12 | cmd: "AT+SHCONF", 13 | doc: "13.2.1" 14 | }); 15 | 16 | let enumC = []; 17 | enumC.push(new ATEnum("URL", "URL")); 18 | enumC.push(new ATEnum("TIMEOUT", "TIMEOUT")); 19 | enumC.push(new ATEnum("BODYLEN", "BODYLEN")); 20 | enumC.push(new ATEnum("HEADERLEN", "HEADERLEN")); 21 | enumC.push(new ATEnum("POLLCNT", "POLLCNT")); 22 | enumC.push(new ATEnum("POLLINTMS", "POLLINTMS")); 23 | enumC.push(new ATEnum("IPVER", "IPVER")); 24 | 25 | let enumI = []; 26 | enumI.push(new ATEnum(0, "IP v4")); 27 | enumI.push(new ATEnum(1, "IP v6")); 28 | 29 | 30 | this.AddParam("param", enumC, "parameter"); 31 | this.AddParam("url", "string", "url"); 32 | this.AddParam("timeout", "number", "timeout"); 33 | this.AddParam("headerlen", "number", "header length"); 34 | this.AddParam("pollcnt", "number", "poll count"); 35 | this.AddParam("pollintms", "number", "poll timeout ms"); 36 | this.AddParam("bodylen", "number", "body length"); 37 | this.AddParam("ipver", enumI, "ip version"); 38 | this.AddParam("dummy", "string", "dummy"); 39 | 40 | this.AddWriteSendParam({param:"URL", url:null}); 41 | this.AddWriteSendParam({param:"TIMEOUT", timeout:null}); 42 | this.AddWriteSendParam({param:"BODYLEN", bodylen:null}); 43 | this.AddWriteSendParam({param:"HEADERLEN", headerlen:null}); 44 | this.AddWriteSendParam({param:"POLLCNT", pollcnt:null}); 45 | this.AddWriteSendParam({param:"POLLINTMS", pollintms:null}); 46 | this.AddWriteSendParam({param:"IPVER", ipver:null}); 47 | 48 | this.AddReadAnswerParam({param:null, dummy:null}); 49 | } 50 | }; -------------------------------------------------------------------------------- /modules/at/at_cclk.js: -------------------------------------------------------------------------------- 1 | let AT_CCLK = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Clock", 11 | example: "+CCLK: \"80/01/06,00:37:28+00\"", 12 | cmd: "AT+CCLK", 13 | doc: "3.2.20" 14 | }); 15 | 16 | this.AddParam("time", "string", "time"); 17 | 18 | this.AddReadAnswerParam({time:null}); 19 | this.AddWriteSendParam({time:null}); 20 | } 21 | 22 | ShowChat(div) 23 | { 24 | super.ShowChat(div); 25 | 26 | const value = this.GetValue(); 27 | 28 | if(this.GetRequestType() == "read") 29 | { 30 | let dt = this.GetTime(); 31 | const optionsDate = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric' }; 32 | const optionsTime = { timeZoneName: "short", hour: "2-digit", minute: "2-digit", second: "2-digit" }; 33 | _CN("span", {}, [dt.toLocaleDateString(undefined, optionsDate)], div); 34 | _CN("span", {}, [dt.toLocaleTimeString(undefined, optionsTime)], div); 35 | } 36 | } 37 | 38 | GetTime() 39 | { 40 | const value = this.GetValue(); 41 | 42 | // 80/01/06,00:37:28+00 43 | let dt = value.time.replace(/"/g,'').split(","); 44 | let d = dt[0].split("/"); 45 | let t = dt[1].split("+")[0].split(":"); 46 | 47 | const ret = new Date(parseInt(d[0])+2000, parseInt(d[1])-1, parseInt(d[2]), parseInt(t[0]), parseInt(t[1]), parseInt(t[2])); 48 | return ret; 49 | } 50 | 51 | ConvertTime(javascriptTime) 52 | { 53 | let t = javascriptTime; 54 | let f = (t.getFullYear() % 100) + "/" + (t.getMonth() + 1).toString().padStart(2, '0') + "/" + (t.getDate()).toString().padStart(2, '0') + ","; 55 | f += (t.getHours()).toString().padStart(2, '0') + ":" + (t.getMinutes()).toString().padStart(2, '0') + ":" + (t.getSeconds()).toString().padStart(2, '0'); 56 | return "\"" + f + "\""; 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /js/tabCommands.js: -------------------------------------------------------------------------------- 1 | class TabCommands 2 | { 3 | Title = "Commands"; 4 | 5 | constructor() 6 | { 7 | this.div = _CN("div", {class:"box tab"}, [_CN("h2", {}, ["Module"])], Tabs.GetDiv()); 8 | 9 | setTimeout(()=>{ 10 | this.Init(); 11 | }, 200); 12 | } 13 | 14 | Init() 15 | { 16 | this.#InitModuleCommands(); 17 | 18 | } 19 | 20 | Select() 21 | { 22 | 23 | } 24 | 25 | #InitModuleCommands() 26 | { 27 | _CN("h3", {}, ["Commands"], this.div); 28 | 29 | this.div.appendChild( 30 | Tabs.AddCmd( 31 | "Reboot (CREBOOT)", 32 | ()=>{ 33 | ATScripts.Reboot().then(()=>{}); 34 | }, 35 | AT_CREBOOT) 36 | ); 37 | 38 | this.div.appendChild( 39 | Tabs.AddCmd( 40 | "Test (AT)", 41 | ()=>{ 42 | AT.Execute().then(()=>{}); 43 | }, 44 | AT) 45 | ); 46 | 47 | this.div.appendChild( 48 | Tabs.AddCmd( 49 | "Echo Off (ATE0)", 50 | ()=>{ 51 | ATE0.Execute().then(()=>{}); 52 | }, 53 | ATE0) 54 | ); 55 | 56 | this.div.appendChild( 57 | Tabs.AddCmd( 58 | "Echo On (ATE1)", 59 | ()=>{ 60 | ATE1.Execute().then(()=>{}); 61 | }, 62 | ATE1) 63 | ); 64 | 65 | this.div.appendChild( 66 | Tabs.AddCmd( 67 | "Show Error messages (CMEE)", 68 | ()=>{ 69 | AT_CMEE.Write([2]).then(()=>{}); 70 | }, 71 | AT_CMEE) 72 | ); 73 | 74 | this.div.appendChild( 75 | Tabs.AddCmd( 76 | "Disable Error messages (CMEE)", 77 | ()=>{ 78 | AT_CMEE.Write([0]).then(()=>{}); 79 | }, 80 | AT_CMEE) 81 | ); 82 | 83 | this.div.appendChild( 84 | Tabs.AddCmd( 85 | "Set Time (CCLK)", 86 | ()=>{ 87 | let f = AT_CCLK.ConvertTime(new Date()); 88 | AT_CCLK.Write([f]).then(()=>{}); 89 | }, 90 | AT_CCLK) 91 | ); 92 | } 93 | }; 94 | 95 | Tabs.AddTab(new TabCommands()); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimCom Tester 2 | This webpage will let you send some simple commands to your SimCom Module. 3 | - Send AT-Commands to you SimCom module directly over the webpage 4 | - No downloads or installation 5 | - Description of every command, with integrated help and AT-manual 6 | - Check module and firmware 7 | 8 | ❕ Actually, only the **SIM7080G** (SIM7070G and SIM7090G) is implemented. Other modules can be used if compatible or can be implemented in future without much work. 9 | 10 | 11 | # Setup 12 | - Connect your module with your PC (USB or Serial). 13 | - Open the webpage with Edge, Chrome or another browser with Serial-functionality. 14 | - Press on "Connect" and select the right serial port on your browser (the first SimTech serial port, on USB) 15 | - If everything is connected, you should see something like this: 16 | 17 | ![image](https://github.com/user-attachments/assets/194d2c5b-7a57-4671-8e90-c0ede48043d3) 18 | 19 | 20 | # How to use 21 | - You can press any predefined commands on the left panel 22 | - Or you can write the commands directly in the "chat" 23 | - If you press on "📃" a tutorial should be visible for that command. 24 | 25 | # How to edit/test 26 | - Create a workspace in GitHub 27 | - Add extension "Live Preview" from Microsoft 28 | - Open index.html and press on the right/top button "show preview", opening the browser-tab in a new window 29 | - Edit and test it until you have a working version. 30 | 31 | # Issues 32 | I am testing a SIM7080 Module, so this page has some 7080-specific commands. 33 | 34 | The structure should let me/us to add (without much works) more commands and to add module-specific commands. 35 | 36 | The page is not able to parse "unsolicited results". I need to integrate this functionality. 37 | 38 | # Credits 39 | [Web Serial Port API (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/API/SerialPort) 40 | [Javascript PDFLib for (github.com)](https://github.com/mozilla/pdf.js) 41 | [SimCom Module (simcom.com)](https://www.simcom.com/product/SIM7080G.html) 42 | 43 | Too complicated or module does not answer? Try a Web Serial Terminal: https://www.serialterminal.com/ 44 | -------------------------------------------------------------------------------- /modules/at/at_cgdcont.js: -------------------------------------------------------------------------------- 1 | let AT_CGDCONT = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | test: true, 8 | read: true, 9 | description: "Define PDP Context", 10 | example: "+CGDCONT: 1,\"IPV4V6\",\"\",\"\",0,0,0", 11 | cmd: "AT+CGDCONT", 12 | doc: "6.2.2" 13 | }); 14 | 15 | let enumPdp = []; 16 | enumPdp.push(new ATEnum("IP", "Internet Protocol")); 17 | enumPdp.push(new ATEnum("IPV6", "Internet Protocol Version 6")); 18 | enumPdp.push(new ATEnum("IPV4V6", "Dual PDN Stack")); 19 | enumPdp.push(new ATEnum("Non-IP", "Transfer of Non-IP data")); 20 | 21 | let enumDComp = []; 22 | enumDComp.push(new ATEnum(0, "Off")); 23 | enumDComp.push(new ATEnum(1, "On")); 24 | enumDComp.push(new ATEnum(2, "V.42bis")); 25 | 26 | let enumHComp = []; 27 | enumHComp.push(new ATEnum(0, "Off")); 28 | enumHComp.push(new ATEnum(1, "On")); 29 | enumHComp.push(new ATEnum(2, "RFC1144")); 30 | enumHComp.push(new ATEnum(3, "RFC2507")); 31 | enumHComp.push(new ATEnum(4, "RFC3095")); 32 | 33 | let enumIP = []; 34 | enumIP.push(new ATEnum(0, "NAS Signaling")); 35 | enumIP.push(new ATEnum(1, "Off")); 36 | 37 | let enumEFlag = []; 38 | enumEFlag.push(new ATEnum(0, "Off")); 39 | enumEFlag.push(new ATEnum(1, "On")); 40 | 41 | this.AddParam("cid", "number", "PDP Context Identifier"); 42 | this.AddParam("pdp_type", enumPdp, "PDP_type"); 43 | this.AddParam("apn", "string", "network apn"); 44 | this.AddParam("pdp_addr", "string", "PDP Address"); 45 | this.AddParam("d_comp", enumDComp, "Data compression"); 46 | this.AddParam("h_comp", enumHComp, "Head compression"); 47 | this.AddParam("ipv4_ctrl", enumIP, "ipv4 information"); 48 | this.AddParam("emergency_flag", enumEFlag, "emergency flag"); 49 | 50 | this.AddReadAnswerParam({cid:null, pdp_type:null, apn:null, pdp_addr:null, d_comp:null, h_comp:null, ipv4_ctrl:null}); 51 | this.AddReadAnswerParam({cid:null, pdp_type:null, apn:null, pdp_addr:null, d_comp:null, h_comp:null, ipv4_ctrl:null, emergency_flag:null}); 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /modules/at/at_cgreg.js: -------------------------------------------------------------------------------- 1 | let AT_CGREG = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | test: true, 8 | read: true, 9 | write: true, 10 | description: "Network Registration Status", 11 | example: "+CGREG: 0,2", 12 | cmd: "AT+CGREG", 13 | doc: "6.2.5" 14 | }); 15 | 16 | let enumN = []; 17 | enumN.push(new ATEnum(0, "Disable network registration unsolicited")); 18 | enumN.push(new ATEnum(1, "Enable network registration unsolicited")); 19 | enumN.push(new ATEnum(2, "Enable network registration and location unsolicited")); 20 | enumN.push(new ATEnum(4, "Enable display GPRS time")); 21 | 22 | let enumStat = []; 23 | enumStat.push(new ATEnum(0, "Not registered, not searching")); 24 | enumStat.push(new ATEnum(1, "Registered, Home network")); 25 | enumStat.push(new ATEnum(2, "Not registered, searching")); 26 | enumStat.push(new ATEnum(3, "Registration denied")); 27 | enumStat.push(new ATEnum(4, "Unknown")); 28 | enumStat.push(new ATEnum(5, "Registered, roaming")); 29 | enumStat.push(new ATEnum(6, "Reserved")); 30 | 31 | let enumNet = []; 32 | enumNet.push(new ATEnum(0, "GSM user")); 33 | enumNet.push(new ATEnum(1, "GSM compact")); 34 | enumNet.push(new ATEnum(3, "GSM egprs")); 35 | enumNet.push(new ATEnum(7, "LTE M1")); 36 | enumNet.push(new ATEnum(9, "LTE NB")); 37 | 38 | let enumIP = []; 39 | enumIP.push(new ATEnum(0, "NAS Signaling")); 40 | enumIP.push(new ATEnum(1, "Off")); 41 | 42 | let enumEFlag = []; 43 | enumEFlag.push(new ATEnum(0, "Off")); 44 | enumEFlag.push(new ATEnum(1, "On")); 45 | 46 | this.AddParam("n", enumN, "network registration"); 47 | this.AddParam("stat", enumStat, "network state"); 48 | this.AddParam("lac", "string", "location area"); 49 | this.AddParam("ci", "string", "cell id"); 50 | this.AddParam("netact", enumNet, "network access"); 51 | this.AddParam("rac", "string", "routing area code"); 52 | 53 | this.AddWriteSendParam({n:null}); 54 | 55 | this.AddReadAnswerParam({n:null, stat:null}); 56 | this.AddReadAnswerParam({n:null, stat:null, lac:null, ci:null, netact:null, rac:null}); 57 | } 58 | }; -------------------------------------------------------------------------------- /modules/at/at_clts.js: -------------------------------------------------------------------------------- 1 | let AT_CLTS = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Get Local Timestamp", 11 | example: "+CLTS: 0", 12 | cmd: "AT+CLTS", 13 | doc: "5.2.4" 14 | }); 15 | 16 | let enumMode = []; 17 | enumMode.push(new ATEnum(0, "disable")); 18 | enumMode.push(new ATEnum(1, "enable")); 19 | this.AddParam("mode", enumMode, "mode"); 20 | 21 | this.AddReadAnswerParam({mode:null}); 22 | this.AddWriteSendParam({mode:null}); 23 | } 24 | 25 | }; 26 | 27 | let _PSUTTZ = new class extends ATBase 28 | { 29 | constructor() 30 | { 31 | super({ 32 | description: "Time Report (see AT+CLTS)", 33 | example: "*PSUTTZ: 2025,04,01,15,12,10,\"\",1", 34 | cmd: "*PSUTTZ", 35 | doc: "5.2.49" 36 | }); 37 | 38 | this.AddParam("year", "integer", "year"); 39 | this.AddParam("month", "integer", "month"); 40 | this.AddParam("day", "integer", "day"); 41 | this.AddParam("hour", "integer", "hour"); 42 | this.AddParam("min", "integer", "min"); 43 | this.AddParam("sec", "integer", "sec"); 44 | this.AddParam("time_zone", "string", "time zone"); 45 | this.AddParam("dst", "integer", "daylight saving"); 46 | 47 | this.AddUnsolicitedAnswerParam({year:null, month:null, day:null, hour:null, min:null, sec:null, time_zone:null, dst:null}); 48 | } 49 | }; 50 | 51 | let _CTZV = new class extends ATBase 52 | { 53 | constructor() 54 | { 55 | super({ 56 | description: "Time Zone Report (see AT+CLTS)", 57 | example: "+CTZV: \"1\"", 58 | cmd: "+CTZV", 59 | doc: "5.2.49" 60 | }); 61 | 62 | this.AddParam("time_zone", "string", "time zone"); 63 | 64 | this.AddUnsolicitedAnswerParam({time_zone:null}); 65 | } 66 | }; 67 | 68 | 69 | let _DST = new class extends ATBase 70 | { 71 | constructor() 72 | { 73 | super({ 74 | description: "Time Daylight Saving Report (see AT+CLTS)", 75 | example: "DST: \"1\"", 76 | cmd: "DST", 77 | doc: "5.2.49" 78 | }); 79 | 80 | this.AddParam("dst", "integer", "daylight saving time"); 81 | 82 | this.AddUnsolicitedAnswerParam({dst:null}); 83 | } 84 | }; 85 | 86 | 87 | -------------------------------------------------------------------------------- /modules/at/at_csq.js: -------------------------------------------------------------------------------- 1 | let AT_CSQ = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | exe: true, 8 | test: true, 9 | description: "Signal Quality Report", 10 | example: "+CSQ: 24,0", 11 | cmd: "AT+CSQ", 12 | doc: "3.2.16" 13 | }); //false, false, true, true, "Signal Quality Report", "+CSQ: 24,0", "AT+CSQ", 1000); 14 | 15 | this.AddParam("rssi", "number", "Radio Signal Strength"); 16 | this.AddParam("ber", "number", "Bit Error Rate"); 17 | 18 | this.AddExeAnswerParam({rssi:null, ber:null}); 19 | } 20 | 21 | GetRSSI_dBm() 22 | { 23 | const value = this.GetValue(); 24 | 25 | let dBm = -115; 26 | if(value.rssi == 1) dBm = -111; 27 | else if(value.rssi < 32) dBm = parseInt(-110 + parseInt((110-54) * (value.rssi - 2) / 28)); 28 | else if(value.rssi == 99) dBm = -120; 29 | return dBm; 30 | } 31 | 32 | ShowChat(div) 33 | { 34 | super.ShowChat(div); 35 | 36 | if(this.GetRequestType() != "exe") return; 37 | 38 | const value = this.GetValue(); 39 | 40 | let strength = "unknown"; 41 | let gauge = 0; 42 | if(value.rssi == 0) strength = "-115dBm (bad)"; 43 | else if(value.rssi == 1) strength = "-111dBm (poor)"; 44 | else if(value.rssi < 31) { 45 | strength = (-110 + parseInt((110-54) * (value.rssi - 2) / 28)) + "dBm (" + (value.rssi < 15 ? "ok" : "good") + ")"; 46 | gauge = 5 + value.rssi * 3; 47 | } 48 | else if(value.rssi == 31) { 49 | strength = ">-52dBm (excellent)"; 50 | gauge= 100 51 | } 52 | else if(value.rssi == 99) strength = "-Unknown-"; 53 | else strength = "Invalid - " + value.rssi; 54 | 55 | let ber = "-Unknown-"; 56 | switch(parseInt(value.ber)) 57 | { 58 | case 0: ber = "<0.2%"; break; 59 | case 1: ber = "0.2%-0.4%"; break; 60 | case 2: ber = "0.4%-0.8%"; break; 61 | case 3: ber = "0.8%-1.6%"; break; 62 | case 4: ber = "1.6%-3.2%"; break; 63 | case 5: ber = "3.2%-6.4%"; break; 64 | case 6: ber = "6.4%-12.8%"; break; 65 | case 7: ber = ">12.8%"; break; 66 | case 99: "-Unknown-"; break; 67 | default: ber = "INVALID"; break; 68 | } 69 | 70 | _CN("span", {}, [TabChat.DrawGauge(0,100,gauge), "rssi: " + strength], div); 71 | _CN("span", {}, ["ber: " + ber], div); 72 | } 73 | }; -------------------------------------------------------------------------------- /modules/at/at_cops.js: -------------------------------------------------------------------------------- 1 | let AT_COPS = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Operator Selection", 11 | example: "+COPS:0,0,\"CHINA MOBILE\"", 12 | cmd: "AT+COPS", 13 | timeout: 120000, 14 | doc: "3.2.9" 15 | }); //true, true, false, true, "Operator Selection", "+COPS:0,0,\"CHINA MOBILE\"", "AT+COPS", 120000); 16 | 17 | let enumM = []; 18 | enumM.push(new ATEnum(0, "Automatic mode")); 19 | enumM.push(new ATEnum(1, "Manual")); 20 | enumM.push(new ATEnum(2, "Manual deregister from network")); 21 | enumM.push(new ATEnum(3, "Set only")); 22 | enumM.push(new ATEnum(4, "Manual/automatic")); 23 | 24 | let enumF = []; 25 | enumF.push(new ATEnum(0, "Long format alphanumeric")); 26 | enumF.push(new ATEnum(1, "Short format alphanumeric")); 27 | enumF.push(new ATEnum(2, "Numeric")); 28 | 29 | let enumN = []; 30 | enumN.push(new ATEnum(0, "User-specified GSM")); 31 | enumN.push(new ATEnum(1, "GSM compact")); 32 | enumN.push(new ATEnum(3, "GSM EGPRS")); 33 | enumN.push(new ATEnum(7, "User-specified LTE M1 A GB")); 34 | enumN.push(new ATEnum(9, "User-specified LTE NB S1")); 35 | 36 | this.AddParam("mode", enumM, "mode"); 37 | this.AddParam("format", enumF, "format"); 38 | this.AddParam("oper", "string", "operator"); 39 | this.AddParam("netact", enumN, "net access activity"); 40 | 41 | this.AddReadAnswerParam({mode:null}); 42 | this.AddReadAnswerParam({mode:null, format:null, oper:null, netact:null}); 43 | 44 | this.AddWriteSendParam({mode:null}); 45 | this.AddWriteSendParam({mode:null, format:null, oper:null}); 46 | } 47 | 48 | ShowChat(div) 49 | { 50 | super.ShowChat(div); 51 | 52 | const value = this.GetValue(); 53 | 54 | if(this.GetRequestType() == "read") 55 | { 56 | Object.keys(value).forEach(k=>{ 57 | const p = this.GetParam(k); 58 | if(p.GetValue(value[k]) != null) 59 | { 60 | _CN("span", {}, [p.GetValue(value[k])?.GetDescription()], div); 61 | } 62 | else 63 | { 64 | _CN("span", {}, [k + ": " + value[k]], div); 65 | } 66 | }); 67 | } 68 | } 69 | 70 | GetOperator() 71 | { 72 | const value = this.GetValue(); 73 | return value.oper; 74 | } 75 | 76 | }; -------------------------------------------------------------------------------- /modules/at/at_cncfg.js: -------------------------------------------------------------------------------- 1 | let AT_CNCFG = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "PDP Config", 11 | example: "+CNCFG: 0,0,\"\",\"\",\"\",0", 12 | cmd: "AT+CNCFG", 13 | doc: "7.2.2" 14 | }); //true, true, false, true, "PDP Config", "+CNCFG: 0,0,\"\",\"\",\"\",0", "AT+CNCFG", 1000); 15 | 16 | let enumIdx = []; 17 | enumIdx.push(new ATEnum(0, "pdpidx 0")); 18 | enumIdx.push(new ATEnum(1, "pdpidx 1")); 19 | enumIdx.push(new ATEnum(2, "pdpidx 2")); 20 | enumIdx.push(new ATEnum(3, "pdpidx 3")); 21 | 22 | let enumIp = []; 23 | enumIp.push(new ATEnum(0, "Dual PDN Stack")); 24 | enumIp.push(new ATEnum(1, "Internet Protocol Version 4")); 25 | enumIp.push(new ATEnum(2, "Internet Protocol Version 6")); 26 | enumIp.push(new ATEnum(3, "NONIP")); 27 | enumIp.push(new ATEnum(4, "EX_NONIP")); 28 | 29 | let enumA = []; 30 | enumA.push(new ATEnum(0, "NONE")); 31 | enumA.push(new ATEnum(1, "PAP")); 32 | enumA.push(new ATEnum(2, "CHAP")); 33 | enumA.push(new ATEnum(3, "PAP or CHAP")); 34 | 35 | this.AddParam("pdpidx", enumIdx, "pdpidx"); 36 | this.AddParam("iptype", enumIp, "ip_type"); 37 | this.AddParam("apn", "string", "APN"); 38 | this.AddParam("username", "string", "Username"); 39 | this.AddParam("password", "string", "Password"); 40 | this.AddParam("authentication", enumA, "Authentication"); 41 | 42 | this.AddReadAnswerParam({pdpidx:null, iptype:null, apn:null, username:null, password:null, authentication:null}); 43 | this.AddWriteSendParam({pdpidx:null, iptype:null}); 44 | this.AddWriteSendParam({pdpidx:null, iptype:null, apn:null}); 45 | this.AddWriteSendParam({pdpidx:null, iptype:null, apn:null, username:null, password:null}); 46 | this.AddWriteSendParam({pdpidx:null, iptype:null, apn:null, username:null, password:null, authentication:null}); 47 | } 48 | 49 | ShowChat(div) 50 | { 51 | super.ShowChat(div); 52 | 53 | const value = this.GetValue(); 54 | 55 | if(this.GetRequestType() == "exe") 56 | { 57 | Object.keys(value).forEach(k=>{ 58 | const p = this.GetParam(k); 59 | if(p.GetValue(value[k]) != null) 60 | { 61 | _CN("span", {}, [p.GetValue(value[k])?.GetDescription()], div); 62 | } 63 | else 64 | { 65 | _CN("span", {}, [k + ": " + value[k]], div); 66 | } 67 | }); 68 | } 69 | } 70 | }; -------------------------------------------------------------------------------- /modules/at/at_creg.js: -------------------------------------------------------------------------------- 1 | let AT_CREG = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Network Registration", 11 | example: "+CREG: 0,2", 12 | cmd: "AT+CREG", 13 | doc: "3.2.14" 14 | }); //true, true, false, true, "Network Registration", "+CREG: 0,2", "AT+CREG", 1000); 15 | 16 | let enumN = []; 17 | enumN.push(new ATEnum(0, "Disable network registration unsolicited result")); 18 | enumN.push(new ATEnum(1, "Enable network registration unsolicited result")); 19 | enumN.push(new ATEnum(2, "Enable network registration unsolicited result code with location information")); 20 | 21 | let enumStat = []; 22 | enumStat.push(new ATEnum(0, "Not registered, MT is not currently searching a new operator to register to")); 23 | enumStat.push(new ATEnum(1, "Registered, home network")); 24 | enumStat.push(new ATEnum(2, "Not registered, but MT is currently searching a new operator to register to")); 25 | enumStat.push(new ATEnum(3, "Registration denied")); 26 | enumStat.push(new ATEnum(4, "Unknown")); 27 | enumStat.push(new ATEnum(5, "Registered, roaming")); 28 | 29 | let enumNetAct = []; 30 | enumNetAct.push(new ATEnum(0, "User-specified GSM access technology")); 31 | enumNetAct.push(new ATEnum(1, "GSM compact")); 32 | enumNetAct.push(new ATEnum(3, "GSM EGPRS")); 33 | enumNetAct.push(new ATEnum(7, "User-specified LTE M1 A GB access technology")); 34 | enumNetAct.push(new ATEnum(9, "User-specified LTE NB S1 access technology")); 35 | 36 | this.AddParam("n", enumN, "network"); 37 | this.AddParam("stat", enumStat, "state"); 38 | this.AddParam("lac", "string", "two byte location area code in hexadecimal format"); 39 | this.AddParam("ci", "string", "two byte cell ID in hexadecimal form"); 40 | this.AddParam("netact", enumNetAct, "Network Activity"); 41 | 42 | this.AddTestAnswerParam({n:null}); 43 | 44 | this.AddReadAnswerParam({n:null, stat:null}); 45 | this.AddReadAnswerParam({n:2, stat:null, lac:null, ci:null, netact:null}); 46 | 47 | this.AddWriteSendParam({n:null}); 48 | } 49 | 50 | ShowChat(div) 51 | { 52 | super.ShowChat(div); 53 | 54 | const value = this.GetValue(); 55 | 56 | if(this.GetRequestType() == "read") 57 | { 58 | _CN("span", {}, [this.GetParam("n").GetValue(value.n)?.GetDescription()], div); 59 | _CN("span", {}, [this.GetParam("stat").GetValue(value.stat)?.GetDescription()], div); 60 | } 61 | } 62 | }; -------------------------------------------------------------------------------- /modules/at/at_clck.js: -------------------------------------------------------------------------------- 1 | let AT_CLCK = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | write: true, 8 | test: true, 9 | description: "Facility Lock", 10 | example: "+CLCK: \"SC\",2", 11 | cmd: "AT+CLCK", 12 | doc: "3.2.7" 13 | }); 14 | 15 | let enumFac = []; 16 | //enumFac.push(new ATEnum("AB", "All Barring services, mode=0")); 17 | //enumFac.push(new ATEnum("AC", "All incoming barring services, mode=0")); 18 | //enumFac.push(new ATEnum("AG", "All outgoing barring services, mode=0")); 19 | //enumFac.push(new ATEnum("AO", "BAOC (Barr All Outgoing Calls")); 20 | //enumFac.push(new ATEnum("IR", "BIC-Roam (Barr Inc.Calls on Roaming)")); 21 | //enumFac.push(new ATEnum("OI", "BOIC (Barr Out. International Calls)")); 22 | //enumFac.push(new ATEnum("OX", "BOIC-exHC (Barr Out. Int. Calls)")); 23 | enumFac.push(new ATEnum("SC", "SIM (lock SIM/UICC card) - PIN1")); 24 | enumFac.push(new ATEnum("FD", "SIM card or active application - PIN2")); 25 | enumFac.push(new ATEnum("PN", "Network Personalization - NCK")); 26 | enumFac.push(new ATEnum("PU", "Network subset Personalization - NSCK")); 27 | enumFac.push(new ATEnum("PP", "Service Provider Personalization - SPCK")); 28 | enumFac.push(new ATEnum("PF", "Lock Phone to the very First inserted SIM card")); 29 | 30 | let enumM = []; 31 | enumM.push(new ATEnum(0, "Unlock")); 32 | enumM.push(new ATEnum(1, "Lock")); 33 | enumM.push(new ATEnum(2, "Query Status")); 34 | 35 | let enumC = []; 36 | enumC.push(new ATEnum(1, "Voice (telephony)")); 37 | enumC.push(new ATEnum(2, "Data refers")); 38 | enumC.push(new ATEnum(4, "Fax (facsimile services)")); 39 | enumC.push(new ATEnum(7, "All classes")); 40 | 41 | let enumS = []; 42 | enumS.push(new ATEnum(0, "Inactive")); 43 | enumS.push(new ATEnum(1, "Active")); 44 | 45 | this.AddParam("fac", enumFac, "facility"); 46 | this.AddParam("mode", enumM, "set mode"); 47 | this.AddParam("passwd", "string", "Password"); 48 | this.AddParam("class", enumC, "Class"); 49 | this.AddParam("status", enumS, "Status"); 50 | 51 | this.AddWriteSendParam({fac:null, mode:null}); 52 | this.AddWriteSendParam({fac:null, mode:null, passwd:null}); 53 | this.AddWriteSendParam({fac:null, mode:null, passwd:null, class:null}); 54 | 55 | this.AddWriteAnswerParam({}); 56 | this.AddWriteAnswerParam({status: null}); 57 | this.AddWriteAnswerParam({status: null, class:null}); 58 | } 59 | 60 | ShowChat(div) 61 | { 62 | super.ShowChat(div); 63 | 64 | if(this.GetRequestType() == "write") 65 | { 66 | const value = this.GetValue(); 67 | _CN("span", {}, [value?.status == 1 ? "ACTIVE" : "INACTIVE"], div); 68 | } 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /modules/at/at_cnact.js: -------------------------------------------------------------------------------- 1 | let AT_CNACT = new class extends ATBase 2 | { 3 | // Active Networks (up to 4 can be active) 4 | #acts = []; 5 | 6 | constructor() 7 | { 8 | //read, write, exe, test, description, example, cmd, timeout) 9 | super({ 10 | read: true, 11 | write: true, 12 | test: true, 13 | description: "APP Network Active", 14 | example: "+CNACT: 0,0,\"0.0.0.0\"", 15 | cmd: "AT+CNACT", 16 | doc: "7.2.1" 17 | }); //true, true, false, true, "APP Network Active", "+CNACT: 0,0,\"0.0.0.0\"", "AT+CNACT", 1000); 18 | 19 | let enumIdx = []; 20 | enumIdx.push(new ATEnum(0, "pdpidx 0")); 21 | enumIdx.push(new ATEnum(1, "pdpidx 1")); 22 | enumIdx.push(new ATEnum(2, "pdpidx 2")); 23 | enumIdx.push(new ATEnum(3, "pdpidx 3")); 24 | 25 | let enumSX = []; 26 | enumSX.push(new ATEnum(0, "Deactived")); 27 | enumSX.push(new ATEnum(1, "Actived")); 28 | enumSX.push(new ATEnum(2, "In operation")); 29 | 30 | let enumA = []; 31 | enumA.push(new ATEnum(0, "Deactive")); 32 | enumA.push(new ATEnum(1, "Active")); 33 | enumA.push(new ATEnum(2, "Auto Active")); 34 | 35 | this.AddParam("pdpidx", enumIdx, "pdpidx"); 36 | this.AddParam("statusx", enumSX, "status X"); 37 | this.AddParam("action", enumA, "action"); 38 | this.AddParam("addressx", "string", "adress X"); 39 | this.AddParam("ipv6address", "string", "IPv6 address"); 40 | 41 | this.AddReadAnswerParam({pdpidx:null, statusx:null, addressx:null}); 42 | this.AddReadAnswerParam({pdpidx:null, statusx:null, addressx:null, ipv6address:null}); 43 | 44 | this.AddWriteSendParam({pdpidx:null, action:null}); 45 | 46 | for(var j=0;j<4;j++) 47 | { 48 | this.#acts.push({active:false, ip:""}); 49 | } 50 | } 51 | 52 | Parse(str) 53 | { 54 | super.Parse(str); 55 | 56 | if(str.split(",").length > 2) 57 | { 58 | let v = this.GetValue(); 59 | this.#acts[parseInt(v.pdpidx)].active = (parseInt(v.statusx) == 1); 60 | this.#acts[parseInt(v.pdpidx)].ip = this.#acts[parseInt(v.pdpidx)].active ? v.addressx : ""; 61 | } 62 | } 63 | 64 | IsActive(index) 65 | { 66 | return this.#acts[index].active; 67 | } 68 | 69 | GetIp(index) 70 | { 71 | return this.IsActive(index) ? this.#acts[index].ip : ""; 72 | } 73 | }; 74 | 75 | let _APP_PDP = new class extends ATBase 76 | { 77 | constructor() 78 | { 79 | super({ 80 | description: "APP Network Active (see AT+CNACT)", 81 | example: "+APP PDP: 0,ACTIVE", 82 | cmd: "+APP PDP", 83 | doc: "7.2.1" 84 | }); 85 | 86 | let enumPdp = []; 87 | enumPdp.push(new ATEnum(0, "")); 88 | enumPdp.push(new ATEnum(1, "")); 89 | enumPdp.push(new ATEnum(2, "")); 90 | enumPdp.push(new ATEnum(3, "")); 91 | this.AddParam("pdpidx", enumPdp, "pdpidx"); 92 | 93 | this.AddParam("active", "string", "active"); 94 | 95 | this.AddUnsolicitedAnswerParam({pdpidx:null, active:null}); 96 | } 97 | }; -------------------------------------------------------------------------------- /modules/at/at_cmgl.js: -------------------------------------------------------------------------------- 1 | let AT_CMGL = new class extends ATBase 2 | { 3 | #messages = []; 4 | 5 | constructor() 6 | { 7 | //read, write, exe, test, description, example, cmd, timeout) 8 | super({ 9 | write: true, 10 | exe: true, 11 | test: true, 12 | description: "List SMS Messages from Preferred Store", 13 | example: "+CMGL: 1,2,,18", 14 | cmd: "AT+CMGL", 15 | timeout: 20000, 16 | doc: "4.2.3" 17 | });// true, true, false, true, "Enter/Read PIN", "+CPIN: READY", "AT+CPIN", 5000); 18 | 19 | let enumS = []; 20 | enumS.push(new ATEnum(0, "Received unread messages")); 21 | enumS.push(new ATEnum(1, "Received read messages")); 22 | enumS.push(new ATEnum(2, "Stored unsent messages")); 23 | enumS.push(new ATEnum(3, "Stored sent messages")); 24 | enumS.push(new ATEnum(4, "All messages")); 25 | enumS.push(new ATEnum("REC UNREAD", "Received unread messages")); 26 | enumS.push(new ATEnum("REC READ", "Received read messages")); 27 | enumS.push(new ATEnum("STO UNSENT", "Stored unsent messages")); 28 | enumS.push(new ATEnum("STO SENT", "Stored sent messages")); 29 | enumS.push(new ATEnum("ALL", "All messages")); 30 | 31 | let enumM = []; 32 | enumM.push(new ATEnum(0, "Normal")); 33 | enumM.push(new ATEnum(1, "Not change status of the specified SMS record")); 34 | 35 | this.AddParam("stat", enumS, "stat"); 36 | this.AddParam("mode", enumM, "mode"); 37 | this.AddParam("index", "number", "sms index"); 38 | this.AddParam("alpha", "string", "alpha"); 39 | this.AddParam("oada", "string", "originating address"); 40 | this.AddParam("scts", "number", "service center timestamp"); 41 | this.AddParam("tooa", "string", "destination address"); 42 | this.AddParam("length", "number", "message length"); 43 | 44 | this.AddWriteSendParam({stat:null}); 45 | this.AddWriteSendParam({stat:null, mode:null}); 46 | 47 | this.AddWriteAnswerParam({index:null, stat:null, oada:null}); 48 | this.AddWriteAnswerParam({index:null, stat:null, oada:null, alpha:null}); 49 | this.AddWriteAnswerParam({index:null, stat:null, oada:null, alpha:null, scts:null}); 50 | this.AddWriteAnswerParam({index:null, stat:null, oada:null, alpha:null, scts:null, tooa:null, length:null}); 51 | } 52 | 53 | Parse(str) 54 | { 55 | super.Parse(str); 56 | let line = this.GetLines().length; 57 | 58 | if(line == 1) this.#messages = []; 59 | if(str == "OK") return; 60 | if((line % 2) == 1) 61 | { 62 | this.#messages.push({raw: str, data:{...this.GetValue()}, msg:""}); 63 | } 64 | else 65 | { 66 | this.#messages[(line - 2) / 2].msg = str.trim(); 67 | } 68 | 69 | console.log("CMGL:", str); 70 | } 71 | 72 | ShowChat(div) 73 | { 74 | super.ShowChat(div); 75 | 76 | if(this.GetRequestType() == "write" || this.GetRequestType() == "read") 77 | { 78 | 79 | } 80 | } 81 | 82 | GetMessages() 83 | { 84 | return this.#messages; 85 | } 86 | 87 | }; -------------------------------------------------------------------------------- /modules/at/at_ccoappara.js: -------------------------------------------------------------------------------- 1 | let AT_CCOAPPARA = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | write: true, 8 | test: true, 9 | description: "Assembling CoAP Data Packet", 10 | cmd: "AT+CCOAPPARA", 11 | doc: "18.2.5" 12 | }); //false, true, false, true, "Assembling CoAP Data Packet", "", "AT+CCOAPPARA", 1000); 13 | 14 | let enumC = []; 15 | enumC.push(new ATEnum(0, "EMPTY")); 16 | enumC.push(new ATEnum(1, "GET")); 17 | enumC.push(new ATEnum(2, "POST")); 18 | enumC.push(new ATEnum(3, "PUT")); 19 | enumC.push(new ATEnum(4, "DELETE")); 20 | enumC.push(new ATEnum(5, "FETCH")); 21 | enumC.push(new ATEnum(6, "PATCH")); 22 | enumC.push(new ATEnum(7, "iPATCH")); 23 | 24 | let enumT = []; 25 | enumT.push(new ATEnum("CON", "Confirmable")); 26 | enumT.push(new ATEnum("NON", "Non confirmable")); 27 | enumT.push(new ATEnum("ACK", "Acknowledgement")); 28 | enumT.push(new ATEnum("RST", "Reset")); 29 | 30 | let enumCodex = []; 31 | enumCodex.push(new ATEnum(0, "ASCII-format")); 32 | enumCodex.push(new ATEnum(1, "HEX-format")); 33 | 34 | this.AddParam("code", enumC, "code"); 35 | this.AddParam("type", enumT, "code"); 36 | this.AddParam("uripath", "string", "uri path"); 37 | this.AddParam("token", "string", "token"); 38 | this.AddParam("uriquery", "string", "uri query"); 39 | this.AddParam("payload", "string", "payload"); 40 | this.AddParam("etag", "string", "etag"); 41 | this.AddParam("mid", "number", "message id"); 42 | this.AddParam("codex", enumCodex, "value format"); 43 | this.AddParam("cont_format", "number", "Content format"); 44 | this.AddParam("accept", "number", "Accept"); 45 | this.AddParam("observe", "number", "Observe"); 46 | this.AddParam("max_age", "number", "Max age"); 47 | this.AddParam("size", "number", "Payload length"); 48 | 49 | for(var j=0;j<30;j++) 50 | { 51 | this.AddParam("param" + j, "string", "code"); 52 | } 53 | 54 | this.AddWriteSendParam({param0:"CODE", code:null}); 55 | this.AddWriteSendParam({param0:"TYPE", type:null}); 56 | this.AddWriteSendParam({param0:"MID", mid:null}); 57 | this.AddWriteSendParam({param0:"TOKEN", codex:null, token:null}); 58 | this.AddWriteSendParam({param0:"CONTENT-FORMAT", cont_format:null}); 59 | this.AddWriteSendParam({param0:"ACCEPT", accept:null}); 60 | this.AddWriteSendParam({param0:"URI-PATH", codex:null, uripath:null}); 61 | this.AddWriteSendParam({param0:"URI-QUERY", codex:null, uriquery:null}); 62 | this.AddWriteSendParam({param0:"ETAG", codex:null, etag:null}); 63 | this.AddWriteSendParam({param0:"OBSERVE", observe:null}); 64 | this.AddWriteSendParam({param0:"MAX-AGE", max_age:null}); 65 | this.AddWriteSendParam({param0:"SIZE", size:null}); 66 | this.AddWriteSendParam({param0:"PAYLOAD", codex:null, payload:null}); 67 | 68 | for(var j=2;j<30;j++) 69 | { 70 | let obj = {}; 71 | for(var k=0;k{ 60 | _CN("span", {}, [k + ": " + value[k]], div); 61 | }); 62 | } 63 | } 64 | 65 | GetLatitude() 66 | { 67 | const value = this.GetValue(); 68 | return value.latitude; 69 | } 70 | 71 | GetLongitude() 72 | { 73 | const value = this.GetValue(); 74 | return value.longitude; 75 | } 76 | 77 | GetAccuracy() 78 | { 79 | const value = this.GetValue(); 80 | return Math.max(parseFloat(value.hpa), parseFloat(value.vpa)); 81 | } 82 | }; -------------------------------------------------------------------------------- /modules/at/at_cpin.js: -------------------------------------------------------------------------------- 1 | let AT_CPIN = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Enter/Read PIN", 11 | example: "+CPIN: READY", 12 | cmd: "AT+CPIN", 13 | timeout: 5000, 14 | doc: "3.2.11" 15 | });// true, true, false, true, "Enter/Read PIN", "+CPIN: READY", "AT+CPIN", 5000); 16 | //this.STATES = ["UNKNOWN", "READY", "SIM PIN", "SIM PUK", "PH_SIM PIN", "PH_SIM PUK", "PH_NET PIN", "SIM PIN2", "SIM PUK2"]; 17 | let enumS = []; 18 | enumS.push(new ATEnum("UNKNOWN", "Unknown State")); 19 | enumS.push(new ATEnum("READY", "MT is not pending for any password")); 20 | enumS.push(new ATEnum("SIM PIN", "MT is waiting SIM PIN to be given")); 21 | enumS.push(new ATEnum("SIM PUK", "MT is waiting for SIM PUK to be given")); 22 | enumS.push(new ATEnum("PH_SIM PIN", "ME is waiting for phone to SIM card (antitheft)")); 23 | enumS.push(new ATEnum("PH_SIM PUK", "ME is waiting for SIM PUK (antitheft)")); 24 | enumS.push(new ATEnum("PH_NET PIN", "ME is waiting network personalization password to be given")); 25 | enumS.push(new ATEnum("SIM PIN2", "PIN2")); 26 | enumS.push(new ATEnum("SIM PUK2", "PUK2")); 27 | 28 | this.AddParam("code", enumS, "code"); 29 | this.AddParam("pin", "string", "pin"); 30 | this.AddParam("newpin", "string", "newpin"); 31 | 32 | this.AddReadAnswerParam({code:null}); 33 | 34 | this.AddWriteSendParam({pin:null}); 35 | this.AddWriteSendParam({pin:null, newpin:null}); 36 | 37 | this.AddUnsolicitedAnswerParam({code:null}); 38 | } 39 | 40 | ShowChat(div) 41 | { 42 | super.ShowChat(div); 43 | 44 | const value = this.GetValue(); 45 | 46 | if(this.GetRequestType() == "read") 47 | { 48 | _CN("span", {}, [this.GetParam("code").GetValue(value.code)?.GetDescription()], div); 49 | } 50 | } 51 | 52 | GetState() 53 | { 54 | const value = this.GetValue(); 55 | 56 | return value.code??"INVALID"; 57 | } 58 | 59 | IsReady() 60 | { 61 | return this.GetState() == "READY"; 62 | } 63 | }; 64 | 65 | let _CPIN = new class extends ATBase 66 | { 67 | constructor() 68 | { 69 | super({ 70 | description: "SIMCARD Report (see AT+CURCCFG)", 71 | example: "+CPIN: READY", 72 | cmd: "+CPIN", 73 | doc: "5.2.49" 74 | }); 75 | 76 | let enumCode = []; 77 | enumCode.push(new ATEnum("READY", "not pending for any pass")); 78 | enumCode.push(new ATEnum("SIM PIN", "waiting SIM PIN")); 79 | enumCode.push(new ATEnum("SIM PUK", "waiting SIM PUK")); 80 | enumCode.push(new ATEnum("PH_SIM PIN", "Antiheft SIM")); 81 | enumCode.push(new ATEnum("PH_SIM PUK", "Antiheft PUK")); 82 | enumCode.push(new ATEnum("PH_NET PIN", "Password personalisation")); 83 | enumCode.push(new ATEnum("SIM PIN2", "wait for PIN2")); 84 | enumCode.push(new ATEnum("SIM PUK2", "wait for PUK2")); 85 | this.AddParam("code", enumCode, "Code"); 86 | 87 | this.AddUnsolicitedAnswerParam({code:null}); 88 | } 89 | 90 | Parse(str) 91 | { 92 | super.Parse(str); 93 | AT_CPIN.Parse(str); 94 | } 95 | }; -------------------------------------------------------------------------------- /modules/at/at_csslcfg.js: -------------------------------------------------------------------------------- 1 | let AT_CSSLCFG = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "Configure SSL Parameters of a Context Identifier", 11 | cmd: "AT+CSSLCFG", 12 | doc: "11.2.1" 13 | }); //true, true, false, false, "Configure SSL Parameters of a Context Identifier", "", "AT+CSSLCFG", 1000); 14 | 15 | let enumC = []; 16 | enumC.push(new ATEnum("SSLVERSION", "SSLVERSION")); 17 | enumC.push(new ATEnum("CIPHERSUITE", "CIPHERSUITE")); 18 | enumC.push(new ATEnum("IGNORERTCTIME", "IGNORERTCTIME")); 19 | enumC.push(new ATEnum("PROTOCOL", "PROTOCOL")); 20 | enumC.push(new ATEnum("SNI", "SNI")); 21 | enumC.push(new ATEnum("CTXINDEX", "CTXINDEX")); 22 | enumC.push(new ATEnum("MAXFRAGLENDISABLE", "MAXFRAGLENDISABLE")); 23 | enumC.push(new ATEnum("CONVERT", "CONVERT")); 24 | enumC.push(new ATEnum("CERTDISABLE", "CERTDISABLE")); 25 | 26 | let enumI = []; 27 | enumI.push(new ATEnum(0, "index 0")); 28 | enumI.push(new ATEnum(1, "index 1")); 29 | enumI.push(new ATEnum(2, "index 2")); 30 | enumI.push(new ATEnum(3, "index 3")); 31 | enumI.push(new ATEnum(4, "index 4")); 32 | enumI.push(new ATEnum(5, "index 5")); 33 | 34 | let enumS = []; 35 | enumS.push(new ATEnum(0, "QAPI_NET_SSL_PROTOCOL_UNKNOWN")); 36 | enumS.push(new ATEnum(1, "QAPI_NET_SSL_PROTOCOL_TLS_1_0")); 37 | enumS.push(new ATEnum(2, "QAPI_NET_SSL_PROTOCOL_TLS_1_1")); 38 | enumS.push(new ATEnum(3, "QAPI_NET_SSL_PROTOCOL_TLS_1_2")); 39 | enumS.push(new ATEnum(4, "QAPI_NET_SSL_PROTOCOL_DTLS_1_0")); 40 | enumS.push(new ATEnum(5, "QAPI_NET_SSL_PROTOCOL_DTLS_1_2")); 41 | enumS.push(new ATEnum(6, "QAPI_NET_SSL_PROTOCOL_TLS_1_3")); 42 | 43 | let enumP = []; 44 | enumP.push(new ATEnum(1, "QAPI_NET_SSL_TLS_E")); 45 | enumP.push(new ATEnum(2, "QAPI_NET_SSL_DTLS_E")); 46 | 47 | let enumST = []; 48 | enumST.push(new ATEnum(1, "QAPI_NET_SSL_CERTIFICATE_E")); 49 | enumST.push(new ATEnum(2, "QAPI_NET_SSL_CA_LIST_E")); 50 | enumST.push(new ATEnum(3, "QAPI_NET_SSL_PSK_TABLE_E")); 51 | 52 | this.AddParam("context", enumC, "context"); 53 | this.AddParam("ctxindex", enumI, "context identifier"); 54 | this.AddParam("sslversion", enumS, "ssl version"); 55 | this.AddParam("protocol", enumP, "protocol"); 56 | this.AddParam("ssltype", enumST, "ssl type"); 57 | this.AddParam("cname", "string", "cname"); 58 | this.AddParam("keyname", "string", "key name"); 59 | this.AddParam("passkey", "string", "pass key"); 60 | this.AddParam("servername", "string", "servername"); 61 | 62 | this.AddWriteSendParam({context:"SSLVERSION", ctxindex:null, sslversion:null}); 63 | this.AddWriteSendParam({context:"PROTOCOL", ctxindex:null, protocol:null}); 64 | this.AddWriteSendParam({context:"CONVERT", ssltype:null, cname:null}); 65 | this.AddWriteSendParam({context:"CONVERT", ssltype:null, cname:null, keyname:null}); 66 | this.AddWriteSendParam({context:"CONVERT", ssltype:null, cname:null, keyname:null, passkey:null}); 67 | this.AddWriteSendParam({context:"SNI", ctxindex:null, servername:null}); 68 | 69 | 70 | } 71 | 72 | }; -------------------------------------------------------------------------------- /css/page.css: -------------------------------------------------------------------------------- 1 | html 2 | { 3 | width: 100%; 4 | height: 100%; 5 | } 6 | 7 | body 8 | { 9 | width: 100%; 10 | height: 100%; 11 | overflow: hidden; 12 | margin: 0px; 13 | background: radial-gradient(#fff, #bbf); 14 | } 15 | 16 | button, select, input, textarea 17 | { 18 | margin:0 auto; 19 | background: linear-gradient(to bottom, #fff, #ffa); 20 | font-size: 110%; 21 | border-radius: 0.5vh; 22 | cursor: pointer; 23 | } 24 | 25 | select, input, textarea 26 | { 27 | background: linear-gradient(to bottom, #fff, #ffe); 28 | } 29 | 30 | textarea 31 | { 32 | font-size: 70%; 33 | } 34 | 35 | .box 36 | { 37 | padding: 0.5vh; 38 | width: 20vh; 39 | height: 10vh; 40 | background: linear-gradient(#fff, #aaa); 41 | position: absolute; 42 | left: 1vh; 43 | top: 1vh; 44 | border-style: outset; 45 | border-width: 2px; 46 | border-radius: 1vh; 47 | font-size: 1.5vh; 48 | } 49 | 50 | .box h2 51 | { 52 | width: 100%; 53 | margin: 0vh; 54 | margin-bottom: 1vh; 55 | font-family: monospace; 56 | font-size: 1.5vh; 57 | text-align: center; 58 | } 59 | 60 | .serialdiv 61 | { 62 | margin:0 auto; 63 | text-align: center; 64 | height: 8vh; 65 | } 66 | 67 | .infotab 68 | { 69 | width: 70vh; 70 | height: 10vh; 71 | left: 30vh; 72 | height: 8vh; 73 | } 74 | 75 | .github 76 | { 77 | width: 200px; 78 | height: 6vh; 79 | right: 15vh; 80 | left: unset !important; 81 | top: 2vh; 82 | opacity: 0.5; 83 | background: linear-gradient(#fff, #aaf); 84 | text-align: center; 85 | } 86 | 87 | .labelInfo 88 | { 89 | display: inline-block; 90 | width: 30vh; 91 | white-space: nowrap; 92 | text-overflow: ellipse; 93 | } 94 | 95 | .labelInfo label 96 | { 97 | display: inline-block; 98 | min-width: 15vh; 99 | } 100 | 101 | .labelInfo i 102 | { 103 | background-color: #aaa; 104 | } 105 | 106 | .simModule 107 | { 108 | position: absolute; 109 | right: 1vh; 110 | top: 1vh; 111 | width: 10vh; 112 | height: 10vh; 113 | background: url("../modules/sim.png"); 114 | background-repeat: no-repeat; 115 | background-size: contain; 116 | } 117 | 118 | .simModule span 119 | { 120 | position: absolute; 121 | top: 1.5vh; 122 | right: 1.5vh; 123 | font-size: 1vh; 124 | height: 1vh; 125 | font-weight: bold; 126 | } 127 | 128 | .paramdiv input, .paramdiv select 129 | { 130 | min-width: 50%; 131 | display: block; 132 | } 133 | 134 | .paramdiv textarea 135 | { 136 | width: 99%; 137 | } 138 | 139 | .pdfviewer 140 | { 141 | position: fixed; 142 | left: 50%; 143 | top: 50%; 144 | width: 76vmin; 145 | height: 100vmin; 146 | transform: translate(-50%, -50%); 147 | background: linear-gradient(to bottom, #eda, #fed, #eda); 148 | z-index: 1010; 149 | } 150 | 151 | .pdfviewer canvas 152 | { 153 | position: absolute; 154 | left: 1vmin; 155 | bottom: 1vmin; 156 | width: 69vmin; 157 | height: 98vmin; 158 | background-color: white; 159 | } 160 | 161 | .pdfviewer div 162 | { 163 | position: absolute; 164 | right: 1vmin; 165 | top: 1vmin; 166 | width: 4vmin; 167 | height: 20vmin; 168 | } 169 | 170 | .pdfviewer span 171 | { 172 | display: inline-block; 173 | width: 4vmin; 174 | height: 4vmin; 175 | font-size: 4vmin; 176 | line-height: 4vmin; 177 | text-align: center; 178 | cursor: pointer; 179 | border-radius: 1vmin; 180 | margin-top: 2vmin; 181 | } 182 | 183 | .pdfviewer span:hover 184 | { 185 | background-color: #ffa; 186 | } -------------------------------------------------------------------------------- /modules/at/at_cpsi.js: -------------------------------------------------------------------------------- 1 | let AT_CPSI = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | test: true, 9 | description: "Inquiring UE System Information", 10 | example: "+CPSI: LTE NB-IOT,Online,460-11,0x5AE1,187212754,82, EUTRAN-BAND5,2506,0,0,-7,-115,-110,13", 11 | cmd: "AT+CPSI", 12 | doc: "5.2.19" 13 | }); //true, false, false, true, "Inquiring UE System Information", "+CPSI: LTE NB-IOT,Online,460-11,0x5AE1,187212754,82, EUTRAN-BAND5,2506,0,0,-7,-115,-110,13", "AT+CPSI", 1000); 14 | 15 | let enumSMode = []; 16 | enumSMode.push(new ATEnum("no service", "NO SERVICE")); 17 | enumSMode.push(new ATEnum("gsm", "GSM")); 18 | enumSMode.push(new ATEnum("lte cat-m1", "LTE CAT-M1")); 19 | enumSMode.push(new ATEnum("lte nb-iot", "LTE NB-IOT")); 20 | 21 | let enumOMode = []; 22 | enumOMode.push(new ATEnum("online", "Online")); 23 | enumOMode.push(new ATEnum("offline", "Offline")); 24 | enumOMode.push(new ATEnum("factory test mode", "Factory Test Mode")); 25 | enumOMode.push(new ATEnum("reset", "Reset")); 26 | enumOMode.push(new ATEnum("low power mode", "Low Power Mode")); 27 | 28 | this.AddParam("systemmode", enumSMode, "system mode"); 29 | this.AddParam("operationmode", enumOMode, "UE operation mode"); 30 | this.AddParam("mccmnc", "string", "MCC-MNC"); 31 | 32 | // If LTE 33 | this.AddParam("tac", "string", "Tracing Area Code"); 34 | this.AddParam("scellid", "string", "Serving Cell ID"); 35 | this.AddParam("pcellid", "string", "Physical Cell ID"); 36 | this.AddParam("frequencyband", "string", "Frequency Band of active set"); 37 | this.AddParam("earfcn", "string", "E-UTRA absolute radio frequency channel number for searching"); 38 | this.AddParam("dlbw", "string", "Transmission bandwidth configuration of the serving cell on the downlink"); 39 | this.AddParam("ulbw", "string", "Transmission bandwidth configuration of the serving cell on the uplink"); 40 | this.AddParam("rsrp", "string", "Current reference signal power"); 41 | this.AddParam("rsrq", "string", "Current reference signal receive quality"); 42 | this.AddParam("rssi", "string", " Current Received signal strength indicator"); 43 | this.AddParam("rssnr", "string", "Average reference signal signal-to-noise ratio"); 44 | 45 | // If GSM 46 | this.AddParam("lac", "string", "Local Area Code"); 47 | this.AddParam("cellid", "string", "Cell ID"); 48 | this.AddParam("absoluterfchnum", "string", "AFRCN for service cell"); 49 | this.AddParam("trackloadjust", "string", "Track LO Adjust"); 50 | this.AddParam("c1", "string", "Coefficient for base station selection"); 51 | this.AddParam("c2", "string", "Coefficient for Cell re-selection"); 52 | 53 | this.AddReadAnswerParam({systemmode:"gsm", operationmode:null, lac:null, cellid:null, absoluterfchnum:null, trackloadjust:null, c1:null, c2:null}); 54 | this.AddReadAnswerParam({systemmode:null, operationmode:null, mccmnc:null, tac:null, scellid:null, pcellid:null, frequencyband:null, earfcn:null, dlbw:null, ulbw:null, rsrp:null, rsrq:null, rssi:null, rssnr:null}); 55 | } 56 | 57 | ShowChat(div) 58 | { 59 | super.ShowChat(div); 60 | 61 | const value = this.GetValue(); 62 | 63 | if(this.GetRequestType() == "read") 64 | { 65 | Object.keys(value).forEach(k=>{ 66 | _CN("span", {}, [k + ": " + value[k]], div); 67 | }); 68 | } 69 | } 70 | }; -------------------------------------------------------------------------------- /js/pdf.js: -------------------------------------------------------------------------------- 1 | let PDFManual = new class 2 | { 3 | #div = null; 4 | #canvas = null; 5 | #menu = null; 6 | #chapters = []; 7 | 8 | #pdf = null; 9 | #currentPage = 1; 10 | 11 | pdfFile = null; 12 | 13 | constructor() 14 | { 15 | _CN("script", {src:'//mozilla.github.io/pdf.js/build/pdf.mjs', type:'module', async:true}, [], document.head); 16 | 17 | let ipdf = setInterval(()=>{ 18 | if(pdfjsLib && pdfjsLib.GlobalWorkerOptions) 19 | { 20 | clearInterval(ipdf); 21 | pdfjsLib.GlobalWorkerOptions.workerSrc = "//mozilla.github.io/pdf.js/build/pdf.worker.mjs"; 22 | } 23 | }, 1000); 24 | 25 | this.#canvas = _CN("canvas", {width:840, height:1188}); 26 | this.#menu = _CN("div"); 27 | this.#div = _CN("div", {class:'pdfviewer', style:"display:none"}, [this.#canvas, this.#menu], document.body); 28 | 29 | setTimeout(()=>{ 30 | this.#createMenu(); 31 | }, 500); 32 | } 33 | 34 | LoadPDF(pdf) 35 | { 36 | this.pdfFile = pdf; 37 | let pdft = pdfjsLib.getDocument(pdf); 38 | 39 | pdft.promise.then(async(pdf)=>{ 40 | this.#pdf = pdf; 41 | 42 | pdf.getOutline().then(outline=>{ 43 | console.log(outline); 44 | this.#LoadChapters(outline); 45 | console.log(this.#chapters); 46 | // 1.4.4 = '[{"num":898,"gen:0},{"name":"XYZ"},85.6,672.2,0]' 47 | }); 48 | }); 49 | } 50 | 51 | OpenChapter(ch) 52 | { 53 | this.#div.style.display = "block"; 54 | 55 | this.#pdf.getPageIndex(ch.dest[0]).then(async (searchpage)=>{ 56 | console.log("FOUND DESTINATION!", ch, searchpage); 57 | 58 | this.#currentPage = parseInt(searchpage) + 1; 59 | 60 | this.#DrawPage(); 61 | }); 62 | } 63 | 64 | GetChapterPage(ch, f) 65 | { 66 | this.#pdf.getPageIndex(ch.dest[0]).then(sp=>{ 67 | f(sp); 68 | }); 69 | } 70 | 71 | async #DrawPage() 72 | { 73 | let pdfpage = await this.#pdf.getPage(this.#currentPage); 74 | 75 | const viewport = pdfpage.getViewport({scale: 2}); 76 | const context = this.#canvas.getContext('2d'); 77 | 78 | this.#canvas.width = viewport.width; 79 | this.#canvas.height = viewport.height; 80 | 81 | const renderContext = { 82 | canvasContext: context, 83 | viewport: viewport, 84 | }; 85 | 86 | await pdfpage.render(renderContext); 87 | this.#canvas.style.display = "block"; 88 | } 89 | 90 | GetChapter(ch) 91 | { 92 | let ret = null; 93 | this.#chapters.forEach(c=>{ 94 | if(c.c == ch) ret = c; 95 | }); 96 | return ret; 97 | } 98 | 99 | #LoadChapters(outline) 100 | { 101 | for(let j=0;j{ 124 | this.#div.style.display = "none"; 125 | this.#canvas.style.display = "none"; 126 | }); 127 | 128 | next.addEventListener("click", ()=>{ 129 | this.#currentPage++; 130 | this.#DrawPage(); 131 | }); 132 | 133 | prev.addEventListener("click", ()=>{ 134 | if(this.#currentPage > 1) 135 | { 136 | this.#currentPage--; 137 | this.#DrawPage(); 138 | } 139 | }); 140 | } 141 | }; -------------------------------------------------------------------------------- /js/tabs.js: -------------------------------------------------------------------------------- 1 | const Tabs = new class 2 | { 3 | #tabs = []; 4 | #div; 5 | #tabManual = null; 6 | #tabPos = {left:2, top:4.5, W:9.5, T:0, offsetX:9.7, offsetY:-2.5, zIndex:100}; 7 | 8 | constructor() 9 | { 10 | window.addEventListener("serialactive", (data)=>{ 11 | if(!this.#div) return; 12 | 13 | if(data.detail) 14 | { 15 | this.#div.style.pointerEvents = "inherit"; 16 | this.#div.style.opacity = 1.0; 17 | } 18 | else 19 | { 20 | this.#div.style.pointerEvents = "none"; 21 | this.#div.style.opacity = 0.5; 22 | } 23 | }); 24 | } 25 | 26 | GetDiv() 27 | { 28 | return this.#div; 29 | } 30 | 31 | Load() 32 | { 33 | this.#div = _CN("div", {class:"box tabs", style:"border-style:none;background:transparent;"}, [], document.body); 34 | 35 | let scripts = [ 36 | {name:"tabModule"}, 37 | {name:"tabCommands"}, 38 | {name:"tabSim"}, 39 | {name:"tabCoap"}, 40 | {name:"tabHttps"}, 41 | {name:"tabTcpUdp"}, 42 | {name:"tabSms"}, 43 | {name:"tabGnss"}, 44 | {name:"tabManual"} 45 | ]; 46 | 47 | this.#tabManual = scripts.length - 1; 48 | 49 | let scriptsTotLoaded = 0; 50 | let scriptsLoading = false; 51 | let scriptLoading = setInterval(()=>{ 52 | if(!scriptsLoading) 53 | { 54 | scriptsLoading = true; 55 | let s = _CN("script", {src:"js/" + scripts[scriptsTotLoaded].name + ".js?v=55" + parseInt(new Date().getTime() / 5000)}, [], document.head); 56 | s.addEventListener("load", ()=>{ 57 | scriptsLoading = false; 58 | if(++scriptsTotLoaded >= scripts.length) clearInterval(scriptLoading); 59 | }) 60 | } 61 | }, 100); 62 | } 63 | 64 | AddTab(tabClass) 65 | { 66 | //#tabPos = {left:2, top:4.5, W:9.5, T:0, offsetX:9.7, offsetY:-2, zIndex:100}; 67 | 68 | let sel = _CN("div", {class:"tabselect"}, [tabClass.Title], this.#div); 69 | sel.style.left = this.#tabPos.left + "vw"; 70 | sel.style.top = this.#tabPos.top + "vh"; 71 | sel.style.zIndex = this.#tabPos.zIndex; 72 | 73 | this.#tabs.push({sel: sel, tab: tabClass}); 74 | 75 | const j = 100 - this.#tabPos.zIndex; 76 | this.#tabPos.left += this.#tabPos.offsetX; 77 | this.#tabPos.zIndex--; 78 | if(this.#tabPos.left > 34) 79 | { 80 | this.#tabPos.T++; 81 | this.#tabPos.left = 2 + (this.#tabPos.T % 2) * (this.#tabPos.W * 0.5); 82 | this.#tabPos.top += this.#tabPos.offsetY; 83 | } 84 | 85 | if(j == 0) 86 | { 87 | sel.style.background = "#eff"; 88 | } 89 | else 90 | { 91 | tabClass.div.style.display = "none"; 92 | } 93 | 94 | sel.addEventListener("click", ()=>{ 95 | this.#SelectTab(j); 96 | }); 97 | } 98 | 99 | OpenManualTab() 100 | { 101 | this.#SelectTab(this.#tabManual); 102 | } 103 | 104 | #SelectTab(index) 105 | { 106 | this.#tabs.forEach((t)=>{ 107 | t.sel.style.background = null; 108 | t.tab.div.style.display = "none"; 109 | }); 110 | 111 | this.#tabs[index].sel.style.background = "#eff"; 112 | this.#tabs[index].tab.div.style.display = "block"; 113 | 114 | this.#tabs[index].tab.Select(); 115 | } 116 | 117 | AddCmd(text, cmd, cmdObj) 118 | { 119 | const regex = /\s*\(.*\)/g; 120 | let title = text.replace(regex, ""); 121 | if(cmdObj) 122 | { 123 | title = cmdObj.GetDescription(); 124 | title += " [" + cmdObj?.GetCmd() + "]"; 125 | } 126 | const found = text.match(regex); 127 | let butt = _CN("button", {}, ["?"]); 128 | let div = _CN("div", {class:"singlecmd", title:title}, [_CN("span", {}, [text.replace(regex, ""), found?_CN("sup",{}, [found[0]]):""]), butt]); 129 | butt.addEventListener("click", ()=>{ 130 | cmd(); 131 | }); 132 | 133 | return div; 134 | } 135 | 136 | }; 137 | -------------------------------------------------------------------------------- /modules/at/at_caserver.js: -------------------------------------------------------------------------------- 1 | let AT_CASERVER = new class extends ATBase 2 | { 3 | #cid = 0; 4 | #result = 0; 5 | 6 | constructor() 7 | { 8 | //read, write, exe, test, description, example, cmd, timeout) 9 | super({ 10 | write: true, 11 | read: true, 12 | test: true, 13 | description: "Open a TCP/UDP Server", 14 | example: "+CASERVER:(0-12),(0-4),(\"TCP\",\"TCP6\",\"UDP\",\"UDP6\"),(1-65535),(0,1)", 15 | cmd: "AT+CASERVER", 16 | doc: "12.2.4" 17 | }); 18 | 19 | let enumR = []; 20 | enumR.push(new ATEnum(0, "Read manually received data (+CARECV)")); 21 | enumR.push(new ATEnum(1, "Report received data (+CAURC)")); 22 | 23 | let enumConn = []; 24 | enumConn.push(new ATEnum("TCP", "TCP")); 25 | enumConn.push(new ATEnum("TCP6", "TCP6")); 26 | enumConn.push(new ATEnum("UDP", "UDP")); 27 | enumConn.push(new ATEnum("UDP6", "UDP6")); 28 | 29 | let enumId = []; 30 | for(var j=0;j<=12;j++) 31 | enumId.push(new ATEnum(j, "CID #" + j)); 32 | let enumPdp = []; 33 | for(var j=0;j<=4;j++) 34 | enumPdp.push(new ATEnum(j, "PDP #" + j)); 35 | 36 | 37 | this.AddParam("cid", enumId, "Command identifier"); 38 | this.AddParam("pdp_index", enumPdp, "PDP connection index"); 39 | this.AddParam("conn_type", enumConn, "Transfer type"); 40 | this.AddParam("port", "number", "Server port (1-65535)"); 41 | this.AddParam("result", "number", "Result code"); 42 | this.AddParam("recv_mode", enumR, "Receive mode"); 43 | 44 | this.AddWriteSendParam({cid:null, pdp_index:null, conn_type:null, port:null, recv_mode:null}); 45 | this.AddWriteSendParam({cid:null, pdp_index:null, conn_type:null, port:null}); 46 | 47 | this.AddWriteAnswerParam({cid:null, result:null}); 48 | 49 | this.AddReadAnswerParam({cid:null, pdp_index:null, conn_type:null, port:null, recv_mode:null}); 50 | } 51 | 52 | Parse(str) 53 | { 54 | super.Parse(str); 55 | 56 | this.GetLines().forEach(l=>{ 57 | if(this.value == "") this.value = l; 58 | if(l.trim().length >= 4) 59 | { 60 | const values = l.substring(this.GetCmd().length-1).trim().split(","); 61 | this.#cid = parseInt(values[0]); 62 | this.#result = parseInt(values[1]); 63 | } 64 | }); 65 | return this.value; 66 | } 67 | 68 | ShowChat(div) 69 | { 70 | super.ShowChat(div); 71 | 72 | this.GetLines().forEach(l=>{ 73 | if(l.trim().length > 1) 74 | { 75 | const values = l.substring(this.GetCmd().length-1).trim().split(","); 76 | if(values.length >= 2) 77 | { 78 | _CN("span", {}, ["cid: " + this.#cid], div); 79 | _CN("span", {}, ["result: " + this.#parseResult()], div); 80 | } 81 | } 82 | }); 83 | } 84 | 85 | #parseResult() 86 | { 87 | switch(this.#result) 88 | { 89 | case 0: return "Success"; 90 | case 1: return "Socket error"; 91 | case 2: return "No memory"; 92 | case 3: return "Connection limit"; 93 | case 4: return "Parameter invalid"; 94 | //case 5: 95 | case 6: return "Invalid IP address"; 96 | case 7: return "Unsupported function"; 97 | //case 8: return "Session type mismatch"; 98 | //case 9: return "Session closed but not released"; 99 | //case 10: return "Illegal operation"; 100 | //case 11: return "Unable to close socket"; 101 | case 12: return "Unable to bind port"; 102 | case 13: return "Unable to listen port"; 103 | //case 14-17: 104 | //case 18: return "Connect failed"; 105 | //case 19: 106 | case 20: return "Unable to resolve host"; 107 | case 21: return "Network not active"; 108 | //case 22: 109 | case 23: return "Remote refuse"; 110 | case 24: return "Certificate time expired"; 111 | case 25: return "Certificate common name mismatch"; 112 | case 26: return "Certificate common name mismatch and time expired"; 113 | case 27: return "SSL connection failed"; 114 | 115 | default: return "Unknown result"; 116 | } 117 | } 118 | 119 | }; -------------------------------------------------------------------------------- /modules/at/at_caopen.js: -------------------------------------------------------------------------------- 1 | let AT_CAOPEN = new class extends ATBase 2 | { 3 | #cid = 0; 4 | #result = 0; 5 | 6 | constructor() 7 | { 8 | //read, write, exe, test, description, example, cmd, timeout) 9 | super({ 10 | write: true, 11 | read: true, 12 | exe: true, 13 | test: true, 14 | description: "Open a TCP/UDP Connection", 15 | example: "AT+CAOPEN:(0-12),(0-4),(\"TCP\",\"UDP\",\"NONIP\"),64,(1-65535),(0,1)", 16 | cmd: "AT+CAOPEN", 17 | doc: "12.2.3" 18 | }); 19 | 20 | let enumR = []; 21 | enumR.push(new ATEnum(0, "Read manually received data (+CARECV)")); 22 | enumR.push(new ATEnum(1, "Report received data (+CAURC)")); 23 | 24 | let enumConn = []; 25 | enumConn.push(new ATEnum("UDP", "UDP")); 26 | enumConn.push(new ATEnum("TCP", "TCP")); 27 | enumConn.push(new ATEnum("NONIP", "NONIP")); 28 | 29 | let enumId = []; 30 | for(var j=0;j<=12;j++) 31 | enumId.push(new ATEnum(j, "CID #" + j)); 32 | let enumPdp = []; 33 | for(var j=0;j<=4;j++) 34 | enumPdp.push(new ATEnum(j, "PDP #" + j)); 35 | 36 | 37 | this.AddParam("cid", enumId, "Command identifier"); 38 | this.AddParam("pdp_index", enumPdp, "PDP connection index"); 39 | this.AddParam("conn_type", enumConn, "Transfer type"); 40 | this.AddParam("server", "string", "Server name or IP"); 41 | this.AddParam("len_server", "number", "Max server name length"); 42 | this.AddParam("port", "number", "Server port (1-65535)"); 43 | this.AddParam("result", "number", "Result code"); 44 | this.AddParam("recv_mode", enumR, "Receive mode"); 45 | 46 | this.AddWriteSendParam({cid:null, pdp_index:null, conn_type:null, server:null, port:null, recv_mode:null}); 47 | this.AddWriteSendParam({cid:null, pdp_index:null, conn_type:null, server:null, port:null}); 48 | 49 | this.AddWriteAnswerParam({cid:null, result:null}); 50 | 51 | this.AddReadAnswerParam({cid:null, pdp_index:null, conn_type:null, server:null, port:null}); 52 | } 53 | 54 | Parse(str) 55 | { 56 | super.Parse(str); 57 | 58 | this.GetLines().forEach(l=>{ 59 | if(this.value == "") this.value = l; 60 | if(l.trim().length >= 4) 61 | { 62 | const values = l.substring(this.GetCmd().length-1).trim().split(","); 63 | this.#cid = parseInt(values[0]); 64 | this.#result = parseInt(values[1]); 65 | } 66 | }); 67 | return this.value; 68 | } 69 | 70 | ShowChat(div) 71 | { 72 | super.ShowChat(div); 73 | 74 | this.GetLines().forEach(l=>{ 75 | if(l.trim().length > 1) 76 | { 77 | const values = l.substring(this.GetCmd().length-1).trim().split(","); 78 | if(values.length >= 2) 79 | { 80 | _CN("span", {}, ["cid: " + this.#cid], div); 81 | _CN("span", {}, ["result: " + this.#parseResult()], div); 82 | } 83 | } 84 | }); 85 | } 86 | 87 | #parseResult() 88 | { 89 | switch(this.#result) 90 | { 91 | case 0: return "Success"; 92 | case 1: return "Socket error"; 93 | case 2: return "No memory"; 94 | case 3: return "Connection limit"; 95 | case 4: return "Parameter invalid"; 96 | //case 5: 97 | case 6: return "Invalid IP address"; 98 | case 7: return "Unsupported function"; 99 | case 8: return "Session type mismatch"; 100 | case 9: return "Session closed but not released"; 101 | case 10: return "Illegal operation"; 102 | case 11: return "Unable to close socket"; 103 | case 12: return "Unable to bind port"; 104 | case 13: return "Unable to listen port"; 105 | //case 14-17: 106 | case 18: return "Connect failed"; 107 | //case 19: 108 | case 20: return "Unable to resolve host"; 109 | case 21: return "Network not active"; 110 | //case 22: 111 | case 23: return "Remote refuse"; 112 | case 24: return "Certificate time expired"; 113 | case 25: return "Certificate common name mismatch"; 114 | case 26: return "Certificate common name mismatch and time expired"; 115 | case 27: return "SSL connection failed"; 116 | 117 | default: return "Unknown result"; 118 | } 119 | } 120 | 121 | }; -------------------------------------------------------------------------------- /modules/at/at_ccoapaction.js: -------------------------------------------------------------------------------- 1 | let AT_CCOAPACTION = new class extends ATBase 2 | { 3 | #packSize = 0; 4 | #payloadSize = 0; 5 | #coapReceived = false; 6 | 7 | constructor() 8 | { 9 | //read, write, exe, test, description, example, cmd, timeout) 10 | super({ 11 | write: true, 12 | exe: true, 13 | test: true, 14 | description: "Operate CoAP Object", 15 | example: "+CCOAPACTION: 0,1", 16 | cmd: "AT+CCOAPACTION", 17 | doc: "18.2.6" 18 | });//false, true, true, true, "Operate CoAP Object", "+CCOAPACTION: 0,1", "AT+CCOAPACTION", 1000); 19 | 20 | let enumT = []; 21 | enumT.push(new ATEnum(4, "Query current receiving queue information")); 22 | enumT.push(new ATEnum(5, "Clear the receive queue")); 23 | enumT.push(new ATEnum(6, "Reconnect and send packet")); 24 | 25 | let enumE = []; 26 | enumE.push(new ATEnum(0, "No errors")); 27 | enumE.push(new ATEnum(1, "receive queue is full")); 28 | enumE.push(new ATEnum(2, "mid CoAP response packet receives timeout")); 29 | enumE.push(new ATEnum(3, "CoAP socket error")); 30 | 31 | this.AddParam("type", enumT, "valid"); 32 | this.AddParam("num", "number", "packets numbers"); 33 | this.AddParam("mid", "number", "message id"); 34 | this.AddParam("errorcode", enumE, "errorcode"); 35 | 36 | this.AddWriteSendParam({type:null}); 37 | 38 | this.AddWriteAnswerParam({type:4, num:null, mid:null}); 39 | this.AddWriteAnswerParam({type:null}); 40 | 41 | this.AddExeAnswerParam({errorcode:null, mid:null}); 42 | } 43 | 44 | Execute() 45 | { 46 | this.#coapReceived = false; 47 | this.#packSize = -1; 48 | this.#payloadSize = -1; 49 | 50 | return super.Execute(); 51 | } 52 | 53 | HoldUp(str) 54 | { 55 | if(this.GetRequestType() == "exe") 56 | { 57 | return !this.#coapReceived; 58 | } 59 | return false; 60 | } 61 | 62 | ShowChat(div) 63 | { 64 | super.ShowChat(div); 65 | 66 | this.GetLines().forEach(l=>{ 67 | if(l.trim().length > 1) 68 | { 69 | //const p = this.GetParams(false); 70 | //_CN("span", {}, [l], div); 71 | 72 | const values = l.substring(this.GetCmd().length-1).trim().split(","); 73 | if(values.length >= 2) 74 | { 75 | _CN("span", {}, ["mid: " + this.GetMid()], div); 76 | if(this.GetRequestType() == "exe" && l.startsWith("+CCOAPRECV:")) 77 | { 78 | _CN("span", {}, ["pack size: " + this.#packSize], div); 79 | _CN("span", {}, ["payload size: " + this.#payloadSize], div); 80 | } 81 | } 82 | } 83 | }); 84 | } 85 | 86 | ShowChatDetail(div) 87 | { 88 | _CN("span", {}, ["mid: " + this.GetMid()], div); 89 | _CN("span", {}, ["pack size: " + this.#packSize], div); 90 | _CN("span", {}, ["payload size: " + this.#payloadSize], div); 91 | } 92 | 93 | GetMid() 94 | { 95 | const value = this.GetValue(); 96 | return value.mid; 97 | } 98 | 99 | SetPackSize(pack, payload) 100 | { 101 | this.#packSize = pack; 102 | this.#payloadSize = payload; 103 | this.#coapReceived = true; 104 | } 105 | 106 | IsCoapReceived() 107 | { 108 | return this.#coapReceived; 109 | } 110 | }; 111 | 112 | 113 | let _CCOAPRECV = new class extends ATBase 114 | { 115 | constructor() 116 | { 117 | super({ 118 | description: "COAPACTION Response", 119 | example: "+CCOAPRECV: 0,120,115", 120 | cmd: "+CCOAPRECV", 121 | doc: "18.2.6" 122 | }); 123 | 124 | this.AddParam("mid", "number", "message id"); 125 | this.AddParam("packsize", "number", "packet size"); 126 | this.AddParam("payloadsize", "number", "payload size"); 127 | 128 | this.AddUnsolicitedAnswerParam({mid:null, packsize:null, payloadsize:null}); 129 | } 130 | 131 | Parse(str) 132 | { 133 | super.Parse(str); 134 | 135 | const v = this.GetValue(); 136 | AT_CCOAPACTION.SetPackSize(v.packsize, v.payloadsize); 137 | 138 | // As this is not a normal command, emulate the OK 139 | super.Parse("OK"); 140 | } 141 | 142 | ShowChat(div) 143 | { 144 | super.ShowChat(div); 145 | 146 | AT_CCOAPACTION.ShowChatDetail(div); 147 | } 148 | }; -------------------------------------------------------------------------------- /js/tabGnss.js: -------------------------------------------------------------------------------- 1 | class TabGnss 2 | { 3 | 4 | Title = "GNSS"; 5 | #map = null; 6 | 7 | constructor() 8 | { 9 | this.div = _CN("div", {class:"box tab"}, [_CN("h2", {}, ["GNSS"])], Tabs.GetDiv()); 10 | this.isGnssPowered = null; 11 | this.#map = { 12 | key: "AkbDWYSRSMpeYuIJEI0dlS--dPnYpbeqUwjLR_fHg9sQY_nJOY3xcMzr606J0Pvv", 13 | script : null, 14 | div : null, 15 | map : null 16 | }; 17 | 18 | setTimeout(()=>{ 19 | this.Init(); 20 | 21 | window.addEventListener("serial", (data)=>{ 22 | if(data.detail.cmd?.GetCmd() == "AT+CGNSPWR") 23 | { 24 | if(data.detail.cmd.GetRequestType() == "read") 25 | { 26 | this.isGnssPowered = AT_CGNSPWR.IsPowered(); 27 | } 28 | if(this.#map.script == null) 29 | { 30 | this.#GenerateMap(); 31 | } 32 | } 33 | else if(data.detail.cmd?.GetCmd() == "AT+CGNSINF") 34 | { 35 | if(this.isGnssPowered && data.detail.cmd.GetRequestType() == "exe") 36 | { 37 | this.#GenerateMap(AT_CGNSINF.GetLatitude(), AT_CGNSINF.GetLongitude(), AT_CGNSINF.GetAccuracy()); 38 | console.log(this.#map.map.layers); 39 | } 40 | } 41 | }); 42 | }, 200); 43 | } 44 | 45 | Init() 46 | { 47 | //this.div.appendChild(Settings.GetGroupDiv("apn")); 48 | //this.div.appendChild(Settings.GetGroupDiv("ssl")); 49 | 50 | this.div.appendChild( 51 | Tabs.AddCmd( 52 | "GET Power Mode", 53 | ()=>{ 54 | AT_CGNSPWR.Read().then(()=>{}); 55 | }, 56 | AT_CGNSPWR) 57 | ); 58 | 59 | _CN("br", {}, [], this.div); 60 | 61 | _CN("button", {style:"margin:1vh;"}, ["POWER ON GNSS"], this.div).addEventListener("click", ()=>{ 62 | AT_CGNSPWR.Write([1]); 63 | }); 64 | 65 | _CN("button", {style:"margin:1vh;"}, ["POWER OFF GNSS"], this.div).addEventListener("click", ()=>{ 66 | AT_CGNSPWR.Write([0]); 67 | }); 68 | 69 | _CN("br", {}, [], this.div); 70 | 71 | _CN("button", {style:"margin:1vh;"}, ["GET GNSS INFO"], this.div).addEventListener("click", ()=>{ 72 | AT_CGNSINF.Execute(); 73 | }); 74 | 75 | } 76 | 77 | Select() 78 | { 79 | if(this.isGnssPowered == null) 80 | { 81 | AT_CGNSPWR.Read(); 82 | } 83 | } 84 | 85 | #GenerateMap(lat, long, acc) 86 | { 87 | if(this.#map.script == null) 88 | { 89 | const bingKey = this.#map.key; 90 | this.#map.div = _CN("div", {id:"myMap", style:"position:relative;width:100%;height:30vh;background-color:gray;"}, [], this.div); 91 | this.#map.script = _CN("script", {src:`https://www.bing.com/api/maps/mapcontrol?key=${bingKey}`}, [], document.body); 92 | return; 93 | } 94 | 95 | let center = new Microsoft.Maps.Location(lat, long); 96 | let zoom = 11; 97 | if(acc < 1000) zoom++; 98 | if(acc < 500) zoom++; 99 | if(acc < 100) zoom++; 100 | if(acc < 50) zoom++; 101 | 102 | this.#map.map = new Microsoft.Maps.Map(this.#map.div, { 103 | center: center, 104 | zoom: zoom 105 | }); 106 | 107 | Microsoft.Maps.loadModule(['Microsoft.Maps.SpatialMath', 'Microsoft.Maps.Contour'], () => { 108 | this.#GenerateCircle(center, acc); 109 | }); 110 | } 111 | 112 | #GenerateCircle(center, accuracy) 113 | { 114 | var locs = Microsoft.Maps.SpatialMath.getRegularPolygon(center, accuracy, 36, Microsoft.Maps.SpatialMath.DistanceUnits.Meters); 115 | let circle1 = new Microsoft.Maps.ContourLine(locs, 'rgba(0,0,150,0.5)'); 116 | 117 | var layer = new Microsoft.Maps.ContourLayer([circle1], { 118 | colorCallback: function (val) { 119 | return val; 120 | }, 121 | polygonOptions: { 122 | strokeThickness: 0 123 | } 124 | }); 125 | 126 | var pushpin = new Microsoft.Maps.Pushpin(center, { title: "+/- " + accuracy + ' meters' }); 127 | layer.add(pushpin); 128 | 129 | this.#map.map.layers.insert(layer); 130 | } 131 | 132 | 133 | #Error(msg, e, o = {}) 134 | { 135 | console.error("GNSS ERROR", e); 136 | const event = new CustomEvent("cominfo", { detail: {error:msg, event:e} }); 137 | window.dispatchEvent(event); 138 | 139 | } 140 | 141 | } 142 | 143 | Tabs.AddTab(new TabGnss()); -------------------------------------------------------------------------------- /js/settings.js: -------------------------------------------------------------------------------- 1 | let Settings = new class 2 | { 3 | #basename = "gsm_"; 4 | #group = []; 5 | #idle = false; 6 | constructor() 7 | { 8 | this.#group.push({name:"apn", info:"APN", options:[{name:"url", type:"url", info:"Url", value:""}]}); 9 | this.#group.push({name:"coap", info:"COAP", options:[{name:"url", type:"url", info:"Url", value:""}]}); 10 | this.#group.push({name:"ssl", info:"SSL Certificate", options:[{name:"cer", type:"text", info:"certificate", value:""}, {name:"name", type:"url", info:"Filename", value:""}]}); 11 | this.#group.push({name:"pin", info:"PINs", options:[{name:"pin", type:"number", info:"PIN 1", value:""}, {name:"puk", type:"number", info:"PUK", value:""}]}); 12 | } 13 | 14 | Init() 15 | { 16 | this.#group.forEach(g=>{ 17 | g.options.forEach(o=>{ 18 | let val = localStorage.getItem(this.#basename + g.name + "_" + o.name); 19 | if(val != null) o.value = val; 20 | }); 21 | }); 22 | } 23 | 24 | AutoSaveChanges(input) 25 | { 26 | if(!input.title) 27 | { 28 | console.error("no title for this imput", input); 29 | return; 30 | } 31 | const t = this.#basename + "_autosave_" + input.title; 32 | const v = localStorage.getItem(t); 33 | /*if(input?.tagName == "textarea") 34 | { 35 | if(v) input.textContent = v; 36 | input.addEventListener("change", ()=>{ 37 | localStorage.setItem(t, input.textContent); 38 | }); 39 | } 40 | else*/ 41 | { 42 | if(v) input.value = v; 43 | input.addEventListener("change", ()=>{ 44 | localStorage.setItem(t, input.value); 45 | 46 | // update current value 47 | this.#group.forEach(g=>{ 48 | g.options.forEach(o=>{ 49 | if(t == this.#basename + g.name + "_" + o.name) o.value = val; 50 | }); 51 | }); 52 | }); 53 | } 54 | } 55 | 56 | GetGroupDiv(name, div) 57 | { 58 | let sdiv = _CN("div", {class:"settingsgroup"}, [], div); 59 | let group = null; 60 | this.#group.forEach(g=>{if(g.name==name)group=g;}); 61 | if(group == null) 62 | { 63 | _CN("b", {}, ["Invalid group: " + name], sdiv); 64 | return sdiv; 65 | } 66 | _CN("h2", {}, [group.info + " settings"], sdiv); 67 | group.options.forEach(o=>{ 68 | const cla = this.#basename + group.name + "_" + o.name; 69 | if(o.type=="url" || o.type=="string" || o.type=="number") 70 | { 71 | _CN("label", {}, [o.info + ": "], sdiv); 72 | let i = _CN("input", {type:o.type=="number"?"number":(o.type=="url"?"url":"text"), value:o.value, class:cla}, [], sdiv); 73 | i.addEventListener("change", ()=>{ 74 | if(this.#idle) return; 75 | 76 | this.#idle = true; 77 | o.value = i.value; 78 | localStorage.setItem(cla, i.value); 79 | setTimeout(()=>{ 80 | [...document.getElementsByClassName(cla)].forEach((oc)=>{ 81 | oc.value = i.value; 82 | }); 83 | }, 10); 84 | setTimeout(()=>{this.#idle = false;}, 200); 85 | }); 86 | } 87 | else if(o.type=="text") 88 | { 89 | _CN("label", {}, [o.info + ": "], sdiv); 90 | let i = _CN("textarea", {class:cla, style:"width:80%", rows:4}, [o.value], sdiv); 91 | i.addEventListener("change", ()=>{ 92 | if(this.#idle) return; 93 | 94 | this.#idle = true; 95 | o.value = i.value; 96 | localStorage.setItem(cla, i.value); 97 | setTimeout(()=>{ 98 | [...document.getElementsByClassName(cla)].forEach((oc)=>{ 99 | oc.value = i.value; 100 | }); 101 | }, 10); 102 | setTimeout(()=>{this.#idle = false;}, 200); 103 | }); 104 | } 105 | _CN("br", {}, [], sdiv); 106 | }); 107 | 108 | return sdiv; 109 | } 110 | 111 | GetValue(p1, p2) 112 | { 113 | let ret = null; 114 | 115 | this.#group.forEach(g=>{ 116 | if(g.name==p1) 117 | { 118 | g.options.forEach(o=>{ 119 | if(o.name==p2) 120 | { 121 | ret = o.value; 122 | } 123 | }); 124 | } 125 | }); 126 | 127 | return ret; 128 | } 129 | }; 130 | 131 | window.addEventListener("load", ()=>{ 132 | setTimeout(()=>{ 133 | Settings.Init(); 134 | }, 1000); 135 | }); 136 | -------------------------------------------------------------------------------- /js/tabSim.js: -------------------------------------------------------------------------------- 1 | class TabSim 2 | { 3 | Title = "SIM"; 4 | #CheckpinButton = null; 5 | 6 | constructor() 7 | { 8 | this.div = _CN("div", {class:"box tab"}, [_CN("h2", {}, ["SIM"])], Tabs.GetDiv()); 9 | this.messageTextMode = null; 10 | this.phoneNr = null; 11 | this.msg = null; 12 | 13 | setTimeout(()=>{ 14 | this.Init(); 15 | 16 | }, 200); 17 | } 18 | 19 | Init() 20 | { 21 | this.#CheckpinButton = _CN("button", {style:"margin:1vh;"}, ["Check PIN"], this.div); 22 | this.#CheckpinButton.addEventListener("click", ()=>{ 23 | this.CheckPINState(); 24 | }); 25 | 26 | this.div.appendChild(Settings.GetGroupDiv("pin")); 27 | 28 | _CN("button", {style:"margin:1vh;"}, ["Enable PIN request"], this.div).addEventListener("click", (e)=>{ 29 | this.EnablePIN(); 30 | }); 31 | _CN("button", {style:"margin:1vh;"}, ["Disable PIN"], this.div).addEventListener("click", (e)=>{ 32 | this.DisablePIN(); 33 | }); 34 | _CN("button", {style:"margin:1vh;"}, ["Query PIN request"], this.div).addEventListener("click", (e)=>{ 35 | this.QueryPIN(); 36 | }); 37 | } 38 | 39 | Select() 40 | { 41 | 42 | } 43 | 44 | CheckPINState() 45 | { 46 | this.#CheckpinButton.textContent = "Checking PIN..."; 47 | AT_CPIN.Read().then(()=>{ 48 | if(AT_CPIN.IsReady()) 49 | { 50 | this.#CheckpinButton.textContent = "Check PIN ✅"; 51 | } 52 | else if(AT_CPIN.GetState() == "SIM PIN") 53 | { 54 | this.#CheckpinButton.textContent = "Checking 📌..."; 55 | AT_CPIN.Write([Settings.GetValue("pin", "pin")]).then(()=>{ 56 | this.#CheckpinButton.textContent = "Check PIN ✅ (PIN activated)"; 57 | }).catch((e)=>{ 58 | this.#CheckpinButton.textContent = "Check PIN ❌"; 59 | this.#Error("Wrong PIN", e); 60 | }); 61 | } 62 | }).catch((e)=>{ 63 | this.#CheckpinButton.textContent = "Check PIN ❌"; 64 | this.#Error("Unable to read PIN", e); 65 | }); 66 | } 67 | 68 | EnablePIN() 69 | { 70 | AT_CLCK.Write([`"SC"`, 2]).then(()=>{ 71 | if(AT_CLCK.GetValue().status == 1) 72 | { 73 | window.dispatchEvent(new CustomEvent("cominfo", { detail: {info:"Pin request is already active"} })); 74 | } 75 | else 76 | { 77 | const pin = Settings.GetValue("pin", "pin"); 78 | AT_CLCK.Write([`"SC"`, 1, `"${pin}"`]).then(()=>{ 79 | let info = "PIN activated successfully - device will be rebooted..."; 80 | window.dispatchEvent(new CustomEvent("cominfo", { detail: {info:info} })); 81 | setTimeout(()=>{ 82 | this.#Reboot(); 83 | }, 1000); 84 | }).catch((e)=>{ 85 | this.#Error("Unable to lock SIM", e); 86 | }); 87 | } 88 | }).catch((e)=>{ 89 | this.#Error("Unable to query SIM", e); 90 | }); 91 | } 92 | 93 | DisablePIN() 94 | { 95 | AT_CLCK.Write([`"SC"`, 2]).then(()=>{ 96 | if(AT_CLCK.GetValue().status == 0) 97 | { 98 | window.dispatchEvent(new CustomEvent("cominfo", { detail: {info:"Pin request is already inactive"} })); 99 | } 100 | else 101 | { 102 | const pin = Settings.GetValue("pin", "pin"); 103 | AT_CLCK.Write([`"SC"`, 0, `"${pin}"`]).then(()=>{ 104 | let info = "PIN deactivated successfully - device will be rebooted..."; 105 | window.dispatchEvent(new CustomEvent("cominfo", { detail: {info:info} })); 106 | setTimeout(()=>{ 107 | this.#Reboot(); 108 | }, 1000); 109 | }).catch((e)=>{ 110 | this.#Error("Unable to unlock SIM", e); 111 | }); 112 | } 113 | }).catch((e)=>{ 114 | this.#Error("Unable to query SIM", e); 115 | }); 116 | } 117 | 118 | #Reboot(requestPin = false) 119 | { 120 | let event = new CustomEvent("cominfo", { detail: {info:"no info"} }) 121 | ATScripts.Reboot().then(()=>{ 122 | setTimeout(()=>{ 123 | this.CheckPINState(); 124 | }, 500); 125 | }).catch(e=>{ 126 | this.#Error("Unable to reboot device", e); 127 | }); 128 | } 129 | 130 | QueryPIN() 131 | { 132 | AT_CLCK.Write([`"SC"`, 2]).then(()=>{ 133 | 134 | }).catch((e)=>{ 135 | this.#Error("Unable to query SIM", e); 136 | }); 137 | } 138 | 139 | #Error(msg, e, o = {}) 140 | { 141 | console.error("SIM ERROR", e | "unknown"); 142 | const event = new CustomEvent("cominfo", { detail: {error:msg, event:e} }); 143 | window.dispatchEvent(event); 144 | 145 | } 146 | 147 | } 148 | 149 | Tabs.AddTab(new TabSim()); -------------------------------------------------------------------------------- /css/chat.css: -------------------------------------------------------------------------------- 1 | .chat 2 | { 3 | width: 50vw; 4 | height: 82vh; 5 | background: linear-gradient(to bottom, #224, #001); 6 | left: unset; 7 | right: 1vh; 8 | top: unset; 9 | bottom: 3vh; 10 | color: springgreen; 11 | overflow-y: scroll; 12 | } 13 | 14 | .chat h2 15 | { 16 | position: sticky; 17 | } 18 | 19 | .chat input 20 | { 21 | position: fixed; 22 | width: 40vw; 23 | right: 5vw; 24 | bottom: 0.5vh; 25 | box-shadow: 0vh 0vh 1vh #fff; 26 | font-size: 2vh; 27 | text-align: center; 28 | border-radius: 1vh; 29 | opacity: 0.5; 30 | transition: all 0.5s ease-in-out; 31 | z-index: 900; 32 | } 33 | 34 | .chat input:hover 35 | { 36 | opacity: 1.0; 37 | background: #ff8; 38 | } 39 | 40 | .chat input:focus 41 | { 42 | opacity: 1.0; 43 | } 44 | 45 | .msg_g 46 | { 47 | position: relative; 48 | display: flow-root; 49 | width: 100%; 50 | min-height: 3vh; 51 | overflow: visible; 52 | vertical-align: bottom; 53 | } 54 | 55 | .msg_g i 56 | { 57 | margin-left: 1vh; 58 | color: #888; 59 | line-height: 2vh; 60 | } 61 | 62 | .msg_g b 63 | { 64 | margin-right: 2vh; 65 | float: right; 66 | cursor: pointer; 67 | opacity: 0.5; 68 | } 69 | 70 | .msg_g b:hover 71 | { 72 | opacity: 1.0; 73 | } 74 | 75 | .msg_g .msg_h, .msg_g .msg_a 76 | { 77 | display: inline-block; 78 | border-radius: 100%; 79 | width: 2vh; 80 | background: linear-gradient(to bottom, #66a, #448); 81 | text-align: center; 82 | color: #fff; 83 | cursor: pointer; 84 | } 85 | 86 | .msg_a 87 | { 88 | font-style: italic; 89 | float: right; 90 | } 91 | 92 | .msg_s 93 | { 94 | position: relative; 95 | display: inline-block; 96 | padding-left: 1vh; 97 | padding-right: 1vh; 98 | float: left; 99 | min-width: 10vh; 100 | border-radius: 1vh; 101 | border-top-left-radius: 0vh; 102 | border-color: #a85; 103 | background: linear-gradient(to bottom, #fff, #ffa); 104 | color: #44b; 105 | cursor: pointer; 106 | } 107 | 108 | .msg_r 109 | { 110 | position: relative; 111 | display: inline-block; 112 | padding-right: 1vh; 113 | padding-left: 2vh; 114 | float: right; 115 | min-width: 10vh; 116 | border-radius: 1vh; 117 | border-top-right-radius: 0vh; 118 | border-color: #a85; 119 | background: linear-gradient(to bottom, #fff, #afa); 120 | color: #008; 121 | text-align: right; 122 | } 123 | 124 | .msg_u 125 | { 126 | background: linear-gradient(to bottom, #fff, #edb) !important; 127 | } 128 | 129 | .msg_r span 130 | { 131 | display: block; 132 | } 133 | 134 | .msg_i 135 | { 136 | position: relative; 137 | display: inline-block; 138 | padding-right: 1vh; 139 | padding-left: 2vh; 140 | margin: 0 auto; 141 | min-width: 10vh; 142 | border-radius: 1vh; 143 | border-bottom-right-radius: 0vh; 144 | border-bottom-left-radius: 0vh; 145 | border-color: #a85; 146 | background: linear-gradient(to bottom, #bbb, #888); 147 | color: #008; 148 | text-align: center; 149 | } 150 | 151 | .msg_bubble 152 | { 153 | position: absolute; 154 | top: 0px; 155 | left: 0px; 156 | width: auto; 157 | min-width: 20vw; 158 | min-height: 8vh; 159 | background: linear-gradient(to bottom, #eef, #fff, #eef); 160 | border-radius: 1vh; 161 | border-style: solid; 162 | border-width: 1px; 163 | border-color: black; 164 | transform: translate(-90%, -80%); 165 | overflow: unset; 166 | margin:0 auto; 167 | box-shadow: 0.5vh 0.5vh 1vh #000; 168 | } 169 | 170 | .msg_bubble b 171 | { 172 | color: #000; 173 | opacity: 1.0; 174 | display: block; 175 | width: 100%; 176 | text-align: center; 177 | margin: 0.5vh 2vw; 178 | } 179 | 180 | .msg_bubble table 181 | { 182 | color: #000; 183 | width: 100%; 184 | margin: 0.5vh 0.1vw; 185 | } 186 | 187 | .msg_gauge 188 | { 189 | position: relative; 190 | display: block; 191 | width: 100%; 192 | height: 2vh; 193 | white-space: nowrap; 194 | font-size: 1.0vh; 195 | } 196 | 197 | .msg_gauge span 198 | { 199 | position: absolute; 200 | display: inline-block; 201 | line-height: 1.8vh; 202 | top: 0px; 203 | } 204 | 205 | .msg_gauge div 206 | { 207 | position: absolute; 208 | left:0px; 209 | top: 0.2vh; 210 | display: inline-block; 211 | width: 100%; 212 | height: 1.3vh; 213 | border-radius: 0.5vh; 214 | background: linear-gradient(to right, #f98, #ee0, #be6, #7d7); 215 | box-shadow: inset 2px 2px 2px #ffa, inset -2px -2px 2px #228; 216 | } 217 | 218 | .msg_gauge b 219 | { 220 | display: inline-block; 221 | position: absolute; 222 | left: 0px; 223 | top: 0px; 224 | height: 2.2vh; 225 | width: 2%; 226 | border-radius: 2px; 227 | margin-right: 0px; 228 | float: none; 229 | opacity: 1.0; 230 | background: linear-gradient(to bottom, #000, #880, #000); 231 | } -------------------------------------------------------------------------------- /modules/at/at_curccfg.js: -------------------------------------------------------------------------------- 1 | let AT_CURCCFG = new class extends ATBase 2 | { 3 | constructor() 4 | { 5 | //read, write, exe, test, description, example, cmd, timeout) 6 | super({ 7 | read: true, 8 | write: true, 9 | test: true, 10 | description: "URC Report Configuration", 11 | example: "+CURCCFG: \"QUALCOMM\",0", 12 | cmd: "AT+CURCCFG", 13 | doc: "5.2.49" 14 | }); 15 | 16 | let enumUrc = []; 17 | enumUrc.push(new ATEnum("QUALCOMM", "")); 18 | enumUrc.push(new ATEnum("SYS", "")); 19 | enumUrc.push(new ATEnum("SIMCARD", "")); 20 | enumUrc.push(new ATEnum("SMS", "")); 21 | enumUrc.push(new ATEnum("NETWORK", "")); 22 | enumUrc.push(new ATEnum("TCPIP", "")); 23 | enumUrc.push(new ATEnum("NIDD", "")); 24 | this.AddParam("urc_type", enumUrc, "mode"); 25 | 26 | let enumEn = []; 27 | enumEn.push(new ATEnum(0, "disabled")); 28 | enumEn.push(new ATEnum(1, "enabled")); 29 | this.AddParam("enable", enumEn, "enable"); 30 | 31 | this.AddWriteSendParam({urc_type:null, enable:null}); 32 | this.AddReadAnswerParam({urc_type:null, enable:null}); 33 | } 34 | }; 35 | 36 | let _QCIMGBOOTTYPE = new class extends ATBase 37 | { 38 | constructor() 39 | { 40 | super({ 41 | description: "QUALCOMM Report (see AT+CURCCFG)", 42 | example: "QCIMGBOOTTYPE : 1", 43 | cmd: "QCIMGBOOTTYPE", 44 | doc: "5.2.49" 45 | }); 46 | 47 | let enumBoot = []; 48 | enumBoot.push(new ATEnum(1, "Modem full image boot")); 49 | enumBoot.push(new ATEnum(2, "Modem page-only image boot")); 50 | this.AddParam("img_boot_type", enumBoot, "boot type"); 51 | 52 | this.AddUnsolicitedAnswerParam({img_boot_type:null}); 53 | } 54 | }; 55 | 56 | let _QCSRVCINFO = new class extends ATBase 57 | { 58 | constructor() 59 | { 60 | super({ 61 | description: "QUALCOMM Report (see AT+CURCCFG)", 62 | example: "QCSRVCINFO : 7,1", 63 | cmd: "QCSRVCINFO", 64 | doc: "5.2.49" 65 | }); 66 | 67 | let enumRat = []; 68 | enumRat.push(new ATEnum(0, "GSM")); 69 | enumRat.push(new ATEnum(7, "CAT-M")); 70 | enumRat.push(new ATEnum(9, "NB-IOT")); 71 | this.AddParam("rat_type", enumRat, "radio access technology"); 72 | 73 | let enumService = []; 74 | enumService.push(new ATEnum(0, "Not register network")); 75 | enumService.push(new ATEnum(1, "Register network")); 76 | this.AddParam("service_status", enumService, "network status"); 77 | 78 | this.AddUnsolicitedAnswerParam({rat_type:null, service_status:null}); 79 | } 80 | }; 81 | 82 | let _QCJDSTATE = new class extends ATBase 83 | { 84 | constructor() 85 | { 86 | super({ 87 | description: "QUALCOMM Report (see AT+CURCCFG)", 88 | example: "$QCJDSTATE : 9,1 0", 89 | cmd: "$QCJDSTATE", 90 | doc: "5.2.49" 91 | }); 92 | 93 | let enumRat = []; 94 | enumRat.push(new ATEnum(0, "GSM")); 95 | enumRat.push(new ATEnum(7, "CAT-M")); 96 | enumRat.push(new ATEnum(9, "NB-IOT")); 97 | this.AddParam("rat_type", enumRat, "radio access technology"); 98 | 99 | let enumJam = []; 100 | enumJam.push(new ATEnum("0 0", "Not Jamming")); 101 | enumJam.push(new ATEnum("0 1", "Soft Jamming")); 102 | enumJam.push(new ATEnum("1 0", "Jamming")); 103 | enumJam.push(new ATEnum("1 1", "Jamming")); 104 | enumJam.push(new ATEnum("2 0", "Unknown")); 105 | enumJam.push(new ATEnum("2 1", "Unknown Jamming")); 106 | this.AddParam("jamming_status", enumJam, "jamming status"); 107 | 108 | this.AddUnsolicitedAnswerParam({rat_type:null, jamming_status:null}); 109 | } 110 | }; 111 | 112 | 113 | let _RDY = new class extends ATBase 114 | { 115 | constructor() 116 | { 117 | super({ 118 | description: "SYS Report (see AT+CURCCFG)", 119 | example: "RDY", 120 | cmd: "RDY", 121 | doc: "5.2.49" 122 | }); 123 | } 124 | }; 125 | 126 | let _CFUN = new class extends ATBase 127 | { 128 | constructor() 129 | { 130 | super({ 131 | description: "SYS Report (see AT+CURCCFG)", 132 | example: "+CFUN: 1", 133 | cmd: "+CFUN", 134 | doc: "5.2.49" 135 | }); 136 | 137 | let enumFun = []; 138 | enumFun.push(new ATEnum(0, "Minimum functionality")); 139 | enumFun.push(new ATEnum(1, "Full functionality (Default)")); 140 | enumFun.push(new ATEnum(4, "Disable phone RF")); 141 | enumFun.push(new ATEnum(5, "Factory Test Mode")); 142 | enumFun.push(new ATEnum(6, "Reset")); 143 | enumFun.push(new ATEnum(7, "Offline Mode")); 144 | this.AddParam("fun", enumFun, "functionality"); 145 | 146 | this.AddUnsolicitedAnswerParam({fun:null}); 147 | } 148 | }; 149 | 150 | /* _CPIN is already set on AT+CPIN */ 151 | 152 | let _SMSREADY = new class extends ATBase 153 | { 154 | constructor() 155 | { 156 | super({ 157 | description: "SMS Report (see AT+CURCCFG)", 158 | example: "SMS Ready", 159 | cmd: "SMS Ready", 160 | doc: "5.2.49" 161 | }); 162 | } 163 | }; 164 | -------------------------------------------------------------------------------- /js/tabModule.js: -------------------------------------------------------------------------------- 1 | class TabModule 2 | { 3 | Title = "Module"; 4 | 5 | constructor() 6 | { 7 | this.div = _CN("div", {class:"box tab"}, [_CN("h2", {}, ["Module"])], Tabs.GetDiv()); 8 | 9 | setTimeout(()=>{ 10 | this.Init(); 11 | }, 200); 12 | } 13 | 14 | Init() 15 | { 16 | this.#InitGlobalInfo(); 17 | 18 | this.#InitNetworkInfo(); 19 | 20 | this.#InitModuleInfo(); 21 | 22 | } 23 | 24 | Select() 25 | { 26 | 27 | } 28 | 29 | #InitGlobalInfo() 30 | { 31 | _CN("h3", {}, ["Global Info"], this.div); 32 | 33 | this.div.appendChild( 34 | Tabs.AddCmd( 35 | "Product Id (ATI)", 36 | ()=>{ 37 | ATI.Execute().then(()=>{}); 38 | }, 39 | ATI) 40 | ); 41 | 42 | this.div.appendChild( 43 | Tabs.AddCmd( 44 | "Model Id (GMM)", 45 | ()=>{ 46 | AT_GMM.Execute().then(()=>{}); 47 | }, 48 | AT_GMM) 49 | ); 50 | 51 | this.div.appendChild( 52 | Tabs.AddCmd( 53 | "TA Revision (GMR)", 54 | ()=>{ 55 | AT_GMR.Execute().then(()=>{}); 56 | }, 57 | AT_GMR) 58 | ); 59 | 60 | this.div.appendChild( 61 | Tabs.AddCmd( 62 | "S/N Id (GSN)", 63 | ()=>{ 64 | AT_GSN.Execute().then(()=>{}); 65 | }, 66 | AT_GSN) 67 | ); 68 | 69 | this.div.appendChild( 70 | Tabs.AddCmd( 71 | "Mobile Subscriber (CIMI)", 72 | ()=>{ 73 | AT_CIMI.Execute().then(()=>{}); 74 | }, 75 | AT_CIMI) 76 | ); 77 | 78 | this.div.appendChild( 79 | Tabs.AddCmd( 80 | "Pin Status (CPIN)", 81 | ()=>{ 82 | AT_CPIN.Read().then(()=>{}); 83 | }, 84 | AT_CPIN) 85 | ); 86 | 87 | this.div.appendChild( 88 | Tabs.AddCmd( 89 | "Show ICCID (CCID)", 90 | ()=>{ 91 | AT_CCID.Execute().then(()=>{}); 92 | }, 93 | AT_CCID) 94 | ); 95 | } 96 | 97 | #InitNetworkInfo() 98 | { 99 | _CN("h3", {}, ["Network Info"], this.div); 100 | 101 | this.div.appendChild( 102 | Tabs.AddCmd( 103 | "Network Registration (CREG)", 104 | ()=>{ 105 | AT_CREG.Read().then(()=>{}); 106 | }, 107 | AT_CREG) 108 | ); 109 | 110 | this.div.appendChild( 111 | Tabs.AddCmd( 112 | "Signal Quality (CSQ)", 113 | ()=>{ 114 | AT_CSQ.Execute().then(()=>{}); 115 | }, 116 | AT_CSQ) 117 | ); 118 | 119 | this.div.appendChild( 120 | Tabs.AddCmd( 121 | "Mode Selection (CNMP)", 122 | ()=>{ 123 | AT_CNMP.Read().then(()=>{}); 124 | }, 125 | AT_CNMP) 126 | ); 127 | 128 | this.div.appendChild( 129 | Tabs.AddCmd( 130 | "CAT/NB Selection (CMNB)", 131 | ()=>{ 132 | AT_CMNB.Read().then(()=>{}); 133 | }, 134 | AT_CMNB) 135 | ); 136 | 137 | this.div.appendChild( 138 | Tabs.AddCmd( 139 | "Inquiring UE (CPSI)", 140 | ()=>{ 141 | AT_CPSI.Read().then(()=>{}); 142 | }, 143 | AT_CPSI) 144 | ); 145 | 146 | this.div.appendChild( 147 | Tabs.AddCmd( 148 | "GPRS Attachment (CGATT)", 149 | ()=>{ 150 | AT_CGATT.Read().then(()=>{}); 151 | }, 152 | AT_CGATT) 153 | ); 154 | 155 | this.div.appendChild( 156 | Tabs.AddCmd( 157 | "Operator Selection (COPS)", 158 | ()=>{ 159 | AT_COPS.Read().then(()=>{}); 160 | }, 161 | AT_COPS) 162 | ); 163 | 164 | this.div.appendChild( 165 | Tabs.AddCmd( 166 | "PDP Context (CGDCONT)", 167 | ()=>{ 168 | AT_CGDCONT.Read().then(()=>{}); 169 | }, 170 | AT_CGDCONT) 171 | ); 172 | 173 | this.div.appendChild( 174 | Tabs.AddCmd( 175 | "Band (CBANDCFG)", 176 | ()=>{ 177 | AT_CBANDCFG.Read().then(()=>{}); 178 | }, 179 | AT_CBANDCFG) 180 | ); 181 | } 182 | 183 | #InitModuleInfo() 184 | { 185 | _CN("h3", {}, ["Module Info"], this.div); 186 | 187 | this.div.appendChild( 188 | Tabs.AddCmd( 189 | "Phone Activity (CPAS)", 190 | ()=>{ 191 | AT_CPAS.Execute().then(()=>{}); 192 | }, 193 | AT_CPAS) 194 | ); 195 | 196 | this.div.appendChild( 197 | Tabs.AddCmd( 198 | "Battery Charge (CBC)", 199 | ()=>{ 200 | AT_CBC.Execute().then(()=>{}); 201 | }, 202 | AT_CBC) 203 | ); 204 | 205 | this.div.appendChild( 206 | Tabs.AddCmd( 207 | "Free Memory (CFSGFRS)", 208 | ()=>{ 209 | AT_CFSGFRS.Read().then(()=>{}); 210 | }, 211 | AT_CFSGFRS) 212 | ); 213 | 214 | this.div.appendChild( 215 | Tabs.AddCmd( 216 | "Get Clock (CCLK)", 217 | ()=>{ 218 | AT_CCLK.Read().then(()=>{}); 219 | }, 220 | AT_CCLK) 221 | ); 222 | 223 | this.div.appendChild( 224 | Tabs.AddCmd( 225 | "Report Configuration (CURCCFG)", 226 | ()=>{ 227 | AT_CURCCFG.Read().then(()=>{}); 228 | }, 229 | AT_CURCCFG) 230 | ); 231 | } 232 | }; 233 | 234 | Tabs.AddTab(new TabModule()); 235 | -------------------------------------------------------------------------------- /js/tabManual.js: -------------------------------------------------------------------------------- 1 | class TabManual 2 | { 3 | Title = "Manual"; 4 | 5 | constructor() 6 | { 7 | this.div = _CN("div", {class:"box tab manual"}, [_CN("h2", {}, ["Manual"])], Tabs.GetDiv()); 8 | 9 | _CN("p", {}, ["Press on 📃 to get more info about the command."], this.div); 10 | 11 | this.manual = _CN("div", {class:"manual"}, [], this.div); 12 | 13 | window.addEventListener("manual", (data)=>{ 14 | Tabs.OpenManualTab(); 15 | this.OpenTutorial(data.detail); 16 | }); 17 | } 18 | 19 | Init() 20 | { 21 | 22 | } 23 | 24 | OpenTutorial(cmd) 25 | { 26 | this.manual.innerHTML = ""; 27 | let manualDiv = _CN("div" ,{style:"opacity:0.4;transition:all 0.3s;"}, ["loading manual..."], this.manual); 28 | 29 | _CN("h1", {}, [cmd.GetCmd()], this.manual); 30 | 31 | let timeout = "-"; 32 | if(cmd.GetTimeout() > 1000) 33 | { 34 | timeout = (cmd.GetTimeout() / 1000) + "s"; 35 | } 36 | setTimeout(()=>{ 37 | let ch = PDFManual.GetChapter(cmd.GetDoc()); 38 | if(ch) 39 | { 40 | manualDiv.textContent = ""; 41 | _CN("span", {style:"cursor:pointer;color:#700;"}, [_CN("img", {src:"./modules/pdf.png", style:"height:18px;vertical-align:middle;"}), " View on SimCom manual"], manualDiv).addEventListener("click", ()=>{ 42 | PDFManual.OpenChapter(ch); 43 | }); 44 | _CN("span", {style:"padding:0px 10px;"}, [" - "], manualDiv); 45 | _CN("span", {style:"cursor:pointer;color:#700;"}, [_CN("img", {src:"./modules/pdf.png", style:"height:18px;vertical-align:middle;"}), " Open on new page"], manualDiv).addEventListener("click", ()=>{ 46 | PDFManual.GetChapterPage(ch, (p)=>{ 47 | window.open(PDFManual.pdfFile + "#page=" + p, "new"); 48 | }); 49 | }); 50 | manualDiv.style.opacity = 1; 51 | } 52 | else 53 | { 54 | manualDiv.textContent = "No SimCom manual found."; 55 | } 56 | }, 100) 57 | 58 | _CN("p", {}, [cmd.GetDescription()], this.manual); 59 | 60 | _CN("table", {border:1}, [ 61 | _CN("tr", {}, [ 62 | _CN("th", {}, ["Test"]), 63 | _CN("th", {}, ["Read"]), 64 | _CN("th", {}, ["Write"]), 65 | _CN("th", {}, ["Execute"]), 66 | _CN("th", {}, ["Timeout"]) 67 | ]), 68 | _CN("tr", {}, [ 69 | _CN("td", {}, [cmd.CanTest()?"✔️":"❌"]), 70 | _CN("td", {}, [cmd.CanRead()?"✔️":"❌"]), 71 | _CN("td", {}, [cmd.CanWrite()?"✔️":"❌"]), 72 | _CN("td", {}, [cmd.CanExecute()?"✔️":"❌"]), 73 | _CN("td", {}, [timeout]) 74 | ]) 75 | ], this.manual); 76 | 77 | const atp = cmd.GetAllParams(); 78 | 79 | console.log(atp); 80 | for(let j=0;j<4;j++) 81 | { 82 | let o = {txt: "", can:false, arr:[], arr2:[], cmd:cmd.GetCmd(), func:null}; 83 | switch(j) 84 | { 85 | case 0: o.txt = "Test"; o.can = cmd.CanTest(); o.arr = atp.test; o.cmd += "=? "; 86 | o.func = ()=>{cmd.Test();}; 87 | break; 88 | case 1: o.txt = "Read"; o.can = cmd.CanRead(); o.arr = atp.read; o.cmd += "? "; 89 | o.func = ()=>{cmd.Read();}; 90 | break; 91 | case 2: o.txt = "Write"; o.can = cmd.CanWrite(); o.arr = atp.write.get; o.arr2 = atp.write.set; o.cmd += "= "; break; 92 | o.func = ()=>{cmd.Write();}; 93 | case 3: o.txt = "Execute"; o.can = cmd.CanExecute(); o.arr = atp.exe; o.cmd += " "; 94 | o.func = ()=>{cmd.Execute();}; 95 | break; 96 | } 97 | if(o.can) 98 | { 99 | let div = _CN("div", {style:"text-align:left;"}, [_CN("h2", {}, [o.txt])], this.manual); 100 | if(Array.isArray(o.arr) && o.arr.length > 0 || j == 2) 101 | { 102 | o.arr2.forEach(px=>{ 103 | let st = o.cmd; 104 | let first = true; 105 | Object.keys(px).forEach(k=>{ 106 | if(first) first = false; 107 | else st += ","; 108 | st += k; 109 | }); 110 | st += " ➡️ (ANSWER)"; 111 | let divP = _CN("div", {style:"text-align:left;cursor:pointer;"}, [st], div); 112 | divP.addEventListener("click", o.func); 113 | }); 114 | 115 | o.arr.forEach(px=>{ 116 | let st = o.cmd + " ➡️ "; 117 | let first = true; 118 | Object.keys(px).forEach(k=>{ 119 | if(first) first = false; 120 | else st += ", "; 121 | st += k; 122 | if(px[k] != null) st += "=" + px[k]; 123 | }); 124 | let divP = _CN("div", {style:"text-align:left;cursor:pointer;"}, [st], div); 125 | divP.addEventListener("click", o.func); 126 | }); 127 | } 128 | else 129 | { 130 | let st = o.cmd + " ➡️ "; 131 | let divP = _CN("div", {style:"text-align:left;cursor:pointer;"}, [st], div); 132 | divP.addEventListener("click", o.func); 133 | } 134 | } 135 | } 136 | 137 | let divP = _CN("div", {style:"text-align:left;"}, [_CN("h2", {}, ["Parameters"])], this.manual); 138 | atp.all.forEach(py=>{ 139 | let div2 = _CN("div", {style:"display:block;padding-left:2vw;"}); 140 | 141 | if(Array.isArray(py?.GetType())) 142 | { 143 | py.GetType().forEach(ptx=>{ 144 | _CN("b", {style:"display:inline-block;min-width:4vw;text-align:center;float:left;"}, [ptx.GetValue()], div2); 145 | _CN("i", {style:"margin-left:1vw;display:inline-block;"}, [ptx.GetDescription()], div2); 146 | _CN("br", {}, [], div2); 147 | }); 148 | } 149 | else 150 | { 151 | _CN("b", {style:"display:inline-block;min-width:4vw;text-align:center;float:left;"}, [py.GetType()], div2); 152 | _CN("i", {style:"margin-left:2vw;display:inline-block;"}, [py.GetDescription()], div2); 153 | } 154 | _CN("div", {style:"margin:0.5vh;padding:1vw;width:94%;box-shadow:0px 0px 0.6vh 1px #006;border-radius:1vh;"}, [_CN("label", {}, [py?.GetName()]), div2], divP); 155 | }); 156 | 157 | } 158 | 159 | Select() 160 | { 161 | 162 | } 163 | 164 | } 165 | 166 | Tabs.AddTab(new TabManual()); -------------------------------------------------------------------------------- /js/tabSms.js: -------------------------------------------------------------------------------- 1 | class TabSms 2 | { 3 | Title = "SMS"; 4 | #table = {}; 5 | 6 | constructor() 7 | { 8 | this.div = _CN("div", {class:"box tab"}, [_CN("h2", {}, ["SMS"])], Tabs.GetDiv()); 9 | this.messageTextMode = null; 10 | this.phoneNr = null; 11 | this.msg = null; 12 | 13 | setTimeout(()=>{ 14 | this.Init(); 15 | 16 | window.addEventListener("serial", (data)=>{ 17 | if(data.detail.cmd?.GetCmd() == "AT+CMGF") 18 | { 19 | this.messageTextMode = AT_CMGF.IsTextMode(); 20 | } 21 | }); 22 | }, 200); 23 | } 24 | 25 | Init() 26 | { 27 | //this.div.appendChild(Settings.GetGroupDiv("apn")); 28 | //this.div.appendChild(Settings.GetGroupDiv("ssl")); 29 | 30 | this.div.appendChild( 31 | Tabs.AddCmd( 32 | "GET Message Mode", 33 | ()=>{ 34 | AT_CMGF.Read().then(()=>{}); 35 | }, 36 | AT_CMGF) 37 | ); 38 | 39 | this.#table.el = _CN("table", {border:1,style:"max-height:40vh;overflow-y:auto;"}, [], this.div); 40 | this.#table.rows = []; 41 | 42 | _CN("button", {style:"margin:1vh;"}, ["GET SMS"], this.div).addEventListener("click", ()=>{ 43 | this.GetSMS(); 44 | }); 45 | 46 | this.phoneNr = _CN("input", {type:"text", value:"", title:"sms_to_nr"}); 47 | _CN("div", {class:"paramdiv"}, [_CN("p", {}, ["Phone number to deliver sms", this.phoneNr])], this.div); 48 | Settings.AutoSaveChanges(this.phoneNr); 49 | 50 | this.msg = _CN("input", {type:"text", value:"", maxlength:160, title:"sms_to_msg"}); 51 | _CN("div", {class:"paramdiv"}, [_CN("p", {}, ["Message to send (max 160 chars)", this.msg])], this.div); 52 | Settings.AutoSaveChanges(this.msg); 53 | 54 | _CN("button", {style:"margin:1vh;"}, ["SEND SMS"], this.div).addEventListener("click", ()=>{ 55 | this.SendSMS(); 56 | }); 57 | 58 | _CN("button", {style:"margin:1vh;"}, ["SEND ESC"], this.div).addEventListener("click", ()=>{ 59 | this.SendESC(); 60 | }); 61 | } 62 | 63 | Select() 64 | { 65 | if(this.messageTextMode == null) 66 | { 67 | AT_CMGF.Read(); 68 | } 69 | } 70 | 71 | GetSMS() 72 | { 73 | this.SetTextMode().then(()=>{ 74 | AT_CMGL.Write(["\"ALL\"", 1]).then(()=>{ 75 | let first = true; 76 | AT_CMGL.GetMessages().forEach(m=>{ 77 | console.log(m); 78 | this.AddTableRow(m, first); 79 | first = false; 80 | }); 81 | }).catch((e)=>{this.#Error("Unable to get messages", e);}); 82 | }).catch((e)=>{this.#Error("Unable to set text mode", e);}); 83 | } 84 | 85 | SendESC() 86 | { 87 | SIMSerial.SendChar(27); 88 | } 89 | 90 | SendSMS() 91 | { 92 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 93 | 94 | this.SetTextMode().then(()=>{ 95 | let abortSMS = false; 96 | setTimeout(()=>{ 97 | if(abortSMS) return; 98 | console.log("send data..."); 99 | SIMSerial.SendData(this.msg.value); 100 | setTimeout(()=>{ 101 | SIMSerial.SendChar(26); 102 | }, 200); 103 | }, 1000); 104 | 105 | let phoneNr = this.phoneNr.value; 106 | phoneNr = phoneNr.replace(/"/g, ''); 107 | phoneNr = '"' + phoneNr + '"'; 108 | AT_CMGS.Write([phoneNr]).then(()=>{ 109 | abortSMS = true; 110 | event.detail.info = "SMS successfully sent"; 111 | window.dispatchEvent(event); 112 | }).catch((e)=>{abortSMS = true; this.#Error("Unable to send messages", e);}); 113 | }).catch((e)=>{this.#Error("Unable to set text mode", e);}); 114 | } 115 | 116 | AddTableRow(data, clear=false) 117 | { 118 | if(clear) 119 | { 120 | [...this.#table.el.getElementsByTagName("tr")].forEach(tr=>{this.#table.el.removeChild(tr);}); 121 | this.#table.rows = []; 122 | _CN("tr", {}, [_CN("th",{},["index"]), _CN("th",{},["state"]), _CN("th",{},["from"]), _CN("th",{},["time"])], this.#table.el); 123 | } 124 | const smstypes = ["✉", "💌","📤","📩","🗂️"]; 125 | let row = {el:null, data:null, open:false}; 126 | let tds = []; 127 | let stat = data.data.stat.replace(/"/g, ''); 128 | let smstype = smstypes[4]; 129 | if(stat == 0 || stat == "REC UNREAD") smstype = smstypes[0]; 130 | else if(stat == 1 || stat == "REC READ") smstype = smstypes[1]; 131 | else if(stat == 2 || stat == "STO UNSENT") smstype = smstypes[2]; 132 | else if(stat == 3 || stat == "STO SENT") smstype = smstypes[3]; 133 | tds.push(_CN("th", {}, [data.data.index])); 134 | tds.push(_CN("td", {title:stat}, [smstype])); 135 | tds.push(_CN("td", {}, [data.data.oada])); 136 | tds.push(_CN("td", {}, [data.data.scts])); 137 | row.data = data; 138 | row.el = _CN("tr", {}, tds, this.#table.el); 139 | row.el.addEventListener("click", ()=>{ 140 | if(!row.open) 141 | { 142 | this.#AddTableMessage(row); 143 | } 144 | else 145 | { 146 | this.#table.el.removeChild(row.el.nextSibling); 147 | row.open = false; 148 | } 149 | }); 150 | } 151 | 152 | #AddTableMessage(row) 153 | { 154 | row.open = true; 155 | let remove = _CN("a", {style:"color:#a00;float:right;"}, ["🗑️"]); 156 | let nrow = _CN("tr", {}, [_CN("td",{},[]), _CN("td",{colspan:3},[row.data.msg, _CN("br"),remove])]); 157 | this.#table.el.insertBefore(nrow, row.el.nextSibling) 158 | 159 | remove.addEventListener("click", ()=>{ 160 | AT_CMGD.Write([row.data.data.index, 0]).then(()=>{ 161 | this.#table.el.removeChild(nrow.previousSibling); 162 | this.#table.el.removeChild(nrow); 163 | }).catch((e)=>{this.#Error("Unable to set delete message", e);}); 164 | }); 165 | } 166 | 167 | SetTextMode() 168 | { 169 | return new Promise((res,rej)=> 170 | { 171 | if(this.messageTextMode) 172 | { 173 | res(); 174 | } 175 | else 176 | { 177 | AT_CMGF.Write([1]).then(()=>{ 178 | res(); 179 | }).catch(()=>{rej();}); 180 | } 181 | }); 182 | } 183 | 184 | 185 | 186 | #Error(msg, e, o = {}) 187 | { 188 | console.error("SMS ERROR", e); 189 | const event = new CustomEvent("cominfo", { detail: {error:msg, event:e} }); 190 | window.dispatchEvent(event); 191 | 192 | } 193 | 194 | } 195 | 196 | Tabs.AddTab(new TabSms()); -------------------------------------------------------------------------------- /js/info.js: -------------------------------------------------------------------------------- 1 | const TabInfo = new class 2 | { 3 | #moduleInit = false; 4 | #moduleInfo = {}; 5 | 6 | constructor() 7 | { 8 | this.div = _CN("div", {class:"box infotab"}, [_CN("h2", {}, ["Module Info"])]); 9 | 10 | this.prod_id = _CN("div", {class:"labelInfo"}, [_CN("label", {}, ["Product Identification: "]), _CN("i")], this.div); 11 | this.man_id = _CN("div", {class:"labelInfo"}, [_CN("label", {}, ["Manufacturer Identification: "]), _CN("i")], this.div); 12 | this.mod_id = _CN("div", {class:"labelInfo"}, [_CN("label", {}, ["Model Identification: "]), _CN("i")], this.div); 13 | this.glo_id = _CN("div", {class:"labelInfo"}, [_CN("label", {}, ["Global Identification: "]), _CN("i")], this.div); 14 | this.rev = _CN("div", {class:"labelInfo"}, [_CN("label", {}, ["Firmware: "]), _CN("i")], this.div); 15 | 16 | this.divGit = _CN("div", {class:"box github"}, [], document.body); 17 | 18 | this.divImg = _CN("div", {class:"simModule"}, [_CN("span", {}, ["?"])], document.body); 19 | } 20 | 21 | Init() 22 | { 23 | document.body.appendChild(this.div); 24 | window.addEventListener("serial", (data)=>{ 25 | this.#Serial(data.detail); 26 | }); 27 | 28 | setTimeout(()=>{ 29 | _CN("div", {}, [_CN("a", {href:"https://github.com/Adrianotiger/simcomtester", target:"_blank"}, ["Github Project"])], this.divGit); 30 | _CN("div", {}, [_CN("i", {}, ["ver 0.63 - 2025", _CN("br"), "© Adriano Petrucci"])], this.divGit); 31 | }, 500); 32 | 33 | let i = window.setInterval(()=>{ 34 | if(SIMSerial && SIMSerial.IsConnected()) 35 | { 36 | console.log("Serial ready!"); 37 | window.clearInterval(i); 38 | document.body.removeChild(document.getElementsByClassName("loading")[0]); 39 | 40 | SIMSerial.SendData("\r\n\r\n"); 41 | setTimeout(()=>{ 42 | this.#InitModule(); 43 | }, 500); 44 | } 45 | },500); 46 | } 47 | 48 | // Start inquiring module and possible commands 49 | async #InitModule(retries = 0) 50 | { 51 | let isConnected = false; 52 | 53 | await AT.Execute().then(()=>{ 54 | isConnected = true; 55 | }).catch((e)=> 56 | { 57 | const event = new CustomEvent("cominfo", { detail: {error:"No answer from module" + (retries<10 ? ", retry... (" + (9-retries) +")":"."), event:e} }); 58 | window.dispatchEvent(event); 59 | }); 60 | 61 | if(!isConnected && retries < 10) 62 | { 63 | setTimeout(()=>{ 64 | SIMSerial.Disconnect(); 65 | setTimeout(()=>{ 66 | if(SIMSerial.IsConnected()) 67 | { 68 | alert("Unable to disconnect port..."); 69 | } 70 | else 71 | { 72 | SIMSerial.Connect(); 73 | setTimeout(()=>{ 74 | SIMSerial.SendData("\r\n\r\n"); 75 | }, 500); 76 | setTimeout(()=>{ 77 | this.#InitModule(retries+1); 78 | }, 1000); 79 | } 80 | }, 1000); 81 | }, 100); 82 | return; 83 | } 84 | 85 | ATE0.Execute().then(()=>{ 86 | ATI.Execute().then(()=>{ 87 | AT_GMI.Execute().then(()=>{ 88 | AT_GMM.Execute().then(()=>{ 89 | AT_GOI.Execute().then(async ()=>{ 90 | let module = AT_GOI.GetValue(); 91 | if(module.search(/70[0-9]+0/)) 92 | { 93 | fetch("modules/sim7080/info.json").then(r=>{return r.json();}).then(j=>{this.#moduleInfo = j}); 94 | await addATCommands("modules/sim7080/at.json"); 95 | PDFManual.LoadPDF("./modules/manuals/SIM70x0_AT_107.pdf"); 96 | 97 | console.log("extended AT commands loaded", ATs); 98 | 99 | window.dispatchEvent( 100 | new CustomEvent("cominfo", { detail: {info:"Module 70*0 found! Loading extended AT commands and manual."} }) 101 | ); 102 | } 103 | else 104 | { 105 | window.dispatchEvent( 106 | new CustomEvent("cominfo", { detail: {error:"Module " + module + " not found in this project."} }) 107 | ); 108 | } 109 | 110 | setTimeout(()=>{ 111 | this.#moduleInit = true; 112 | this.#InitOver(); 113 | }, 500); 114 | 115 | AT_GMR.Execute().then(()=>{ 116 | let revision = AT_GMR.GetValue(); 117 | if(this.#moduleInfo.firmware) 118 | { 119 | console.log(this.#moduleInfo.firmware, revision); 120 | const reg = new RegExp(this.#moduleInfo.firmware.version, 'g'); 121 | let m; 122 | if ((m = reg.exec(revision)) !== null) 123 | { 124 | if(m.length == 2 && parseInt(m[2]) < parseInt(this.#moduleInfo.firmware.last)) 125 | { 126 | window.dispatchEvent( 127 | new CustomEvent("cominfo", { detail: {error:"Module firmware (" + m[1] + ") is out of date, there is a newer firmware: " + this.#moduleInfo.firmware.last} }) 128 | ); 129 | } 130 | else if(m.length == 2) 131 | { 132 | window.dispatchEvent( 133 | new CustomEvent("cominfo", { detail: {info:"Module firmware is " + m[1] + ". Up to date."} }) 134 | ); 135 | } 136 | } 137 | } 138 | }); 139 | }); 140 | }); 141 | }); 142 | }); 143 | }).catch(()=> 144 | { 145 | alert("Unable to execute AT* command"); 146 | }); 147 | } 148 | 149 | #InitOver() 150 | { 151 | this.divImg.getElementsByTagName("span")[0].textContent = this.glo_id.getElementsByTagName("i")[0].textContent; 152 | Tabs.Load(); 153 | } 154 | 155 | #Serial(data) 156 | { 157 | console.log(data); 158 | switch(data.cmd?.GetCmd()) 159 | { 160 | case "ATI": 161 | this.prod_id.getElementsByTagName("i")[0].textContent = ATI.GetValue(); 162 | break; 163 | case "AT+GMI": 164 | this.man_id.getElementsByTagName("i")[0].textContent = AT_GMI.GetValue(); 165 | break; 166 | case "AT+GMM": 167 | this.mod_id.getElementsByTagName("i")[0].textContent = AT_GMM.GetValue(); 168 | break; 169 | case "AT+GOI": 170 | this.glo_id.getElementsByTagName("i")[0].textContent = AT_GOI.GetValue(); 171 | break; 172 | case "AT+GMR": 173 | this.rev.getElementsByTagName("i")[0].textContent = AT_GMR.GetValue(); 174 | break; 175 | } 176 | } 177 | }; 178 | 179 | window.addEventListener("load", ()=>{ 180 | TabInfo.Init(); 181 | }); 182 | -------------------------------------------------------------------------------- /js/tabCoap.js: -------------------------------------------------------------------------------- 1 | class TabCoap 2 | { 3 | Title = "Coap"; 4 | 5 | constructor() 6 | { 7 | this.div = _CN("div", {class:"box tab"}, [_CN("h2", {}, ["COAP"])], Tabs.GetDiv()); 8 | this.pdpidx = null; 9 | this.iptype = null; 10 | this.code = null; 11 | this.path = ""; 12 | this.query = ""; 13 | this.mid = null; 14 | this.payload = ""; 15 | 16 | setTimeout(()=>{ 17 | this.Init(); 18 | }, 200); 19 | } 20 | 21 | Init() 22 | { 23 | this.div.appendChild(Settings.GetGroupDiv("apn")); 24 | this.div.appendChild(Settings.GetGroupDiv("coap")); 25 | _CN("button", {style:"margin:1vh;"}, ["Check Status"], this.div).addEventListener("click", ()=>{ 26 | this.CheckStatus(); 27 | }); 28 | 29 | let addDiv = AT_CNCFG.GetParamDiv("pdpidx", "Select PDPidx (Packet Data Protocol Identifier) to use for this COAP"); 30 | this.div.appendChild(addDiv.div); 31 | this.pdpidx = addDiv.inp; 32 | 33 | addDiv = AT_CNCFG.GetParamDiv("iptype", "Select IP type", 1); 34 | this.div.appendChild(addDiv.div); 35 | this.iptype = addDiv.inp; 36 | 37 | addDiv = AT_CCOAPPARA.GetParamDiv("code", "Message request type", 2); 38 | this.div.appendChild(addDiv.div); 39 | this.code = addDiv.inp; 40 | 41 | addDiv = AT_CCOAPPARA.GetParamDiv("mid", "Message Id", 10); 42 | this.div.appendChild(addDiv.div); 43 | this.mid = addDiv.inp; 44 | 45 | addDiv = AT_CCOAPPARA.GetParamDiv("uripath", "Query relative URL (ex:'home/dir')"); 46 | this.div.appendChild(addDiv.div); 47 | this.path = addDiv.inp; 48 | 49 | addDiv = AT_CCOAPPARA.GetParamDiv("uriquery", "Queries (ex:'topic=event&page=4')", "t=test"); 50 | this.div.appendChild(addDiv.div); 51 | this.query = addDiv.inp; 52 | 53 | addDiv = AT_CCOAPPARA.GetParamDiv("payload", "Payload, message to send"); 54 | this.div.appendChild(addDiv.div); 55 | addDiv.inp.value = "Hello World!"; 56 | this.payload = addDiv.inp; 57 | 58 | _CN("br", {}, [], this.div); 59 | _CN("button", {style:"margin:1vh;"}, ["Send Coap"], this.div).addEventListener("click", ()=>{ 60 | this.SendCoap(); 61 | }); 62 | 63 | } 64 | 65 | Select() 66 | { 67 | 68 | } 69 | 70 | CheckStatus() 71 | { 72 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 73 | 74 | return new Promise((res, rej) => { 75 | ATScripts.CheckPIN(Settings.GetValue("pin", "pin")).then(()=>{ 76 | ATScripts.CheckNetwork().then(()=>{ 77 | 78 | ATScripts.CheckAPN(Settings.GetValue("apn", "url"), this.pdpidx.value).then(()=>{ 79 | res(); // successfully tested pin, network and apn 80 | }).catch(e=>{this.#Error("NO APN", e); rej();}); 81 | 82 | }).catch(e=>{this.#Error("NO CONNECTION", e); rej();}); 83 | }).catch(e=>{this.#Error("PIN ERROR", e); rej();}); 84 | }); 85 | } 86 | 87 | SendCoap() 88 | { 89 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 90 | 91 | return new Promise((res, rej)=>{ 92 | this.CheckStatus().then(()=>{ 93 | 94 | event.detail.info = "Activate PDP"; 95 | window.dispatchEvent(event); 96 | 97 | // activate pdp 98 | this.#ActivatePDP().then(()=>{ 99 | event.detail.info = "Send PDP on idx " + this.pdpidx.value + ", ip: " + AT_CNACT.GetIp(parseInt(this.pdpidx.value)); 100 | window.dispatchEvent(event); 101 | AT_CCOAPINIT.Execute().then(()=>{ 102 | AT_CCOAPURL.Write([Settings.GetValue("coap", "url")]).then(()=>{ 103 | this.#ExecuteCoap().then(()=>{ 104 | 105 | }).catch(e=>{this.#Error("COAP Send ERROR", e, true); rej();}); 106 | }).catch(e=>{this.#Error("AT_CCOAPURL ERROR", e, true); rej();}); 107 | }).catch(e=>{this.#Error("AT_CCOAPINIT ERROR", e, true); rej();}); 108 | }).catch(e=>{this.#Error("AT_CNACT ERROR", e); rej();}); 109 | 110 | }).catch(e=>{this.#Error("CHECK ERROR", e); rej();}); 111 | }); 112 | } 113 | 114 | #ActivatePDP() 115 | { 116 | let index = parseInt(this.pdpidx.value); 117 | 118 | return new Promise((res, rej)=>{ 119 | if(AT_CNACT.IsActive(index)) 120 | { 121 | res(); 122 | } 123 | else // not active, try to activate 124 | { 125 | ATScripts.CheckAPN(Settings.GetValue("apn", "url"), index).then(()=>{ 126 | res(); // successfully tested pin, network and apn 127 | }).catch(e=>{this.#Error("NO APN", e); rej();}); 128 | } 129 | }); 130 | } 131 | 132 | #ExecuteCoap() 133 | { 134 | let params = []; 135 | params.push("code"); 136 | params.push(this.code.value); 137 | 138 | if(this.path.value.trim().length > 0) 139 | { 140 | params.push("uri-path"); 141 | params.push(0); // ascii 142 | params.push(this.path.value.trim()); 143 | } 144 | 145 | if(this.query.value.trim().length > 0) 146 | { 147 | params.push("uri-query"); 148 | params.push(0); // ascii 149 | params.push(this.query.value.trim()); 150 | } 151 | 152 | if(this.mid.value.trim().length > 0) 153 | { 154 | params.push("mid"); 155 | params.push(this.mid.value); 156 | this.mid.value++; 157 | } 158 | 159 | params.push("payload"); 160 | params.push(0); // ascii 161 | params.push(this.payload.value.trim()); 162 | 163 | return new Promise((res, rej)=>{ 164 | // Set params 165 | AT_CCOAPPARA.Write(params).then(()=>{ 166 | // Send Coap 167 | AT_CCOAPACTION.Execute().then(()=>{ 168 | // Wait for the response 169 | setTimeout(()=>{ 170 | if(AT_CCOAPACTION.IsCoapReceived()) 171 | { 172 | // Get and parse header 173 | AT_CCOAPHEAD.Write([AT_CCOAPACTION.GetMid(), 1]).then(()=>{ 174 | 175 | // Everything ok! Terminate Coap and close 176 | AT_CCOAPTERM.Execute().then(()=>{ 177 | res(); 178 | }).catch(()=>{res();}); 179 | }).catch((e)=>{this.#Error("AT_COAPHEAD ERROR", e, true); rej();}); 180 | } 181 | else 182 | { 183 | this.#Error("COAP No Answer Received", null, true); 184 | rej(); 185 | } 186 | }, 500); 187 | }).catch((e)=>{this.#Error("AT_COAPACTION ERROR", e, true); rej();}); 188 | }).catch((e)=>{this.#Error("AT_CCOAPPARA ERROR", e, true); rej();}); 189 | }); 190 | } 191 | 192 | #Error(msg, e, terminateCoap=false) 193 | { 194 | console.error("COAP ERROR", e); 195 | const event = new CustomEvent("cominfo", { detail: {error:msg, event:e} }); 196 | window.dispatchEvent(event); 197 | 198 | if(terminateCoap) 199 | { 200 | AT_CCOAPTERM.Execute(); 201 | } 202 | } 203 | 204 | } 205 | 206 | Tabs.AddTab(new TabCoap()); -------------------------------------------------------------------------------- /js/chat.js: -------------------------------------------------------------------------------- 1 | const TabChat = new class 2 | { 3 | constructor() 4 | { 5 | this.div = _CN("div", {class:"box chat"}, [_CN("h2", {}, ["Chat"])]); 6 | this.chat = _CN("input", {type:"text", placeholder:"custom AT commands"}, [], this.div); 7 | } 8 | 9 | Init() 10 | { 11 | document.body.appendChild(this.div); 12 | window.addEventListener("serial", (data)=>{ 13 | this.#Serial(data.detail); 14 | }); 15 | window.addEventListener("send", (data)=>{ 16 | this.#Send(data.detail); 17 | }); 18 | window.addEventListener("cominfo", (data)=>{ 19 | this.#Info(data.detail); 20 | }); 21 | window.addEventListener("terminal", (data)=>{ 22 | this.#Terminal(data.detail); 23 | }); 24 | 25 | this.chat.addEventListener("keypress", (k)=>{ 26 | if(k.key === "Enter") 27 | { 28 | SIMSerial.Send(this.chat.value + "\r\n", null).then(()=>{ 29 | // Successfully sent. 30 | }).catch(err=>{ 31 | console.warn("ERROR SENDING OVER CHAT:", err); 32 | }); 33 | } 34 | }); 35 | 36 | window.addEventListener("serialactive", (data)=>{ 37 | if(data.detail) 38 | { 39 | this.div.style.pointerEvents = "inherit"; 40 | this.div.style.opacity = 1; 41 | } 42 | else 43 | { 44 | this.div.style.pointerEvents = "none"; 45 | this.div.style.opacity = 0.5; 46 | } 47 | }); 48 | } 49 | 50 | DrawGauge(minVal, maxVal, curVal) 51 | { 52 | let gauge = _CN("div", {class:"msg_gauge"}); 53 | if(minVal==0 && maxVal==100) 54 | { 55 | let val = curVal * 50; 56 | _CN("div", {}, [_CN("b", {style:`transform:translate(${val}%, -20%);`})], gauge); 57 | _CN("span", {style:"left:5px;"}, [minVal + "%"], gauge); 58 | _CN("span", {style:"right:5px;"}, [maxVal + "%"], gauge); 59 | } 60 | return gauge; 61 | } 62 | 63 | #Serial(data) 64 | { 65 | let div = _CN("div", {class:"msg_g"}, [], this.div); 66 | let msg = _CN("div", {class:"msg_r"}, [], div); 67 | 68 | if(data.cmd) 69 | { 70 | if(data.answer.trim().startsWith("+") || data.cmd.GetRequestType() == "unsolicited") 71 | { 72 | const cmd = data.cmd; 73 | const cmdd = data.answer.trim().split("\r")[0].trim(); 74 | let info = _CN("span", {class:"msg_a"}, ["i"], div); 75 | let bubble = null; 76 | if(cmd.GetRequestType() == 'unsolicited') msg.classList.add("msg_u"); 77 | info.addEventListener("mouseenter",(e)=>{ 78 | if(bubble == null) 79 | { 80 | let params = []; 81 | switch(cmd.GetRequestType()) 82 | { 83 | case 'exe': params = cmd.GetAllParams().exe; break; 84 | case 'test': params = cmd.GetAllParams().test; break; 85 | case 'read': params = cmd.GetAllParams().read; break; 86 | case 'write': params = cmd.GetAllParams().write.get; break; 87 | case 'unsolicited': params = cmd.GetAllParams().unsolicited; break; 88 | default: params = cmd.GetAllParams().all;; break; 89 | } 90 | 91 | let layerX = e.layerX; 92 | if(layerX < 400) layerX = 400; 93 | bubble = _CN("div", {class:"msg_bubble", style:`left:${layerX}px;`}, [], div); 94 | _CN("b", {}, [cmd.GetDescription()], bubble); 95 | let table = _CN("table", {border:1}, [], bubble); 96 | const lst = cmd.Comma2List(cmdd.substring(cmdd.indexOf(":") + 1)); 97 | let lstindex = 0; 98 | let defi = 0; 99 | for(let j=0;j{ 101 | console.log(cmd.GetParam(pk)); 102 | const px = cmd.GetParam(pk); 103 | let val = lst[lstindex++]; 104 | if(Array.isArray(px.GetType())) 105 | { 106 | let vals = val; 107 | val = _CN("select", {style:"font-size:x-small"}); 108 | px.GetType().forEach(t=>{ 109 | let o = _CN("option", {}, [t.GetValue() + " - " + t.GetDescription()], val); 110 | if(vals.replace(/\"/g, '')==t.GetValue()) o.selected = true; 111 | }); 112 | } 113 | _CN("tr",{}, [ 114 | _CN("td",{}, [px.GetName()]), 115 | _CN("td",{}, [val]), 116 | _CN("td",{}, [px.GetDescription()]) 117 | ], table); 118 | }); 119 | 120 | bubble.addEventListener("mouseleave",()=>{ 121 | div.removeChild(bubble); 122 | bubble = null; 123 | }); 124 | } 125 | }); 126 | } 127 | 128 | data.cmd.ShowChat(msg); 129 | } 130 | else 131 | { 132 | var at = new ATBase({read:true, write:true, test:true, exe:true}); 133 | at.Parse(data.answer); 134 | at.ShowChat(msg); 135 | } 136 | 137 | setTimeout(()=>{ 138 | //_CN("br", {}, [], this.div); 139 | 140 | //const r = this.div.getBoundingClientRect(); 141 | this.div.scrollTo({top: parseInt(this.div.scrollHeight), behavior:"smooth"}); 142 | }, 50); 143 | } 144 | 145 | #Send(data) 146 | { 147 | const req = data.req + "\r\n"; 148 | let div = _CN("div", {class:"msg_g"}, [], this.div); 149 | let send = _CN("div", {class:"msg_s"}, [data.req], div); 150 | 151 | if(data.cmd) 152 | { 153 | const cmd2 = data.cmd; 154 | if(data.cmd.CanTest() && data.req.indexOf("=?") < 0) 155 | { 156 | let help = _CN("span", {class:"msg_h"}, ["?"], div); 157 | let req2 = req.trim(); 158 | if(req2.indexOf("=") > 0) 159 | req2 = req2.substring(0, req2.indexOf("=")); 160 | else if(req2.indexOf("?") > 0) 161 | req2 = req2.substring(0, req2.indexOf("?")); 162 | 163 | help.addEventListener("click", ()=>{ 164 | cmd2.Test(); 165 | }); 166 | } 167 | _CN("i", {}, [data.cmd.GetDescription()], div); 168 | let manual = _CN("b", {}, ["📃"], div); 169 | manual.addEventListener("click", ()=>{ 170 | const event = new CustomEvent("manual", { detail: cmd2 }); 171 | window.dispatchEvent(event); 172 | }); 173 | } 174 | else 175 | { 176 | _CN("i", {}, ["-unknown command-"], div); 177 | } 178 | 179 | send.addEventListener("click", ()=>{ 180 | this.chat.value = req.trim(); 181 | SIMSerial.Send(req); 182 | }); 183 | } 184 | 185 | #Info(data) 186 | { 187 | let div = _CN("div", {class:"msg_g", style:"text-align:center;"}, [], this.div); 188 | if(data.error) 189 | { 190 | _CN("div", {class:"msg_i", style:"background:linear-gradient(to bottom, #fee, #f88);"}, [data.error], div); 191 | } 192 | else if(data.info) 193 | { 194 | _CN("div", {class:"msg_i"}, [data.info], div); 195 | } 196 | } 197 | 198 | #Terminal(data) 199 | { 200 | let div = _CN("div", {class:"msg_g"}, [], this.div); 201 | let msg = _CN("div", {class:"msg_r", style:"background:linear-gradient(to bottom, #445, #112, #445);color:springgreen;"}, [data], div); 202 | } 203 | }; 204 | 205 | window.addEventListener("load", ()=>{ 206 | TabChat.Init(); 207 | }); -------------------------------------------------------------------------------- /js/atscripts.js: -------------------------------------------------------------------------------- 1 | const ATScripts = new class 2 | { 3 | constructor() 4 | { 5 | } 6 | 7 | CheckPIN(pinCode = null) 8 | { 9 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 10 | 11 | return new Promise((res, rej) => { 12 | event.detail.info = "Check PIN"; 13 | window.dispatchEvent(event); 14 | 15 | // Check Pin 16 | AT_CPIN.Read().then(()=>{ 17 | switch(AT_CPIN.GetState()) 18 | { 19 | // module is ready 20 | case "READY": 21 | event.detail.info = "PIN is OK"; 22 | window.dispatchEvent(event); 23 | res(); 24 | return; 25 | // sim is locked with a pin 26 | case "SIM READY": 27 | event.detail.info = "insert PIN"; 28 | window.dispatchEvent(event); 29 | 30 | AT_CPIN.Write({pinCode}).then(()=>{ 31 | event.detail.info = "PIN OK"; 32 | window.dispatchEvent(event); 33 | res(); 34 | }).catch((e)=>{ 35 | event.detail.info = "invalid PIN"; 36 | window.dispatchEvent(event); 37 | rej(); 38 | }); 39 | 40 | return; 41 | } 42 | rej(); 43 | 44 | }).catch(e=>{this.#Error("PIN ERROR - STATE: " + AT_CPIN.GetState(), e); rej();}); 45 | }); 46 | } 47 | 48 | CheckNetwork() 49 | { 50 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 51 | 52 | return new Promise((res, rej) => { 53 | event.detail.info = "Check Network"; 54 | window.dispatchEvent(event); 55 | 56 | // Check Signal 57 | AT_CSQ.Execute().then(()=>{ 58 | if(AT_CSQ.GetRSSI_dBm() >= -100) 59 | { 60 | // Check Network 61 | this.#AttachGPRS().then(()=>{ 62 | // Check Operator 63 | AT_COPS.Read().then(()=>{ 64 | if(AT_COPS.GetOperator().length > 1) 65 | { 66 | event.detail.info = "Network is OK"; 67 | window.dispatchEvent(event); 68 | res(); 69 | } 70 | else 71 | { 72 | this.#Error("Wrong Operator", e); 73 | rej(); 74 | } 75 | }).catch(e=>{this.#Error("NO Operator", e); rej();}); 76 | }).catch(e=>{this.#Error("NO GPRS", e); rej();}); 77 | } 78 | else 79 | { 80 | this.#Error("POOR SIGNAL", e); 81 | rej(); 82 | } 83 | }).catch(e=>{this.#Error("NO SIGNAL", e); rej();}); 84 | }); 85 | } 86 | 87 | #AttachGPRS() 88 | { 89 | return new Promise((acc, rej)=>{ 90 | AT_CGATT.Read().then(()=>{ 91 | if(AT_CGATT.IsAttached()) 92 | { 93 | acc(); 94 | } 95 | else 96 | { 97 | AT_CGATT.Attach().then(()=>{ 98 | AT_CGATT.Read().then(()=>{ 99 | if(AT_CGATT.IsAttached()) 100 | { 101 | acc(); 102 | } 103 | else 104 | { 105 | rej(); 106 | } 107 | }).catch(()=>rej()); 108 | }).catch(()=>rej()); 109 | } 110 | }).catch(()=>rej()); 111 | }); 112 | } 113 | 114 | // Be sure to check Network first 115 | CheckAPN(apn, pdpidx=0) 116 | { 117 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 118 | 119 | return new Promise((res, rej) => { 120 | event.detail.info = "Check APN"; 121 | window.dispatchEvent(event); 122 | 123 | AT_CGNAPN.Execute().then(()=>{ 124 | if(apn == AT_CGNAPN.GetApn()) 125 | { 126 | // check Network Active 127 | AT_CNACT.Read().then(()=>{ 128 | if(!AT_CNACT.IsActive(pdpidx)) // all networks are inactive, try to activate network pdpidx 129 | { 130 | AT_CNACT.Write([pdpidx, 1]).then(()=>{ 131 | setTimeout(()=>{ 132 | AT_CNACT.Read().then(()=>{ 133 | if(!AT_CNACT.IsActive(pdpidx)) // still not active, why? 134 | { 135 | this.#Error("Can't activate network " + pdpidx, 0); 136 | rej(); 137 | } 138 | else 139 | { 140 | res(); 141 | } 142 | }).catch(e=>{this.#Error("Network Active Request failed (2)", e); rej();}); 143 | }, 1000); 144 | }).catch(e=>{this.#Error("Unable to activate Network", e); rej();}); 145 | } 146 | else 147 | { 148 | event.detail.info = "APN successfully tested. Ready to be used."; 149 | window.dispatchEvent(event); 150 | res(); 151 | } 152 | }).catch(e=>{this.#Error("Network Active Request failed", e); rej();}); 153 | } 154 | else 155 | { 156 | this.#Error("Please set the URL for your APN", false) 157 | rej(); 158 | } 159 | }).catch(e=>{this.#Error("NO APN", e); rej();}); 160 | }); 161 | } 162 | 163 | Reboot() 164 | { 165 | return new Promise((res, rej) => { 166 | // Execute Reboot and wait at lease 2 seconds 167 | AT_CREBOOT.Execute().then(()=>{ 168 | let step = 0; 169 | const event = new CustomEvent("cominfo", { detail: {info:"Reconnecting Module..."} }); 170 | window.dispatchEvent(event); 171 | let i = setInterval(()=>{ 172 | if(step == 1) 173 | { 174 | if(!SIMSerial.IsConnected()) 175 | { 176 | SIMSerial.Connect(); 177 | } 178 | // Serial should now be connected 179 | const event = new CustomEvent("cominfo", { detail: {info:"Connected"} }); 180 | window.dispatchEvent(event); 181 | step = 1; 182 | } 183 | else if(step == 2) 184 | { 185 | // Send new line, to be sure the next AT command will be detected 186 | step++ 187 | SIMSerial.SendData("\r\n\r\n"); 188 | } 189 | else if(step >= 3) 190 | { 191 | // At this point, after 4 seconds, the module should be ready. set echo Off and test it 192 | clearInterval(i); 193 | ATE0.Execute().then(()=>{ 194 | const event = new CustomEvent("cominfo", { detail: {info:"Module is ready"} }); 195 | window.dispatchEvent(event); 196 | res(); 197 | }).catch(e=>{ 198 | const event = new CustomEvent("cominfo", { detail: {error:"Unable to connect module", event:e} }); 199 | window.dispatchEvent(event); 200 | rej(); 201 | }); 202 | } 203 | step++; 204 | }, 1000); 205 | }).catch(e=>{ 206 | const event = new CustomEvent("cominfo", { detail: {error:"Unable to reboot module", event:e} }); 207 | window.dispatchEvent(event); 208 | rej(); 209 | }); 210 | }); 211 | } 212 | 213 | #Error(msg, e) 214 | { 215 | console.error("ATSCRIPTS ERROR", e); 216 | const event = new CustomEvent("cominfo", { detail: {error:msg, event:e} }); 217 | window.dispatchEvent(event); 218 | } 219 | }; -------------------------------------------------------------------------------- /js/tabTcpUdp.js: -------------------------------------------------------------------------------- 1 | class TabTcpUdp 2 | { 3 | Title = "TCP/UDP"; 4 | 5 | constructor() 6 | { 7 | this.div = _CN("div", {class:"box tab"}, [_CN("h2", {}, ["TCP/UDP"])], Tabs.GetDiv()); 8 | this.connTypeClient = null; 9 | this.connTypeServer = null; 10 | this.cid = null; 11 | this.pdpindex = null; 12 | this.server = null; 13 | this.port = null; 14 | this.answer = null; 15 | 16 | setTimeout(()=>{ 17 | this.Init(); 18 | }, 200); 19 | } 20 | 21 | Init() 22 | { 23 | this.div.appendChild(Settings.GetGroupDiv("apn")); 24 | 25 | _CN("button", {style:"margin:1vh;"}, ["Check Status"], this.div).addEventListener("click", ()=>{ 26 | this.CheckStatus(); 27 | }); 28 | 29 | _CN("h2", {}, ["Create Server"], this.div); 30 | 31 | this.cid = AT_CAOPEN.GetParamDiv("cid", "Select CID", 0); 32 | this.div.appendChild(this.cid.div); 33 | 34 | this.pdpindex = AT_CAOPEN.GetParamDiv("pdp_index", "Select PDP index", 0); 35 | this.div.appendChild(this.pdpindex.div); 36 | 37 | this.port = AT_CAOPEN.GetParamDiv("port", "Port (1-65535)", 15005); 38 | this.div.appendChild(this.port.div); 39 | 40 | this.answer = AT_CAOPEN.GetParamDiv("recv_mode", "Receive Mode", 0); 41 | this.div.appendChild(this.answer.div); 42 | 43 | this.connTypeServer = AT_CASERVER.GetParamDiv("conn_type", "Connection Type", "UDP"); 44 | this.div.appendChild(this.connTypeServer.div); 45 | 46 | _CN("button", {style:"margin:1vh;"}, ["Create Server"], this.div).addEventListener("click", ()=>{ 47 | this.#CreateServer(); 48 | }); 49 | 50 | this.server = AT_CAOPEN.GetParamDiv("server", "Server name or IP", "TestServer"); 51 | this.div.appendChild(this.server.div); 52 | 53 | this.connTypeClient = AT_CAOPEN.GetParamDiv("conn_type", "Connection Type", "TCP"); 54 | this.div.appendChild(this.connTypeClient.div); 55 | 56 | _CN("button", {style:"margin:1vh;"}, ["Connect Server"], this.div).addEventListener("click", ()=>{ 57 | this.#ConnectServer(); 58 | }); 59 | 60 | let cstate = _CN("button", {style:"margin:1vh;"}, ["Query State"]); 61 | cstate.addEventListener("click", ()=>{ 62 | AT_CASTATE.Read(); 63 | }); 64 | 65 | let cclose = _CN("button", {style:"margin:1vh;"}, ["Close Connection"]); 66 | cclose.addEventListener("click", ()=>{ 67 | AT_CACLOSE.Write([this.cid]); 68 | }); 69 | 70 | _CN("table", {}, [ 71 | _CN("tr", {}, [ 72 | _CN("td", {}, [cstate]), 73 | _CN("td", {}, [cclose]) 74 | ]) 75 | ], this.div); 76 | } 77 | 78 | Select() 79 | { 80 | 81 | } 82 | 83 | CheckStatus() 84 | { 85 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 86 | 87 | return new Promise((res, rej) => { 88 | event.detail.info = "Check PIN"; 89 | window.dispatchEvent(event); 90 | 91 | // Check Pin 92 | AT_CPIN.Read().then(()=>{ 93 | 94 | if(AT_CPIN.GetState() == "READY") 95 | { 96 | event.detail.info = "Check Network"; 97 | window.dispatchEvent(event); 98 | // Check Signal 99 | AT_CSQ.Execute().then(()=>{ 100 | if(AT_CSQ.GetRSSI_dBm() >= -100) 101 | { 102 | // Check Network 103 | this.#AttachGPRS().then(()=>{ 104 | // Check Operator 105 | AT_COPS.Read().then(()=>{ 106 | if(AT_COPS.GetOperator().length > 1) 107 | { 108 | event.detail.info = "Check Apn"; 109 | window.dispatchEvent(event); 110 | AT_CGNAPN.Execute().then(()=>{ 111 | if(Settings.GetValue("apn", "url") == AT_CGNAPN.GetApn()) 112 | { 113 | event.detail.info = "HTTP-Connection successfully tested. Ready to be used."; 114 | window.dispatchEvent(event); 115 | res(); 116 | } 117 | else 118 | { 119 | rej(); 120 | } 121 | }).catch(e=>{this.#Error("NO APN", e); rej();}); 122 | } 123 | else 124 | { 125 | rej(); 126 | } 127 | }).catch(e=>{this.#Error("NO OPERATOR", e); rej();}); 128 | }).catch(e=>{this.#Error("NO GPRS", e); rej();}); 129 | } 130 | else 131 | { 132 | rej(); 133 | } 134 | }).catch(e=>{this.#Error("NO SIGNAL", e); rej();}); 135 | } 136 | }).catch(e=>{this.#Error("PIN ERROR", e); rej();}); 137 | }); 138 | } 139 | 140 | #CreateServer() 141 | { 142 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 143 | 144 | return new Promise((res, rej)=>{ 145 | this.CheckStatus().then(()=>{ 146 | this.#ActivatePDP(this.pdpindex.value).then(()=>{ 147 | // {cid:null, pdp_index:null, conn_type:null, server:null, port:null, recv_mode:null} 148 | AT_CASERVER.Write([this.cid.inp.value, this.pdpindex.inp.value, "\"" + this.connTypeServer.inp.value + "\"", this.port.inp.value, this.answer.inp.value]).then(()=>{ 149 | // Server created ? 150 | }).catch(e=>{this.#Error("CASERVER ERROR", e); rej();}); 151 | }).catch(e=>{this.#Error("PDP ERROR", e); rej();}); 152 | }).catch(e=>{this.#Error("CHECK ERROR", e); rej();}); 153 | }); 154 | } 155 | 156 | #ConnectServer() 157 | { 158 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 159 | 160 | return new Promise((res, rej)=>{ 161 | this.CheckStatus().then(()=>{ 162 | this.#ActivatePDP(this.pdpindex.value).then(()=>{ 163 | // {cid:null, pdp_index:null, conn_type:null, server:null, port:null, recv_mode:null} 164 | AT_CAOPEN.Write([this.cid.inp.value, this.pdpindex.inp.value, "\"" + this.connTypeClient.inp.value + "\"", "\"" + this.server.inp.value + "\"", this.port.inp.value, this.answer.inp.value]).then(()=>{ 165 | // Server connected ? 166 | }).catch(e=>{this.#Error("CAOPEN ERROR", e); rej();}); 167 | }).catch(e=>{this.#Error("PDP ERROR", e); rej();}); 168 | }).catch(e=>{this.#Error("CHECK ERROR", e); rej();}); 169 | }); 170 | } 171 | 172 | #ActivatePDP(index=0) 173 | { 174 | return new Promise((res, rej)=>{ 175 | // Check if already active 176 | AT_CNACT.Read().then(()=>{ 177 | if(AT_CNACT.IsActive(index)) 178 | { 179 | res(); 180 | } 181 | else // not active, try to activate 182 | { 183 | AT_CNACT.Write([index, 1]).then(()=>{ 184 | AT_CNACT.Read().then(()=>{ 185 | if(AT_CNACT.IsActive(index)) 186 | { 187 | res(); 188 | } 189 | }).catch(e=>{this.#Error("AT_CNACT ERROR", e); rej();}); 190 | }).catch(e=>{this.#Error("AT_CNACT ERROR", e); rej();}); 191 | } 192 | }).catch(e=>{this.#Error("AT_CNACT ERROR", e); rej();}); 193 | }); 194 | } 195 | 196 | #AttachGPRS() 197 | { 198 | return new Promise((acc, rej)=>{ 199 | AT_CGATT.Read().then(()=>{ 200 | if(AT_CGATT.IsAttached()) 201 | { 202 | acc(); 203 | } 204 | else 205 | { 206 | AT_CGATT.Attach().then(()=>{ 207 | AT_CGATT.Read().then(()=>{ 208 | if(AT_CGATT.IsAttached()) 209 | { 210 | acc(); 211 | } 212 | else 213 | { 214 | rej(); 215 | } 216 | }).catch(()=>rej()); 217 | }).catch(()=>rej()); 218 | } 219 | }).catch(()=>rej()); 220 | }); 221 | } 222 | 223 | #Error(msg, e, o = {}) 224 | { 225 | console.error("HTTPS ERROR", e); 226 | const event = new CustomEvent("cominfo", { detail: {error:msg, event:e} }); 227 | window.dispatchEvent(event); 228 | 229 | if(o.terminateFS) 230 | { 231 | AT_CFSTERM.Execute(); 232 | } 233 | 234 | if(o.disconnect) 235 | { 236 | AT_SHDISC.Execute(); 237 | } 238 | } 239 | } 240 | 241 | Tabs.AddTab(new TabTcpUdp()); -------------------------------------------------------------------------------- /modules/at/at_ccoaphead.js: -------------------------------------------------------------------------------- 1 | let AT_CCOAPHEAD = new class extends ATBase 2 | { 3 | #heads = []; 4 | constructor() 5 | { 6 | //read, write, exe, test, description, example, cmd, timeout) 7 | super({ 8 | write: true, 9 | test: true, 10 | description: "Read Head of CoAP Packet", 11 | example: "+CCOAPHEAD: 1,1,2,0,4.04,1,,,,,,,0,,,,,,,,", 12 | cmd: "AT+CCOAPHEAD", 13 | doc: "18.2.7" 14 | });//false, true, false, true, "Read Head of CoAP Packet", "+CCOAPHEAD: 1,1,2,0,4.04,1,,,,,,,0,,,,,,,,", "AT+CCOAPHEAD", 1000); 15 | 16 | let enumC = []; 17 | enumC.push(new ATEnum(0, "Print data in raw mode")); 18 | enumC.push(new ATEnum(1, "Print data after parsing")); 19 | 20 | let enumT = []; 21 | enumT.push(new ATEnum(0, "Req. Confirmable")); 22 | enumT.push(new ATEnum(1, "Req. Non-confirmable")); 23 | enumT.push(new ATEnum(2, "Resp. Acknowledgement")); 24 | enumT.push(new ATEnum(3, "Resp. Reset")); 25 | 26 | let enumCode = []; 27 | enumCode.push(new ATEnum("0.00", "Method:EMPTY")); 28 | enumCode.push(new ATEnum("0.01", "Method:GET")); 29 | enumCode.push(new ATEnum("0.02", "Method:POST")); 30 | enumCode.push(new ATEnum("0.03", "Method:PUT")); 31 | enumCode.push(new ATEnum("0.04", "Method:DELETE")); 32 | enumCode.push(new ATEnum("0.05", "Method:FETCH")); 33 | enumCode.push(new ATEnum("0.06", "Method:PATCH")); 34 | enumCode.push(new ATEnum("0.07", "Method:iPATCH")); 35 | enumCode.push(new ATEnum("2.01", "Success:Created")); 36 | enumCode.push(new ATEnum("2.02", "Success:Deleted")); 37 | enumCode.push(new ATEnum("2.03", "Success:Valid")); 38 | enumCode.push(new ATEnum("2.04", "Success:Changed")); 39 | enumCode.push(new ATEnum("2.05", "Success:Content")); 40 | enumCode.push(new ATEnum("2.31", "Success:Continue")); 41 | enumCode.push(new ATEnum("4.00", "Client Err:Bad Request")); 42 | enumCode.push(new ATEnum("4.01", "Client Err:Unauthorized")); 43 | enumCode.push(new ATEnum("4.02", "Client Er:Bad Option")); 44 | enumCode.push(new ATEnum("4.03", "Client Err:Forbidden")); 45 | enumCode.push(new ATEnum("4.04", "Client Err:Not Found")); 46 | enumCode.push(new ATEnum("4.05", "Client Err:Method Not Allowed")); 47 | enumCode.push(new ATEnum("4.06", "Client Err:Not Acceptable")); 48 | enumCode.push(new ATEnum("4.08", "Client Err:Req Enty.Incomplete")); 49 | enumCode.push(new ATEnum("4.09", "Client Err:Conflict")); 50 | enumCode.push(new ATEnum("4.12", "Client Err:Precondition Failed")); 51 | enumCode.push(new ATEnum("4.13", "Client Err:Req Enty Too Large")); 52 | enumCode.push(new ATEnum("4.15", "Client Err:Invalid Content-Format")); 53 | enumCode.push(new ATEnum("5.00", "Server Err:Internal server err.")); 54 | enumCode.push(new ATEnum("5.01", "Server Err:Not implemented")); 55 | enumCode.push(new ATEnum("5.02", "Server Err:Bad gateway")); 56 | enumCode.push(new ATEnum("5.03", "Server Err:Service unavailable")); 57 | enumCode.push(new ATEnum("5.04", "Server Err:Gateway timeout")); 58 | enumCode.push(new ATEnum("5.05", "Server Err:Proxying not supported")); 59 | enumCode.push(new ATEnum("7.00", "Signaling Codes: Unassigned")); 60 | enumCode.push(new ATEnum("7.01", "Signaling Codes: CSM")); 61 | enumCode.push(new ATEnum("7.02", "Signaling Codes: Ping")); 62 | enumCode.push(new ATEnum("7.03", "Signaling Codes: Pong")); 63 | enumCode.push(new ATEnum("7.04", "Signaling Codes: Release")); 64 | enumCode.push(new ATEnum("7.05", "Signaling Codes: Abort")); 65 | 66 | 67 | this.AddParam("convert", enumC, "convert"); 68 | this.AddParam("ver", "number", "convert"); 69 | this.AddParam("type", enumT, "convert"); 70 | this.AddParam("tkl", "number", "convert"); 71 | this.AddParam("code", enumCode, "convert"); 72 | this.AddParam("mid", "number", "message ID"); 73 | this.AddParam("token", "string", "convert"); 74 | this.AddParam("contentformat", "string", "convert"); 75 | this.AddParam("maxage", "string", "convert"); 76 | this.AddParam("etag", "string", "convert"); 77 | this.AddParam("accept", "string", "convert"); 78 | this.AddParam("ifmatch", "string", "convert"); 79 | this.AddParam("ifnonematch", "string", "convert"); 80 | this.AddParam("urihost", "string", "convert"); 81 | this.AddParam("uriport", "string", "convert"); 82 | this.AddParam("uripath", "string", "convert"); 83 | this.AddParam("uriquery", "string", "convert"); 84 | this.AddParam("locationpath", "string", "convert"); 85 | this.AddParam("locationquery", "string", "convert"); 86 | this.AddParam("proxyuri", "string", "convert"); 87 | this.AddParam("observe", "string", "convert"); 88 | this.AddParam("block2", "string", "convert"); 89 | this.AddParam("block1", "string", "convert"); 90 | this.AddParam("size", "string", "convert"); 91 | 92 | this.AddParam("length", "string", "convert"); 93 | this.AddParam("data", "string", "convert"); 94 | 95 | this.AddWriteAnswerParam({convert:null, length:null, data:null}); 96 | this.AddWriteAnswerParam({convert:null, ver:null, type:null, tkl:null, code:null, mid:null, token:null, contentformat:null, maxage:null, etag:null, accept:null, ifmatch:null, 97 | ifnonematch:null, urihost:null, uriport:null, uripath:null, uriquery:null, locationpath:null, locationquery:null, proxyuri:null, observe:null, 98 | block2:null, block1:null, size:null}); 99 | 100 | this.AddWriteSendParam({mid:null, convert:null}); 101 | } 102 | 103 | Parse(str) 104 | { 105 | super.Parse(str); 106 | 107 | this.#heads = []; 108 | 109 | let index = 0; 110 | this.GetLines().forEach(l=>{ 111 | if(this.value == "") this.value = l; 112 | if(l.indexOf("+CCOAPHEAD:") === 0) 113 | { 114 | if(this.GetRequestType() == "write") 115 | { 116 | const values = l.substring(this.GetCmd().length-1).trim().split(","); 117 | 118 | if(values.length >= 3) 119 | { 120 | this.#heads['convert'] = parseInt(values[0]); 121 | let i = 1; 122 | if(this.#heads['convert'] == 0) 123 | { 124 | this.#heads['length'] = values[i++]; 125 | this.#heads['data'] = values[i++]; 126 | } 127 | else if(this.#heads['convert'] == 1) 128 | { 129 | this.#heads['ver'] = values[i++]; 130 | this.#heads['type'] = values[i++]; 131 | this.#heads['tkl'] = values[i++]; 132 | this.#heads['code'] = values[i++]; 133 | this.#heads['mid'] = values[i++]; 134 | this.#heads['token'] = values[i++]; 135 | this.#heads['content-format'] = values[i++]; 136 | this.#heads['max-age'] = values[i++]; 137 | this.#heads['etag'] = values[i++]; 138 | this.#heads['accept'] = values[i++]; 139 | this.#heads['if-match'] = values[i++]; 140 | this.#heads['if-none-match'] = values[i++]; 141 | this.#heads['uri-host'] = values[i++]; 142 | this.#heads['uri-port'] = values[i++]; 143 | this.#heads['uri-path'] = values[i++]; 144 | this.#heads['uri-query'] = values[i++]; 145 | this.#heads['location-path'] = values[i++]; 146 | this.#heads['location-query'] = values[i++]; 147 | this.#heads['proxy-uri'] = values[i++]; 148 | this.#heads['observe'] = values[i++]; 149 | this.#heads['block2'] = values[i++]; 150 | this.#heads['block1'] = values[i++]; 151 | this.#heads['size'] = values[i++]; 152 | } 153 | } 154 | } 155 | index++; 156 | } 157 | }); 158 | return this.value; 159 | } 160 | 161 | ShowChat(div) 162 | { 163 | super.ShowChat(div); 164 | 165 | this.GetLines().forEach(l=>{ 166 | if(l.indexOf("+CCOAPHEAD:") === 0 && this.GetRequestType() == "write") 167 | { 168 | const values = l.substring(this.GetCmd().length-1).trim().split(","); 169 | if(values.length >= 3) 170 | { 171 | _CN("span", {}, ["convert: " + this.#heads['convert']], div); 172 | if(this.#heads['convert'] == 0) 173 | { 174 | _CN("span", {}, ["length: " + this.#heads['length']], div); 175 | _CN("span", {}, ["data: " + this.#heads['data']], div); 176 | } 177 | else if(this.#heads['convert'] == 1) 178 | { 179 | Object.keys(this.#heads).forEach(k=>{ 180 | if(this.#heads[k].length > 0) 181 | { 182 | _CN("span", {}, [k + ": " + this.#heads[k]], div); 183 | } 184 | }); 185 | } 186 | else 187 | { 188 | _CN("span", {}, ["Invalid convert type!"], div); 189 | } 190 | } 191 | } 192 | }); 193 | } 194 | }; -------------------------------------------------------------------------------- /js/tabHttps.js: -------------------------------------------------------------------------------- 1 | class TabHttps 2 | { 3 | Title = "HTTPs"; 4 | 5 | constructor() 6 | { 7 | this.div = _CN("div", {class:"box tab"}, [_CN("h2", {}, ["HTTPs"])], Tabs.GetDiv()); 8 | this.ctxindex = null; 9 | this.sslver = null; 10 | this.url = null; 11 | this.path = null; 12 | this.type = null; 13 | this.headers = null; 14 | this.params = null; 15 | 16 | 17 | setTimeout(()=>{ 18 | this.Init(); 19 | }, 200); 20 | } 21 | 22 | Init() 23 | { 24 | this.div.appendChild(Settings.GetGroupDiv("apn")); 25 | this.div.appendChild(Settings.GetGroupDiv("ssl")); 26 | 27 | _CN("button", {style:"margin:1vh;"}, ["Check Status"], this.div).addEventListener("click", ()=>{ 28 | this.CheckStatus(); 29 | }); 30 | 31 | _CN("button", {style:"margin:1vh;"}, ["Upload Certificate"], this.div).addEventListener("click", ()=>{ 32 | this.UploadSSL(); 33 | }); 34 | 35 | let addDiv = AT_CSSLCFG.GetParamDiv("ctxindex", "Select CTX Index", 1); 36 | this.div.appendChild(addDiv.div); 37 | this.ctxindex = addDiv.inp; 38 | 39 | addDiv = AT_CSSLCFG.GetParamDiv("sslversion", "Select SSL Version", 3); 40 | this.div.appendChild(addDiv.div); 41 | this.sslver = addDiv.inp; 42 | 43 | this.url = _CN("input", {type:"text", value:"", title:"https_url"}); 44 | _CN("div", {class:"paramdiv"}, [_CN("p", {}, ["https-url to make request (ex: https://www.xxx.ch)", this.url])], this.div); 45 | Settings.AutoSaveChanges(this.url); 46 | 47 | this.path = _CN("input", {type:"text", value:"", title:"https_path"}); 48 | _CN("div", {class:"paramdiv"}, [_CN("p", {}, ["https-path to make request (ex: directory/index.php)", this.path])], this.div); 49 | Settings.AutoSaveChanges(this.path); 50 | 51 | addDiv = AT_SHREQ.GetParamDiv("type", "Request type", 3); 52 | this.div.appendChild(addDiv.div); 53 | this.type = addDiv.inp; 54 | 55 | this.headers = _CN("textarea", {title:"https_headers", rows:5}, []); 56 | _CN("div", {class:"paramdiv"}, [_CN("p", {}, ["1 header for line (ex: Content-Type=application/x- www-form-urlencoded)", this.headers])], this.div); 57 | Settings.AutoSaveChanges(this.headers); 58 | 59 | this.params = _CN("textarea", {title:"https_params", rows:5}, []); 60 | _CN("div", {class:"paramdiv"}, [_CN("p", {}, ["1 parameter for line (ex: topic=my cats)", this.params])], this.div); 61 | Settings.AutoSaveChanges(this.params); 62 | 63 | _CN("button", {style:"margin:1vh;"}, ["SEND HTTPS REQUEST"], this.div).addEventListener("click", ()=>{ 64 | this.SendHttps(); 65 | }); 66 | 67 | } 68 | 69 | Select() 70 | { 71 | 72 | } 73 | 74 | CheckStatus() 75 | { 76 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 77 | 78 | return new Promise((res, rej) => { 79 | event.detail.info = "Check PIN"; 80 | window.dispatchEvent(event); 81 | 82 | // Check Pin 83 | AT_CPIN.Read().then(()=>{ 84 | 85 | if(AT_CPIN.GetState() == "READY") 86 | { 87 | event.detail.info = "Check Network"; 88 | window.dispatchEvent(event); 89 | // Check Signal 90 | AT_CSQ.Execute().then(()=>{ 91 | if(AT_CSQ.GetRSSI_dBm() >= -100) 92 | { 93 | // Check Network 94 | this.#AttachGPRS().then(()=>{ 95 | // Check Operator 96 | AT_COPS.Read().then(()=>{ 97 | if(AT_COPS.GetOperator().length > 1) 98 | { 99 | event.detail.info = "Check Apn"; 100 | window.dispatchEvent(event); 101 | AT_CGNAPN.Execute().then(()=>{ 102 | if(Settings.GetValue("apn", "url") == AT_CGNAPN.GetApn()) 103 | { 104 | event.detail.info = "HTTP-Connection successfully tested. Ready to be used."; 105 | window.dispatchEvent(event); 106 | res(); 107 | } 108 | else 109 | { 110 | rej(); 111 | } 112 | }).catch(e=>{this.#Error("NO APN", e); rej();}); 113 | } 114 | else 115 | { 116 | rej(); 117 | } 118 | }).catch(e=>{this.#Error("NO OPERATOR", e); rej();}); 119 | }).catch(e=>{this.#Error("NO GPRS", e); rej();}); 120 | } 121 | else 122 | { 123 | rej(); 124 | } 125 | }).catch(e=>{this.#Error("NO SIGNAL", e); rej();}); 126 | } 127 | }).catch(e=>{this.#Error("PIN ERROR", e); rej();}); 128 | }); 129 | } 130 | 131 | UploadSSL() 132 | { 133 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 134 | const FILE_NAME = Settings.GetValue("ssl", "name"); 135 | 136 | return new Promise((res, rej)=>{ 137 | AT_CFSINIT.Execute().then(()=>{ 138 | const cer = Settings.GetValue("ssl", "cer"); 139 | if(cer.length >= 10240) 140 | { 141 | this.#Error("Certificate is bigger than 10k!", null, {terminateFS:true}); 142 | rej(); 143 | return; 144 | } 145 | // try to delete the file, if it exists 146 | AT_CFSDFILE.Write([3, FILE_NAME]).finally(()=>{ 147 | setTimeout(()=>{ 148 | SIMSerial.SendData(cer); 149 | }, 500); 150 | // write file, 500ms after sending command 151 | AT_CFSWFILE.Write([3, FILE_NAME, 1, cer.length, 2000]).then(()=>{ 152 | // terminate file system 153 | AT_CFSTERM.Execute().finally(()=>{ 154 | AT_CSSLCFG.Write(["CONVERT", 2, FILE_NAME]).then(()=>{ 155 | 156 | event.detail.info = "SSL successfully uploaded and configured."; 157 | window.dispatchEvent(event); 158 | 159 | }).catch(e=>{this.#Error("SSL ERROR", e); rej();}); 160 | }); 161 | }).catch(e=>{this.#Error("CFSWFILE ERROR", e, {terminateFS:true}); rej();}); 162 | }); 163 | }).catch(e=>{this.#Error("FS NOT ACCESSIBLE", e, {terminateFS:true}); rej();}); 164 | }); 165 | } 166 | 167 | #SendHttpsValues(headers, step = 0) 168 | { 169 | if(step == 0) 170 | { 171 | return new Promise((res, rej)=>{ 172 | if(headers) 173 | { 174 | AT_SHCHEAD.Execute().then(()=>{ 175 | this.#SendHttpsValues(true, 1).then(()=>{ 176 | res(); 177 | }).catch(e=>{this.#Error("HEADs ERROR", e); rej();}); 178 | }).catch(e=>{this.#Error("AT_SHCHEAD ERROR", e); rej();}); 179 | } 180 | else 181 | { 182 | AT_SHCPARA.Execute().then(()=>{ 183 | this.#SendHttpsValues(false, 1).then(()=>{ 184 | res(); 185 | }).catch(e=>{this.#Error("PARAMs ERROR", e); rej();}); 186 | }).catch(e=>{this.#Error("AT_SHCPARA ERROR", e); rej();}); 187 | } 188 | }); 189 | } 190 | else 191 | { 192 | return new Promise((res, rej)=>{ 193 | if(headers) 194 | { 195 | let header_arr = []; 196 | this.headers.value.split("\n").forEach(h=>{if(h.length > 2) header_arr.push(h);}); 197 | if(step > header_arr.length) 198 | { 199 | res(); 200 | return; 201 | } 202 | const header = header_arr[step-1].trim().split("=", 2); 203 | AT_SHAHEAD.Write(['"' + header[0] + '"', '"' + header[1] + '"']).then(()=>{ 204 | 205 | this.#SendHttpsValues(true, step+1).then(()=>{ 206 | res(); 207 | }).catch(e=>{this.#Error("HEADs ERROR", e); rej();}); 208 | 209 | }).catch(e=>{this.#Error("AT_SHAHEAD ERROR", e); rej();}); 210 | } 211 | else 212 | { 213 | let params = []; 214 | this.params.value.split("\n").forEach(p=>{if(p.length > 2) params.push(p);}); 215 | if(step > params.length) 216 | { 217 | res(); 218 | return; 219 | } 220 | const param = params[step-1].trim().split("=", 2); 221 | AT_SHPARA.Write(['"' + param[0] + '"', '"' + param[1] + '"']).then(()=>{ 222 | 223 | this.#SendHttpsValues(false, step+1).then(()=>{ 224 | res(); 225 | }).catch(e=>{this.#Error("PARAMs ERROR", e); rej();}); 226 | 227 | }).catch(e=>{this.#Error("AT_SHPARA ERROR", e); rej();}); 228 | } 229 | }); 230 | } 231 | } 232 | 233 | SendHttps() 234 | { 235 | const event = new CustomEvent("cominfo", { detail: {info:""} }); 236 | 237 | return new Promise((res, rej)=>{ 238 | this.CheckStatus().then(()=>{ 239 | this.#ActivatePDP().then(()=>{ 240 | event.detail.info = "Configure SSL"; 241 | window.dispatchEvent(event); 242 | this.#SetCertificate().then(()=>{ 243 | // configure apn 244 | 245 | AT_SHCONF.Write(["URL", this.url.value]).then(()=>{ 246 | AT_SHCONF.Write(["BODYLEN", this.params.value.length + 100]).then(()=>{ 247 | AT_SHCONF.Write(["HEADERLEN", this.headers.value.length + 100]).then(()=>{ 248 | AT_SHCONN.Execute().then(()=>{ 249 | AT_SHSTATE.Read().then(()=>{ 250 | if(!AT_SHSTATE.IsConnected()) 251 | { 252 | this.#Error("Unable to connect", null, {disconnect:true}); 253 | rej(); 254 | } 255 | // send all headers 256 | this.#SendHttpsValues(true).then(()=>{ 257 | // send all params 258 | this.#SendHttpsValues(false).then(()=>{ 259 | 260 | AT_SHREQ.Write([this.path.value, this.type.value]).then(()=>{ 261 | 262 | if(/*AT_SHREQ.GetStatusCode() == 200 && */AT_SHREQ.GetDataLength() > 0) 263 | { 264 | AT_SHREAD.Write([0, AT_SHREQ.GetDataLength()]).then(()=>{ 265 | 266 | AT_SHDISC.Execute(); 267 | 268 | event.detail.info = "Request successfull."; 269 | window.dispatchEvent(event); 270 | 271 | }).catch(e=>{this.#Error("SHREQ ERROR", e, {disconnect:true}); rej();}); 272 | } 273 | else 274 | { 275 | this.#Error("Server ERROR", null, {disconnect:true}); 276 | rej(); 277 | } 278 | }).catch(e=>{this.#Error("SHREQ ERROR", e, {disconnect:true}); rej();}); 279 | 280 | }).catch(e=>{this.#Error("HEADERS ERROR", e, {disconnect:true}); rej();}); 281 | }).catch(e=>{this.#Error("HEADERS ERROR", e, {disconnect:true}); rej();}); 282 | 283 | }).catch(e=>{this.#Error("AT_SHSTATE ERROR", e, {disconnect:true}); rej();}); 284 | }).catch(e=>{this.#Error("AT_SHCONN ERROR", e, {disconnect:true}); rej();}); 285 | }).catch(e=>{this.#Error("AT_SHCONF HEADERLEN ERROR", e); rej();}); 286 | }).catch(e=>{this.#Error("AT_SHCONF BODYLEN ERROR", e); rej();}); 287 | }).catch(e=>{this.#Error("AT_SHCONF URL ERROR", e); rej();}); 288 | 289 | }).catch(e=>{this.#Error("CErtificate ERROR", e); rej();}); 290 | }).catch(e=>{this.#Error("PDP ERROR", e); rej();}); 291 | }).catch(e=>{this.#Error("CHECK ERROR", e); rej();}); 292 | }); 293 | } 294 | 295 | #SetCertificate() 296 | { 297 | return new Promise((res, rej)=>{ 298 | AT_CCLK.Read().then(()=>{ 299 | // Set time, if time is not right 300 | if(AT_CCLK.GetTime().getFullYear() != (new Date()).getFullYear()) 301 | { 302 | AT_CCLK.Write([AT_CCLK.ConvertTime(new Date())]).then(()=>{ 303 | AT_CCLK.Read().then(()=>{ 304 | if(AT_CCLK.GetTime().getFullYear() == (new Date()).getFullYear()) 305 | { 306 | return this.#SetCertificate(); 307 | } 308 | this.#Error("AT_CCLK ERROR", "Unable to set clock"); 309 | rej(); 310 | }).catch(e=>{this.#Error("AT_CCLK ERROR", e); rej();}); 311 | }); 312 | } 313 | else 314 | { 315 | AT_CSSLCFG.Write(["SSLVERSION", this.ctxindex.value, this.sslver.value]).then(()=>{ 316 | AT_SHSSL.Write([this.ctxindex.value, /*Settings.GetValue("ssl", "name")*/"\"\""]).then(()=>{ 317 | const url = this.url.value; 318 | if((url.match(/./g) || []).length < 2) 319 | { 320 | res(); 321 | } 322 | else // set sni 323 | { 324 | let domain = url.substring(url.indexOf("//") + 2); 325 | if(domain.indexOf("/") > 0) domain = domain.substring(domain.indexOf("/")); 326 | //AT+CSSLCFG="sni",1,"goldengames.ch" 327 | AT_CSSLCFG.Write(["SNI", this.ctxindex.value, domain]).then(()=>{ 328 | res(); 329 | }).catch(e=>{this.#Error("AT_CSSLCFG SNI ERROR", e); rej();}); 330 | } 331 | }).catch(e=>{this.#Error("AT_SHSSL ERROR", e); rej();}); 332 | }).catch(e=>{this.#Error("AT_CSSLCFG SSLVERSION ERROR", e); rej();}); 333 | } 334 | }).catch(e=>{this.#Error("AT_CCLK ERROR", e); rej();}); 335 | }); 336 | } 337 | 338 | #ActivatePDP() 339 | { 340 | let index = 0; 341 | 342 | return new Promise((res, rej)=>{ 343 | // Check if already active 344 | AT_CNACT.Read().then(()=>{ 345 | if(AT_CNACT.IsActive(index)) 346 | { 347 | res(); 348 | } 349 | else // not active, try to activate 350 | { 351 | AT_CNACT.Write([index, 1]).then(()=>{ 352 | AT_CNACT.Read().then(()=>{ 353 | if(AT_CNACT.IsActive(index)) 354 | { 355 | res(); 356 | } 357 | }).catch(e=>{this.#Error("AT_CNACT ERROR", e); rej();}); 358 | }).catch(e=>{this.#Error("AT_CNACT ERROR", e); rej();}); 359 | } 360 | }).catch(e=>{this.#Error("AT_CNACT ERROR", e); rej();}); 361 | }); 362 | } 363 | 364 | 365 | #AttachGPRS() 366 | { 367 | return new Promise((acc, rej)=>{ 368 | AT_CGATT.Read().then(()=>{ 369 | if(AT_CGATT.IsAttached()) 370 | { 371 | acc(); 372 | } 373 | else 374 | { 375 | AT_CGATT.Attach().then(()=>{ 376 | AT_CGATT.Read().then(()=>{ 377 | if(AT_CGATT.IsAttached()) 378 | { 379 | acc(); 380 | } 381 | else 382 | { 383 | rej(); 384 | } 385 | }).catch(()=>rej()); 386 | }).catch(()=>rej()); 387 | } 388 | }).catch(()=>rej()); 389 | }); 390 | } 391 | 392 | #Error(msg, e, o = {}) 393 | { 394 | console.error("HTTPS ERROR", e); 395 | const event = new CustomEvent("cominfo", { detail: {error:msg, event:e} }); 396 | window.dispatchEvent(event); 397 | 398 | if(o.terminateFS) 399 | { 400 | AT_CFSTERM.Execute(); 401 | } 402 | 403 | if(o.disconnect) 404 | { 405 | AT_SHDISC.Execute(); 406 | } 407 | } 408 | 409 | } 410 | 411 | Tabs.AddTab(new TabHttps()); --------------------------------------------------------------------------------