View in color | License | Download script | History | Other scripts by: janeks |
30-Apr 15:58 UTC
[0.056] 22.994k
[0.056] 22.994k
sms-funcs.rREBOL [
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
] |