I’m looking for a small wip library (.dwl) to create a TCP client using AT commands for the GPRS connection, and then the DATA-MODE to transfer the data.
I have already tried the WIPSoft library, but I’m experiencing a lot of trouble using it. It seems I have encountered the most part of the problems described in this forum without any working result.
Does anyone can send me a piece of working code to build a TCP client connection ?
By using Open AT Lua to write additional AT commands, you can run something like that:
-------------------------------------------------------------------------
-- AT+TCPCONNECT=<address>,<port>,<nbytes> will:
-- * read <nbytes> bytes of data from the UART port where the AT command is typed
-- * connect a TCP socket to address:port
-- * send the data read from UART to the TCP socket
-- * shutdown the TCP connection.
-------------------------------------------------------------------------
at.commands['AT+TCPCONNECT='] = function (cmd, address, port, nbytes)
local data = read_n_bytes_from_uart (nbytes, cmd.port)
local socket = wip.tcp_client (address, port)
socket:write(data)
socket:close()
return "\r\nOK"
end
function read_n_bytes_from_uart(bytes_to_read, uart)
local ch = wip.fcm (uart)
local buffer = { }
while true do
local segment = internal.wip_read(ch, bytes_to_read)
if segment then
table.insert(buffer, segment)
bytes_to_read = bytes_to_read - #segment
end
if bytes_to_read == 0 then break end
ch:_wait_read()
end
ch:close()
return table.concat (buffer)
end
Notice that the the big ugly function read_n_bytes_from_uart() is a work around a known bug in the current release (blocking to read a specified number of bytes from a channel sometimes incorrectly waits for an extra byte). In the upcoming version of Open AT Lua, the program will simply be:
at.commands['AT+TCPCONNECT='] = function (cmd, address, port, nbytes)
local uart = wip.fcm(cmd.port) -- reserve the UART port and switch it to DATA mode
local data = uart:read(nbytes..'*') -- block to read `nbytes' bytes of data from uart in DATA mode
uart:close() -- switch UART back to AT mode and release it
local socket = wip.tcp_client (address, port) -- create & connect the socket
socket:write(data) -- send data
socket:close() -- close and release socket
return "\r\nOK"
end
Oops, I forgot the grps config part. Here’s to start GPRS:
----------------------------------------------------
-- AT+TCPSTARTGPRS=<login>,<password>,<apn>
-- starts the GPRS connection with the specified config
----------------------------------------------------
at.commands['AT+TCPSTARTGPRS='] = function (cmd, login, password, apn)
if proc.bearers.GPRS then return { "GPRS already up\r\n", "OK\r\n" } end
local b = wip.bearer_client( 'GPRS', { login=login; password=password; apn=apn })
if not b then error() end
return "OK\r\n"
end
and here’s to shut it down:
----------------------------------------------------
-- AT+TCPSTOPGPRS stops the GPRS bearer
----------------------------------------------------
at.commands['AT+TCPSTOPGPRS'] = function (cmd)
local b = proc.bearers.GPRS
if b then b:close(); return "OK\r\n"
else return { "GPRS already down\r\n", "OK\r\n" } end
end
In fact, I have already tryed to manage a Open AT C code having the same behaviour you have described above.
My problem is that I am transmitting data via AT command, not in DATA_MODE.
That results in a datasize problem (multi AT commands are possible, but modem’s storage is limited).
if you want to do it in C, you’ll need to figure out and use the adl_fcmSubscribe() API. Be warned that it’s not very intuitive, and it’s cumbersome to bufferize data with it. I heard that Wavecom wants to provide a better, direct interface to UART-like ports, but don’t hold your breadth.
However, for your problem, I can’t think of any added value provided by C, that would match the additional development and maintenance costs it induces (you’re not realtime-bound, you don’t have resource issues, you don’t need to do anything close to the metal).
I have never tried OpenAT Lua before but I will try it. It looks easyier than “c” OpenAT. I hope so!
Question:
local data = uart:read(nbytes..'*') -- block to read `nbytes' bytes of data from uart in DATA mode
uart:close() -- switch UART back to AT mode and release it
-> I guess there is no DATA_Mode like the one escaped by “+++”?
(That does not really matter.)
local data = uart:read(nbytes..'*') -- block to read `nbytes' bytes of data from uart in DATA mode
uart:close() -- switch UART back to AT mode and release it
-> Is ‘nbytes’ limited ? (I mean: is the data stored in the modem’s memory or is it directly dispatched to the V24?)
The command “uart=wip.fcm(port)” switches the port to DATA mode, and it stays that way until “uart:close()” is called or “+++” is entered. If you want to read everything until the user types “+++”, replace the call to read_n_bytes_from_uart() by uart:read(“a"). (“a” is for “all”, and "” is for “block until reading is finished”).
Unfortunately there’s an other a pending bug (in the WIP/FCM library this time, not in Lua) that forbids a second wip.fcm() after the uart has been closed. It can be fixed either by waiting for next delivery of WIP, or with a C-based workaround (PM me for details if you need it and you’re in a hurry).
‘data’ is stored as a string in RAM, so that’s your limitation. You can also use A&D or flash objects API to store your data but the program will be slightly more complex. You can also flush data more regularly if you prefer:
at.commands['AT+TCPCONNECT='] = function (cmd, address, port)
local uart = wip.fcm(cmd.port)
local tcp = wip.tcp_client(address, port)
while(true) do
repeat
local buf = uart:read() -- read whatever's available on uart
tcp:write(buf) -- flush it on tcp
until buf=="" -- do it again until there's nothing left to read
uart:wait("read") -- wait for a "more data to read" signal on uart
end
end
Yet another solution would be to separate TCP connection establishment and data emission: AT+TCPCONNECT=, opens connection, AT+TCPSEND= reads ans sends bytes of data then returns to AT mode without shutting donw the TCP connection; that way, AT+TCPSEND can be called several times. Finally, AT+TCPCLOSE shuts it down:
-- Warning: untested, no error handling.
TCP_SOCKET = nil
at.commands['AT+TCPCONNECT='] = function (cmd, address, port)
TCP_SOCKET = wip.tcp_client (address, port)
return "OK\r\n"
end
at.commands['AT+TCPSEND='] = function (cmd, nbytes)
local data = read_n_bytes_from_uart (nbytes, cmd.port)
TCP_SOCKET:write (data)
return "OK\r\n"
end
at.commands['AT+TCPCLOSE'] = function(cmd)
TCP_SOCKET:close()
TCP_SOCKET = nil
return "OK\r\n"
end