Logic Machine Forum
problem with 4g modem - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Hardware (https://forum.logicmachine.net/forumdisplay.php?fid=12)
+--- Thread: problem with 4g modem (/showthread.php?tid=3839)

Pages: 1 2


problem with 4g modem - Frank68 - 31.01.2022

Hello

I asked for the 4g modem to be installed in the reactor, since a customer has only provided me with 4g sim, when the APN returns and the internet connects, I send the emails but I have an error in sending the SMS.
Does the SMS library also have to be modified in order to manage the new modem?

  below the error reported in the offending lines


Code:
function sendsms(number, message)
  require('socket')
  client = socket.udp()
  client:sendto(number .. ' ' .. message, '127.0.0.1', 12535)
end



RE: problem with 4g modem - admin - 31.01.2022

This script has nothing to do with the SMS sending via modem it simply sends message to the resident script. Post your full resident SMS script and a screenshot from System config > Status > System status > Serial ports.


RE: problem with 4g modem - Frank68 - 31.01.2022

(31.01.2022, 15:30)admin Wrote: This script has nothing to do with the SMS sending via modem it simply sends message to the resident script. Post your full resident SMS script and a screenshot from System config > Status > System status > Serial ports.

resident sms

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 = 'ttyACM3'
  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
  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)
  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

-- 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 = 'ttyACM3'
  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
  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)
  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
user library
Code:
AT = {
  -- 7-bit alphabet
  alphabet = {
    64, 163, 36, 165, 232, 233, 249, 236, 242, 199, 10, 216, 248,
    13, 197, 229, 10, 95, 10, 10, 10, 10, 10, 10, 10, 10, 10, 38,
    198, 230, 223, 201, 32, 33, 34, 35, 164, 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, 161, 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, 196, 214, 209, 220, 167, 191, 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, 228, 246,
    241, 252, 224
  },
  parsepdu = function(pdu)
    local data, len, msg, data, sender, offset, ntype, timestamp

    msg = {}

    -- offset from service center number
    offset = tonumber(pdu:sub(1, 2), 16) * 2

    -- sender number length
    len = tonumber(pdu:sub(offset + 5, offset + 6), 16)
    len = math.ceil(len / 2) * 2

    -- sender number type
    ntype = tonumber(pdu:sub(offset + 7, offset + 8), 16)
    ntype = bit.band(bit.rshift(ntype, 4), 0x07)

    -- raw sender number
    sender = pdu:sub(offset + 9, offset + len + 8)

    -- decode sender number
    msg.sender = AT.decodesender(sender, ntype)
    -----------------------------------------------
    -- timestamp --
    offset = offset + len + 13
    timestamp = pdu:sub(offset, offset + 13)
    timestamp = AT.decodeswapped(timestamp)

    msg.timestamp = AT.decodetime(timestamp)
    -----------------------------------------------
    -- message
    len = tonumber(pdu:sub(offset + 14, offset + 15), 16)
    data = pdu:sub(offset + 16)
    msg.data = AT.decode7bit(data, len)

    return msg
  end,
  -- decode sender address depending on source type
  decodesender = function(sender, ntype)
    if ntype == 5 then
      return AT.decode7bit(sender)
    else
      return AT.decodeswapped(sender)
    end
  end,
  -- decode time in sms pdu
  decodetime = function(timestamp)
    local offset, year, time

    offset = tonumber(timestamp:sub(13, 14)) or 0
    offset = offset * 15 * 60

    year = tonumber(timestamp:sub(1, 2))

    time = os.time({
      year = year < 70 and (2000 + year) or (1900 + year),
      month = tonumber(timestamp:sub(3, 4)),
      day = tonumber(timestamp:sub(5, 6)),
      hour = tonumber(timestamp:sub(7, 8)),
      min = tonumber(timestamp:sub(9, 10)),
      sec = tonumber(timestamp:sub(11, 12))
    }) or os.time()

    return time
  end,
  -- convert swapped number to normal
  decodeswapped = function(data)
    local i, nr, len, buf
    buf = {}

    -- real byte length
    len = math.floor(data:len() / 2)
    -- read 2 bytes at once
    for i = 1, len do
      -- convert low byte to number
      nr = tonumber(data:sub(i * 2, i * 2))
      if nr then
        table.insert(buf, tostring(nr))
      end

      -- convert high byte to number
      nr = tonumber(data:sub(i * 2 - 1, i * 2 - 1))
      if nr then
        table.insert(buf, tostring(nr))
      end
    end

    return table.concat(buf)
  end,
  -- convert from 7 bit char to 8 bit
  from7bit = function(c)
    if c < 128 then
      return string.char(AT.alphabet[ c + 1 ])
    else
      return ' '
    end
  end,
  -- converts from 7 bit to 8 bit
  decode7bit = function(data, len)
    local i, o, byte, prev, curr, mask, buf, res

    -- convert to binary string
    data = lmcore.hextostr(data, true)

    -- init vars
    o = 0
    prev = 0
    buf = {}

    for i = 1, data:len() do
      byte = data:byte(i, i)

      -- get 7 bit data
      mask = bit.lshift(1, 7 - o) - 1

      -- get current chunk
      curr = bit.band(byte, mask)
      curr = bit.lshift(curr, o)
      curr = bit.bor(curr, prev)

      -- save bit chunk
      prev = bit.rshift(byte, 7 - o)

      -- add to buffer
      table.insert(buf, AT.from7bit(curr))

      -- every 7th step prev will have a full char
      if o == 6 then
        table.insert(buf, AT.from7bit(prev))
        prev = 0
      end

      o = (o + 1) % 7
    end

    -- catch last char in buffer
    if prev > 0 then
      table.insert(buf, AT.from7bit(prev))
    end

    -- flatten buffer
    res = table.concat(buf)
    if len then
      res = res:sub(1, len)
    end

    return res
  end
}

function AT:init(dev, reset)
  require('serial')

  local t = setmetatable({}, { __index = AT })

  t.dev = dev

  while true do
    if t:reinit(30, reset) then
      break
    else
      if reset then
        t:reset()
      else
        return nil
      end
    end
  end

  return t
end

function AT:open(timeout)
  local port

  while true do
    if io.exists(self.dev) then
      port = serial.open(self.dev)

      if port then
        break
      end
    end

    if timeout then
      timeout = timeout - 1

      if timeout <= 0 then
        return false
      end
    end

    os.sleep(1)
  end

  self.port = port
  self.buffer = {}

  return true
end

function AT:reset()
  --alert('modem reset')
  os.execute('usbreset /dev/bus/usb/001/001')
end

function AT:reinit(timeout, reset)
  local res

  if reset then
    self:reset()
  end

  res = self:open(timeout)
  self.buffer = {}

  return res
end

function AT:close()
  if self.port then
    self.port:close()
    self.port = nil
  end
end

-- read single line from port
function AT:read(timeout)
  local char, err, timeout, deftimeout, line

  -- default timeout is 1 second, converted to 0.1 sec ticks
  timeout = tonumber(timeout) or 1
  timeout = timeout * 10

  deftimeout = timeout

  -- read until got one line or timeout occured
  while timeout > 0 do
    -- read 1 char
    char, err = self.port:read(1, 0.1)

    -- got data
    if char then
      -- got LF, end of line
      if char == '\n' then
        -- convert to string and empty buffer
        line = table.concat(self.buffer)
        self.buffer = {}
        line = line:trim()

        -- return only lines with data
        if #line > 0 then
          return line
        -- reset timeout
        else
          timeout = deftimeout
        end
      -- ignore CR
      elseif char ~= '\r' then
        table.insert(self.buffer, char)
      end
    -- read timeout
    elseif err == 'timeout' then
      timeout = timeout - 1
    -- other error
    else
      break
    end
  end

  print('error', err)
  return nil, err
end

-- blocking read until cmd is received
function AT:readuntil(cmd, timeout)
  local line, err
  timeout = timeout or 5

  while timeout > 0 do
    line, err = self:read()

    -- read line ok
    if line then
      if line == cmd or line == 'COMMAND NOT SUPPORT' or line:match('ERROR') then
        return line
      else
        timeout = timeout - 1
        err = 'invalid line'
      end
    -- timeout
    elseif err == 'timeout' then
      timeout = timeout - 1
    -- other error
    else
      break
    end
  end

  return nil, err
end

-- send command to terminal
function AT:send(cmd)
  local res, err = self.port:write(cmd .. '\r\n')

  -- write ok, get local echo
  if res then
    res, err = self:readuntil(cmd)
    self:read()
  end

  return res, err
end

-- main handler
function AT:run()
  local res, err, cmd, pos, sms

  res, err = self:read()
  if err then
    return err == 'timeout'
  end

  -- check for incoming command
  if res:sub(1, 1) ~= '+' then
    return true
  end

  pos = res:find(':', 1, true)

  if not pos then
    return true
  end

  -- get command type
  cmd = res:sub(2, pos - 1)

  -- check only for incoming sms
  if cmd ~= 'CMTI' then
    return
  end

  -- read from sim
  sms = self:incsms(res)

  -- sms seems to be valid, pass to handler if specified
  if sms and self.smshandler then
    self.smshandler(sms)
  end

  return true
end

-- incoming sms handler
function AT:incsms(res)
  local chunks, index, sms

  -- get message index from result
  chunks = res:split(',')
  if #chunks == 2 then
    -- get index and read from it
    index = tonumber(chunks[ 2 ])
    sms = self:readsms(index)
    -- delete sms from store
    self:deletesms(index)
  end

  return sms
end

-- delete sms at index
function AT:deletesms(index)
  local cmd, res

  -- send delete request
  cmd = 'AT+CMGD=' .. index
  res = self:send(cmd)

  return res
end

-- read sms at index
function AT:readsms(index)
  local cmd, res, sms

  -- send read request
  cmd = 'AT+CMGR=' .. index
  res = self:send(cmd)

  -- no message at then index
  if res == 'OK' then
    return nil, 'not found'
  end

  -- read sms pdu and try decoding
  sms = self:read()
  res, sms = pcall(AT.parsepdu, sms)

  -- decode failed
  if not res then
    return nil, sms
  end

  -- wait for ok from modem
  self:readuntil('OK')

  return sms
end

function AT:sendsms(number, message)
  local cmd, res

  -- switch to text mode
  self:send('AT+CMGF=1')

  -- set number
  cmd = string.format('AT+CMGS="%s"', number)
  res = self:send(cmd)

  -- number seems to be valid
  if res ~= 'ERROR' then
    -- message and CTRL+Z
    self.port:write(message .. string.char(0x1A))
    res = self:readuntil('OK')
  end

  -- switch back to pdu mode
  self:send('AT+CMGF=0')

  return res
end

-- set sms handler
function AT:setsmshandler(fn)
  if type(fn) == 'function' then
    self.smshandler = fn
  end
end

table.contains = function(t, v)
  for _, i in pairs(t) do
    if i == v then
      return true
    end
  end
end

function sendsms(number, message)
  require('socket')
  client = socket.udp()
  client:sendto(number .. ' ' .. message, '127.0.0.1', 12535)
end



RE: problem with 4g modem - admin - 01.02.2022

Replace ttyACM3 with ttyUSB2


RE: problem with 4g modem - Frank68 - 01.02.2022

(01.02.2022, 08:20)admin Wrote: Replace ttyACM3 with ttyUSB2

Nothing

I have this error when i try send sms


User library sms:465: attempt to index global 'client' (a nil value)
stack traceback:
User library sms:465: in function 'sendsms'

but in other reactor works

thanks


RE: problem with 4g modem - admin - 01.02.2022

Replace the whole sendsms function with this and check if it works. Also check if you have any messages in Logs.
Code:
function sendsms(number, message)
  local client, err = require('socket').udp()
  if client then
    client:sendto(number .. ' ' .. message, '127.0.0.1', 12535)
    client:close()
  else
    log('failed to created socket: ' .. tostring(err))
  end
end



RE: problem with 4g modem - Frank68 - 01.02.2022

(01.02.2022, 12:18)admin Wrote: Replace the whole sendsms function with this and check if it works. Also check if you have any messages in Logs.
Code:
function sendsms(number, message)
  local client, err = require('socket').udp()
  if client then
    client:sendto(number .. ' ' .. message, '127.0.0.1', 12535)
    client:close()
  else
    log('failed to created socket: ' .. tostring(err))
  end
end

nothinig in log but nothing sms send


RE: problem with 4g modem - admin - 01.02.2022

You have the same code in the resident script twice, this can lead to errors. You've also commented out all alerts so there's no way of knowing if the script is working or not.

Replace your resident script with this and post what you get in alerts:
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 = 'ttyACM3'
  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
  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)
  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



RE: problem with 4g modem - Frank68 - 01.02.2022

(01.02.2022, 13:35)admin Wrote: You have the same code in the resident script twice, this can lead to errors. You've also commented out all alerts so there's no way of knowing if the script is working or not.

Replace your resident script with this and post what you get in alerts:
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 = 'ttyACM3'
  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
  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)
  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

problem to init


RE: problem with 4g modem - admin - 01.02.2022

Sorry, that was an old script. Replace ttyACM3 with ttyUSB2 and restart the script via disable/enable.


RE: problem with 4g modem - Frank68 - 01.02.2022

(01.02.2022, 14:56)admin Wrote: Sorry, that was an old script. Replace ttyACM3 with ttyUSB2 and restart the script via disable/enable.

Same error , need som in init script ?


RE: problem with 4g modem - admin - 02.02.2022

Can you provide remote access to your LM?


RE: problem with 4g modem - Frank68 - 02.02.2022

(02.02.2022, 09:13)admin Wrote: Can you provide remote access to your LM?

via zerotier is ok ?


RE: problem with 4g modem - admin - 02.02.2022

Yes, send your network ID, LM ZeroTier IP and admin password via PM.


RE: problem with 4g modem - admin - 02.02.2022

Check if it's working now. You had a space after the serial port name so it did not work:
Code:
comport = 'ttyUSB2 '



RE: problem with 4g modem - Frank68 - 02.02.2022

(02.02.2022, 09:53)admin Wrote: Check if it's working now. You had a space after the serial port name so it did not work:
Code:
comport = 'ttyUSB2 '
tanks a lot


RE: problem with 4g modem - Frank68 - 02.02.2022

Hello

For the problem of sending sms I solved with your help in 2 reactor out of 3, in the third with the same scripts, if I text the sms calling send it works, while if it is called from the script the alalrme event does not work, while the mails from the same script do
The alalrme event scripts I checked it are like in the reactor it works in, I'm getting lost and I don't know where.

I accept advice

Thank you


RE: problem with 4g modem - admin - 03.02.2022

Have you replaced the sendsms function as specified? https://forum.logicmachine.net/showthread.php?tid=3839&pid=24831#pid24831
Do you have anything in alerts and logs?


RE: problem with 4g modem - Frank68 - 03.02.2022

(03.02.2022, 07:27)admin Wrote: Have you replaced the sendsms function as specified? https://forum.logicmachine.net/showthread.php?tid=3839&pid=24831#pid24831
Do you have anything in alerts and logs?
Hello

I found the problem, the phone number had a space at the end for which it was not valid, now I try how to remove the spaces before and after, both for the phone number and if I can also for the email address so as to no longer have the problem.

Thank you


RE: problem with 4g modem - andrepneves@gmail.com - 01.07.2024

Hi,

We are having the same problem that Frank68 sending SMS. 

The LM was working fine but from one day to the other it stop working. We tried changing the comport, factory reset the LM and even tried it on other LM with no result.

On Alert tab we keep getting SMS USB init failed.

Another thing I find strange is that the serial ports don't show on system status (view image).

Our firmware is Version: 20230612.

Thanks for your hel p,

BR,
Neves