User Tools

Site Tools


Send SMS via USB Modem

If you need send SMS using own GSM modem you can use Custom Protocols to instruct modem send messages.

To send SMS you need send a few AT-commands to modem. Unfortunately, sometimes they are vendor-specific and we can't built in support all modems into WebHMI. So we publish custom protocol that will help you understand the idea and adopt it for your modem.

Here is the sample protocol that will send message:

function createDevices ()
    addDevice({name = "SMS",  shift = 0, base = 10, xtraFields = {1, 5}});
end
 
function readRegister (reg, device, unitId)
    return "SMS";
end
 
function writeRegister (reg, device, unitId, newValue)
    sendString("AT+CPIN=\"0000\"\r");
    sendString("AT+CMGF=1\r");
    sendString("AT+CSMP=17,167,0,0\r");
    sendString("AT+CMGS=\"+" .. string.sub(reg.addr, 4) .. "\"\r");
    sendString(newValue);
    sendString(string.char(26));
    return true; 
end

Protocol parameters:

  • Type: Serial Port
  • Address validation: ^(SMS[0-9]+)$
  • Validation error message: Invalid phone number. Valid SMS addresses are SMSxxxxxxxxxx where xxxx is a phone number.

Go to Setup → Registers → Tools → Custom Protocols and add this protocol. After that you can create connection using this protocol. Some modems could answer on AT commands with huge delays. You might need specify extremely long timeouts for them in connection settings (3-6 seconds!) in you will see such behavior.

Please note that modern modems usually have multiple UARTs (/dev/ttyUSB0, /dev/ttyUSB1, /dev/ttyUSB2, etc). Some of these UARTs can be used for data exchange only, another - for control modem during the established call. You have to find such control port manually (basically, try one by one) to find port that will react on AT-commands and use this post in this custom protocol.

To send SMS to phone number 1234567890 you need to create a register with address SMS1234567890 with data type String. Once register was created you can send SMS to this phone it by writing text to this register.

When WebHMI will get command to write new text to this register it will send needed AT command to modem and modem will send SMS to phone number specified in register address.

If you will have troubles with sending SMS you can use this debug version of custom protocol. It will echo commands and modem replies into WebHMI communication log. This might help you debug the issue.

function createDevices ()
    addDevice({name = "SMS",  shift = 0, base = 10, xtraFields = {1, 5}});
end
 
function readRegister (reg, device, unitId)
    return "Ok"; -- Just a placeholder to allow type new values on Register's page,
end
 
function writeRegister (reg, device, unitId, newValue)
    local replyTmp = "" 
 
    DEBUG("entered sms protocol for value "..newValue)
    --sendString("AT+CPIN=\"0000\"\r"); -- Some modems will require enter PIN code
 
    sendString("AT+CMGF=1\r");   -- Switch modem into text mode
 
    -- Get modem's reply
    replyTmp  = ReadModemReply()
    if (replyTmp ~= "") then
        DEBUG("modem replied with "..replyTmp)
    end 
 
    -- Get text mode parameters
    sendString("AT+CSMP=17,167,0,0\r");
 
    -- Get modem's reply
    replyTmp  = ReadModemReply()
    if (replyTmp ~= "") then
        DEBUG("modem replied with "..replyTmp)
    end 
 
    -- Tell phone number to modem. We are using raw register address and cut phone number from it starting at char #4
    sendString("AT+CMGS=\"+" .. string.sub(reg.addr, 4) .. "\"\r") 
 
    -- Get modem's reply
    replyTmp  = ReadModemReply()
    if (replyTmp ~= "") then
       DEBUG("modem replied with "..replyTmp)
    end 
 
    -- Send message (newValue) and line end character (ASCII code #26)
    sendString(newValue..string.char(26))
 
    -- Get modem's reply
    replyTmp  = ReadModemReply()
    if (replyTmp ~= "") then
        DEBUG("modem replied with "..replyTmp)
    end 
 
    return true; 
end
 
function ReadModemReply()
local CR = "\r"    
local one_char_tmp = ""
local readStringTmp = ""
     repeat 
       one_char_tmp = readString(1) 
       if (one_char_tmp ~= false) then 
            readStringTmp = readStringTmp..one_char_tmp
        else
            DEBUG("can't readString")
            return ""
       end 
until (one_char_tmp == CR)
readString(1)  -- read rest symbol
 
return readStringTmp
 
end

Page Tools