├── .codespellrc ├── .github ├── dependabot.yml └── workflows │ ├── check-arduino.yml │ ├── compile-examples.yml │ ├── report-size-deltas.yml │ ├── spell-check.yml │ └── sync-labels.yml ├── CHANGELOG ├── LICENSE.txt ├── README.adoc ├── docs ├── api.md └── readme.md ├── examples ├── GPRSPing │ ├── GPRSPing.ino │ └── arduino_secrets.h ├── GPRSUdpNtpClient │ ├── GPRSUdpNtpClient.ino │ └── arduino_secrets.h ├── GsmLocation │ ├── GsmLocation.ino │ └── arduino_secrets.h ├── GsmSSLWebClient │ ├── GsmSSLWebClient.ino │ └── arduino_secrets.h ├── GsmWebClient │ ├── GsmWebClient.ino │ └── arduino_secrets.h ├── GsmWebServer │ ├── GsmWebServer.ino │ └── arduino_secrets.h ├── MakeVoiceCall │ ├── MakeVoiceCall.ino │ └── arduino_secrets.h ├── ReceiveSMS │ ├── ReceiveSMS.ino │ └── arduino_secrets.h ├── ReceiveVoiceCall │ ├── ReceiveVoiceCall.ino │ └── arduino_secrets.h ├── SSLCertificateManagement │ ├── SSLCertificateManagement.ino │ └── arduino_secrets.h ├── SendSMS │ ├── SendSMS.ino │ └── arduino_secrets.h └── Tools │ ├── BandManagement │ └── BandManagement.ino │ ├── ChooseRadioAccessTechnology │ └── ChooseRadioAccessTechnology.ino │ ├── FileUtilsHttpDownload │ ├── FileUtilsHttpDownload.ino │ ├── Helpers.h │ └── arduino_secrets.h │ ├── FileUtilsJsonFile │ ├── Config.h │ └── FileUtilsJsonFile.ino │ ├── FileUtilsReadBlock │ └── FileUtilsReadBlock.ino │ ├── GsmScanNetworks │ ├── GsmScanNetworks.ino │ └── arduino_secrets.h │ ├── HttpUtilsGet │ ├── HttpUtilsGet.ino │ └── arduino_secrets.h │ ├── HttpUtilsSSLGet │ ├── HttpUtilsSSLGet.ino │ └── arduino_secrets.h │ ├── PinManagement │ └── PinManagement.ino │ ├── SerialGSMPassthrough │ └── SerialGSMPassthrough.ino │ ├── TestGPRS │ ├── TestGPRS.ino │ └── arduino_secrets.h │ ├── TestModem │ └── TestModem.ino │ └── TestWebServer │ ├── TestWebServer.ino │ └── arduino_secrets.h ├── keywords.txt ├── library.properties └── src ├── GPRS.cpp ├── GPRS.h ├── GSM.cpp ├── GSM.h ├── GSMBand.cpp ├── GSMBand.h ├── GSMClient.cpp ├── GSMClient.h ├── GSMFileUtils.cpp ├── GSMFileUtils.h ├── GSMHttpUtils.cpp ├── GSMHttpUtils.h ├── GSMLocation.cpp ├── GSMLocation.h ├── GSMModem.cpp ├── GSMModem.h ├── GSMPIN.cpp ├── GSMPIN.h ├── GSMSSLClient.cpp ├── GSMSSLClient.h ├── GSMScanner.cpp ├── GSMScanner.h ├── GSMServer.cpp ├── GSMServer.h ├── GSMUdp.cpp ├── GSMUdp.h ├── GSMVoiceCall.cpp ├── GSMVoiceCall.h ├── GSM_SMS.cpp ├── GSM_SMS.h ├── MKRGSM.h ├── Modem.cpp ├── Modem.h └── utility ├── GSMRootCerts.h ├── GSMSocketBuffer.cpp └── GSMSocketBuffer.h /.codespellrc: -------------------------------------------------------------------------------- 1 | # See: https://github.com/codespell-project/codespell#using-a-config-file 2 | [codespell] 3 | # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: 4 | ignore-words-list = , 5 | check-filenames = 6 | check-hidden = 7 | skip = ./.git 8 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#about-the-dependabotyml-file 2 | version: 2 3 | 4 | updates: 5 | # Configure check for outdated GitHub Actions actions in workflows. 6 | # See: https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot 7 | - package-ecosystem: github-actions 8 | directory: / # Check the repository's workflows under /.github/workflows/ 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /.github/workflows/check-arduino.yml: -------------------------------------------------------------------------------- 1 | name: Check Arduino 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | pull_request: 7 | schedule: 8 | # Run every Tuesday at 8 AM UTC to catch breakage caused by new rules added to Arduino Lint. 9 | - cron: "0 8 * * TUE" 10 | workflow_dispatch: 11 | repository_dispatch: 12 | 13 | jobs: 14 | lint: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v4 20 | 21 | - name: Arduino Lint 22 | uses: arduino/arduino-lint-action@v2 23 | with: 24 | compliance: specification 25 | library-manager: update 26 | # Always use this setting for official repositories. Remove for 3rd party projects. 27 | official: true 28 | project-type: library 29 | -------------------------------------------------------------------------------- /.github/workflows/compile-examples.yml: -------------------------------------------------------------------------------- 1 | name: Compile Examples 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | paths: 7 | - ".github/workflows/compile-examples.yml" 8 | - "examples/**" 9 | - "src/**" 10 | pull_request: 11 | paths: 12 | - ".github/workflows/compile-examples.yml" 13 | - "examples/**" 14 | - "src/**" 15 | schedule: 16 | # Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms). 17 | - cron: "0 8 * * TUE" 18 | workflow_dispatch: 19 | repository_dispatch: 20 | 21 | jobs: 22 | build: 23 | name: ${{ matrix.board.fqbn }} 24 | runs-on: ubuntu-latest 25 | 26 | env: 27 | SKETCHES_REPORTS_PATH: sketches-reports 28 | 29 | strategy: 30 | fail-fast: false 31 | 32 | matrix: 33 | board: 34 | - fqbn: arduino:samd:mkrgsm1400 35 | platforms: | 36 | - name: arduino:samd 37 | artifact-name-suffix: arduino-samd-mkrgsm1400 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | - name: Compile examples 44 | uses: arduino/compile-sketches@v1 45 | with: 46 | github-token: ${{ secrets.GITHUB_TOKEN }} 47 | fqbn: ${{ matrix.board.fqbn }} 48 | platforms: ${{ matrix.board.platforms }} 49 | libraries: | 50 | # Install the library from the local path. 51 | - source-path: ./ 52 | - name: Arduino_JSON 53 | - name: ArduinoMqttClient 54 | sketch-paths: | 55 | - examples 56 | enable-deltas-report: true 57 | sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} 58 | 59 | - name: Save sketches report as workflow artifact 60 | uses: actions/upload-artifact@v4 61 | with: 62 | if-no-files-found: error 63 | path: ${{ env.SKETCHES_REPORTS_PATH }} 64 | name: sketches-report-${{ matrix.board.artifact-name-suffix }} 65 | -------------------------------------------------------------------------------- /.github/workflows/report-size-deltas.yml: -------------------------------------------------------------------------------- 1 | name: Report Size Deltas 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | paths: 7 | - ".github/workflows/report-size-deltas.yml" 8 | schedule: 9 | # Run at the minimum interval allowed by GitHub Actions. 10 | # Note: GitHub Actions periodically has outages which result in workflow failures. 11 | # In this event, the workflows will start passing again once the service recovers. 12 | - cron: "*/5 * * * *" 13 | workflow_dispatch: 14 | repository_dispatch: 15 | 16 | jobs: 17 | report: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Comment size deltas reports to PRs 21 | uses: arduino/report-size-deltas@v1 22 | with: 23 | # Regex matching the names of the workflow artifacts created by the "Compile Examples" workflow 24 | sketches-reports-source: ^sketches-report-.+ 25 | -------------------------------------------------------------------------------- /.github/workflows/spell-check.yml: -------------------------------------------------------------------------------- 1 | name: Spell Check 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | pull_request: 7 | schedule: 8 | # Run every Tuesday at 8 AM UTC to catch new misspelling detections resulting from dictionary updates. 9 | - cron: "0 8 * * TUE" 10 | workflow_dispatch: 11 | repository_dispatch: 12 | 13 | jobs: 14 | spellcheck: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v4 20 | 21 | - name: Spell check 22 | uses: codespell-project/actions-codespell@master 23 | -------------------------------------------------------------------------------- /.github/workflows/sync-labels.yml: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md 2 | name: Sync Labels 3 | 4 | # See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows 5 | on: 6 | push: 7 | paths: 8 | - ".github/workflows/sync-labels.ya?ml" 9 | - ".github/label-configuration-files/*.ya?ml" 10 | pull_request: 11 | paths: 12 | - ".github/workflows/sync-labels.ya?ml" 13 | - ".github/label-configuration-files/*.ya?ml" 14 | schedule: 15 | # Run daily at 8 AM UTC to sync with changes to shared label configurations. 16 | - cron: "0 8 * * *" 17 | workflow_dispatch: 18 | repository_dispatch: 19 | 20 | env: 21 | CONFIGURATIONS_FOLDER: .github/label-configuration-files 22 | CONFIGURATIONS_ARTIFACT: label-configuration-files 23 | 24 | jobs: 25 | check: 26 | runs-on: ubuntu-latest 27 | 28 | steps: 29 | - name: Checkout repository 30 | uses: actions/checkout@v4 31 | 32 | - name: Download JSON schema for labels configuration file 33 | id: download-schema 34 | uses: carlosperate/download-file-action@v2 35 | with: 36 | file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json 37 | location: ${{ runner.temp }}/label-configuration-schema 38 | 39 | - name: Install JSON schema validator 40 | run: | 41 | sudo npm install \ 42 | --global \ 43 | ajv-cli \ 44 | ajv-formats 45 | 46 | - name: Validate local labels configuration 47 | run: | 48 | # See: https://github.com/ajv-validator/ajv-cli#readme 49 | ajv validate \ 50 | --all-errors \ 51 | -c ajv-formats \ 52 | -s "${{ steps.download-schema.outputs.file-path }}" \ 53 | -d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}" 54 | 55 | download: 56 | needs: check 57 | runs-on: ubuntu-latest 58 | 59 | strategy: 60 | matrix: 61 | filename: 62 | # Filenames of the shared configurations to apply to the repository in addition to the local configuration. 63 | # https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels 64 | - universal.yml 65 | 66 | steps: 67 | - name: Download 68 | uses: carlosperate/download-file-action@v2 69 | with: 70 | file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} 71 | 72 | - name: Pass configuration files to next job via workflow artifact 73 | uses: actions/upload-artifact@v4 74 | with: 75 | path: | 76 | *.yaml 77 | *.yml 78 | if-no-files-found: error 79 | name: ${{ env.CONFIGURATIONS_ARTIFACT }} 80 | 81 | sync: 82 | needs: download 83 | runs-on: ubuntu-latest 84 | 85 | steps: 86 | - name: Set environment variables 87 | run: | 88 | # See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable 89 | echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV" 90 | 91 | - name: Determine whether to dry run 92 | id: dry-run 93 | if: > 94 | github.event_name == 'pull_request' || 95 | ( 96 | ( 97 | github.event_name == 'push' || 98 | github.event_name == 'workflow_dispatch' 99 | ) && 100 | github.ref != format('refs/heads/{0}', github.event.repository.default_branch) 101 | ) 102 | run: | 103 | # Use of this flag in the github-label-sync command will cause it to only check the validity of the 104 | # configuration. 105 | echo "::set-output name=flag::--dry-run" 106 | 107 | - name: Checkout repository 108 | uses: actions/checkout@v4 109 | 110 | - name: Download configuration files artifact 111 | uses: actions/download-artifact@v4 112 | with: 113 | name: ${{ env.CONFIGURATIONS_ARTIFACT }} 114 | path: ${{ env.CONFIGURATIONS_FOLDER }} 115 | 116 | - name: Remove unneeded artifact 117 | uses: geekyeggo/delete-artifact@v5 118 | with: 119 | name: ${{ env.CONFIGURATIONS_ARTIFACT }} 120 | 121 | - name: Merge label configuration files 122 | run: | 123 | # Merge all configuration files 124 | shopt -s extglob 125 | cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}" 126 | 127 | - name: Install github-label-sync 128 | run: sudo npm install --global github-label-sync 129 | 130 | - name: Sync labels 131 | env: 132 | GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} 133 | run: | 134 | # See: https://github.com/Financial-Times/github-label-sync 135 | github-label-sync \ 136 | --labels "${{ env.MERGED_CONFIGURATION_PATH }}" \ 137 | ${{ steps.dry-run.outputs.flag }} \ 138 | ${{ github.repository }} 139 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | MKRGSM ?.?.? - ????.??.?? 2 | 3 | MKRGSM 1.4.2 - 2019.06.18 4 | 5 | * fixed compilation under gcc 7.4.0 6 | 7 | MKRGSM 1.4.1 - 2019.04.15 8 | 9 | * Corrected GSMClient::connect(...) return code on failure 10 | * Corrected manage SSL profile AT command for GSMSSLClient 11 | * Replaced bundled "Amazon Root CA 1" root certificate with "Starfield Services Root Certificate Authority - G2 root CA" 12 | 13 | MKRGSM 1.4.0 - 2019.03.26 14 | 15 | * GSMBand, BandManagement example: Added support for 1800 MHz and UMTS 2100 MHz bands. 16 | * Added GSMModem::getICCID() API. 17 | * Added MODEM.setBaudRate(...) and MODEM.debug(print) API's. Thanks @dzindra. 18 | * Added Amazon Root CA 1. 19 | 20 | MKRGSM 1.3.3 - 2019.01.15 21 | 22 | * Fixed GSMClient::write for write lengths of > 256. 23 | 24 | MKRGSM 1.3.2 - 2018.12.17 25 | 26 | * Fixed one character SMS not being received correctly 27 | * Fixed warning and incorrect enum comparison in GSM::shutdown() 28 | 29 | MKRGSM 1.3.1 - 2018.11.12 30 | 31 | * Changed where required, in MKRGSM's examples, the server's URL arduino.cc\80 in example.org\80, because http://arduino.cc will be no longer available 32 | * Updated src/GSMClient.cpp in order to support asynchronous use of MKRGSM's library, moved the state assignment in the first line of stop() API. Thanks @Nels52 33 | * Added GSM status check in GSM::shutdown() to fix socket close errors generation by consecutive shutdown API's calling 34 | 35 | MKRGSM 1.3.0 - 2018.10.22 36 | 37 | * Changed GSM to GSM_OFF. Thanks @FrancMunoz 38 | * Added GSM::getLocalTime() API. Thanks @FrancMunoz 39 | * Added socket buffer to improve TCP socket read performance 40 | * Replaced boolean type with bool in examples. Thanks @per1234 41 | * Changed AT command handling to wait at least 20 ms for URC's, after receiving an AT command response before sending a new command. Thanks @FrancMunoz 42 | * Added root SSL certs and enabled SSL cert validation 43 | * Added GSM::setTimeout(...) and GPRS::setTimeout(...) API's 44 | * Added GSM::status() API 45 | 46 | MKRGSM 1.2.1 - 2018.09.13 47 | 48 | * Fixed GPRS credentials (username and password) not being used by the modem. Now auth type is set to automatic. 49 | 50 | MKRGSM 1.2.0 - 2018.07.23 51 | 52 | * Added MODEM.noDebug() API to disable debug output 53 | * GSM::isAccessAlive() now checks if network is registered 54 | * Added timeout to ping operations 55 | * Added GPRS::status() API to retrieve the current GPRS status 56 | * Fixed GSMClient::write(uint8_t c) 57 | 58 | MKRGSM 1.1.2 - 2018.02.20 59 | 60 | * Improved stability of low power mode 61 | * Improved stability and performance when using GSMClient and GSMUDP 62 | 63 | MKRGSM 1.1.1 - 2018.01.24 64 | 65 | * Fixed GSMServer.available() behaviour when client.stop() is called on an accepted socket 66 | 67 | MKRGSM 1.1.0 - 2018.01.02 68 | 69 | * Added new GSMLocation API 70 | * Fixed GSMClient write failing for lengths of 512 or over 71 | * Removed use of double negatives and corrected some bit wise ANDs with logical ANDs in example sketches 72 | 73 | MKRGSM 1.0.2 - 2017.12.11 74 | 75 | * Added new GPRSPing, GsmSSLWebClient, GPRSUdpNtpClient and SerialGSMPassthrough example sketches 76 | 77 | MKRGSM 1.0.1 - 2017.12.04 78 | 79 | * Examples updated with support for the Arduino Create secret tab 80 | 81 | MKRGSM 1.0.0 - 2017.11.29 82 | 83 | * Initial release 84 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | :repository-owner: arduino-libraries 2 | :repository-name: MKRGSM 3 | 4 | = {repository-name} Library for Arduino = 5 | 6 | image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"] 7 | image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"] 8 | image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"] 9 | 10 | This library enables an Arduino MKR GSM 1400 board to do most of the operations you can do with a GSM phone: place and receive voice calls, send and receive SMS, and connect to the internet over a GPRS network. 11 | 12 | For more information about this library please visit us at 13 | http://www.arduino.cc/en/Reference/{repository-name} 14 | -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | # MKRGSM library 2 | 3 | The [MKR GSM library](https://www.arduino.cc/en/Reference/MKRGSM) can be installed using the [Arduino library manager](https://www.arduino.cc/en/Guide/Libraries). 4 | 5 | With the [Arduino MKR GSM 1400](https://store.arduino.cc/mkr-gsm-1400) and this library you can do most of the operations you can do with a GSM phone: place and receive voice calls, send and receive SMS, and connect to the internet over a GPRS network. The on board module, operates in 3G with a 2G fallback. 6 | 7 | Arduino MKR GSM 1400 has a modem that transfers data from a serial port to the GSM network. The modem executes operations via a series of AT commands. The library abstracts low level communications between the modem and SIM card. It relies on the [Serial library](https://www.arduino.cc/en/Reference/Serial) for communication between the modem and Arduino. 8 | 9 | Typically, each individual command is part of a larger series necessary to execute a particular function. The library can also receive information and return it to you when necessary. 10 | 11 | This library is based on the [GSM](https://www.arduino.cc/en/Reference/GSM) library of the Arduino GSM shield, adding new features like UDP, SSL and DTMF tone recognition. 12 | 13 | To use this library 14 | ``` 15 | #include 16 | ``` 17 | 18 | ## Library structure 19 | 20 | As the library enables multiple types of functionality, there are a number of different classes. 21 | 22 | - The `GSM` class takes care of commands to the radio modem. This handles the connectivity aspects of the module and registers your system in the GSM infrastructure. All of your GSM/GPRS programs will need to include an object of this class to handle the necessary low level communication. 23 | - Voice call handling, managed by the `GSMVoiceCall` class. 24 | - Send/receive SMS messages, managed by the `GSM_SMS` class. 25 | - The `GPRSClass` is for connecting to the internet. 26 | - `GSMClient` includes implementations for a client, similar to the Ethernet and WiFi libraries. 27 | - `GSMServer` includes implementations for a server, similar to the Ethernet and WiFi libraries. NB : A number of network operators do not allow for incoming connections from the public internet, but will allow them from inside their own. Check with your operator to see what restrictions there are on data use. 28 | - A number of utility classes such as GSMScanner and GSMModem 29 | 30 | ## Library compatibility 31 | 32 | The library tries to be as compatible as possible with the current Ethernet and WiFi101 library. Porting a program from an Arduino Ethernet or WiFi101 library to an Arduino with the MKR GSM 1400 should be fairly easy. While it is not possible to simply run Ethernet or WiFi101 compatible code on the MKR GSM 1400 as-is, some minor, library specific, modifications will be necessary, like including the GSM and GPRS specific libraries and getting network configuration settings from your cellular network provider. 33 | -------------------------------------------------------------------------------- /examples/GPRSPing/GPRSPing.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This uses an MKR GSM 1400 to continuously ping a host specified by IP Address or name. 4 | 5 | Circuit: 6 | * MKR GSM 1400 board 7 | * Antenna 8 | * SIM card with a data plan 9 | 10 | created 06 Dec 2017 11 | by Arturo Guadalupi 12 | */ 13 | #include 14 | 15 | #include "arduino_secrets.h" 16 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 17 | // PIN Number 18 | const char PINNUMBER[] = SECRET_PINNUMBER; 19 | // APN data 20 | const char GPRS_APN[] = SECRET_GPRS_APN; 21 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 22 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 23 | 24 | // initialize the library instance 25 | GSMSSLClient client; 26 | GPRS gprs; 27 | GSM gsmAccess; 28 | 29 | // Specify IP address or hostname 30 | String hostName = "www.google.com"; 31 | int pingResult; 32 | 33 | void setup() { 34 | // Initialize serial and wait for port to open: 35 | Serial.begin(9600); 36 | while (!Serial) { 37 | ; // wait for serial port to connect. Needed for native USB port only 38 | } 39 | 40 | Serial.println("Starting Arduino GPRS ping."); 41 | // connection state 42 | bool connected = false; 43 | 44 | // After starting the modem with GSM.begin() 45 | // attach the shield to the GPRS network with the APN, login and password 46 | while (!connected) { 47 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 48 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 49 | connected = true; 50 | } else { 51 | Serial.println("Not connected"); 52 | delay(1000); 53 | } 54 | } 55 | } 56 | 57 | void loop() { 58 | Serial.print("Pinging "); 59 | Serial.print(hostName); 60 | Serial.print(": "); 61 | 62 | pingResult = gprs.ping(hostName); 63 | 64 | if (pingResult >= 0) { 65 | Serial.print("SUCCESS! RTT = "); 66 | Serial.print(pingResult); 67 | Serial.println(" ms"); 68 | } else { 69 | Serial.print("FAILED! Error code: "); 70 | Serial.println(pingResult); 71 | } 72 | 73 | delay(5000); 74 | } 75 | -------------------------------------------------------------------------------- /examples/GPRSPing/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | #define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN 3 | #define SECRET_GPRS_LOGIN "login" // replace with your GPRS login 4 | #define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password 5 | -------------------------------------------------------------------------------- /examples/GPRSUdpNtpClient/GPRSUdpNtpClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Udp NTP Client 4 | 5 | Get the time from a Network Time Protocol (NTP) time server 6 | Demonstrates use of UDP sendPacket and ReceivePacket 7 | For more on NTP time servers and the messages needed to communicate with them, 8 | see http://en.wikipedia.org/wiki/Network_Time_Protocol 9 | 10 | created 4 Sep 2010 11 | by Michael Margolis 12 | modified 9 Apr 2012 13 | by Tom Igoe 14 | 15 | modified 6 Dec 2017 ported from WiFi101 to MKRGSM 16 | by Arturo Guadalupi 17 | 18 | This code is in the public domain. 19 | 20 | */ 21 | 22 | #include 23 | 24 | #include "arduino_secrets.h" 25 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 26 | // PIN Number 27 | const char PINNUMBER[] = SECRET_PINNUMBER; 28 | // APN data 29 | const char GPRS_APN[] = SECRET_GPRS_APN; 30 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 31 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 32 | 33 | unsigned int localPort = 2390; // local port to listen for UDP packets 34 | 35 | IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server 36 | 37 | const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message 38 | 39 | byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 40 | 41 | // initialize the library instance 42 | GSMClient client; 43 | GPRS gprs; 44 | GSM gsmAccess; 45 | 46 | // A UDP instance to let us send and receive packets over UDP 47 | GSMUDP Udp; 48 | 49 | void setup() 50 | { 51 | // Open serial communications and wait for port to open: 52 | Serial.begin(9600); 53 | while (!Serial) { 54 | ; // wait for serial port to connect. Needed for native USB port only 55 | } 56 | 57 | Serial.println("Starting Arduino GPRS NTP client."); 58 | // connection state 59 | bool connected = false; 60 | 61 | // After starting the modem with GSM.begin() 62 | // attach the shield to the GPRS network with the APN, login and password 63 | while (!connected) { 64 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 65 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 66 | connected = true; 67 | } else { 68 | Serial.println("Not connected"); 69 | delay(1000); 70 | } 71 | } 72 | 73 | Serial.println("\nStarting connection to server..."); 74 | Udp.begin(localPort); 75 | } 76 | 77 | void loop() 78 | { 79 | sendNTPpacket(timeServer); // send an NTP packet to a time server 80 | // wait to see if a reply is available 81 | delay(1000); 82 | if ( Udp.parsePacket() ) { 83 | Serial.println("packet received"); 84 | // We've received a packet, read the data from it 85 | Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer 86 | 87 | //the timestamp starts at byte 40 of the received packet and is four bytes, 88 | // or two words, long. First, extract the two words: 89 | 90 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 91 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 92 | // combine the four bytes (two words) into a long integer 93 | // this is NTP time (seconds since Jan 1 1900): 94 | unsigned long secsSince1900 = highWord << 16 | lowWord; 95 | Serial.print("Seconds since Jan 1 1900 = " ); 96 | Serial.println(secsSince1900); 97 | 98 | // now convert NTP time into everyday time: 99 | Serial.print("Unix time = "); 100 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: 101 | const unsigned long seventyYears = 2208988800UL; 102 | // subtract seventy years: 103 | unsigned long epoch = secsSince1900 - seventyYears; 104 | // print Unix time: 105 | Serial.println(epoch); 106 | 107 | 108 | // print the hour, minute and second: 109 | Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT) 110 | Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day) 111 | Serial.print(':'); 112 | if ( ((epoch % 3600) / 60) < 10 ) { 113 | // In the first 10 minutes of each hour, we'll want a leading '0' 114 | Serial.print('0'); 115 | } 116 | Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) 117 | Serial.print(':'); 118 | if ( (epoch % 60) < 10 ) { 119 | // In the first 10 seconds of each minute, we'll want a leading '0' 120 | Serial.print('0'); 121 | } 122 | Serial.println(epoch % 60); // print the second 123 | } 124 | // wait ten seconds before asking for the time again 125 | delay(10000); 126 | } 127 | 128 | // send an NTP request to the time server at the given address 129 | unsigned long sendNTPpacket(IPAddress& address) 130 | { 131 | //Serial.println("1"); 132 | // set all bytes in the buffer to 0 133 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 134 | // Initialize values needed to form NTP request 135 | // (see URL above for details on the packets) 136 | //Serial.println("2"); 137 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 138 | packetBuffer[1] = 0; // Stratum, or type of clock 139 | packetBuffer[2] = 6; // Polling Interval 140 | packetBuffer[3] = 0xEC; // Peer Clock Precision 141 | // 8 bytes of zero for Root Delay & Root Dispersion 142 | packetBuffer[12] = 49; 143 | packetBuffer[13] = 0x4E; 144 | packetBuffer[14] = 49; 145 | packetBuffer[15] = 52; 146 | 147 | //Serial.println("3"); 148 | 149 | // all NTP fields have been given values, now 150 | // you can send a packet requesting a timestamp: 151 | Udp.beginPacket(address, 123); //NTP requests are to port 123 152 | //Serial.println("4"); 153 | Udp.write(packetBuffer, NTP_PACKET_SIZE); 154 | //Serial.println("5"); 155 | Udp.endPacket(); 156 | //Serial.println("6"); 157 | } 158 | -------------------------------------------------------------------------------- /examples/GPRSUdpNtpClient/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | #define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN 3 | #define SECRET_GPRS_LOGIN "login" // replace with your GPRS login 4 | #define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password 5 | -------------------------------------------------------------------------------- /examples/GsmLocation/GsmLocation.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Location 3 | 4 | This sketch uses the celluar network to determine the location of a MKR GSM 1400 board 5 | and prints it to the Serial Monitor. The location is based on the cellular towers in 6 | range, and requires a GPRS data connection to be enabled. 7 | 8 | Circuit: 9 | MKR GSM 1400 board 10 | Antenna 11 | SIM card with a data plan 12 | 13 | created 15 Dec 2017 14 | by Sandeep Mistry 15 | */ 16 | 17 | // libraries 18 | #include 19 | 20 | #include "arduino_secrets.h" 21 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 22 | // PIN Number 23 | const char PINNUMBER[] = SECRET_PINNUMBER; 24 | // APN data 25 | const char GPRS_APN[] = SECRET_GPRS_APN; 26 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 27 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 28 | 29 | // initialize the library instance 30 | GSMLocation location; 31 | GPRS gprs; 32 | GSM gsmAccess; 33 | 34 | void setup() { 35 | // initialize serial communications and wait for port to open: 36 | Serial.begin(9600); 37 | while (!Serial) { 38 | ; // wait for serial port to connect. Needed for native USB port only 39 | } 40 | 41 | Serial.println("Starting GSM location."); 42 | // connection state 43 | bool connected = false; 44 | 45 | // After starting the modem with GSM.begin() 46 | // attach the shield to the GPRS network with the APN, login and password 47 | while (!connected) { 48 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 49 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 50 | connected = true; 51 | } else { 52 | Serial.println("Not connected"); 53 | delay(1000); 54 | } 55 | } 56 | 57 | location.begin(); 58 | } 59 | 60 | void loop() { 61 | if (location.available()) { 62 | Serial.print("Location: "); 63 | Serial.print(location.latitude(), 7); 64 | Serial.print(", "); 65 | Serial.println(location.longitude(), 7); 66 | 67 | Serial.print("Altitude: "); 68 | Serial.print(location.altitude()); 69 | Serial.println("m"); 70 | 71 | Serial.print("Accuracy: +/- "); 72 | Serial.print(location.accuracy()); 73 | Serial.println("m"); 74 | 75 | Serial.println(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /examples/GsmLocation/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | #define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN 3 | #define SECRET_GPRS_LOGIN "login" // replace with your GPRS login 4 | #define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password 5 | -------------------------------------------------------------------------------- /examples/GsmSSLWebClient/GsmSSLWebClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Web client 3 | 4 | This sketch connects to a website using SSL through a MKR GSM 1400 board. Specifically, 5 | this example downloads the URL "http://www.arduino.cc/asciilogo.txt" and 6 | prints it to the Serial Monitor. 7 | 8 | Circuit: 9 | * MKR GSM 1400 board 10 | * Antenna 11 | * SIM card with a data plan 12 | 13 | created 8 Mar 2012 14 | by Tom Igoe 15 | */ 16 | 17 | // libraries 18 | #include 19 | 20 | #include "arduino_secrets.h" 21 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 22 | // PIN Number 23 | const char PINNUMBER[] = SECRET_PINNUMBER; 24 | // APN data 25 | const char GPRS_APN[] = SECRET_GPRS_APN; 26 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 27 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 28 | 29 | // initialize the library instance 30 | GSMSSLClient client; 31 | GPRS gprs; 32 | GSM gsmAccess; 33 | 34 | // URL, path and port (for example: arduino.cc) 35 | char server[] = "arduino.cc"; 36 | char path[] = "/asciilogo.txt"; 37 | int port = 443; // port 443 is the default for HTTPS 38 | 39 | void setup() { 40 | // initialize serial communications and wait for port to open: 41 | Serial.begin(9600); 42 | while (!Serial) { 43 | ; // wait for serial port to connect. Needed for native USB port only 44 | } 45 | 46 | Serial.println("Starting Arduino web client."); 47 | // connection state 48 | bool connected = false; 49 | 50 | // After starting the modem with GSM.begin() 51 | // attach the shield to the GPRS network with the APN, login and password 52 | while (!connected) { 53 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 54 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 55 | connected = true; 56 | } else { 57 | Serial.println("Not connected"); 58 | delay(1000); 59 | } 60 | } 61 | 62 | Serial.println("connecting..."); 63 | 64 | // if you get a connection, report back via serial: 65 | if (client.connect(server, port)) { 66 | Serial.println("connected"); 67 | // Make a HTTP request: 68 | client.print("GET "); 69 | client.print(path); 70 | client.println(" HTTP/1.1"); 71 | client.print("Host: "); 72 | client.println(server); 73 | client.println("Connection: close"); 74 | client.println(); 75 | } else { 76 | // if you didn't get a connection to the server: 77 | Serial.println("connection failed"); 78 | } 79 | } 80 | 81 | void loop() { 82 | // if there are incoming bytes available 83 | // from the server, read them and print them: 84 | if (client.available()) { 85 | char c = client.read(); 86 | Serial.print(c); 87 | } 88 | 89 | // if the server's disconnected, stop the client: 90 | if (!client.available() && !client.connected()) { 91 | Serial.println(); 92 | Serial.println("disconnecting."); 93 | client.stop(); 94 | 95 | // do nothing forevermore: 96 | for (;;) 97 | ; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /examples/GsmSSLWebClient/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | #define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN 3 | #define SECRET_GPRS_LOGIN "login" // replace with your GPRS login 4 | #define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password 5 | -------------------------------------------------------------------------------- /examples/GsmWebClient/GsmWebClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Web client 3 | 4 | This sketch connects to a website through a MKR GSM 1400 board. Specifically, 5 | this example downloads the URL "http://www.example.org/" and 6 | prints it to the Serial Monitor. 7 | 8 | Circuit: 9 | * MKR GSM 1400 board 10 | * Antenna 11 | * SIM card with a data plan 12 | 13 | created 8 Mar 2012 14 | by Tom Igoe 15 | */ 16 | 17 | // libraries 18 | #include 19 | 20 | #include "arduino_secrets.h" 21 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 22 | // PIN Number 23 | const char PINNUMBER[] = SECRET_PINNUMBER; 24 | // APN data 25 | const char GPRS_APN[] = SECRET_GPRS_APN; 26 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 27 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 28 | 29 | // initialize the library instance 30 | GSMClient client; 31 | GPRS gprs; 32 | GSM gsmAccess; 33 | 34 | // URL, path and port (for example: example.org) 35 | char server[] = "example.org"; 36 | char path[] = "/"; 37 | int port = 80; // port 80 is the default for HTTP 38 | 39 | void setup() { 40 | // initialize serial communications and wait for port to open: 41 | Serial.begin(9600); 42 | while (!Serial) { 43 | ; // wait for serial port to connect. Needed for native USB port only 44 | } 45 | 46 | Serial.println("Starting Arduino web client."); 47 | // connection state 48 | bool connected = false; 49 | 50 | // After starting the modem with GSM.begin() 51 | // attach the shield to the GPRS network with the APN, login and password 52 | while (!connected) { 53 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 54 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 55 | connected = true; 56 | } else { 57 | Serial.println("Not connected"); 58 | delay(1000); 59 | } 60 | } 61 | 62 | Serial.println("connecting..."); 63 | 64 | // if you get a connection, report back via serial: 65 | if (client.connect(server, port)) { 66 | Serial.println("connected"); 67 | // Make a HTTP request: 68 | client.print("GET "); 69 | client.print(path); 70 | client.println(" HTTP/1.1"); 71 | client.print("Host: "); 72 | client.println(server); 73 | client.println("Connection: close"); 74 | client.println(); 75 | } else { 76 | // if you didn't get a connection to the server: 77 | Serial.println("connection failed"); 78 | } 79 | } 80 | 81 | void loop() { 82 | // if there are incoming bytes available 83 | // from the server, read them and print them: 84 | if (client.available()) { 85 | char c = client.read(); 86 | Serial.print(c); 87 | } 88 | 89 | // if the server's disconnected, stop the client: 90 | if (!client.available() && !client.connected()) { 91 | Serial.println(); 92 | Serial.println("disconnecting."); 93 | client.stop(); 94 | 95 | // do nothing forevermore: 96 | for (;;) 97 | ; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /examples/GsmWebClient/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | #define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN 3 | #define SECRET_GPRS_LOGIN "login" // replace with your GPRS login 4 | #define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password 5 | -------------------------------------------------------------------------------- /examples/GsmWebServer/GsmWebServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | GSM Web Server 3 | 4 | A simple web server that shows the value of the analog input pins. 5 | using a MKR GSM 1400 board. 6 | 7 | Circuit: 8 | * MKR GSM 1400 board 9 | * Antenna 10 | * Analog inputs attached to pins A0 through A5 (optional) 11 | 12 | created 8 Mar 2012 13 | by Tom Igoe 14 | */ 15 | 16 | // libraries 17 | #include 18 | 19 | #include "arduino_secrets.h" 20 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 21 | // PIN Number 22 | const char PINNUMBER[] = SECRET_PINNUMBER; 23 | // APN data 24 | const char GPRS_APN[] = SECRET_GPRS_APN; 25 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 26 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 27 | 28 | 29 | // initialize the library instance 30 | GPRS gprs; 31 | GSM gsmAccess; // include a 'true' parameter for debug enabled 32 | GSMServer server(80); // port 80 (http default) 33 | 34 | // timeout 35 | const unsigned long __TIMEOUT__ = 10 * 1000; 36 | 37 | void setup() { 38 | // initialize serial communications and wait for port to open: 39 | Serial.begin(9600); 40 | while (!Serial) { 41 | ; // wait for serial port to connect. Needed for native USB port only 42 | } 43 | 44 | // connection state 45 | bool connected = false; 46 | 47 | // Start GSM shield 48 | // If your SIM has PIN, pass it as a parameter of begin() in quotes 49 | while (!connected) { 50 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 51 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 52 | connected = true; 53 | } else { 54 | Serial.println("Not connected"); 55 | delay(1000); 56 | } 57 | } 58 | 59 | Serial.println("Connected to GPRS network"); 60 | 61 | // start server 62 | server.begin(); 63 | 64 | //Get IP. 65 | IPAddress LocalIP = gprs.getIPAddress(); 66 | Serial.println("Server IP address="); 67 | Serial.println(LocalIP); 68 | } 69 | 70 | void loop() { 71 | 72 | 73 | // listen for incoming clients 74 | GSMClient client = server.available(); 75 | 76 | 77 | 78 | if (client) { 79 | while (client.connected()) { 80 | if (client.available()) { 81 | Serial.println("Receiving request!"); 82 | bool sendResponse = false; 83 | while (int c = client.read()) { 84 | if (c == -1) { 85 | break; 86 | } else if (c == '\n') { 87 | sendResponse = true; 88 | } 89 | } 90 | 91 | // if you've gotten to the end of the line (received a newline 92 | // character) 93 | if (sendResponse) { 94 | // send a standard http response header 95 | client.println("HTTP/1.1 200 OK"); 96 | client.println("Content-Type: text/html"); 97 | client.println(); 98 | client.println(""); 99 | // output the value of each analog input pin 100 | for (int analogChannel = 0; analogChannel < 6; analogChannel++) { 101 | client.print("analog input "); 102 | client.print(analogChannel); 103 | client.print(" is "); 104 | client.print(analogRead(analogChannel)); 105 | client.println("
"); 106 | } 107 | client.println(""); 108 | //necessary delay 109 | delay(1000); 110 | client.stop(); 111 | } 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /examples/GsmWebServer/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | #define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN 3 | #define SECRET_GPRS_LOGIN "login" // replace with your GPRS login 4 | #define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password 5 | -------------------------------------------------------------------------------- /examples/MakeVoiceCall/MakeVoiceCall.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Make Voice Call 3 | 4 | This sketch, for the MKR GSM 1400 board, puts a voice call to 5 | a remote phone number that you enter through the Serial Monitor. 6 | To make it work, open the Serial Monitor, and when you see the 7 | READY message, type a phone number. Make sure the Serial Monitor 8 | is set to send a just newline when you press return. 9 | 10 | Circuit: 11 | * MKR GSM 1400 board 12 | * Antenna 13 | * SIM card that can send voice calls 14 | 15 | 16 | created Mar 2012 17 | by Javier Zorzano 18 | */ 19 | 20 | // libraries 21 | #include 22 | 23 | #include "arduino_secrets.h" 24 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 25 | // PIN Number 26 | const char PINNUMBER[] = SECRET_PINNUMBER; 27 | 28 | // initialize the library instance 29 | GSM gsmAccess; // include a 'true' parameter for debug enabled 30 | GSMVoiceCall vcs; 31 | 32 | String remoteNumber = ""; // the number you will call 33 | char charbuffer[20]; 34 | 35 | void setup() { 36 | 37 | // initialize serial communications and wait for port to open: 38 | Serial.begin(9600); 39 | while (!Serial) { 40 | ; // wait for serial port to connect. Needed for native USB port only 41 | } 42 | 43 | Serial.println("Make Voice Call"); 44 | 45 | // connection state 46 | bool connected = false; 47 | 48 | // Start GSM shield 49 | // If your SIM has PIN, pass it as a parameter of begin() in quotes 50 | while (!connected) { 51 | if (gsmAccess.begin(PINNUMBER) == GSM_READY) { 52 | connected = true; 53 | } else { 54 | Serial.println("Not connected"); 55 | delay(1000); 56 | } 57 | } 58 | 59 | Serial.println("GSM initialized."); 60 | Serial.println("Enter phone number to call."); 61 | 62 | } 63 | 64 | void loop() { 65 | 66 | // add any incoming characters to the String: 67 | while (Serial.available() > 0) { 68 | char inChar = Serial.read(); 69 | // if it's a newline, that means you should make the call: 70 | if (inChar == '\n') { 71 | // make sure the phone number is not too long: 72 | if (remoteNumber.length() < 20) { 73 | // let the user know you're calling: 74 | Serial.print("Calling to : "); 75 | Serial.println(remoteNumber); 76 | Serial.println(); 77 | 78 | // Call the remote number 79 | remoteNumber.toCharArray(charbuffer, 20); 80 | 81 | 82 | // Check if the receiving end has picked up the call 83 | if (vcs.voiceCall(charbuffer)) { 84 | Serial.println("Call Established. Enter line to end"); 85 | // Wait for some input from the line 86 | while (Serial.read() != '\n' && (vcs.getvoiceCallStatus() == TALKING)); 87 | // And hang up 88 | vcs.hangCall(); 89 | } 90 | Serial.println("Call Finished"); 91 | remoteNumber = ""; 92 | Serial.println("Enter phone number to call."); 93 | } else { 94 | Serial.println("That's too long for a phone number. I'm forgetting it"); 95 | remoteNumber = ""; 96 | } 97 | } else { 98 | // add the latest character to the message to send: 99 | if (inChar != '\r') { 100 | remoteNumber += inChar; 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /examples/MakeVoiceCall/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | -------------------------------------------------------------------------------- /examples/ReceiveSMS/ReceiveSMS.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SMS receiver 3 | 4 | This sketch, for the MKR GSM 1400 board, waits for a SMS message 5 | and displays it through the Serial port. 6 | 7 | Circuit: 8 | * MKR GSM 1400 board 9 | * Antenna 10 | * SIM card that can receive SMS messages 11 | 12 | created 25 Feb 2012 13 | by Javier Zorzano / TD 14 | */ 15 | 16 | // include the GSM library 17 | #include 18 | 19 | #include "arduino_secrets.h" 20 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 21 | // PIN Number 22 | const char PINNUMBER[] = SECRET_PINNUMBER; 23 | 24 | // initialize the library instances 25 | GSM gsmAccess; 26 | GSM_SMS sms; 27 | 28 | // Array to hold the number a SMS is retrieved from 29 | char senderNumber[20]; 30 | 31 | void setup() { 32 | // initialize serial communications and wait for port to open: 33 | Serial.begin(9600); 34 | while (!Serial) { 35 | ; // wait for serial port to connect. Needed for native USB port only 36 | } 37 | 38 | Serial.println("SMS Messages Receiver"); 39 | 40 | // connection state 41 | bool connected = false; 42 | 43 | // Start GSM connection 44 | while (!connected) { 45 | if (gsmAccess.begin(PINNUMBER) == GSM_READY) { 46 | connected = true; 47 | } else { 48 | Serial.println("Not connected"); 49 | delay(1000); 50 | } 51 | } 52 | 53 | Serial.println("GSM initialized"); 54 | Serial.println("Waiting for messages"); 55 | } 56 | 57 | void loop() { 58 | int c; 59 | 60 | // If there are any SMSs available() 61 | if (sms.available()) { 62 | Serial.println("Message received from:"); 63 | 64 | // Get remote number 65 | sms.remoteNumber(senderNumber, 20); 66 | Serial.println(senderNumber); 67 | 68 | // An example of message disposal 69 | // Any messages starting with # should be discarded 70 | if (sms.peek() == '#') { 71 | Serial.println("Discarded SMS"); 72 | sms.flush(); 73 | } 74 | 75 | // Read message bytes and print them 76 | while ((c = sms.read()) != -1) { 77 | Serial.print((char)c); 78 | } 79 | 80 | Serial.println("\nEND OF MESSAGE"); 81 | 82 | // Delete message from modem memory 83 | sms.flush(); 84 | Serial.println("MESSAGE DELETED"); 85 | } 86 | 87 | delay(1000); 88 | 89 | } 90 | -------------------------------------------------------------------------------- /examples/ReceiveSMS/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | -------------------------------------------------------------------------------- /examples/ReceiveVoiceCall/ReceiveVoiceCall.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Receive Voice Call 3 | 4 | This sketch, for the MKR GSM 1400 board, receives voice calls, 5 | displays the calling number, waits a few seconds then hangs up. 6 | 7 | Circuit: 8 | * MKR GSM 1400 board 9 | * Antenna 10 | * SIM card that can accept voice calls 11 | 12 | created Mar 2012 13 | by Javier Zorzano 14 | */ 15 | 16 | // Include the GSM library 17 | #include 18 | 19 | #include "arduino_secrets.h" 20 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 21 | // PIN Number 22 | const char PINNUMBER[] = SECRET_PINNUMBER; 23 | 24 | // initialize the library instance 25 | GSM gsmAccess; 26 | GSMVoiceCall vcs; 27 | 28 | // Array to hold the number for the incoming call 29 | char numtel[20]; 30 | 31 | void setup() { 32 | // initialize serial communications and wait for port to open: 33 | Serial.begin(9600); 34 | while (!Serial) { 35 | ; // wait for serial port to connect. Needed for native USB port only 36 | } 37 | 38 | Serial.println("Receive Voice Call"); 39 | 40 | // connection state 41 | bool connected = false; 42 | 43 | // Start GSM shield 44 | // If your SIM has PIN, pass it as a parameter of begin() in quotes 45 | while (!connected) { 46 | if (gsmAccess.begin(PINNUMBER) == GSM_READY) { 47 | connected = true; 48 | } else { 49 | Serial.println("Not connected"); 50 | delay(1000); 51 | } 52 | } 53 | 54 | // This makes sure the modem correctly reports incoming events 55 | vcs.hangCall(); 56 | 57 | Serial.println("Waiting for a call"); 58 | } 59 | 60 | void loop() { 61 | // Check the status of the voice call 62 | switch (vcs.getvoiceCallStatus()) { 63 | case IDLE_CALL: // Nothing is happening 64 | 65 | break; 66 | 67 | case RECEIVINGCALL: // Yes! Someone is calling us 68 | 69 | Serial.println("RECEIVING CALL"); 70 | 71 | // Retrieve the calling number 72 | vcs.retrieveCallingNumber(numtel, 20); 73 | 74 | // Print the calling number 75 | Serial.print("Number:"); 76 | Serial.println(numtel); 77 | 78 | // Answer the call, establish the call 79 | vcs.answerCall(); 80 | break; 81 | 82 | case TALKING: // In this case the call would be established 83 | 84 | Serial.println("TALKING. Press enter to hang up."); 85 | while (Serial.read() != '\n') { 86 | delay(100); 87 | } 88 | vcs.hangCall(); 89 | Serial.println("Hanging up and waiting for the next call."); 90 | break; 91 | } 92 | delay(1000); 93 | } 94 | -------------------------------------------------------------------------------- /examples/ReceiveVoiceCall/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | -------------------------------------------------------------------------------- /examples/SSLCertificateManagement/SSLCertificateManagement.ino: -------------------------------------------------------------------------------- 1 | /* 2 | ArduinoMqttClient - SSLCertificateManagement 3 | 4 | This example shows how to upload a self signed certificate 5 | by GSMSSLClient's APIs, connect to a MQTT broker, 6 | and publish a message to a topic once a second. 7 | 8 | The circuit: 9 | - Arduino MKR GSM 1400 10 | 11 | This example code is in the public domain. 12 | */ 13 | 14 | #include 15 | #include 16 | #include "arduino_secrets.h" 17 | 18 | 19 | const char PINNUMBER[] = SECRET_PINNUMBER; 20 | // APN data 21 | const char GPRS_APN[] = SECRET_GPRS_APN; 22 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 23 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 24 | 25 | // initialize the library instance 26 | GSMSSLClient client; 27 | GPRS gprs; 28 | GSM gsmAccess; 29 | MqttClient mqttClient(client); 30 | 31 | // replace with your broker, port and topic 32 | const char broker[] = ""; 33 | int port = 8883; 34 | const char topic[] = ""; 35 | 36 | const long interval = 1000; 37 | unsigned long previousMillis = 0; 38 | 39 | int count = 0; 40 | 41 | 42 | void setup() { 43 | // Initialize serial and wait for port to open: 44 | Serial.begin(9600); 45 | while (!Serial) { 46 | ; // wait for serial port to connect. Needed for native USB port only 47 | } 48 | 49 | bool connected = false; 50 | // After starting the modem with GSM.begin() 51 | // attach the shield to the GPRS network with the APN, login and password 52 | while (!connected) { 53 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 54 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 55 | connected = true; 56 | } else { 57 | Serial.println("Not connected"); 58 | delay(1000); 59 | } 60 | } 61 | 62 | Serial.println("You're connected to the network"); 63 | Serial.println(); 64 | 65 | // eraseAllCertificates erases all the certificates stored in the onboard 66 | // GSM module 67 | client.eraseAllCertificates(); 68 | 69 | client.setUserRoots(SECRET_GSM_ROOT_CERTS, SECRET_GSM_ROOT_SIZE); 70 | client.setSignedCertificate(SECRET_CERT, "MKRGSM01", sizeof(SECRET_CERT)); 71 | client.setPrivateKey(SECRET_KEY, "MKRGSMKEY01", sizeof(SECRET_KEY)); 72 | 73 | client.useSignedCertificate("MKRGSM01"); 74 | client.usePrivateKey("MKRGSMKEY01"); 75 | client.setTrustedRoot("Let_s_Encrypt_Authority_X3"); 76 | 77 | 78 | Serial.print("Attempting to connect to the MQTT broker: "); 79 | Serial.println(broker); 80 | 81 | if (!mqttClient.connect(broker, port)) { 82 | 83 | Serial.print("MQTT connection failed! Error code = "); 84 | Serial.println(mqttClient.connectError()); 85 | 86 | while (1); 87 | } 88 | 89 | Serial.println("You're connected to the MQTT broker!"); 90 | Serial.println(); 91 | 92 | 93 | } 94 | 95 | void loop() { 96 | // call poll() regularly to allow the library to send MQTT keep alives which 97 | // avoids being disconnected by the broker 98 | mqttClient.poll(); 99 | 100 | // to avoid having delays in loop, we'll use the strategy from BlinkWithoutDelay 101 | // see: File -> Examples -> 02.Digital -> BlinkWithoutDelay for more info 102 | unsigned long currentMillis = millis(); 103 | 104 | if (currentMillis - previousMillis >= interval) { 105 | // save the last time a message was sent 106 | previousMillis = currentMillis; 107 | 108 | Serial.print("Sending message to topic: "); 109 | Serial.println(topic); 110 | Serial.print("hello "); 111 | Serial.println(count); 112 | 113 | // send message, the Print interface can be used to set the message contents 114 | mqttClient.beginMessage(topic); 115 | mqttClient.print("hello "); 116 | mqttClient.print(count); 117 | if (!mqttClient.endMessage()) { 118 | Serial.println("transmission error"); 119 | } 120 | 121 | Serial.println(); 122 | 123 | count++; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /examples/SendSMS/SendSMS.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SMS sender 3 | 4 | This sketch, for the MKR GSM 1400 board,sends an SMS message 5 | you enter in the Serial Monitor. Connect your Arduino with the 6 | GSM shield and SIM card, open the Serial Monitor, and wait for 7 | the "READY" message to appear in the monitor. Next, type a 8 | message to send and press "return". Make sure the serial 9 | monitor is set to send a newline when you press return. 10 | 11 | Circuit: 12 | * MKR GSM 1400 board 13 | * Antenna 14 | * SIM card that can send SMS 15 | 16 | created 25 Feb 2012 17 | by Tom Igoe 18 | */ 19 | 20 | // Include the GSM library 21 | #include 22 | 23 | #include "arduino_secrets.h" 24 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 25 | // PIN Number 26 | const char PINNUMBER[] = SECRET_PINNUMBER; 27 | 28 | // initialize the library instance 29 | GSM gsmAccess; 30 | GSM_SMS sms; 31 | 32 | void setup() { 33 | // initialize serial communications and wait for port to open: 34 | Serial.begin(9600); 35 | while (!Serial) { 36 | ; // wait for serial port to connect. Needed for native USB port only 37 | } 38 | 39 | Serial.println("SMS Messages Sender"); 40 | 41 | // connection state 42 | bool connected = false; 43 | 44 | // Start GSM shield 45 | // If your SIM has PIN, pass it as a parameter of begin() in quotes 46 | while (!connected) { 47 | if (gsmAccess.begin(PINNUMBER) == GSM_READY) { 48 | connected = true; 49 | } else { 50 | Serial.println("Not connected"); 51 | delay(1000); 52 | } 53 | } 54 | 55 | Serial.println("GSM initialized"); 56 | } 57 | 58 | void loop() { 59 | 60 | Serial.print("Enter a mobile number: "); 61 | char remoteNum[20]; // telephone number to send SMS 62 | readSerial(remoteNum); 63 | Serial.println(remoteNum); 64 | 65 | // SMS text 66 | Serial.print("Now, enter SMS content: "); 67 | char txtMsg[200]; 68 | readSerial(txtMsg); 69 | Serial.println("SENDING"); 70 | Serial.println(); 71 | Serial.println("Message:"); 72 | Serial.println(txtMsg); 73 | 74 | // send the message 75 | sms.beginSMS(remoteNum); 76 | sms.print(txtMsg); 77 | sms.endSMS(); 78 | Serial.println("\nCOMPLETE!\n"); 79 | } 80 | 81 | /* 82 | Read input serial 83 | */ 84 | int readSerial(char result[]) { 85 | int i = 0; 86 | while (1) { 87 | while (Serial.available() > 0) { 88 | char inChar = Serial.read(); 89 | if (inChar == '\n') { 90 | result[i] = '\0'; 91 | Serial.flush(); 92 | return 0; 93 | } 94 | if (inChar != '\r') { 95 | result[i] = inChar; 96 | i++; 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /examples/SendSMS/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | -------------------------------------------------------------------------------- /examples/Tools/BandManagement/BandManagement.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Band Management 3 | 4 | This sketch, for the MKR GSM 1400 board, checks the band 5 | currently configured in the modem and allows you to change 6 | it. 7 | 8 | Please check http://www.worldtimezone.com/gsm.html 9 | Usual configurations: 10 | Europe, Africa, Middle East: E-GSM(900)+DCS(1800) 11 | USA, Canada, South America: GSM(850)+PCS(1900) 12 | Mexico: PCS(1900) 13 | Brazil: GSM(850)+E-GSM(900)+DCS(1800)+PCS(1900) 14 | 15 | 16 | Circuit: 17 | * MKR GSM 1400 board 18 | * Antenna 19 | 20 | created 12 June 2012 21 | by Javier Zorzano, Scott Fitzgerald 22 | */ 23 | 24 | // libraries 25 | #include 26 | 27 | // initialize the library instance 28 | GSMBand band; 29 | 30 | void setup() { 31 | // initialize serial communications and wait for port to open: 32 | Serial.begin(9600); 33 | while (!Serial) { 34 | ; // wait for serial port to connect. Needed for native USB port only 35 | } 36 | 37 | // Beginning the band manager restarts the modem 38 | Serial.println("Restarting modem..."); 39 | band.begin(); 40 | Serial.println("Modem restarted."); 41 | 42 | }; 43 | 44 | 45 | void loop() { 46 | // Get current band 47 | String bandName = band.getBand(); // Get and print band name 48 | Serial.print("Current band:"); 49 | Serial.println(bandName); 50 | Serial.println("Want to change the band you’re on?"); 51 | String newBandName; 52 | newBandName = askUser(); 53 | // Tell the user what we are about to do… 54 | Serial.print("\nConfiguring band "); 55 | Serial.println(newBandName); 56 | // Change the band 57 | bool operationSuccess; 58 | operationSuccess = band.setBand(newBandName); 59 | // Tell the user if the operation was OK 60 | if (operationSuccess) { 61 | Serial.println("Success"); 62 | } else { 63 | Serial.println("Error while changing band"); 64 | } 65 | 66 | if (operationSuccess) { 67 | while (true); 68 | } 69 | } 70 | 71 | // This function offers the user different options 72 | // through the Serial interface 73 | // The user selects one 74 | String askUser() { 75 | String newBand; 76 | Serial.println("Select band:"); 77 | // Print the different options 78 | Serial.println("1 : E-GSM(900)"); 79 | Serial.println("2 : DCS(1800)"); 80 | Serial.println("3 : PCS(1900)"); 81 | Serial.println("4 : E-GSM(900)+DCS(1800) ex: Europe"); 82 | Serial.println("5 : GSM(850)+PCS(1900) Ex: USA, South Am."); 83 | Serial.println("6 : GSM800(800)+GSM(850)+E-GSM(900)+PCS(1900)"); 84 | Serial.println("7 : UMTS(2100)"); 85 | Serial.println("8 : GSM(850)+E-GSM(900)+PCS(1900)+UMTS(2100)"); 86 | 87 | // Empty the incoming buffer 88 | while (Serial.available()) { 89 | Serial.read(); 90 | } 91 | 92 | // Wait for an answer, just look at the first character 93 | while (!Serial.available()); 94 | char c = Serial.read(); 95 | if (c == '1') { 96 | newBand = GSM_MODE_EGSM; 97 | } else if (c == '2') { 98 | newBand = GSM_MODE_DCS; 99 | } else if (c == '3') { 100 | newBand = GSM_MODE_PCS; 101 | } else if (c == '4') { 102 | newBand = GSM_MODE_EGSM_DCS; 103 | } else if (c == '5') { 104 | newBand = GSM_MODE_GSM850_PCS; 105 | } else if (c == '6') { 106 | newBand = GSM_MODE_GSM850_EGSM_DCS_PCS; 107 | } else if (c == '7') { 108 | newBand = GSM_MODE_UMTS; 109 | } else if (c == '8') { 110 | newBand = GSM_MODE_GSM850_EGSM_PCS_UMTS; 111 | } else { 112 | newBand = "GSM_MODE_UNDEFINED"; 113 | } 114 | 115 | return newBand; 116 | } 117 | -------------------------------------------------------------------------------- /examples/Tools/ChooseRadioAccessTechnology/ChooseRadioAccessTechnology.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Radio Access Technology selection for Arduino MKR GSM 1400 3 | 4 | This sketch allows you to select your preferred Radio Access 5 | Technology (RAT). 6 | 7 | You can choose among 2G, 3G/UTMS or a combination of both. 8 | 9 | The chosen configuration will be saved to the modem's internal memory 10 | and will be preserved through MKR GSM 1400 sketch uploads. 11 | 12 | In order to change the RAT, you will need to run this sketch again. 13 | 14 | Circuit: 15 | - MKR GSM 1400 board 16 | - Antenna 17 | - SIM card 18 | 19 | Created 19 August 2019 20 | by Riccardo Rizzo 21 | 22 | */ 23 | 24 | #include 25 | 26 | 27 | void setup() { 28 | Serial.begin(9600); 29 | while (!Serial); 30 | 31 | MODEM.begin(); 32 | while (!MODEM.noop()); 33 | 34 | for (int i = 0; i < 80; i++) Serial.print("*"); 35 | Serial.println(); 36 | Serial.println("This sketch allows you to select your preferred"); 37 | Serial.println("GSM Radio Access Technology (RAT)."); 38 | Serial.println(); 39 | Serial.println("You can choose among 2G, 3G/UMTS or a combination of both."); 40 | Serial.println(); 41 | Serial.println("The chosen configuration will be saved to the modem's internal memory"); 42 | Serial.println("and will be preserved through MKR GSM 1400 sketch uploads."); 43 | Serial.println(); 44 | Serial.println("In order to change the RAT, you will need to run this sketch again."); 45 | for (int i = 0; i < 80; i++) Serial.print("*"); 46 | 47 | Serial.println(); 48 | Serial.println(); 49 | Serial.println("Please choose your Radio Access Technology:"); 50 | Serial.println(); 51 | Serial.println(" 0 - 2G only"); 52 | Serial.println(" 1 - 3G/UMTS only"); 53 | Serial.println(" 2 - 2G preferred, 3G/UMTS as failover"); 54 | Serial.println(" 3 - 3G/UMTS preferred, 2G as failover (default)"); 55 | Serial.println(); 56 | } 57 | 58 | void loop() { 59 | String uratChoice; 60 | 61 | Serial.print("> "); 62 | 63 | Serial.setTimeout(-1); 64 | while (Serial.available() == 0); 65 | String uratInput = Serial.readStringUntil('\n'); 66 | uratInput.trim(); 67 | int urat = uratInput.toInt(); 68 | Serial.println(urat); 69 | 70 | switch (urat) { 71 | case 0: 72 | uratChoice = "0"; 73 | break; 74 | case 1: 75 | uratChoice = "2"; 76 | break; 77 | case 2: 78 | uratChoice = "1,0"; 79 | break; 80 | case 3: 81 | uratChoice = "1,2"; 82 | break; 83 | default: 84 | Serial.println("Invalid input. Please, retry."); 85 | return; 86 | } 87 | 88 | setRAT(uratChoice); 89 | apply(); 90 | 91 | Serial.println(); 92 | Serial.println("Radio Access Technology selected."); 93 | Serial.println("Now you can upload your 2G or 3G application sketch."); 94 | while (true); 95 | } 96 | 97 | bool setRAT(String choice) 98 | { 99 | String response; 100 | 101 | Serial.print("Disconnecting from network: "); 102 | MODEM.sendf("AT+COPS=2"); 103 | MODEM.waitForResponse(10000); 104 | Serial.println("done."); 105 | 106 | Serial.print("Setting Radio Access Technology: "); 107 | MODEM.sendf("AT+URAT=%s", choice.c_str()); 108 | MODEM.waitForResponse(10000, &response); 109 | Serial.println("done."); 110 | 111 | return true; 112 | } 113 | 114 | bool apply() 115 | { 116 | Serial.print("Applying changes and saving configuration: "); 117 | MODEM.reset(); 118 | delay(5000); 119 | Serial.println("Modem restart"); 120 | MODEM.begin(true); 121 | 122 | do { 123 | delay(1000); 124 | MODEM.noop(); 125 | } while (MODEM.waitForResponse(1000) != 1); 126 | 127 | Serial.println("done."); 128 | 129 | return true; 130 | } 131 | -------------------------------------------------------------------------------- /examples/Tools/FileUtilsHttpDownload/FileUtilsHttpDownload.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Download a large file and store it into the GSM module filesystem. 3 | 4 | This sketch connects to a website through a MKR GSM 1400 board and 5 | downloads a large file and stores it into the filesystem of the GSM 6 | module. 7 | 8 | The file is processed in blocks of 512 bytes in order to save RAM. 9 | A block of data is read from the GSM module and the appended to a 10 | file created by the sketch. 11 | 12 | Circuit: 13 | * MKR GSM 1400 board 14 | * Antenna 15 | * SIM card with a data plan 16 | 17 | created 19 June 2020 18 | by Giampaolo Mancini 19 | */ 20 | 21 | // libraries 22 | #include 23 | 24 | GSMFileUtils fileUtils(false); 25 | 26 | #include "Helpers.h" 27 | 28 | #include "arduino_secrets.h" 29 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 30 | // PIN Number 31 | const char PINNUMBER[] = SECRET_PINNUMBER; 32 | // APN data 33 | const char GPRS_APN[] = SECRET_GPRS_APN; 34 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 35 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 36 | 37 | // initialize the library instance 38 | GSMClient client; 39 | GPRS gprs; 40 | GSM gsmAccess; 41 | 42 | // URL, path and port (for example: example.org) 43 | 44 | void setup() 45 | { 46 | // initialize serial communications and wait for port to open: 47 | Serial.begin(9600); 48 | while (!Serial) { 49 | ; // wait for serial port to connect. Needed for native USB port only 50 | } 51 | 52 | Serial.println("Starting Arduino web client."); 53 | 54 | fileUtils.begin(); 55 | 56 | // List files on the GSM module's filesystem 57 | auto numberOfFiles = fileUtils.fileCount(); 58 | Serial.print("Number of Files: "); 59 | Serial.println(numberOfFiles); 60 | Serial.println(); 61 | 62 | printFiles(fileUtils); 63 | 64 | auto server = promptAndReadLine("Please, enter server name:", "arduino.cc"); 65 | auto port = promptAndReadInt("Please, enter server port:", 80); 66 | auto filename = promptAndReadLine("Please, enter file name:", "asciilogo.txt"); 67 | auto filesize = promptAndReadInt("Please, enter file size:", 2263); 68 | Serial.println("Connecting..."); 69 | 70 | // connection state 71 | bool connected = false; 72 | 73 | // After starting the modem with GSM.begin() 74 | // attach the shield to the GPRS network with the APN, login and password 75 | while (!connected) { 76 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 77 | connected = true; 78 | } else { 79 | Serial.println("Not connected"); 80 | delay(1000); 81 | } 82 | } 83 | 84 | // if you get a connection, report back via serial: 85 | if (client.connect(server.c_str(), port)) { 86 | Serial.println("connected"); 87 | // Make a HTTP request: 88 | client.print("GET /"); 89 | client.print(filename); 90 | client.println(" HTTP/1.1"); 91 | client.print("Host: "); 92 | client.println(server); 93 | client.println("Connection: close"); 94 | client.println(); 95 | } else { 96 | // if you didn't get a connection to the server: 97 | Serial.println("Connection failed"); 98 | } 99 | 100 | // Download and store block-by-block 101 | storeFileBuffered(filename, filesize); 102 | 103 | auto updateBinSize = fileUtils.listFile(filename); 104 | Serial.print(filename); 105 | Serial.print(" downloaded size: "); 106 | Serial.println(updateBinSize); 107 | 108 | numberOfFiles = fileUtils.fileCount(); 109 | Serial.print("Number of Files: "); 110 | Serial.println(numberOfFiles); 111 | Serial.println(); 112 | 113 | printFiles(fileUtils); 114 | 115 | } 116 | 117 | void loop() 118 | { 119 | // if there are incoming bytes available 120 | // from the server, read them and print them: 121 | if (client.available()) { 122 | char r = client.read(); 123 | if (r < 16) 124 | Serial.print(0); 125 | Serial.print(r, HEX); 126 | 127 | } 128 | 129 | // if the server's disconnected, stop the client: 130 | if (!client.available() && !client.connected()) { 131 | Serial.println(); 132 | Serial.println("disconnecting."); 133 | client.stop(); 134 | 135 | // do nothing forevermore: 136 | for (;;) 137 | ; 138 | } 139 | } 140 | 141 | void storeFileBuffered(String filename, uint32_t totalLen) 142 | { 143 | Serial.print("Ready to download \""); 144 | Serial.print(filename); 145 | Serial.print("\" - len: "); 146 | Serial.print(totalLen); 147 | Serial.println(" bytes."); 148 | 149 | constexpr uint32_t len { 512 }; 150 | 151 | uint32_t cycles = totalLen / len; 152 | uint32_t spares = totalLen % len; 153 | 154 | int totalRead { 0 }; 155 | 156 | fileUtils.deleteFile(filename); 157 | 158 | Serial.print("Saving file in "); 159 | Serial.print(cycles + 1); 160 | Serial.print(" blocks. ["); 161 | Serial.print(cycles); 162 | Serial.print(' '); 163 | Serial.print(len); 164 | Serial.print(" -bytes blocks and "); 165 | Serial.print(spares); 166 | Serial.println(" bytes]."); 167 | 168 | bool is_header_complete = false; 169 | String http_header; 170 | 171 | // Skip the HTTP header 172 | while (!is_header_complete) { 173 | while (client.available()) { 174 | const char c = client.read(); 175 | http_header += c; 176 | if (http_header.endsWith("\r\n\r\n")) { 177 | Serial.println("Header Complete"); 178 | is_header_complete = true; 179 | break; 180 | } 181 | } 182 | } 183 | 184 | // Define download and save lambda 185 | auto downloadAndSaveTrunk = [filename](uint32_t len) { 186 | char buf[len] { 0 }; 187 | uint32_t written { 0 }; 188 | 189 | if (client.available()) 190 | written = client.readBytes(buf, len); 191 | 192 | fileUtils.appendFile(filename, buf, written); 193 | return written; 194 | }; 195 | 196 | // Define wrapper function 197 | auto saveTrunk = [&totalRead, downloadAndSaveTrunk](size_t iter, uint32_t len) { 198 | Serial.print("Block "); 199 | if (iter < 10) Serial.print(' '); if (iter < 100) Serial.print(' '); 200 | Serial.print(iter); 201 | 202 | totalRead += downloadAndSaveTrunk(len); 203 | 204 | Serial.print(": "); 205 | Serial.print(len); 206 | Serial.print(" - "); 207 | Serial.print(totalRead); 208 | Serial.println(); 209 | }; 210 | 211 | // Download and save complete trunks + spares 212 | for (auto c = 0; c <= cycles; c++) 213 | saveTrunk(c, len); 214 | 215 | Serial.println(); 216 | 217 | } 218 | -------------------------------------------------------------------------------- /examples/Tools/FileUtilsHttpDownload/Helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | String readLine() 5 | { 6 | String line; 7 | 8 | while (1) 9 | { 10 | if (Serial.available()) 11 | { 12 | char c = Serial.read(); 13 | 14 | if (c == '\r') 15 | { 16 | // ignore 17 | } 18 | else if (c == '\n') 19 | { 20 | break; 21 | } 22 | 23 | line += c; 24 | } 25 | } 26 | 27 | line.trim(); 28 | 29 | return line; 30 | } 31 | 32 | String promptAndReadLine(const char* prompt, const char* defaultValue) { 33 | Serial.print(prompt); 34 | Serial.print(" ["); 35 | Serial.print(defaultValue); 36 | Serial.print("]: "); 37 | 38 | String s = readLine(); 39 | 40 | if (s.length() == 0) { 41 | s = defaultValue; 42 | } 43 | 44 | Serial.println(s); 45 | 46 | return s; 47 | } 48 | 49 | int promptAndReadInt(const char* prompt, const int defaultValue) { 50 | Serial.print(prompt); 51 | Serial.print(" ["); 52 | Serial.print(defaultValue); 53 | Serial.print("]: "); 54 | 55 | String s = readLine(); 56 | int r; 57 | 58 | if (s.length() == 0) { 59 | r = defaultValue; 60 | } else { 61 | r = s.toInt(); 62 | } 63 | 64 | Serial.println(r); 65 | 66 | return r; 67 | } 68 | 69 | String promptAndReadLine(const char *prompt) 70 | { 71 | Serial.print(prompt); 72 | String s = readLine(); 73 | Serial.println(s); 74 | 75 | return s; 76 | } 77 | 78 | int promptAndReadInt(const char *prompt) 79 | { 80 | Serial.print(prompt); 81 | String s = readLine(); 82 | Serial.println(s); 83 | 84 | return s.toInt(); 85 | } 86 | 87 | 88 | String toHex(char c) 89 | { 90 | String hex; 91 | 92 | hex = "0x"; 93 | if (c < 16) 94 | hex += "0"; 95 | hex += String(c, HEX); 96 | 97 | return hex; 98 | } 99 | 100 | void printHex(const String& buf, const unsigned int cols) 101 | { 102 | for (size_t i = 0; i < buf.length(); i++) { 103 | String hex = toHex(buf[i]); 104 | hex += " "; 105 | Serial.print(hex); 106 | if (i % cols == (cols - 1)) 107 | Serial.println(); 108 | } 109 | Serial.println(); 110 | } 111 | 112 | void printHex(const uint8_t* buf, const size_t len, const unsigned int cols) 113 | { 114 | for (size_t i = 0; i < len; i++) { 115 | // Serial.print("0x"); 116 | if (buf[i] < 16) 117 | Serial.print(0); 118 | Serial.print(buf[i], HEX); 119 | // if (i != len - 1) Serial.print(", "); 120 | if (i % cols == (cols - 1)) 121 | Serial.println(); 122 | } 123 | Serial.println(); 124 | } 125 | -------------------------------------------------------------------------------- /examples/Tools/FileUtilsHttpDownload/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | #define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN 3 | #define SECRET_GPRS_LOGIN "login" // replace with your GPRS login 4 | #define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password 5 | -------------------------------------------------------------------------------- /examples/Tools/FileUtilsJsonFile/Config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | // Make the struct Printable to allow Serial.print-ing 7 | struct Config : public Printable { 8 | String deviceId; 9 | int timestamp; 10 | 11 | String toJson() 12 | { 13 | JSONVar conf; 14 | 15 | conf["deviceId"] = deviceId.c_str(); 16 | conf["timestamp"] = timestamp; 17 | 18 | return JSON.stringify(conf); 19 | } 20 | 21 | bool fromJSON(const String buf) 22 | { 23 | auto conf = JSON.parse(buf); 24 | 25 | if (!checkProperty(conf, "deviceId", "string")) 26 | return false; 27 | 28 | if (!checkProperty(conf, "timestamp", "number")) 29 | return false; 30 | 31 | const char * c_str_device_id = conf["deviceId"]; 32 | deviceId = String(c_str_device_id); 33 | timestamp = int { conf["timestamp"] }; 34 | 35 | return true; 36 | } 37 | 38 | virtual size_t printTo(Print& p) const 39 | { 40 | size_t written { 0 }; 41 | 42 | written += p.print("DeviceId: "); 43 | written += p.println(deviceId); 44 | written += p.print("Timestamp: "); 45 | written += p.println(timestamp); 46 | 47 | return written; 48 | } 49 | 50 | private: 51 | bool checkProperty(JSONVar json, String property, String type) 52 | { 53 | if (!json.hasOwnProperty(property)) { 54 | Serial.print(property); 55 | Serial.println(" not found"); 56 | return false; 57 | } 58 | 59 | if (JSON.typeof(json[property]) != type) { 60 | Serial.print(property); 61 | Serial.print(" != \""); 62 | Serial.print(type); 63 | Serial.println("\""); 64 | return false; 65 | } 66 | 67 | return true; 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /examples/Tools/FileUtilsJsonFile/FileUtilsJsonFile.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Manage JSON configurations via GSM module filesystem. 3 | 4 | This sketch demonstrates how to use the internal filesystem 5 | of the GSM module to store and retrieve data and configurations 6 | both as JSON objects or C++ structs. 7 | 8 | Circuit: 9 | * MKR GSM 1400 board 10 | 11 | created 19 June 2020 12 | by Giampaolo Mancini 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include "Config.h" 19 | 20 | GSMFileUtils fileUtils; 21 | 22 | void setup() 23 | { 24 | Serial.begin(9600); 25 | 26 | while (!Serial) 27 | ; 28 | 29 | Serial.println("Store and Retrieve JSON data to GSM module storage."); 30 | Serial.println(); 31 | 32 | fileUtils.begin(); 33 | 34 | simpleDemo(); 35 | structDemo(); 36 | 37 | while (true) 38 | ; 39 | } 40 | 41 | void loop() 42 | { 43 | } 44 | 45 | void simpleDemo() 46 | { 47 | 48 | Serial.println(); 49 | Serial.println("========================"); 50 | Serial.println("Running simple JSON demo"); 51 | Serial.println(); 52 | 53 | JSONVar myObject; 54 | 55 | myObject["hello"] = "world"; 56 | myObject["true"] = true; 57 | myObject["x"] = 42; 58 | 59 | String jsonString = JSON.stringify(myObject); 60 | 61 | Serial.println("Saving JSON file (test.json): "); 62 | Serial.println(jsonString); 63 | Serial.println(); 64 | fileUtils.downloadFile("test.json", jsonString); 65 | 66 | printFiles(fileUtils); 67 | Serial.println(); 68 | 69 | String jsonData; 70 | Serial.println("Reading JSON file (test.json): "); 71 | fileUtils.readFile("test.json", &jsonData); 72 | 73 | Serial.println("File contents:"); 74 | Serial.println(jsonData); 75 | Serial.println(); 76 | 77 | Serial.println("Parsing JSON contents:"); 78 | JSONVar myConf = JSON.parse(jsonData); 79 | Serial.print("myConf[\"hello\"]: "); 80 | Serial.println(myConf["hello"]); 81 | Serial.print("myConf[\"true\"]: "); 82 | Serial.println(myConf["true"]); 83 | Serial.print("myConf[\"x\"]: "); 84 | Serial.println(myConf["x"]); 85 | } 86 | 87 | void structDemo() 88 | { 89 | GSMModem modem; 90 | 91 | Serial.println(); 92 | Serial.println("========================"); 93 | Serial.println("Running Configuration via struct and JSON demo"); 94 | Serial.println(); 95 | Serial.println("Creating configuration struct:"); 96 | 97 | Config conf; 98 | conf.deviceId = modem.getICCID(); 99 | conf.timestamp = millis(); 100 | 101 | Serial.print(conf); 102 | 103 | fileUtils.downloadFile("conf.json", conf.toJson()); 104 | 105 | Serial.println(); 106 | printFiles(fileUtils); 107 | Serial.println(); 108 | 109 | Serial.println("Reading configuration file:"); 110 | 111 | String jsonConf; 112 | fileUtils.readFile("conf.json", &jsonConf); 113 | Serial.println(jsonConf); 114 | Serial.println(); 115 | 116 | Serial.println("Reading configuration struct:"); 117 | Config newConf; 118 | newConf.fromJSON(jsonConf); 119 | 120 | Serial.print(newConf); 121 | } 122 | -------------------------------------------------------------------------------- /examples/Tools/FileUtilsReadBlock/FileUtilsReadBlock.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Read large files block-by-block from the GSM module filesystem. 3 | 4 | This sketch allows you to read large (max 2.5 MB) files from the 5 | module's internal filesystem using successive block-by-block reads. 6 | 7 | The contents of the file are printed to the Serial port as an 8 | hexadecimal string which can be later converted to the original 9 | content using an external tool, such as 'xxd', eg. 10 | 11 | 'xxd -p -r sketch_output.txt data.bin' 12 | 13 | Circuit: 14 | - MKR GSM 1400 board 15 | 16 | Created 19 June 2020 17 | by Giampaolo Mancini 18 | 19 | */ 20 | 21 | #include 22 | 23 | GSMFileUtils fileUtils(false); 24 | 25 | // An existing file 26 | constexpr char* filename { "update.bin" }; 27 | 28 | // Read block size 29 | constexpr unsigned int blockSize { 512 }; 30 | 31 | void setup() 32 | { 33 | Serial.begin(115200); 34 | while (!Serial) 35 | ; 36 | 37 | fileUtils.begin(); 38 | 39 | auto size = fileUtils.listFile(filename); 40 | auto cycles = (size / blockSize) + 1; 41 | 42 | uint32_t totalRead { 0 }; 43 | 44 | for (auto i = 0; i < cycles; i++) { 45 | uint8_t block[blockSize] { 0 }; 46 | auto read = fileUtils.readBlock(filename, i * blockSize, blockSize, block); 47 | totalRead += read; 48 | for (auto j = 0; j < read; j++) { 49 | if (block[j] < 16) 50 | Serial.print(0); 51 | Serial.print(block[j], HEX); 52 | } 53 | Serial.println(); 54 | } 55 | 56 | if (totalRead != size) { 57 | Serial.print("ERROR - File size: "); 58 | Serial.print(size); 59 | Serial.print(" Bytes read: "); 60 | Serial.println(totalRead); 61 | } 62 | } 63 | 64 | void loop() 65 | { 66 | } 67 | -------------------------------------------------------------------------------- /examples/Tools/GsmScanNetworks/GsmScanNetworks.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | GSM Scan Networks 4 | 5 | This example prints out the IMEI number of the modem, 6 | then checks to see if it's connected to a carrier. If so, 7 | it prints the phone number associated with the card. 8 | Then it scans for nearby networks and prints out their signal strengths. 9 | 10 | Circuit: 11 | * MKR GSM 1400 board 12 | * Antenna 13 | * SIM card 14 | 15 | Created 8 Mar 2012 16 | by Tom Igoe, implemented by Javier Carazo 17 | Modified 4 Feb 2013 18 | by Scott Fitzgerald 19 | */ 20 | 21 | // libraries 22 | #include 23 | 24 | #include "arduino_secrets.h" 25 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 26 | // PIN Number 27 | const char PINNUMBER[] = SECRET_PINNUMBER; 28 | 29 | // initialize the library instance 30 | GSM gsmAccess; // include a 'true' parameter to enable debugging 31 | GSMScanner scannerNetworks; 32 | GSMModem modemTest; 33 | 34 | // Save data variables 35 | String IMEI = ""; 36 | 37 | // Serial Monitor result messages 38 | String errortext = "ERROR"; 39 | 40 | void setup() { 41 | // initialize serial communications and wait for port to open: 42 | Serial.begin(9600); 43 | while (!Serial) { 44 | ; // wait for serial port to connect. Needed for native USB port only 45 | } 46 | 47 | Serial.println("GSM networks scanner"); 48 | scannerNetworks.begin(); 49 | 50 | // connection state 51 | bool connected = false; 52 | 53 | // Start GSM shield 54 | // If your SIM has PIN, pass it as a parameter of begin() in quotes 55 | while (!connected) { 56 | if (gsmAccess.begin(PINNUMBER) == GSM_READY) { 57 | connected = true; 58 | } else { 59 | Serial.println("Not connected"); 60 | delay(1000); 61 | } 62 | } 63 | 64 | // get modem parameters 65 | // IMEI, modem unique identifier 66 | Serial.print("Modem IMEI: "); 67 | IMEI = modemTest.getIMEI(); 68 | IMEI.replace("\n", ""); 69 | if (IMEI != NULL) { 70 | Serial.println(IMEI); 71 | } 72 | } 73 | 74 | void loop() { 75 | // scan for existing networks, displays a list of networks 76 | Serial.println("Scanning available networks. May take some seconds."); 77 | Serial.println(scannerNetworks.readNetworks()); 78 | 79 | // currently connected carrier 80 | Serial.print("Current carrier: "); 81 | Serial.println(scannerNetworks.getCurrentCarrier()); 82 | 83 | // returns strength and BER 84 | // signal strength in 0-31 scale. 31 means power > 51 dBm 85 | // BER is the Bit Error Rate. 0-7 scale. 99=not detectable 86 | Serial.print("Signal Strength: "); 87 | Serial.print(scannerNetworks.getSignalStrength()); 88 | Serial.println(" [0-31]"); 89 | 90 | } 91 | -------------------------------------------------------------------------------- /examples/Tools/GsmScanNetworks/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | -------------------------------------------------------------------------------- /examples/Tools/HttpUtilsGet/HttpUtilsGet.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch shows how to use the HTTP command to 3 | make an HTTP request and store the result in the 4 | SARA-U201 internal storage 5 | 6 | Circuit: 7 | - MKR GSM 1400 board 8 | 9 | Created 3 September 2020 10 | by Riccardo Rizzo 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include "arduino_secrets.h" 17 | 18 | 19 | const char PINNUMBER[] = SECRET_PINNUMBER; 20 | // APN data 21 | const char GPRS_APN[] = SECRET_GPRS_APN; 22 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 23 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 24 | 25 | // initialize the library instance 26 | GSMHttpUtils httpClient; 27 | GPRS gprs; 28 | GSM gsmAccess; 29 | 30 | GSMFileUtils fileUtils(false); 31 | 32 | // URL, path and port (for example: example.org) 33 | char server[] = "example.org"; 34 | char path[] = "/"; 35 | int port = 80; // port 80 is the default for HTTP 36 | 37 | // An existing file 38 | constexpr char* filename { "get.ffs" }; 39 | 40 | // Read block size 41 | constexpr unsigned int blockSize { 512 }; 42 | 43 | 44 | const long interval = 1000; 45 | unsigned long previousMillis = 0; 46 | 47 | int count = 0; 48 | 49 | void setup() { 50 | //Initialize serial and wait for port to open: 51 | Serial.begin(9600); 52 | while (!Serial) { 53 | ; // wait for serial port to connect. Needed for native USB port only 54 | } 55 | 56 | bool connected = false; 57 | // After starting the modem with GSM.begin() 58 | // attach the shield to the GPRS network with the APN, login and password 59 | while (!connected) { 60 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 61 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 62 | connected = true; 63 | } else { 64 | Serial.println("Not connected"); 65 | delay(1000); 66 | } 67 | } 68 | fileUtils.begin(false); 69 | 70 | // configure all the parameters to make the http request 71 | httpClient.configServer(server, port); 72 | httpClient.get(path, filename); 73 | } 74 | 75 | void loop() { 76 | if (httpClient.responseStatus()) { 77 | Serial.println("received"); 78 | String fileList[10]; 79 | auto size = fileUtils.listFiles(fileList); 80 | for (int i = 0; i < size && i <10; i++) { 81 | if (fileList[i] == filename) { 82 | Serial.print("file found: "); 83 | Serial.println(fileList[i]); 84 | } 85 | } 86 | while (1); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /examples/Tools/HttpUtilsGet/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // GSM settings 2 | #define SECRET_PINNUMBER "" 3 | #define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN 4 | #define SECRET_GPRS_LOGIN "login" // replace with your GPRS login 5 | #define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password 6 | -------------------------------------------------------------------------------- /examples/Tools/HttpUtilsSSLGet/HttpUtilsSSLGet.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch shows how to use the HTTP command to 3 | make an HTTP request to the HTTPS end point and store 4 | the result in the SARA-U201 internal storage 5 | 6 | Circuit: 7 | - MKR GSM 1400 board 8 | 9 | Created 3 September 2020 10 | by Riccardo Rizzo 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include "arduino_secrets.h" 17 | 18 | 19 | const char PINNUMBER[] = SECRET_PINNUMBER; 20 | // APN data 21 | const char GPRS_APN[] = SECRET_GPRS_APN; 22 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 23 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 24 | 25 | // initialize the library instance 26 | GSMHttpUtils httpClient; 27 | GPRS gprs; 28 | GSM gsmAccess; 29 | 30 | GSMFileUtils fileUtils(false); 31 | 32 | // URL, path and port (for example: example.org) 33 | char server[] = "google.com"; 34 | char path[] = "/"; 35 | int port = 443; // port 80 is the default for HTTP 36 | 37 | // An existing file 38 | constexpr char* filename { "get.ffs" }; 39 | 40 | 41 | // Read block size 42 | constexpr unsigned int blockSize { 512 }; 43 | 44 | 45 | const long interval = 1000; 46 | unsigned long previousMillis = 0; 47 | 48 | int count = 0; 49 | 50 | void readFile(); 51 | 52 | void setup() { 53 | //Initialize serial and wait for port to open: 54 | Serial.begin(9600); 55 | while (!Serial) { 56 | ; // wait for serial port to connect. Needed for native USB port only 57 | } 58 | 59 | bool connected = false; 60 | // After starting the modem with GSM.begin() 61 | // attach the shield to the GPRS network with the APN, login and password 62 | while (!connected) { 63 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 64 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 65 | connected = true; 66 | } else { 67 | Serial.println("Not connected"); 68 | delay(1000); 69 | } 70 | } 71 | fileUtils.begin(false); 72 | 73 | httpClient.enableSSL(); 74 | httpClient.configServer(server, port); 75 | httpClient.get(path, filename); 76 | } 77 | 78 | void loop() { 79 | if (httpClient.responseStatus()) { 80 | Serial.println("received"); 81 | 82 | readFile(); 83 | while (1); 84 | } 85 | } 86 | 87 | void readFile() { 88 | String fileList[10]; 89 | auto size = fileUtils.listFiles(fileList); 90 | for (int i = 0; i < size && i <10; i++) { 91 | if (fileList[i] == filename) { 92 | Serial.print("file found: "); 93 | Serial.println(fileList[i]); 94 | } 95 | 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /examples/Tools/PinManagement/PinManagement.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This example enables you to change or remove the PIN number of 4 | a SIM card inserted into a GSM shield. 5 | 6 | Circuit: 7 | * MKR GSM 1400 board 8 | * Antenna 9 | * SIM card 10 | 11 | Created 12 Jun 2012 12 | by David del Peral 13 | */ 14 | 15 | // libraries 16 | #include 17 | 18 | // pin manager object 19 | GSMPIN PINManager; 20 | 21 | // save input in serial by user 22 | String user_input = ""; 23 | 24 | // authenticated with PIN code 25 | bool auth = false; 26 | 27 | // Serial Monitor result messages 28 | String oktext = "OK"; 29 | String errortext = "ERROR"; 30 | 31 | void setup() { 32 | // initialize serial communications and wait for port to open: 33 | Serial.begin(9600); 34 | while (!Serial) { 35 | ; // wait for serial port to connect. Needed for native USB port only 36 | } 37 | 38 | Serial.println("Change PIN example\n"); 39 | PINManager.begin(); 40 | 41 | // check if the SIM has pin lock 42 | while (!auth) { 43 | int pin_query = PINManager.isPIN(); 44 | if (pin_query == 1) { 45 | // if SIM is locked, enter PIN code 46 | Serial.print("Enter PIN code: "); 47 | user_input = readSerial(); 48 | // check PIN code 49 | if (PINManager.checkPIN(user_input) == 0) { 50 | auth = true; 51 | PINManager.setPINUsed(true); 52 | Serial.println(oktext); 53 | } else { 54 | // if PIN code was incorrect 55 | Serial.println("Incorrect PIN. Remember that you have 3 opportunities."); 56 | } 57 | } else if (pin_query == -1) { 58 | // PIN code is locked, user must enter PUK code 59 | Serial.println("PIN locked. Enter PUK code: "); 60 | String puk = readSerial(); 61 | Serial.print("Now, enter a new PIN code: "); 62 | user_input = readSerial(); 63 | // check PUK code 64 | if (PINManager.checkPUK(puk, user_input) == 0) { 65 | auth = true; 66 | PINManager.setPINUsed(true); 67 | Serial.println(oktext); 68 | } else { 69 | // if PUK or the new PIN are incorrect 70 | Serial.println("Incorrect PUK or invalid new PIN. Try again!."); 71 | } 72 | } else if (pin_query == -2) { 73 | // the worst case, PIN and PUK are locked 74 | Serial.println("PIN and PUK locked. Use PIN2/PUK2 in a mobile phone."); 75 | while (true); 76 | } else { 77 | // SIM does not require authentication 78 | Serial.println("No pin necessary."); 79 | auth = true; 80 | } 81 | } 82 | 83 | // start GSM shield 84 | Serial.print("Checking register in GSM network..."); 85 | if (PINManager.checkReg() == 0) { 86 | Serial.println(oktext); 87 | } 88 | // if you are connected by roaming 89 | else if (PINManager.checkReg() == 1) { 90 | Serial.println("ROAMING " + oktext); 91 | } else { 92 | // error connection 93 | Serial.println(errortext); 94 | while (true); 95 | } 96 | } 97 | 98 | void loop() { 99 | // Function loop implements pin management user menu 100 | // Only if your SIM uses pin lock can you change the PIN code 101 | // user_op variables save user option 102 | 103 | Serial.println("Choose an option:\n1 - On/Off PIN."); 104 | if (PINManager.getPINUsed()) { 105 | Serial.println("2 - Change PIN."); 106 | } 107 | String user_op = readSerial(); 108 | if (user_op == "1") { 109 | Serial.println("Enter your PIN code:"); 110 | user_input = readSerial(); 111 | // activate/deactivate PIN lock 112 | PINManager.switchPIN(user_input); 113 | } else if (user_op == "2" && PINManager.getPINUsed()) { 114 | Serial.println("Enter your actual PIN code:"); 115 | String oldPIN = readSerial(); 116 | Serial.println("Now, enter your new PIN code:"); 117 | String newPIN = readSerial(); 118 | // change PIN 119 | PINManager.changePIN(oldPIN, newPIN); 120 | } else { 121 | Serial.println("Incorrect option. Try again!."); 122 | } 123 | delay(1000); 124 | } 125 | 126 | /* 127 | Read input serial 128 | */ 129 | String readSerial() { 130 | String text = ""; 131 | while (1) { 132 | while (Serial.available() > 0) { 133 | char inChar = Serial.read(); 134 | if (inChar == '\n') { 135 | return text; 136 | } 137 | if (inChar != '\r') { 138 | text += inChar; 139 | } 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /examples/Tools/SerialGSMPassthrough/SerialGSMPassthrough.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SerialGSMPassthrough sketch 3 | 4 | This sketch allows you to send AT commands from the USB CDC serial port 5 | of the MKR GSM 1400 board to the onboard u-blox SARA-U201 celluar module. 6 | 7 | For a list of supported AT commands see: 8 | https://www.u-blox.com/sites/default/files/u-blox-CEL_ATCommands_%28UBX-13002752%29.pdf 9 | 10 | Circuit: 11 | - MKR GSM 1400 board 12 | - Antenna 13 | - 1500 mAh or higher LiPo battery connected 14 | - SIM card 15 | 16 | Make sure the Serial Monitor's line ending is set to "Both NL and CR" 17 | 18 | create 11 December 2017 19 | Sandeep Mistry 20 | */ 21 | 22 | // baud rate used for both Serial ports 23 | unsigned long baud = 115200; 24 | 25 | void setup() { 26 | // reset the u-blox module 27 | pinMode(GSM_RESETN, OUTPUT); 28 | digitalWrite(GSM_RESETN, HIGH); 29 | delay(100); 30 | digitalWrite(GSM_RESETN, LOW); 31 | 32 | Serial.begin(baud); 33 | SerialGSM.begin(baud); 34 | } 35 | 36 | void loop() { 37 | if (Serial.available()) { 38 | SerialGSM.write(Serial.read()); 39 | } 40 | 41 | if (SerialGSM.available()) { 42 | Serial.write(SerialGSM.read()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/Tools/TestGPRS/TestGPRS.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This sketch tests the MKR GSM 1400 board's ability to connect to a 4 | GPRS network. It asks for APN information through the 5 | Serial Monitor and tries to connect to example.org. 6 | 7 | Circuit: 8 | * MKR GSM 1400 board 9 | * Antenna 10 | * SIM card with data plan 11 | 12 | Created 18 Jun 2012 13 | by David del Peral 14 | */ 15 | 16 | // libraries 17 | #include 18 | 19 | #include "arduino_secrets.h" 20 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 21 | // PIN Number 22 | const char PINNUMBER[] = SECRET_PINNUMBER; 23 | 24 | // initialize the library instance 25 | GSM gsmAccess; // GSM access: include a 'true' parameter for debug enabled 26 | GPRS gprsAccess; // GPRS access 27 | GSMClient client; // Client service for TCP connection 28 | 29 | // messages for Serial Monitor response 30 | String oktext = "OK"; 31 | String errortext = "ERROR"; 32 | 33 | // URL and path (for example: example.org) 34 | char url[] = "example.org"; 35 | char urlproxy[] = "http://www.example.org"; 36 | char path[] = "/"; 37 | 38 | // variable for save response obtained 39 | String response = ""; 40 | 41 | // use a proxy 42 | bool use_proxy = false; 43 | 44 | void setup() { 45 | // initialize serial communications and wait for port to open: 46 | Serial.begin(9600); 47 | while (!Serial) { 48 | ; // wait for serial port to connect. Needed for native USB port only 49 | } 50 | } 51 | 52 | void loop() { 53 | use_proxy = false; 54 | 55 | // start GSM shield 56 | // if your SIM has PIN, pass it as a parameter of begin() in quotes 57 | Serial.print("Connecting GSM network..."); 58 | if (gsmAccess.begin(PINNUMBER) != GSM_READY) { 59 | Serial.println(errortext); 60 | while (true); 61 | } 62 | Serial.println(oktext); 63 | 64 | // read APN introduced by user 65 | char apn[50]; 66 | Serial.print("Enter your APN: "); 67 | readSerial(apn); 68 | Serial.println(apn); 69 | 70 | // Read APN login introduced by user 71 | char login[50]; 72 | Serial.print("Now, enter your login: "); 73 | readSerial(login); 74 | Serial.println(login); 75 | 76 | // read APN password introduced by user 77 | char password[20]; 78 | Serial.print("Finally, enter your password: "); 79 | readSerial(password); 80 | 81 | // attach GPRS 82 | Serial.println("Attaching to GPRS with your APN..."); 83 | if (gprsAccess.attachGPRS(apn, login, password) != GPRS_READY) { 84 | Serial.println(errortext); 85 | } else { 86 | 87 | Serial.println(oktext); 88 | 89 | // read proxy introduced by user 90 | char proxy[100]; 91 | Serial.print("If your carrier uses a proxy, enter it, if not press enter: "); 92 | readSerial(proxy); 93 | Serial.println(proxy); 94 | 95 | // if user introduced a proxy, asks them for proxy port 96 | int pport; 97 | if (proxy[0] != '\0') { 98 | // read proxy port introduced by user 99 | char proxyport[10]; 100 | Serial.print("Enter the proxy port: "); 101 | readSerial(proxyport); 102 | // cast proxy port introduced to integer 103 | pport = (int) proxyport; 104 | use_proxy = true; 105 | Serial.println(proxyport); 106 | } 107 | 108 | // connection with example.org and realize HTTP request 109 | Serial.print("Connecting and sending GET request to example.org..."); 110 | int res_connect; 111 | 112 | // if using a proxy, connect with it 113 | if (use_proxy) { 114 | res_connect = client.connect(proxy, pport); 115 | } else { 116 | res_connect = client.connect(url, 80); 117 | } 118 | 119 | if (res_connect) { 120 | // make a HTTP 1.0 GET request (client sends the request) 121 | client.print("GET "); 122 | 123 | // if using a proxy, the path is the example.org URL 124 | if (use_proxy) { 125 | client.print(urlproxy); 126 | } else { 127 | client.print(path); 128 | } 129 | 130 | client.println(" HTTP/1.0"); 131 | client.println(); 132 | Serial.println(oktext); 133 | } else { 134 | // if you didn't get a connection to the server 135 | Serial.println(errortext); 136 | } 137 | Serial.print("Receiving response..."); 138 | 139 | bool test = true; 140 | while (test) { 141 | // if there are incoming bytes available 142 | // from the server, read and check them 143 | if (client.available()) { 144 | char c = client.read(); 145 | response += c; 146 | 147 | // cast response obtained from string to char array 148 | char responsechar[response.length() + 1]; 149 | response.toCharArray(responsechar, response.length() + 1); 150 | 151 | // if response includes a "200 OK" substring 152 | if (strstr(responsechar, "200 OK") != NULL) { 153 | Serial.println(oktext); 154 | Serial.println("TEST COMPLETE!"); 155 | test = false; 156 | } 157 | } 158 | 159 | // if the server's disconnected, stop the client: 160 | if (!client.connected()) { 161 | Serial.println(); 162 | Serial.println("disconnecting."); 163 | client.stop(); 164 | test = false; 165 | } 166 | } 167 | } 168 | } 169 | 170 | /* 171 | Read input serial 172 | */ 173 | int readSerial(char result[]) { 174 | int i = 0; 175 | while (1) { 176 | while (Serial.available() > 0) { 177 | char inChar = Serial.read(); 178 | if (inChar == '\n') { 179 | result[i] = '\0'; 180 | return 0; 181 | } 182 | if (inChar != '\r') { 183 | result[i] = inChar; 184 | i++; 185 | } 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /examples/Tools/TestGPRS/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | -------------------------------------------------------------------------------- /examples/Tools/TestModem/TestModem.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This example tests to see if the modem of the 4 | MKR GSM 1400 board is working correctly. You do not need 5 | a SIM card for this example. 6 | 7 | Circuit: 8 | * MKR GSM 1400 board 9 | * Antenna 10 | 11 | Created 12 Jun 2012 12 | by David del Peral 13 | modified 21 Nov 2012 14 | by Tom Igoe 15 | */ 16 | 17 | // libraries 18 | #include 19 | 20 | // modem verification object 21 | GSMModem modem; 22 | 23 | // IMEI variable 24 | String IMEI = ""; 25 | 26 | void setup() { 27 | // initialize serial communications and wait for port to open: 28 | Serial.begin(9600); 29 | while (!Serial) { 30 | ; // wait for serial port to connect. Needed for native USB port only 31 | } 32 | 33 | // start modem test (reset and check response) 34 | Serial.print("Starting modem test..."); 35 | if (modem.begin()) { 36 | Serial.println("modem.begin() succeeded"); 37 | } else { 38 | Serial.println("ERROR, no modem answer."); 39 | } 40 | } 41 | 42 | void loop() { 43 | // get modem IMEI 44 | Serial.print("Checking IMEI..."); 45 | IMEI = modem.getIMEI(); 46 | 47 | // check IMEI response 48 | if (IMEI != NULL) { 49 | // show IMEI in Serial Monitor 50 | Serial.println("Modem's IMEI: " + IMEI); 51 | // reset modem to check booting: 52 | Serial.print("Resetting modem..."); 53 | modem.begin(); 54 | // get and check IMEI one more time 55 | if (modem.getIMEI() != NULL) { 56 | Serial.println("Modem is functioning properly"); 57 | } else { 58 | Serial.println("Error: getIMEI() failed after modem.begin()"); 59 | } 60 | } else { 61 | Serial.println("Error: Could not get IMEI"); 62 | } 63 | // do nothing: 64 | while (true); 65 | } 66 | -------------------------------------------------------------------------------- /examples/Tools/TestWebServer/TestWebServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Basic Web Server 3 | 4 | A simple web server that replies with nothing, but prints the client's request 5 | and the server IP address. 6 | 7 | Circuit: 8 | * MKR GSM 1400 board 9 | * Antenna 10 | 11 | created 12 | by David Cuartielles 13 | modified 21 Nov 2012 14 | by Tom Igoe 15 | */ 16 | #include 17 | 18 | #include "arduino_secrets.h" 19 | // Please enter your sensitive data in the Secret tab or arduino_secrets.h 20 | // PIN Number 21 | const char PINNUMBER[] = SECRET_PINNUMBER; 22 | // APN data 23 | const char GPRS_APN[] = SECRET_GPRS_APN; 24 | const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN; 25 | const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD; 26 | 27 | 28 | // initialize the library instance 29 | GPRS gprs; 30 | GSM gsmAccess; // include a 'true' parameter for debug enabled 31 | GSMServer server(80); // port 80 (http default) 32 | 33 | // timeout 34 | const unsigned long __TIMEOUT__ = 10 * 1000; 35 | 36 | void setup() { 37 | // initialize serial communications and wait for port to open: 38 | Serial.begin(9600); 39 | while (!Serial) { 40 | ; // wait for serial port to connect. Needed for native USB port only 41 | } 42 | 43 | Serial.println("starting,.."); 44 | // connection state 45 | bool connected = false; 46 | 47 | // Start GSM shield 48 | // If your SIM has PIN, pass it as a parameter of begin() in quotes 49 | while (!connected) { 50 | if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && 51 | (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) { 52 | connected = true; 53 | } else { 54 | Serial.println("Not connected"); 55 | delay(1000); 56 | } 57 | } 58 | 59 | Serial.println("Connected to GPRS network"); 60 | 61 | // start server 62 | server.begin(); 63 | 64 | //Get IP. 65 | IPAddress LocalIP = gprs.getIPAddress(); 66 | Serial.println("Server IP address="); 67 | Serial.println(LocalIP); 68 | } 69 | 70 | void loop() { 71 | GSMClient client = server.available(); 72 | 73 | if (client) { 74 | if (client.available()) { 75 | Serial.write(client.read()); 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /examples/Tools/TestWebServer/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_PINNUMBER "" 2 | #define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN 3 | #define SECRET_GPRS_LOGIN "login" // replace with your GPRS login 4 | #define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password 5 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For MKRGSM 3 | ####################################### 4 | # Class 5 | ####################################### 6 | 7 | MKRGSM KEYWORD1 8 | GSM KEYWORD1 9 | GSMVoiceCall KEYWORD1 10 | GSM_SMS KEYWORD1 11 | GPRS KEYWORD1 12 | GSMClient KEYWORD1 13 | GSMServer KEYWORD1 14 | GSMModem KEYWORD1 15 | GSMScanner KEYWORD1 16 | GSMPIN KEYWORD1 17 | GSMBand KEYWORD1 18 | GSMSSLClient KEYWORD1 19 | GSMUdp KEYWORD1 20 | GSMLocation KEYWORD1 21 | 22 | ####################################### 23 | # Methods and Functions 24 | ####################################### 25 | 26 | begin KEYWORD2 27 | shutdown KEYWORD2 28 | gatVoiceCallStatus KEYWORD2 29 | ready KEYWORD2 30 | setTimeout KEYWORD2 31 | voiceCall KEYWORD2 32 | answerCall KEYWORD2 33 | hangCall KEYWORD2 34 | retrieveCallingNumber KEYWORD2 35 | beginSMS KEYWORD2 36 | endSMS KEYWORD2 37 | remoteNumber KEYWORD2 38 | attachGPRS KEYWORD2 39 | begnWrite KEYWORD2 40 | endWrite KEYWORD2 41 | getIMEI KEYWORD2 42 | getICCID KEYWORD2 43 | getCurrentCarrier KEYWORD2 44 | getSignalStrength KEYWORD2 45 | readNetworks KEYWORD2 46 | isPIN KEYWORD2 47 | checkPIN KEYWORD2 48 | checkPUK KEYWORD2 49 | changePIN KEYWORD2 50 | switchPIN KEYWORD2 51 | checkReg KEYWORD2 52 | getPINUsed KEYWORD2 53 | setPINUsed KEYWORD2 54 | getBand KEYWORD2 55 | setBand KEYWORD2 56 | getvoiceCallStatus KEYWORD2 57 | hostByName KEYWORD2 58 | ping KEYWORD2 59 | getTime KEYWORD2 60 | getLocalTime KEYWORD2 61 | lowPowerMode KEYWORD2 62 | noLowPowerMode KEYWORD2 63 | peekDTMF KEYWORD2 64 | readDTMF KEYWORD2 65 | writeDTMF KEYWORD2 66 | enableI2SInput KEYWORD2 67 | disableI2SInput KEYWORD2 68 | latitude KEYWORD2 69 | longitude KEYWORD2 70 | altitude KEYWORD2 71 | accuracy KEYWORD2 72 | 73 | ####################################### 74 | # Constants 75 | ####################################### 76 | 77 | ERROR LITERAL1 78 | IDLE LITERAL1 79 | CONNECTING LITERAL1 80 | GSM_READY LITERAL1 81 | GPRS_READY LITERAL1 82 | TRANSPARENT_CONNECTED LITERAL1 83 | IDLE_CALL LITERAL1 84 | CALLING LITERAL1 85 | RECEIVINGCALL LITERAL1 86 | TALKING LITERAL1 87 | GSM_MODE_UNDEFINED LITERAL1 88 | GSM_MODE_EGSM LITERAL1 89 | GSM_MODE_DCS LITERAL1 90 | GSM_MODE_PCS LITERAL1 91 | GSM_MODE_EGSM_DCS LITERAL1 92 | GSM_MODE_GSM850_PCS LITERAL1 93 | GSM_MODE_GSM850_EGSM_DCS_PCS LITERAL1 94 | GSM_MODE_UMTS LITERAL1 95 | GSM_MODE_GSM850_EGSM_PCS_UMTS LITERAL1 96 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=MKRGSM 2 | version=1.5.0 3 | author=Arduino 4 | maintainer=Arduino 5 | sentence=Enables GSM/GRPS network connection using the Arduino MKR GSM 1400 board. 6 | paragraph=Use this library to make/receive voice calls, to send and receive SMS with the u-blox SARA-U201 module.
This library also allows you to connect to internet through the GPRS networks. You can use web Clients and Servers.
7 | category=Communication 8 | url=http://www.arduino.cc/en/Reference/MKRGSM 9 | architectures=samd 10 | includes=MKRGSM.h 11 | -------------------------------------------------------------------------------- /src/GPRS.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GPRS_H_INCLUDED 21 | #define _GPRS_H_INCLUDED 22 | 23 | #include 24 | #include "GSM.h" 25 | 26 | #include "Modem.h" 27 | 28 | enum { 29 | GPRS_PING_DEST_UNREACHABLE = -1, 30 | GPRS_PING_TIMEOUT = -2, 31 | GPRS_PING_UNKNOWN_HOST = -3, 32 | GPRS_PING_ERROR = -4 33 | }; 34 | 35 | class GPRS : public ModemUrcHandler { 36 | 37 | public: 38 | 39 | GPRS(); 40 | virtual ~GPRS(); 41 | 42 | /** Attach to GPRS/GSM network 43 | @param networkId APN GPRS 44 | @param user Username 45 | @param pass Password 46 | @return connection status 47 | */ 48 | GSM3_NetworkStatus_t networkAttach(char* networkId, char* user, char* pass) 49 | { 50 | return attachGPRS(networkId, user, pass); 51 | }; 52 | 53 | /** Detach GPRS/GSM network 54 | @return connection status 55 | */ 56 | GSM3_NetworkStatus_t networkDetach(){ return detachGPRS(); }; 57 | 58 | /** Attach to GPRS service 59 | @param apn APN GPRS 60 | @param user_name Username 61 | @param password Password 62 | @param synchronous Sync mode 63 | @return connection status 64 | */ 65 | GSM3_NetworkStatus_t attachGPRS(const char* apn, const char* user_name, const char* password, bool synchronous = true); 66 | 67 | /** Detach GPRS service 68 | @param synchronous Sync mode 69 | @return connection status 70 | */ 71 | GSM3_NetworkStatus_t detachGPRS(bool synchronous = true); 72 | 73 | /** Returns 0 if last command is still executing 74 | @return 1 if success, >1 if error 75 | */ 76 | int ready(); 77 | 78 | /** Get actual assigned IP address in IPAddress format 79 | @return IP address in IPAddress format 80 | */ 81 | IPAddress getIPAddress(); 82 | 83 | void setTimeout(unsigned long timeout); 84 | 85 | int hostByName(const char* hostname, IPAddress& result); 86 | int hostByName(const String &hostname, IPAddress& result) { return hostByName(hostname.c_str(), result); } 87 | 88 | int ping(const char* hostname, uint8_t ttl = 128); 89 | int ping(const String& hostname, uint8_t ttl = 128); 90 | int ping(IPAddress ip, uint8_t ttl = 128); 91 | 92 | GSM3_NetworkStatus_t status(); 93 | 94 | void handleUrc(const String& urc); 95 | 96 | private: 97 | const char* _apn; 98 | const char* _username; 99 | const char* _password; 100 | int _state; 101 | GSM3_NetworkStatus_t _status; 102 | String _response; 103 | int _pingResult; 104 | unsigned long _timeout; 105 | }; 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /src/GSM.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_H_INCLUDED 21 | #define _GSM_H_INCLUDED 22 | 23 | #include 24 | 25 | enum GSM3_NetworkStatus_t { ERROR, IDLE, CONNECTING, GSM_READY, GPRS_READY, TRANSPARENT_CONNECTED, GSM_OFF}; 26 | 27 | class GSM { 28 | 29 | public: 30 | /** Constructor 31 | @param debug Determines debug mode 32 | */ 33 | GSM(bool debug = false); 34 | 35 | /** Start the GSM/GPRS modem, attaching to the GSM network 36 | @param pin SIM PIN number (4 digits in a string, example: "1234"). If 37 | NULL the SIM has no configured PIN. 38 | @param restart Restart the modem. Default is TRUE. The modem receives 39 | a signal through the Ctrl/D7 pin. If it is shut down, it will 40 | start-up. If it is running, it will restart. Takes up to 10 41 | seconds 42 | @param synchronous If TRUE the call only returns after the Start is complete 43 | or fails. If FALSE the call will return immediately. You have 44 | to call repeatedly ready() until you get a result. Default is TRUE. 45 | @return If synchronous, GSM3_NetworkStatus_t. If asynchronous, returns 0. 46 | */ 47 | GSM3_NetworkStatus_t begin(const char* pin = 0, bool restart = true, bool synchronous = true); 48 | 49 | /** Check network access status 50 | @return 1 if Alive, 0 if down 51 | */ 52 | int isAccessAlive(); 53 | 54 | /** Shutdown the modem (power off really) 55 | @return true if successful 56 | */ 57 | bool shutdown(); 58 | 59 | /** Secure shutdown the modem (power off really) 60 | @return always true 61 | */ 62 | bool secureShutdown(); 63 | 64 | /** Get last command status 65 | @return returns 0 if last command is still executing, 1 success, >1 error 66 | */ 67 | int ready(); 68 | 69 | void setTimeout(unsigned long timeout); 70 | 71 | unsigned long getTime(); 72 | unsigned long getLocalTime(); 73 | 74 | int lowPowerMode(); 75 | int noLowPowerMode(); 76 | 77 | GSM3_NetworkStatus_t status(); 78 | 79 | private: 80 | GSM3_NetworkStatus_t _state; 81 | int _readyState; 82 | const char* _pin; 83 | String _response; 84 | unsigned long _timeout; 85 | }; 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /src/GSMBand.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "Modem.h" 21 | 22 | #include "GSMBand.h" 23 | 24 | /* Used in URAT to set the access technology, the first value indicates 25 | the technology used (0 GSM/GPRS/eGSM (single mode), 1 GSM/GPRS/eGSM and UMTS(dual mode)) 26 | the second parameter sets, if more than one, which technology's bands should be preferred(0 GSM/GPRS/eGSM, 2 UTRAN)*/ 27 | #define GSM_BANDS "1,0" 28 | #define UMTS_BANDS "1,2" 29 | 30 | GSMBand::GSMBand(bool trace) 31 | { 32 | if (trace) { 33 | MODEM.debug(); 34 | } 35 | } 36 | 37 | GSM3_NetworkStatus_t GSMBand::begin() 38 | { 39 | return (GSM3_NetworkStatus_t)MODEM.begin(); 40 | } 41 | 42 | bool GSMBand::setRAT(const char* act) { 43 | 44 | MODEM.sendf("AT+URAT=%s", act); 45 | if (MODEM.waitForResponse(10000) == 1) { 46 | return true; 47 | } 48 | return false; 49 | } 50 | 51 | String GSMBand::getBand() 52 | { 53 | String response; 54 | 55 | MODEM.send("AT+UBANDSEL?"); 56 | 57 | if (MODEM.waitForResponse(100, &response) == 1) { 58 | if (response.startsWith("+UBANDSEL: ")) { 59 | response.remove(0, 11); 60 | 61 | if (response == "900") { 62 | return GSM_MODE_EGSM; 63 | } else if (response == "1800") { 64 | return GSM_MODE_DCS; 65 | } else if (response == "1900") { 66 | return GSM_MODE_PCS; 67 | } else if (response == "900,1800") { 68 | return GSM_MODE_EGSM_DCS; 69 | } else if (response == "850,1900") { 70 | return GSM_MODE_GSM850_PCS; 71 | } else if (response == "850,900,1800,1900") { 72 | return GSM_MODE_GSM850_EGSM_DCS_PCS; 73 | } else if (response == "2100") { 74 | return GSM_MODE_UMTS; 75 | } else if (response == "850,900,1900,2100") { 76 | return GSM_MODE_GSM850_EGSM_PCS_UMTS; 77 | } 78 | } 79 | } 80 | 81 | return GSM_MODE_UNDEFINED; 82 | } 83 | 84 | bool GSMBand::setBand(String band) 85 | { 86 | const char* bands; 87 | 88 | // Set the Radio Access Technology to support the 1800 MHz frequency 89 | // in accord with the bands selected 90 | if (band == "DCS_MODE" || band == "EGSM_DCS_MODE" || band == "GSM850_EGSM_DCS_PCS_MODE") { 91 | setRAT(GSM_BANDS); 92 | } else { 93 | setRAT(UMTS_BANDS); 94 | } 95 | 96 | if (band == GSM_MODE_EGSM) { 97 | bands = "900"; 98 | } else if (band == GSM_MODE_DCS) { 99 | bands = "1800"; 100 | } else if (band == GSM_MODE_PCS) { 101 | bands = "1900"; 102 | } else if (band == GSM_MODE_EGSM_DCS) { 103 | bands = "900,1800"; 104 | } else if (band == GSM_MODE_GSM850_PCS) { 105 | bands = "850,1900"; 106 | } else if (band == GSM_MODE_GSM850_EGSM_DCS_PCS) { 107 | bands = "850,900,1800,1900"; 108 | } else if (band == GSM_MODE_UMTS) { 109 | bands = "2100"; 110 | } else if (band == GSM_MODE_GSM850_EGSM_PCS_UMTS) { 111 | bands = "850,900,1900,2100"; 112 | } else { 113 | return false; 114 | } 115 | 116 | for (int i = 0; i < 10; i++) { 117 | MODEM.sendf("AT+UBANDSEL=%s", bands); 118 | int result = MODEM.waitForResponse(10000); 119 | 120 | if (result == 1) { 121 | return true; 122 | } else if (result == 2) { 123 | return false; 124 | } 125 | 126 | // retry ... 127 | delay(100); 128 | } 129 | 130 | return false; 131 | } 132 | -------------------------------------------------------------------------------- /src/GSMBand.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_BAND_H_INCLUDED 21 | #define _GSM_BAND_H_INCLUDED 22 | 23 | #include "GSM.h" 24 | 25 | #define NUMBEROFBANDS 9 26 | #define GSM_MODE_UNDEFINED "UNDEFINED" 27 | #define GSM_MODE_EGSM "EGSM_MODE" 28 | #define GSM_MODE_DCS "DCS_MODE" 29 | #define GSM_MODE_PCS "PCS_MODE" 30 | #define GSM_MODE_EGSM_DCS "EGSM_DCS_MODE" 31 | #define GSM_MODE_GSM850_PCS "GSM850_PCS_MODE" 32 | #define GSM_MODE_GSM850_EGSM_DCS_PCS "GSM850_EGSM_DCS_PCS_MODE" 33 | #define GSM_MODE_UMTS "UMTS_MODE" 34 | #define GSM_MODE_GSM850_EGSM_PCS_UMTS "GSM850_EGSM_PCS_UMTS_MODE" 35 | 36 | 37 | enum GSM3GSMBand {UNDEFINED, EGSM_MODE, DCS_MODE, PCS_MODE, EGSM_DCS_MODE, GSM850_PCS_MODE, GSM850_EGSM_DCS_PCS_MODE, GSM_UMTS_MODE, GSM_GSM850_EGSM_PCS_UMTS_MODE}; 38 | 39 | class GSMBand { 40 | 41 | public: 42 | 43 | /** Constructor 44 | @param trace If true, dumps all AT dialogue to Serial 45 | */ 46 | GSMBand(bool trace = false); 47 | 48 | /** Forces modem hardware restart, so we begin from scratch 49 | @return always returns IDLE status 50 | */ 51 | GSM3_NetworkStatus_t begin(); 52 | 53 | /** Get current modem work band 54 | @return current modem work band 55 | */ 56 | String getBand(); 57 | 58 | /** Changes the modem operating band 59 | @param band Desired new band 60 | @return true if success, false otherwise 61 | */ 62 | bool setBand(String band); 63 | 64 | private: 65 | 66 | /** Change the Radio access technology 67 | @param act desired access technology 68 | @return true if success, false otherwise 69 | */ 70 | bool setRAT(const char* act); 71 | }; 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/GSMClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_CLIENT_H_INCLUDED 21 | #define _GSM_CLIENT_H_INCLUDED 22 | 23 | #include "Modem.h" 24 | 25 | #include 26 | 27 | class GSMClient : public Client, public ModemUrcHandler { 28 | 29 | public: 30 | 31 | /** Constructor 32 | @param synch Sync mode 33 | */ 34 | GSMClient(bool synch = true); 35 | 36 | /** Constructor 37 | @param socket Socket 38 | @param synch Sync mode 39 | */ 40 | GSMClient(int socket, bool synch); 41 | 42 | virtual ~GSMClient(); 43 | 44 | /** Get last command status 45 | @return returns 0 if last command is still executing, 1 success, >1 error 46 | */ 47 | virtual int ready(); 48 | 49 | /** Connect to server by IP address 50 | @param (IPAddress) 51 | @param (uint16_t) 52 | @return returns 0 on failure, 1 on success (sync mode) 53 | 0 if last command is still executing, 1 success, 2 if there are no resources (async mode) */ 54 | int connect(IPAddress, uint16_t); 55 | int connectSSL(IPAddress, uint16_t); 56 | 57 | /** Connect to server by hostname 58 | @param host Hostname 59 | @param port Port 60 | @return returns 0 on failure, 1 on success (sync mode) 61 | 0 if last command is still executing, 1 success, 2 if there are no resources (async mode) 62 | */ 63 | int connect(const char *host, uint16_t port); 64 | int connectSSL(const char *host, uint16_t port); 65 | 66 | /** Initialize write in request 67 | @param sync Sync mode 68 | */ 69 | void beginWrite(bool sync = false); 70 | 71 | /** Write a character in request 72 | @param c Character 73 | @return size 74 | */ 75 | size_t write(uint8_t c); 76 | 77 | /** Write a characters buffer in request 78 | @param buf Buffer 79 | @return buffer size 80 | */ 81 | size_t write(const uint8_t *buf); 82 | 83 | /** Write a characters buffer with size in request 84 | @param (uint8_t*) Buffer 85 | @param (size_t) Buffer size 86 | @return buffer size 87 | */ 88 | size_t write(const uint8_t*, size_t); 89 | 90 | /** Finish write request 91 | @param sync Sync mode 92 | */ 93 | void endWrite(bool sync = false); 94 | 95 | /** Check if connected to server 96 | @return 1 if connected 97 | */ 98 | uint8_t connected(); 99 | 100 | operator bool(); 101 | 102 | /** Read from response buffer and copy size specified to buffer 103 | @param buf Buffer 104 | @param size Buffer size 105 | @return bytes read 106 | */ 107 | int read(uint8_t *buf, size_t size); 108 | 109 | /** Read a character from response buffer 110 | @return character 111 | */ 112 | int read(); 113 | 114 | /** Check if exists a response available 115 | @return 1 if exists, 0 if not exists 116 | */ 117 | int available(); 118 | 119 | /** Read a character from response buffer but does not move the pointer. 120 | @return character 121 | */ 122 | int peek(); 123 | 124 | /** Flush response buffer 125 | */ 126 | void flush(); 127 | 128 | /** Stop client 129 | */ 130 | void stop(); 131 | 132 | /** Set SSL profile 133 | */ 134 | void setCertificateValidationLevel(uint8_t ssl); 135 | 136 | virtual void handleUrc(const String& urc); 137 | 138 | private: 139 | int connect(); 140 | 141 | bool _synch; 142 | int _socket; 143 | int _connected; 144 | 145 | int _state; 146 | IPAddress _ip; 147 | const char* _host; 148 | uint16_t _port; 149 | bool _ssl; 150 | 151 | int _sslprofile; 152 | bool _writeSync; 153 | String _response; 154 | }; 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /src/GSMFileUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | class GSMFileUtils { 7 | public: 8 | GSMFileUtils(bool debug = false); 9 | 10 | bool begin(const bool restart); 11 | bool begin() { return begin(true); }; 12 | 13 | uint32_t fileCount() const { return _count; }; 14 | size_t listFiles(String list[]) const; 15 | uint32_t listFile(const String filename) const; 16 | 17 | uint32_t downloadFile(const String filename, const char buf[], const uint32_t size, const bool append); 18 | uint32_t downloadFile(const String filename, const uint8_t buf[], const uint32_t size, const bool append) {return downloadFile(filename, reinterpret_cast(&buf), size, false); }; 19 | uint32_t downloadFile(const String filename, const char buf[], const uint32_t size) { return downloadFile(filename, buf, size, false); }; 20 | uint32_t downloadFile(const String filename, const uint8_t buf[], const uint32_t size) { return downloadFile(filename, buf, size, false); }; 21 | uint32_t downloadFile(const String filename, const String& buf) { return downloadFile(filename, buf.c_str(), buf.length(), false); } 22 | 23 | uint32_t appendFile(const String filename, const String& buf) { return downloadFile(filename, buf.c_str(), buf.length(), true); } 24 | uint32_t appendFile(const String filename, const char buf[], const uint32_t size) { return downloadFile(filename, buf, size, true); } 25 | 26 | bool deleteFile(const String filename); 27 | int deleteFiles(); 28 | 29 | uint32_t readFile(const String filename, String* content); 30 | uint32_t readFile(const String filename, uint8_t* content); 31 | uint32_t readBlock(const String filename, const uint32_t offset, const uint32_t len, uint8_t* content); 32 | 33 | uint32_t freeSpace(); 34 | 35 | private: 36 | int _count; 37 | String _files; 38 | 39 | bool _debug; 40 | 41 | void _countFiles(); 42 | int _getFileList(); 43 | 44 | }; 45 | 46 | void printFiles(const GSMFileUtils fileUtils); 47 | -------------------------------------------------------------------------------- /src/GSMHttpUtils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2020 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "Modem.h" 21 | 22 | #include "GSMHttpUtils.h" 23 | 24 | #define TRUST_ROOT_TYPE "CA,\"" 25 | #define CLIENT_CERT_TYPE "CC,\"" 26 | #define CLIENT_KEY_TYPE "PK,\"" 27 | 28 | bool GSMHttpUtils::_rootCertsLoaded = false; 29 | 30 | GSMHttpUtils::GSMHttpUtils() : 31 | _gsmRoots(GSM_ROOT_CERTS), 32 | _sizeRoot(GSM_NUM_ROOT_CERTS), 33 | _httpresp(false), 34 | _ssl(false) 35 | { 36 | MODEM.addUrcHandler(this); 37 | } 38 | 39 | GSMHttpUtils::~GSMHttpUtils() 40 | { 41 | MODEM.removeUrcHandler(this); 42 | } 43 | 44 | 45 | void GSMHttpUtils::setSignedCertificate(const uint8_t* cert, const char* name, size_t size) { 46 | MODEM.sendf("AT+USECMNG=0,1,\"%s\",%d", name, size); 47 | MODEM.waitForResponse(1000); 48 | 49 | MODEM.write(cert, size); 50 | MODEM.waitForResponse(1000); 51 | } 52 | 53 | void GSMHttpUtils::setPrivateKey(const uint8_t* key, const char*name, size_t size) { 54 | 55 | MODEM.sendf("AT+USECMNG=0,2,\"%s\",%d", name, size); 56 | MODEM.waitForResponse(1000); 57 | MODEM.write(key, size); 58 | MODEM.waitForResponse(1000); 59 | } 60 | 61 | void GSMHttpUtils::setTrustedRoot(const char* name) { 62 | MODEM.sendf("AT+USECPRF=0,3,\"%s\"", name); 63 | MODEM.waitForResponse(100); 64 | } 65 | 66 | void GSMHttpUtils::useSignedCertificate(const char* name) { 67 | MODEM.sendf("AT+USECPRF=0,5,\"%s\"", name); 68 | MODEM.waitForResponse(100); 69 | } 70 | 71 | void GSMHttpUtils::usePrivateKey(const char* name) { 72 | MODEM.sendf("AT+USECPRF=0,6,\"%s\"", name); 73 | MODEM.waitForResponse(100); 74 | } 75 | 76 | void GSMHttpUtils::eraseTrustedRoot() { 77 | for(int i=0; i< _sizeRoot; i++) { 78 | eraseCert(_gsmRoots[i].name, 0); 79 | } 80 | } 81 | 82 | void GSMHttpUtils::eraseAllCertificates() { 83 | for (int cert_type = 0; cert_type < 3; cert_type++) { 84 | String response = ""; 85 | MODEM.sendf("AT+USECMNG=3,%d", cert_type); 86 | MODEM.waitForResponse(100, &response); 87 | int index = 0; 88 | bool done = true; 89 | if(response != "") { 90 | while(done) { 91 | int index_tmp = response.indexOf("\r\n", index); 92 | String certname = ""; 93 | if (index_tmp > 0) { 94 | certname = response.substring(index, index_tmp); 95 | index = index_tmp + 2; 96 | } else { 97 | certname = response.substring(index); 98 | done = false; 99 | } 100 | if(certname != "") { 101 | removeCertForType(certname, cert_type); 102 | } 103 | } 104 | } 105 | } 106 | } 107 | 108 | void GSMHttpUtils::removeCertForType(String certname, int type) { 109 | int start_ind = -1; 110 | int last_ind = 0; 111 | switch (type) { 112 | case 0: 113 | start_ind = certname.indexOf(TRUST_ROOT_TYPE) + sizeof(TRUST_ROOT_TYPE) - 1; 114 | break; 115 | case 1: 116 | start_ind = certname.indexOf(CLIENT_CERT_TYPE) + sizeof(CLIENT_CERT_TYPE) - 1; 117 | break; 118 | case 2: 119 | start_ind = certname.indexOf(CLIENT_KEY_TYPE) + sizeof(CLIENT_KEY_TYPE) - 1; 120 | break; 121 | default: 122 | break; 123 | } 124 | 125 | if (start_ind >= 0) { 126 | last_ind = certname.indexOf("\"",start_ind); 127 | eraseCert(certname.substring(start_ind, last_ind).c_str(), type); 128 | } 129 | } 130 | 131 | void GSMHttpUtils::eraseCert(const char* name, int type) { 132 | MODEM.sendf("AT+USECMNG=2,%d,\"%s\"", type, name); 133 | MODEM.waitForResponse(100); 134 | } 135 | 136 | void GSMHttpUtils::setUserRoots(const GSMRootCert * userRoots, size_t size) { 137 | _gsmRoots = userRoots; 138 | _sizeRoot = size; 139 | } 140 | 141 | void GSMHttpUtils::handleUrc(const String& urc) 142 | { 143 | if (urc.startsWith("+UUHTTPCR: ")) { 144 | _httpresp = false; 145 | if (urc.endsWith(",1")) { 146 | _httpresp = true; 147 | } 148 | 149 | } 150 | } 151 | 152 | void GSMHttpUtils::enableSSL() { 153 | // Sets the profile ID #1 154 | MODEM.sendf("AT+USECPRF=0,0,1"); 155 | MODEM.waitForResponse(100); 156 | _ssl = true; 157 | } 158 | 159 | void GSMHttpUtils::disableSSL() { 160 | if(_ssl) { 161 | // Sets the profile ID #0 162 | MODEM.sendf("AT+USECPRF=0,0,0"); 163 | MODEM.waitForResponse(100); 164 | } 165 | _ssl = false; 166 | } 167 | 168 | void GSMHttpUtils::configServer(const char* url, int httpport) { 169 | 170 | // Reset the HTTP profile #0 171 | MODEM.send("AT+UHTTP=0"); 172 | MODEM.waitForResponse(100); 173 | 174 | // Sets HTTP server name 175 | MODEM.sendf("AT+UHTTP=0,1,\"%s\"",url); 176 | MODEM.waitForResponse(100); 177 | 178 | // Sets HTTP server port 179 | MODEM.sendf("AT+UHTTP=0,5,%d",httpport); 180 | MODEM.waitForResponse(100); 181 | 182 | // Sets HTTP secure option 183 | if(_ssl) { 184 | MODEM.send("AT+UHTTP=0,6,1,0"); 185 | MODEM.waitForResponse(100); 186 | } 187 | 188 | // DNS resolution of url 189 | MODEM.sendf("AT+UDNSRN=0,\"%s\"",url); 190 | MODEM.waitForResponse(10000); 191 | } 192 | 193 | void GSMHttpUtils::head(const char* path, const char* filename) { 194 | // Makes a HEAD request and store the response in _file 195 | MODEM.sendf("AT+UHTTPC=0,0,\"%s\",\"%s\"",path, filename); 196 | MODEM.waitForResponse(100); 197 | 198 | } 199 | 200 | void GSMHttpUtils::get(const char* path, const char* filename) { 201 | // Makes a GET request and store it in _file 202 | MODEM.sendf("AT+UHTTPC=0,1,\"%s\",\"%s\"",path, filename); 203 | MODEM.waitForResponse(100); 204 | 205 | } 206 | 207 | void GSMHttpUtils::del(const char* path, const char* filename) { 208 | // make a DELETE request and store it in _file 209 | MODEM.sendf("AT+UHTTPC=0,2,\"%s\",\"%s\"",path, filename); 210 | MODEM.waitForResponse(100); 211 | } 212 | 213 | void GSMHttpUtils::put(const char* path, const char* filename) { 214 | // make a PUT request and store it in _file 215 | MODEM.sendf("AT+UHTTPC=0,3,\"%s\",\"%s\"",path, filename); 216 | MODEM.waitForResponse(100); 217 | } 218 | 219 | void GSMHttpUtils::post(const char* path, const char* filename) { 220 | // make a POST request and store it in _file 221 | MODEM.sendf("AT+UHTTPC=0,4,\"%s\",\"%s\"",path, filename); 222 | MODEM.waitForResponse(100); 223 | } 224 | 225 | 226 | bool GSMHttpUtils::responseStatus() { 227 | MODEM.poll(); 228 | return _httpresp; 229 | } 230 | -------------------------------------------------------------------------------- /src/GSMHttpUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2020 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_HTTP_UTILS_H_INCLUDED 21 | #define _GSM_HTTP_UTILS_H_INCLUDED 22 | 23 | #include "GSMClient.h" 24 | #include "utility/GSMRootCerts.h" 25 | class GSMHttpUtils: public GSMClient { 26 | 27 | public: 28 | GSMHttpUtils(); 29 | virtual ~GSMHttpUtils(); 30 | 31 | virtual void setSignedCertificate(const uint8_t* cert, const char* name, size_t size); 32 | virtual void setPrivateKey(const uint8_t* key, const char* name, size_t size); 33 | virtual void useSignedCertificate(const char* name); 34 | virtual void usePrivateKey(const char* name); 35 | virtual void setTrustedRoot(const char* name); 36 | virtual void setUserRoots(const GSMRootCert * userRoots, size_t size); 37 | virtual void eraseTrustedRoot(); 38 | virtual void eraseAllCertificates(); 39 | virtual void eraseCert(const char* name, int type); 40 | virtual void handleUrc(const String& urc); 41 | virtual void enableSSL(); 42 | virtual void disableSSL(); 43 | virtual void configServer(const char* url, int httpport); 44 | virtual void head(const char* path, const char* filename); 45 | virtual void get(const char* path, const char* filename); 46 | virtual void del(const char* path, const char* filename); 47 | virtual void put(const char* path, const char* filename); 48 | virtual void post(const char* path, const char* filename); 49 | virtual bool responseStatus(); 50 | private: 51 | void removeCertForType(String certname, int type); 52 | 53 | private: 54 | static bool _rootCertsLoaded; 55 | int _certIndex; 56 | const GSMRootCert * _gsmRoots; 57 | int _sizeRoot; 58 | bool _httpresp; 59 | bool _ssl; 60 | 61 | }; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/GSMLocation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "GSMLocation.h" 21 | 22 | #define GSM_LOCATION_UPDATE_INTERVAL 1100 23 | 24 | GSMLocation::GSMLocation() : 25 | _commandSent(false), 26 | _locationAvailable(false), 27 | _latitude(0), 28 | _longitude(0), 29 | _altitude(0), 30 | _uncertainty(0) 31 | { 32 | MODEM.addUrcHandler(this); 33 | } 34 | 35 | GSMLocation::~GSMLocation() 36 | { 37 | MODEM.removeUrcHandler(this); 38 | } 39 | 40 | int GSMLocation::begin() 41 | { 42 | MODEM.send("AT+ULOCCELL=1"); 43 | 44 | if (MODEM.waitForResponse() != 1) { 45 | return 0; 46 | } 47 | 48 | return 1; 49 | } 50 | 51 | int GSMLocation::available() 52 | { 53 | MODEM.poll(); 54 | 55 | if (!_commandSent) { 56 | _commandSent = true; 57 | _locationAvailable = false; 58 | 59 | MODEM.send("AT+ULOC=2,2,0,1,1"); 60 | MODEM.waitForResponse(); 61 | } 62 | 63 | if (_locationAvailable) { 64 | _commandSent = false; 65 | _locationAvailable = false; 66 | 67 | return 1; 68 | } 69 | 70 | return 0; 71 | } 72 | 73 | float GSMLocation::latitude() 74 | { 75 | return _latitude; 76 | } 77 | 78 | float GSMLocation::longitude() 79 | { 80 | return _longitude; 81 | } 82 | 83 | long GSMLocation::altitude() 84 | { 85 | return _altitude; 86 | } 87 | 88 | long GSMLocation::accuracy() 89 | { 90 | return _uncertainty; 91 | } 92 | 93 | void GSMLocation::handleUrc(const String& urc) 94 | { 95 | if (urc.startsWith("+UULOC: ")) { 96 | String temp = urc; 97 | int lastCommaIndex; 98 | 99 | _locationAvailable = true; 100 | 101 | lastCommaIndex = temp.lastIndexOf(','); 102 | _uncertainty = temp.substring(lastCommaIndex + 1).toInt(); 103 | temp.remove(lastCommaIndex); 104 | 105 | lastCommaIndex = temp.lastIndexOf(','); 106 | _altitude = temp.substring(lastCommaIndex + 1).toInt(); 107 | temp.remove(lastCommaIndex); 108 | 109 | lastCommaIndex = temp.lastIndexOf(','); 110 | _longitude = temp.substring(lastCommaIndex + 1).toFloat(); 111 | temp.remove(lastCommaIndex); 112 | 113 | lastCommaIndex = temp.lastIndexOf(','); 114 | _latitude = temp.substring(lastCommaIndex + 1).toFloat(); 115 | temp.remove(lastCommaIndex); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/GSMLocation.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_LOCATION_H_INCLUDED 21 | #define _GSM_LOCATION_H_INCLUDED 22 | 23 | #include 24 | 25 | #include "Modem.h" 26 | 27 | class GSMLocation : public ModemUrcHandler { 28 | 29 | public: 30 | GSMLocation(); 31 | virtual ~GSMLocation(); 32 | 33 | int begin(); 34 | 35 | int available(); 36 | 37 | float latitude(); 38 | float longitude(); 39 | long altitude(); 40 | long accuracy(); 41 | 42 | void handleUrc(const String& urc); 43 | 44 | private: 45 | bool _commandSent; 46 | bool _locationAvailable; 47 | 48 | float _latitude; 49 | float _longitude; 50 | long _altitude; 51 | long _uncertainty; 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/GSMModem.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "Modem.h" 21 | 22 | #include "GSMModem.h" 23 | 24 | GSMModem::GSMModem() 25 | { 26 | } 27 | 28 | int GSMModem::begin() 29 | { 30 | if (!MODEM.begin()) { 31 | return 0; 32 | } 33 | 34 | return 1; 35 | } 36 | 37 | String GSMModem::getIMEI() 38 | { 39 | String imei; 40 | 41 | imei.reserve(15); 42 | 43 | MODEM.send("AT+CGSN"); 44 | MODEM.waitForResponse(100, &imei); 45 | 46 | return imei; 47 | } 48 | 49 | String GSMModem::getICCID() 50 | { 51 | String iccid; 52 | 53 | iccid.reserve(7 + 20); 54 | 55 | MODEM.send("AT+CCID"); 56 | MODEM.waitForResponse(1000, &iccid); 57 | 58 | if (iccid.startsWith("+CCID: ")) { 59 | iccid.remove(0, 7); 60 | } else { 61 | iccid = ""; 62 | } 63 | 64 | return iccid; 65 | } 66 | -------------------------------------------------------------------------------- /src/GSMModem.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_MODEM_H_INCLUDED 21 | #define _GSM_MODEM_H_INCLUDED 22 | 23 | #include 24 | 25 | class GSMModem { 26 | 27 | public: 28 | 29 | /** Constructor */ 30 | GSMModem(); 31 | 32 | /** Check modem response and restart it 33 | */ 34 | int begin(); 35 | 36 | /** Obtain modem IMEI (command AT) 37 | @return modem IMEI number 38 | */ 39 | String getIMEI(); 40 | 41 | /** Obtain SIM card ICCID (command AT) 42 | @return SIM ICCID number 43 | */ 44 | String getICCID(); 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/GSMPIN.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "Modem.h" 21 | 22 | #include "GSMPIN.h" 23 | 24 | GSMPIN::GSMPIN() : 25 | _pinUsed(false) 26 | { 27 | } 28 | 29 | void GSMPIN::begin() 30 | { 31 | MODEM.begin(); 32 | } 33 | 34 | int GSMPIN::isPIN() 35 | { 36 | String response; 37 | 38 | for (unsigned long start = millis(); (millis() - start) < 1000;) { 39 | MODEM.send("AT+CPIN?"); 40 | 41 | if (MODEM.waitForResponse(10000, &response) == 1) { 42 | if (response.startsWith("+CPIN: ")) { 43 | if (response.endsWith("READY")) { 44 | return 0; 45 | } else if (response.endsWith("SIM PIN")) { 46 | return 1; 47 | } else if (response.endsWith("SIM PUK")) { 48 | return -1; 49 | } else { 50 | return -2; 51 | } 52 | } 53 | } 54 | 55 | delay(100); 56 | } 57 | 58 | return -2; 59 | } 60 | 61 | int GSMPIN::checkPIN(String pin) 62 | { 63 | MODEM.sendf("AT+CPIN=\"%s\"", pin.c_str()); 64 | if (MODEM.waitForResponse(10000) == 1) { 65 | return 0; 66 | } 67 | 68 | return -1; 69 | } 70 | 71 | 72 | int GSMPIN::checkPUK(String puk, String pin) 73 | { 74 | MODEM.sendf("AT+CPIN=\"%s\",\"%s\"", puk.c_str(), pin.c_str()); 75 | if (MODEM.waitForResponse(10000) == 1) { 76 | return 0; 77 | } 78 | 79 | return -1; 80 | } 81 | 82 | void GSMPIN::changePIN(String old, String pin) 83 | { 84 | MODEM.sendf("AT+CPWD=\"SC\",\"%s\",\"%s\"", old.c_str(), pin.c_str()); 85 | if (MODEM.waitForResponse(10000) == 1) { 86 | Serial.println("Pin changed successfully."); 87 | } else { 88 | Serial.println("ERROR"); 89 | } 90 | } 91 | 92 | void GSMPIN::switchPIN(String pin) 93 | { 94 | String response; 95 | 96 | MODEM.send("AT+CLCK=\"SC\",2"); 97 | if (MODEM.waitForResponse(180000, &response) != 1) { 98 | Serial.println("ERROR"); 99 | return; 100 | } 101 | 102 | if (response == "+CLCK: 0") { 103 | MODEM.sendf("AT+CLCK=\"SC\",1,\"%s\"", pin.c_str()); 104 | if (MODEM.waitForResponse(180000, &response) == 1) { 105 | Serial.println("OK. PIN lock on."); 106 | _pinUsed = true; 107 | } else { 108 | Serial.println("ERROR"); 109 | _pinUsed = false; 110 | } 111 | } else if (response == "+CLCK: 1") { 112 | MODEM.sendf("AT+CLCK=\"SC\",0,\"%s\"", pin.c_str()); 113 | if (MODEM.waitForResponse(180000, &response) == 1) { 114 | Serial.println("OK. PIN lock off."); 115 | _pinUsed = false; 116 | } else { 117 | Serial.println("ERROR"); 118 | _pinUsed = true; 119 | } 120 | } else { 121 | Serial.println("ERROR"); 122 | } 123 | } 124 | 125 | int GSMPIN::checkReg() 126 | { 127 | for (unsigned long start = millis(); (millis() - start) < 10000L;) { 128 | MODEM.send("AT+CREG?"); 129 | 130 | String response = ""; 131 | 132 | if (MODEM.waitForResponse(100, &response) == 1) { 133 | if (response.startsWith("+CREG: ")) { 134 | if (response.endsWith(",1")) { 135 | return 0; 136 | } else if (response.endsWith(",5")) { 137 | return 1; 138 | } 139 | } 140 | } 141 | 142 | delay(100); 143 | } 144 | 145 | return -1; 146 | } 147 | 148 | bool GSMPIN::getPINUsed() 149 | { 150 | return _pinUsed; 151 | } 152 | 153 | void GSMPIN::setPINUsed(bool used) 154 | { 155 | _pinUsed = used; 156 | } 157 | -------------------------------------------------------------------------------- /src/GSMPIN.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_PIN_H_INCLUDED 21 | #define _GSM_PIN_H_INCLUDED 22 | 23 | #include 24 | 25 | class GSMPIN { 26 | 27 | public: 28 | 29 | /** Constructor */ 30 | GSMPIN(); 31 | 32 | /** Check modem response and restart it 33 | */ 34 | void begin(); 35 | 36 | /** Check if PIN lock or PUK lock is activated 37 | @return 0 if PIN lock is off, 1 if PIN lock is on, -1 if PUK lock is on, -2 if error exists 38 | */ 39 | int isPIN(); 40 | 41 | /** Check if PIN code is correct and valid 42 | @param pin PIN code 43 | @return 0 if is correct, -1 if is incorrect 44 | */ 45 | int checkPIN(String pin); 46 | 47 | /** Check if PUK code is correct and establish new PIN code 48 | @param puk PUK code 49 | @param pin New PIN code 50 | @return 0 if successful, otherwise return -1 51 | */ 52 | int checkPUK(String puk, String pin); 53 | 54 | /** Change PIN code 55 | @param old Old PIN code 56 | @param pin New PIN code 57 | */ 58 | void changePIN(String old, String pin); 59 | 60 | /** Change PIN lock status 61 | @param pin PIN code 62 | */ 63 | void switchPIN(String pin); 64 | 65 | /** Check if modem was registered in GSM/GPRS network 66 | @return 0 if modem was registered, 1 if modem was registered in roaming, -1 if error exists 67 | */ 68 | int checkReg(); 69 | 70 | /** Return if PIN lock is used 71 | @return true if PIN lock is used, otherwise, return false 72 | */ 73 | bool getPINUsed(); 74 | 75 | /** Set PIN lock status 76 | @param used New PIN lock status 77 | */ 78 | void setPINUsed(bool used); 79 | 80 | private: 81 | bool _pinUsed; 82 | }; 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/GSMSSLClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "Modem.h" 21 | 22 | #include "GSMSSLClient.h" 23 | 24 | enum { 25 | SSL_CLIENT_STATE_LOAD_ROOT_CERT, 26 | SSL_CLIENT_STATE_WAIT_LOAD_ROOT_CERT_RESPONSE, 27 | SSL_CLIENT_STATE_WAIT_DELETE_ROOT_CERT_RESPONSE 28 | }; 29 | 30 | #define TRUST_ROOT_TYPE "CA,\"" 31 | #define CLIENT_CERT_TYPE "CC,\"" 32 | #define CLIENT_KEY_TYPE "PK,\"" 33 | 34 | bool GSMSSLClient::_rootCertsLoaded = false; 35 | 36 | GSMSSLClient::GSMSSLClient(bool synch) : 37 | GSMClient(synch), 38 | _gsmRoots(GSM_ROOT_CERTS), 39 | _sizeRoot(GSM_NUM_ROOT_CERTS) 40 | { 41 | } 42 | 43 | GSMSSLClient::~GSMSSLClient() 44 | { 45 | } 46 | 47 | int GSMSSLClient::ready() 48 | { 49 | if (_rootCertsLoaded) { 50 | // root certs loaded already, continue to regular GSMClient 51 | return GSMClient::ready(); 52 | } 53 | 54 | int ready = MODEM.ready(); 55 | 56 | if (ready == 0) { 57 | // a command is still running 58 | return 0; 59 | } 60 | 61 | switch (_state) { 62 | case SSL_CLIENT_STATE_LOAD_ROOT_CERT: { 63 | if (_gsmRoots[_certIndex].size) { 64 | // load the next root cert 65 | MODEM.sendf("AT+USECMNG=0,0,\"%s\",%d", _gsmRoots[_certIndex].name, _gsmRoots[_certIndex].size); 66 | if (MODEM.waitForPrompt() != 1) { 67 | // failure 68 | ready = -1; 69 | } else { 70 | // send the cert contents 71 | MODEM.write(_gsmRoots[_certIndex].data, _gsmRoots[_certIndex].size); 72 | 73 | _state = SSL_CLIENT_STATE_WAIT_LOAD_ROOT_CERT_RESPONSE; 74 | ready = 0; 75 | } 76 | } else { 77 | // remove the next root cert name 78 | MODEM.sendf("AT+USECMNG=2,0,\"%s\"", _gsmRoots[_certIndex].name); 79 | 80 | _state = SSL_CLIENT_STATE_WAIT_DELETE_ROOT_CERT_RESPONSE; 81 | ready = 0; 82 | } 83 | break; 84 | } 85 | 86 | case SSL_CLIENT_STATE_WAIT_LOAD_ROOT_CERT_RESPONSE: { 87 | if (ready > 1) { 88 | // error 89 | } else { 90 | _certIndex++; 91 | 92 | if (_certIndex == _sizeRoot) { 93 | // all certs loaded 94 | _rootCertsLoaded = true; 95 | } else { 96 | // load next 97 | _state = SSL_CLIENT_STATE_LOAD_ROOT_CERT; 98 | } 99 | 100 | ready = 0; 101 | } 102 | break; 103 | } 104 | 105 | case SSL_CLIENT_STATE_WAIT_DELETE_ROOT_CERT_RESPONSE: { 106 | // ignore ready response, root cert might not exist 107 | _certIndex++; 108 | 109 | if (_certIndex == GSM_NUM_ROOT_CERTS) { 110 | // all certs loaded 111 | _rootCertsLoaded = true; 112 | } else { 113 | // load next 114 | _state = SSL_CLIENT_STATE_LOAD_ROOT_CERT; 115 | } 116 | 117 | ready = 0; 118 | break; 119 | } 120 | } 121 | 122 | return ready; 123 | } 124 | 125 | int GSMSSLClient::connect(IPAddress ip, uint16_t port) 126 | { 127 | _certIndex = 0; 128 | _state = SSL_CLIENT_STATE_LOAD_ROOT_CERT; 129 | 130 | return connectSSL(ip, port); 131 | } 132 | 133 | int GSMSSLClient::connect(const char* host, uint16_t port) 134 | { 135 | _certIndex = 0; 136 | _state = SSL_CLIENT_STATE_LOAD_ROOT_CERT; 137 | 138 | return connectSSL(host, port); 139 | } 140 | 141 | void GSMSSLClient::setSignedCertificate(const uint8_t* cert, const char* name, size_t size) { 142 | MODEM.sendf("AT+USECMNG=0,1,\"%s\",%d", name, size); 143 | MODEM.waitForResponse(1000); 144 | 145 | MODEM.write(cert, size); 146 | MODEM.waitForResponse(1000); 147 | } 148 | 149 | void GSMSSLClient::setPrivateKey(const uint8_t* key, const char*name, size_t size) { 150 | 151 | MODEM.sendf("AT+USECMNG=0,2,\"%s\",%d", name, size); 152 | MODEM.waitForResponse(1000); 153 | MODEM.write(key, size); 154 | MODEM.waitForResponse(1000); 155 | } 156 | 157 | void GSMSSLClient::setTrustedRoot(const char* name) { 158 | MODEM.sendf("AT+USECPRF=0,3,\"%s\"", name); 159 | MODEM.waitForResponse(100); 160 | } 161 | 162 | void GSMSSLClient::useSignedCertificate(const char* name) { 163 | MODEM.sendf("AT+USECPRF=0,5,\"%s\"", name); 164 | MODEM.waitForResponse(100); 165 | } 166 | 167 | void GSMSSLClient::usePrivateKey(const char* name) { 168 | MODEM.sendf("AT+USECPRF=0,6,\"%s\"", name); 169 | MODEM.waitForResponse(100); 170 | } 171 | 172 | void GSMSSLClient::eraseTrustedRoot() { 173 | for(int i=0; i< _sizeRoot; i++) { 174 | eraseCert(_gsmRoots[i].name, 0); 175 | } 176 | } 177 | 178 | void GSMSSLClient::eraseAllCertificates() { 179 | for (int cert_type = 0; cert_type < 3; cert_type++) { 180 | String response = ""; 181 | MODEM.sendf("AT+USECMNG=3,%d", cert_type); 182 | MODEM.waitForResponse(100, &response); 183 | int index = 0; 184 | bool done = true; 185 | if(response != "") { 186 | while(done) { 187 | int index_tmp = response.indexOf("\r\n", index); 188 | String certname = ""; 189 | if (index_tmp > 0) { 190 | certname = response.substring(index, index_tmp); 191 | index = index_tmp + 2; 192 | } else { 193 | certname = response.substring(index); 194 | done = false; 195 | } 196 | if(certname != "") { 197 | removeCertForType(certname, cert_type); 198 | } 199 | } 200 | } 201 | } 202 | } 203 | 204 | void GSMSSLClient::removeCertForType(String certname, int type) { 205 | int start_ind = -1; 206 | int last_ind = 0; 207 | switch (type) { 208 | case 0: 209 | start_ind = certname.indexOf(TRUST_ROOT_TYPE) + sizeof(TRUST_ROOT_TYPE) - 1; 210 | break; 211 | case 1: 212 | start_ind = certname.indexOf(CLIENT_CERT_TYPE) + sizeof(CLIENT_CERT_TYPE) - 1; 213 | break; 214 | case 2: 215 | start_ind = certname.indexOf(CLIENT_KEY_TYPE) + sizeof(CLIENT_KEY_TYPE) - 1; 216 | break; 217 | default: 218 | break; 219 | } 220 | 221 | if (start_ind >= 0) { 222 | last_ind = certname.indexOf("\"",start_ind); 223 | eraseCert(certname.substring(start_ind, last_ind).c_str(), type); 224 | } 225 | } 226 | 227 | void GSMSSLClient::eraseCert(const char* name, int type) { 228 | MODEM.sendf("AT+USECMNG=2,%d,\"%s\"", type, name); 229 | MODEM.waitForResponse(100); 230 | } 231 | 232 | void GSMSSLClient::setUserRoots(const GSMRootCert * userRoots, size_t size) { 233 | _gsmRoots = userRoots; 234 | _sizeRoot = size; 235 | } 236 | -------------------------------------------------------------------------------- /src/GSMSSLClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_SSL_CLIENT_H_INCLUDED 21 | #define _GSM_SSL_CLIENT_H_INCLUDED 22 | 23 | #include "GSMClient.h" 24 | #include "utility/GSMRootCerts.h" 25 | class GSMSSLClient : public GSMClient { 26 | 27 | public: 28 | GSMSSLClient(bool synch = true); 29 | virtual ~GSMSSLClient(); 30 | 31 | virtual int ready(); 32 | 33 | virtual int connect(IPAddress ip, uint16_t port); 34 | virtual int connect(const char* host, uint16_t port); 35 | virtual void setSignedCertificate(const uint8_t* cert, const char* name, size_t size); 36 | virtual void setPrivateKey(const uint8_t* key, const char* name, size_t size); 37 | virtual void useSignedCertificate(const char* name); 38 | virtual void usePrivateKey(const char* name); 39 | virtual void setTrustedRoot(const char* name); 40 | virtual void setUserRoots(const GSMRootCert * userRoots, size_t size); 41 | virtual void eraseTrustedRoot(); 42 | virtual void eraseAllCertificates(); 43 | virtual void eraseCert(const char* name, int type); 44 | private: 45 | void removeCertForType(String certname, int type); 46 | 47 | private: 48 | static bool _rootCertsLoaded; 49 | int _certIndex; 50 | int _state; 51 | const GSMRootCert * _gsmRoots; 52 | int _sizeRoot; 53 | 54 | }; 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/GSMScanner.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "Modem.h" 21 | 22 | #include "GSMScanner.h" 23 | 24 | GSMScanner::GSMScanner(bool trace) 25 | { 26 | if (trace) { 27 | MODEM.debug(); 28 | } 29 | } 30 | 31 | GSM3_NetworkStatus_t GSMScanner::begin() 32 | { 33 | MODEM.begin(); 34 | 35 | return IDLE; 36 | } 37 | 38 | String GSMScanner::getCurrentCarrier() 39 | { 40 | String response; 41 | 42 | MODEM.send("AT+COPS?"); 43 | if (MODEM.waitForResponse(180000, &response) == 1) { 44 | int firstQuoteIndex = response.indexOf('"'); 45 | int lastQuoteIndex = response.lastIndexOf('"'); 46 | 47 | if (firstQuoteIndex != -1 && lastQuoteIndex != -1 && firstQuoteIndex != lastQuoteIndex) { 48 | return response.substring(firstQuoteIndex + 1, lastQuoteIndex); 49 | } 50 | } 51 | 52 | return ""; 53 | } 54 | 55 | String GSMScanner::getSignalStrength() 56 | { 57 | String response; 58 | 59 | MODEM.send("AT+CSQ"); 60 | if (MODEM.waitForResponse(100, &response) == 1) { 61 | int firstSpaceIndex = response.indexOf(' '); 62 | int lastCommaIndex = response.lastIndexOf(','); 63 | 64 | if (firstSpaceIndex != -1 && lastCommaIndex != -1) { 65 | return response.substring(firstSpaceIndex + 1, lastCommaIndex); 66 | } 67 | } 68 | 69 | return ""; 70 | } 71 | 72 | String GSMScanner::readNetworks() 73 | { 74 | String response; 75 | 76 | MODEM.send("AT+COPS=?"); 77 | if (MODEM.waitForResponse(180000, &response) == 1) { 78 | String result; 79 | unsigned int responseLength = response.length(); 80 | 81 | for(unsigned int i = 0; i < responseLength; i++) { 82 | for (; i < responseLength; i++) { 83 | if (response[i] == '"') { 84 | result += "> "; 85 | break; 86 | } 87 | } 88 | 89 | for (i++; i < responseLength; i++) { 90 | if (response[i] == '"') { 91 | result += '\n'; 92 | break; 93 | } 94 | 95 | result += response[i]; 96 | } 97 | 98 | for (i++; i < responseLength; i++) { 99 | if (response[i] == ')') { 100 | break; 101 | } 102 | } 103 | } 104 | 105 | return result; 106 | } 107 | 108 | return ""; 109 | } 110 | -------------------------------------------------------------------------------- /src/GSMScanner.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_SCANNER_H_INCLUDED 21 | #define _GSM_SCANNER_H_INCLUDED 22 | 23 | #include "GSM.h" 24 | 25 | class GSMScanner { 26 | 27 | public: 28 | /** Constructor 29 | @param trace if true, dumps all AT dialogue to Serial 30 | @return - 31 | */ 32 | GSMScanner(bool trace = false); 33 | 34 | /** begin (forces modem hardware restart, so we begin from scratch) 35 | @return Always returns IDLE status 36 | */ 37 | GSM3_NetworkStatus_t begin(); 38 | 39 | /** Read current carrier 40 | @return Current carrier 41 | */ 42 | String getCurrentCarrier(); 43 | 44 | /** Obtain signal strength 45 | @return Signal Strength 46 | */ 47 | String getSignalStrength(); 48 | 49 | /** Search available carriers 50 | @return A string with list of networks available 51 | */ 52 | String readNetworks(); 53 | }; 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/GSMServer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "GSMServer.h" 21 | 22 | enum { 23 | SERVER_STATE_IDLE, 24 | SERVER_STATE_CREATE_SOCKET, 25 | SERVER_STATE_WAIT_CREATE_SOCKET_RESPONSE, 26 | SERVER_STATE_LISTEN, 27 | SERVER_STATE_WAIT_LISTEN_RESPONSE, 28 | SERVER_STATE_CLOSE_SOCKET, 29 | SERVER_STATE_WAIT_CLOSE_SOCKET 30 | }; 31 | 32 | GSMServer::GSMServer(uint16_t port, bool synch) : 33 | _port(port), 34 | _synch(synch), 35 | _socket(-1), 36 | _state(SERVER_STATE_IDLE) 37 | { 38 | for (int i = 0; i < MAX_CHILD_SOCKETS; i++) { 39 | _childSockets[i].socket = -1; 40 | _childSockets[i].accepted = false; 41 | _childSockets[i].available = 0; 42 | } 43 | 44 | MODEM.addUrcHandler(this); 45 | } 46 | 47 | GSMServer::~GSMServer() 48 | { 49 | MODEM.removeUrcHandler(this); 50 | } 51 | 52 | int GSMServer::ready() 53 | { 54 | int ready = MODEM.ready(); 55 | 56 | if (ready == 0) { 57 | return 0; 58 | } 59 | 60 | switch (_state) { 61 | case SERVER_STATE_IDLE: 62 | default: { 63 | break; 64 | } 65 | 66 | case SERVER_STATE_CREATE_SOCKET: { 67 | MODEM.setResponseDataStorage(&_response); 68 | MODEM.send("AT+USOCR=6"); 69 | 70 | _state = SERVER_STATE_WAIT_CREATE_SOCKET_RESPONSE; 71 | ready = 0; 72 | break; 73 | } 74 | 75 | case SERVER_STATE_WAIT_CREATE_SOCKET_RESPONSE: { 76 | if (ready > 1 || !_response.startsWith("+USOCR: ")) { 77 | _state = SERVER_STATE_IDLE; 78 | } else { 79 | _socket = _response.charAt(_response.length() - 1) - '0'; 80 | 81 | _state = SERVER_STATE_LISTEN; 82 | ready = 0; 83 | } 84 | break; 85 | } 86 | 87 | case SERVER_STATE_LISTEN: { 88 | MODEM.sendf("AT+USOLI=%d,%d", _socket, _port); 89 | 90 | _state = SERVER_STATE_WAIT_LISTEN_RESPONSE; 91 | ready = 0; 92 | break; 93 | } 94 | 95 | case SERVER_STATE_WAIT_LISTEN_RESPONSE: { 96 | if (ready > 1) { 97 | _state = SERVER_STATE_CLOSE_SOCKET; 98 | ready = 0; 99 | } else { 100 | _state = SERVER_STATE_IDLE; 101 | } 102 | break; 103 | } 104 | 105 | case SERVER_STATE_CLOSE_SOCKET: { 106 | MODEM.sendf("AT+USOCL=%d", _socket); 107 | 108 | _state = SERVER_STATE_WAIT_CLOSE_SOCKET; 109 | ready = 0; 110 | break; 111 | } 112 | 113 | case SERVER_STATE_WAIT_CLOSE_SOCKET: { 114 | _state = SERVER_STATE_IDLE; 115 | _socket = -1; 116 | break; 117 | } 118 | } 119 | 120 | return ready; 121 | } 122 | 123 | void GSMServer::begin() 124 | { 125 | _state = SERVER_STATE_CREATE_SOCKET; 126 | 127 | if (_synch) { 128 | while (ready() == 0); 129 | } 130 | } 131 | 132 | GSMClient GSMServer::available(bool synch) 133 | { 134 | MODEM.poll(); 135 | 136 | int socket = -1; 137 | 138 | if (_socket != -1) { 139 | // search for new accepted sockets first 140 | for (int i = 0; i < MAX_CHILD_SOCKETS; i++) { 141 | if (_childSockets[i].socket != -1 && _childSockets[i].accepted) { 142 | _childSockets[i].accepted = false; 143 | socket = _childSockets[i].socket; 144 | 145 | break; 146 | } 147 | } 148 | 149 | if (socket == -1) { 150 | // no new accepted sockets, search for one with data to be read 151 | for (int i = 0; i < MAX_CHILD_SOCKETS; i++) { 152 | if (_childSockets[i].socket != -1) { 153 | // check if socket is still alive 154 | MODEM.sendf("AT+USORD=%d,0", _childSockets[i].socket); 155 | if (MODEM.waitForResponse(10000) != 1) { 156 | // closed 157 | _childSockets[i].socket = -1; 158 | _childSockets[i].accepted = false; 159 | _childSockets[i].available = 0; 160 | 161 | continue; 162 | } 163 | 164 | if (_childSockets[i].available) { 165 | _childSockets[i].available = 0; 166 | socket = _childSockets[i].socket; 167 | break; 168 | } 169 | } 170 | } 171 | } 172 | } 173 | 174 | return GSMClient(socket, synch); 175 | } 176 | 177 | void GSMServer::beginWrite() 178 | { 179 | } 180 | 181 | size_t GSMServer::write(uint8_t c) 182 | { 183 | return write(&c, sizeof(c)); 184 | } 185 | 186 | size_t GSMServer::write(const uint8_t *buf) 187 | { 188 | return write(buf, strlen((const char*)buf)); 189 | } 190 | 191 | size_t GSMServer::write(const uint8_t *buf, size_t sz) 192 | { 193 | size_t written = 0; 194 | 195 | MODEM.poll(); 196 | 197 | if (_socket != -1) { 198 | for (int i = 0; i < MAX_CHILD_SOCKETS; i++) { 199 | if (_childSockets[i].socket != -1) { 200 | GSMClient client(_childSockets[i].socket, true); 201 | 202 | written += client.write(buf, sz); 203 | } 204 | } 205 | } 206 | 207 | return written; 208 | } 209 | 210 | void GSMServer::endWrite() 211 | { 212 | } 213 | 214 | void GSMServer::stop() 215 | { 216 | if (_socket < 0) { 217 | return; 218 | } 219 | 220 | MODEM.sendf("AT+USOCL=%d", _socket); 221 | MODEM.waitForResponse(10000); 222 | 223 | _socket = -1; 224 | } 225 | 226 | void GSMServer::handleUrc(const String& urc) 227 | { 228 | if (urc.startsWith("+UUSOLI: ")) { 229 | int socket = urc.charAt(9) - '0'; 230 | 231 | for (int i = 0; i < MAX_CHILD_SOCKETS; i++) { 232 | if (_childSockets[i].socket == -1) { 233 | _childSockets[i].socket = socket; 234 | _childSockets[i].accepted = true; 235 | _childSockets[i].available = 0; 236 | 237 | break; 238 | } 239 | } 240 | } else if (urc.startsWith("+UUSOCL: ")) { 241 | int socket = urc.charAt(urc.length() - 1) - '0'; 242 | 243 | if (socket == _socket) { 244 | _socket = -1; 245 | } else { 246 | for (int i = 0; i < MAX_CHILD_SOCKETS; i++) { 247 | if (_childSockets[i].socket == socket) { 248 | _childSockets[i].socket = -1; 249 | _childSockets[i].accepted = false; 250 | _childSockets[i].available = 0; 251 | 252 | break; 253 | } 254 | } 255 | } 256 | } else if (urc.startsWith("+UUSORD: ")) { 257 | int socket = urc.charAt(9) - '0'; 258 | 259 | for (int i = 0; i < MAX_CHILD_SOCKETS; i++) { 260 | if (_childSockets[i].socket == socket) { 261 | int commaIndex = urc.indexOf(','); 262 | if (commaIndex != -1) { 263 | _childSockets[i].available = urc.substring(commaIndex + 1).toInt(); 264 | } 265 | 266 | break; 267 | } 268 | } 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /src/GSMServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_SERVER_H_INCLUDED 21 | #define _GSM_SERVER_H_INCLUDED 22 | 23 | #include 24 | #include "GSMClient.h" 25 | 26 | #include "Modem.h" 27 | 28 | class GSMServer : public Server, public ModemUrcHandler { 29 | 30 | public: 31 | 32 | /** Constructor 33 | @param port Port 34 | @param synch True if the server acts synchronously 35 | */ 36 | GSMServer(uint16_t port, bool synch = true); 37 | 38 | ~GSMServer(); 39 | 40 | /** Get last command status 41 | @return returns 0 if last command is still executing, 1 success, >1 error 42 | */ 43 | int ready(); 44 | 45 | /** Initialize server 46 | */ 47 | void begin(); 48 | 49 | /** Check if there is an incoming client request 50 | @param synch If true, the returned client is synchronous or 51 | blocking. 52 | @return Client if successful, else error 53 | */ 54 | GSMClient available(bool synch = true); 55 | 56 | // Just to keep in line with Ethernet. 57 | // Write to every open socket... 58 | //void write(uint8_t); 59 | //void write(const uint8_t *buf, size_t size); 60 | 61 | /** Begin write in socket 62 | */ 63 | void beginWrite(); 64 | 65 | /** Write character in socket 66 | @param c Character 67 | @return size 68 | */ 69 | size_t write(uint8_t c); 70 | 71 | /** Write buffer in socket 72 | @param buf Buffer 73 | @return size 74 | */ 75 | size_t write(const uint8_t *buf); 76 | 77 | /** Write buffer in socket with size 78 | @param buf Buffer 79 | @param sz Buffer size 80 | @return size 81 | */ 82 | size_t write(const uint8_t *buf, size_t sz); 83 | 84 | /** End write in socket 85 | */ 86 | void endWrite(); 87 | 88 | /** Stop server 89 | */ 90 | void stop(); 91 | 92 | virtual void handleUrc(const String& urc); 93 | 94 | private: 95 | uint16_t _port; 96 | bool _synch; 97 | 98 | int _socket; 99 | int _state; 100 | String _response; 101 | 102 | #define MAX_CHILD_SOCKETS 6 103 | struct { 104 | int socket; 105 | bool accepted; 106 | int available; 107 | } _childSockets[MAX_CHILD_SOCKETS]; 108 | }; 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /src/GSMUdp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include 21 | 22 | #include "GSMUdp.h" 23 | 24 | GSMUDP::GSMUDP() : 25 | _socket(-1), 26 | _packetReceived(false), 27 | _txIp((uint32_t)0), 28 | _txHost(NULL), 29 | _txPort(0), 30 | _txSize(0), 31 | _rxIp((uint32_t)0), 32 | _rxPort(0), 33 | _rxSize(0), 34 | _rxIndex(0) 35 | { 36 | MODEM.addUrcHandler(this); 37 | } 38 | 39 | GSMUDP::~GSMUDP() 40 | { 41 | MODEM.removeUrcHandler(this); 42 | } 43 | 44 | uint8_t GSMUDP::begin(uint16_t port) 45 | { 46 | String response; 47 | 48 | MODEM.send("AT+USOCR=17"); 49 | 50 | if (MODEM.waitForResponse(100, &response) != 1) { 51 | return 0; 52 | } 53 | 54 | _socket = response.charAt(response.length() - 1) - '0'; 55 | 56 | MODEM.sendf("AT+USOLI=%d,%d", _socket, port); 57 | if (MODEM.waitForResponse(10000) != 1) { 58 | stop(); 59 | return 0; 60 | } 61 | 62 | return 1; 63 | } 64 | 65 | void GSMUDP::stop() 66 | { 67 | if (_socket < 0) { 68 | return; 69 | } 70 | 71 | MODEM.sendf("AT+USOCL=%d", _socket); 72 | MODEM.waitForResponse(10000); 73 | 74 | _socket = -1; 75 | } 76 | 77 | int GSMUDP::beginPacket(IPAddress ip, uint16_t port) 78 | { 79 | if (_socket < 0) { 80 | return 0; 81 | } 82 | 83 | _txIp = ip; 84 | _txHost = NULL; 85 | _txPort = port; 86 | _txSize = 0; 87 | 88 | return 1; 89 | } 90 | 91 | int GSMUDP::beginPacket(const char *host, uint16_t port) 92 | { 93 | if (_socket < 0) { 94 | return 0; 95 | } 96 | 97 | _txIp = (uint32_t)0; 98 | _txHost = host; 99 | _txPort = port; 100 | _txSize = 0; 101 | 102 | return 1; 103 | } 104 | 105 | int GSMUDP::endPacket() 106 | { 107 | String command; 108 | 109 | if (_txHost != NULL) { 110 | command.reserve(26 + strlen(_txHost) + _txSize * 2); 111 | } else { 112 | command.reserve(41 + _txSize * 2); 113 | } 114 | 115 | command += "AT+USOST="; 116 | command += _socket; 117 | command += ",\""; 118 | 119 | if (_txHost != NULL) { 120 | command += _txHost; 121 | } else { 122 | command += _txIp[0]; 123 | command += '.'; 124 | command += _txIp[1]; 125 | command += '.'; 126 | command += _txIp[2]; 127 | command += '.'; 128 | command += _txIp[3]; 129 | } 130 | 131 | command += "\","; 132 | command += _txPort; 133 | command += ",", 134 | command += _txSize; 135 | command += ",\""; 136 | 137 | for (size_t i = 0; i < _txSize; i++) { 138 | byte b = _txBuffer[i]; 139 | 140 | byte n1 = (b >> 4) & 0x0f; 141 | byte n2 = (b & 0x0f); 142 | 143 | command += (char)(n1 > 9 ? 'A' + n1 - 10 : '0' + n1); 144 | command += (char)(n2 > 9 ? 'A' + n2 - 10 : '0' + n2); 145 | } 146 | 147 | command += "\""; 148 | 149 | MODEM.send(command); 150 | 151 | if (MODEM.waitForResponse() == 1) { 152 | return 1; 153 | } else { 154 | return 0; 155 | } 156 | } 157 | 158 | size_t GSMUDP::write(uint8_t b) 159 | { 160 | return write(&b, sizeof(b)); 161 | } 162 | 163 | size_t GSMUDP::write(const uint8_t *buffer, size_t size) 164 | { 165 | if (_socket < 0) { 166 | return 0; 167 | } 168 | 169 | size_t spaceAvailable = sizeof(_txBuffer) - _txSize; 170 | 171 | if (size > spaceAvailable) { 172 | size = spaceAvailable; 173 | } 174 | 175 | memcpy(&_txBuffer[_txSize], buffer, size); 176 | _txSize += size; 177 | 178 | return size; 179 | } 180 | 181 | int GSMUDP::parsePacket() 182 | { 183 | MODEM.poll(); 184 | 185 | if (_socket < 0) { 186 | return 0; 187 | } 188 | 189 | if (!_packetReceived) { 190 | return 0; 191 | } 192 | _packetReceived = false; 193 | 194 | String response; 195 | 196 | MODEM.sendf("AT+USORF=%d,%d", _socket, sizeof(_rxBuffer)); 197 | if (MODEM.waitForResponse(10000, &response) != 1) { 198 | return 0; 199 | } 200 | 201 | if (!response.startsWith("+USORF: ")) { 202 | return 0; 203 | } 204 | 205 | response.remove(0, 11); 206 | 207 | int firstQuoteIndex = response.indexOf('"'); 208 | if (firstQuoteIndex == -1) { 209 | return 0; 210 | } 211 | 212 | String ip = response.substring(0, firstQuoteIndex); 213 | _rxIp.fromString(ip); 214 | 215 | response.remove(0, firstQuoteIndex + 2); 216 | 217 | int firstCommaIndex = response.indexOf(','); 218 | if (firstCommaIndex == -1) { 219 | return 0; 220 | } 221 | 222 | String port = response.substring(0, firstCommaIndex); 223 | _rxPort = port.toInt(); 224 | firstQuoteIndex = response.indexOf("\""); 225 | 226 | response.remove(0, firstQuoteIndex + 1); 227 | response.remove(response.length() - 1); 228 | 229 | _rxIndex = 0; 230 | _rxSize = response.length() / 2; 231 | 232 | for (size_t i = 0; i < _rxSize; i++) { 233 | byte n1 = response[i * 2]; 234 | byte n2 = response[i * 2 + 1]; 235 | 236 | if (n1 > '9') { 237 | n1 = (n1 - 'A') + 10; 238 | } else { 239 | n1 = (n1 - '0'); 240 | } 241 | 242 | if (n2 > '9') { 243 | n2 = (n2 - 'A') + 10; 244 | } else { 245 | n2 = (n2 - '0'); 246 | } 247 | 248 | _rxBuffer[i] = (n1 << 4) | n2; 249 | } 250 | 251 | MODEM.poll(); 252 | 253 | return _rxSize; 254 | } 255 | 256 | int GSMUDP::available() 257 | { 258 | if (_socket < 0) { 259 | return 0; 260 | } 261 | 262 | return (_rxSize - _rxIndex); 263 | } 264 | 265 | int GSMUDP::read() 266 | { 267 | byte b; 268 | 269 | if (read(&b, sizeof(b)) == 1) { 270 | return b; 271 | } 272 | 273 | return -1; 274 | } 275 | 276 | int GSMUDP::read(unsigned char* buffer, size_t len) 277 | { 278 | size_t readMax = available(); 279 | 280 | if (len > readMax) { 281 | len = readMax; 282 | } 283 | 284 | memcpy(buffer, &_rxBuffer[_rxIndex], len); 285 | 286 | _rxIndex += len; 287 | 288 | return len; 289 | } 290 | 291 | int GSMUDP::peek() 292 | { 293 | if (available() > 1) { 294 | return _rxBuffer[_rxIndex]; 295 | } 296 | 297 | return -1; 298 | } 299 | 300 | void GSMUDP::flush() 301 | { 302 | } 303 | 304 | IPAddress GSMUDP::remoteIP() 305 | { 306 | return _rxIp; 307 | } 308 | 309 | uint16_t GSMUDP::remotePort() 310 | { 311 | return _rxPort; 312 | } 313 | 314 | void GSMUDP::handleUrc(const String& urc) 315 | { 316 | if (urc.startsWith("+UUSORF: ")) { 317 | int socket = urc.charAt(9) - '0'; 318 | 319 | if (socket == _socket) { 320 | _packetReceived = true; 321 | } 322 | } else if (urc.startsWith("+UUSOCL: ")) { 323 | int socket = urc.charAt(urc.length() - 1) - '0'; 324 | 325 | if (socket == _socket) { 326 | // this socket closed 327 | _socket = -1; 328 | _rxIndex = 0; 329 | _rxSize = 0; 330 | } 331 | } 332 | } 333 | -------------------------------------------------------------------------------- /src/GSMUdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_UDP_H_INCLUDED 21 | #define _GSM_UDP_H_INCLUDED 22 | 23 | #include 24 | 25 | #include "Modem.h" 26 | 27 | class GSMUDP : public UDP, public ModemUrcHandler { 28 | 29 | public: 30 | GSMUDP(); // Constructor 31 | virtual ~GSMUDP(); 32 | 33 | virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use 34 | virtual void stop(); // Finish with the UDP socket 35 | 36 | // Sending UDP packets 37 | 38 | // Start building up a packet to send to the remote host specified by ip and port 39 | // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port 40 | virtual int beginPacket(IPAddress ip, uint16_t port); 41 | // Start building up a packet to send to the remote host specified by ip and port 42 | // Returns 1 if successful, 0 if there was a problem resolving the hostname or port 43 | virtual int beginPacket(const char *host, uint16_t port); 44 | // Finish off this packet and send it 45 | // Returns 1 if the packet was sent successfully, 0 if there was an error 46 | virtual int endPacket(); 47 | // Write a single byte into the packet 48 | virtual size_t write(uint8_t); 49 | // Write size bytes from buffer into the packet 50 | virtual size_t write(const uint8_t *buffer, size_t size); 51 | 52 | using Print::write; 53 | 54 | // Start processing the next available incoming packet 55 | // Returns the size of the packet in bytes, or 0 if no packets are available 56 | virtual int parsePacket(); 57 | // Number of bytes remaining in the current packet 58 | virtual int available(); 59 | // Read a single byte from the current packet 60 | virtual int read(); 61 | // Read up to len bytes from the current packet and place them into buffer 62 | // Returns the number of bytes read, or 0 if none are available 63 | virtual int read(unsigned char* buffer, size_t len); 64 | // Read up to len characters from the current packet and place them into buffer 65 | // Returns the number of characters read, or 0 if none are available 66 | virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; 67 | // Return the next byte from the current packet without moving on to the next byte 68 | virtual int peek(); 69 | virtual void flush(); // Finish reading the current packet 70 | 71 | // Return the IP address of the host who sent the current incoming packet 72 | virtual IPAddress remoteIP(); 73 | // Return the port of the host who sent the current incoming packet 74 | virtual uint16_t remotePort(); 75 | 76 | virtual void handleUrc(const String& urc); 77 | 78 | private: 79 | int _socket; 80 | bool _packetReceived; 81 | 82 | IPAddress _txIp; 83 | const char* _txHost; 84 | uint16_t _txPort; 85 | size_t _txSize; 86 | uint8_t _txBuffer[512]; 87 | 88 | IPAddress _rxIp; 89 | uint16_t _rxPort; 90 | size_t _rxSize; 91 | size_t _rxIndex; 92 | uint8_t _rxBuffer[512]; 93 | }; 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /src/GSMVoiceCall.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "GSMVoiceCall.h" 21 | 22 | GSMVoiceCall::GSMVoiceCall(bool synch) : 23 | _synch(synch), 24 | _callStatus(IDLE_CALL) 25 | { 26 | MODEM.addUrcHandler(this); 27 | } 28 | 29 | GSMVoiceCall::~GSMVoiceCall() 30 | { 31 | MODEM.removeUrcHandler(this); 32 | } 33 | 34 | GSM3_voiceCall_st GSMVoiceCall::getvoiceCallStatus() 35 | { 36 | MODEM.poll(); 37 | 38 | return _callStatus; 39 | } 40 | 41 | int GSMVoiceCall::ready() 42 | { 43 | return MODEM.ready(); 44 | } 45 | 46 | int GSMVoiceCall::voiceCall(const char* to, unsigned long timeout) 47 | { 48 | if (_synch) { 49 | while (ready() == 0); 50 | } else { 51 | int r = ready(); 52 | 53 | if (r == 0) { 54 | return 0; 55 | } 56 | } 57 | 58 | MODEM.sendf("ATD%s;", to); 59 | 60 | if (_synch) { 61 | if (MODEM.waitForResponse(180000) != 1) { 62 | return 0; 63 | } 64 | 65 | _callStatus = CALLING; 66 | for (unsigned long start = millis(); (timeout == 0) || ((millis() - start) < timeout);) { 67 | if (getvoiceCallStatus() != CALLING) { 68 | break; 69 | } 70 | } 71 | 72 | if (getvoiceCallStatus() != TALKING) { 73 | hangCall(); 74 | return 0; 75 | } 76 | 77 | return 1; 78 | } else { 79 | return ready(); 80 | } 81 | } 82 | 83 | int GSMVoiceCall::answerCall() 84 | { 85 | if (_synch) { 86 | while (ready() == 0); 87 | } else { 88 | int r = ready(); 89 | 90 | if (r == 0) { 91 | return 0; 92 | } 93 | } 94 | 95 | MODEM.send("ATA"); 96 | 97 | if (_synch) { 98 | if (MODEM.waitForResponse(20000) == 1) { 99 | return 1; 100 | } 101 | } 102 | 103 | return 0; 104 | } 105 | 106 | int GSMVoiceCall::hangCall() 107 | { 108 | if (_synch) { 109 | while (ready() == 0); 110 | } else { 111 | int r = ready(); 112 | 113 | if (r == 0) { 114 | return 0; 115 | } 116 | } 117 | 118 | MODEM.send("ATH"); 119 | 120 | if (_synch) { 121 | if (MODEM.waitForResponse(200000) == 1) { 122 | return 1; 123 | } 124 | } 125 | 126 | return 0; 127 | } 128 | 129 | int GSMVoiceCall::retrieveCallingNumber(char* buffer, int bufsize) 130 | { 131 | String response; 132 | 133 | if (_synch) { 134 | while (ready() == 0); 135 | } else { 136 | int r = ready(); 137 | 138 | if (r == 0) { 139 | return 0; 140 | } 141 | } 142 | 143 | MODEM.send("AT+CLCC"); 144 | if (MODEM.waitForResponse(100, &response) == 1) { 145 | int phoneNumberStartIndex = response.indexOf("\""); 146 | if (phoneNumberStartIndex != -1) { 147 | int i = phoneNumberStartIndex + 1; 148 | 149 | while (i < (int)response.length() && bufsize > 1) { 150 | char c = response[i]; 151 | 152 | if (c == '"') { 153 | break; 154 | } 155 | 156 | *buffer++ = c; 157 | bufsize--; 158 | i++; 159 | } 160 | 161 | *buffer = '\0'; 162 | return 1; 163 | } else { 164 | *buffer = '\0'; 165 | } 166 | } 167 | 168 | return 0; 169 | } 170 | 171 | int GSMVoiceCall::enableI2SInput(long sampleRate) 172 | { 173 | if (disableI2SInput() == 0) { 174 | return 0; 175 | } 176 | 177 | int sampleRateNumber; 178 | 179 | switch(sampleRate) { 180 | case 8000: 181 | sampleRateNumber = 0; 182 | break; 183 | 184 | case 11025: 185 | sampleRateNumber = 1; 186 | break; 187 | 188 | case 12000: 189 | sampleRateNumber = 2; 190 | break; 191 | 192 | case 16000: 193 | sampleRateNumber = 3; 194 | break; 195 | 196 | case 22050: 197 | sampleRateNumber = 4; 198 | break; 199 | 200 | case 24000: 201 | sampleRateNumber = 5; 202 | break; 203 | 204 | case 32000: 205 | sampleRateNumber = 6; 206 | break; 207 | 208 | case 44100: 209 | sampleRateNumber = 7; 210 | break; 211 | 212 | case 48000: 213 | sampleRateNumber = 8; 214 | break; 215 | 216 | default: 217 | return 0; 218 | break; 219 | } 220 | 221 | MODEM.sendf("AT+UI2S=11,1,0,%d,1", sampleRateNumber); // mode, port, WA, sample rate, slave 222 | if (MODEM.waitForResponse() != 1) { 223 | return 0; 224 | } 225 | 226 | // enable 227 | MODEM.send("AT+USPM=1,1,0,0,2"); 228 | if (MODEM.waitForResponse() != 1) { 229 | return 0; 230 | } 231 | 232 | return 1; 233 | } 234 | 235 | int GSMVoiceCall::peekDTMF() 236 | { 237 | MODEM.poll(); 238 | 239 | if (_dtmfBuffer.length()) { 240 | return _dtmfBuffer.charAt(0); 241 | } 242 | 243 | return -1; 244 | } 245 | 246 | int GSMVoiceCall::readDTMF() 247 | { 248 | MODEM.poll(); 249 | 250 | if (_dtmfBuffer.length()) { 251 | char c = _dtmfBuffer.charAt(0); 252 | 253 | _dtmfBuffer.remove(0, 1); 254 | 255 | return c; 256 | } 257 | 258 | return -1; 259 | } 260 | 261 | int GSMVoiceCall::writeDTMF(char c) 262 | { 263 | switch (c) { 264 | case '0': 265 | case '1': 266 | case '2': 267 | case '3': 268 | case '4': 269 | case '5': 270 | case '6': 271 | case '7': 272 | case '8': 273 | case '9': 274 | case '#': 275 | case '*': 276 | case 'A': 277 | case 'B': 278 | case 'C': 279 | case 'D': 280 | break; 281 | 282 | default: 283 | return 0; // invalid 284 | break; 285 | } 286 | 287 | MODEM.sendf("AT+VTS=%c", c); 288 | 289 | if (MODEM.waitForResponse(420000) != 1) { 290 | return 0; 291 | } 292 | 293 | return 1; 294 | } 295 | 296 | int GSMVoiceCall::disableI2SInput() 297 | { 298 | MODEM.send("AT+USPM=255,255,0,0,2"); 299 | 300 | if (MODEM.waitForResponse() == 1) { 301 | return 1; 302 | } 303 | 304 | return 0; 305 | } 306 | 307 | void GSMVoiceCall::handleUrc(const String& urc) 308 | { 309 | if (urc.startsWith("+UCALLSTAT: ")) { 310 | int status = urc.charAt(urc.length() - 1) - '0'; 311 | 312 | if (status == 0 || status == 1 || status == 7) { 313 | _callStatus = TALKING; 314 | _dtmfBuffer = ""; 315 | } else if (status == 2 || status == 3) { 316 | _callStatus = CALLING; 317 | } else if (status == 4 || status == 5) { 318 | _callStatus = RECEIVINGCALL; 319 | } else { 320 | _callStatus = IDLE_CALL; 321 | } 322 | } else if (urc.startsWith("+UUDTMFD: ")) { 323 | _dtmfBuffer += urc.charAt(10); 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /src/GSMVoiceCall.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_VOICE_CALL_H_INCLUDED 21 | #define _GSM_VOICE_CALL_H_INCLUDED 22 | 23 | #include "Modem.h" 24 | 25 | enum GSM3_voiceCall_st { IDLE_CALL, CALLING, RECEIVINGCALL, TALKING}; 26 | 27 | class GSMVoiceCall : public ModemUrcHandler { 28 | 29 | public: 30 | /** Service creation 31 | @param synch If true, the service calls are synchronous 32 | */ 33 | GSMVoiceCall(bool synch = true); 34 | 35 | virtual ~GSMVoiceCall(); 36 | 37 | /** Voice call status 38 | @return Status of the voice call, as described in GSM3MobileVoiceProvider.h 39 | { IDLE_CALL, CALLING, RECEIVINGCALL, TALKING}; 40 | */ 41 | GSM3_voiceCall_st getvoiceCallStatus(); 42 | 43 | /** Get last command status 44 | @return Returns 0 if last command is still executing, 1 success, >1 error 45 | */ 46 | int ready(); 47 | 48 | /** Place a voice call. If asynchronous, returns while ringing. If synchronous 49 | returns if the call is established or cancelled. 50 | @param to Receiver number. Country extension can be used or not. 51 | Char buffer should not be released or used until command is over 52 | @param timeout In milliseconds. Time ringing before closing the call. 53 | Only used in synchronous mode. 54 | If zero, ring indefinitely 55 | @return In asynchronous mode returns 0 if last command is still executing, 1 success, >1 error 56 | In synchronous mode returns 1 if the call is placed, 0 if not. 57 | */ 58 | int voiceCall(const char* to, unsigned long timeout = 30000); 59 | 60 | /** Accept an incoming voice call 61 | @return In asynchronous mode returns 0 if last command is still executing, 1 success, >1 error 62 | In synchronous mode returns 1 if the call is answered, 0 if not. 63 | */ 64 | int answerCall(); 65 | 66 | /** Hang an established call or an incoming ring 67 | @return In asynchronous mode returns 0 if last command is still executing, 1 success, >1 error 68 | In synchronous mode returns 1 if the call is answered, 0 if not. 69 | */ 70 | int hangCall(); 71 | 72 | /** Retrieve the calling number, put it in buffer 73 | @param buffer pointer to the buffer memory 74 | @param bufsize size of available memory area, at least should be 10 characters 75 | @return In asynchronous mode returns 0 if last command is still executing, 1 success, >1 error 76 | In synchronous mode returns 1 if the number is correctly taken 0 if not 77 | */ 78 | int retrieveCallingNumber(char* buffer, int bufsize); 79 | 80 | int peekDTMF(); 81 | int readDTMF(); 82 | int writeDTMF(char c); 83 | 84 | int enableI2SInput(long sampleRate); 85 | int disableI2SInput(); 86 | 87 | virtual void handleUrc(const String& urc); 88 | private: 89 | int _synch; 90 | GSM3_voiceCall_st _callStatus; 91 | String _dtmfBuffer; 92 | }; 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/GSM_SMS.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "Modem.h" 21 | 22 | #include "GSM_SMS.h" 23 | 24 | enum { 25 | SMS_STATE_IDLE, 26 | SMS_STATE_LIST_MESSAGES, 27 | SMS_STATE_WAIT_LIST_MESSAGES_RESPONSE 28 | }; 29 | 30 | GSM_SMS::GSM_SMS(bool synch) : 31 | _synch(synch), 32 | _state(SMS_STATE_IDLE), 33 | _smsTxActive(false) 34 | { 35 | } 36 | 37 | size_t GSM_SMS::write(uint8_t c) 38 | { 39 | if (_smsTxActive) { 40 | return MODEM.write(c); 41 | } 42 | 43 | return 0; 44 | } 45 | 46 | int GSM_SMS::beginSMS(const char* to) 47 | { 48 | MODEM.sendf("AT+CMGS=\"%s\"", to); 49 | if (MODEM.waitForResponse(100) == 2) { 50 | _smsTxActive = false; 51 | 52 | return (_synch) ? 0 : 2; 53 | } 54 | 55 | _smsTxActive = true; 56 | 57 | return 1; 58 | } 59 | 60 | int GSM_SMS::ready() 61 | { 62 | int ready = MODEM.ready(); 63 | 64 | if (ready == 0) { 65 | return 0; 66 | } 67 | 68 | switch(_state) { 69 | case SMS_STATE_IDLE: 70 | default: { 71 | break; 72 | } 73 | 74 | case SMS_STATE_LIST_MESSAGES: { 75 | MODEM.setResponseDataStorage(&_incomingBuffer); 76 | MODEM.send("AT+CMGL=\"REC UNREAD\""); 77 | _state = SMS_STATE_WAIT_LIST_MESSAGES_RESPONSE; 78 | ready = 0; 79 | break; 80 | } 81 | 82 | case SMS_STATE_WAIT_LIST_MESSAGES_RESPONSE: { 83 | _state = SMS_STATE_IDLE; 84 | break; 85 | } 86 | } 87 | 88 | return ready; 89 | } 90 | 91 | int GSM_SMS::endSMS() 92 | { 93 | int r; 94 | 95 | if (_smsTxActive) { 96 | MODEM.write(26); 97 | 98 | if (_synch) { 99 | while ((r = MODEM.ready()) == 0) { 100 | delay(100); 101 | } 102 | } else { 103 | r = MODEM.ready(); 104 | } 105 | 106 | return r; 107 | } else { 108 | return (_synch ? 0 : 2); 109 | } 110 | } 111 | 112 | int GSM_SMS::available() 113 | { 114 | if (_incomingBuffer.length() != 0) { 115 | int nextMessageIndex = _incomingBuffer.indexOf("\r\n+CMGL: "); 116 | 117 | if (nextMessageIndex != -1) { 118 | _incomingBuffer.remove(0, nextMessageIndex + 2); 119 | } else { 120 | _incomingBuffer = ""; 121 | } 122 | } 123 | 124 | if (_incomingBuffer.length() == 0) { 125 | int r; 126 | 127 | if (_state == SMS_STATE_IDLE) { 128 | _state = SMS_STATE_LIST_MESSAGES; 129 | } 130 | 131 | if (_synch) { 132 | while ((r = ready()) == 0) { 133 | delay(100); 134 | } 135 | } else { 136 | r = ready(); 137 | } 138 | 139 | if (r != 1) { 140 | return 0; 141 | } 142 | } 143 | 144 | if (_incomingBuffer.startsWith("+CMGL: ")) { 145 | _smsDataIndex = _incomingBuffer.indexOf('\n') + 1; 146 | 147 | _smsDataEndIndex = _incomingBuffer.indexOf("\r\n+CMGL: "); 148 | if (_smsDataEndIndex == -1) { 149 | _smsDataEndIndex = _incomingBuffer.length() - 1; 150 | } 151 | 152 | return (_smsDataEndIndex - _smsDataIndex) + 1; 153 | } else { 154 | _incomingBuffer = ""; 155 | } 156 | 157 | return 0; 158 | } 159 | 160 | int GSM_SMS::remoteNumber(char* number, int nlength) 161 | { 162 | #define PHONE_NUMBER_START_SEARCH_PATTERN "\"REC UNREAD\",\"" 163 | int phoneNumberStartIndex = _incomingBuffer.indexOf(PHONE_NUMBER_START_SEARCH_PATTERN); 164 | 165 | if (phoneNumberStartIndex != -1) { 166 | int i = phoneNumberStartIndex + sizeof(PHONE_NUMBER_START_SEARCH_PATTERN) - 1; 167 | 168 | while (i < (int)_incomingBuffer.length() && nlength > 1) { 169 | char c = _incomingBuffer[i]; 170 | 171 | if (c == '"') { 172 | break; 173 | } 174 | 175 | *number++ = c; 176 | nlength--; 177 | i++; 178 | } 179 | 180 | *number = '\0'; 181 | return 1; 182 | } else { 183 | *number = '\0'; 184 | } 185 | 186 | return 2; 187 | } 188 | 189 | int GSM_SMS::read() 190 | { 191 | int bufferLength = _incomingBuffer.length(); 192 | 193 | if (_smsDataIndex < bufferLength && _smsDataIndex <= _smsDataEndIndex) { 194 | return _incomingBuffer[_smsDataIndex++]; 195 | } 196 | 197 | return -1; 198 | } 199 | 200 | int GSM_SMS::peek() 201 | { 202 | if (_smsDataIndex < (int)_incomingBuffer.length() && _smsDataIndex <= _smsDataEndIndex) { 203 | return _incomingBuffer[_smsDataIndex]; 204 | } 205 | 206 | return -1; 207 | } 208 | 209 | void GSM_SMS::flush() 210 | { 211 | int smsIndexStart = _incomingBuffer.indexOf(' '); 212 | int smsIndexEnd = _incomingBuffer.indexOf(','); 213 | 214 | if (smsIndexStart != -1 && smsIndexEnd != -1) { 215 | while (MODEM.ready() == 0); 216 | 217 | MODEM.sendf("AT+CMGD=%s", _incomingBuffer.substring(smsIndexStart + 1, smsIndexEnd).c_str()); 218 | 219 | if (_synch) { 220 | MODEM.waitForResponse(55000); 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/GSM_SMS.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSM_SMS_H_INCLUDED 21 | #define _GSM_SMS_H_INCLUDED 22 | 23 | #include 24 | 25 | class GSM_SMS : public Stream { 26 | 27 | public: 28 | /** Constructor 29 | @param synch Determines sync mode 30 | */ 31 | GSM_SMS(bool synch = true); 32 | 33 | /** Write a character in SMS message 34 | @param c Character 35 | @return size 36 | */ 37 | size_t write(uint8_t c); 38 | 39 | /** Begin a SMS to send it 40 | @param to Destination 41 | @return error command if it exists 42 | */ 43 | int beginSMS(const char* to); 44 | 45 | /** Get last command status 46 | @return returns 0 if last command is still executing, 1 success, >1 error 47 | */ 48 | int ready(); 49 | 50 | /** End SMS 51 | @return error command if it exists 52 | */ 53 | int endSMS(); 54 | 55 | /** Check if SMS available and prepare it to be read 56 | @return number of bytes in a received SMS 57 | */ 58 | int available(); 59 | 60 | /** Read sender number phone 61 | @param number Buffer for save number phone 62 | @param nlength Buffer length 63 | @return 1 success, >1 error 64 | */ 65 | int remoteNumber(char* number, int nlength); 66 | 67 | /** Read one char for SMS buffer (advance circular buffer) 68 | @return byte 69 | */ 70 | int read(); 71 | 72 | /** Read a byte but do not advance the buffer header (circular buffer) 73 | @return byte 74 | */ 75 | int peek(); 76 | 77 | /** Delete the SMS from Modem memory and process answer 78 | */ 79 | void flush(); 80 | 81 | private: 82 | bool _synch; 83 | int _state; 84 | String _incomingBuffer; 85 | int _smsDataIndex; 86 | int _smsDataEndIndex; 87 | bool _smsTxActive; 88 | }; 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/MKRGSM.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _MKRGSM_H_INCLUDED 21 | #define _MKRGSM_H_INCLUDED 22 | 23 | #include "GSM.h" 24 | #include "GSMVoiceCall.h" 25 | #include "GSM_SMS.h" 26 | #include "GPRS.h" 27 | #include "GSMClient.h" 28 | #include "GSMServer.h" 29 | #include "GSMModem.h" 30 | #include "GSMScanner.h" 31 | #include "GSMPIN.h" 32 | #include "GSMBand.h" 33 | 34 | #include "GSMSSLClient.h" 35 | #include "GSMUdp.h" 36 | #include "GSMLocation.h" 37 | 38 | #include "GSMFileUtils.h" 39 | #include "GSMHttpUtils.h" 40 | #endif 41 | -------------------------------------------------------------------------------- /src/Modem.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include "Modem.h" 21 | 22 | #define MODEM_MIN_RESPONSE_OR_URC_WAIT_TIME_MS 20 23 | 24 | ModemUrcHandler* ModemClass::_urcHandlers[MAX_URC_HANDLERS] = { NULL }; 25 | Print* ModemClass::_debugPrint = NULL; 26 | 27 | ModemClass::ModemClass(Uart& uart, unsigned long baud, int resetPin, int dtrPin) : 28 | _uart(&uart), 29 | _baud(baud), 30 | _resetPin(resetPin), 31 | _dtrPin(dtrPin), 32 | _lowPowerMode(false), 33 | _lastResponseOrUrcMillis(0), 34 | _atCommandState(AT_COMMAND_IDLE), 35 | _ready(1), 36 | _responseDataStorage(NULL) 37 | { 38 | _buffer.reserve(64); 39 | } 40 | 41 | int ModemClass::begin(bool restart) 42 | { 43 | _uart->begin(_baud > 115200 ? 115200 : _baud); 44 | 45 | if (_resetPin > -1 && restart) { 46 | pinMode(_resetPin, OUTPUT); 47 | digitalWrite(_resetPin, HIGH); 48 | delayMicroseconds(150); 49 | digitalWrite(_resetPin, LOW); 50 | delay(3); 51 | digitalWrite(_resetPin, HIGH); 52 | delay(600); 53 | digitalWrite(_resetPin, LOW); 54 | } else { 55 | if (!autosense()) { 56 | return 0; 57 | } 58 | 59 | if (!reset()) { 60 | return 0; 61 | } 62 | } 63 | 64 | if (!autosense()) { 65 | return 0; 66 | } 67 | 68 | if (_baud > 115200) { 69 | sendf("AT+IPR=%ld", _baud); 70 | if (waitForResponse() != 1) { 71 | return 0; 72 | } 73 | 74 | _uart->end(); 75 | delay(100); 76 | _uart->begin(_baud); 77 | 78 | if (!autosense()) { 79 | return 0; 80 | } 81 | } 82 | 83 | if (_dtrPin > -1) { 84 | pinMode(_dtrPin, OUTPUT); 85 | noLowPowerMode(); 86 | 87 | send("AT+UPSV=3"); 88 | if (waitForResponse() != 1) { 89 | return 0; 90 | } 91 | } 92 | 93 | return 1; 94 | } 95 | 96 | void ModemClass::end() 97 | { 98 | _uart->end(); 99 | digitalWrite(_resetPin, HIGH); 100 | 101 | if (_dtrPin > -1) { 102 | digitalWrite(_dtrPin, LOW); 103 | } 104 | } 105 | 106 | void ModemClass::debug() 107 | { 108 | debug(Serial); 109 | } 110 | 111 | void ModemClass::debug(Print& p) 112 | { 113 | _debugPrint = &p; 114 | } 115 | 116 | void ModemClass::noDebug() 117 | { 118 | _debugPrint = NULL; 119 | } 120 | 121 | int ModemClass::autosense(unsigned int timeout) 122 | { 123 | for (unsigned long start = millis(); (millis() - start) < timeout;) { 124 | if (noop() == 1) { 125 | return 1; 126 | } 127 | 128 | delay(100); 129 | } 130 | 131 | return 0; 132 | } 133 | 134 | int ModemClass::noop() 135 | { 136 | send("AT"); 137 | 138 | return (waitForResponse() == 1); 139 | } 140 | 141 | int ModemClass::reset() 142 | { 143 | send("AT+CFUN=16"); 144 | 145 | return (waitForResponse(1000) == 1); 146 | } 147 | 148 | int ModemClass::lowPowerMode() 149 | { 150 | if (_dtrPin > -1) { 151 | _lowPowerMode = true; 152 | 153 | digitalWrite(_dtrPin, HIGH); 154 | 155 | return 1; 156 | } 157 | 158 | return 0; 159 | } 160 | 161 | int ModemClass::noLowPowerMode() 162 | { 163 | if (_dtrPin > -1) { 164 | _lowPowerMode = false; 165 | 166 | digitalWrite(_dtrPin, LOW); 167 | 168 | return 1; 169 | } 170 | 171 | return 0; 172 | } 173 | 174 | size_t ModemClass::write(uint8_t c) 175 | { 176 | return _uart->write(c); 177 | } 178 | 179 | size_t ModemClass::write(const uint8_t* buf, size_t size) 180 | { 181 | return _uart->write(buf, size); 182 | } 183 | 184 | void ModemClass::send(const char* command) 185 | { 186 | if (_lowPowerMode) { 187 | digitalWrite(_dtrPin, LOW); 188 | delay(5); 189 | } 190 | 191 | // compare the time of the last response or URC and ensure 192 | // at least 20ms have passed before sending a new command 193 | unsigned long delta = millis() - _lastResponseOrUrcMillis; 194 | if(delta < MODEM_MIN_RESPONSE_OR_URC_WAIT_TIME_MS) { 195 | delay(MODEM_MIN_RESPONSE_OR_URC_WAIT_TIME_MS - delta); 196 | } 197 | 198 | _uart->println(command); 199 | _uart->flush(); 200 | _atCommandState = AT_COMMAND_IDLE; 201 | _ready = 0; 202 | } 203 | 204 | void ModemClass::sendf(const char *fmt, ...) 205 | { 206 | char buf[BUFSIZ]; 207 | 208 | va_list ap; 209 | va_start((ap), (fmt)); 210 | vsnprintf(buf, sizeof(buf) - 1, fmt, ap); 211 | va_end(ap); 212 | 213 | send(buf); 214 | } 215 | 216 | int ModemClass::waitForResponse(unsigned long timeout, String* responseDataStorage) 217 | { 218 | _responseDataStorage = responseDataStorage; 219 | for (unsigned long start = millis(); (millis() - start) < timeout;) { 220 | int r = ready(); 221 | 222 | if (r != 0) { 223 | _responseDataStorage = NULL; 224 | return r; 225 | } 226 | } 227 | 228 | _responseDataStorage = NULL; 229 | _buffer = ""; 230 | return -1; 231 | } 232 | 233 | int ModemClass::waitForPrompt(unsigned long timeout) 234 | { 235 | for (unsigned long start = millis(); (millis() - start) < timeout;) { 236 | ready(); 237 | 238 | if (_buffer.endsWith(">")) { 239 | return 1; 240 | } 241 | } 242 | 243 | return -1; 244 | } 245 | 246 | int ModemClass::ready() 247 | { 248 | poll(); 249 | 250 | return _ready; 251 | } 252 | 253 | void ModemClass::poll() 254 | { 255 | while (_uart->available()) { 256 | char c = _uart->read(); 257 | 258 | if (_debugPrint) { 259 | _debugPrint->write(c); 260 | } 261 | 262 | _buffer += c; 263 | 264 | switch (_atCommandState) { 265 | case AT_COMMAND_IDLE: 266 | default: { 267 | 268 | if (_buffer.startsWith("AT") && _buffer.endsWith("\r\n")) { 269 | _atCommandState = AT_RECEIVING_RESPONSE; 270 | _buffer = ""; 271 | } else if (_buffer.endsWith("\r\n")) { 272 | _buffer.trim(); 273 | 274 | if (_buffer.length()) { 275 | _lastResponseOrUrcMillis = millis(); 276 | 277 | for (int i = 0; i < MAX_URC_HANDLERS; i++) { 278 | if (_urcHandlers[i] != NULL) { 279 | _urcHandlers[i]->handleUrc(_buffer); 280 | } 281 | } 282 | } 283 | 284 | _buffer = ""; 285 | } 286 | 287 | break; 288 | } 289 | 290 | case AT_RECEIVING_RESPONSE: { 291 | if (c == '\n') { 292 | _lastResponseOrUrcMillis = millis(); 293 | 294 | int responseResultIndex = _buffer.lastIndexOf("OK\r\n"); 295 | if (responseResultIndex != -1) { 296 | _ready = 1; 297 | } else { 298 | responseResultIndex = _buffer.lastIndexOf("ERROR\r\n"); 299 | if (responseResultIndex != -1) { 300 | _ready = 2; 301 | } else { 302 | responseResultIndex = _buffer.lastIndexOf("NO CARRIER\r\n"); 303 | if (responseResultIndex != -1) { 304 | _ready = 3; 305 | } 306 | } 307 | } 308 | 309 | if (_ready != 0) { 310 | if (_lowPowerMode) { 311 | digitalWrite(_dtrPin, HIGH); 312 | } 313 | 314 | if (_responseDataStorage != NULL) { 315 | _buffer.remove(responseResultIndex); 316 | _buffer.trim(); 317 | 318 | *_responseDataStorage = _buffer; 319 | 320 | _responseDataStorage = NULL; 321 | } 322 | 323 | _atCommandState = AT_COMMAND_IDLE; 324 | _buffer = ""; 325 | return; 326 | } 327 | } 328 | break; 329 | } 330 | } 331 | } 332 | } 333 | 334 | void ModemClass::setResponseDataStorage(String* responseDataStorage) 335 | { 336 | _responseDataStorage = responseDataStorage; 337 | } 338 | 339 | void ModemClass::addUrcHandler(ModemUrcHandler* handler) 340 | { 341 | for (int i = 0; i < MAX_URC_HANDLERS; i++) { 342 | if (_urcHandlers[i] == NULL) { 343 | _urcHandlers[i] = handler; 344 | break; 345 | } 346 | } 347 | } 348 | 349 | void ModemClass::removeUrcHandler(ModemUrcHandler* handler) 350 | { 351 | for (int i = 0; i < MAX_URC_HANDLERS; i++) { 352 | if (_urcHandlers[i] == handler) { 353 | _urcHandlers[i] = NULL; 354 | break; 355 | } 356 | } 357 | } 358 | 359 | void ModemClass::setBaudRate(unsigned long baud) 360 | { 361 | _baud = baud; 362 | } 363 | 364 | ModemClass MODEM(SerialGSM, 921600, GSM_RESETN, GSM_DTR); 365 | -------------------------------------------------------------------------------- /src/Modem.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2017 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _MODEM_INCLUDED_H 21 | #define _MODEM_INCLUDED_H 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | class ModemUrcHandler { 29 | public: 30 | virtual void handleUrc(const String& urc) = 0; 31 | }; 32 | 33 | class ModemClass { 34 | public: 35 | ModemClass(Uart& uart, unsigned long baud, int resetPin, int dtrPin); 36 | 37 | int begin(bool restart = true); 38 | void end(); 39 | 40 | void debug(); 41 | void debug(Print& p); 42 | void noDebug(); 43 | 44 | int autosense(unsigned int timeout = 10000); 45 | 46 | int noop(); 47 | int reset(); 48 | 49 | int lowPowerMode(); 50 | int noLowPowerMode(); 51 | 52 | size_t write(uint8_t c); 53 | size_t write(const uint8_t*, size_t); 54 | 55 | void send(const char* command); 56 | void send(const String& command) { send(command.c_str()); } 57 | void sendf(const char *fmt, ...); 58 | 59 | int waitForResponse(unsigned long timeout = 100, String* responseDataStorage = NULL); 60 | int waitForPrompt(unsigned long timeout = 500); 61 | int ready(); 62 | void poll(); 63 | void setResponseDataStorage(String* responseDataStorage); 64 | 65 | void addUrcHandler(ModemUrcHandler* handler); 66 | void removeUrcHandler(ModemUrcHandler* handler); 67 | 68 | void setBaudRate(unsigned long baud); 69 | 70 | private: 71 | Uart* _uart; 72 | unsigned long _baud; 73 | int _resetPin; 74 | int _dtrPin; 75 | bool _lowPowerMode; 76 | unsigned long _lastResponseOrUrcMillis; 77 | 78 | enum { 79 | AT_COMMAND_IDLE, 80 | AT_RECEIVING_RESPONSE 81 | } _atCommandState; 82 | int _ready; 83 | String _buffer; 84 | String* _responseDataStorage; 85 | 86 | #define MAX_URC_HANDLERS 10 // 7 sockets + GPRS + GSMLocation + GSMVoiceCall 87 | static ModemUrcHandler* _urcHandlers[MAX_URC_HANDLERS]; 88 | static Print* _debugPrint; 89 | }; 90 | 91 | extern ModemClass MODEM; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /src/utility/GSMSocketBuffer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2018 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include "Modem.h" 24 | 25 | #include "GSMSocketBuffer.h" 26 | 27 | #define GSM_SOCKET_NUM_BUFFERS (sizeof(_buffers) / sizeof(_buffers[0])) 28 | 29 | #define GSM_SOCKET_BUFFER_SIZE 512 30 | 31 | GSMSocketBufferClass::GSMSocketBufferClass() 32 | { 33 | memset(&_buffers, 0x00, sizeof(_buffers)); 34 | } 35 | 36 | GSMSocketBufferClass::~GSMSocketBufferClass() 37 | { 38 | for (unsigned int i = 0; i < GSM_SOCKET_NUM_BUFFERS; i++) { 39 | close(i); 40 | } 41 | } 42 | 43 | void GSMSocketBufferClass::close(int socket) 44 | { 45 | if (_buffers[socket].data) { 46 | free(_buffers[socket].data); 47 | _buffers[socket].data = _buffers[socket].head = NULL; 48 | _buffers[socket].length = 0; 49 | } 50 | } 51 | 52 | int GSMSocketBufferClass::available(int socket) 53 | { 54 | if (_buffers[socket].length == 0) { 55 | if (_buffers[socket].data == NULL) { 56 | _buffers[socket].data = _buffers[socket].head = (uint8_t*)malloc(GSM_SOCKET_BUFFER_SIZE); 57 | _buffers[socket].length = 0; 58 | } 59 | 60 | String response; 61 | 62 | MODEM.sendf("AT+USORD=%d,%d", socket, GSM_SOCKET_BUFFER_SIZE); 63 | int status = MODEM.waitForResponse(10000, &response); 64 | if (status != 1) { 65 | return -1; 66 | } 67 | 68 | if (!response.startsWith("+USORD: ")) { 69 | return 0; 70 | } 71 | 72 | int firstQuoteIndex = response.indexOf("\""); 73 | 74 | response.remove(0, firstQuoteIndex + 1); 75 | response.remove(response.length() - 1); 76 | 77 | size_t size = response.length() / 2; 78 | 79 | for (size_t i = 0; i < size; i++) { 80 | byte n1 = response[i * 2]; 81 | byte n2 = response[i * 2 + 1]; 82 | 83 | if (n1 > '9') { 84 | n1 = (n1 - 'A') + 10; 85 | } else { 86 | n1 = (n1 - '0'); 87 | } 88 | 89 | if (n2 > '9') { 90 | n2 = (n2 - 'A') + 10; 91 | } else { 92 | n2 = (n2 - '0'); 93 | } 94 | 95 | _buffers[socket].data[i] = (n1 << 4) | n2; 96 | } 97 | 98 | _buffers[socket].head = _buffers[socket].data; 99 | _buffers[socket].length = size; 100 | } 101 | 102 | return _buffers[socket].length; 103 | } 104 | 105 | int GSMSocketBufferClass::peek(int socket) 106 | { 107 | if (!available(socket)) { 108 | return -1; 109 | } 110 | 111 | return *_buffers[socket].head; 112 | } 113 | 114 | int GSMSocketBufferClass::read(int socket, uint8_t* data, size_t length) 115 | { 116 | int avail = available(socket); 117 | 118 | if (!avail) { 119 | return 0; 120 | } 121 | 122 | if (avail < (int)length) { 123 | length = avail; 124 | } 125 | 126 | memcpy(data, _buffers[socket].head, length); 127 | _buffers[socket].head += length; 128 | _buffers[socket].length -= length; 129 | 130 | return length; 131 | } 132 | 133 | GSMSocketBufferClass GSMSocketBuffer; 134 | -------------------------------------------------------------------------------- /src/utility/GSMSocketBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of the MKRGSM library. 3 | Copyright (C) 2018 Arduino AG (http://www.arduino.cc/) 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef _GSMSOCKET_BUFFER_H_INCLUDED 21 | #define _GSMSOCKET_BUFFER_H_INCLUDED 22 | 23 | #include 24 | #include 25 | 26 | class GSMSocketBufferClass { 27 | 28 | public: 29 | public: 30 | GSMSocketBufferClass(); 31 | virtual ~GSMSocketBufferClass(); 32 | 33 | void close(int socket); 34 | 35 | int available(int socket); 36 | int peek(int socket); 37 | int read(int socket, uint8_t* data, size_t length); 38 | 39 | private: 40 | struct { 41 | uint8_t* data; 42 | uint8_t* head; 43 | int length; 44 | } _buffers[7]; 45 | }; 46 | 47 | extern GSMSocketBufferClass GSMSocketBuffer; 48 | 49 | #endif 50 | --------------------------------------------------------------------------------