Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sim7600 SSL support v.0.12.0 #808

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open

Conversation

floBik
Copy link

@floBik floBik commented Sep 9, 2024

Co-authored-by: @Matt-Stedman

The following PR is an evolution of PR #767 and should resolve issue #786 . A few things have been done:

  • Bump to v0.12.0 of TinyGSM
  • Refactoring of certificate handling
  • updated readme
  • some bug fixes

Feel free to test this and give some feedback if something should be changed.

@apanagar
Copy link

First off, thanks for this work. This PR looks like exactly what I was looking for. I'm currently trying to run this code on the sim7600 but it seems like the String class in framework-arduino-sam doesn't have an isEmpty method: https://github.com/arduino/ArduinoCore-sam/blob/master/cores/arduino/WString.h

Currently getting the following error trace:

Processing due (platform: atmelsam; board: due; framework: arduino)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/due.html
PLATFORM: Atmel SAM (8.3.0) > Arduino Due (Programming Port)
HARDWARE: AT91SAM3X8E 84MHz, 96KB RAM, 512KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink, stlink)
PACKAGES: 
 - framework-arduino-sam @ 1.6.12 
 - framework-cmsis @ 1.40500.0 (4.5.0) 
 - framework-cmsis-atmel @ 1.2.2 
 - toolchain-gccarmnoneeabi @ 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 6 compatible libraries
Scanning dependencies...
Dependency Graph
|-- StreamDebugger @ 1.0.1
|-- TinyGSM @ 0.12.0
Building in release mode
Compiling .pio/build/due/src/main.cpp.o
Compiling .pio/build/due/FrameworkArduinoVariant/variant.cpp.o
Compiling .pio/build/due/FrameworkArduino/IPAddress.cpp.o
Compiling .pio/build/due/FrameworkArduino/Print.cpp.o
Compiling .pio/build/due/FrameworkArduino/Reset.cpp.o
Compiling .pio/build/due/FrameworkArduino/RingBuffer.cpp.o
Compiling .pio/build/due/FrameworkArduino/Stream.cpp.o
Compiling .pio/build/due/FrameworkArduino/UARTClass.cpp.o
Compiling .pio/build/due/FrameworkArduino/USARTClass.cpp.o
Compiling .pio/build/due/FrameworkArduino/USB/CDC.cpp.o
In file included from lib/TinyGSM/src/TinyGsmClient.h:55:0,
                 from src/main.cpp:100:
lib/TinyGSM/src/TinyGsmClientSIM7600.h: In member function 'virtual int TinyGsmSim7600::GsmClientSecureSim7600::connect(const char*, uint16_t, int)':
lib/TinyGSM/src/TinyGsmClientSIM7600.h:362:51: error: 'class String' has no member named 'isEmpty'
       if (certValidation && at->certificates[mux].isEmpty()) {return -1;}
                                                   ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h: In member function 'virtual void TinyGsmSim7600::GsmClientSecureSim7600::stop(uint32_t)':
lib/TinyGSM/src/TinyGsmClientSIM7600.h:372:30: error: 'class String' has no member named 'isEmpty'
       if (!certificates[mux].isEmpty()) {
                              ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:376:36: error: 'class String' has no member named 'isEmpty'
       if (!clientCertificates[mux].isEmpty()) {
                                    ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:380:35: error: 'class String' has no member named 'isEmpty'
       if (!clientPrivateKeys[mux].isEmpty()) {
                                   ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h: In member function 'bool TinyGsmSim7600::modemConnect(const char*, uint16_t, uint8_t, SSLVersion, int)':
lib/TinyGSM/src/TinyGsmClientSIM7600.h:913:30: error: 'class String' has no member named 'isEmpty'
       if (!certificates[mux].isEmpty()) {
                              ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:919:36: error: 'class String' has no member named 'isEmpty'
       if (!clientCertificates[mux].isEmpty()) {
                                    ^~~~~~~
In file included from lib/TinyGSM/src/TinyGsmClient.h:55:0,
                 from src/main.cpp:100:
lib/TinyGSM/src/TinyGsmClientSIM7600.h:924:35: error: 'class String' has no member named 'isEmpty'
       if (!clientPrivateKeys[mux].isEmpty()) {
                                   ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:929:30: error: 'class String' has no member named 'isEmpty'
       if (!certificates[mux].isEmpty() &&!clientCertificates[mux].isEmpty() && !clientPrivateKeys[mux].isEmpty()) {
                              ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:929:67: error: 'class String' has no member named 'isEmpty'
       if (!certificates[mux].isEmpty() &&!clientCertificates[mux].isEmpty() && !clientPrivateKeys[mux].isEmpty()) {
                                                                   ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:929:104: error: 'class String' has no member named 'isEmpty'
       if (!certificates[mux].isEmpty() &&!clientCertificates[mux].isEmpty() && !clientPrivateKeys[mux].isEmpty()) {
                                                                                                        ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:931:36: error: 'class String' has no member named 'isEmpty'
       } else if (certificates[mux].isEmpty() && !clientCertificates[mux].isEmpty() && !clientPrivateKeys[mux].isEmpty()) {
                                    ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:931:74: error: 'class String' has no member named 'isEmpty'
       } else if (certificates[mux].isEmpty() && !clientCertificates[mux].isEmpty() && !clientPrivateKeys[mux].isEmpty()) {
                                                                          ^~~~~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:931:111: error: 'class String' has no member named 'isEmpty'
       } else if (certificates[mux].isEmpty() && !clientCertificates[mux].isEmpty() && !clientPrivateKeys[mux].isEmpty()) {
                                                                                                               ^~~~~~~
src/main.cpp: In function 'void loop()':
src/main.cpp:239:15: error: no matching function for call to 'TinyGsmSim7600::GsmClientSecureSim7600::stop()'
   client.stop();
               ^
In file included from lib/TinyGSM/src/TinyGsmClient.h:55:0,
                 from src/main.cpp:100:
lib/TinyGSM/src/TinyGsmClientSIM7600.h:368:11: note: candidate: virtual void TinyGsmSim7600::GsmClientSecureSim7600::stop(uint32_t)
      void stop(uint32_t maxWaitMs) override {
           ^~~~
lib/TinyGSM/src/TinyGsmClientSIM7600.h:368:11: note:   candidate expects 1 argument, 0 provided
*** [.pio/build/due/src/main.cpp.o] Error 1
===================================================================== [FAILED] Took 1.04 seconds =====================================================================

https://registry.platformio.org/tools/platformio/framework-arduino-sam
Using the Arduino Due specifically because the sim7600 tx/rx are 3.3v and the Due natively supports 3.3v.

Thanks again

@arduino12
Copy link

arduino12 commented Dec 13, 2024

@floBik
It looks like Arduino String doesn't support the isEmpty() method-
(I am also using the Arduino Core STM32 if it matters..)

So I replaced all str.isEmpty() calls with !str.length() in TinyGsmClientSIM7600.h..
It compiles but doesn't work.. TINY_GSM_DEBUG didn't help..

I use the SIM7600E modem, and these commands seems to fail in the modem.gprsConnect():

AT+CCHCLOSE=0 -> ERROR
AT+CIPCLOSE=0 -> +CIPCLOSE: 0,4 ERROR
AT+CCHSEND=0,32 -> ERROR
AT+CCHSEND=0,17 -> ERROR
AT+CCHSEND=0,21 -> ERROR
AT+CCHSEND=0,2 -> ERROR
AT+CCHRECV? -> +CCHRECV: LEN,0,0 OK
AT+CCHCLOSE=0 -> ERROR
AT+CIPCLOSE=0 -> +CIPCLOSE: 0,4 ERROR

But the modem.gprsConnect() returns 0..

Any help will be much appreciated!

@floBik
Copy link
Author

floBik commented Jan 20, 2025

Hi everyone,

I have just committed a fix for the problem with the .isEmpty() function, using .length() instead. This should solve the problem.

@arduino12 If this doesn't solve your problem, post your code so I can have a look.

@arduino12
Copy link

Hi,

Thanks @floBik !

I don't have the SIM7600 modem by now so I can't test your fix..
I solved my problem using the raw HTTPS AT commands:

int8_t send_at_cmd(const char *cmd)
{
  modem.sendAT(cmd);
  return modem.waitResponse() == 1 ? 0 : 1;
}

int8_t send_https_post_request(const char *ip_address, const char *url, const char *content)
{
  int ret;
  char cmd[256];

  send_at_cmd("+HTTPTERM");
  if (send_at_cmd("+HTTPINIT"))
    return -1; // Failed starting HTTPS service!

  sprintf(cmd, "+HTTPPARA=\"URL\",\"https://%s%s\"", ip_address, url);
  if (send_at_cmd(cmd))
    return -2; // Failed setting HTTPS URL!

  if (send_at_cmd("+HTTPPARA=\"CONTENT\",\"application/json\""))
    return -3; // Failed setting HTTPS content-type!

  sprintf(cmd, "+HTTPDATA=%d,2000", strlen(content));
  modem.sendAT(cmd);
  if (modem.waitResponse("DOWNLOAD") != 1)
    return -4; // Failed setting HTTPS user-data!

  modem.stream.print(content);
  modem.stream.flush();
  if (modem.waitResponse() != 1)
    return -5; // Failed sending HTTPS user-data B!

  if (send_at_cmd("+HTTPACTION=1"))
    return -6; // Failed sending HTTPS post request!

  return 0;
}

I think its better to use the AT HTTP commands instead of making HTTP(S) packets using ArduinoHttpClient for this modem-
Will be useful to have something like the above function in the TinyGSM SIM7600 driver..!

Arad :)

Copy link

@st31ny st31ny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heyy, I just had a look on your code — thank you very much for your contribution!

Your implementation looks indeed pretty good and I tested it successfully. I just found some minor (mostly stylistic) issues.

return true;
}

bool setClientPrivateKey(const String& certificateName,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, we only need one function to set/reset both client cert and client pk, since setting only the cert or only the pk does not make any sense.

if (certificates[mux].length() != 0 &&
clientCertificates[mux].length() != 0 &&
clientPrivateKeys[mux].length() != 0) {
authmode = 2;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can actually be ORed into authmode, so no need for the extra branch.

if (waitResponse(5000L) != 1) return false;

sendAT(GF("+CCHOPEN="), mux, ',', GF("\""), host, GF("\","), port);
// The reply is OK followed by +CIPOPEN: <link_num>,<err> where <link_num>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy/paste?

@@ -292,7 +533,21 @@ class TinyGsmSim7600 : public TinyGsmModem<TinyGsmSim7600>,
/*
* Secure socket layer (SSL) functions
*/
// No functions of this type supported
public:
bool addCertificate(const char* certificateName, const char* cert,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, you want to override addCertificateImpl and deleteCertificateImpl resp. here (and have it protected).

Comment on lines +241 to +243
String certificates[TINY_GSM_MUX_COUNT];
String clientCertificates[TINY_GSM_MUX_COUNT];
String clientPrivateKeys[TINY_GSM_MUX_COUNT];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed?

Comment on lines +334 to +346
at->sendAT(GF("+CIPRXGET=4,"), mux);
size_t result = 0;
if (at->waitResponse(GF("+CIPRXGET:")) == 1) {
at->streamSkipUntil(','); // Skip mode 4
at->streamSkipUntil(','); // Skip mux
result = at->streamGetIntBefore('\n');
at->waitResponse();
}
// DBG("### Available:", result, "on", mux);
if (!result) {
at->sockets[mux]->sock_connected = at->modemGetConnected(mux);
}
return result;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look like an appropriate error handling (why CIPRXGET here?)… Maybe just check modemGetConnected() like for non-ssl.

// NOT SUPPORTED


class GsmClientSecureSim7600 : public GsmClientSim7600 {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my understanding, the SIM7600 only supports two SSL connections — so there should probably be a lower limit somewhere here to enforce this.

if (!clientPrivateKeys[mux].length() != 0) {
deleteCertificate(clientPrivateKeys[mux].c_str());
}
GsmClientSim7600::stop(maxWaitMs);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually also sends a CIPCLOSE which we probably don't want here, so better don't call this here.

Comment on lines +372 to +382
if (certificates[mux].length() != 0) {
deleteCertificate(certificates[mux].c_str());
}

if (!clientCertificates[mux].length() != 0) {
deleteCertificate(clientCertificates[mux].c_str());
}

if (!clientPrivateKeys[mux].length() != 0) {
deleteCertificate(clientPrivateKeys[mux].c_str());
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, the one adding certificates is also responsible for deleting them, so we don't want to delete them unconditionally here.


return true;
// We assume this works, so we can do ssh disconnect too
// stop the SSH client
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// stop the SSH client
// stop the SSL client

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants