Skip to content

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?

*/
// 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.


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

@rwtorres
Copy link

@floBik Hello, very interested in your project, I saw in another post of yours that you sucessfully implemented MQTT over TLS on the SIM7600 with this code, could you provide me an example code? Thank you very much.

@SRGDamia1
Copy link
Collaborator

I've incorporated this code on a side fork that I will (hopefully) finish merging here soon. On that fork, I created an example that connected to AWS IoT Core, which is MQTT on TLS: https://github.com/EnviroDIY/TinyGSM/tree/master/examples/AWS_IoTCore

One of the reasons I haven't pushed it here yet is that I have made changes to modems that I don't own to test (including the SIM7600), so if you can test it and let me know how it works for you, I'd appreciate it!

@alex-reusables
Copy link

@st31ny @floBik Wondering if there is a blocker here or something I could help with as it would be great to get this merged for those of us running SIM 7600. I see some changes were requested on Feb 5 a commit was pushed on the 13th, but maybe some of the requested changes were not addressed.

@floBik
Copy link
Author

floBik commented May 13, 2025

Hey @alex-reusables,

@SRGDamia1 included most of my changes in her fork. This made most of this review/MR irrelevant. After testing, I only noticed a few bugs, which I addressed in this PR: EnviroDIY#52

@alex-reusables
Copy link

@floBik Thanks for following up! We're using this TinyGSM library in a production context so would prefer to avoid pulling in forks or branches as it gets a bit tricky to manage on our end.

@st31ny
Copy link

st31ny commented May 14, 2025

@floBik Thanks for following up! We're using this TinyGSM library in a production context so would prefer to avoid pulling in forks or branches as it gets a bit tricky to manage on our end.

Same here — really looking forward to get this merged to master!

@floBik @SRGDamia1, is there anything we can help on to get this merged soon?

@Matt-Stedman
Copy link

@vshymanskyy Anything we can do to speed this along? The SIM7600 is an extremely popular chip and SSL is a must nowadays - it's been nearly a year now since this was first added, and most of our projects are now using @floBik's fork and you can imagine that's not best practice at all.

@pcxx13
Copy link

pcxx13 commented Nov 23, 2025

Great work @floBik @Matt-Stedman ! SSL support for SIMCOM7600 is a long time overdue.

I now have native SSL support between my 7600, TinyGSM and ArduinoHTTPClient working perfectly with FirebaseRTDB for POST and GET requests without the need for SSLClient. Certificate loading and activating is also working.

Has anyone been able to get BIN file download working with the forked SSL library? I can obtain the headers and content length ok, but as soon as the BIN file download starts it fails at 6026 bytes. With the AT debugger in play it seems that even the 6026 has data corruption. This is working when SSLClient is installed, but I really want to use your SSL supported library

12:31:00.424 -> Content length: 784496
12:31:33.504 -> OTA written successfully: 6026/784496 bytes written.
12:31:33.504 -> Error from Update.end(): 6

I am using #define TINY_GSM_RX_BUFFER 1024 and have tried reducing and increasing buffer size with no success.

Any comments and suggestions appreciated. Just wanted to check if anyone has tried <1MB BIN file downloading over SSL?

@Matt-Stedman
Copy link

@vshymanskyy Can we please get this merged? Or are you waiting for me to implement/accept @st31ny's changes? I'll see about doing that now, otherwise @floBik it may be you?

@apeman76

This comment was marked as off-topic.

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.

10 participants