diff --git a/.github/workflows/arduino-lint.yml b/.github/workflows/arduino-lint.yml
index e280129..3b3538b 100644
--- a/.github/workflows/arduino-lint.yml
+++ b/.github/workflows/arduino-lint.yml
@@ -19,10 +19,10 @@ jobs:
uses: actions/checkout@v4
- name: Arduino Lint
- uses: arduino/arduino-lint-action@v1
+ uses: arduino/arduino-lint-action@v2
with:
compliance: specification
- library-manager: submit
+ library-manager: update
# Always use this setting for official repositories. Remove for 3rd party projects.
official: true
project-type: library
\ No newline at end of file
diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml
index b1d15b8..12f25e1 100644
--- a/.github/workflows/compile-examples.yml
+++ b/.github/workflows/compile-examples.yml
@@ -25,9 +25,12 @@ env:
UNIVERSAL_SKETCH_PATHS: |
- examples/HTTPClient
- examples/HTTPSClient
- - examples/TimeAndLocation
+ - examples/GetTime
+ - examples/GetLocation
+ - examples/DeleteSMS
- examples/ReceiveSMS
- examples/SendSMS
+ - examples/ModemTerminal
SKETCHES_REPORTS_PATH: sketches-reports
SKETCHES_REPORTS_ARTIFACT_NAME: sketches-reports
diff --git a/.github/workflows/render-documentation.yml b/.github/workflows/render-documentation.yml
index 30ee933..db3617f 100644
--- a/.github/workflows/render-documentation.yml
+++ b/.github/workflows/render-documentation.yml
@@ -25,4 +25,5 @@ jobs:
with:
source-path: './src'
target-path: './docs/api.md'
- fail-on-warnings: true
\ No newline at end of file
+ fail-on-warnings: true
+ commit: ${{ github.event_name != 'pull_request' }} # Only commit changes if not a PR
diff --git a/README.md b/README.md
index 1bf33c6..0942055 100644
--- a/README.md
+++ b/README.md
@@ -1,39 +1,82 @@
-# Arduino Cellular
+# ๐ก Arduino Cellular
[](https://github.com/arduino-libraries/Arduino_Cellular/actions/workflows/arduino-lint.yml) [](https://github.com/arduino-libraries/Arduino_Cellular/actions/workflows/compile-examples.yml) [](https://github.com/arduino-libraries/Arduino_Cellular/actions/workflows/spell-check.yml) [](https://github.com/arduino-libraries/Arduino_Cellular/actions/workflows/sync-labels.yml) [](https://github.com/arduino-libraries/Arduino_Cellular/actions/workflows/render-documentation.yml)
-This library provides a toolkit for interacting with the official Arduino 4G Modules. It allows you to connect to the internet, send and receive SMS messages, and get location from the cellular network or GPS.
+This library provides a toolkit for interacting with the official Arduino 4G Modules ([EMEA](https://store.arduino.cc/products/4g-module-emea) and [Global Versions](https://store.arduino.cc/products/4g-module-global)).
+It allows you to connect to the internet, send and receive SMS messages, and get location from the cellular network or GPS.
## Examples
-* [examples/HTTPClient]() - Example of using this library together with [HttpClient]() to connect to a web server
-* [examples/HTTPClient]() - Example of using this library together with [HttpClient]() that uses [BearSSL]() under the hood to create a secure connection to a web server
-* [examples/ReceiveSMS]() - Example for the SMS sending and receiving functionality
-* [examples/TimeAndLocation]() - Use GPS, or Cellular to acquire the location and time of the device.
-* [examples/ModemTerminal]() - A handy example for debugging and Testing AT commands
+* [DeleteSMS](examples/DeleteSMS) - Example that shows how to delete SMS.
+* [GetLocation](examples/GetLocation) - Shows how to get the current GPS location.
+* [GetTime](examples/GetTime) - Use GPS to acquire the time of the device.
+* [HTTPClient](examples/HTTPClient) - Example of using this library together with [ArduinoHttpClient]() to connect to a web server
+* [HTTPSClient](examples/HTTPSClient) - Example of using this library together with [ArduinoHttpClient]() that uses [BearSSL]() under the hood to create a secure connection to a web server
+* [ModemTerminal](examples/ModemTerminal) - A handy example for debugging and Testing AT commands
+* [ReceiveSMS](examples/ReceiveSMS) - Example for the SMS sending and receiving functionality
+* [SendSMS](examples/SendSMS) - Shows how to send an SMS
-## Features
+## โจ Features
* Fast 4G connection to the internet
* Secure SSL connections with BearSSL
* Get location using GPS or GSM
* Synchronise time with the cell provider
* Send and Receive SMS Messages
-## Instructions
-1. Insert your Arduino 4G module to the Arduino Portenta Mid Carrier
-2. Insert a valid SIM card either on the back of the Arduino 4G miniPCI board, or the **PCIE_SIM** connector on the Portenta Mid Carrier
-3. Connect the 6 **SERIAL1** header pins to their corresponding pins on the **PCIE_BREAKOUT** header using jumpers
-
-4. Connect the **3V3 PCIE** pin to the **3V3 Buck**
-
-5. Connect external power to the Mid Carrier, via the **VIN** (5-12V) because modem use a lot of power when connecting or getting a GPS location. Make sure your supply can handle around 3A.
-6. Get the APN settings from your network operator and add them to the "ArduinoSecrets.h" file for each sketch
-```c
-const char apn[] = "live.vodafone.com";
-const char gprsUser[] = "live";
-const char gprsPass[] = "";
-```
-7. Install the library and it's dependencies
-8. Enjoy
+## ๐ Instructions
+1. Insert a nano SIM card in the **PCIE_SIM** connector on the [Arduino Portenta Mid Carrier](https://docs.arduino.cc/hardware/portenta-mid-carrier/).
+2. Connect the Serial (J17) to the adjacent PCIE Breakout Pins (J16) with jumpers included in the Portenta Mid Carrier:
+ | Serial 1 (J17) | PCIE Breakout (J16) |
+ |------------------------|---------------------|
+ | RX (Pin 1) | CK_N (Pin 1) |
+ | TX (Pin 2) | CK_P (Pin 3) |
+ | RTS (Pin 3) | RX_N (Pin 5) |
+ | CTS (Pin 4) | RX_P (Pin 7) |
+ | mPCIE_GPIO_RST (Pin 5) | mPCIE_RST (Pin 9) |
+
+
+3. On J9, using jumpers connect the following pins:
+ | Source (J9) | Buck Converter (J9) |
+ |------------------|---------------------|
+ | 3V3 PCIE (Pin 1) | 3V3 BUCK (Pin 3) |
+ | OUT VCC (Pin 2) | 3V3 BUCK EN (Pin 4) |
+
+
+4. Insert the [Arduino Pro 4G Module](https://docs.arduino.cc/hardware/pro-4g-module) in the Arduino Portenta Mid Carrier.
+
+5. Screw one black post with a white nut from under the Portenta Mid Carrier. Using another black post, screw the board to the post. Place two washers on top, and one underneath the Pro 4G Module. So that the board is fixed to the post snuggly and horizontally.
+
+6. (EMEA and GNSS variants) Connect the cellular antenna (flat antenna in [Arduino Pro 4G Module Antennas Kit](https://store.arduino.cc/products/4g-module-antenna)) to the left microUFL connector marked MAIN.
+
+7. (PRO 4G GNSS only) Connect the GNSS antenna (square antenna in [Arduino Pro 4G Module Antennas Kit](https://store.arduino.cc/products/4g-module-antenna)) to the middle microUFL connector marked GNSS.
+
+
+
+8. Insert a [Portenta C33](https://docs.arduino.cc/hardware/portenta-c33) or [Portenta H7](https://docs.arduino.cc/hardware/portenta-h7) Board into the marked location. The USB-C port of the Portenta board should be next to the Ethernet port on the Mid Carrier.
+
+9. Insert a Terminal Block 2-pin > DC female adapter into the screw terminal (J4). Ensure that the negative (-) pin is connected to GND.
+
+
+
+10. Use a 5V adapter that can output at least 3A and connect it to the DC female adapter.
+
+11. Connect the Portenta board to your computer using a USB-C cable.
+
+12. Install the `Arduino_Cellular` library and its dependencies
+
+13. Obtain the APN (Access Point Name) settings from your network operator and add them to the `arduino_secrets.h` file for each sketch. For example:
+ ```cpp
+ #define SECRET_PINNUMBER "" // replace with your SIM card PIN
+ #define SECRET_GPRS_APN "services.telenor.se" // replace with your GPRS APN
+ #define SECRET_GPRS_LOGIN "" // replace with your GPRS login
+ #define SECRET_GPRS_PASSWORD "" // replace with your GPRS password
+ ```
+
+14. Upload sketch to the Portenta board. Enjoy!
+
+
+## ๐ Documentation
+
+For more information about this library please read the documentation [here](./docs).
diff --git a/docs/Arduino_Portenta_Mid_Carrier_GNSS_with_GNSS_MAIN_Antennas.jpg b/docs/Arduino_Portenta_Mid_Carrier_GNSS_with_GNSS_MAIN_Antennas.jpg
new file mode 100644
index 0000000..0ca4fa7
Binary files /dev/null and b/docs/Arduino_Portenta_Mid_Carrier_GNSS_with_GNSS_MAIN_Antennas.jpg differ
diff --git a/docs/Arduino_Portenta_Mid_Carrier_PortentaC33_4GPRO_GNSS_All_Antennas.jpg b/docs/Arduino_Portenta_Mid_Carrier_PortentaC33_4GPRO_GNSS_All_Antennas.jpg
new file mode 100644
index 0000000..35a1719
Binary files /dev/null and b/docs/Arduino_Portenta_Mid_Carrier_PortentaC33_4GPRO_GNSS_All_Antennas.jpg differ
diff --git a/docs/Arduino_Portenta_Mid_Carrier_PortentaH7_and_PCIEBreakout_Pins.jpg b/docs/Arduino_Portenta_Mid_Carrier_PortentaH7_and_PCIEBreakout_Pins.jpg
new file mode 100644
index 0000000..06e86d7
Binary files /dev/null and b/docs/Arduino_Portenta_Mid_Carrier_PortentaH7_and_PCIEBreakout_Pins.jpg differ
diff --git a/docs/Arduino_Portenta_Mid_Carrier_SIM_and_Power_Pins.jpg b/docs/Arduino_Portenta_Mid_Carrier_SIM_and_Power_Pins.jpg
new file mode 100644
index 0000000..37b3e2b
Binary files /dev/null and b/docs/Arduino_Portenta_Mid_Carrier_SIM_and_Power_Pins.jpg differ
diff --git a/docs/api.md b/docs/api.md
index b27ddbf..7d5b0e4 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -3,10 +3,10 @@
Members | Descriptions
--------------------------------|---------------------------------------------
`class ` [`ArduinoCellular`](#class_arduino_cellular) | This class provides methods to interact with the Arduino Pro Modem, such as connecting to the network, sending [SMS](#class_s_m_s) messages, getting GPS location, and more.
-`class ` [`ModemInterface`](#class_modem_interface) | Represents the interface to the 4G modem module.
+`class ` [`ModemInterface`](#class_modem_interface) | Represents the interface to the 4G modem module which extends the TinyGsmBG96 class.
`class ` [`SMS`](#class_s_m_s) | Represents an [SMS](#class_s_m_s) message.
`class ` [`Time`](#class_time) | Represents a point in time with year, month, day, hour, minute, second, and offset.
-`struct ` [`Location`](#struct_location) | Represents a geographic location with latitude and longitude coordinates.
+`struct ` [`Geolocation`](#struct_geolocation) | Represents a geographic location with latitude and longitude coordinates.
# class `ArduinoCellular`
@@ -16,20 +16,22 @@ This class provides methods to interact with the Arduino Pro Modem, such as conn
Members | Descriptions
--------------------------------|---------------------------------------------
-| [`ArduinoCellular`](#class_arduino_cellular_1a96d1d9f3fbe80adc3d460b4364d47870) | Default constructor. |
-| [`begin`](#class_arduino_cellular_1ad5ca7cf61f48c40569f41f3029d6516e) | Initializes the modem. |
-| [`connect`](#class_arduino_cellular_1a041c9d5c546b82858b01859383d11fb7) | Connects to the network using the specified APN, GPRS username, and GPRS password. |
+| [`ArduinoCellular`](#class_arduino_cellular_1a96d1d9f3fbe80adc3d460b4364d47870) | Creates an instance of the [ArduinoCellular](#class_arduino_cellular) class. |
+| [`begin`](#class_arduino_cellular_1ad5ca7cf61f48c40569f41f3029d6516e) | Initializes the modem. This function must be called before using any other functions in the library. |
+| [`unlockSIM`](#class_arduino_cellular_1aa0be2795ff7b23c39ecef90d9906bbdf) | Unlocks the SIM card using the specified PIN. |
+| [`connect`](#class_arduino_cellular_1a7fb3c3e841b39c4faacef32cec6277b4) | Registers with the cellular network and connects to the Internet if the APN, GPRS username, and GPRS password are provided. |
| [`isConnectedToOperator`](#class_arduino_cellular_1af7453ef90702e9042e2b4b18fa89db03) | Checks if the modem is registered on the network. |
| [`isConnectedToInternet`](#class_arduino_cellular_1a6f8251e06de1810897b8bd8f8fb1b1a2) | Checks if the GPRS network is connected. |
-| [`enableGPS`](#class_arduino_cellular_1abe77a53e0eba6e8d62ba5db3bb6f5e92) | Enables or disables the GPS module. |
-| [`getGPSLocation`](#class_arduino_cellular_1aee57a2eec5be06172b2fb7cd574d9106) | Gets the GPS location. (Blocking call) |
-| [`getCellularLocation`](#class_arduino_cellular_1ac94da4914e08cc549134e6fe5575b5a6) | Gets the cellular location. (Blocking call) |
+| [`enableGPS`](#class_arduino_cellular_1abe77a53e0eba6e8d62ba5db3bb6f5e92) | Enables or disables the GPS functionality. |
+| [`getGPSLocation`](#class_arduino_cellular_1a41225f52d059df173f028ecd0c039ec3) | Gets the GPS location. (Blocking call) |
| [`getCellularTime`](#class_arduino_cellular_1a6b3ce5485badff582584d539e790aff4) | Gets the current time from the network. |
| [`getGPSTime`](#class_arduino_cellular_1a4aeb898c958e6eb001d606f0c7da8799) | Gets the current time from the GPS module. |
| [`sendSMS`](#class_arduino_cellular_1a371aef1318857f0863f443eaeabf4ac2) | Sends an [SMS](#class_s_m_s) message to the specified number. |
-| [`getReadSMS`](#class_arduino_cellular_1a5da65683df86af75590c7a68766236ee) | Gets the list of read [SMS](#class_s_m_s) messages. |
-| [`getUnreadSMS`](#class_arduino_cellular_1af1e3b2fad0a64f3b7675c88100ddbca5) | Gets the list of unread [SMS](#class_s_m_s) messages. |
-| [`sendATCommand`](#class_arduino_cellular_1a1d20e97f47d05d5420a98f79f213f978) | Sends an AT command to the modem and waits for a response, then returns the response. |
+| [`getReadSMS`](#class_arduino_cellular_1ae032c4e4cade6579a2c1edfe53d2ff2b) | Gets the list of read [SMS](#class_s_m_s) messages. |
+| [`getUnreadSMS`](#class_arduino_cellular_1a212513654884058947a2a4d332f6ccfc) | Gets the list of unread [SMS](#class_s_m_s) messages. |
+| [`deleteSMS`](#class_arduino_cellular_1abe4337f0bc8c486a076011309120ace1) | Deletes an [SMS](#class_s_m_s) message at the specified index. |
+| [`sendATCommand`](#class_arduino_cellular_1a58a3e3713af0c01ad1075a2509c6874d) | Sends an AT command to the modem and waits for a response, then returns the response. |
+| [`sendUSSDCommand`](#class_arduino_cellular_1a6886aec5850836ea8e8f135d4e5632ab) | Sends a USSD command to the network operator and waits for a response. |
| [`getNetworkClient`](#class_arduino_cellular_1acff92474af3bd819b62f132cf12f45ba) | Gets the Network client. (OSI Layer 3) |
| [`getSecureNetworkClient`](#class_arduino_cellular_1a8b7486d1a682787588c015af8d65a38e) | Gets the Transport Layer Security (TLS) client. (OSI Layer 4) |
| [`getHTTPClient`](#class_arduino_cellular_1aa1b4c3bbd14984d2a7ed1db7fa1ac930) | Gets the HTTP client for the specified server and port. |
@@ -46,7 +48,7 @@ This class provides methods to interact with the Arduino Pro Modem, such as conn
ArduinoCellular()
```
-Default constructor.
+Creates an instance of the [ArduinoCellular](#class_arduino_cellular) class.
@@ -56,26 +58,39 @@ Default constructor.
void begin()
```
-Initializes the modem.
+Initializes the modem. This function must be called before using any other functions in the library.
-### `connect`
+### `unlockSIM`
```cpp
-bool connect(String apn, String gprsUser, String gprsPass, String pin)
+bool unlockSIM(String pin)
```
-Connects to the network using the specified APN, GPRS username, and GPRS password.
+Unlocks the SIM card using the specified PIN.
#### Parameters
-* `apn` The Access Point Name.
+* `pin` The SIM card PIN.
-* `gprsUser` The GPRS username.
+#### Returns
+True if the SIM card is unlocked, false otherwise.
+
-* `gprsPass` The GPRS password.
+### `connect`
-* `pin` The SIM card PIN.
+```cpp
+bool connect(String apn, String username, String password)
+```
+
+Registers with the cellular network and connects to the Internet if the APN, GPRS username, and GPRS password are provided.
+
+#### Parameters
+* `apn` The Access Point Name.
+
+* `username` The APN username.
+
+* `password` The APN password.
#### Returns
True if the connection is successful, false otherwise.
@@ -111,19 +126,19 @@ True if the GPRS network is connected, false otherwise.
bool enableGPS(bool assisted)
```
-Enables or disables the GPS module.
+Enables or disables the GPS functionality.
#### Parameters
* `assisted` True to enable assisted GPS, false to disable it. Assist GPS uses the network to get the GPS location faster, so cellular needs to be enabled.
#### Returns
-True if the GPS module is enabled, false otherwise.
+True if GPS was enabled successfully, false otherwise.
-### `getGPSLocation`
+### `getGPSLocation`
```cpp
-Location getGPSLocation(unsigned long timeout)
+Geolocation getGPSLocation(unsigned long timeout)
```
Gets the GPS location. (Blocking call)
@@ -135,21 +150,6 @@ Gets the GPS location. (Blocking call)
The GPS location. If the location is not retrieved, the latitude and longitude will be 0.0.
-### `getCellularLocation`
-
-```cpp
-Location getCellularLocation(unsigned long timeout)
-```
-
-Gets the cellular location. (Blocking call)
-
-#### Parameters
-* `timeout` The timeout (In milliseconds) to wait for the cellular location.
-
-#### Returns
-The cellular location. If the location is not retrieved, the latitude and longitude will be 0.0.
-
-
### `getCellularTime`
```cpp
@@ -188,7 +188,7 @@ Sends an [SMS](#class_s_m_s) message to the specified number.
* `message` The message to send.
-### `getReadSMS`
+### `getReadSMS`
```cpp
std::vector< SMS > getReadSMS()
@@ -200,7 +200,7 @@ Gets the list of read [SMS](#class_s_m_s) messages.
A vector of [SMS](#class_s_m_s) messages.
-### `getUnreadSMS`
+### `getUnreadSMS`
```cpp
std::vector< SMS > getUnreadSMS()
@@ -212,10 +212,25 @@ Gets the list of unread [SMS](#class_s_m_s) messages.
A vector of [SMS](#class_s_m_s) messages.
-### `sendATCommand`
+### `deleteSMS`
+
+```cpp
+bool deleteSMS(uint16_t index)
+```
+
+Deletes an [SMS](#class_s_m_s) message at the specified index.
+
+#### Parameters
+* `index` The index of the [SMS](#class_s_m_s) message to delete.
+
+#### Returns
+True if the [SMS](#class_s_m_s) message was successfully deleted, false otherwise.
+
+
+### `sendATCommand`
```cpp
-String sendATCommand(char * command, unsigned long timeout)
+String sendATCommand(const char * command, unsigned long timeout)
```
Sends an AT command to the modem and waits for a response, then returns the response.
@@ -223,12 +238,27 @@ Sends an AT command to the modem and waits for a response, then returns the resp
#### Parameters
* `command` The AT command to send.
-* `timeout` The timeout (In milliseconds) to wait for the response.
+* `timeout` The timeout (In milliseconds) to wait for the response. Default is 1000ms.
#### Returns
The response from the modem.
+### `sendUSSDCommand`
+
+```cpp
+String sendUSSDCommand(const char * command)
+```
+
+Sends a USSD command to the network operator and waits for a response.
+
+#### Parameters
+* `command` The USSD command to send.
+
+#### Returns
+The response from the network operator. (Note: The response may be an [SMS](#class_s_m_s) message or a USSD response)
+
+
### `getNetworkClient`
```cpp
@@ -332,16 +362,16 @@ class ModemInterface
: public TinyGsmBG96
```
-Represents the interface to the 4G modem module.
+Represents the interface to the 4G modem module which extends the TinyGsmBG96 class.
## Summary
Members | Descriptions
--------------------------------|---------------------------------------------
| [`stream`](#class_modem_interface_1a4a8be6e54608e2cbd9704614b807b4b0) | The stream object for communication with the modem. |
-| [`power_pin`](#class_modem_interface_1a3b23e45b1497e372a4965d87656523d6) | The pin number for controlling the power of the modem. |
-| [`ModemInterface`](#class_modem_interface_1a4fad197930f994b036cc3f1645612fce) | Constructor for the [ModemInterface](#class_modem_interface) class. |
-| [`init`](#class_modem_interface_1a2f8f381994be24bb821ace646f7fde9b) | Initializes the modem interface. |
+| [`powerPin`](#class_modem_interface_1a26e5e7417ff90759520c89776fb0c7f2) | The pin number for controlling the power of the modem. |
+| [`ModemInterface`](#class_modem_interface_1aa364cae2d778d717ca1c53a0e4ee8702) | Constructor for the [ModemInterface](#class_modem_interface) class. |
+| [`init`](#class_modem_interface_1a2f8f381994be24bb821ace646f7fde9b) | Initializes the modem interface. (Overrides the init method in TinyGsmBG96) |
## Members
@@ -354,19 +384,19 @@ Stream * stream
The stream object for communication with the modem.
-### `power_pin`
+### `powerPin`
```cpp
-int power_pin
+int powerPin
```
The pin number for controlling the power of the modem.
-### `ModemInterface`
+### `ModemInterface`
```cpp
-inline explicit ModemInterface(Stream & stream, int power_pin)
+inline explicit ModemInterface(Stream & stream, int powerPin)
```
Constructor for the [ModemInterface](#class_modem_interface) class.
@@ -374,7 +404,7 @@ Constructor for the [ModemInterface](#class_modem_interface) class.
#### Parameters
* `stream` The stream object for communication with the modem.
-* `power_pin` The pin number for controlling the power of the modem.
+* `powerPin` The pin number for controlling the power of the modem.
### `init`
@@ -383,7 +413,7 @@ Constructor for the [ModemInterface](#class_modem_interface) class.
inline bool init(const char * pin)
```
-Initializes the modem interface.
+Initializes the modem interface. (Overrides the init method in TinyGsmBG96)
#### Parameters
* `pin` The PIN code for the SIM card (optional).
@@ -400,18 +430,28 @@ Represents an [SMS](#class_s_m_s) message.
Members | Descriptions
--------------------------------|---------------------------------------------
-| [`number`](#class_s_m_s_1a7e93b46a5ea599e6fdc27295afaf4c51) | The phone number associated with the [SMS](#class_s_m_s). |
+| [`index`](#class_s_m_s_1a1d7df5242fd17e58cb5c7ef1f81472fb) | The index of the [SMS](#class_s_m_s) message. |
+| [`sender`](#class_s_m_s_1aafb60a0ef09724cc5e3f659505c9dab3) | The phone number associated with the [SMS](#class_s_m_s). |
| [`message`](#class_s_m_s_1ad2f3aac08b66f78472b18727a653c7c4) | The content of the [SMS](#class_s_m_s) message. |
| [`timestamp`](#class_s_m_s_1a8f275bdda4111b2ecc95f269cec70940) | The timestamp when the [SMS](#class_s_m_s) was received. |
| [`SMS`](#class_s_m_s_1ac4a683a43558570b5a9cb3a92100c29e) | Default constructor for [SMS](#class_s_m_s). Initializes the number, message, and timestamp to empty values. |
-| [`SMS`](#class_s_m_s_1a964afc86f65da37c4bf8e099e250f9de) | Constructor for [SMS](#class_s_m_s). |
+| [`SMS`](#class_s_m_s_1abb10fd15a6e3d1f3b6a9bb24123d4e0a) | Constructor for [SMS](#class_s_m_s). |
## Members
-### `number`
+### `index`
+
+```cpp
+int16_t index
+```
+
+The index of the [SMS](#class_s_m_s) message.
+
+
+### `sender`
```cpp
-String number
+String sender
```
The phone number associated with the [SMS](#class_s_m_s).
@@ -444,15 +484,17 @@ inline SMS()
Default constructor for [SMS](#class_s_m_s). Initializes the number, message, and timestamp to empty values.
-### `SMS`
+### `SMS`
```cpp
-inline SMS(String number, String message, Time timestamp)
+inline SMS(int16_t index, String sender, String message, Time timestamp)
```
Constructor for [SMS](#class_s_m_s).
#### Parameters
-* `number` The phone number associated with the [SMS](#class_s_m_s).
+* `index` The index of the [SMS](#class_s_m_s) message.
+
+* `sender` The phone number associated with the sender of the [SMS](#class_s_m_s).
* `message` The content of the [SMS](#class_s_m_s) message.
@@ -782,7 +824,7 @@ Returns the timezone offset of the time.
The timezone offset of the time.
-# struct `Location`
+# struct `Geolocation`
Represents a geographic location with latitude and longitude coordinates.
@@ -790,12 +832,12 @@ Represents a geographic location with latitude and longitude coordinates.
Members | Descriptions
--------------------------------|---------------------------------------------
-| [`latitude`](#struct_location_1a194bf3edf130d2a4bf281720e7d01409) | The latitude coordinate of the location. |
-| [`longitude`](#struct_location_1ae36169ef2dfcad63e26b492a6a82b990) | The longitude coordinate of the location. |
+| [`latitude`](#struct_geolocation_1a86c7bea43545766d1da49a566b579846) | The latitude coordinate of the location. |
+| [`longitude`](#struct_geolocation_1a6df627e2a4f3566e7a40cec69c94fd06) | The longitude coordinate of the location. |
## Members
-### `latitude`
+### `latitude`
```cpp
float latitude
@@ -804,7 +846,7 @@ float latitude
The latitude coordinate of the location.
-### `longitude`
+### `longitude`
```cpp
float longitude
diff --git a/docs/readme.md b/docs/readme.md
index 20c9ef4..a01592a 100644
--- a/docs/readme.md
+++ b/docs/readme.md
@@ -1,30 +1,30 @@
-# Arduino Cellular Library
+# ๐ก Arduino Cellular Library
-
-## Initialising
+## โคต๏ธ Initialising
This guide outlines the steps to establish cellular network connectivity using an Arduino equipped with a cellular modem. The process involves initializing the modem, setting necessary configurations, and establishing a connection to the network.
First, you need to include the ArduinoCellular library in your sketch. This library facilitates communication between your Arduino board and the cellular module.
-```c
+```cpp
#include
```
Create an instance of the ArduinoCellular class. This instance will be used to interact with the cellular module.
-```c
+```cpp
ArduinoCellular cellular = ArduinoCellular();
```
To begin, initialize the modem with basic configurations such as setting the modem to text mode, enabling intrrerupts etc. This is done by calling the begin() method on your cellular instance.
-```c
+```cpp
cellular.begin();
```
-To connect to your mobile network and start a cellular data session, use the connect() method. This requires the APN (Access Point Name), login credentials (if any), and your SIM card's PIN number (if it's locked).
+To connect to your mobile network and start a cellular data session, use the connect() method. This requires the APN (Access Point Name) and login credentials (if any). You can unlock your SIM card's using its PIN number (if it's locked).
-```c
-cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD, SECRET_PINNUMBER);
+```cpp
+cellular.unlockSIM(SECRET_PINNUMBER)
+cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD);
```
@@ -33,7 +33,7 @@ Note: It's a best practice to store sensitive information like the GPRS APN, log
**arduino_secrets.h**
Create or edit the arduino_secrets.h file in your project directory and define the necessary secrets as follows:
-```c
+```cpp
#define SECRET_GPRS_APN "your_apn_here"
#define SECRET_GPRS_LOGIN "your_login_here"
#define SECRET_GPRS_PASSWORD "your_password_here"
@@ -43,7 +43,7 @@ Create or edit the arduino_secrets.h file in your project directory and define t
Replace the placeholder values with the actual APN, login, password, and PIN number provided by your mobile network operator or SIM card provider.
-## Network
+## ๐ Network
The Arduino environment provides a set of classes designed to abstract the complexities of handling network communications. Among these, the Client class plays a crucial role as it defines a standard interface for network communication across various Arduino-compatible networking libraries.
The Arduino networking stack is designed to simplify the process of implementing network communication for IoT (Internet of Things) projects. This stack encompasses both hardware (e.g., Ethernet shields, WiFi modules) and software components (libraries that interface with the hardware). The stack is built in a way that allows sketches (Arduino programs) to communicate over the network using common protocols like TCP and UDP without needing to delve into the low-level mechanics of these protocols.
@@ -63,13 +63,13 @@ This layered approach is not only modular but also highly flexible, allowing dev
### Network Client (OSI Layer 3)
Represents a basic client for network communication, suitable for protocols like TCP/IP.
-```c
+```cpp
TinyGSMClient client = cellular.getNetworkClient();
```
### Secure Network Client
Adds a layer of security by implementing SSL/TLS encryption over the basic client.
-```c
+```cpp
BearSSLClient secureClient = cellular.getSecureNetworkClient();
```
@@ -78,20 +78,20 @@ For convenience we added getters for http and https clients.
### HTTP and HTTPS Clients:
These are high-level clients designed for web communication. They abstract the complexities of HTTP/HTTPS protocols, making it easy to send web requests and process responses.
-```c
+```cpp
HttpClient http = cellular.getHTTPClient(server, port);
HttpClient http = cellular.getHTTPSClient(server, port);
```
-## SMS
+## ๐จ SMS
The SMS functionality allows devices to exchange information with users or other systems through simple text messages, enabling a wide range of applications from remote monitoring to control systems or a fallback communication method when the others are not available.
### Reading SMS Messages
**getReadSMS():** This method returns a vector containing SMS messages that have already been read. It's particularly useful for applications that need to process or display messages that have been acknowledged.
-**getUnreadSMS(): **This method fetches a vector of unread SMS messages, allowing the application to process or notify users about new messages.
+**getUnreadSMS():** This method fetches a vector of unread SMS messages, allowing the application to process or notify users about new messages.
Each SMS message is represented as an instance of the `SMS` class, which contains the sender's number, the message text, and a timestamp marking when the message was received.
@@ -99,7 +99,7 @@ Each SMS message is represented as an instance of the `SMS` class, which contain
### The SMS Class
The SMS class serves as a container for information related to a single SMS message. It includes the following attributes:
-* `number`: The phone number from which the SMS was sent.
+* `sender`: The phone number from which the SMS was sent.
* `message`: The body of the SMS message.
* `timestamp`: A timestamp indicating when the message was received by the module.
@@ -115,7 +115,7 @@ The method sendSMS() is designed for this purpose, taking two parameters:
This functionality allows Arduino devices to communicate outwardly to users or other systems, sending alerts, data, or control commands via SMS.
-## Time and Location
+## โ๏ธ๐ Time and Location
These features enable precise tracking of device locations and ensure synchronized operations across different systems. This guide focuses on utilizing GPS and cellular network capabilities for location tracking and time synchronization. It's important to note that GPS functionality is exclusively available in the Global Version of the modem, highlighting the need for appropriate hardware selection based on the project requirements.
### GPS Location
@@ -125,11 +125,6 @@ GPS Location is ideal for applications requiring high-precision location data, s
To enable GPS Location you will need to call `enableGPS(bool assisted)`. Assisted GPS or A-GPS is an enhancement of GPS that uses the cellular network to get the location, it performs that much quicker than without assistance but depends on Cellular network coverage.
-### Cellular Location
-**Method Overview:** `getCellularLocation(unsigned long timeout = 10000)` also provides location tracking but utilizes the cellular network. Similar to the GPS method, it's a blocking call with a specified timeout, returning latitude and longitude values through a Location structure. If the location is not obtained, the values default to 0.0.
-
-Cellular location is suitable for scenarios where GPS signals are weak or unavailable, offering a broader coverage area at the expense of location accuracy. This method leverages the cellular network's infrastructure to approximate the device's location.
-
### Time Synchronization
Time synchronization is crucial for maintaining accurate timing across IoT devices, especially for data logging, scheduled tasks, and time-stamped communications.
diff --git a/examples/DeleteSMS/DeleteSMS.ino b/examples/DeleteSMS/DeleteSMS.ino
new file mode 100644
index 0000000..966a763
--- /dev/null
+++ b/examples/DeleteSMS/DeleteSMS.ino
@@ -0,0 +1,63 @@
+/**
+ * This example demonstrates how to delete SMS messages using the ArduinoCellular library.
+ *
+ * Instructions:
+ * 1. Insert a SIM card with or without PIN code in the Arduino Pro 4G Module.
+ * 2. Provide sufficient power to the Arduino Pro 4G Module. Ideally, use a 5V power supply
+ * with a current rating of at least 2A and connect it to the VIN and GND pins.
+ * 3. Send an SMS to the SIM card number to test the SMS reception.
+ * 4. Upload the sketch to the connected Arduino board.
+ * 5. Check the serial monitor for the received SMS.
+ * 6. Enter the index of the SMS you want to delete in the serial monitor.
+ *
+ * Initial author: Sebastian Romero
+*/
+
+#include "ArduinoCellular.h"
+
+ArduinoCellular cellular = ArduinoCellular();
+
+void printMessages(std::vector msg){
+ for(int i = 0; i < msg.size(); i++){
+ Serial.println("SMS:");
+ Serial.print("* Index: "); Serial.println(msg[i].index);
+ Serial.print("* From: "); Serial.println(msg[i].sender);
+ Serial.print("* Timestamp: "); Serial.println(msg[i].timestamp.getISO8601());
+ Serial.println("* Message: "); Serial.println(msg[i].message);
+ Serial.println("--------------------\n");
+ }
+}
+
+void setup(){
+ Serial.begin(115200);
+ while (!Serial);
+ cellular.begin();
+ delay(2000); // Give the modem some time to initialize
+}
+
+void loop(){
+ std::vector readSMS = cellular.getReadSMS();
+ if(readSMS.size() > 0){
+ Serial.println("Read SMS:");
+ printMessages(readSMS);
+ }
+
+ std::vector unreadSMS = cellular.getUnreadSMS();
+ if(unreadSMS.size() > 0){
+ Serial.println("Unread SMS:");
+ printMessages(unreadSMS);
+ }
+
+ // Prompt user which SMS to delete
+ Serial.println("Enter the index of the SMS you want to delete:");
+
+ while(Serial.available() == 0);
+ auto index = Serial.readStringUntil('\n').toInt();
+ Serial.println("Deleting SMS...");
+
+ if(cellular.deleteSMS(index)){
+ Serial.println("SMS deleted.");
+ } else {
+ Serial.println("Failed to delete SMS.");
+ }
+}
diff --git a/examples/GetLocation/GetLocation.ino b/examples/GetLocation/GetLocation.ino
new file mode 100644
index 0000000..a59aa6c
--- /dev/null
+++ b/examples/GetLocation/GetLocation.ino
@@ -0,0 +1,37 @@
+/**
+ * This example demonstrates how to get the current GPS location using the ArduinoCellular library.
+ *
+ * Instructions:
+ * 1. Move the Arduino Pro 4G Module to an outdoor location with a clear view of the sky.
+ * 2. Provide sufficient power to the Arduino Pro 4G Module. Ideally, use a 5V power supply
+ * 3. Upload the sketch to the connected Arduino board.
+ * 4. Open the serial monitor to view the output.
+ *
+ * Initial author: Sebastian Romero
+*/
+
+#include "ArduinoCellular.h"
+
+ArduinoCellular cellular = ArduinoCellular();
+
+void setup(){
+ Serial.begin(115200);
+ while (!Serial);
+ cellular.setDebugStream(Serial);
+ cellular.begin();
+
+ if(!cellular.enableGPS()){
+ Serial.println("Failed to enable GPS");
+ while(true); // Stop the program
+ }
+ delay(2000); // Give the modem some time to initialize
+}
+
+void loop(){
+ Geolocation location = cellular.getGPSLocation();
+ Serial.println("GPS Location:");
+ Serial.print("* Latitude: "); Serial.println(location.latitude, 6);
+ Serial.print("* Longitude: "); Serial.println(location.longitude, 6);
+ Serial.println("--------------------\n");
+ delay(10000);
+}
diff --git a/examples/GetTime/GetTime.ino b/examples/GetTime/GetTime.ino
new file mode 100644
index 0000000..6071b44
--- /dev/null
+++ b/examples/GetTime/GetTime.ino
@@ -0,0 +1,41 @@
+/**
+ * This example demonstrates how to get the current time using the ArduinoCellular library.
+ * It derives the time from GPS connection.
+ *
+ * Instructions:
+ * 1. Move the Arduino Pro 4G Module to an outdoor location with a clear view of the sky.
+ * 2. Provide sufficient power to the Arduino Pro 4G Module. Ideally, use a 5V power supply
+ * 3. Upload the sketch to the connected Arduino board.
+ * 4. Open the serial monitor to view the output.
+ *
+ * Initial author: Cristian Dragomir
+*/
+
+#include "ArduinoCellular.h"
+
+ArduinoCellular cellular = ArduinoCellular();
+
+void setup(){
+ Serial.begin(115200);
+ while (!Serial);
+ cellular.begin();
+
+ if(!cellular.enableGPS()){
+ Serial.println("Failed to enable GPS");
+ while(true); // Stop the program
+ }
+ delay(2000); // Give the modem some time to initialize
+}
+
+void loop(){
+ Geolocation location = cellular.getGPSLocation(10000);
+
+ if(location.latitude == 0.0 && location.longitude == 0.0){
+ Serial.println("Failed to get GPS location");
+ } else {
+ Time time = cellular.getGPSTime();
+ Serial.print("Current time (ISO8601): "); Serial.println(time.getISO8601());
+ }
+
+ delay(10000);
+}
\ No newline at end of file
diff --git a/examples/HTTPClient/HTTPClient.ino b/examples/HTTPClient/HTTPClient.ino
index 5525676..fa275ce 100644
--- a/examples/HTTPClient/HTTPClient.ino
+++ b/examples/HTTPClient/HTTPClient.ino
@@ -1,3 +1,18 @@
+/**
+ * This example demonstrates how to make a HTTP GET request using
+ * the ArduinoHttpClient library and the ArduinoCellular library.
+ *
+ * Instructions:
+ * 1. Insert a SIM card with or without PIN code in the Arduino Pro 4G Module.
+ * 2. Provide sufficient power to the Arduino Pro 4G Module. Ideally, use a 5V power supply
+ * with a current rating of at least 2A and connect it to the VIN and GND pins.
+ * 3. Specify the APN, login, and password for your cellular network provider.
+ * 4. Upload the sketch to the connected Arduino board.
+ * 5. Open the serial monitor to view the output.
+ *
+ * Initial author: Cristian Dragomir
+*/
+
#define ARDUINO_CELLULAR_DEBUG
#include "ArduinoCellular.h"
@@ -10,14 +25,7 @@ const int port = 80;
ArduinoCellular cellular = ArduinoCellular();
HttpClient client = cellular.getHTTPClient(server, port);
-void setup(){
- Serial.begin(115200);
- while (!Serial);
- cellular.begin();
- cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD, SECRET_PINNUMBER);
-}
-
-void loop(){
+void getResource(){
Serial.println("Making GET request...");
@@ -32,7 +40,27 @@ void loop(){
Serial.println(response);
client.stop();
+}
- delay(5000);
+void setup(){
+ Serial.begin(115200);
+ while (!Serial);
+ // cellular.setDebugStream(Serial); // Uncomment this line to enable debug output
+ cellular.begin();
+ if(String(SECRET_PINNUMBER).length() > 0 && !cellular.unlockSIM(SECRET_PINNUMBER)){
+ Serial.println("Failed to unlock SIM card.");
+ while(true); // Stop here
+ }
+
+ Serial.println("Connecting...");
+ if(!cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD)){
+ Serial.println("Failed to connect to the network.");
+ while(true); // Stop here
+ }
+ Serial.println("Connected!");
+
+ getResource();
}
+
+void loop(){}
diff --git a/examples/HTTPSClient/HTTPSClient.ino b/examples/HTTPSClient/HTTPSClient.ino
index f4b45d7..20a328a 100644
--- a/examples/HTTPSClient/HTTPSClient.ino
+++ b/examples/HTTPSClient/HTTPSClient.ino
@@ -1,3 +1,17 @@
+/**
+ * Example demonstrating how to make an HTTPS GET request using
+ * the ArduinoHttpClient library and the ArduinoCellular library.
+ *
+ * Instructions:
+ * 1. Insert a SIM card with or without PIN code in the Arduino Pro 4G Module.
+ * 2. Provide sufficient power to the Arduino Pro 4G Module. Ideally, use a 5V power supply
+ * with a current rating of at least 2A and connect it to the VIN and GND pins.
+ * 3. Specify the APN, login, and password for your cellular network provider.
+ * 4. Upload the sketch to the connected Arduino board.
+ * 5. Open the serial monitor to view the output.
+ *
+ * Initial author: Cristian Dragomir
+*/
#include
#include "ArduinoCellular.h"
@@ -11,15 +25,7 @@ const int port = 443;
ArduinoCellular cellular = ArduinoCellular();
HttpClient client = cellular.getHTTPSClient(server, port);
-void setup(){
- Serial.begin(115200);
- while (!Serial);
-
- cellular.begin();
- cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD, SECRET_PINNUMBER);
-}
-
-void loop(){
+void getResource(){
Serial.println("Making GET request...");
client.get(resource);
@@ -33,5 +39,28 @@ void loop(){
Serial.println(response);
client.stop();
- delay(5000);
}
+
+void setup(){
+ Serial.begin(115200);
+ while (!Serial);
+
+ // cellular.setDebugStream(Serial); // Uncomment this line to enable debug output
+ cellular.begin();
+
+ if(String(SECRET_PINNUMBER).length() > 0 && !cellular.unlockSIM(SECRET_PINNUMBER)){
+ Serial.println("Failed to unlock SIM card.");
+ while(true); // Stop here
+ }
+
+ Serial.println("Connecting...");
+ if(!cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD)){
+ Serial.println("Failed to connect to the network.");
+ while(true); // Stop here
+ }
+ Serial.println("Connected!");
+
+ getResource();
+}
+
+void loop(){}
diff --git a/examples/ModemTerminal/ModemTerminal.ino b/examples/ModemTerminal/ModemTerminal.ino
index 7436d2e..6d064ae 100644
--- a/examples/ModemTerminal/ModemTerminal.ino
+++ b/examples/ModemTerminal/ModemTerminal.ino
@@ -1,31 +1,46 @@
+/**
+ * The ModemTerminal example demonstrates how to use the ArduinoCellular library to send raw AT commands to the modem.
+ *
+ * Instructions:
+ * 1. Insert a SIM card with or without PIN code in the Arduino Pro 4G Module.
+ * 2. Provide sufficient power to the Arduino Pro 4G Module. Ideally, use a 5V power supply
+ * with a current rating of at least 2A and connect it to the VIN and GND pins.
+ * 3. Specify the APN, login, and password for your cellular network provider.
+ * 4. Upload the sketch to the connected Arduino board.
+ * 5. Open the serial monitor and type AT commands to interact with the modem.
+ *
+ * Initial author: Cristian Dragomir
+*/
+
#include "ArduinoCellular.h"
#include "arduino_secrets.h"
-
ArduinoCellular cellular = ArduinoCellular();
-float lat = 0.00;
-float lon = 0.00;
-
-
void setup(){
Serial.begin(115200);
while (!Serial);
+ cellular.setDebugStream(Serial); // Uncomment this line to enable debug output
cellular.begin();
- cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD, SECRET_PINNUMBER);
+
+ if(String(SECRET_PINNUMBER).length() > 0 && !cellular.unlockSIM(SECRET_PINNUMBER)){
+ Serial.println("Failed to unlock SIM card.");
+ while(true); // Stop here
+ }
+
+ Serial.println("Connecting...");
+ cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD);
+ Serial.println("Connected!");
+ Serial.println("You can now send AT commands to the modem.");
}
void loop() {
- if (Serial.available() > 0) {
- // Define a buffer to store incoming data. Adjust the size as needed.
- char incomingData[255]; // Adjust the size according to your needs
-
- // Read data from serial until newline is found
- int size = Serial.readBytesUntil('\n', incomingData, sizeof(incomingData) - 1); // Leave space for null terminator
-
- // Null-terminate the string
- incomingData[size] = '\0';
- // Call the sendATCommand function with the read data
- Serial.println(cellular.sendATCommand(GF(incomingData)));
- }
+ while(Serial.available() == 0); // Wait for user input
+
+ // Read data from serial until newline
+ String userInput = Serial.readStringUntil('\n');
+
+ // Call the sendATCommand function with the read data
+ String response = cellular.sendATCommand(userInput.c_str());
+ Serial.println(response);
}
\ No newline at end of file
diff --git a/examples/ReceiveSMS/ReceiveSMS.ino b/examples/ReceiveSMS/ReceiveSMS.ino
index 6564db4..f866f65 100644
--- a/examples/ReceiveSMS/ReceiveSMS.ino
+++ b/examples/ReceiveSMS/ReceiveSMS.ino
@@ -1,53 +1,95 @@
-#include "ArduinoCellular.h"
-#include "arduino_secrets.h"
+/**
+ * This example demonstrates how to receive SMS messages using ArduinoCellular library.
+ * It supports both polling and interrupt based methods to check for new SMS messages.
+ *
+ * Instructions:
+ * 1. Insert a SIM card with or without PIN code in the Arduino Pro 4G Module.
+ * 2. Provide sufficient power to the Arduino Pro 4G Module. Ideally, use a 5V power supply
+ * with a current rating of at least 2A and connect it to the VIN and GND pins.
+ * 3. Specify the PIN code of your SIM card if it has one.
+ * 4. Upload the sketch to the connected Arduino board.
+ * 5. Send an SMS to the SIM card number to test the SMS reception.
+ * 6. Check the serial monitor for the received SMS.
+ *
+ * Initial author: Cristian Dragomir
+*/
-// #define TINY_GSM_DEBUG Serial
-// #define ARDUINO_CELLULAR_DEBUG
+#include "ArduinoCellular.h"
constexpr int NEW_SMS_INTERRUPT_PIN = A0;
ArduinoCellular cellular = ArduinoCellular();
volatile boolean smsReceived = false;
+constexpr int POLLING_INTERVAL_MS = 1 * 60 * 1000; // 1 minute
void printMessages(std::vector msg){
for(int i = 0; i < msg.size(); i++){
Serial.println("SMS:");
- Serial.print("\t * From: "); Serial.println(msg[i].number);
- Serial.print("\t * Message: "); Serial.println(msg[i].message);
- Serial.print("\t * Timestamp: "); Serial.println(msg[i].timestamp.getISO8601());
+ Serial.print("* Index: "); Serial.println(msg[i].index);
+ Serial.print("* From: "); Serial.println(msg[i].sender);
+ Serial.print("* Timestamp: "); Serial.println(msg[i].timestamp.getISO8601());
+ Serial.println("* Message: "); Serial.println(msg[i].message);
+ Serial.println("--------------------\n");
}
}
void onSMSReceived(){
- Serial.println("New SMS received!");
smsReceived = true;
}
void setup(){
Serial.begin(115200);
while (!Serial);
- cellular.setDebugStream(Serial);
-
+ // cellular.setDebugStream(Serial); // Uncomment this line to enable debug output
cellular.begin();
- Serial.println("Connecting...");
- cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD, SECRET_PINNUMBER);
+
+ String pinCode = ""; // If your SIM card has a PIN code, specify it here e.g. "1234"
+ if(pinCode.length() > 0 && !cellular.unlockSIM(pinCode)){
+ Serial.println("Failed to unlock SIM card.");
+ while(true); // Stop here
+ }
+ Serial.println("Connecting to network...");
+ cellular.connect();
+ Serial.println("Connected!");
+
+ // Send USSD command for cost control, if supported by the network provider
+ // Some network providers send the response as an SMS message
+ // Some network providers send the response as a USSD response
+ //Serial.println("Sending USSD command...");
+ //Serial.println(cellular.sendUSSDCommand("*123#"));
+
// Register interrupt based callback for new SMS
attachInterrupt(digitalPinToInterrupt(NEW_SMS_INTERRUPT_PIN), onSMSReceived, RISING);
- Serial.println("Read SMS:");
std::vector readSMS = cellular.getReadSMS();
- printMessages(readSMS);
+ if(readSMS.size() > 0){
+ Serial.println("Read SMS:");
+ printMessages(readSMS);
+ }
- Serial.println("Unread SMS:");
std::vector unreadSMS = cellular.getUnreadSMS();
- printMessages(unreadSMS);
+ if(unreadSMS.size() > 0){
+ Serial.println("Unread SMS:");
+ printMessages(unreadSMS);
+ }
}
void loop(){
- if(smsReceived){
+ static unsigned long lastPoll = 0;
+ static bool checkForNewSMS = false;
+
+ if(millis() - lastPoll > POLLING_INTERVAL_MS){
+ checkForNewSMS = true;
+ lastPoll = millis();
+ }
+
+ if(smsReceived || checkForNewSMS){
smsReceived = false;
+ checkForNewSMS = false;
std::vector unreadSMS = cellular.getUnreadSMS();
+
if (unreadSMS.size() > 0){
+ Serial.println("New SMS received!");
printMessages(unreadSMS);
}
}
diff --git a/examples/ReceiveSMS/arduino_secrets.h b/examples/ReceiveSMS/arduino_secrets.h
deleted file mode 100644
index bbcdcc9..0000000
--- a/examples/ReceiveSMS/arduino_secrets.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#define SECRET_PINNUMBER "" // replace with your SIM card PIN
-#define SECRET_GPRS_APN "apn" // replace with your GPRS APN
-#define SECRET_GPRS_LOGIN "login" // replace with your GPRS login
-#define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password
-
-
-#define SECRET_PINNUMBER "1234" // replace with your SIM card PIN
-#define SECRET_GPRS_APN "live.vodafone.com" // replace with your GPRS APN
-#define SECRET_GPRS_LOGIN "live" // replace with your GPRS login
-#define SECRET_GPRS_PASSWORD "" // replace with your GPRS password
diff --git a/examples/SendSMS/SendSMS.ino b/examples/SendSMS/SendSMS.ino
index 563d5b8..f65bd9c 100644
--- a/examples/SendSMS/SendSMS.ino
+++ b/examples/SendSMS/SendSMS.ino
@@ -15,10 +15,6 @@
*/
#include "ArduinoCellular.h"
-const char apn[] = "internet";
-const char gprsUser[] = "";
-const char gprsPass[] = "";
-
ArduinoCellular cellular = ArduinoCellular();
void setup(){
@@ -26,11 +22,18 @@ void setup(){
while (!Serial);
delay(1000); // Give the serial monitor some time to start
+ // cellular.setDebugStream(Serial); // Uncomment this line to enable debug output
cellular.begin();
- String pinCode = "1234"; // If your SIM card has a PIN code, specify it here
+
+ String pinCode = ""; // If your SIM card has a PIN code, specify it here e.g. "1234"
+ if(pinCode.length() > 0 && !cellular.unlockSIM(pinCode)){
+ Serial.println("Failed to unlock SIM card.");
+ while(true); // Stop here
+ }
Serial.println("Connecting to network...");
- cellular.connect(apn, gprsUser, gprsPass, pinCode);
+ cellular.connect(); // APN settings are not required for sending SMS
+ Serial.println("Connected!");
Serial.println("Sending SMS...");
cellular.sendSMS("", "bleep bleep");
diff --git a/examples/TimeAndLocation/TimeAndLocation.ino b/examples/TimeAndLocation/TimeAndLocation.ino
deleted file mode 100644
index 2e2c286..0000000
--- a/examples/TimeAndLocation/TimeAndLocation.ino
+++ /dev/null
@@ -1,36 +0,0 @@
-#define DUMP_AT_COMMANDS
-
-#include "ArduinoCellular.h"
-#include "arduino_secrets.h"
-
-ArduinoCellular cellular = ArduinoCellular();
-
-float lat = 0.00000;
-float lon = 0.00000;
-int year = 0;
-int month = 0;
-int day = 0;
-int hour = 0;
-int minute = 0;
-int second = 0;
-
-
-void setup(){
- Serial.begin(115200);
- while (!Serial);
- cellular.begin();
- //cellular.connect(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD, SECRET_PINNUMBER);
- //cellular.enableGPS(false);
-}
-
-void loop(){
- Location loc = cellular.getGPSLocation(10000);
- Serial.print("Latitude: "); Serial.println(lat);
- Serial.print("Longitude: "); Serial.println(lon);
-
- Time t = cellular.getGPSTime();
- Serial.print("ISO String: "); Serial.println(t.getISO8601());
-
- delay(1000);
-
-}
\ No newline at end of file
diff --git a/examples/TimeAndLocation/arduino_secrets.h b/examples/TimeAndLocation/arduino_secrets.h
deleted file mode 100644
index de218ed..0000000
--- a/examples/TimeAndLocation/arduino_secrets.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#define SECRET_PINNUMBER "" // replace with your SIM card PIN
-#define SECRET_GPRS_APN "apn" // replace with your GPRS APN
-#define SECRET_GPRS_LOGIN "login" // replace with your GPRS login
-#define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password
\ No newline at end of file
diff --git a/extras/connection_img/buck.jpg b/extras/connection_img/buck.jpg
deleted file mode 100644
index 3d6a235..0000000
Binary files a/extras/connection_img/buck.jpg and /dev/null differ
diff --git a/extras/connection_img/header.jpg b/extras/connection_img/header.jpg
deleted file mode 100644
index f6c43c1..0000000
Binary files a/extras/connection_img/header.jpg and /dev/null differ
diff --git a/library.properties b/library.properties
index 138d0c3..17450a8 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=Arduino_Cellular
-version=1.0.0
+version=1.2.1
author=Arduino
maintainer=Arduino
sentence=This library provides a toolkit for interacting with the official Arduino Pro 4G Modules.
@@ -8,4 +8,4 @@ category=Communication
url=https://github.com/arduino-libraries/Arduino_Cellular
depends=ArduinoBearSSL,StreamDebugger,TinyGSM,ArduinoHttpClient
architectures=renesas_portenta, mbed_portenta
-includes=Arduino_Cellular.h
\ No newline at end of file
+includes=Arduino_Cellular.h
diff --git a/src/ArduinoCellular.cpp b/src/ArduinoCellular.cpp
index ad709fc..cf362b6 100644
--- a/src/ArduinoCellular.cpp
+++ b/src/ArduinoCellular.cpp
@@ -1,6 +1,9 @@
#include "ArduinoCellular.h"
+#if defined(ARDUINO_ARCH_MBED)
+ #include "Watchdog.h"
+#endif
unsigned long ArduinoCellular::getTime() {
int year, month, day, hour, minute, second;
@@ -10,19 +13,16 @@ unsigned long ArduinoCellular::getTime() {
}
ArduinoCellular::ArduinoCellular() {
-
}
void ArduinoCellular::begin() {
- // set sim slot
modem.init();
-
String modemInfo = this ->sendATCommand("I");
if(modemInfo.indexOf("EC200A") > 0){
this->model = ModemModel::EC200;
- } else if (modemInfo.indexOf("EG95") > 0){
- this->model = ModemModel::EG95;
+ } else if (modemInfo.indexOf("EG25") > 0){
+ this->model = ModemModel::EG25;
} else {
this->model = ModemModel::Unsupported;
}
@@ -38,43 +38,61 @@ void ArduinoCellular::begin() {
modem.sendAT("+CNMI=2,1,0,0,0");
modem.waitResponse();
-
+#if defined(ARDUINO_CELLULAR_BEARSSL)
ArduinoBearSSL.onGetTime(ArduinoCellular::getTime);
+#endif
}
-bool ArduinoCellular::connect(String apn, String gprsUser, String gprsPass, String pin){
+bool ArduinoCellular::connect(String apn, String username, String password){
SimStatus simStatus = getSimStatus();
- if(simStatus == SimStatus::SIM_LOCKED && pin.length() > 0){
- unlockSIM(pin.c_str());
+
+ if(simStatus == SimStatus::SIM_LOCKED){
+ if(this->debugStream != nullptr){
+ this->debugStream->println("SIM locked, cannot connect to network.");
+ }
+
+ return false;
}
- simStatus = getSimStatus();
- if(simStatus == SimStatus::SIM_READY) {
- if(awaitNetworkRegistration()){
- if(connectToGPRS(apn.c_str(), gprsUser.c_str(), gprsPass.c_str())){
- if(this->debugStream != nullptr){
- this->debugStream->println("Setting DNS...");
- }
-
- auto response = this->sendATCommand("+QIDNSCFG=1,\"8.8.8.8\",\"8.8.4.4\"");
-
- if(this->debugStream != nullptr){
- this->debugStream->println(response);
- }
- return true;
- }
+ if(simStatus != SimStatus::SIM_READY) {
+ if(this->debugStream != nullptr){
+ this->debugStream->println("SIM not ready, cannot connect to network.");
+ }
+ return false;
+ }
+
+ if(!awaitNetworkRegistration()){
+ return false;
+ }
+
+ if(apn.length() == 0){
+ if(this->debugStream != nullptr){
+ this->debugStream->println("No APN specified, not connecting to GPRS");
+ }
+ return true;
+ }
+
+ if(connectToGPRS(apn.c_str(), username.c_str(), password.c_str())){
+ auto response = this->sendATCommand("+QIDNSCFG=1,\"8.8.8.8\",\"8.8.4.4\"");
+
+ if(response.indexOf("OK") != -1){
+ return true;
} else {
+ if(this->debugStream != nullptr){
+ this->debugStream->println("Failed to set DNS.");
+ }
return false;
}
+
}
- return false;
+ return false;
}
-Location ArduinoCellular::getGPSLocation(unsigned long timeout){
- if (model == ModemModel::EG95){
+Geolocation ArduinoCellular::getGPSLocation(unsigned long timeout){
+ if (model == ModemModel::EG25){
float latitude = 0.00000;
float longitude = 0.00000;
unsigned long startTime = millis();
@@ -84,7 +102,7 @@ Location ArduinoCellular::getGPSLocation(unsigned long timeout){
delay(1000);
}
- Location loc;
+ Geolocation loc;
loc.latitude = latitude;
loc.longitude = longitude;
@@ -93,7 +111,7 @@ Location ArduinoCellular::getGPSLocation(unsigned long timeout){
if(this->debugStream != nullptr){
this->debugStream->println("Unsupported modem model");
}
- return Location();
+ return Geolocation();
}
}
@@ -104,14 +122,23 @@ Time ArduinoCellular::getGPSTime(){
}
Time ArduinoCellular::getCellularTime(){
- int year, month, day, hour, minute, second;
+ int year = 1970;
+ int month = 1;
+ int day = 1;
+ int hour = 0;
+ int minute = 0;
+ int second = 0;
float tz;
- modem.getNetworkTime(&year, &month, &day, &hour, &minute, &second, &tz);
+ if (modem.NTPServerSync() == 0) {
+ modem.getNetworkTime(&year, &month, &day, &hour, &minute, &second, &tz);
+ }
return Time(year, month, day, hour, minute, second);
}
void ArduinoCellular::sendSMS(String number, String message){
+ modem.sendAT("+CMGF=1");
+ modem.waitResponse(1000);
modem.sendAT(GF("+CMGS=\""), number, GF("\""));
if (modem.waitResponse(GF(">")) != 1) { }
modem.stream->print(message); // Actually send the message
@@ -141,6 +168,7 @@ HttpClient ArduinoCellular::getHTTPClient(const char * server, const int port){
return HttpClient(* new TinyGsmClient(modem), server, port);
}
+#if defined(ARDUINO_CELLULAR_BEARSSL)
HttpClient ArduinoCellular::getHTTPSClient(const char * server, const int port){
return HttpClient(* new BearSSLClient(* new TinyGsmClient(modem)), server, port);
}
@@ -148,6 +176,7 @@ HttpClient ArduinoCellular::getHTTPSClient(const char * server, const int port){
BearSSLClient ArduinoCellular::getSecureNetworkClient(){
return BearSSLClient(* new TinyGsmClient(modem));
}
+#endif
bool ArduinoCellular::isConnectedToOperator(){
return modem.isNetworkConnected();
@@ -176,36 +205,49 @@ SimStatus ArduinoCellular::getSimStatus(){
this->debugStream->println("SIM Status: " + String(simStatus));
}
- if (modem.getSimStatus() == 0) {
+ if (simStatus == 0) {
return SimStatus::SIM_ERROR;
- } else if (modem.getSimStatus() == 1) {
+ } else if (simStatus == 1) {
return SimStatus::SIM_READY;
- } else if (modem.getSimStatus() == 2) {
+ } else if (simStatus == 2) {
return SimStatus::SIM_LOCKED;
- } else if (modem.getSimStatus() == 3) {
+ } else if (simStatus == 3) {
return SimStatus::SIM_ANTITHEFT_LOCKED;
} else {
return SimStatus::SIM_ERROR;
}
}
-bool ArduinoCellular::unlockSIM(const char * pin){
- if(this->debugStream != nullptr){
- this->debugStream->println("Unlocking SIM...");
+bool ArduinoCellular::unlockSIM(String pin){
+ int simStatus = modem.getSimStatus();
+ if(simStatus == SIM_LOCKED) {
+ if(this->debugStream != nullptr){
+ this->debugStream->println("Unlocking SIM...");
+ }
+ return modem.simUnlock(pin.c_str());
}
- return modem.simUnlock(pin);
+ else if(simStatus == SIM_ERROR || simStatus == SIM_ANTITHEFT_LOCKED) {
+ return false;
+ }
+ /* SIM is ready */
+ return true;
}
bool ArduinoCellular::awaitNetworkRegistration(){
if(this->debugStream != nullptr){
this->debugStream->println("Waiting for network registration...");
}
- while (!modem.waitForNetwork()) {
+ while (!modem.waitForNetwork(waitForNetworkTimeout)) {
if(this->debugStream != nullptr){
this->debugStream->print(".");
}
+ #if defined(ARDUINO_ARCH_MBED)
+ if(mbed::Watchdog::get_instance().is_running()) {
+ mbed::Watchdog::get_instance().kick();
+ }
+ #endif
delay(2000);
- }
+ }
return true;
}
@@ -214,31 +256,33 @@ bool ArduinoCellular::enableGPS(bool assisted){
this->debugStream->println("Enabling GPS...");
}
+ String response;
+
if(assisted){
- sendATCommand("AT+QGPSCFG=\"agpsposmode\",33488767");
+ response = sendATCommand("+QGPSCFG=\"agpsposmode\",33488767", 10000);
} else {
- sendATCommand("AT+QGPSCFG=\"agpsposmode\",8388608");
+ // Sets the 23rd bit to 1 to enable standalone GPS
+ response = sendATCommand("+QGPSCFG=\"agpsposmode\",8388608", 10000);
}
- //modem.sendAT(GF("+UTIME=1,1"));
- //modem.waitResponse();
- //modem.sendAT(GF("+UGPIOC=23,0,1"));
-
- //modem.waitResponse();
+ if(response.indexOf("OK") == -1){
+ if(this->debugStream != nullptr){
+ this->debugStream->println("Failed to set GPS mode.");
+ this->debugStream->println("Response: " + response);
+ }
+ return false;
+ }
return modem.enableGPS();
- //delay(10000);
}
-String ArduinoCellular::sendATCommand( char * command, unsigned long timeout){
- String resp;
- modem.sendAT(const_cast(command));
- modem.waitResponse(timeout, resp);
- return resp;
+String ArduinoCellular::sendATCommand(const char * command, unsigned long timeout){
+ String response;
+ modem.sendAT(command);
+ modem.waitResponse(timeout, response);
+ return response;
}
-
-
Time parseTimestamp(const String ×tampStr) {
int hour, minute, second, day, month, year, offset;
@@ -249,9 +293,9 @@ Time parseTimestamp(const String ×tampStr) {
int firstSlashIndex = date.indexOf('/');
int secondSlashIndex = date.lastIndexOf('/');
- day = date.substring(0, firstSlashIndex).toInt();
+ year = date.substring(0, firstSlashIndex).toInt() + 2000;
month = date.substring(firstSlashIndex + 1, secondSlashIndex).toInt();
- year = date.substring(secondSlashIndex + 1).toInt() + 2000;
+ day = date.substring(secondSlashIndex + 1).toInt();
int firstColonIndex = time.indexOf(':');
int secondColonIndex = time.lastIndexOf(':');
@@ -263,6 +307,7 @@ Time parseTimestamp(const String ×tampStr) {
return Time(year, month, day, hour, minute, second, offset);
}
+
// Parses a single SMS entry from the data
SMS parseSMSEntry(const String& entry, const String& message) {
SMS sms;
@@ -272,8 +317,12 @@ SMS parseSMSEntry(const String& entry, const String& message) {
int fourthQuoteIndex = entry.indexOf('"', thirdQuoteIndex + 1);
int commaIndexBeforeTimestamp = entry.lastIndexOf(',', entry.lastIndexOf(',') - 1);
+ String command = "+CMGL: ";
+ // Index is between "+CMGL: " and first "," symbol
+ sms.index = entry.substring(entry.indexOf(command) + command.length(), entry.indexOf(',')).toInt();
+
// Extracting number and raw timestamp
- sms.number = entry.substring(thirdQuoteIndex + 1, fourthQuoteIndex);
+ sms.sender = entry.substring(thirdQuoteIndex + 1, fourthQuoteIndex);
String rawTimestamp = entry.substring(commaIndexBeforeTimestamp + 2, entry.indexOf('+', commaIndexBeforeTimestamp) + 3);
// Parse the timestamp
@@ -293,13 +342,11 @@ std::vector splitStringByLines(const String& input, char delimiter = '\n
if (endIndex == -1)
endIndex = input.length();
String line = input.substring(startIndex, endIndex);
- if(line.length() > 0 && line != "\r" && line != "\n" && line != "\r\n"){
- // Remove trailing \r if it exists
- if (line.endsWith("\r")) {
- line.remove(line.length() - 1);
- }
- lines.push_back(line);
+ // Remove trailing \r if it exists
+ if (line.endsWith("\r")) {
+ line.remove(line.length() - 1);
}
+ lines.push_back(line);
startIndex = endIndex + 1;
}
return lines;
@@ -309,19 +356,33 @@ std::vector splitStringByLines(const String& input, char delimiter = '\n
std::vector parseSMSData(const String& data) {
std::vector smsList = std::vector();
std::vector lines = splitStringByLines(data);
-
- // Remove last line if it's "OK"
- if (lines.size() > 0 && lines[lines.size() - 1] == "OK") {
- lines.pop_back();
+
+ // Remove first line if it's empty
+ if (lines.size() > 0 && lines[0] == "") {
+ lines.erase(lines.begin());
}
- for(int i = 0; i < lines.size(); i += 2){
+ // Remove last 2 lines if second to last line is "OK"
+ if (lines.size() >= 2 && lines.back() == "OK") {
+ lines.erase(lines.end() - 2, lines.end());
+ }
+
+ for(int i = 0; i < lines.size(); i ++){
if (lines[i].startsWith("+CMGL:")) {
+ String entry = lines[i];
String message = "";
- if(i + 1 < lines.size()){
- message = lines[i + 1];
+ // Loop through the lines until the next +CMGL line and extract the message by concatenating the lines
+ for (int j = i + 1; j < lines.size(); j++) {
+ if (lines[j].startsWith("+CMGL:")) {
+ i = j - 1;
+ break;
+ }
+ message += lines[j] + "\n";
}
- SMS sms = parseSMSEntry(lines[i], message);
+ // Remove the trailing newline character from the message
+ message.remove(message.length() - 1);
+
+ SMS sms = parseSMSEntry(entry, message);
smsList.push_back(sms);
}
}
@@ -329,6 +390,10 @@ std::vector parseSMSData(const String& data) {
return smsList;
}
+String ArduinoCellular::sendUSSDCommand(const char * command){
+ return modem.sendUSSD(command);
+}
+
std::vector ArduinoCellular::getReadSMS(){
String rawMessages = sendATCommand("+CMGL=\"REC READ\"");
if(rawMessages.indexOf("OK") == -1){
@@ -351,6 +416,12 @@ std::vector ArduinoCellular::getUnreadSMS(){
}
}
+bool ArduinoCellular::deleteSMS(uint16_t index){
+ String command = "+CMGD=" + String(index);
+ String response = sendATCommand(const_cast(command.c_str()));
+ return response.indexOf("OK") != -1;
+}
+
void ArduinoCellular::setDebugStream(Stream &stream){
this->debugStream = &stream;
}
diff --git a/src/ArduinoCellular.h b/src/ArduinoCellular.h
index e6ab0a6..a04707e 100644
--- a/src/ArduinoCellular.h
+++ b/src/ArduinoCellular.h
@@ -16,8 +16,18 @@
#include
#include
-#include "ArduinoBearSSLConfig.h"
-#include
+
+#if defined __has_include
+ #if !__has_include ()
+ #define ARDUINO_CELLULAR_BEARSSL
+ #endif
+#endif
+
+#if defined(ARDUINO_CELLULAR_BEARSSL)
+ #include "ArduinoBearSSLConfig.h"
+ #include
+#endif
+
#include
#include
@@ -27,7 +37,7 @@
*/
enum ModemModel {
EC200, /**< Quectel EC200 modem. */
- EG95, /**< Quectel EG95 modem. */
+ EG25, /**< Quectel EG25 modem. */
Unsupported /**< Unsupported modem model. */
};
@@ -36,7 +46,8 @@ enum ModemModel {
*/
class SMS {
public:
- String number; /**< The phone number associated with the SMS. */
+ int16_t index; /**< The index of the SMS message. */
+ String sender; /**< The phone number associated with the SMS. */
String message; /**< The content of the SMS message. */
Time timestamp; /**< The timestamp when the SMS was received. */
@@ -45,19 +56,22 @@ class SMS {
* Initializes the number, message, and timestamp to empty values.
*/
SMS() {
- this->number = "";
+ this->index = -1;
+ this->sender = "";
this->message = "";
this->timestamp = Time();
}
/**
* Constructor for SMS.
- * @param number The phone number associated with the SMS.
+ * @param index The index of the SMS message.
+ * @param sender The phone number associated with the sender of the SMS.
* @param message The content of the SMS message.
* @param timestamp The timestamp when the SMS was received.
*/
- SMS(String number, String message, Time timestamp) {
- this->number = number;
+ SMS(int16_t index, String sender, String message, Time timestamp) {
+ this->index = index;
+ this->sender = sender;
this->message = message;
this->timestamp = timestamp;
}
@@ -65,10 +79,10 @@ class SMS {
/**
- * @struct Location
+ * @struct Geolocation
* @brief Represents a geographic location with latitude and longitude coordinates.
*/
-struct Location {
+struct Geolocation {
float latitude; /**< The latitude coordinate of the location. */
float longitude; /**< The longitude coordinate of the location. */
};
@@ -82,24 +96,32 @@ struct Location {
class ArduinoCellular {
public:
/**
- * @brief Default constructor.
+ * @brief Creates an instance of the ArduinoCellular class.
*/
ArduinoCellular();
/**
* @brief Initializes the modem.
+ * This function must be called before using any other functions in the library.
*/
void begin();
/**
- * @brief Connects to the network using the specified APN, GPRS username, and GPRS password.
- * @param apn The Access Point Name.
- * @param gprsUser The GPRS username.
- * @param gprsPass The GPRS password.
+ * @brief Unlocks the SIM card using the specified PIN.
* @param pin The SIM card PIN.
+ * @return True if the SIM card is unlocked, false otherwise.
+ */
+ bool unlockSIM(String pin);
+
+ /**
+ * @brief Registers with the cellular network and connects to the Internet
+ * if the APN, GPRS username, and GPRS password are provided.
+ * @param apn The Access Point Name.
+ * @param username The APN username.
+ * @param password The APN password.
* @return True if the connection is successful, false otherwise.
*/
- bool connect(String apn, String gprsUser, String gprsPass, String pin = "");
+ bool connect(String apn = "", String username = "", String password = "");
/**
* @brief Checks if the modem is registered on the network.
@@ -114,9 +136,9 @@ class ArduinoCellular {
bool isConnectedToInternet();
/**
- * @brief Enables or disables the GPS module.
+ * @brief Enables or disables the GPS functionality.
* @param assisted True to enable assisted GPS, false to disable it. Assist GPS uses the network to get the GPS location faster, so cellular needs to be enabled.
- * @return True if the GPS module is enabled, false otherwise.
+ * @return True if GPS was enabled successfully, false otherwise.
*/
bool enableGPS(bool assisted = false);
@@ -125,15 +147,8 @@ class ArduinoCellular {
* @param timeout The timeout (In milliseconds) to wait for the GPS location.
* @return The GPS location. If the location is not retrieved, the latitude and longitude will be 0.0.
*/
- Location getGPSLocation(unsigned long timeout = 60000);
+ Geolocation getGPSLocation(unsigned long timeout = 60000);
- /**
- * @brief Gets the cellular location. (Blocking call)
- * @param timeout The timeout (In milliseconds) to wait for the cellular location.
- * @return The cellular location. If the location is not retrieved, the latitude and longitude will be 0.0.
- */
- Location getCellularLocation(unsigned long timeout = 10000);
-
/**
* @brief Gets the current time from the network.
* @return The current time.
@@ -165,13 +180,31 @@ class ArduinoCellular {
*/
std::vector getUnreadSMS();
+ /**
+ * @brief Deletes an SMS message at the specified index.
+ *
+ * @param index The index of the SMS message to delete.
+ * @return True if the SMS message was successfully deleted, false otherwise.
+ */
+ bool deleteSMS(uint16_t index);
+
/**
* @brief Sends an AT command to the modem and waits for a response, then returns the response.
* @param command The AT command to send.
- * @param timeout The timeout (In milliseconds) to wait for the response.
+ * @param timeout The timeout (In milliseconds) to wait for the response. Default is 1000ms.
* @return The response from the modem.
*/
- String sendATCommand(char * command, unsigned long timeout = 1000);
+ String sendATCommand(const char * command, unsigned long timeout = 1000);
+
+
+
+ /**
+ * @brief Sends a USSD command to the network operator and waits for a response.
+ * @param command The USSD command to send.
+ * @return The response from the network operator. (Note: The response may be an SMS message or a USSD response)
+ */
+ String sendUSSDCommand(const char * command);
+
/**
@@ -184,7 +217,9 @@ class ArduinoCellular {
* @brief Gets the Transport Layer Security (TLS) client. (OSI Layer 4)
* @return The GSM client.
*/
+#if defined(ARDUINO_CELLULAR_BEARSSL)
BearSSLClient getSecureNetworkClient();
+#endif
/**
* @brief Gets the HTTP client for the specified server and port.
@@ -233,13 +268,6 @@ class ArduinoCellular {
*/
SimStatus getSimStatus();
- /**
- * @brief Unlocks the SIM card using the specified PIN.
- * @param pin The SIM card PIN.
- * @return True if the SIM card is unlocked, false otherwise.
- */
- bool unlockSIM(const char * pin);
-
/**
* @brief Waits for network registration. (Blocking call)
* @return True if the network registration is successful, false otherwise.
@@ -262,6 +290,8 @@ class ArduinoCellular {
Stream* debugStream = nullptr; /**< The stream to be used for printing debugging messages. */
static unsigned long getTime(); /** Callback for getting the current time as an unix timestamp. */
+
+ static constexpr unsigned long waitForNetworkTimeout = 20000L; /**< Maximum wait time for network registration (In milliseconds). */
};
diff --git a/src/ModemInterface.cpp b/src/ModemInterface.cpp
index c1b8048..a8777a0 100644
--- a/src/ModemInterface.cpp
+++ b/src/ModemInterface.cpp
@@ -4,32 +4,32 @@
#include
-
#if defined(ARDUINO_PORTENTA_C33)
+ // On the C33 the Serial1 object is already defined, but it does not have hardware flow control
+ // mbed allows us to define a UART object with software flow control on given pins
// P602/P110/P603/P604 -> Serial1
- UART Serial1_FC(UART1_TX_PIN, UART1_RX_PIN, 61, 62);
+ UART Serial1_FC(UART1_TX_PIN, UART1_RX_PIN, PORTENTA_C33_CTS_PIN, PORTENTA_C33_RTS_PIN);
#ifdef DUMP_AT_COMMANDS
StreamDebugger debugger(Serial1_FC, Serial);
- __attribute__ ((init_priority (101))) ModemInterface modem(debugger, 32);
+
+ // we need to make sure that the Modem object is initialised before anything else in the sketch to avoid issues with the TinyGSM library
+ // the init_priority attribute is used to set the priority of the constructor, the lower the number the higher the priority (101 to 65535)
+ // for more information see https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
+ __attribute__ ((init_priority (101))) ModemInterface modem(debugger, PORTENTA_C33_MODEM_ON_PIN);
#else
- __attribute__ ((init_priority (101))) ModemInterface modem(Serial1_FC, 32);
+ __attribute__ ((init_priority (101))) ModemInterface modem(Serial1_FC, PORTENTA_C33_MODEM_ON_PIN);
#endif
-// P708 (32) is the ON pin
#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(CORE_CM4)
-#include "pinDefinitions.h"
-
+ #include "pinDefinitions.h"
-// P602/P110/P603/P604 -> Serial1
+ // P602/P110/P603/P604 -> Serial1
#ifdef DUMP_AT_COMMANDS
StreamDebugger debugger(Serial1, Serial);
- __attribute__ ((init_priority (101))) ModemInterface modem(debugger, PinNameToIndex(PG_3));
+ __attribute__ ((init_priority (101))) ModemInterface modem(debugger, PinNameToIndex(PORTENTA_H7_MODEM_ON_PIN));
#else
- __attribute__ ((init_priority (101))) ModemInterface modem(Serial1, PinNameToIndex(PG_3));
+ __attribute__ ((init_priority (101))) ModemInterface modem(Serial1, PinNameToIndex(PORTENTA_H7_MODEM_ON_PIN));
#endif
-
-
-// PG3 () is the ON pin
#endif
diff --git a/src/ModemInterface.h b/src/ModemInterface.h
index c04f1f4..14086a6 100644
--- a/src/ModemInterface.h
+++ b/src/ModemInterface.h
@@ -11,6 +11,14 @@
#define TINY_GSM_RX_BUFFER 1024
#define TINY_GSM_MODEM_BG96
+#if defined(ARDUINO_PORTENTA_H7_M7) || defined(CORE_CM4)
+ #define PORTENTA_H7_MODEM_ON_PIN PG_3 // PG3 is the ON pin
+#elif defined(ARDUINO_PORTENTA_C33)
+ #define PORTENTA_C33_CTS_PIN 61
+ #define PORTENTA_C33_RTS_PIN 62
+ #define PORTENTA_C33_MODEM_ON_PIN 32
+#endif
+
#include
#include
@@ -19,30 +27,34 @@
/**
* @class ModemInterface
- * @brief Represents the interface to the 4G modem module.
+ * @brief Represents the interface to the 4G modem module which extends the TinyGsmBG96 class.
*/
class ModemInterface : public TinyGsmBG96 {
public:
/**
* @brief Constructor for the ModemInterface class.
* @param stream The stream object for communication with the modem.
- * @param power_pin The pin number for controlling the power of the modem.
+ * @param powerPin The pin number for controlling the power of the modem.
*/
- explicit ModemInterface(Stream& stream, int power_pin) : TinyGsmBG96(stream),stream(&stream),power_pin(power_pin) {
+ explicit ModemInterface(Stream& stream, int powerPin) : TinyGsmBG96(stream),stream(&stream),powerPin(powerPin) {
};
/**
- * @brief Initializes the modem interface.
+ * @brief Initializes the modem interface. (Overrides the init method in TinyGsmBG96)
* @param pin The PIN code for the SIM card (optional).
* @return True if initialization is successful, false otherwise.
*/
bool init(const char* pin = NULL) {
- pinMode(power_pin, OUTPUT);
- digitalWrite(power_pin, HIGH);
+ // Power on the modem
+ pinMode(powerPin, OUTPUT);
+ digitalWrite(powerPin, HIGH);
delay(1000);
+
#ifdef DUMP_AT_COMMANDS
#if defined(ARDUINO_PORTENTA_C33)
+ // On the C33 we have defined a UART object with software flow control on given pins in the .cpp file, we'll use extern to access and begin communication
+
extern UART Serial1_FC;
Serial1_FC.begin(115200);
#endif
@@ -54,7 +66,7 @@ class ModemInterface : public TinyGsmBG96 {
public:
Stream* stream; /**< The stream object for communication with the modem. */
- int power_pin; /**< The pin number for controlling the power of the modem. */
+ int powerPin; /**< The pin number for controlling the power of the modem. */
};
/**