MaJerle / lwcell

Lightweight cellular modem host AT library
MIT License
395 stars 147 forks source link

SIM7070G support #71

Open Sazerac4 opened 1 year ago

Sazerac4 commented 1 year ago

Hello, I have used this library with a SIM868, and it worked very well. I am currently migrating to the SIM7070G chip. I have some questions :

MaJerle commented 1 year ago
  • Do I need to alter a lot of things?

Likely yes - standardized commands will work (mostly the one for boot, etc), but the rest, mainly connection commands won't since 7070 embeds different ones.

  • If so, what are the important files to look at?

Mostly the file that does all the processing and decides what command is next. That being lwgsm_int.c

  • I tried to activate all the logs of the library. I don't see the AT Command and Responses. Is this normal?

Logs in the library do not output actual command send and data received. You can do this by printing data sent in the send callback function and if you manually print out data you receive before you call lwgsm_input function.

Sazerac4 commented 1 year ago

Hello, thank you for your help.

I looked in more detail in the library and I identified the AT command codes to modify. For now, I'm doing a stupid ENUM replacement and looking for each AT command for adjustments. I hope to be able to integrate the changes to the library correctly once I have the TCP/IP stack working.

Context:

For debug, I use:

lwgsmr_t
lwgsm_input_process(const void* data, size_t len) {
 ....
 LWGSM_DEBUGF(LWGSM_CFG_DBG_AT | LWGSM_DBG_TYPE_ALL, "[AT](%02u)<%.*s\r\n", len, len, data);
...
}

and

static size_t
send_data(const void* data, size_t len) {
 ...
 LWGSM_DEBUGF(LWGSM_CFG_DBG_AT | LWGSM_DBG_TYPE_ALL, "[AT](%02u)>%.*s\r\n", len, len, data);
...
}

New AT command I try to add:

    LWGSM_CMD_CNACT,      /*! App Network Active */
    LWGSM_CMD_CACID,    /*!< Set TCP/UDP identifier */
    LWGSM_CMD_CASSLCFG, /*!< Set SSL certificate and timeout parameters */
    LWGSM_CMD_CAOPEN,   /*!< Open a TCP/UDP connection */
    LWGSM_CMD_CASERVER, /*!< Open a TCP/UDP server */
    LWGSM_CMD_CASEND,   /*!< Send data via an established connection */
    LWGSM_CMD_CARECV,   /*!< Receive data via an established connection */
    LWGSM_CMD_CACLOSE,  /*!< Close TCP or UDP Connection  */
    LWGSM_CMD_CACFG,    /*!< Configure transparent transmission parameters*/
    LWGSM_CMD_CASWITCH, /*!< Switch to transparent transport mode */

I try to understand the architecture to implement well the new commands. What is the process if I want to send two AT command for one functionality ?

Example : I want to open a socket. I need to do this:

AT+CASSLCFG=0,"SSL",0

OK

AT+CAOPEN=0,0,"TCP","117.131.85.139",6004

+CAOPEN: 0,0
OK

I try to start with

lwgsmr_t
lwgsm_conn_start(lwgsm_conn_p* conn, lwgsm_conn_type_t type, const char* const host, lwgsm_port_t port, void* const arg,
                 lwgsm_evt_fn conn_evt_fn, const uint32_t blocking) {
    LWGSM_MSG_VAR_DEFINE(msg);

    LWGSM_ASSERT("host != NULL", host != NULL);
    LWGSM_ASSERT("port > 0", port > 0);
    LWGSM_ASSERT("conn_evt_fn != NULL", conn_evt_fn != NULL);

    LWGSM_MSG_VAR_ALLOC(msg, blocking);
    LWGSM_MSG_VAR_REF(msg).cmd_def = LWGSM_CMD_CACID ; //XXX: LWGSM_CMD_CIPSTART  AT+CASSLCFG=0,"SSL",0
    LWGSM_MSG_VAR_REF(msg).cmd = LWGSM_CMD_CAOPEN ; //XXX: LWGSM_CMD_CIPSTATUS
    LWGSM_MSG_VAR_REF(msg).msg.conn_start.num = LWGSM_CFG_MAX_CONNS; /* Set maximal value as invalid number */
    LWGSM_MSG_VAR_REF(msg).msg.conn_start.conn = conn;
    LWGSM_MSG_VAR_REF(msg).msg.conn_start.type = type;
    LWGSM_MSG_VAR_REF(msg).msg.conn_start.host = host;
    LWGSM_MSG_VAR_REF(msg).msg.conn_start.port = port;
    LWGSM_MSG_VAR_REF(msg).msg.conn_start.evt_func = conn_evt_fn;
    LWGSM_MSG_VAR_REF(msg).msg.conn_start.arg = arg;

    return lwgsmi_send_msg_to_producer_mbox(&LWGSM_MSG_VAR_REF(msg), lwgsmi_initiate_cmd, 60000);
}
        case LWGSM_CMD_CAOPEN:
            { /* Start a new connection */
                lwgsm_conn_t* c = NULL;

                /* Do we have network connection? */
                /* Check if we are connected to network */

                msg->msg.conn_start.num = 0; /* Start with max value = invalidated */

                for (int16_t i = LWGSM_CFG_MAX_CONNS - 1; i >= 0; --i)
                { /* Find available connection */
                    if (!lwgsm.m.conns[i].status.f.active)
                    {
                        c                       = &lwgsm.m.conns[i];
                        c->num                  = LWGSM_U8(i);
                        msg->msg.conn_start.num = LWGSM_U8(i); /* Set connection number for message structure */
                        break;
                    }
                }
                if (c == NULL)
                {
                    lwgsmi_send_conn_error_cb(msg, lwgsmERRNOFREECONN);
                    return lwgsmERRNOFREECONN; /* We don't have available connection */
                }

                if (msg->msg.conn_start.conn != NULL)
                {                                  /* Is user interested about connection info? */
                    *msg->msg.conn_start.conn = c; /* Save connection for user */
                }

                AT_PORT_SEND_BEGIN_AT();
                AT_PORT_SEND_CONST_STR("+CAOPEN=");
                lwgsmi_send_number(LWGSM_U32(c->num), 0, 0); 
                lwgsmi_send_number(0, 0, 1);                 /
                if (msg->msg.conn_start.type == LWGSM_CONN_TYPE_UDP)
                {
                    lwgsmi_send_string("UDP", 0, 1, 1);
                }
                else
                {
                    lwgsmi_send_string("TCP", 0, 1, 1);
                }
                lwgsmi_send_string(msg->msg.conn_start.host, 0, 1, 1);
                // lwgsmi_send_number(strlen(msg->msg.conn_start.host), 0, 1, 1);
                lwgsmi_send_port(msg->msg.conn_start.port, 0, 1);
                AT_PORT_SEND_END_AT();
                break;
            }

I don't think I'm reasoning correctly about the general process of the library yet. Could I have an example process with my example?

Regards, Florrant

MaJerle commented 1 year ago

Multi at command for one functionality is pretty common indeed

Look at my imolementation of connection start or for instance sending sms. There is a subcomnand routine that can set new command to avoid completing the existing one.

Sazerac4 commented 1 year ago

Hello,

I began to understand deeper how work the library and my SIM7070G. To add officially SIM7070 IP Stack for lwgsm, I created a branch lwgm/SIM7070 I propose to create additional files to handle the growing number of AT commands.

WIP:

What did you think ?

MaJerle commented 1 year ago

In order to be successful with multiple devices, we need to create a different way of commands: