18.04.2024, 10:04
Try this:
Code:
-- init
if not numbers then
require('user.sms')
require('json')
require('socket')
-- allowed numbers, SMS from other numbers will be ignored
numbers = { '3332958126' }
-- port number depends on modem model
comport = 'ttyUSB2'
doreset = false -- set to true if USB reset is required before starting any communication
-- if SIM PIN is enabled, uncomment the line below and replace 0000 with SIM PIN
-- pincode = '0000'
-- command parser
parser = function(cmd, sender)
local find, pos, name, mode, offset, value, dvalue, obj, message
cmd = cmd:trim()
mode = cmd:sub(1, 1):upper()
-- invalid request
if mode ~= 'W' and mode ~= 'R' then
return
end
cmd = cmd:sub(3):trim()
-- parse object name/address
find = cmd:sub(1, 1) == '"' and '"' or ' '
offset = find == '"' and 1 or 0
-- pad with space when in read mode
if mode == 'R' and find == ' ' then
cmd = cmd .. ' '
end
-- find object name
pos = cmd:find(find, 1 + offset, true)
-- name end not found, stop
if not pos then
return
end
-- get name part
name = cmd:sub(1 + offset, pos - offset):trim()
if mode == 'W' then
value = cmd:sub(pos + offset):trim()
if #value > 0 then
-- try decoding value
dvalue = json.pdecode(value)
if dvalue ~= nil then
value = dvalue
end
-- send to bus
grp.write(name, value)
end
-- read request
else
obj = grp.find(name)
-- object not known
if not obj then
return
end
-- send read request and wait for an update
obj:read()
os.sleep(1)
-- read new value
value = grp.getvalue(name)
-- got no value
if value == nil then
return
end
-- add object name if specified
if obj.name then
name = string.format('%s (%s)', obj.name, obj.address)
end
message = string.format('Value of %s is %s', name, json.encode(value))
modem:sendsms('+' .. sender, message)
end
end
-- incoming sms handler
readcsq = function()
local res, err, reply = modem:send('AT+CSQ')
local rssi
if reply then
rssi = reply:match('%+CSQ:%s+(%d+),(%d+)')
end
rssi = tonumber(rssi) or 0
if 2 <= rssi and rssi <= 9 then
quality = 'marginal'
elseif 10 <= rssi and rssi <= 14 then
quality = 'ok'
elseif 15 <= rssi and rssi <= 19 then
quality = 'good'
elseif 20 <= rssi and rssi <= 30 then
quality = 'excellent'
else
quality = 'unknown'
end
grp.write('32/0/0', quality) -- Modem signal level write to group
end
csqtime = os.time()
handler = function(sms)
--alert('incoming sms: [%s] %s', tostring(sms.sender), tostring(sms.data))
-- sms from known number, call parser
if table.contains(numbers, sms.sender) then
--parser(sms.data, sms.sender)
end
end
-- check local udp server for messages to send
udphandler = function(server)
-- check for local sms to send
local msg = server:receive()
-- got no message
if not msg then
return
end
-- split into number and message
local sep = msg:find(' ')
if not sep then
return
end
--alert('sending sms: ' .. msg)
modem:sendsms(msg:sub(1, sep - 1), msg:sub(sep + 1))
end
end
-- handle data from modem
if modem then
if modem:run() then
udphandler(server)
now = os.time()
delta = math.abs(now - csqtime)
if delta >= 15 then
csqtime = now
readcsq()
end
else
--alert('SMS handler lost connection')
modem:reinit()
end
-- modem init
else
--alert('SMS handler init')
-- open serial port
modem = AT:init('/dev/' .. comport, doreset)
-- init ok
if modem then
-- set sms handler
modem:setsmshandler(handler)
-- send pin if set
if pincode then
modem:send('AT+CPIN=' .. pincode)
modem:read()
end
-- set to pdu mode
modem:send('AT+CMGF=0')
-- enable sms notifications
modem:send('AT+CNMI=1,1,0,0,0')
-- fixup encoding
modem:send('AT+CSCS="GSM"')
-- delete all saved messages
modem:send('AT+CMGD=1,4')
-- local udp server for sending sms
server = socket.udp()
server:setsockname('127.0.0.1', 12535)
server:settimeout(0.1)
--alert('SMS handler started')
-- init failed
else
--alert('SMS USB init failed')
end
end