Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXOS8700CQ MODSERIAL mbed
wnc_control.cpp
- Committer:
- fkellermavnet
- Date:
- 2016-07-22
- Revision:
- 30:33be8e2992f3
- Parent:
- 22:41e6c417ace1
- Child:
- 32:1e052a3e73fe
File content as of revision 30:33be8e2992f3:
#include "mbed.h"
#include <cctype>
#include <string>
#include "config_me.h"
#include "SerialBuffered.h"
#include "wnc_control.h"
extern Serial pc;
extern Serial mdm;
extern string MyServerIpAddress;
extern string MySocketData;
int reinitialize_mdm(void);
enum WNC_ERR_e {
WNC_OK =0,
WNC_CMD_ERR = -1,
WNC_NO_RESPONSE = -2
};
// Contains result of last call to send_wnc_cmd(..)
WNC_ERR_e WNC_MDM_ERR = WNC_OK;
// Contains the RAW WNC UART responses
static string wncStr;
static int socketOpen = 0;
void software_init_mdm(void)
{
do
{
WNC_MDM_ERR = WNC_OK;
at_init_wnc();
if (WNC_MDM_ERR == WNC_NO_RESPONSE)
reinitialize_mdm();
} while (WNC_MDM_ERR != WNC_OK);
}
void resolve_mdm(void)
{
do
{
WNC_MDM_ERR = WNC_OK;
at_dnsresolve_wnc(MY_SERVER_URL, &MyServerIpAddress);
if (WNC_MDM_ERR == WNC_NO_RESPONSE)
{
reinitialize_mdm();
software_init_mdm();
}
else if (WNC_MDM_ERR == WNC_CMD_ERR)
{
pc.puts("Bad URL!!!!!!\r\n");
MyServerIpAddress = "192.168.0.1";
WNC_MDM_ERR = WNC_OK;
}
} while (WNC_MDM_ERR != WNC_OK);
pc.printf("My Server IP: %s\r\n", MyServerIpAddress.c_str());
}
void sockopen_mdm(void)
{
do
{
at_at_wnc();
at_at_wnc();
WNC_MDM_ERR = WNC_OK;
at_sockopen_wnc(MyServerIpAddress, MY_PORT_STR);
if (WNC_MDM_ERR == WNC_NO_RESPONSE)
{
reinitialize_mdm();
software_init_mdm();
}
else if (WNC_MDM_ERR == WNC_CMD_ERR)
pc.puts("Socket open fail!!!!\r\n");
else
socketOpen = 1;
} while (WNC_MDM_ERR != WNC_OK);
}
void sockwrite_mdm(const char * s)
{
if (socketOpen == 1)
{
do
{
WNC_MDM_ERR = WNC_OK;
at_sockwrite_wnc(s);
if (WNC_MDM_ERR == WNC_NO_RESPONSE)
{
reinitialize_mdm();
software_init_mdm();
}
else if (WNC_MDM_ERR == WNC_CMD_ERR)
{
pc.puts("Socket Write fail!!!\r\n");
// Have seen when write fails modem gets stuck in bad state, try to recover
reinitialize_mdm();
software_init_mdm();
}
} while (WNC_MDM_ERR != WNC_OK);
}
else
puts("Socket is closed for write!\r\n");
}
unsigned sockread_mdm(string * sockData, int len, int retries)
{
unsigned n = 0;
// Clean slate:
sockData->erase();
if (socketOpen == 1)
{
do
{
WNC_MDM_ERR = WNC_OK;
n = at_sockread_wnc(sockData, len, retries);
if (WNC_MDM_ERR == WNC_NO_RESPONSE)
{
if (n == 0)
{
reinitialize_mdm();
software_init_mdm();
}
else
puts("Sock read partial data!!!\r\n");
}
else if (WNC_MDM_ERR == WNC_CMD_ERR)
puts("Sock read fail!!!!\r\n");
} while (WNC_MDM_ERR == WNC_NO_RESPONSE);
}
else
puts("Socket is closed for read\r\n");
return (n);
}
void sockclose_mdm(void)
{
do
{
WNC_MDM_ERR = WNC_OK;
at_sockclose_wnc();
// Assume close happened even if it went bad
// going bad will result in a re-init anyways and if close
// fails we're pretty much in bad state and not much can do
socketOpen = 0;
if (WNC_MDM_ERR == WNC_NO_RESPONSE)
{
reinitialize_mdm();
software_init_mdm();
}
else if (WNC_MDM_ERR == WNC_CMD_ERR)
puts("Sock close fail!!!\r\n");
} while (WNC_MDM_ERR != WNC_OK);
}
/**
* C++ version 0.4 char* style "itoa":
* Written by Lukás Chmela
* Released under GPLv3.
*/
char* itoa(int value, char* result, int base)
{
// check that the base if valid
if ( base < 2 || base > 36 ) {
*result = '\0';
return result;
}
char* ptr = result, *ptr1 = result, tmp_char;
int tmp_value;
do {
tmp_value = value;
value /= base;
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];
} while ( value );
// Apply negative sign
if ( tmp_value < 0 )
*ptr++ = '-';
*ptr-- = '\0';
while ( ptr1 < ptr ) {
tmp_char = *ptr;
*ptr-- = *ptr1;
*ptr1++ = tmp_char;
}
return result;
}
extern int mdm_sendAtCmdRsp(const char *cmd, const char **rsp_list, int timeout_ms, string * rsp, int * len);
// Sets a global with failure or success, assumes 1 thread all the time
int send_wnc_cmd(const char * s, string ** r, int ms_timeout)
{
static const char * rsp_lst[] = { "OK", "ERROR", NULL };
int len;
// Per WNC between every AT cmd:
wait_ms(20);
pc.printf("Send: %s\r\n",s);
int res = mdm_sendAtCmdRsp(s, rsp_lst, ms_timeout, &wncStr, &len);
*r = &wncStr; // Return a pointer to the static string
if (res >= 0)
{
pc.puts("[");
pc.puts(wncStr.c_str());
pc.puts("]\n\r");
if (res > 0)
{
if (WNC_MDM_ERR != WNC_NO_RESPONSE)
WNC_MDM_ERR = WNC_CMD_ERR;
return -1;
}
else
return 0;
}
else
{
WNC_MDM_ERR = WNC_NO_RESPONSE;
pc.puts("No response from WNC!\n\r");
return -2;
}
}
void at_at_wnc(void)
{
string * pRespStr;
send_wnc_cmd("AT", &pRespStr, WNC_TIMEOUT_MS); // Heartbeat?
}
void at_init_wnc(void)
{
string * pRespStr;
send_wnc_cmd("AT", &pRespStr, WNC_TIMEOUT_MS); // Heartbeat?
send_wnc_cmd("ATE1", &pRespStr, WNC_TIMEOUT_MS); // Echo ON
string cmd_str("AT%PDNSET=1,");
cmd_str += MY_APN_STR;
cmd_str += ",IP";
send_wnc_cmd(cmd_str.c_str(), &pRespStr, 2*WNC_TIMEOUT_MS); // Set APN, cmd seems to take a little longer sometimes
send_wnc_cmd("AT@INTERNET=1", &pRespStr, WNC_TIMEOUT_MS); // Internet services enabled
send_wnc_cmd("AT@SOCKDIAL=1", &pRespStr, WNC_TIMEOUT_MS);
}
void at_sockopen_wnc(const string & ipStr, const char * port )
{
string * pRespStr;
send_wnc_cmd("AT@SOCKCREAT=1", &pRespStr, WNC_TIMEOUT_MS);
string cmd_str("AT@SOCKCONN=1,\"");
cmd_str += ipStr;
cmd_str += "\",";
cmd_str += port;
send_wnc_cmd(cmd_str.c_str(), &pRespStr, WNC_TIMEOUT_MS);
}
void at_sockclose_wnc(void)
{
string * pRespStr;
send_wnc_cmd("AT@SOCKCLOSE=1", &pRespStr, WNC_TIMEOUT_MS);
}
int at_dnsresolve_wnc(const char * s, string * ipStr)
{
string * pRespStr;
string str(s);
str = "AT@DNSRESVDON=\"" + str;
str += "\"\r\n";
if (send_wnc_cmd(str.c_str(), &pRespStr, WNC_TIMEOUT_MS) == 0)
{
size_t pos_start = pRespStr->find(":\"") + 2;
if (pos_start != string::npos)
{
size_t pos_end = pRespStr->rfind("\"") - 1;
if (pos_end != string::npos)
{
if (pos_end > pos_start)
{
// Make a copy for use later (the source string is re-used)
*ipStr = pRespStr->substr(pos_start, pos_end - pos_start + 1);
return 1;
}
else
pc.puts("URL Resolve fail, substr Err\r\n");
}
else
pc.puts("URL Resolve fail, no 2nd quote\r\n");
}
else
pc.puts("URL Resolve fail, no quotes\r\n");
}
else
pc.puts("URL Resolve fail, WNC cmd fail\r\n");
return -1;
}
void at_sockwrite_wnc(const char * s)
{
string * pRespStr;
char num2str[6];
size_t sLen = strlen(s);
if (sLen <= 99999)
{
string cmd_str("AT@SOCKWRITE=1,");
itoa(sLen, num2str, 10);
cmd_str += num2str;
cmd_str += ",\"";
while(*s != '\0')
{
itoa((int)*s++, num2str, 16);
// Always 2-digit ascii hex:
if (strlen(num2str) == 1)
{
num2str[2] = '\0';
num2str[1] = num2str[0];
num2str[0] = '0';
}
cmd_str += num2str;
}
cmd_str += "\"";
send_wnc_cmd(cmd_str.c_str(), &pRespStr, WNC_TIMEOUT_MS);
}
else
pc.puts("sockwrite Err, string to long\r\n");
}
unsigned at_sockread_wnc(string * pS, unsigned n, unsigned retries = 0)
{
unsigned i;
string * pRespStr;
string cmd_str("AT@SOCKREAD=1,");
// Clean slate
pS->erase();
if (n <= 1500)
{
char num2str[6];
itoa(n, num2str, 10);
cmd_str += num2str;
retries += 1;
while (retries--)
{
// Assuming someone is sending then calling this to receive response, invoke
// a pause to give the response some time to come back and then also
// between each retry.
wait_ms(10);
send_wnc_cmd(cmd_str.c_str(), &pRespStr, WNC_TIMEOUT_MS);
size_t pos_start = pRespStr->find("\"") + 1;
size_t pos_end = pRespStr->rfind("\"") - 1;
i = pos_end - pos_start + 1;
if (i > 0)
{
retries = 0; // If any data found stop retrying
string byte;
while (pos_start < pos_end)
{
byte = pRespStr->substr(pos_start, 2);
*pS += (char)strtol(byte.c_str(), NULL, 16);
pos_start += 2;
}
return i;
}
}
}
else
pc.puts("sockread Err, to many to read\r\n");
return 0;
}