1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | rem Email380.bas
rem
rem last revision 2005 May 13
rem
rem send an Email from a Tiger 380 with Ethernet module
rem when capture pin is connected to common;
rem LED6 indicates that a message is being sent
rem the macro makes use of the XPorts modem mode to
rem establish a connection - once established it is plain SMTP
rem
rem see RFC 821 for more details on SMTP
rem
rem XPort modem mode set to 'Without Echo' so we get only SMTP replies
rem
rem the IP and Gateway address of the Tiger have
rem to be setup correctly in the Ethernet module
REG &ERR_MSG = &TEXT_VARIABLE8
REG &SPACES = &TEXT_VARIABLE7
REG &ERR_REJECTED = &USER_TEXT1
REG &ERR_DISABLED = &USER_TEXT2
REG &ERR_TIMEOUT = &USER_TEXT3
REG &MSG_DONE = &USER_TEXT4
REG &SERVER = &USER_TEXT5
REG &FROM = &USER_TEXT6
REG &TO = &USER_TEXT7
REG &DOMAIN = &USER_TEXT8
REG &SUBJECT = &USER_TEXT9
// #msg values
CONST mNONE = 0
CONST mRESTART = 7
CONST mRESET_MODEM = 8
CONST mDISCONNECT = 9
CONST mCONNECT = 10
CONST mHELO = 11
CONST mFROM = 12
CONST mTO = 13
CONST mDATA = 14
CONST mdFROM = 15 // not mandatory
CONST mdTO = 16 // not mandatory
CONST mdSUBJECT = 17 // not mandatory
CONST mdPRIORITY = 18 // not mandatory
CONST mdLINE1 = 19 // the actual mail body
CONST mEND_MESSAGE = 20
// initialize text registers
MEM &ERR_REJECTED = "Email rejected"
MEM &ERR_DISABLED = "Email permanently disabled !!!"
MEM &ERR_TIMEOUT = "Communication timed out"
MEM &MSG_DONE = "Done"
MEM &SERVER = "192.168.10.1/0025"
MEM &FROM = "tiger380"
MEM &TO = "technician"
MEM &DOMAIN = "mycompany.com"
MEM &SUBJECT = "Alarm"
// #state values
CONST sIDLE = 0
CONST sSEND = 1
CONST sWAIT_FOR_REPLY = 2 // wait for SMTP replies
CONST sWAIT = 3 // pauses for modem commands
CONST sERROR = 4
CONST sRESET = 5
// serial setup
CONST SLAVE_MODE = 0000
CONST MASTER_MODE = 0002
MEM &SERIAL_MODE1 = SLAVE_MODE
MEM &STRING_LENGTH = 0 // replies have variable length
MEM &STRING_CHARACTER = CR // all SMTP replies should end with CR/LF
// don't wait forever for replies
CONST TIMEOUT = 300 // 30.0 secs (only the CONNECT should take that long)
// there has to be a pause >1sec before and after the '+++' for disconnect
CONST MODEM_TIMEOUT = 12
// don't send messages when a permanent messaging failure has occured
BITREG &USER_MEMORY_1 = [ |SEND_MESSAGE ]
MEM &USER_MEMORY_1 = 0x0001 // send messages
// mail priority
CONST PRIORITY_HIGHEST = 1
CONST PRIORITY_HIGH = 2
CONST PRIORITY_NORMAL = 3
////////////////////////////////////////////////////////////////////////////////
CUSTOMER_ID_MACRO:
////////////////////////////////////////////////////////////////////////////////
write &SPACES
append "Email 380"
append &SPACES
END
////////////////////////////////////////////////////////////////////////////////
RESET_MACRO:
////////////////////////////////////////////////////////////////////////////////
#state = sIDLE
#msg = mNONE
|message_sent = false
&TIMER1 = 0
&SERIAL_MODE1 = SLAVE_MODE // so we can talk to the meter in ASCII mode
&SPACES = " " // spaces for scrolling text messages
END
////////////////////////////////////////////////////////////////////////////////
MAIN_MACRO:
////////////////////////////////////////////////////////////////////////////////
select #state
case sIDLE:
|LED6 = off
// send email when capture pin is connected to common
if |CAPTURE_PIN = on and |SEND_MESSAGE = true then
&SERIAL_MODE1 = MASTER_MODE
// terminate any connections before we start with a new one
#msg = mRESTART
#state = sSEND
|message_sent = false
&TIMER1 = 0
endif
case sSEND:
if &CODE2 >= 0200 then
// in fast mode we have to wait a little for the print command to finish
#state = sWAIT
endif
|LED6 = on
&TIMER1 = 0
print "" // reset serial buffer
select #msg
// modem commands
case mRESTART:
// timer is already reset so we just wait before we send '+++'
#state = sWAIT
case mRESET_MODEM:
// wait agagin after the '+++'
#state = sWAIT
print "+++"
case mDISCONNECT:
// wait again before we start a new connection
#state = sWAIT
print "ATH" + CHR(CR) // hang up connection
case mCONNECT:
#state = sWAIT_FOR_REPLY
// dial to IP address and SMTP port
print "ATDT" + &SERVER + CHR(CR)
// SMTP commands
case mHELO:
#state = sWAIT_FOR_REPLY
print "HELO " + &DOMAIN // "Hello, I am from <domain>"
case mFROM:
#state = sWAIT_FOR_REPLY
print "MAIL FROM: <" + &FROM + "@" + &DOMAIN + ">"
case mTO:
#state = sWAIT_FOR_REPLY
print "RCPT TO: <" + &TO + "@" + &DOMAIN + ">"
// actual email text
case mDATA:
print "DATA"
case mdFROM:
print "From: " + &FROM + "@" + &DOMAIN
case mdTO:
print "To: " + &TO + "@" + &DOMAIN
case mdSUBJECT:
print "Subject: " + &SUBJECT
case mdPRIORITY:
print "X-Priority: " + PRIORITY_HIGHEST
case mdLINE1:
// add an empty line to separate the mail body from the mail header
print CHR(CR) + CHR(LF)
// current data cannot be stored in a fixed string (e.g. "CH1: ~9" would be
// replaced with the actual value at download time) but has to be
// assembled to print at runtime
print &HOURS_MINUTES + CHR(TAB) + "CH1: " + &CH1 + CHR(TAB) + "CH2: " + &CH2
case mEND_MESSAGE:
#state = sWAIT_FOR_REPLY
|message_sent = true
print "."
endsel
// only SMTP commands send CR/LF
if #msg > mCONNECT then
print CHR(CR)+CHR(LF)
if #msg > mTO then
// keep on sending the email text line by line without WAIT_FOR_REPLY
#msg = #msg + 1
endif
endif
case sWAIT_FOR_REPLY:
if |RECEIVE_READY = true then
// let's first assume that the reply is OK and we can continue...
#state = sSEND
// ...then check for errors
if #msg = mCONNECT then
// got service ready reply on connect
if SERIAL_INPUT = "220" then
#msg = mHELO
else // wrong answer
#state = sERROR
&ERR_MSG = &ERR_REJECTED
endif
else
if &RECEIVE_BUFFER[0] = ASC("4") or SERIAL_INPUT = "552" then
// couldn't get through or mailbox is full
#state = sERROR
&ERR_MSG = &ERR_REJECTED
elsif &RECEIVE_BUFFER[0] = ASC("5") then
// permanent failure, see RFC 821 for more details on error codes
|SEND_MESSAGE = false
#state = sERROR
&ERR_MSG = &ERR_DISABLED
elsif #msg >= mEND_MESSAGE then
// terminate current connection
#msg = mRESTART
else
#msg = #msg + 1
endif
endif
elsif &TIMER1 > TIMEOUT then
// don't wait forever
#state = sERROR
&ERR_MSG = &ERR_TIMEOUT
endif
case sWAIT:
if #msg >= mDATA and &TIMER1 > 0 then
// delay new output to avoid aborting old message (only in fast mode)
#state = sSEND
elsif &TIMER1 > MODEM_TIMEOUT then
// wait before and after the '+++' to terminate the connection
if #msg = mDISCONNECT and |message_sent = true then
#state = sRESET
else
#msg = #msg + 1
#state = sSEND
endif
endif
case sERROR:
// terminate current connection
#msg = mRESTART
#state = sSEND
|message_sent = true
write &SPACES
append &ERR_MSG
append &SPACES
case sRESET:
print "" // reset serial buffer
&SERIAL_MODE1 = SLAVE_MODE
#msg = mNONE
#state = sIDLE
write &SPACES
append &MSG_DONE
append &SPACES
endsel
END
|
Download Email380.bas
(7.3 KB , Aug. 26, 2008)