'Preamble OPTION BASE 0 CONST Mime$="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" CONST Secs=1000,Mins=Secs*60,Hrs=Mins*60 CONST GSM=1,GSMRST=16,LAN=2,LANRST=2,RL1=15 CONST GSMTRchg=30,PRchg=180,PCRchg=2,DnRmdr=5 CONST WDTime=60000 CONST q=chr$(34) CONST defHB="05:59" ' time to send the daily heartbeat message , set to -1 to disable CONST defPA="8.8.8.8" ' an address to ping on the internet CONST defAMbl$="+4470123456789" ' the "admin" mobile number CONST defIP="192.168.0.14" ' the unit's static IP address CONST defGW="192.168.0.1" ' its network gateway CONST defMS="255.255.255.0"' network mask CONST defAP="xyz" ' your wifi access point CONST defPW="bXkgcGFzc3dvcmQ==" ' and its password in B64 encoded form CONST defTmpAlm=40 ' the enclosure temperature alarm point ' 0-63 Flag CONSTs CONST SlaveSKT =0 CONST LANUp =1 CONST InetUp =2 CONST GSMUp =3 CONST GSMReg =4 CONST WDRst =7 CONST Conn =8 'HTTP channels 0... ' =9 ' =10 ' =11 ' =12 '... to 4 CONST HBFg =28 CONST ConRFG =29 CONST ConPFG =30 CONST TOFg =31 'H/W Init WATCHDOG OFF PIN(LANRST)=1:SETPIN LANRST,DOUT PIN(GSMRST)=0:SETPIN GSMRST,DOUT,OC PIN(RL1)=1:SETPIN RL1,DOUT,OC 'S/W Init DIM STRING A$,B$,D$,HBTm LENGTH 5,MAC LENGTH 20 DIM STRING PA$ LENGTH 15,IP$ LENGTH 15,GW$ LENGTH 15,MS$ LENGTH 15,AP$ LENGTH 32,PW$ LENGTH 32 DIM STRING LNBuf$,CBuf$,Ver LENGTH 64,LANRxLN$,LANTxLN$,TC$ LENGTH 1,LL1$ LENGTH 16,LL2$ LENGTH 16 DIM INTEGER FLAGS,h,m,C,Z,Chan,PTmr,PCt,RL1TMR DIM INTEGER LANf,GSMf,DSMSCt,OBSMSCt,IBSMSCt,Temp,TmpAlm DIM FLOAT x HBTm=defHB AMbl$=defAMbl$ TmpAlm=defTmpAlm PA$=defPA IP$=defIP GW$=defGW MS$=defMS AP$=defAP PW$=B64Dec$(defPW) Ver="SMS Gateway V1.2 (C)2016,2017" CL Ver,0 SetClock IF MM.WATCHDOG THEN FlagSet WDRst:CL "*** RESTART FORCED BY WATCHDOG ***",0 ELSE FlagRes WDRst FLAGS=0:FlagSet SlaveSKT TC$=" ":a$=Replace$(Replace$(DS$(),":",""),"-","") LL2$= MID$(a$,3,6) + MID$(a$,10,4) + STRING$(6," ") BuildLCD CL "System coming up",0 'timer inits PTmr=PRchg GSMPollTMR=GSMTRchg PCt=1:RL1TMR=-1 CL "Starting LAN Interface",0 TIMER=0 Open "COM2:9600,1024" As #LAN ESP8266Reset FlagSet LANUp:FlagSet InetUp CL "... LAN up in "+STR$(TIMER)+"mS",0 CL "Starting GSM Interface",0 Chan=TIMER Open "COM1:9600,8192" As #GSM M590Reset FlagSet GSMUp:FlagSet GSMReg CL "... GSM up in "+STR$(TIMER-Chan)+"mS",0 CL "Starting Core timer thread",0 SETTICK 1*Secs,CoreTMR,4 CL "Boot took "+STR$(TIMER)+"mS",0 GL GSMSend(AMbl$,"SMS Gateway has started") CL "System Running",0 GetTemp Main: WATCHDOG=WDTime IF LEFT$(TIME$,5)=HBTm THEN IF FlagTest(HBFg)=0 THEN GL GSMSend(AMbl$,"SMS Gateway heartbeat. " + DATE$ + " " + TIME$) FlagSet HBFg END IF ELSE FlagRes HBFg END IF IF RL1TMR=0 then RL1TMR=-1 FlagSet SlaveSKT PIN(RL1)=1 A$="Slave socket power ON" CL A$,0 GL GSMSend(AMbl$,A$) END IF IF PTmr<=0 THEN PTmr=PRchg A$=ESP8266Exec$("AT+PING="+q+PA+q,4000,0) IF A$="OK" THEN IF FlagTest(InetUp)=0 THEN GL GSMSend(AMbl$,"I/Net UP") END IF FlagSet InetUp CL "I/Net connected OK",0 LANf=0:DSMSCt=0 PCt=PCRchg ELSE FlagRes InetUp LANf=LANf+1:IF LANf>9 THEN LANf=9 CL "I/Net Down",0 PCt=PCt-1 IF PCt=0 THEN GL GSMSend(AMbl$,"I/Net DOWN, please check") ELSE CL "... for "+STR$(ABS(PCt)*PRchg),0 x=ABS(PCt)/DnRmdr IF x=INT(x) AND x>0 THEN DSMSCt=DSMSCt+1:IF DSMSCt>99 THEN DSMSCt=99 GL GSMSend(AMbl$,"I/Net remains DOWN, please check") END IF END IF END IF 'convenient place GetTemp SetClock CL "Enclosure Temp " + str$(Temp)+"C",0 END IF IF GSMPollTMR<=0 THEN GSMPollTMR=GSMTRchg A$="AT+CREG?" A$=M590Exec$(A$,2,0,"+CREG: 0,1") IF A$="T/O" OR A$="ERROR" THEN FlagRes GSMReg GSMf=GSMf+1:IF GSMf>9 THEN GSMf=9 CL A$,0 CL "GSM not registered",0 ELSE FlagSet GSMReg GSMf=0 CL A$,0 CL "GSM registration OK",0 END IF FlushIO(GSM) 'check recieved messages A$="AT+CMGL=4" CL A$,0 PRINT#GSM,A$ PAUSE 500 DO A$=GetIO$(GSM,2) IF A$<>"" then CL A$,0 IF A$="OK" THEN EXIT DO IF INSTR(A$,"+CMGL:") THEN 'envelope B$=GetIO$(GSM,2) 'message CL B$,0 A$=Replace$(A$,CHR$(34),"") z=Split(A$,",") ' 1 2 3 4 5 6 '+CMGL: 1,REC UNREAD,+447777777,,16/10/07,22:11:35+04 IF SP$(2)="REC UNREAD" THEN IF RIGHT$(RTRim$(SP$(3)),13)=AMbl$ THEN SELECT CASE UCASE$(B$) CASE "AFGHANISTANBANANASTAND" ' magic message from admin mobile to activate the relay FlagRes SlaveSKT PIN(RL1)=0:RL1TMR=10 A$="Slave socket power OFF" CL A$,0 GL GSMSend(AMbl$,A$) CASE "PING" GL GSMSend(AMbl$,"OK FLAGS="+RIGHT$(BIN$(FLAGS,8),8)+" "+STR$(Temp)+"C") END SELECT END IF END IF END IF LOOP A$="AT+CMGD=1,1" A$=M590Exec$(A$,2,0,"OK") FlushIO(GSM) END IF 'Console input A$=INKEY$ DO WHILE A$<>"" SELECT CASE ASC(A$) CASE 13 IF CBuf$<>"" THEN CBuf$=UCASE$(CBuf$):FlagSet ConRFG CASE 0 TO 31 CASE 127 TO 255 CASE ELSE IF LEN(CBuf$)<255 THEN CBuf$=CBuf$+A$ ELSE CL "Console buffer over-run",0:CBuf$="":FlagRes ConRFG END IF END SELECT A$=INKEY$ LOOP IF FlagTest(ConRFG)=1 THEN 'parse the commands FlagRes ConPFG args=Split(Trim$(CBuf$)," ") SELECT CASE SP$(1) ' individual verbs CASE "HELP" CL SP$(1),0 CL "Console commands:",0 CL " HELP =This list.",0 CL " DEBUG =Show internal flags etc.",0 CL " HEARTBEAT hh:mm|-1 =Set/Disable daily Heartbeat SMS time (24H)",0 CL " ADMINPH +44<num> =Set the Admin mobile No.",0 CL " NETWORK DHCP|STATIC [<ip> <mask> <gateway>] =Set the LAN IP Address",0 CL " PING <ip> =Set the Internet test IP Address",0 CL "",0 CL "Current Settings:",0 CL " Admin Phone No. "+AMbl$ CL " Heartbeat SMS "+HBTm CL " IP,Gateway,Mask "+IP$+" "+GW$+" "+MS$,0 CL " MAC address "+MAC,0 CL " Inet Ping IP "+PA$,0 CL "",0 CL " Enclosure Temp " + str$(Temp)+"C",0 CL " Temp alarm at " + str$(TmpAlm)+"C",0 CL "",0 CL "Additional material:",0 CL " Geoff Graham (MMBasic) and MicroMite.org (MicroMite)",0 CL "",0 CASE "DEBUG" CL SP$(1),0 CL "FLAGS="+Bin$(FLAGS,32),0 CASE "HEARTBEAT" IF args<2 THEN FlagSet ConPFG ELSE IF SP$(2)="-1" then HBTm=SP$(2):CL "Daily heartbeat disabled",0:GOTO HBTExit IF LEN(SP$(2))<>5 then FlagSet ConPFG ELSE z=VAL(LEFT$(SP$(2),2)) IF z<0 OR z>23 THEN 'hours FlagSet ConPFG ELSE z=VAL(RIGHT$(SP$(2),2)) 'Mins IF z<0 OR z>59 THEN FlagSet ConPFG ELSE IF MID$(SP$(2),3,1)<>":" THEN 'seperator FlagSet ConPFG ELSE HBTm=SP$(2) CL "Daily heartbeat set : "+SP$(2),0 END IF END IF END IF END IF END IF HBTExit: CASE ELSE FlagSet ConPFG END SELECT IF FlagTest(ConPFG)=1 THEN CL "Malformed command: "+CBuf$,0 END IF CBuf$="":FlagRes ConRFG END IF 'Web API parsing LANRxLN$=GetIO$(LAN,1) IF LANRxLN$="" OR LANRxLN$="T/O" THEN GOTO Main CL LANRxLN$,0 IF MID$(LANRxLN$,2,8)=",CONNECT" THEN Chan=VAL(LANRxLN$) IF Chan>=0 AND Chan<=4 THEN FlagSet Conn+Chan CL "Inbound connect channel "+STR$(Chan),0 GOTO IPEXIT END IF END IF IF MID$(LANRxLN$,2,7)=",CLOSED" THEN Chan=VAL(LANRxLN$) IF Chan>=0 AND Chan<=4 THEN IF FlagTest(Conn+Chan)=0 THEN A$="Abnormally " ELSE A$="" CL "Closed channel "+STR$(Chan),0 FlagRes Conn+Chan GOTO IPEXIT END IF END IF IF LEFT$(LANRxLN$,5)="+IPD," THEN DO:a$=GetIO$(LAN,2):LOOP UNTIL a$="Connection: Keep-Alive" Chan=VAL(MID$(LANRxLN$,6,1)) IF Chan>4 THEN GOTO IPDerrEXIT IF FlagTest(Conn+Chan)=0 THEN GOTO IPDerrEXIT 'channel not open z=INSTR(LANRxLN$,":GET /") '+IPD,0,nnn:GET /smssend?tel=077?msg=XYZ HTTP/1.1 IF z=0 THEN GOTO IPDerrEXIT LANRxLN$=MID$(LANRxLN$,z+6) z=INSTR(LANRxLN$," HTTP") IF z=0 THEN GOTO IPDerrEXIT LANRxLN$=LEFT$(LANRxLN$,z-1) args=Split(Replace$(LANRxLN$,"+"," "),"?") SELECT CASE SP$(1) CASE "smssend" IF args <3 THEN GOTO IPDerrEXIT Tel$="":Msg$="" FOR n=2 TO args a$=Trim$(URLDecode$(MID$(sp$(n),5))) SELECT CASE LEFT$(ucase$(SP$(n)),4) CASE "TEL=" Tel$=a$ CASE "MSG=" Msg$=a$ END SELECT NEXT IF Tel$="" OR Msg$="" THEN GOTO IPDerrEXIT CL "O/B SMS "+Tel$+":"+Msg$,0 z=GSMSend(Tel$,Msg$) IF z=0 THEN B$="OK: Message Queued for sending":GOTO IPOKEXIT ELSE B$="ERROR: Gateway failed to send message {"+STR$(z)+"}" GOTO IPOKEXIT END IF CASE "stat" 'IF z=>8 AND Z<=11 THEN 'other API calls go here... 'z=INSTR(LANRxLN$,":GET /whatever?") 'IF z<>0 THEN 'etc... ' B$="OK: STAT="+LL1$+LL2$ ' GOTO IPOKEXIT END SELECT GOTO IPDerrEXIT 'default action IF we don't find an API call END IF GOTO IPEXIT IPDerrEXIT: B$="ERROR: Malformed request {"+LANRxLN$+"}" IPOKEXIT: PRINT #LAN,"AT+CIPSENDEX="+STR$(Chan)+",255" PAUSE 100 PRINT#LAN,B$+"\0" PAUSE 100 PRINT#LAN,"AT+CIPCLOSE="+STR$(Chan) FlagRes Conn+Chan IPEXIT: GOTO Main '------------------ ESP8266 WiFi Modem SUBsys ------------- SUB ESP8266Reset LOCAL STRING A$ LOCAL INTEGER N FlagRes LANUp PULSE LANRST,10 PAUSE 400 LANExec "ATE0",2,0 LANExec "AT+CWAUTOCONN=0",2,0 LANExec "AT+CWMODE=1",2,0 LANExec "AT+CWQAP",4,0 LANExec "AT+RFVDD",2,0 LANExec "AT+CWJAP="+q+AP$+q+","+q+PW$+q,10,1 LANExec "AT+CIPSTA="+q+IP$+q+","+q+GW$+q+","+q+MS$+q,2,0 LANExec "AT+CIFSR",2,0 LANExec "AT+CWAUTOCONN=1",2,0 LANExec "AT+CIPMUX=1",2,0 LANExec "AT+CIPSERVER=1,19090",2,0 LANTxLN$="":LANRxLN$="" FlagSet LANUp END SUB SUB LANExec(CM$,T,Suppress) LOCAL STRING A$ A$=ESP8266Exec$(CM$,T,Suppress) IF Suppress<2 THEN CL A$,0 END SUB FUNCTION ESP8266Exec$(Com$,TimeOut,Obf) LOCAL STRING A$ LENGTH 1,LN$ LOCAL INTEGER C CL Com$,obf PRINT #LAN,Com$ DO LN$=GetIO$(LAN,TimeOut) ' get special values IF INSTR(LN$,"+CIFSR:STAMAC,")<>0 THEN MAC=MID$(LN$,16) MAC=LEFT$(MAC,INSTR(MAC,CHR$(34))-1) END IF IF INSTR(LN$,"WIFI DISCONNECT") THEN FlagRes(LANUp) IF INSTR(LN$,"WIFI CONNECTED") THEN FlagSet(LANUp) IF LN$="T/O" THEN ESP8266Exec$="T/O":FlagRes LANUp:EXIT DO IF LN$<>"" THEN IF Obf<2 THEN CL "["+LN$+"]",0 IF LN$="OK" OR LN$=">" OR LN$="SEND OK" THEN ESP8266Exec$=LN$:EXIT DO IF INSTR(LN$,"ERROR") THEN ESP8266Exec$="ERROR ["+LNBuf$+"]":EXIT DO END IF LOOP END FUNCTION '------------------ M590 GSM Modem SUBsys ----------------------- SUB M590Reset LOCAL STRING A$ LOCAL INTEGER N PIN(GSMRST)=0 'can't use pulse because it should already be lo PAUSE 500 'BOOT is active LO and at least 300mS PIN(GSMRST)=1 ClearTOTimer DO IF FlagTest(TOFg) THEN GOTO GSMFail A$=GetIO$(GSM,5) CL A$,0 LOOP UNTIL A$="MODEM:STARTUP" ClearTOTimer DO IF FlagTest(TOFg) THEN GOTO GSMFail A$=GetIO$(GSM,120) CL A$,0 LOOP UNTIL A$="+PBREADY" FlushIO(GSM) GSMExec "ATE0",2,0,"OK" '(TURN OFF LOCAL ECHO) FlushIO(GSM) GSMExec "AT+CPAS",2,0,"+CPAS: 0" IF FlagTest(TOFg) THEN GOTO GSMFail DO PRINT #GSM,"AT+CREG?" DO:A$=GetIO$(GSM,2):LOOP WHILE LEN(A$)=0 CL A$,0 IF FlagTest(TOFg) THEN GOTO CREGWait IF INSTR(A$,"+CREG:") THEN IF INSTR(A$,"+CREG: 0,1")=0 THEN ' registered? GOTO CREGWait ELSE CL "Registered on GSM network",0 GSMf=0 EXIT DO END IF END IF CREGWait: CL "Waiting for GSM network registration",0 PAUSE 5000 FlushIO(GSM) GSMf=1 LOOP IF GSMf THEN GOTO GSMFail GSMf=0 GSMExec "AT+ENPWRSAVE=0",2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+COPS?",2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+CSQ",2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+XBANDSEL?",2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+CCID?",2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+CSCA?",2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+CFUN?",2,0,"+CFUN: 1,0" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+CPIN?",2,0,"+CPIN: READY" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+CSMS?",2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+CMGF=1",2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+CSCS="+CHR$(34)+"GSM"+CHR$(34),2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) GSMExec "AT+CMGD=1,1",2,0,"OK" IF FlagTest(TOFg) THEN GOTO GSMFail FlushIO(GSM) EXIT SUB GSMFail: FlagRes GSMUp GSMf=1 CL "... Failed to start in "+STR$(TIMER-Chan)+"mS",0 END SUB SUB GSMExec(CM$,T,obf,Resp$) LOCAL STRING A$ A$=M590Exec$(CM$,T,obf,Resp$):CL A$,0 END SUB FUNCTION M590Exec$(Com$,TimeOut,obf,Resp$) LOCAL STRING A$ LENGTH 1,LN$,LNBuf$ LOCAL INTEGER C,n,z CL Com$,obf z=Split(Resp$,"|") PRINT #GSM,Com$ StartTOTimer TimeOut DO IF FlagTest(TOFg) THEN M590Exec$="T/O ["+LNBuf$+"]":FlagRes GSMUp:EXIT DO IF LOC(#GSM)<>0 THEN A$=INPUT$(1,#GSM):C=ASC(A$) SELECT CASE C CASE 13 IF LN$<>"" THEN LNBuf$=LNBuf$+LN$ CL "["+LNBuf$+"]",0 FOR n=1 TO z IF LN$=SP$(n) THEN M590Exec$=LN$:EXIT DO NEXT IF INSTR(LN$,"ERROR") THEN M590Exec$="ERROR ["+LNBuf$+"]":FlagRes GSMUp:EXIT DO LN$="":LNBuf$="" END IF CASE 0 TO 31 CASE ELSE LN$=LN$+A$ END SELECT END IF LOOP ClearTOTimer FlagSet GSMUp END FUNCTION FUNCTION GSMSend(t$,m$) LOCAL INTEGER n LOCAL STRING A$ IF GSMf<>0 THEN GSMSend=10191:EXIT FUNCTION a$="AT+CMGS="+chr$(34)+t$+CHR$(34) PRINT#GSM,A$ CL A$,0 PAUSE 1000 a$=LEFT$(m$,140) PRINT#GSM,A$+CHR$(26); CL a$,0 PAUSE 100 DO A$=GetIO$(GSM,15) CL A$,0 IF INSTR(A$,"+CMGS:") THEN GSMSend=0:EXIT FUNCTION IF A$="T/O" THEN EXIT DO LOOP GSMSend=10156 END FUNCTION SUB GL(z as integer) IF z=0 then CL "SMS Send OK",0 ELSE CL "SMS Send Fail ("+STR$(z)+")",0 END SUB '---------------------------------------------------- SUB CL(Com$,obf) SELECT CASE Obf CASE 0 PRINT DS$();Com$ CASE 1 PRINT DS$();STRING$(20,"#") CASE ELSE END SELECT END SUB FUNCTION GetIO$(io,TimeOut) LOCAL STRING a$,b$ LOCAL INTEGER c StartTOTimer TimeOut DO IF FlagTest(TOFg) THEN GetIO$="T/O":EXIT DO IF LOC(#io)<>0 THEN A$=INPUT$(1,#io):C=ASC(A$) SELECT CASE C CASE 13 GetIO$=b$:EXIT DO CASE 0 TO 31 CASE ELSE IF LEN(b$)+LEN(a$)<255 THEN b$=b$+a$ ELSE b$=a$ END SELECT END IF LOOP ClearTOTimer END FUNCTION SUB FlushIO(stream) LOCAL STRING A$ DO WHILE LOC(#stream)<>0 PAUSE 50:A$=INPUT$(LOC(#stream),#stream):PAUSE 50 LOOP END SUB SUB CoreTMR PTmr=PTmr-1 GSMPollTMR=GSMPollTMR-1 RL1TMR=RL1TMR-1 IF TC$="*" THEN TC$=" " ELSE TC$="*" BuildLCD END SUB SUB StartTOTimer(Timeout) FlagRes TOFg:SETTICK TimeOut*1000,SetTOFg,2 END SUB SUB ClearTOTimer SETTICK 0,0,2:FlagRes TOFg END SUB SUB SetTOFg FlagSet TOFg END SUB SUB BuildLCD LL1$="L" + STR$(LANf) + "G" + STR$(GSMf) + "S" + STR$(PIN(16)) + "O" + STR$(OBSMSCt,4,0,"0") + "I" + STR$(IBSMSCt,4,0,"0") LL2$=LEFT$(LL2$,10) + " " + TC$ + STR$(DSMSCt,2,0,"0") 'PRINT LL1$:PRINT LL2$:PRINT END SUB FUNCTION DS$() LOCAL a$,b$ DO:a$=date$:b$=time$:LOOP WHILE a$<>date$ OR b$<>time$ DS$=RIGHT$(a$,4)+MID$(a$,3,3)+"-"+LEFT$(a$,2)+" "+b$+" " END FUNCTION FUNCTION Replace$(a$,b$,c$) LOCAL INTEGER z LOCAL STRING x$,y$ z=1 DO z=INSTR(z,a$,b$) IF z=0 THEN EXIT DO x$=LEFT$(a$,z-1):y$=MID$(a$,z+LEN(b$)):a$=x$+c$+y$:z=LEN(x$)+LEN(c$) LOOP Replace$=a$ END FUNCTION FUNCTION URLDecode$(a$) LOCAL INTEGER z LOCAL STRING b$,c$ z=1 DO z=INSTR(z,a$,"%") IF z=0 OR z=LEN(a$) THEN EXIT DO b$=MID$(a$,z,3):c$=CHR$(VAL("&h"+MID$(b$,2))):a$=Replace$(a$,b$,c$) LOOP URLDecode$=a$ END FUNCTION FUNCTION Trim$(a$) Trim$=LTrim$(RTrim$(a$)) END FUNCTION FUNCTION LTrim$(a$) LOCAL INTEGER m FOR m=1 TO LEN(a$) IF NOT(MID$(a$,m,1)=" " OR MID$(a$,m,1)=CHR$(9)) THEN LTrim$=MID$(a$,m):EXIT FUNCTION NEXT LTrim$="" END FUNCTION FUNCTION RTrim$(a$) LOCAL INTEGER n FOR n=LEN(a$) TO 1 STEP -1 IF NOT(MID$(a$,n,1)=" " OR MID$(a$,n,1)=CHR$(9)) THEN RTrim$=LEFT$(a$,n):EXIT FUNCTION NEXT RTrim$="" END FUNCTION FUNCTION Split(a$,b$) LOCAL INTEGER z,n,m ON ERROR SKIP ERASE SP$ z=1:n=0 DO z=INSTR(z,a$,b$) IF z=0 THEN IF n=0 THEN DIM SP$(1):SP$(1)=a$:Split=1:EXIT FUNCTION ELSE EXIT DO END IF ELSE n=n+1:z=z+LEN(b$) END IF LOOP m=n+1:n=1 DIM SP$(m) DO z=INSTR(1,a$,b$) IF z=0 THEN SP$(m)=a$:EXIT DO ELSE SP$(n)=LEFT$(a$,z-1):a$=MID$(a$,z+LEN(b$)):n=n+1 END IF LOOP Split=m END FUNCTION SUB FlagSet(bit AS INTEGER) FLAGS=FLAGS OR (2^bit) END SUB SUB FlagRes(bit AS INTEGER) FLAGS=(FLAGS OR (2^bit)) XOR (2^bit) END SUB FUNCTION FlagTest(bit AS INTEGER) AS INTEGER FlagTest=ABS(SGN(FLAGS AND (2^bit))) END FUNCTION FUNCTION B64Dec$(x$) LOCAL INTEGER w1,w2,w3,w4,n LOCAL STRING so$ FOR n=1 TO LEN(x$) STEP 4 w1=MD(MID$(x$,n,1)):w2=MD(MID$(x$,n+1,1)):w3=MD(MID$(x$,n+2,1)):w4=MD(MID$(x$,n+3,1)) IF w2>=0 THEN so$=so$+CHR$(((w1*4+INT(w2/16)) AND 255)) IF w3>=0 THEN so$=so$+CHR$(((w2*16+INT(w3/4)) AND 255)) IF w4>=0 THEN so$=so$+CHR$(((w3*64+w4) AND 255)) NEXT B64Dec$=so$ END FUNCTION FUNCTION MD(x$) IF LEN(x$)=0 THEN MD=-1 ELSE MD=INSTR(Mime$,x$)-1 END FUNCTION SUB SetClock RTC GETTIME END SUB SUB GetTemp RTC GetReg 17,Temp IF Temp>=TmpAlm THEN GL GSMSend(AMbl$,"Enclosure temperature alarm! Temp is " + str$(Temp)+"C Threshold is " + str$(TmpAlm)+"C") END SUB