Script Library: 1213 scripts
 

sms-funcs.r

REBOL [ Title: "sms-Functions" Version: 1.1.0 Date: 25-Jul-2006 Author: "Janeks Kamerovskis" File: %sms-funcs.r Purpose: { funcions that allows send and receive SMS by GSM modem } notes: { } library: [ level: 'intermediate platform: 'all type: [ function tutorial tool] domain: [ other-net ] tested-under: [ REBOL/View 1.3.50.3.1 on "Windows XP"] support: none license: none see-also: none ] ] ;this shoud be specified here or somwhere else: ;this is valid for Windoze system/ports/serial: [ com1 com2 com3 com4 com5 com6 com7 com8 com9 com10 ] ; --->>> ar šo nez kāpēc velk tikai uz Com1 ti. neiet. ja lieto paplašināto porta specifikāciju!!! ;system/ports/serial: [ com6 ] ; ar šo strādā ja lieto paplašināto porta specifikāciju - ņem tikai port1 ;for other system should be something another ;... sms-in-dir: %smsesin/ sms-out-dir: %smsesout/ sms-unsent-dir: %smsesunsent/ sms-in-dir: join what-dir sms-in-dir sms-out-dir: join what-dir sms-out-dir sms-unsent-dir: join what-dir sms-unsent-dir stat-file: join what-dir %cell-stats ; setting this value forces to do not test for phone model with AT commands ; [ "brandname" "full model name" ] ;phone-model: [ "SIEMENS" "SIEMENS MC35i" ] ;phone-model: [ "Nokia" "Nokia 30" ] phone-brands:[ ; "AT" "Nokia" "SIEMENS" ] ;last error log file if not value? 'last-error-log-file [ last-error-log-file: %last_err.log ] send-str: func [ str2send port ][ for i 1 (length? str2send) 1 [ insert port to-char str2send/:i ] ] open-sms-port: func [ sp-name [ string! ] "Serial port name of GSM modem" /local rez sp rez-obj ][ rez-obj: make object! [ serial-port: none open-reply: none phone: make object! [ brandname: none model: none ] ] either not error? sp: try [ gpsPort: rejoin [ "port" index? find system/ports/serial to-word sp-name ] ; open/mode to-url rejoin [ "serial://" gpsPort "/9600/8/none/1" ] [ write read string no-wait ] ; open/mode to-url rejoin [ "serial://" gpsPort "/9600/8/none/1" ] [ write read string no-wait ] open/mode to-url rejoin [ "serial://" gpsPort "/19200/8/none/1" ] [ write read no-wait direct ] ; open/mode serial://port1/9600/none [write read string no-wait] ; sp: open/mode [ ; open/mode [ ; scheme: 'serial ; host: 'port7 ; how to corectly put here gpsPort value ??? ; host: to-word rejoin [ "port" index? find system/ports/serial to-word sp-name ] ; ][ write read string no-wait ] ][ insert sp rejoin [ "ATE" crlf ] rez: last parse copy wait [ 0.1 sp ] crlf either "OK" = rez [ insert sp "AT+CMGF=1^M^/" copy wait [ 0.1 sp ] either not value? 'phone-model [ rez-obj/serial-port: sp rez-obj/open-reply: "OK" rez-obj/phone/brandname: first check-phone-model sp rez-obj/phone/model: second check-phone-model sp ][ either phone-model [ rez-obj/serial-port: sp rez-obj/open-reply: "OK" rez-obj/phone/brandname: first phone-model rez-obj/phone/model: second phone-model ][ rez-obj/serial-port: sp rez-obj/open-reply: "OK" rez-obj/phone/brandname: first check-phone-model sp rez-obj/phone/model: second check-phone-model sp ] ] ][ rez-obj/serial-port: sp rez-obj/open-reply: rez ] ][ rez-obj/open-reply: "Port could not be opened!" ] return rez-obj ] check-phone-model: func [ sp [ port! ] "Opened serial port" /local rez phb ][ insert sp rejoin [ "ATI" crlf ] rez: parse copy wait [ 0.1 sp ] crlf foreach wrd phone-brands [ if find rez wrd [ phb: wrd ] ] switch/default phb [ "Nokia" [ insert sp rejoin [ "ATI3" crlf ] rez: parse copy wait [ 0.1 sp ] crlf reduce [ phb rejoin [ rez/1 " " rez/2 ] ] ] "Siemens" [ reduce [ phb rejoin [ rez/1 " " rez/2 ] ] ] ][ [ "AT" "Unknown" ] ] ] sends-sms: func [ mp [ object! ] "Phone/modem object (see code)" ph [ string! number! ] "Phone number to send" msg [ string! ] "Message text" /local modcoms rez ][ modcoms: reduce [ rejoin [ "AT+CMGF=1" crlf ] rejoin [ "AT+CMGS=" {"} ph {"} crlf ] rejoin [ msg to-char 26 ] rejoin [ {+CMGS: 5} crlf ] ;check for that message is accepted in modem? ] foreach cm modcoms [ insert mp/serial-port cm wait 1 rez: parse copy wait mp/serial-port crlf ; probe rez if not attempt [ rez: last rez ][ ;Probably need to change to be shure that port is empty rez: "EMPTY REZ" ] if rez = "ERROR" [ break ] ] return rez ] write-sms: func [ {Write sms to modem storage. Returns stored message ID Note: Modem should be set to text mode (AT+CMGF=1)} mp [ object! ] "Phone/modem object (see code)" ph [ string! number! ] "Phone number to send" msg [ string! ] "Message text" /local rez ][ rez: copy [] insert mp/serial-port rejoin [ "AT+CMGW=" {"} ph {"} crlf ] repend rez parse copy wait mp/serial-port crlf insert mp/serial-port rejoin [ msg to-char 26 ] repend rez parse copy wait mp/serial-port crlf either try [ rez: to-integer select rez "+CMGW:" ] [ rez ][ last rez ] ] send-stored-sms: func [ {Send sms from modem storage Note: Modem should be set to text mode (AT+CMGF=1)} mp [ object! ] "Phone/modem object (see code)" id [ string! number! ] "Stored message ID" /local rez ][ rez: copy [] insert mp/serial-port rejoin [ "AT+CMSS=" id crlf ] repend rez parse copy wait mp/serial-port crlf either "OK" = last rez [ select rez "+CMSS:" ][ last rez ] ] send-sms: func [ mp [ object! ] "Phone/modem object (see code)" ph [ string! number! ] "Phone number to send" msg [ string! ] "Message text" /local id rez ][ id: write-sms mp ph msg either number? id [ rez: send-stored-sms mp id erase-sms mp id ][ "ERROR" ] return rez ] file-num: func [n] [ ; Output 000n file name format: n: form n insert/dup n "0" 4 - length? n to-file n ] convert-date-time: func [ sms-date-time /local datex ][ datex: parse first parse sms-date-time "," "/" to-date rejoin [ rejoin [ reverse copy/part next load form datex 2 add first copy/part load form datex 1 2000 ] to-time second parse sms-date-time "," ] ] sms: make object! [ ID: none status: none dest-phone: none src-phone: none date-time: none content: "" ] reset-sms: func [ ; sms [ object! ] ][ sms/ID: none sms/status: none sms/dest-phone: none sms/src-phone: none sms/date-time: none sms/content: copy "" ] read-sms: func [ {Read sms from modem storage Note: Modem should be set to text mode (AT+CMGF=1)} mp [ object! ] "Phone/modem object (see code)" /only "Filter only given types of SMSes" sms-type [ string! block! ] {SMS type: any of "STO SENT", "STO UNSENT", "REC READ", "REC UNREAD" } /local rez smses sms-id r-lines ][ sms-id: none smses: copy [] rez: copy [] r-lines: copy [] either only [ insert mp/serial-port rejoin [ {AT+CMGL="} sms-type {"} crlf ] ][ insert mp/serial-port rejoin [ {AT+CMGL="ALL"} crlf ] ] wait 1 while [ rez: parse/all copy wait [ 0.1 mp/serial-port ] crlf all [ not "OK" = last rez not "ERROR" = last rez ] ][ either mp/phone/brandname = "Siemens" [ repend r-lines rez ][ repend r-lines next rez ] wait 1 ] either mp/phone/brandname = "Siemens" [ repend r-lines rez ][ repend r-lines next rez ] r-lines: copy/part r-lines ( length? r-lines ) - 2 foreach resp-line r-lines [ either "+CMGL:" = copy/part resp-line 6 [ reset-sms sms sms-blk: parse/all resp-line "," sms-id: to-integer second parse sms-blk/1 " " switch sms-blk/2 [ "STO SENT" [ sms/status: sms-blk/2 sms/id: sms-id sms/dest-phone: sms-blk/3 ] "STO UNSENT" [ sms/status: sms-blk/2 sms/id: sms-id ] "REC READ" [ sms/status: sms-blk/2 sms/id: sms-id sms/src-phone: sms-blk/3 sms/date-time: convert-date-time sms-blk/5 "," ] "REC UNREAD" [ sms/status: sms-blk/2 sms/id: sms-id sms/src-phone: sms-blk/3 sms/date-time: convert-date-time sms-blk/5 "," ] ] repend smses [ sms-id sms-blk ] ][ if sms-id [ if 0 < length? sms/content [ sms/content: repend sms/content newline ] sms/content: repend sms/content resp-line change/only next find smses sms-id make sms [] ] ] ] rez: smses ; if empty? rez [ ; rez: "EMPTY REZ" ; ] ; if rez = "ERROR" [ break ] return rez ] erase-sms: func [ {Erase sms from modem storage Note: Modem should be set to text mode (AT+CMGF=1)} mp [ object! ] "Phone/modem object (see code)" sms-id [ integer! string! ] "SMS index number" /local rez ][ rez: copy [] insert mp/serial-port rejoin [ "AT+CMGD=" sms-id crlf ] repend rez parse copy wait mp/serial-port crlf return last rez ] cell-strength: func [ sp [ port! ] "Serial port of GSM modem" /local rez ][ insert sp rejoin [ "AT+CSQ" crlf ] rez: parse copy wait [ 1 sp ] crlf either find rez "ERROR" [ rez: "ERROR" ][ rez: divide to-integer first parse rez/2 "," 31 ] return rez ] sms-save2disk: func [ sms [ object! ] "SMS for storing to disk" dir [ file! ] "Directory to store" /local files file ][ files: sort/reverse load dir file: files/1 file: either file [1 + to-integer file] [1] file: file-num file save join dir file compose [ ID: (sms/ID) status: (sms/status) dest-phone: (sms/dest-phone) src-phone: (sms/src-phone) date-time: (sms/date-time) content: (sms/content) ] file ] downl-sms: func [ sp-name [ object! ] "Phone/modem object (see code)" /only "Filter only given types of SMSes" sms-type [ string! block! ] {SMS type: any of "STO SENT", "STO UNSENT", "REC READ", "REC UNREAD" } /local smses ][ either only [ smses: read-sms/only sp-name sms-type ][ smses: read-sms sp-name ] either all [ block? smses not empty? smses ] [ foreach [ id sms ] smses [ sms-save2disk sms sms-in-dir erase-sms sp-name id ] ][ smses: [] ] smses ] read-sms-from-disk: func [ dir /local rez sms-obj ][ rez: copy [] foreach file reverse read dir [ sms-obj: construct load rejoin [ dir file ] sms-obj/id: to-integer file repend rez [ sms-obj/id sms-obj ] ] return rez ] test-port: does [ for i 1 20 1 [ mp: open-sms-port "COM4" print [ mp/2 mp/3/1 mp/3/2 ] wait 1 close mp/1 wait 1 ] ] sms-file-server: func [ {Reads and sends simple text SMSes from and to files. Certain directories are required to run this funcion - see beginning of this script file! } ][ mp: open-sms-port "COM4" forever [ save stat-file compose [ cell-strength: (cell-strength mp/serial-port) ] smses-to-send: read-sms-from-disk sms-unsent-dir foreach [ sms-id sms ] smses-to-send [ either "ERROR" <> send-sms mp sms/dest-phone sms/content [ sms/status: "STO SENT" sms/date-time: now sms-save2disk sms sms-out-dir delete rejoin [ sms-unsent-dir file-num sms-id ] print rejoin [ "SMS to " sms/dest-phone " sent at " now ] ][ print rejoin [ "SMS to " sms/dest-phone " failed to send at " now ] print either port? wait [ 1 mp/serial-port ] [ rejoin [ "Port clearing o'k!" copy mp/serial-por ] ] [ "Port empty!" ] ] ] smses-received: downl-sms mp foreach [ sms-id sms ] smses-received [ print rejoin [ "SMS from " sms/src-phone " received at " sms/date-time ] ] isBr: false loop 10 [ wait 1 if input? [ print "SMS reading stopped!!!" isBr: true break ] ] if isbr [ break ] ] close mp/serial-port ]
halt ;; to terminate script if DO'ne from webpage