diff --git a/README.md b/README.md index 4ae56db..7ba1de4 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ - [Enabling debug output](#enabling-debug-output) - [Modem features](#modem-features) - [Initialization and status](#initialization-and-status) + - [Power management](#power-management) - [GPS management](#gps-management) - [Network management](#network-management) - [NTP time synchronization](#ntp-time-synchronization) @@ -406,6 +407,33 @@ void loop() { } ``` +### Power management + +```cpp +#include "SIM7600Modem.h" +using namespace SIM7600; +Modem modem(&Serial1); // Use Serial1 for communication + +void setup() { + // ... Initialize modem as shown in the previous example + + // Reset the modem (requires re-initialization after power on) + Status status = modem.reset(); + if (status != Status::Success) { + // Handle error + } + + // Power off the modem (requires re-initialization after power on) + status = modem.powerOff(); + if (status != Status::Success) { + // Handle error + } + + // If you have a SIM7600 with power control pin, turn it off as well + digitalWrite(7, LOW); +} +``` + ### GPS management ```cpp @@ -580,6 +608,9 @@ and MQTT. You need to define your callback functions with the appropriate signat using namespace SIM7600; Modem modem(&Serial1); // Use Serial1 for communication +// Modem ready event callback +void modemReadyCB() { Serial.println("Event: Modem is ready!"); } + // Network changed event callback void networkChangedCB(const bool registered, const RegStatus reg_status) { Serial.printf("Event: Network changed! Registered: %s, Status: %u\r\n", @@ -598,6 +629,9 @@ void mqttNetworkClosedCB() { Serial.println("Event: MQTT network connection clos void setup() { // ... Initialize modem as shown in the previous example + // Set modem ready event callback + modem.setModemReadyCallback(modemReadyCB); + // Set network changed event callback modem.setNetworkChangedCallback(networkChangedCB); diff --git a/examples/ModemTest/ModemTest.ino b/examples/ModemTest/ModemTest.ino index 09dd253..da84a5a 100644 --- a/examples/ModemTest/ModemTest.ino +++ b/examples/ModemTest/ModemTest.ino @@ -50,6 +50,8 @@ void handleSerial(); /* Callback functions definitions */ // Modem +void modemReadyCB() { Serial.println("Event: Modem is ready!"); } + void networkChangedCB(const bool registered, const SIM7600::RegStatus reg_status) { Serial.printf("Event: Network changed! Registered: %s, Status: %u\r\n", registered ? "Yes" : "No", @@ -131,6 +133,7 @@ void setup() { digitalWrite(GSM_GPIO_ENABLE, HIGH); // Modem callbacks + modem.setModemReadyCallback(modemReadyCB); modem.setNetworkChangedCallback(networkChangedCB); modem.setTCPNetworkClosedCallback(tcpNetworkClosedCB); modem.setMQTTNetworkClosedCallback(mqttNetworkClosedCB); @@ -187,12 +190,46 @@ void handleSerial() { SIM7600::Status status; switch (c) { + // ESP32 and modem control case '|': { Serial.println("Restarting ESP32..."); ESP.restart(); } break; + case '/': + { + status = modem.init(); + + if (status == SIM7600::Status::Success) { + Serial.println("Modem initialized successfully!"); + } else { + Serial.printf("Modem initialization failed: %s\r\n", SIM7600::statusToString(status)); + } + } break; + + case '*': + { + status = modem.reset(); + + if (status == SIM7600::Status::Success) { + Serial.println("Modem reset successfully"); + } else { + Serial.printf("Modem reset failed: %s\r\n", SIM7600::statusToString(status)); + } + } break; + + case '-': + { + status = modem.powerOff(); + + if (status == SIM7600::Status::Success) { + Serial.println("Modem powered off successfully"); + } else { + Serial.printf("Modem power off failed: %s\r\n", SIM7600::statusToString(status)); + } + } break; + // Modem tests case '1': { diff --git a/src/SIM7600Modem.cpp b/src/SIM7600Modem.cpp index defb65d..077c5a0 100644 --- a/src/SIM7600Modem.cpp +++ b/src/SIM7600Modem.cpp @@ -13,6 +13,7 @@ namespace SIM7600 { Modem::Modem() : _serial(nullptr) + , _cb_modem_ready(nullptr) , _cb_network_changed(nullptr) , _cb_tcp_network_closed(nullptr) , _cb_mqtt_network_closed(nullptr) @@ -26,6 +27,7 @@ Modem::Modem() Modem::Modem(Stream* serial) : _serial(serial) + , _cb_modem_ready(nullptr) , _cb_network_changed(nullptr) , _cb_tcp_network_closed(nullptr) , _cb_mqtt_network_closed(nullptr) @@ -39,6 +41,12 @@ Modem::Modem(Stream* serial) void Modem::setSerialPort(Stream* serial) { _serial = serial; } +Status Modem::setModemReadyCallback(ModemReadyCB callback) { + if (callback == nullptr) return Status::InvalidCallback; + _cb_modem_ready = callback; + return Status::Success; +} + Status Modem::setNetworkChangedCallback(NetworkChangedCB callback) { if (callback == nullptr) return Status::InvalidCallback; _cb_network_changed = callback; @@ -124,6 +132,20 @@ Status Modem::init(const char* pin, const uint32_t timeout_ms) { return Status::Success; } +Status Modem::powerOff() { + SIM7600_LOGI(tag, "Powering off SIM7600 modem"); + + // Send power off command + return sendATCmdAndWaitResp("AT+CPOF", AT_OK); +} + +Status Modem::reset() { + SIM7600_LOGI(tag, "Resetting SIM7600 modem"); + + // Send reset command + return sendATCmdAndWaitResp("AT+CRESET", AT_OK); +} + Status Modem::sendATCmd(const char* cmd_format, ...) { va_list args; va_start(args, cmd_format); @@ -1228,6 +1250,9 @@ bool Modem::_handleURCs() { // Modem ready if (strcmp(_rx_buf, "RDY") == 0) { SIM7600_LOGD(tag, "URC: Modem is ready"); + + if (_cb_modem_ready != nullptr) _cb_modem_ready(); + return true; } diff --git a/src/SIM7600Modem.h b/src/SIM7600Modem.h index 177fa6c..22165d0 100644 --- a/src/SIM7600Modem.h +++ b/src/SIM7600Modem.h @@ -104,10 +104,12 @@ class Modem { public: // Callback function types. Use std::function if available. #if SIM7600_HAS_STD_FUNCTION + using ModemReadyCB = std::function; using NetworkChangedCB = std::function; using TCPNetworkClosedCB = std::function; using MQTTNetworkClosedCB = std::function; #else + using ModemReadyCB = void (*)(); using NetworkChangedCB = void (*)(const bool registered, const RegStatus status); using TCPNetworkClosedCB = void (*)(); using MQTTNetworkClosedCB = void (*)(); @@ -131,6 +133,13 @@ class Modem { */ void setSerialPort(Stream* serial); + /** + * @brief Set the modem ready callback. + * @param callback Callback function when the modem delivers ready status ("RDY" URC). + * @return Status::Success on success, error code otherwise. + */ + Status setModemReadyCallback(ModemReadyCB callback); + /** * @brief Set the network changed callback. * @param callback Callback function to be called when the network registration status changes. @@ -163,6 +172,20 @@ class Modem { Status init(const char* pin = nullptr, uint32_t timeout_ms = SIM7600_MODEM_DEFAULT_INIT_TIMEOUT_MS); + /** + * @brief Reset the modem. The modem losses its configuration and needs to be re-initialized + * with init() in the next power on. + * @return Status::Success on success, error code otherwise. + */ + Status reset(); + + /** + * @brief Power off the modem. The modem losses its configuration and needs to be re-initialized + * with init() in the next power on. + * @return Status::Success on success, error code otherwise. + */ + Status powerOff(); + /** * @brief Send an AT command to the modem. * @param cmd_format Format string for the AT command. @@ -505,6 +528,7 @@ class Modem { private: Stream* _serial; + ModemReadyCB _cb_modem_ready; NetworkChangedCB _cb_network_changed; TCPNetworkClosedCB _cb_tcp_network_closed; MQTTNetworkClosedCB _cb_mqtt_network_closed;