├── .gitattributes ├── .github └── workflows │ ├── add_issue_to_project.yml │ └── compile-sketch.yml ├── .gitignore ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── README.md ├── Utils ├── Multi_TCP_Echo.py └── Multi_UDP_Echo.py ├── examples ├── SARA-R5_Example10_SocketPingPong │ └── SARA-R5_Example10_SocketPingPong.ino ├── SARA-R5_Example10_SocketPingPong_BinaryTCP │ └── SARA-R5_Example10_SocketPingPong_BinaryTCP.ino ├── SARA-R5_Example10_SocketPingPong_MultipleTCP │ └── SARA-R5_Example10_SocketPingPong_MultipleTCP.ino ├── SARA-R5_Example10_SocketPingPong_MultipleUDP │ └── SARA-R5_Example10_SocketPingPong_MultipleUDP.ino ├── SARA-R5_Example11_Clock │ └── SARA-R5_Example11_Clock.ino ├── SARA-R5_Example12_AssistNowOnline │ ├── SARA-R5_AssistNow_Online.ino │ ├── SARA-R5_Example12_AssistNowOnline.ino │ └── secrets.h ├── SARA-R5_Example13_SetClockWithNTP │ ├── SARA-R5_Example13_SetClockWithNTP.ino │ └── SARA-R5_NTP.ino ├── SARA-R5_Example14_AssistNowOffline │ ├── SARA-R5_AssistNow_Offline.ino │ ├── SARA-R5_Example14_AssistNowOffline.ino │ ├── SARA-R5_NTP.ino │ └── secrets.h ├── SARA-R5_Example15_GNSS_NTRIP_Caster_With_Callbacks │ ├── GNSS_Callbacks.ino │ ├── SARA-R5_Callbacks.ino │ ├── SARA-R5_Example15_GNSS_NTRIP_Caster_With_Callbacks.ino │ ├── SARA-R5_NTRIP_Client.ino │ ├── Utils.ino │ └── secrets.h ├── SARA-R5_Example16_GNSS_NTRIP_Caster__Polling │ ├── SARA-R5_Example16_GNSS_NTRIP_Caster__Polling.ino │ ├── SARA-R5_NTRIP_Client.ino │ └── secrets.h ├── SARA-R5_Example17_ThingSpeak_MQTT │ └── SARA-R5_Example17_ThingSpeak_MQTT.ino ├── SARA-R5_Example1_GNSS_GPRMC │ └── SARA-R5_Example1_GNSS_GPRMC.ino ├── SARA-R5_Example2_Identification │ └── SARA-R5_Example2_Identification.ino ├── SARA-R5_Example2_Identification_ESPSoftwareSerial │ └── SARA-R5_Example2_Identification_ESPSoftwareSerial.ino ├── SARA-R5_Example3_NetworkInfo │ └── SARA-R5_Example3_NetworkInfo.ino ├── SARA-R5_Example4_RegisterOperator │ └── SARA-R5_Example4_RegisterOperator.ino ├── SARA-R5_Example5_ReceiveSMS │ └── SARA-R5_Example5_ReceiveSMS.ino ├── SARA-R5_Example6_SendSMS │ └── SARA-R5_Example6_SendSMS.ino ├── SARA-R5_Example7_ConfigurePacketSwitchedData │ └── SARA-R5_Example7_ConfigurePacketSwitchedData.ino ├── SARA-R5_Example8_Ping │ └── SARA-R5_Example8_Ping.ino └── SARA-R5_Example9_ThingSpeak │ └── SARA-R5_Example9_ThingSpeak.ino ├── img └── Contributing.JPG ├── keywords.txt ├── library.properties └── src ├── SparkFun_u-blox_SARA-R5_Arduino_Library.cpp └── SparkFun_u-blox_SARA-R5_Arduino_Library.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain -------------------------------------------------------------------------------- /.github/workflows/add_issue_to_project.yml: -------------------------------------------------------------------------------- 1 | name: Add new issue to our main project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@main 14 | with: 15 | # You can target a project in a different organization 16 | # to the issue 17 | project-url: https://github.com/orgs/sparkfun/projects/19 18 | github-token: ${{ secrets.DEFECT_ADD_TO_PROJECT }} 19 | -------------------------------------------------------------------------------- /.github/workflows/compile-sketch.yml: -------------------------------------------------------------------------------- 1 | name: Compile Sketch 2 | 3 | on: 4 | # push: 5 | 6 | pull_request: 7 | 8 | workflow_dispatch: 9 | 10 | jobs: 11 | compile-sketch: 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | fail-fast: false 16 | 17 | matrix: 18 | board: 19 | # ATmega2560 20 | # https://github.com/arduino/ArduinoCore-avr/blob/master/boards.txt 21 | - fqbn: arduino:avr:mega 22 | platforms: | 23 | - name: arduino:avr 24 | source-url: https://downloads.arduino.cc/packages/package_index.json 25 | 26 | # ESP32 27 | # https://github.com/espressif/arduino-esp32/blob/master/boards.txt 28 | - fqbn: esp32:esp32:esp32 29 | platforms: | 30 | - name: esp32:esp32 31 | source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 32 | 33 | # ESP32-S2 34 | # https://github.com/espressif/arduino-esp32/blob/master/boards.txt 35 | - fqbn: esp32:esp32:esp32s2 36 | platforms: | 37 | - name: esp32:esp32 38 | source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 39 | 40 | # ESP32-C3 41 | # https://github.com/espressif/arduino-esp32/blob/master/boards.txt 42 | - fqbn: esp32:esp32:esp32c3 43 | platforms: | 44 | - name: esp32:esp32 45 | source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 46 | 47 | # Artemis / Apollo3 48 | # https://github.com/sparkfun/Arduino_Apollo3/blob/main/boards.txt 49 | - fqbn: SparkFun:apollo3:sfe_artemis_atp 50 | platforms: | 51 | - name: SparkFun:apollo3 52 | source-url: https://raw.githubusercontent.com/sparkfun/Arduino_Apollo3/master/package_sparkfun_apollo3_index.json 53 | 54 | # ESP8266 55 | # https://github.com/esp8266/Arduino/blob/master/boards.txt 56 | - fqbn: esp8266:esp8266:thingdev 57 | platforms: | 58 | - name: esp8266:esp8266 59 | source-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json 60 | 61 | # SAMD21 62 | # https://github.com/arduino/ArduinoCore-samd/blob/master/boards.txt 63 | - fqbn: arduino:samd:mkr1000 64 | platforms: | 65 | - name: arduino:samd 66 | # source-url: https://downloads.arduino.cc/packages/package_index.json 67 | 68 | # Nano BLE 33 / nRF52840 69 | # https://github.com/arduino/ArduinoCore-mbed/blob/master/boards.txt 70 | - fqbn: arduino:mbed:nano33ble 71 | platforms: | 72 | - name: arduino:mbed 73 | # source-url: https://downloads.arduino.cc/packages/package_index.json 74 | 75 | # RP2040 76 | # https://github.com/arduino/ArduinoCore-mbed/blob/master/boards.txt 77 | - fqbn: rp2040:rp2040:sparkfun_promicrorp2040 78 | platforms: | 79 | - name: rp2040:rp2040 80 | source-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json 81 | 82 | # STM32 83 | # https://github.com/arduino/ArduinoCore-mbed/blob/master/boards.txt 84 | - fqbn: STMicroelectronics:stm32:GenF4 85 | platforms: | 86 | - name: STMicroelectronics:stm32 87 | source-url: https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json 88 | 89 | steps: 90 | - name: Checkout 91 | uses: actions/checkout@v2 92 | 93 | - name: Branch name 94 | run: echo running on branch ${GITHUB_REF##*/} 95 | 96 | - name: Compile Sketch 97 | uses: arduino/compile-sketches@v1 98 | with: 99 | platforms: ${{ matrix.board.platforms }} 100 | fqbn: ${{ matrix.board.fqbn }} 101 | libraries: | 102 | - source-path: ./ 103 | sketch-paths: | 104 | - examples/SARA-R5_Example10_SocketPingPong 105 | enable-warnings-report: true 106 | enable-deltas-report: true 107 | # verbose: true 108 | 109 | # outputs: 110 | # report-artifact-name: ${{ steps.report-artifact-name.outputs.report-artifact-name }} 111 | 112 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE settings directories/folders 2 | .vscode/ 3 | 4 | # Windows image file caches 5 | Thumbs.db 6 | ehthumbs.db 7 | 8 | # Folder config file 9 | Desktop.ini 10 | 11 | # Recycle Bin used on file shares 12 | $RECYCLE.BIN/ 13 | 14 | # Windows Installer files 15 | *.cab 16 | *.msi 17 | *.msm 18 | *.msp 19 | 20 | # Windows shortcuts 21 | *.lnk 22 | 23 | # C build files 24 | _build 25 | *.elf 26 | *.hex 27 | *.exe 28 | 29 | # Arduino CLI config file 30 | *.yml 31 | Makefile 32 | 33 | # ========================= 34 | # Operating System Files 35 | # ========================= 36 | 37 | # OSX 38 | # ========================= 39 | 40 | .DS_Store 41 | .AppleDouble 42 | .LSOverride 43 | 44 | # Thumbnails 45 | ._* 46 | 47 | # Files that might appear in the root of a volume 48 | .DocumentRevisions-V100 49 | .fseventsd 50 | .Spotlight-V100 51 | .TemporaryItems 52 | .Trashes 53 | .VolumeIcon.icns 54 | 55 | # Directories potentially created on remote AFP share 56 | .AppleDB 57 | .AppleDesktop 58 | Network Trash Folder 59 | Temporary Items 60 | .apdisk 61 | 62 | # Test examples 63 | test -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | Thank you so *much* for offering to help out. We truly appreciate it. 4 | 5 | If you'd like to contribute, start by searching through the [issues](https://github.com/sparkfun/SparkFun_u-blox_SARA-R5_Arduino_Library/issues) and [pull requests](https://github.com/sparkfun/SparkFun_u-blox_SARA-R5_Arduino_Library/pulls) to see whether someone else has raised a similar idea or question. 6 | Please check the [closed issues](https://github.com/sparkfun/SparkFun_u-blox_SARA-R5_Arduino_Library/issues?q=is%3Aissue+is%3Aclosed) 7 | and [closed pull requests](https://github.com/sparkfun/SparkFun_u-blox_SARA-R5_Arduino_Library/pulls?q=is%3Apr+is%3Aclosed) too - you may find that your issue or feature has already been discussed. 8 | 9 | If you decide to add a feature to this library, please create a PR and follow these best practices: 10 | 11 | * Change as little as possible. Do not submit a PR that changes 100 lines of whitespace. Break up into multiple PRs if necessary. 12 | * If you've added a new feature document it with a simple example sketch. This serves both as a test of your PR and as a quick way for users to quickly learn how to use your new feature. 13 | * If you add new functions also add them to _keywords.txt_ so that they are properly highlighted in Arduino. [Read more](https://www.arduino.cc/en/Hacking/libraryTutorial). 14 | * **Important:** Please submit your PR using the [release_candidate branch](https://github.com/sparkfun/SparkFun_u-blox_SARA-R5_Arduino_Library/tree/release_candidate). That way, we can merge and test your PR quickly without changing the _master_ branch 15 | 16 | ![Contributing.JPG](./img/Contributing.JPG) 17 | 18 | ## Style guide 19 | 20 | Please read and follow the [Arduino API style guide](https://www.arduino.cc/en/Reference/APIStyleGuide). Also read and consider the [Arduino style guide](https://www.arduino.cc/en/Reference/StyleGuide). 21 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Subject of the issue 2 | Describe your issue here. 3 | 4 | ### Your workbench 5 | * What platform are you using? 6 | * What version of the device are you using? Is there a firmware version? 7 | * How is the device wired to your platform? 8 | * How is everything being powered? 9 | * Are there any additional details that may help us help you? 10 | 11 | ### Steps to reproduce 12 | Tell us how to reproduce this issue. Please post stripped down example code demonstrating your issue to a gist. 13 | 14 | ### Expected behaviour 15 | Tell us what should happen 16 | 17 | ### Actual behaviour 18 | Tell us what happens instead -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | SparkFun License Information 2 | ============================ 3 | 4 | SparkFun uses two different licenses for our files — one for hardware and one for code. 5 | 6 | Hardware 7 | --------- 8 | 9 | **SparkFun hardware is released under [Creative Commons Share-alike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/).** 10 | 11 | Note: This is a human-readable summary of (and not a substitute for) the [license](http://creativecommons.org/licenses/by-sa/4.0/legalcode). 12 | 13 | You are free to: 14 | 15 | Share — copy and redistribute the material in any medium or format 16 | Adapt — remix, transform, and build upon the material 17 | for any purpose, even commercially. 18 | The licensor cannot revoke these freedoms as long as you follow the license terms. 19 | Under the following terms: 20 | 21 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 22 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 23 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 24 | Notices: 25 | 26 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 27 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 28 | 29 | 30 | Code 31 | -------- 32 | 33 | **SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT).** 34 | 35 | The MIT License (MIT) 36 | 37 | Copyright (c) 2020 SparkFun Electronics 38 | 39 | Permission is hereby granted, free of charge, to any person obtaining a copy 40 | of this software and associated documentation files (the "Software"), to deal 41 | in the Software without restriction, including without limitation the rights 42 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 43 | copies of the Software, and to permit persons to whom the Software is 44 | furnished to do so, subject to the following conditions: 45 | 46 | The above copyright notice and this permission notice shall be included in all 47 | copies or substantial portions of the Software. 48 | 49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun u-blox SARA-R5 Arduino Library 2 | ============================== 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
MicroMod Asset Tracker Carrier BoardSparkFun LTE GNSS Breakout - SARA-R5SparkFun MicroMod LTE GNSS Function Board - u-blox SARA-R5
MicroMod Asset Tracker Carrier BoardLTE GNSS Breakout - SARA-R5SparkFun MicroMod LTE GNSS Function Board - u-blox SARA-R5
16 | 17 | An Arduino library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud, as used on the [SparkFun MicroMod Asset Tracker](https://www.sparkfun.com/products/17272), the [SparkFun LTE GNSS Breakout - SARA-R5](https://www.sparkfun.com/products/18031), and the [SparkFun MicroMod LTE GNSS Function Board - u-blox SARA-R5](https://www.sparkfun.com/products/18431) 18 | 19 | v1.1 has had a thorough update and includes new features and examples. This library now supports up to 7 simultaneous TCP or UDP sockets. There are new examples to show how to play ping pong with multiple TCP and UDP sockets. 20 | 21 | v1.1 also supports binary data transfers correctly. There are new examples showing how you can integrate this library with the [SparkFun u-blox GNSS Arduino Library](https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library) and use the SARA-R5 to: download AssistNow Online and Offline data and push it to the GNSS; open a connection to a NTRIP Caster (such as RTK2go, Skylark or Emlid Caster) and push RTK correction data to the GNSS. 22 | 23 | You can install this library using the Arduino IDE Library Manager: search for _**SparkFun u-blox SARA-R5**_ 24 | 25 | ## Repository Contents 26 | 27 | * **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. 28 | * **/src** - Source files for the library (.cpp, .h). 29 | * **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. 30 | * **library.properties** - General library properties for the Arduino package manager. 31 | 32 | ## Contributing 33 | 34 | If you would like to contribute to this library: please do, we truly appreciate it, but please follow [these guidelines](./CONTRIBUTING.md). Thanks! 35 | 36 | ## Documentation 37 | 38 | * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. 39 | * **MicroMod Asset Tracker** 40 | * **[Hookup Guide](https://learn.sparkfun.com/tutorials/micromod-asset-tracker-carrier-board-hookup-guide)** - Hookup Guide for the MicroMod Asset Tracker Carrier Board. 41 | * **[GitHub Product Repository](https://github.com/sparkfun/MicroMod_Asset_Tracker)** - MicroMod Asset Tracker repository (including hardware files). 42 | * **SparkFun LTE GNSS Breakout - SARA-R5** 43 | * **[Hookup Guide](https://learn.sparkfun.com/tutorials/lte-gnss-breakout---sara-r5-hookup-guide)** - Hookup Guide for the LTE GNSS Breakout - SARA-R5. 44 | * **[GitHub Product Repository](https://github.com/sparkfun/SparkFun_LTE_GNSS_Breakout_SARA-R510M8S)** - LTE GNSS Breakout - SARA-R5 repository (including hardware files). 45 | * **SparkFun MicroMod LTE GNSS Function Board - u-blox SARA - R5** 46 | * **[Hookup Guide](https://docs.sparkfun.com/SparkFun_MicroMod_LTE_GNSS_Function_Board_u-blox_SARA-R5/)** - Hookup Guide for the SparkFun MicroMod LTE GNSS Function Board - u-blox SARA-R5. 47 | * **[GitHub Product Repository](https://github.com/sparkfun/SparkFun_MicroMod_LTE_GNSS_Function_Board_u-blox_SARA-R5)** - SparkFun MicroMod LTE GNSS Function Board - u-blox SARA-R5 repository (including hardware files). 48 | * **[LICENSE.md](./LICENSE.md)** - License Information 49 | 50 | ## Products that use this library 51 | 52 | * **[DEV-17272](https://www.sparkfun.com/products/17272)** - MicroMod Asset Tracker 53 | * **[GPS-18031](https://www.sparkfun.com/products/18031)** - SparkFun LTE GNSS Breakout - SARA-R5 54 | * **[DEV-18031](https://www.sparkfun.com/products/18431)** - SparkFun MicroMod LTE GNSS Function Board - u-blox SARA-R5 55 | 56 | - Your friends at SparkFun. 57 | -------------------------------------------------------------------------------- /Utils/Multi_TCP_Echo.py: -------------------------------------------------------------------------------- 1 | # Multiple TCP Echo Server 2 | # Based on the third example from: 3 | # https://rosettacode.org/wiki/Echo_server#Python 4 | 5 | #!usr/bin/env python 6 | import socket 7 | import threading 8 | 9 | NUM_PORTS = 5 # Echo on this many ports starting at PORT_BASE 10 | PORT_BASE = 1200 # Change this if required 11 | HOST = '192.168.0.50' # Change this to match your local IP 12 | SOCKET_TIMEOUT = 30 13 | 14 | # This function handles reading data sent by a client, echoing it back 15 | # and closing the connection in case of timeout (30s) or "quit" command 16 | # This function is meant to be started in a separate thread 17 | # (one thread per client) 18 | def handle_echo(client_connection, client_address, port): 19 | client_connection.settimeout(SOCKET_TIMEOUT) 20 | try: 21 | while True: 22 | data = client_connection.recv(1024) 23 | # Close connection if "quit" received from client 24 | if data == b'quit\r\n' or data == b'quit\n': 25 | print('{} : {} disconnected'.format(client_address,port)) 26 | client_connection.shutdown(1) 27 | client_connection.close() 28 | break 29 | # Echo back to client 30 | elif data: 31 | print('FROM {} : {} : {}'.format(client_address,port,data)) 32 | client_connection.send(data) 33 | # Timeout and close connection after 30s of inactivity 34 | except socket.timeout: 35 | print('{} : {} timed out'.format(client_address,port)) 36 | client_connection.shutdown(1) 37 | client_connection.close() 38 | 39 | # This function opens a socket and listens on specified port. As soon as a 40 | # connection is received, it is transfered to another socket so that the main 41 | # socket is not blocked and can accept new clients. 42 | def listen(host, port): 43 | # Create the main socket (IPv4, TCP) 44 | connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 45 | connection.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 46 | connection.bind((host, port)) 47 | # Listen for clients (max 10 clients in waiting) 48 | connection.listen(10) 49 | # Every time a client connects, allow a dedicated socket and a dedicated 50 | # thread to handle communication with that client without blocking others. 51 | # Once the new thread has taken over, wait for the next client. 52 | while True: 53 | current_connection, client_address = connection.accept() 54 | print('{} : {} connected'.format(client_address, port)) 55 | handler_thread = threading.Thread( \ 56 | target = handle_echo, \ 57 | args = (current_connection,client_address,port) \ 58 | ) 59 | # daemon makes sure all threads are killed if the main server process 60 | # gets killed 61 | handler_thread.daemon = True 62 | handler_thread.start() 63 | 64 | if __name__ == "__main__": 65 | print('starting') 66 | 67 | threads = list() 68 | 69 | for i in range(NUM_PORTS): 70 | threads.append( threading.Thread( \ 71 | target = listen, args = (HOST, PORT_BASE + i)) ) 72 | threads[i].daemon = True 73 | threads[i].start() 74 | 75 | -------------------------------------------------------------------------------- /Utils/Multi_UDP_Echo.py: -------------------------------------------------------------------------------- 1 | # Multiple UDP Echo Server 2 | # Based on code by David Manouchehri 3 | # Threading added by PaulZC 4 | 5 | #!/usr/bin/env python2 6 | # -*- coding: utf-8 -*- 7 | 8 | # Original author: David Manouchehri 9 | # This script will always echo back data on the UDP port of your choice. 10 | # Useful if you want nmap to report a UDP port as "open" instead of "open|filtered" on a standard scan. 11 | # Works with both Python 2 & 3. 12 | 13 | import socket 14 | import threading 15 | 16 | num_ports = 5 # Echo on this many ports starting at server_port_base 17 | server_port_base = 1200 # Change this if required 18 | server_address = '192.168.0.50' # Change this to match your local IP 19 | 20 | def echo(address, port): 21 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 22 | serv = (address, port) 23 | sock.bind(serv) 24 | while True: 25 | payload, client_address = sock.recvfrom(4) # Try to receive 4 bytes 26 | print("Port " + str(port) + ": Echoing 4 bytes back to " + str(client_address)) 27 | sent = sock.sendto(payload, client_address) 28 | 29 | if __name__ == "__main__": 30 | print("Listening on " + server_address) 31 | 32 | threads = list() 33 | 34 | for i in range(num_ports): 35 | threads.append( threading.Thread( \ 36 | target = echo, args = (server_address, server_port_base + i)) ) 37 | threads[i].daemon = True 38 | threads[i].start() 39 | 40 | 41 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example11_Clock/SARA-R5_Example11_Clock.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Clock 7 | 8 | Written by: Paul Clark 9 | Date: January 3rd 2022 10 | 11 | This example demonstrates how to use the clock function to read the time from the SARA-R5. 12 | 13 | Note: the clock will be set to network time only if your network supports NITZ (Network Identity and Time Zone) 14 | 15 | Feel like supporting open source hardware? 16 | Buy a board from SparkFun! 17 | 18 | Licence: MIT 19 | Please see LICENSE.md for full details 20 | 21 | */ 22 | 23 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 24 | 25 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 26 | #define saraSerial Serial1 27 | 28 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 29 | //SoftwareSerial saraSerial(8, 9); 30 | 31 | // Create a SARA_R5 object to use throughout the sketch 32 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 33 | // but we can start the SARA without a power pin. It just means we need to manually 34 | // turn the power on if required! ;-D 35 | SARA_R5 mySARA; 36 | 37 | // Create a SARA_R5 object to use throughout the sketch 38 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 39 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 40 | // the pin name is G2 which is connected to pin AD34. 41 | // Change the pin number if required. 42 | //SARA_R5 mySARA(34); 43 | 44 | void setup() 45 | { 46 | Serial.begin(115200); // Start the serial console 47 | 48 | // Wait for user to press key to begin 49 | Serial.println(F("SARA-R5 Example")); 50 | 51 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 52 | 53 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 54 | // Comment the next line if required 55 | mySARA.invertPowerPin(true); 56 | 57 | // Initialize the SARA 58 | if (mySARA.begin(saraSerial, 9600) ) 59 | { 60 | Serial.println(F("SARA-R5 connected!")); 61 | } 62 | else 63 | { 64 | Serial.println(F("Unable to communicate with the SARA.")); 65 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 66 | while (1) ; // Loop forever on fail 67 | } 68 | Serial.println(); 69 | 70 | // Make sure automatic time zone updates are enabled 71 | if (mySARA.autoTimeZone(true) != SARA_R5_SUCCESS) 72 | Serial.println(F("Enable autoTimeZone failed!")); 73 | 74 | // Read and print the clock as a String 75 | String theTime = mySARA.clock(); 76 | Serial.println(theTime); 77 | 78 | // Read and print the hour, minute, etc. separately 79 | uint8_t year, month, day, hour, minute, second; 80 | int8_t timeZone; 81 | if (mySARA.clock( &year, &month, &day, &hour, &minute, &second, &timeZone ) == SARA_R5_SUCCESS) 82 | // Note: not all Arduino boards implement printf correctly. The formatting may not be correct on some boards. 83 | // Note: the timeZone is defined in 15 minute increments, not hours. -28 indicates the time zone is 7 hours behind UTC/GMT. 84 | Serial.printf("%02d/%02d/%02d %02d:%02d:%02d %+d\r\n", year, month, day, hour, minute, second, timeZone); 85 | 86 | } 87 | 88 | void loop() 89 | { 90 | // Nothing to do here 91 | } 92 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example12_AssistNowOnline/SARA-R5_AssistNow_Online.ino: -------------------------------------------------------------------------------- 1 | 2 | #include "secrets.h" // Update secrets.h with your AssistNow token string 3 | 4 | // u-blox AssistNow https servers 5 | const char assistNowServer[] = "online-live1.services.u-blox.com"; 6 | //const char assistNowServer[] = "online-live2.services.u-blox.com"; // Alternate server 7 | 8 | const char getQuery[] = "GetOnlineData.ashx?"; 9 | const char tokenPrefix[] = "token="; 10 | const char tokenSuffix[] = ";"; 11 | const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal 12 | const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos 13 | 14 | volatile bool httpResultSeen = false; // Flag to indicate that the HTTP URC was received 15 | 16 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 17 | 18 | // processHTTPcommandResult is provided to the SARA-R5 library via a 19 | // callback setter -- setHTTPCommandCallback. (See the end of setup()) 20 | void processHTTPcommandResult(int profile, int command, int result) 21 | { 22 | Serial.println(); 23 | Serial.print(F("HTTP Command Result: profile: ")); 24 | Serial.print(profile); 25 | Serial.print(F(" command: ")); 26 | Serial.print(command); 27 | Serial.print(F(" result: ")); 28 | Serial.print(result); 29 | if (result == 0) 30 | Serial.print(F(" (fail)")); 31 | if (result == 1) 32 | Serial.print(F(" (success)")); 33 | Serial.println(); 34 | 35 | // Get and print the most recent HTTP protocol error 36 | int error_class; 37 | int error_code; 38 | mySARA.getHTTPprotocolError(0, &error_class, &error_code); 39 | Serial.print(F("Most recent HTTP protocol error: class: ")); 40 | Serial.print(error_class); 41 | Serial.print(F(" code: ")); 42 | Serial.print(error_code); 43 | if (error_code == 0) 44 | Serial.print(F(" (no error)")); 45 | Serial.println(); 46 | 47 | httpResultSeen = true; // Set the flag 48 | } 49 | 50 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 51 | 52 | bool getAssistNowOnlineData(String theFilename) 53 | { 54 | // Use HTTP GET to receive the AssistNow_Online data. Store it in the SARA-R5's internal file system. 55 | 56 | String theServer = assistNowServer; // Convert the AssistNow server to String 57 | 58 | const int REQUEST_BUFFER_SIZE = 256; 59 | char theRequest[REQUEST_BUFFER_SIZE]; 60 | 61 | // Assemble the request 62 | // Note the slash at the beginning 63 | snprintf(theRequest, REQUEST_BUFFER_SIZE, "/%s%s%s%s%s%s", 64 | getQuery, 65 | tokenPrefix, 66 | myAssistNowToken, 67 | tokenSuffix, 68 | getGNSS, 69 | getDataType); 70 | 71 | String theRequestStr = theRequest; // Convert to String 72 | 73 | Serial.print(F("getAssistNowOnlineData: HTTP GET is https://")); 74 | Serial.print(theServer); 75 | Serial.println(theRequestStr); 76 | 77 | Serial.print(F("getAssistNowOnlineData: the AssistNow data will be stored in: ")); 78 | Serial.println(theFilename); 79 | 80 | // Reset HTTP profile 0 81 | mySARA.resetHTTPprofile(0); 82 | 83 | // Set the server name 84 | mySARA.setHTTPserverName(0, theServer); 85 | 86 | // Use HTTPS 87 | mySARA.setHTTPsecure(0, false); // Setting this to true causes the GET to fail. Maybe due to the default CMNG profile? 88 | 89 | // Set a callback to process the HTTP command result 90 | mySARA.setHTTPCommandCallback(&processHTTPcommandResult); 91 | 92 | httpResultSeen = false; // Clear the flag 93 | 94 | // HTTP GET 95 | mySARA.sendHTTPGET(0, theRequestStr, theFilename); 96 | 97 | // Wait for 20 seconds while calling mySARA.bufferedPoll() to see the HTTP result. 98 | Serial.print(F("getAssistNowOnlineData: Waiting up to 20 seconds for the HTTP Result")); 99 | int i = 0; 100 | while ((i < 20000) && (httpResultSeen == false)) 101 | { 102 | mySARA.bufferedPoll(); // Keep processing data from the SARA so we can catch the HTTP command result 103 | i++; 104 | delay(1); 105 | if (i % 1000 == 0) 106 | Serial.print(F(".")); 107 | } 108 | Serial.println(); 109 | 110 | if (httpResultSeen == false) 111 | { 112 | Serial.print(F("getAssistNowOnlineData: HTTP GET failed!")); 113 | return false; 114 | } 115 | 116 | int fileSize; 117 | if (mySARA.getFileSize(theFilename, &fileSize) != SARA_R5_SUCCESS) 118 | { 119 | Serial.print(F("getAssistNowOnlineData: No file written?!")); 120 | return false; 121 | } 122 | 123 | Serial.print(F("File size is: ")); 124 | Serial.println(fileSize); 125 | 126 | return true; 127 | } 128 | 129 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 130 | 131 | void prettyPrintString(String theString) // Pretty-print a String in HEX and ASCII format 132 | { 133 | int theLength = theString.length(); 134 | 135 | Serial.println(); 136 | Serial.print(F("String length is ")); 137 | Serial.print(theLength); 138 | Serial.print(F(" (0x")); 139 | Serial.print(theLength, HEX); 140 | Serial.println(F(")")); 141 | Serial.println(); 142 | 143 | for (int i = 0; i < theLength; i += 16) 144 | { 145 | if (i < 10000) Serial.print(F("0")); 146 | if (i < 1000) Serial.print(F("0")); 147 | if (i < 100) Serial.print(F("0")); 148 | if (i < 10) Serial.print(F("0")); 149 | Serial.print(i); 150 | 151 | Serial.print(F(" 0x")); 152 | 153 | if (i < 0x1000) Serial.print(F("0")); 154 | if (i < 0x100) Serial.print(F("0")); 155 | if (i < 0x10) Serial.print(F("0")); 156 | Serial.print(i, HEX); 157 | 158 | Serial.print(F(" ")); 159 | 160 | int j; 161 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 162 | { 163 | if (theString[i + j] < 0x10) Serial.print(F("0")); 164 | Serial.print(theString[i + j], HEX); 165 | Serial.print(F(" ")); 166 | } 167 | 168 | if (((i + j) == theLength) && (j < 16)) 169 | { 170 | for (int k = 0; k < (16 - (theLength % 16)); k++) 171 | { 172 | Serial.print(F(" ")); 173 | } 174 | } 175 | 176 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 177 | { 178 | if ((theString[i + j] >= 0x20) && (theString[i + j] <= 0x7E)) 179 | Serial.write(theString[i + j]); 180 | else 181 | Serial.print(F(".")); 182 | } 183 | 184 | Serial.println(); 185 | } 186 | 187 | Serial.println(); 188 | } 189 | 190 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 191 | 192 | void prettyPrintChars(char *theData, int theLength) // Pretty-print char data in HEX and ASCII format 193 | { 194 | Serial.println(); 195 | Serial.print(F("String length is ")); 196 | Serial.print(theLength); 197 | Serial.print(F(" (0x")); 198 | Serial.print(theLength, HEX); 199 | Serial.println(F(")")); 200 | Serial.println(); 201 | 202 | for (int i = 0; i < theLength; i += 16) 203 | { 204 | if (i < 10000) Serial.print(F("0")); 205 | if (i < 1000) Serial.print(F("0")); 206 | if (i < 100) Serial.print(F("0")); 207 | if (i < 10) Serial.print(F("0")); 208 | Serial.print(i); 209 | 210 | Serial.print(F(" 0x")); 211 | 212 | if (i < 0x1000) Serial.print(F("0")); 213 | if (i < 0x100) Serial.print(F("0")); 214 | if (i < 0x10) Serial.print(F("0")); 215 | Serial.print(i, HEX); 216 | 217 | Serial.print(F(" ")); 218 | 219 | int j; 220 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 221 | { 222 | if (theData[i + j] < 0x10) Serial.print(F("0")); 223 | Serial.print(theData[i + j], HEX); 224 | Serial.print(F(" ")); 225 | } 226 | 227 | if (((i + j) == theLength) && (j < 16)) 228 | { 229 | for (int k = 0; k < (16 - (theLength % 16)); k++) 230 | { 231 | Serial.print(F(" ")); 232 | } 233 | } 234 | 235 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 236 | { 237 | if ((theData[i + j] >= 0x20) && (theData[i + j] <= 0x7E)) 238 | Serial.write(theData[i + j]); 239 | else 240 | Serial.print(F(".")); 241 | } 242 | 243 | Serial.println(); 244 | } 245 | 246 | Serial.println(); 247 | } 248 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example12_AssistNowOnline/SARA-R5_Example12_AssistNowOnline.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | u-blox AssistNow Online 7 | 8 | Written by: Paul Clark 9 | Date: January 8th 2021 10 | 11 | This example uses the SARA's mobile data connection to: 12 | * Request AssistNow Online data from the u-blox server 13 | * Provide assistance data to an external u-blox GNSS module over I2C (not to the one built-in to the SARA-R510M8S) 14 | 15 | The PDP profile is read from NVM. Please make sure you have run examples 4 & 7 previously to set up the profile. 16 | 17 | You will need to have a token to be able to access Thingstream. See the AssistNow README for more details: 18 | https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/tree/main/examples/AssistNow 19 | 20 | Update secrets.h with your AssistNow token string 21 | 22 | Note: this code does not use the AssistNow or CellLocate features built-in to the SARA-R510M8S. 23 | Those features are great but the assistance data remains 'hidden' and cannot be read and passed to an external GNSS. 24 | This code downloads the assistance data to the SARA-R5's internal file system where it can be accessed, 25 | used and re-used with an external GNSS. 26 | 27 | Feel like supporting open source hardware? 28 | Buy a board from SparkFun! 29 | 30 | Licence: MIT 31 | Please see LICENSE.md for full details 32 | 33 | */ 34 | 35 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 36 | 37 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 38 | 39 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 40 | #define saraSerial Serial1 41 | 42 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 43 | //SoftwareSerial saraSerial(8, 9); 44 | 45 | // Create a SARA_R5 object to use throughout the sketch 46 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 47 | // but we can start the SARA without a power pin. It just means we need to manually 48 | // turn the power on if required! ;-D 49 | SARA_R5 mySARA; 50 | 51 | // Create a SARA_R5 object to use throughout the sketch 52 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 53 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 54 | // the pin name is G2 which is connected to pin AD34. 55 | // Change the pin number if required. 56 | //SARA_R5 mySARA(34); 57 | 58 | // Create a SARA_R5 object to use throughout the sketch 59 | // If you are using the LTE GNSS Breakout, and have access to the SARA's RESET_N pin, you can pass that to the library too 60 | // allowing it to do an emergency shutdown if required. 61 | // Change the pin numbers if required. 62 | //SARA_R5 mySARA(34, 35); // PWR_ON, RESET_N 63 | 64 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 65 | 66 | #include //http://librarymanager/All#SparkFun_u-blox_GNSS 67 | SFE_UBLOX_GNSS myGNSS; 68 | 69 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 70 | 71 | void setup() 72 | { 73 | String currentOperator = ""; 74 | 75 | Serial.begin(115200); // Start the serial console 76 | 77 | // Wait for user to press key to begin 78 | Serial.println(F("SARA-R5 Example")); 79 | Serial.println(F("Wait for the SARA NI LED to light up - then press any key to begin")); 80 | 81 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 82 | ; 83 | while (Serial.available()) // Empty the serial RX buffer 84 | Serial.read(); 85 | 86 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 87 | 88 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 89 | 90 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 91 | // Comment the next line if required 92 | mySARA.invertPowerPin(true); 93 | 94 | // Initialize the SARA 95 | if (mySARA.begin(saraSerial, 115200) ) 96 | { 97 | Serial.println(F("SARA-R5 connected!")); 98 | } 99 | else 100 | { 101 | Serial.println(F("Unable to communicate with the SARA.")); 102 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 103 | while (1) ; // Loop forever on fail 104 | } 105 | Serial.println(); 106 | 107 | // First check to see if we're connected to an operator: 108 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 109 | { 110 | Serial.print(F("Connected to: ")); 111 | Serial.println(currentOperator); 112 | } 113 | else 114 | { 115 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 116 | while (1) 117 | ; // Do nothing more 118 | } 119 | 120 | // Deactivate the PSD profile - in case one is already active 121 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_DEACTIVATE) != SARA_R5_SUCCESS) 122 | { 123 | Serial.println(F("Warning: performPDPaction (deactivate profile) failed. Probably because no profile was active.")); 124 | } 125 | 126 | // Load the PSD profile from NVM - these were saved by a previous example 127 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_LOAD) != SARA_R5_SUCCESS) 128 | { 129 | Serial.println(F("performPDPaction (load from NVM) failed! Freezing...")); 130 | while (1) 131 | ; // Do nothing more 132 | } 133 | 134 | // Activate the profile 135 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_ACTIVATE) != SARA_R5_SUCCESS) 136 | { 137 | Serial.println(F("performPDPaction (activate profile) failed! Freezing...")); 138 | while (1) 139 | ; // Do nothing more 140 | } 141 | 142 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 143 | 144 | // Start I2C. Connect to the GNSS. 145 | 146 | Wire.begin(); //Start I2C 147 | 148 | //myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 149 | 150 | if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port 151 | { 152 | Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); 153 | while (1); 154 | } 155 | Serial.println(F("u-blox module connected")); 156 | 157 | myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise 158 | 159 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 160 | 161 | // Request the AssistNow data from the server. Data is stored in the SARA's file system. 162 | 163 | String theFilename = "assistnow_online.ubx"; // The file that will contain the AssistNow Online data 164 | 165 | if (getAssistNowOnlineData(theFilename) == false) // See SARA-R5_AssistNow_Online.ino 166 | { 167 | Serial.println(F("getAssistNowOnlineData failed! Freezing...")); 168 | while (1) 169 | ; // Do nothing more 170 | } 171 | 172 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 173 | 174 | // Read the AssistNow data from file and push it to the module 175 | 176 | int fileSize; 177 | if (mySARA.getFileSize(theFilename, &fileSize) != SARA_R5_SUCCESS) 178 | { 179 | Serial.print(F("getFileSize failed! Freezing...")); 180 | while (1) 181 | ; // Do nothing more 182 | } 183 | 184 | Serial.print(F("AssistNow file size is: ")); 185 | Serial.println(fileSize); 186 | 187 | // Read the data from file 188 | char *theAssistData = new char[fileSize]; 189 | if (mySARA.getFileContents(theFilename, theAssistData) != SARA_R5_SUCCESS) 190 | { 191 | Serial.println(F("getFileContents failed! Freezing...")); 192 | while (1) 193 | ; // Do nothing more 194 | } 195 | 196 | //prettyPrintChars(theAssistData, fileSize); // Uncomment this line to see the whole file contents (including the HTTP header) 197 | 198 | // Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data 199 | myGNSS.setAckAiding(1); 200 | 201 | // Speed things up by setting setI2CpollingWait to 1ms 202 | myGNSS.setI2CpollingWait(1); 203 | 204 | // Push all the AssistNow data. 205 | // 206 | // pushAssistNowData is clever and will only push valid UBX-format data. 207 | // It will ignore the HTTP header at the start of the AssistNow file. 208 | // 209 | // We have called setAckAiding(1) to instruct the module to return MGA-ACK messages. 210 | // So, set the pushAssistNowData mgaAck parameter to SFE_UBLOX_MGA_ASSIST_ACK_YES. 211 | // Wait for up to 100ms for each ACK to arrive! 100ms is a bit excessive... 7ms is nearer the mark. 212 | myGNSS.pushAssistNowData((const uint8_t *)theAssistData, fileSize, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100); 213 | 214 | // Delete the memory allocated to store the AssistNow data 215 | delete[] theAssistData; 216 | 217 | // Set setI2CpollingWait to 125ms to avoid pounding the I2C bus 218 | myGNSS.setI2CpollingWait(125); 219 | 220 | // Delete the file after use. This is optional as the SARA will automatically overwrite the file. 221 | // And you might want to reuse it? AssistNow Online data is valid for 2-4 hours. 222 | //if (mySARA.deleteFile(theFilename) != SARA_R5_SUCCESS) 223 | //{ 224 | // Serial.println(F("Warning: deleteFile failed!")); 225 | //} 226 | } 227 | 228 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 229 | 230 | void loop() 231 | { 232 | // Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D 233 | 234 | long latitude = myGNSS.getLatitude(); 235 | Serial.print(F("Lat: ")); 236 | Serial.print(latitude); 237 | 238 | long longitude = myGNSS.getLongitude(); 239 | Serial.print(F(" Long: ")); 240 | Serial.print(longitude); 241 | Serial.print(F(" (degrees * 10^-7)")); 242 | 243 | long altitude = myGNSS.getAltitude(); 244 | Serial.print(F(" Alt: ")); 245 | Serial.print(altitude); 246 | Serial.print(F(" (mm)")); 247 | 248 | byte SIV = myGNSS.getSIV(); 249 | Serial.print(F(" SIV: ")); 250 | Serial.print(SIV); 251 | 252 | byte fixType = myGNSS.getFixType(); 253 | Serial.print(F(" Fix: ")); 254 | if(fixType == 0) Serial.print(F("No fix")); 255 | else if(fixType == 1) Serial.print(F("Dead reckoning")); 256 | else if(fixType == 2) Serial.print(F("2D")); 257 | else if(fixType == 3) Serial.print(F("3D")); 258 | else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning")); 259 | else if(fixType == 5) Serial.print(F("Time only")); 260 | 261 | Serial.println(); 262 | } 263 | 264 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 265 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example12_AssistNowOnline/secrets.h: -------------------------------------------------------------------------------- 1 | //Your AssistNow token 2 | const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ"; 3 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example13_SetClockWithNTP/SARA-R5_Example13_SetClockWithNTP.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Set Clock With NTP 7 | 8 | Written by: Paul Clark 9 | Date: January 9th 2022 10 | 11 | This example demonstrates how to set the SARA-R5's internal Real Time Clock using NTP. 12 | When the SARA-R5 registers on a network, it will set its clock automatically if: 13 | Automatic time zone is enabled 14 | Your network supports NITZ (Network Identity and Time Zone) 15 | But for things like AssistNow Offline, it is convenient to have the SARA's RTC set to UTC. 16 | Then the clock can be used to select the AssistNow data for now/today without time zone headaches. 17 | This example shows how to: 18 | Disable the automatic time zone (using autoTimeZoneForBegin before .begin) 19 | Set the SARA's clock to UTC using NTP (see SARA-R5_NTP.ino) 20 | 21 | The PDP profile is read from NVM. Please make sure you have run examples 4 & 7 previously to set up the profile. 22 | 23 | Feel like supporting open source hardware? 24 | Buy a board from SparkFun! 25 | 26 | Licence: MIT 27 | Please see LICENSE.md for full details 28 | 29 | */ 30 | 31 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 32 | 33 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 34 | 35 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 36 | #define saraSerial Serial1 37 | 38 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 39 | //SoftwareSerial saraSerial(8, 9); 40 | 41 | // Create a SARA_R5 object to use throughout the sketch 42 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 43 | // but we can start the SARA without a power pin. It just means we need to manually 44 | // turn the power on if required! ;-D 45 | SARA_R5 mySARA; 46 | 47 | // Create a SARA_R5 object to use throughout the sketch 48 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 49 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 50 | // the pin name is G2 which is connected to pin AD34. 51 | // Change the pin number if required. 52 | //SARA_R5 mySARA(34); 53 | 54 | // Create a SARA_R5 object to use throughout the sketch 55 | // If you are using the LTE GNSS Breakout, and have access to the SARA's RESET_N pin, you can pass that to the library too 56 | // allowing it to do an emergency shutdown if required. 57 | // Change the pin numbers if required. 58 | //SARA_R5 mySARA(34, 35); // PWR_ON, RESET_N 59 | 60 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 61 | 62 | void setup() 63 | { 64 | String currentOperator = ""; 65 | 66 | Serial.begin(115200); // Start the serial console 67 | 68 | // Wait for user to press key to begin 69 | Serial.println(F("SARA-R5 Example")); 70 | Serial.println(F("Wait for the SARA NI LED to light up - then press any key to begin")); 71 | 72 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 73 | ; 74 | while (Serial.available()) // Empty the serial RX buffer 75 | Serial.read(); 76 | 77 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 78 | 79 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 80 | 81 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 82 | // Comment the next line if required 83 | mySARA.invertPowerPin(true); 84 | 85 | // Disable the automatic time zone so we can use UTC. We need to do this _before_ .begin 86 | mySARA.autoTimeZoneForBegin(false); 87 | 88 | // Initialize the SARA 89 | if (mySARA.begin(saraSerial, 115200) ) 90 | { 91 | Serial.println(F("SARA-R5 connected!")); 92 | } 93 | else 94 | { 95 | Serial.println(F("Unable to communicate with the SARA.")); 96 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 97 | while (1) ; // Loop forever on fail 98 | } 99 | Serial.println(); 100 | 101 | // First check to see if we're connected to an operator: 102 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 103 | { 104 | Serial.print(F("Connected to: ")); 105 | Serial.println(currentOperator); 106 | } 107 | else 108 | { 109 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 110 | while (1) 111 | ; // Do nothing more 112 | } 113 | 114 | // Deactivate the PSD profile - in case one is already active 115 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_DEACTIVATE) != SARA_R5_SUCCESS) 116 | { 117 | Serial.println(F("Warning: performPDPaction (deactivate profile) failed. Probably because no profile was active.")); 118 | } 119 | 120 | // Load the PSD profile from NVM - these were saved by a previous example 121 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_LOAD) != SARA_R5_SUCCESS) 122 | { 123 | Serial.println(F("performPDPaction (load from NVM) failed! Freezing...")); 124 | while (1) 125 | ; // Do nothing more 126 | } 127 | 128 | // Activate the profile 129 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_ACTIVATE) != SARA_R5_SUCCESS) 130 | { 131 | Serial.println(F("performPDPaction (activate profile) failed! Freezing...")); 132 | while (1) 133 | ; // Do nothing more 134 | } 135 | 136 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 137 | 138 | //Get the time from an NTP server and use it to set the clock. See SARA-R5_NTP.ino 139 | uint8_t y, mo, d, h, min, s; 140 | bool success = getNTPTime(&y, &mo, &d, &h, &min, &s); 141 | if (!success) 142 | { 143 | Serial.println(F("getNTPTime failed! Freezing...")); 144 | while (1) 145 | ; // Do nothing more 146 | } 147 | 148 | //Set the SARA's RTC. Set the time zone to zero so the clock uses UTC 149 | if (mySARA.setClock(y, mo, d, h, min, s, 0) != SARA_R5_SUCCESS) 150 | { 151 | Serial.println(F("setClock failed! Freezing...")); 152 | while (1) 153 | ; // Do nothing more 154 | } 155 | 156 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 157 | 158 | // Read and print the clock as a String 159 | Serial.print(F("The UTC time is: ")); 160 | String theTime = mySARA.clock(); 161 | Serial.println(theTime); 162 | } 163 | 164 | void loop() 165 | { 166 | // Nothing to do here 167 | } 168 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example13_SetClockWithNTP/SARA-R5_NTP.ino: -------------------------------------------------------------------------------- 1 | 2 | #include // Note: this is the standard c time library, not Time.h 3 | 4 | // Get the time from NTP 5 | // This code is based heavily on: 6 | // https://docs.arduino.cc/tutorials/mkr-nb-1500/mkr-nb-library-examples#mkr-nb-gprs-udp-ntp-client 7 | // Many thanks to: Michael Margolis, Tom Igoe, Arturo Guadalupi, et al 8 | 9 | // NTP Server 10 | const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server 11 | //const char* ntpServer = "africa.pool.ntp.org"; // The Network Time Protocol Server 12 | //const char* ntpServer = "asia.pool.ntp.org"; // The Network Time Protocol Server 13 | //const char* ntpServer = "europe.pool.ntp.org"; // The Network Time Protocol Server 14 | //const char* ntpServer = "north-america.pool.ntp.org"; // The Network Time Protocol Server 15 | //const char* ntpServer = "oceania.pool.ntp.org"; // The Network Time Protocol Server 16 | //const char* ntpServer = "south-america.pool.ntp.org"; // The Network Time Protocol Server 17 | 18 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 19 | 20 | bool getNTPTime(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h, uint8_t *min, uint8_t *s) 21 | { 22 | int serverPort = 123; //NTP requests are to port 123 23 | 24 | // Set up the packetBuffer for the NTP request 25 | const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message 26 | byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 27 | 28 | // set all bytes in the buffer to 0 29 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 30 | 31 | // Initialize values needed to form NTP request 32 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 33 | packetBuffer[1] = 0; // Stratum, or type of clock 34 | packetBuffer[2] = 6; // Polling Interval 35 | packetBuffer[3] = 0xEC; // Peer Clock Precision 36 | // 8 bytes of zero for Root Delay & Root Dispersion 37 | packetBuffer[12] = 49; 38 | packetBuffer[13] = 0x4E; 39 | packetBuffer[14] = 49; 40 | packetBuffer[15] = 52; 41 | 42 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 43 | 44 | //Allocate a UDP socket to talk to the NTP server 45 | 46 | int socketNum = mySARA.socketOpen(SARA_R5_UDP); 47 | if (socketNum == -1) 48 | { 49 | Serial.println(F("getNTPTime: socketOpen failed!")); 50 | return (false); 51 | } 52 | 53 | Serial.print(F("getNTPTime: using socket ")); 54 | Serial.println(socketNum); 55 | 56 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 57 | 58 | // Send the request - NTP uses UDP 59 | 60 | if (mySARA.socketWriteUDP(socketNum, ntpServer, serverPort, (const char *)&packetBuffer, NTP_PACKET_SIZE) != SARA_R5_SUCCESS) // Send the request 61 | { 62 | Serial.println(F("getNTPTime: socketWrite failed!")); 63 | mySARA.socketClose(socketNum); // Be nice. Close the socket 64 | return (false); 65 | } 66 | 67 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 68 | 69 | // Wait up to 10 seconds for the response 70 | unsigned long requestTime = millis(); 71 | 72 | while (millis() < (requestTime + 10000)) 73 | { 74 | // We could use the Socket Read Callback to get the data, but, just for giggles, 75 | // and to prove it works, let's poll the arrival of the data manually... 76 | int avail = 0; 77 | if (mySARA.socketReadAvailableUDP(socketNum, &avail) != SARA_R5_SUCCESS) 78 | { 79 | Serial.println(F("getNTPTime: socketReadAvailable failed!")); 80 | mySARA.socketClose(socketNum); // Be nice. Close the socket 81 | return (false); 82 | } 83 | 84 | if (avail >= NTP_PACKET_SIZE) // Is enough data available? 85 | { 86 | if (avail > NTP_PACKET_SIZE) // Too much data? 87 | { 88 | Serial.print(F("getNTPTime: too much data received! Length: ")); 89 | Serial.print(avail); 90 | Serial.print(F(". Reading ")); 91 | Serial.print(NTP_PACKET_SIZE); 92 | Serial.println(F(" bytes...")); 93 | } 94 | 95 | if (mySARA.socketReadUDP(socketNum, NTP_PACKET_SIZE, (char *)&packetBuffer) != SARA_R5_SUCCESS) 96 | { 97 | Serial.println(F("getNTPTime: socketRead failed!")); 98 | mySARA.socketClose(socketNum); // Be nice. Close the socket 99 | return (false); 100 | } 101 | 102 | // Extract the time from the reply 103 | 104 | Serial.print(F("getNTPTime: received ")); 105 | Serial.print(avail); 106 | Serial.println(F(" bytes. Extracting the time...")); 107 | 108 | //the timestamp starts at byte 40 of the received packet and is four bytes, 109 | // or two words, long. First, esxtract the two words: 110 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 111 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 112 | 113 | // combine the four bytes (two words) into a long integer 114 | // this is NTP time (seconds since Jan 1 1900): 115 | unsigned long secsSince1900 = highWord << 16 | lowWord; 116 | 117 | Serial.print(F("getNTPTime: seconds since Jan 1 1900 = ")); 118 | Serial.println(secsSince1900); 119 | 120 | // now convert NTP time into everyday time: 121 | Serial.print(F("getNTPTime: Unix time = ")); 122 | 123 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: 124 | const unsigned long seventyYears = 2208988800UL; 125 | 126 | // subtract seventy years: 127 | unsigned long epoch = secsSince1900 - seventyYears; 128 | 129 | // print Unix time: 130 | Serial.println(epoch); 131 | 132 | // Instead of calculating the year, month, day, etc. manually, let's use time_t and tm to do it for us! 133 | time_t dateTime = epoch; 134 | tm *theTime = gmtime(&dateTime); 135 | 136 | // Load the time into y, mo, d, h, min, s 137 | *y = theTime->tm_year - 100; // tm_year is years since 1900. Convert to years since 2000. 138 | *mo = theTime->tm_mon + 1; //tm_mon starts at zero. Add 1 for January. 139 | *d = theTime->tm_mday; 140 | *h = theTime->tm_hour; 141 | *min = theTime->tm_min; 142 | *s = theTime->tm_sec; 143 | 144 | // Finish off by printing the time 145 | Serial.print(F("getNTPTime: YY/MM/DD HH:MM:SS : ")); 146 | if (*y < 10) Serial.print(F("0")); 147 | Serial.print(*y); 148 | Serial.print(F("/")); 149 | if (*mo < 10) Serial.print(F("0")); 150 | Serial.print(*mo); 151 | Serial.print(F("/")); 152 | if (*d < 10) Serial.print(F("0")); 153 | Serial.print(*d); 154 | Serial.print(F(" ")); 155 | if (*h < 10) Serial.print(F("0")); 156 | Serial.print(*h); 157 | Serial.print(F(":")); 158 | if (*min < 10) Serial.print(F("0")); 159 | Serial.print(*min); 160 | Serial.print(F(":")); 161 | if (*s < 10) Serial.print(F("0")); 162 | Serial.println(*s); 163 | 164 | mySARA.socketClose(socketNum); // Be nice. Close the socket 165 | return (true); // We are done! 166 | } 167 | 168 | delay(100); // Wait before trying again 169 | } 170 | 171 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 172 | 173 | Serial.println(F("getNTPTime: no NTP data received!")); 174 | mySARA.socketClose(socketNum); // Be nice. Close the socket 175 | return (false); 176 | } 177 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example14_AssistNowOffline/SARA-R5_AssistNow_Offline.ino: -------------------------------------------------------------------------------- 1 | 2 | #include "secrets.h" // Update secrets.h with your AssistNow token string 3 | 4 | // u-blox AssistNow https servers 5 | const char assistNowOfflineServer[] = "offline-live1.services.u-blox.com"; 6 | //const char assistNowOfflineServer[] = "offline-live2.services.u-blox.com"; // Alternate server 7 | 8 | const char getQuery[] = "GetOfflineData.ashx?"; 9 | const char tokenPrefix[] = "token="; 10 | const char tokenSuffix[] = ";"; 11 | const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal 12 | const char getFormat[] = "format=mga;"; // Data format. Leave set to mga for M8 onwards. Can be aid. 13 | const char getPeriod[] = "period=1;"; // Optional. The number of weeks into the future that the data will be valid. Can be 1-5. Default = 4. 14 | const char getMgaResolution[] = "resolution=1;"; // Optional. Data resolution: 1 = every day; 2 = every other day; 3 = every 3rd day. 15 | //Note: always use resolution=1. findMGAANOForDate does not yet support finding the 'closest' date. It needs an exact match. 16 | 17 | volatile bool httpResultSeen = false; // Flag to indicate that the HTTP URC was received 18 | 19 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 20 | 21 | // processHTTPcommandResult is provided to the SARA-R5 library via a 22 | // callback setter -- setHTTPCommandCallback. (See the end of setup()) 23 | void processHTTPcommandResult(int profile, int command, int result) 24 | { 25 | Serial.println(); 26 | Serial.print(F("HTTP Command Result: profile: ")); 27 | Serial.print(profile); 28 | Serial.print(F(" command: ")); 29 | Serial.print(command); 30 | Serial.print(F(" result: ")); 31 | Serial.print(result); 32 | if (result == 0) 33 | Serial.print(F(" (fail)")); 34 | if (result == 1) 35 | Serial.print(F(" (success)")); 36 | Serial.println(); 37 | 38 | // Get and print the most recent HTTP protocol error 39 | int error_class; 40 | int error_code; 41 | mySARA.getHTTPprotocolError(0, &error_class, &error_code); 42 | Serial.print(F("Most recent HTTP protocol error: class: ")); 43 | Serial.print(error_class); 44 | Serial.print(F(" code: ")); 45 | Serial.print(error_code); 46 | if (error_code == 0) 47 | Serial.print(F(" (no error)")); 48 | Serial.println(); 49 | 50 | httpResultSeen = true; // Set the flag 51 | } 52 | 53 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 54 | 55 | bool getAssistNowOfflineData(String theFilename) 56 | { 57 | // Use HTTP GET to receive the AssistNow_Offline data. Store it in the SARA-R5's internal file system. 58 | 59 | String theServer = assistNowOfflineServer; // Convert the AssistNow server to String 60 | 61 | const int REQUEST_BUFFER_SIZE = 256; 62 | char theRequest[REQUEST_BUFFER_SIZE]; 63 | 64 | // Assemble the request 65 | // Note the slash at the beginning 66 | snprintf(theRequest, REQUEST_BUFFER_SIZE, "/%s%s%s%s%s%s%s%s", 67 | getQuery, 68 | tokenPrefix, 69 | myAssistNowToken, 70 | tokenSuffix, 71 | getGNSS, 72 | getFormat, 73 | getPeriod, 74 | getMgaResolution 75 | ); 76 | 77 | 78 | String theRequestStr = theRequest; // Convert to String 79 | 80 | Serial.print(F("getAssistNowOfflineData: HTTP GET is https://")); 81 | Serial.print(theServer); 82 | Serial.println(theRequestStr); 83 | 84 | Serial.print(F("getAssistNowOfflineData: the AssistNow data will be stored in: ")); 85 | Serial.println(theFilename); 86 | 87 | // Reset HTTP profile 0 88 | mySARA.resetHTTPprofile(0); 89 | 90 | // Set the server name 91 | mySARA.setHTTPserverName(0, theServer); 92 | 93 | // Use HTTPS 94 | mySARA.setHTTPsecure(0, false); // Setting this to true causes the GET to fail. Maybe due to the default CMNG profile? 95 | 96 | // Set a callback to process the HTTP command result 97 | mySARA.setHTTPCommandCallback(&processHTTPcommandResult); 98 | 99 | httpResultSeen = false; // Clear the flag 100 | 101 | // HTTP GET 102 | mySARA.sendHTTPGET(0, theRequestStr, theFilename); 103 | 104 | // Wait for 20 seconds while calling mySARA.bufferedPoll() to see the HTTP result. 105 | Serial.print(F("getAssistNowOfflineData: Waiting up to 20 seconds for the HTTP Result")); 106 | int i = 0; 107 | while ((i < 20000) && (httpResultSeen == false)) 108 | { 109 | mySARA.bufferedPoll(); // Keep processing data from the SARA so we can catch the HTTP command result 110 | i++; 111 | delay(1); 112 | if (i % 1000 == 0) 113 | Serial.print(F(".")); 114 | } 115 | Serial.println(); 116 | 117 | if (httpResultSeen == false) 118 | { 119 | Serial.print(F("getAssistNowOfflineData: HTTP GET failed!")); 120 | return false; 121 | } 122 | 123 | return true; 124 | } 125 | 126 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 127 | 128 | void prettyPrintString(String theString) // Pretty-print a String in HEX and ASCII format 129 | { 130 | int theLength = theString.length(); 131 | 132 | Serial.println(); 133 | Serial.print(F("String length is ")); 134 | Serial.print(theLength); 135 | Serial.print(F(" (0x")); 136 | Serial.print(theLength, HEX); 137 | Serial.println(F(")")); 138 | Serial.println(); 139 | 140 | for (int i = 0; i < theLength; i += 16) 141 | { 142 | if (i < 10000) Serial.print(F("0")); 143 | if (i < 1000) Serial.print(F("0")); 144 | if (i < 100) Serial.print(F("0")); 145 | if (i < 10) Serial.print(F("0")); 146 | Serial.print(i); 147 | 148 | Serial.print(F(" 0x")); 149 | 150 | if (i < 0x1000) Serial.print(F("0")); 151 | if (i < 0x100) Serial.print(F("0")); 152 | if (i < 0x10) Serial.print(F("0")); 153 | Serial.print(i, HEX); 154 | 155 | Serial.print(F(" ")); 156 | 157 | int j; 158 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 159 | { 160 | if (theString[i + j] < 0x10) Serial.print(F("0")); 161 | Serial.print(theString[i + j], HEX); 162 | Serial.print(F(" ")); 163 | } 164 | 165 | if (((i + j) == theLength) && (j < 16)) 166 | { 167 | for (int k = 0; k < (16 - (theLength % 16)); k++) 168 | { 169 | Serial.print(F(" ")); 170 | } 171 | } 172 | 173 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 174 | { 175 | if ((theString[i + j] >= 0x20) && (theString[i + j] <= 0x7E)) 176 | Serial.write(theString[i + j]); 177 | else 178 | Serial.print(F(".")); 179 | } 180 | 181 | Serial.println(); 182 | } 183 | 184 | Serial.println(); 185 | } 186 | 187 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 188 | 189 | void prettyPrintChars(char *theData, int theLength) // Pretty-print char data in HEX and ASCII format 190 | { 191 | Serial.println(); 192 | Serial.print(F("String length is ")); 193 | Serial.print(theLength); 194 | Serial.print(F(" (0x")); 195 | Serial.print(theLength, HEX); 196 | Serial.println(F(")")); 197 | Serial.println(); 198 | 199 | for (int i = 0; i < theLength; i += 16) 200 | { 201 | if (i < 10000) Serial.print(F("0")); 202 | if (i < 1000) Serial.print(F("0")); 203 | if (i < 100) Serial.print(F("0")); 204 | if (i < 10) Serial.print(F("0")); 205 | Serial.print(i); 206 | 207 | Serial.print(F(" 0x")); 208 | 209 | if (i < 0x1000) Serial.print(F("0")); 210 | if (i < 0x100) Serial.print(F("0")); 211 | if (i < 0x10) Serial.print(F("0")); 212 | Serial.print(i, HEX); 213 | 214 | Serial.print(F(" ")); 215 | 216 | int j; 217 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 218 | { 219 | if (theData[i + j] < 0x10) Serial.print(F("0")); 220 | Serial.print(theData[i + j], HEX); 221 | Serial.print(F(" ")); 222 | } 223 | 224 | if (((i + j) == theLength) && (j < 16)) 225 | { 226 | for (int k = 0; k < (16 - (theLength % 16)); k++) 227 | { 228 | Serial.print(F(" ")); 229 | } 230 | } 231 | 232 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 233 | { 234 | if ((theData[i + j] >= 0x20) && (theData[i + j] <= 0x7E)) 235 | Serial.write(theData[i + j]); 236 | else 237 | Serial.print(F(".")); 238 | } 239 | 240 | Serial.println(); 241 | } 242 | 243 | Serial.println(); 244 | } 245 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example14_AssistNowOffline/SARA-R5_NTP.ino: -------------------------------------------------------------------------------- 1 | 2 | #include // Note: this is the standard c time library, not Time.h 3 | 4 | // Get the time from NTP 5 | // This code is based heavily on: 6 | // https://docs.arduino.cc/tutorials/mkr-nb-1500/mkr-nb-library-examples#mkr-nb-gprs-udp-ntp-client 7 | // Many thanks to: Michael Margolis, Tom Igoe, Arturo Guadalupi, et al 8 | 9 | // NTP Server 10 | const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server 11 | //const char* ntpServer = "africa.pool.ntp.org"; // The Network Time Protocol Server 12 | //const char* ntpServer = "asia.pool.ntp.org"; // The Network Time Protocol Server 13 | //const char* ntpServer = "europe.pool.ntp.org"; // The Network Time Protocol Server 14 | //const char* ntpServer = "north-america.pool.ntp.org"; // The Network Time Protocol Server 15 | //const char* ntpServer = "oceania.pool.ntp.org"; // The Network Time Protocol Server 16 | //const char* ntpServer = "south-america.pool.ntp.org"; // The Network Time Protocol Server 17 | 18 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 19 | 20 | bool getNTPTime(uint8_t *y, uint8_t *mo, uint8_t *d, uint8_t *h, uint8_t *min, uint8_t *s) 21 | { 22 | int serverPort = 123; //NTP requests are to port 123 23 | 24 | // Set up the packetBuffer for the NTP request 25 | const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message 26 | byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 27 | 28 | // set all bytes in the buffer to 0 29 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 30 | 31 | // Initialize values needed to form NTP request 32 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 33 | packetBuffer[1] = 0; // Stratum, or type of clock 34 | packetBuffer[2] = 6; // Polling Interval 35 | packetBuffer[3] = 0xEC; // Peer Clock Precision 36 | // 8 bytes of zero for Root Delay & Root Dispersion 37 | packetBuffer[12] = 49; 38 | packetBuffer[13] = 0x4E; 39 | packetBuffer[14] = 49; 40 | packetBuffer[15] = 52; 41 | 42 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 43 | 44 | //Allocate a UDP socket to talk to the NTP server 45 | 46 | int socketNum = mySARA.socketOpen(SARA_R5_UDP); 47 | if (socketNum == -1) 48 | { 49 | Serial.println(F("getNTPTime: socketOpen failed!")); 50 | return (false); 51 | } 52 | 53 | Serial.print(F("getNTPTime: using socket ")); 54 | Serial.println(socketNum); 55 | 56 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 57 | 58 | // Send the request - NTP uses UDP 59 | 60 | if (mySARA.socketWriteUDP(socketNum, ntpServer, serverPort, (const char *)&packetBuffer, NTP_PACKET_SIZE) != SARA_R5_SUCCESS) // Send the request 61 | { 62 | Serial.println(F("getNTPTime: socketWrite failed!")); 63 | mySARA.socketClose(socketNum); // Be nice. Close the socket 64 | return (false); 65 | } 66 | 67 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 68 | 69 | // Wait up to 10 seconds for the response 70 | unsigned long requestTime = millis(); 71 | 72 | while (millis() < (requestTime + 10000)) 73 | { 74 | // We could use the Socket Read Callback to get the data, but, just for giggles, 75 | // and to prove it works, let's poll the arrival of the data manually... 76 | int avail = 0; 77 | if (mySARA.socketReadAvailableUDP(socketNum, &avail) != SARA_R5_SUCCESS) 78 | { 79 | Serial.println(F("getNTPTime: socketReadAvailable failed!")); 80 | mySARA.socketClose(socketNum); // Be nice. Close the socket 81 | return (false); 82 | } 83 | 84 | if (avail >= NTP_PACKET_SIZE) // Is enough data available? 85 | { 86 | if (avail > NTP_PACKET_SIZE) // Too much data? 87 | { 88 | Serial.print(F("getNTPTime: too much data received! Length: ")); 89 | Serial.print(avail); 90 | Serial.print(F(". Reading ")); 91 | Serial.print(NTP_PACKET_SIZE); 92 | Serial.println(F(" bytes...")); 93 | } 94 | 95 | if (mySARA.socketReadUDP(socketNum, NTP_PACKET_SIZE, (char *)&packetBuffer) != SARA_R5_SUCCESS) 96 | { 97 | Serial.println(F("getNTPTime: socketRead failed!")); 98 | mySARA.socketClose(socketNum); // Be nice. Close the socket 99 | return (false); 100 | } 101 | 102 | // Extract the time from the reply 103 | 104 | Serial.print(F("getNTPTime: received ")); 105 | Serial.print(avail); 106 | Serial.println(F(" bytes. Extracting the time...")); 107 | 108 | //the timestamp starts at byte 40 of the received packet and is four bytes, 109 | // or two words, long. First, esxtract the two words: 110 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 111 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 112 | 113 | // combine the four bytes (two words) into a long integer 114 | // this is NTP time (seconds since Jan 1 1900): 115 | unsigned long secsSince1900 = highWord << 16 | lowWord; 116 | 117 | Serial.print(F("getNTPTime: seconds since Jan 1 1900 = ")); 118 | Serial.println(secsSince1900); 119 | 120 | // now convert NTP time into everyday time: 121 | Serial.print(F("getNTPTime: Unix time = ")); 122 | 123 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: 124 | const unsigned long seventyYears = 2208988800UL; 125 | 126 | // subtract seventy years: 127 | unsigned long epoch = secsSince1900 - seventyYears; 128 | 129 | // print Unix time: 130 | Serial.println(epoch); 131 | 132 | // Instead of calculating the year, month, day, etc. manually, let's use time_t and tm to do it for us! 133 | time_t dateTime = epoch; 134 | tm *theTime = gmtime(&dateTime); 135 | 136 | // Load the time into y, mo, d, h, min, s 137 | *y = theTime->tm_year - 100; // tm_year is years since 1900. Convert to years since 2000. 138 | *mo = theTime->tm_mon + 1; //tm_mon starts at zero. Add 1 for January. 139 | *d = theTime->tm_mday; 140 | *h = theTime->tm_hour; 141 | *min = theTime->tm_min; 142 | *s = theTime->tm_sec; 143 | 144 | // Finish off by printing the time 145 | Serial.print(F("getNTPTime: YY/MM/DD HH:MM:SS : ")); 146 | if (*y < 10) Serial.print(F("0")); 147 | Serial.print(*y); 148 | Serial.print(F("/")); 149 | if (*mo < 10) Serial.print(F("0")); 150 | Serial.print(*mo); 151 | Serial.print(F("/")); 152 | if (*d < 10) Serial.print(F("0")); 153 | Serial.print(*d); 154 | Serial.print(F(" ")); 155 | if (*h < 10) Serial.print(F("0")); 156 | Serial.print(*h); 157 | Serial.print(F(":")); 158 | if (*min < 10) Serial.print(F("0")); 159 | Serial.print(*min); 160 | Serial.print(F(":")); 161 | if (*s < 10) Serial.print(F("0")); 162 | Serial.println(*s); 163 | 164 | mySARA.socketClose(socketNum); // Be nice. Close the socket 165 | return (true); // We are done! 166 | } 167 | 168 | delay(100); // Wait before trying again 169 | } 170 | 171 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 172 | 173 | Serial.println(F("getNTPTime: no NTP data received!")); 174 | mySARA.socketClose(socketNum); // Be nice. Close the socket 175 | return (false); 176 | } 177 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example14_AssistNowOffline/secrets.h: -------------------------------------------------------------------------------- 1 | //Your AssistNow token 2 | const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ"; 3 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example15_GNSS_NTRIP_Caster_With_Callbacks/GNSS_Callbacks.ino: -------------------------------------------------------------------------------- 1 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2 | 3 | // Callback: pushGPGGA will be called when new GPGGA NMEA data arrives 4 | // See u-blox_structs.h for the full definition of NMEA_GGA_data_t 5 | // _____ You can use any name you like for the callback. Use the same name when you call setNMEAGPGGAcallback 6 | // / _____ This _must_ be NMEA_GGA_data_t 7 | // | / _____ You can use any name you like for the struct 8 | // | | / 9 | // | | | 10 | void pushGPGGA(NMEA_GGA_data_t nmeaData) 11 | { 12 | if (connectionOpen) 13 | { 14 | Serial.print(F("Pushing GGA to server: ")); 15 | Serial.print((const char *)nmeaData.nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end 16 | 17 | //Push our current GGA sentence to caster 18 | mySARA.socketWrite(socketNum, (const char *)nmeaData.nmea); 19 | } 20 | } 21 | 22 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 23 | 24 | // Callback: printPVTdata will be called when new NAV PVT data arrives 25 | // See u-blox_structs.h for the full definition of UBX_NAV_PVT_data_t 26 | // _____ You can use any name you like for the callback. Use the same name when you call setAutoPVTcallback 27 | // / _____ This _must_ be UBX_NAV_PVT_data_t 28 | // | / _____ You can use any name you like for the struct 29 | // | | / 30 | // | | | 31 | void printPVTdata(UBX_NAV_PVT_data_t ubxDataStruct) 32 | { 33 | double latitude = ubxDataStruct.lat; // Print the latitude 34 | Serial.print(F("Lat: ")); 35 | Serial.print(latitude / 10000000.0, 7); 36 | 37 | double longitude = ubxDataStruct.lon; // Print the longitude 38 | Serial.print(F(" Long: ")); 39 | Serial.print(longitude / 10000000.0, 7); 40 | 41 | double altitude = ubxDataStruct.hMSL; // Print the height above mean sea level 42 | Serial.print(F(" Height: ")); 43 | Serial.print(altitude / 1000.0, 3); 44 | 45 | uint8_t fixType = ubxDataStruct.fixType; // Print the fix type 46 | Serial.print(F(" Fix: ")); 47 | Serial.print(fixType); 48 | if (fixType == 0) 49 | Serial.print(F(" (None)")); 50 | else if (fixType == 1) 51 | Serial.print(F(" (Dead Reckoning)")); 52 | else if (fixType == 2) 53 | Serial.print(F(" (2D)")); 54 | else if (fixType == 3) 55 | Serial.print(F(" (3D)")); 56 | else if (fixType == 3) 57 | Serial.print(F(" (GNSS + Dead Reckoning)")); 58 | else if (fixType == 5) 59 | Serial.print(F(" (Time Only)")); 60 | else 61 | Serial.print(F(" (UNKNOWN)")); 62 | 63 | uint8_t carrSoln = ubxDataStruct.flags.bits.carrSoln; // Print the carrier solution 64 | Serial.print(F(" Carrier Solution: ")); 65 | Serial.print(carrSoln); 66 | if (carrSoln == 0) 67 | Serial.print(F(" (None)")); 68 | else if (carrSoln == 1) 69 | Serial.print(F(" (Floating)")); 70 | else if (carrSoln == 2) 71 | Serial.print(F(" (Fixed)")); 72 | else 73 | Serial.print(F(" (UNKNOWN)")); 74 | 75 | uint32_t hAcc = ubxDataStruct.hAcc; // Print the horizontal accuracy estimate 76 | Serial.print(F(" Horizontal Accuracy Estimate: ")); 77 | Serial.print(hAcc); 78 | Serial.print(F(" (mm)")); 79 | 80 | Serial.println(); 81 | } 82 | 83 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 84 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example15_GNSS_NTRIP_Caster_With_Callbacks/SARA-R5_Callbacks.ino: -------------------------------------------------------------------------------- 1 | // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 2 | 3 | // processSocketData is provided to the SARA-R5 library via a 4 | // callback setter -- setSocketReadCallbackPlus. (See setup()) 5 | void processSocketData(int socket, const char *theData, int dataLength, IPAddress remoteAddress, int remotePort) 6 | { 7 | Serial.print(F("processSocketData: Data received on socket ")); 8 | Serial.print(socket); 9 | Serial.print(F(". Length is ")); 10 | Serial.print(dataLength); 11 | 12 | if (connectionOpen) 13 | { 14 | Serial.println(F(". Pushing it to the GNSS...")); 15 | myGNSS.pushRawData((uint8_t *)theData, (size_t)dataLength); 16 | 17 | lastReceivedRTCM_ms = millis(); // Update lastReceivedRTCM_ms 18 | } 19 | else 20 | { 21 | Serial.println(); 22 | } 23 | } 24 | 25 | // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 26 | 27 | // processSocketClose is provided to the SARA-R5 library via a 28 | // callback setter -- setSocketCloseCallback. (See setup()) 29 | // 30 | // Note: the SARA-R5 only sends a +UUSOCL URC when the socket is closed by the remote 31 | void processSocketClose(int socket) 32 | { 33 | Serial.print(F("processSocketClose: Socket ")); 34 | Serial.print(socket); 35 | Serial.println(F(" closed!")); 36 | 37 | if (socket == socketNum) 38 | { 39 | socketNum = -1; 40 | connectionOpen = false; 41 | } 42 | } 43 | 44 | // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 45 | 46 | // processPSDAction is provided to the SARA-R5 library via a 47 | // callback setter -- setPSDActionCallback. (See setup()) 48 | void processPSDAction(int result, IPAddress ip) 49 | { 50 | Serial.print(F("processPSDAction: result: ")); 51 | Serial.print(String(result)); 52 | if (result == 0) 53 | Serial.print(F(" (success)")); 54 | Serial.print(F(" IP Address: \"")); 55 | Serial.print(String(ip[0])); 56 | Serial.print(F(".")); 57 | Serial.print(String(ip[1])); 58 | Serial.print(F(".")); 59 | Serial.print(String(ip[2])); 60 | Serial.print(F(".")); 61 | Serial.print(String(ip[3])); 62 | Serial.println(F("\"")); 63 | } 64 | 65 | // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 66 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example15_GNSS_NTRIP_Caster_With_Callbacks/SARA-R5_Example15_GNSS_NTRIP_Caster_With_Callbacks.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | u-blox GNSS NTRIP Caster Client 7 | 8 | Written by: Paul Clark 9 | Date: January 14th 2021 10 | 11 | This example uses the SARA's mobile data connection to: 12 | * Request RTK RTCM data from a NTRIP Caster service 13 | * Push the RTCM data to an external u-blox GNSS module over I2C (not to the one built-in to the SARA-R510M8S) 14 | 15 | The PDP profile is read from NVM. Please make sure you have run examples 4 & 7 previously to set up the profile. 16 | 17 | Update secrets.h with your NTRIP Caster username and password 18 | 19 | ************************************************************************************************** 20 | * Important Note: * 21 | * * 22 | * This example pulls kBytes of correction data from the NTRIP Caster. * 23 | * Depending on your location and service provider, the data rate may exceed the allowable * 24 | * rates for LTE-M or NB-IoT. * 25 | * Worst case, your service provider may throttle or block the connection - now or in the future. * 26 | * We are looking for a long-term solution to this - almost certainly using LTE Cat 1 instead. * 27 | ************************************************************************************************** 28 | 29 | Feel like supporting open source hardware? 30 | Buy a board from SparkFun! 31 | 32 | Licence: MIT 33 | Please see LICENSE.md for full details 34 | 35 | */ 36 | 37 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 38 | 39 | // The ESP32 core has a built in base64 library but not every platform does 40 | // We'll use an external lib if necessary. 41 | 42 | #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_APOLLO3) || defined(ARDUINO_ARDUINO_NANO33BLE) 43 | #include "base64.h" //Built-in ESP32 library 44 | #else 45 | #include //nfriendly library from https://github.com/adamvr/arduino-base64, will work with any platform 46 | #endif 47 | 48 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 49 | 50 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 51 | 52 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 53 | #define saraSerial Serial1 54 | 55 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 56 | //SoftwareSerial saraSerial(8, 9); 57 | 58 | // Create a SARA_R5 object to use throughout the sketch 59 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 60 | // but we can start the SARA without a power pin. It just means we need to manually 61 | // turn the power on if required! ;-D 62 | SARA_R5 mySARA; 63 | 64 | // Create a SARA_R5 object to use throughout the sketch 65 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 66 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 67 | // the pin name is G2 which is connected to pin AD34. 68 | // Change the pin number if required. 69 | //SARA_R5 mySARA(34); 70 | 71 | // Create a SARA_R5 object to use throughout the sketch 72 | // If you are using the LTE GNSS Breakout, and have access to the SARA's RESET_N pin, you can pass that to the library too 73 | // allowing it to do an emergency shutdown if required. 74 | // Change the pin numbers if required. 75 | //SARA_R5 mySARA(34, 35); // PWR_ON, RESET_N 76 | 77 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 78 | 79 | #include //http://librarymanager/All#SparkFun_u-blox_GNSS 80 | SFE_UBLOX_GNSS myGNSS; 81 | 82 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 83 | 84 | // Globals 85 | 86 | volatile int socketNum = -1; // The TCP socket number. -1 indicates invalid/closed socket 87 | volatile bool connectionOpen = false; // Flag to indicate if the connection to the NTRIP Caster is open 88 | volatile unsigned long lastReceivedRTCM_ms; // Record when data last arrived - so we can time out if required 89 | 90 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 91 | 92 | void setup() 93 | { 94 | String currentOperator = ""; 95 | 96 | Serial.begin(115200); // Start the serial console 97 | 98 | // Wait for user to press key to begin 99 | Serial.println(F("SARA-R5 Example")); 100 | Serial.println(F("Wait for the SARA NI LED to light up - then press any key to begin")); 101 | 102 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 103 | ; 104 | while (Serial.available()) // Empty the serial RX buffer 105 | Serial.read(); 106 | 107 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 108 | 109 | // Start communication with the SARA-R5. Load and activate the Packet Switched Data profile. 110 | 111 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 112 | 113 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 114 | // Comment the next line if required 115 | mySARA.invertPowerPin(true); 116 | 117 | // Initialize the SARA 118 | if (mySARA.begin(saraSerial, 115200) ) 119 | { 120 | Serial.println(F("SARA-R5 connected!")); 121 | } 122 | else 123 | { 124 | Serial.println(F("Unable to communicate with the SARA.")); 125 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 126 | while (1) ; // Loop forever on fail 127 | } 128 | Serial.println(); 129 | 130 | // First check to see if we're connected to an operator: 131 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 132 | { 133 | Serial.print(F("Connected to: ")); 134 | Serial.println(currentOperator); 135 | } 136 | else 137 | { 138 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 139 | while (1) 140 | ; // Do nothing more 141 | } 142 | 143 | // Deactivate the PSD profile - in case one is already active 144 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_DEACTIVATE) != SARA_R5_SUCCESS) 145 | { 146 | Serial.println(F("Warning: performPDPaction (deactivate profile) failed. Probably because no profile was active.")); 147 | } 148 | 149 | // Load the PSD profile from NVM - these were saved by a previous example 150 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_LOAD) != SARA_R5_SUCCESS) 151 | { 152 | Serial.println(F("performPDPaction (load from NVM) failed! Freezing...")); 153 | while (1) 154 | ; // Do nothing more 155 | } 156 | 157 | // Set a callback to process the results of the PSD Action - OPTIONAL 158 | mySARA.setPSDActionCallback(&processPSDAction); 159 | 160 | // Activate the profile 161 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_ACTIVATE) != SARA_R5_SUCCESS) 162 | { 163 | Serial.println(F("performPDPaction (activate profile) failed! Freezing...")); 164 | while (1) 165 | ; // Do nothing more 166 | } 167 | 168 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 169 | 170 | //Print the dynamic IP Address (for profile 0) 171 | IPAddress myAddress; 172 | mySARA.getNetworkAssignedIPAddress(0, &myAddress); 173 | Serial.print(F("\r\nMy IP Address is: ")); 174 | Serial.print(myAddress[0]); 175 | Serial.print(F(".")); 176 | Serial.print(myAddress[1]); 177 | Serial.print(F(".")); 178 | Serial.print(myAddress[2]); 179 | Serial.print(F(".")); 180 | Serial.println(myAddress[3]); 181 | 182 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 183 | 184 | // Set a callback to process the socket data 185 | // This will push the RTCM data to the GNSS 186 | mySARA.setSocketReadCallbackPlus(&processSocketData); 187 | 188 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 189 | 190 | // Set a callback to process the socket close 191 | // 192 | // Note: the SARA-R5 only sends a +UUSOCL URC when the socket os closed by the remote 193 | mySARA.setSocketCloseCallback(&processSocketClose); 194 | 195 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 196 | 197 | // Start I2C. Connect to the GNSS. 198 | 199 | Wire.begin(); //Start I2C 200 | 201 | // Uncomment the next line to enable the 'major' GNSS debug messages on Serial so you can see what AssistNow data is being sent 202 | //myGNSS.enableDebugging(Serial, true); 203 | 204 | if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port 205 | { 206 | Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); 207 | while (1); 208 | } 209 | Serial.println(F("u-blox module connected")); 210 | 211 | myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages 212 | myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); //Be sure RTCM3 input is enabled. UBX + RTCM3 is not a valid state. 213 | 214 | myGNSS.setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED); // Set the differential mode - ambiguities are fixed whenever possible 215 | 216 | myGNSS.setNavigationFrequency(1); //Set output in Hz. 217 | 218 | // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA 219 | myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP); 220 | 221 | myGNSS.setNMEAGPGGAcallback(&pushGPGGA); // Set up the callback for GPGGA 222 | 223 | myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C, 10); // Tell the module to output GGA every 10 seconds 224 | 225 | myGNSS.setAutoPVTcallback(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata so we can watch the carrier solution go to fixed 226 | 227 | //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save the ioPort and message settings to NVM 228 | 229 | } 230 | 231 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 232 | 233 | void loop() 234 | { 235 | myGNSS.checkUblox(); // Check for the arrival of new GNSS data and process it. 236 | myGNSS.checkCallbacks(); // Check if any GNSS callbacks are waiting to be processed. 237 | 238 | mySARA.bufferedPoll(); // Process the SARA-R5 URC's. This pushes the incoming RTCM data to the GNSS. 239 | 240 | enum states // Use a 'state machine' to open and close the connection 241 | { 242 | open_connection, 243 | check_connection_and_wait_for_keypress, 244 | close_connection, 245 | waiting_for_keypress 246 | }; 247 | static states state = open_connection; 248 | 249 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 250 | 251 | switch (state) 252 | { 253 | case open_connection: 254 | Serial.println(F("Connecting to the NTRIP caster...")); 255 | if (beginClient((int *)&socketNum, (bool *)&connectionOpen)) // Try to open the connection to the caster 256 | { 257 | Serial.println(F("Connected to the NTRIP caster! Press any key to disconnect...")); 258 | state = check_connection_and_wait_for_keypress; // Move on 259 | } 260 | else 261 | { 262 | Serial.print(F("Could not connect to the caster. Trying again in 5 seconds.")); 263 | for (int i = 0; i < 5; i++) 264 | { 265 | delay(1000); 266 | Serial.print(F(".")); 267 | } 268 | Serial.println(); 269 | } 270 | break; 271 | 272 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 273 | 274 | case check_connection_and_wait_for_keypress: 275 | // If the connection has dropped or timed out, or if the user has pressed a key 276 | if ((checkConnection((int)socketNum, (bool)connectionOpen) == false) || (keyPressed())) 277 | { 278 | state = close_connection; // Move on 279 | } 280 | break; 281 | 282 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 283 | 284 | case close_connection: 285 | Serial.println(F("Closing the connection to the NTRIP caster...")); 286 | closeConnection((int *)&socketNum, (bool *)&connectionOpen); 287 | Serial.println(F("Press any key to reconnect...")); 288 | state = waiting_for_keypress; // Move on 289 | break; 290 | 291 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 292 | 293 | case waiting_for_keypress: 294 | // Wait for the user to press a key 295 | if (keyPressed()) 296 | state = open_connection; // Move on 297 | break; 298 | } 299 | } 300 | 301 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 302 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example15_GNSS_NTRIP_Caster_With_Callbacks/SARA-R5_NTRIP_Client.ino: -------------------------------------------------------------------------------- 1 | 2 | #include "secrets.h" // Update secrets.h with your AssistNow token string 3 | 4 | const unsigned long maxTimeBeforeHangup_ms = 20000UL; //If we fail to get a complete RTCM frame after 20s, then disconnect from caster 5 | 6 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 7 | 8 | //Connect to NTRIP Caster. Return true is connection is successful. 9 | bool beginClient(int *theSocket, bool *connectionIsOpen) 10 | { 11 | // Sanity check - return now if the socket is already open (should be impossible, but still...) 12 | if (*theSocket >= 0) 13 | { 14 | Serial.print(F("beginClient: Socket is already open")); 15 | if (*connectionIsOpen) 16 | { 17 | Serial.println(F(" and the connection is open!")); 18 | } 19 | else 20 | { 21 | Serial.println(F("!")); 22 | } 23 | return (false); 24 | } 25 | 26 | Serial.println(F("beginClient: Opening TCP socket")); 27 | 28 | *theSocket = mySARA.socketOpen(SARA_R5_TCP); 29 | if (*theSocket == -1) 30 | { 31 | Serial.println(F("beginClient: socketOpen failed!")); 32 | return (false); 33 | } 34 | 35 | Serial.print(F("beginClient: Using socket ")); 36 | Serial.println(*theSocket); 37 | 38 | Serial.print(F("beginClient: Connecting to ")); 39 | Serial.print(casterHost); 40 | Serial.print(F(" on port ")); 41 | Serial.println(casterPort); 42 | 43 | if (mySARA.socketConnect(*theSocket, casterHost, casterPort) != SARA_R5_SUCCESS) 44 | { 45 | Serial.println(F("beginClient: socketConnect failed!")); 46 | } 47 | else 48 | { 49 | Serial.print(F("beginClient: Connected to ")); 50 | Serial.print(casterHost); 51 | Serial.print(F(" : ")); 52 | Serial.println(casterPort); 53 | 54 | Serial.print(F("beginClient: Requesting NTRIP Data from mount point ")); 55 | Serial.println(mountPoint); 56 | 57 | // Set up the server request (GET) 58 | const int SERVER_BUFFER_SIZE = 512; 59 | char *serverRequest = new char[SERVER_BUFFER_SIZE]; 60 | memset(serverRequest, 0, SERVER_BUFFER_SIZE); 61 | snprintf(serverRequest, 62 | SERVER_BUFFER_SIZE, 63 | "GET /%s HTTP/1.0\r\nUser-Agent: NTRIP SparkFun u-blox Client v1.0\r\n", 64 | mountPoint); 65 | 66 | // Set up the credentials 67 | const int CREDENTIALS_BUFFER_SIZE = 512; 68 | char *credentials = new char[CREDENTIALS_BUFFER_SIZE]; 69 | memset(credentials, 0, CREDENTIALS_BUFFER_SIZE); 70 | if (strlen(casterUser) == 0) 71 | { 72 | strncpy(credentials, "Accept: */*\r\nConnection: close\r\n", CREDENTIALS_BUFFER_SIZE); 73 | } 74 | else 75 | { 76 | //Pass base64 encoded user:pw 77 | int userCredentialsSize = sizeof(casterUser) + sizeof(casterUserPW) + 1; //The ':' takes up a spot 78 | char *userCredentials = new char[userCredentialsSize]; 79 | memset(userCredentials, 0, userCredentialsSize); 80 | snprintf(userCredentials, userCredentialsSize, "%s:%s", casterUser, casterUserPW); 81 | 82 | Serial.print(F("beginClient: Sending credentials: ")); 83 | Serial.println(userCredentials); 84 | 85 | #if defined(ARDUINO_ARCH_ESP32) 86 | //Encode with ESP32 built-in library 87 | base64 b; 88 | String strEncodedCredentials = b.encode(userCredentials); 89 | int encodedCredentialsSize = strEncodedCredentials.length() + 1; 90 | char *encodedCredentials = new char[encodedCredentialsSize]; 91 | memset(encodedCredentials, 0, encodedCredentialsSize); 92 | strEncodedCredentials.toCharArray(encodedCredentials, encodedCredentialsSize); //Convert String to char array 93 | #elif defined(ARDUINO_ARCH_APOLLO3) || defined(ARDUINO_ARDUINO_NANO33BLE) 94 | int encodedCredentialsSize = userCredentialsSize * 8; 95 | char *encodedCredentials = new char[encodedCredentialsSize]; 96 | memset(encodedCredentials, 0, encodedCredentialsSize); 97 | size_t olen; 98 | mbedtls_base64_encode((unsigned char *)encodedCredentials, encodedCredentialsSize, &olen, (const unsigned char *)userCredentials, strlen(userCredentials)); 99 | #else 100 | //Encode with nfriendly library 101 | int encodedLen = base64_enc_len(userCredentialsSize); 102 | char *encodedCredentials = new char[encodedLen]; //Create array large enough to house encoded data 103 | memset(encodedCredentials, 0, encodedLen); 104 | base64_encode(encodedCredentials, userCredentials, strlen(userCredentials)); //Note: Input array is consumed 105 | #endif 106 | 107 | snprintf(credentials, CREDENTIALS_BUFFER_SIZE, "Authorization: Basic %s\r\n", encodedCredentials); 108 | delete[] userCredentials; 109 | delete[] encodedCredentials; 110 | } 111 | 112 | // Add the encoded credentials to the server request 113 | strncat(serverRequest, credentials, SERVER_BUFFER_SIZE - 1); 114 | strncat(serverRequest, "\r\n", SERVER_BUFFER_SIZE - 1); 115 | 116 | Serial.print(F("beginClient: serverRequest size: ")); 117 | Serial.print(strlen(serverRequest)); 118 | Serial.print(F(" of ")); 119 | Serial.print(SERVER_BUFFER_SIZE); 120 | Serial.println(F(" bytes available")); 121 | 122 | // Send the server request 123 | Serial.println(F("beginClient: Sending server request: ")); 124 | Serial.println(serverRequest); 125 | 126 | mySARA.socketWrite(*theSocket, (const char *)serverRequest); 127 | 128 | //Wait up to 5 seconds for response. Poll the number of available bytes. Don't use the callback yet. 129 | unsigned long startTime = millis(); 130 | int availableLength = 0; 131 | while (availableLength == 0) 132 | { 133 | mySARA.socketReadAvailable(*theSocket, &availableLength); 134 | if (millis() > (startTime + 5000)) 135 | { 136 | Serial.println(F("beginClient: Caster timed out!")); 137 | closeConnection(theSocket, connectionIsOpen); 138 | delete[] serverRequest; 139 | delete[] credentials; 140 | return (false); 141 | } 142 | delay(100); 143 | } 144 | 145 | Serial.print(F("beginClient: server replied with ")); 146 | Serial.print(availableLength); 147 | Serial.println(F(" bytes")); 148 | 149 | //Check reply 150 | int connectionResult = 0; 151 | char *response = new char[512 * 4]; 152 | memset(response, 0, 512 * 4); 153 | size_t responseSpot = 0; 154 | while ((availableLength > 0) && (connectionResult == 0)) // Read bytes from the caster and store them 155 | { 156 | if ((responseSpot + availableLength) >= ((512 * 4) - 1)) // Exit the loop if we get too much data 157 | break; 158 | 159 | mySARA.socketRead(*theSocket, availableLength, &response[responseSpot]); 160 | responseSpot += availableLength; 161 | 162 | //Serial.print(F("beginClient: response is: ")); 163 | //Serial.println(response); 164 | 165 | if (connectionResult == 0) // Only print success/fail once 166 | { 167 | if (strstr(response, "200") != NULL) //Look for '200 OK' 168 | { 169 | Serial.println(F("beginClient: 200 seen!")); 170 | connectionResult = 200; 171 | } 172 | if (strstr(response, "401") != NULL) //Look for '401 Unauthorized' 173 | { 174 | Serial.println(F("beginClient: Hey - your credentials look bad! Check your caster username and password.")); 175 | connectionResult = 401; 176 | } 177 | } 178 | 179 | mySARA.socketReadAvailable(*theSocket, &availableLength); // Update availableLength 180 | 181 | Serial.print(F("beginClient: socket now has ")); 182 | Serial.print(availableLength); 183 | Serial.println(F(" bytes available")); 184 | } 185 | response[responseSpot] = '\0'; // NULL-terminate the response 186 | 187 | //Serial.print(F("beginClient: Caster responded with: ")); Serial.println(response); // Uncomment this line to see the full response 188 | 189 | // Free the memory allocated for serverRequest, credentials and response 190 | delete[] serverRequest; 191 | delete[] credentials; 192 | delete[] response; 193 | 194 | if (connectionResult != 200) 195 | { 196 | Serial.print(F("beginClient: Failed to connect to ")); 197 | Serial.println(casterHost); 198 | closeConnection(theSocket, connectionIsOpen); 199 | return (false); 200 | } 201 | else 202 | { 203 | Serial.print(F("beginClient: Connected to: ")); 204 | Serial.println(casterHost); 205 | lastReceivedRTCM_ms = millis(); //Reset timeout 206 | } 207 | 208 | } //End attempt to connect 209 | 210 | *connectionIsOpen = true; 211 | return (true); 212 | } // /beginClient 213 | 214 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 215 | 216 | //Check the connection 217 | //Return false if: the connection has dropped, or if we receive no data for maxTimeBeforeHangup_ms 218 | bool checkConnection(int theSocket, bool connectionIsOpen) 219 | { 220 | if ((theSocket >= 0) && connectionIsOpen) // Check that the connection is still open 221 | { 222 | ; // Nothing to do here. The RTCM is pushed to the GNSS by the callabck. 223 | } 224 | else 225 | { 226 | Serial.println(F("checkConnection: Connection dropped!")); 227 | return (false); // Connection has dropped - return false 228 | } 229 | 230 | //Timeout if we don't have new data for maxTimeBeforeHangup_ms 231 | if ((millis() - lastReceivedRTCM_ms) > maxTimeBeforeHangup_ms) 232 | { 233 | Serial.println(F("checkConnection: RTCM timeout!")); 234 | return (false); // Connection has timed out - return false 235 | } 236 | 237 | return (true); 238 | } // /processConnection 239 | 240 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 241 | 242 | void closeConnection(int *theSocket, bool *connectionIsOpen) 243 | { 244 | // Check the socket is actually open, otherwise we'll get an error when we try to close it 245 | if (*theSocket >= 0) 246 | { 247 | mySARA.socketClose(*theSocket); 248 | Serial.println(F("closeConnection: Connection closed!")); 249 | } 250 | else 251 | { 252 | Serial.println(F("closeConnection: Connection was already closed!")); 253 | } 254 | 255 | *theSocket = -1; // Clear the socket number to indicate it is closed 256 | *connectionIsOpen = false; // Flag that the connection is closed 257 | } 258 | 259 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 260 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example15_GNSS_NTRIP_Caster_With_Callbacks/Utils.ino: -------------------------------------------------------------------------------- 1 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2 | 3 | void prettyPrintString(String theString) // Pretty-print a String in HEX and ASCII format 4 | { 5 | int theLength = theString.length(); 6 | 7 | Serial.println(); 8 | Serial.print(F("String length is ")); 9 | Serial.print(theLength); 10 | Serial.print(F(" (0x")); 11 | Serial.print(theLength, HEX); 12 | Serial.println(F(")")); 13 | Serial.println(); 14 | 15 | for (int i = 0; i < theLength; i += 16) 16 | { 17 | if (i < 10000) Serial.print(F("0")); 18 | if (i < 1000) Serial.print(F("0")); 19 | if (i < 100) Serial.print(F("0")); 20 | if (i < 10) Serial.print(F("0")); 21 | Serial.print(i); 22 | 23 | Serial.print(F(" 0x")); 24 | 25 | if (i < 0x1000) Serial.print(F("0")); 26 | if (i < 0x100) Serial.print(F("0")); 27 | if (i < 0x10) Serial.print(F("0")); 28 | Serial.print(i, HEX); 29 | 30 | Serial.print(F(" ")); 31 | 32 | int j; 33 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 34 | { 35 | if (theString[i + j] < 0x10) Serial.print(F("0")); 36 | Serial.print(theString[i + j], HEX); 37 | Serial.print(F(" ")); 38 | } 39 | 40 | if (((i + j) == theLength) && (j < 16)) 41 | { 42 | for (int k = 0; k < (16 - (theLength % 16)); k++) 43 | { 44 | Serial.print(F(" ")); 45 | } 46 | } 47 | 48 | for (j = 0; ((i + j) < theLength) && (j < 16); j++) 49 | { 50 | if ((theString[i + j] >= 0x20) && (theString[i + j] <= 0x7E)) 51 | Serial.write(theString[i + j]); 52 | else 53 | Serial.print(F(".")); 54 | } 55 | 56 | Serial.println(); 57 | } 58 | 59 | Serial.println(); 60 | } 61 | 62 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 63 | 64 | //Return true if a key has been pressed 65 | bool keyPressed() 66 | { 67 | if (Serial.available()) // Check for a new key press 68 | { 69 | delay(100); // Wait for any more keystrokes to arrive 70 | while (Serial.available()) // Empty the serial buffer 71 | Serial.read(); 72 | return (true); 73 | } 74 | 75 | return (false); 76 | } 77 | 78 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 79 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example15_GNSS_NTRIP_Caster_With_Callbacks/secrets.h: -------------------------------------------------------------------------------- 1 | //Your WiFi credentials 2 | const char ssid[] = "yourSSID"; 3 | const char password[] = "yourPassword"; 4 | 5 | //RTK2Go works well and is free 6 | //const char casterHost[] = "rtk2go.com"; 7 | //const uint16_t casterPort = 2101; 8 | //const char casterUser[] = "myEmail@test.com"; //User must provide their own email address to use RTK2Go 9 | //const char casterUserPW[] = ""; 10 | //const char mountPoint[] = "bldr_SparkFun1"; //The mount point you want to get data from 11 | 12 | //Emlid Caster also works well and is free 13 | //const char casterHost[] = "caster.emlid.com"; 14 | //const uint16_t casterPort = 2101; 15 | //const char casterUser[] = "u99696"; //User name and pw must be obtained through their web portal 16 | //const char casterUserPW[] = "466zez"; 17 | //const char mountPoint[] = "MP1979"; //The mount point you want to get data from 18 | 19 | // Skylark (Swift Navigation) is awesome - but requires a subscription: 20 | // https://www.swiftnav.com/skylark 21 | // https://account.swiftnav.com/sign-up 22 | // Use the promo-code ONEMONTHFREE for a free one month access to Skylark on one device 23 | const char casterHost[] = "na.skylark.swiftnav.com"; // na = North Americs L1+L2; eu = Europe L1+L2 24 | const uint16_t casterPort = 2101; 25 | const char casterUser[] = "NTRIPusername+accountSubdomain"; // This is generated when you add a device to your Skylark account 26 | const char casterUserPW[] = "devicePassword"; 27 | const char mountPoint[] = "CRS"; // The mount point you want to get data from. Select CRS (Cloud Reference Station) for the ZED-F9x 28 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example16_GNSS_NTRIP_Caster__Polling/SARA-R5_Example16_GNSS_NTRIP_Caster__Polling.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | u-blox GNSS NTRIP Caster Client - Polling 7 | 8 | This version uses polling to check for the arrival of new RTK correction and NMEA GPGGA data. 9 | It performs better on Mbed OS platforms: SparkFun Artemis; Arduino Nano 10 | 11 | Written by: Paul Clark 12 | Date: January 18th 2021 13 | 14 | This example uses the SARA's mobile data connection to: 15 | * Request RTK RTCM data from a NTRIP Caster service 16 | * Push the RTCM data to an external u-blox GNSS module over I2C (not to the one built-in to the SARA-R510M8S) 17 | * NMEA GPGGA data is pushed to the Caster every 10 seconds 18 | 19 | The PDP profile is read from NVM. Please make sure you have run examples 4 & 7 previously to set up the profile. 20 | 21 | Update secrets.h with your NTRIP Caster username and password 22 | 23 | ************************************************************************************************** 24 | * Important Note: * 25 | * * 26 | * This example pulls kBytes of correction data from the NTRIP Caster. * 27 | * Depending on your location and service provider, the data rate may exceed the allowable * 28 | * rates for LTE-M or NB-IoT. * 29 | * Worst case, your service provider may throttle or block the connection - now or in the future. * 30 | * We are looking for a long-term solution to this - almost certainly using LTE Cat 1 instead. * 31 | ************************************************************************************************** 32 | 33 | Feel like supporting open source hardware? 34 | Buy a board from SparkFun! 35 | 36 | Licence: MIT 37 | Please see LICENSE.md for full details 38 | 39 | */ 40 | 41 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 42 | 43 | // The ESP32 core has a built in base64 library but not every platform does 44 | // We'll use an external lib if necessary. 45 | 46 | #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_APOLLO3) || defined(ARDUINO_ARDUINO_NANO33BLE) 47 | #include "base64.h" //Built-in ESP32 library 48 | #else 49 | #include //nfriendly library from https://github.com/adamvr/arduino-base64, will work with any platform 50 | #endif 51 | 52 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 53 | 54 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 55 | 56 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 57 | #define saraSerial Serial1 58 | 59 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 60 | //SoftwareSerial saraSerial(8, 9); 61 | 62 | // Create a SARA_R5 object to use throughout the sketch 63 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 64 | // but we can start the SARA without a power pin. It just means we need to manually 65 | // turn the power on if required! ;-D 66 | SARA_R5 mySARA; 67 | 68 | // Create a SARA_R5 object to use throughout the sketch 69 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 70 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 71 | // the pin name is G2 which is connected to pin AD34. 72 | // Change the pin number if required. 73 | //SARA_R5 mySARA(34); 74 | 75 | // Create a SARA_R5 object to use throughout the sketch 76 | // If you are using the LTE GNSS Breakout, and have access to the SARA's RESET_N pin, you can pass that to the library too 77 | // allowing it to do an emergency shutdown if required. 78 | // Change the pin numbers if required. 79 | //SARA_R5 mySARA(34, 35); // PWR_ON, RESET_N 80 | 81 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 82 | 83 | #include //http://librarymanager/All#SparkFun_u-blox_GNSS 84 | SFE_UBLOX_GNSS myGNSS; 85 | 86 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 87 | 88 | // Globals 89 | 90 | volatile int socketNum = -1; // The TCP socket number. -1 indicates invalid/closed socket 91 | volatile bool connectionOpen = false; // Flag to indicate if the connection to the NTRIP Caster is open 92 | volatile unsigned long lastReceivedRTCM_ms; // Record when data last arrived - so we can time out if required 93 | 94 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 95 | 96 | void setup() 97 | { 98 | String currentOperator = ""; 99 | 100 | Serial.begin(115200); // Start the serial console 101 | 102 | // Wait for user to press key to begin 103 | Serial.println(F("SARA-R5 Example")); 104 | Serial.println(F("Wait for the SARA NI LED to light up - then press any key to begin")); 105 | 106 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 107 | ; 108 | while (Serial.available()) // Empty the serial RX buffer 109 | Serial.read(); 110 | 111 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 112 | 113 | // Start communication with the SARA-R5. Load and activate the Packet Switched Data profile. 114 | 115 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 116 | 117 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 118 | // Comment the next line if required 119 | mySARA.invertPowerPin(true); 120 | 121 | // Initialize the SARA 122 | if (mySARA.begin(saraSerial, 115200) ) 123 | { 124 | Serial.println(F("SARA-R5 connected!")); 125 | } 126 | else 127 | { 128 | Serial.println(F("Unable to communicate with the SARA.")); 129 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 130 | while (1) ; // Loop forever on fail 131 | } 132 | Serial.println(); 133 | 134 | // First check to see if we're connected to an operator: 135 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 136 | { 137 | Serial.print(F("Connected to: ")); 138 | Serial.println(currentOperator); 139 | } 140 | else 141 | { 142 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 143 | while (1) 144 | ; // Do nothing more 145 | } 146 | 147 | // Deactivate the PSD profile - in case one is already active 148 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_DEACTIVATE) != SARA_R5_SUCCESS) 149 | { 150 | Serial.println(F("Warning: performPDPaction (deactivate profile) failed. Probably because no profile was active.")); 151 | } 152 | 153 | // Load the PSD profile from NVM - these were saved by a previous example 154 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_LOAD) != SARA_R5_SUCCESS) 155 | { 156 | Serial.println(F("performPDPaction (load from NVM) failed! Freezing...")); 157 | while (1) 158 | ; // Do nothing more 159 | } 160 | 161 | // Activate the profile 162 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_ACTIVATE) != SARA_R5_SUCCESS) 163 | { 164 | Serial.println(F("performPDPaction (activate profile) failed! Freezing...")); 165 | while (1) 166 | ; // Do nothing more 167 | } 168 | 169 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 170 | 171 | //Print the dynamic IP Address (for profile 0) 172 | IPAddress myAddress; 173 | mySARA.getNetworkAssignedIPAddress(0, &myAddress); 174 | Serial.print(F("\r\nMy IP Address is: ")); 175 | Serial.print(myAddress[0]); 176 | Serial.print(F(".")); 177 | Serial.print(myAddress[1]); 178 | Serial.print(F(".")); 179 | Serial.print(myAddress[2]); 180 | Serial.print(F(".")); 181 | Serial.println(myAddress[3]); 182 | 183 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 184 | 185 | // Start I2C. Connect to the GNSS. 186 | 187 | Wire.begin(); //Start I2C 188 | 189 | // Uncomment the next line to enable the 'major' GNSS debug messages on Serial so you can see what AssistNow data is being sent 190 | //myGNSS.enableDebugging(Serial, true); 191 | 192 | if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port 193 | { 194 | Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing.")); 195 | while (1); 196 | } 197 | Serial.println(F("u-blox module connected")); 198 | 199 | myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages 200 | myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); //Be sure RTCM3 input is enabled. UBX + RTCM3 is not a valid state. 201 | 202 | myGNSS.setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED); // Set the differential mode - ambiguities are fixed whenever possible 203 | 204 | myGNSS.setNavigationFrequency(1); //Set the navigation rate to 1Hz 205 | 206 | myGNSS.setAutoPVT(true); // Enable automatic PVT reports at the navigation frequency 207 | 208 | // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA 209 | myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP); 210 | 211 | myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C, 10); // Tell the module to output GGA every 10 seconds 212 | 213 | //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save the ioPort and message settings to NVM 214 | 215 | } 216 | 217 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 218 | 219 | void loop() 220 | { 221 | enum states // Use a 'state machine' to open and close the connection 222 | { 223 | open_connection, 224 | check_connection_and_wait_for_keypress, 225 | close_connection, 226 | waiting_for_keypress 227 | }; 228 | static states state = open_connection; 229 | 230 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 231 | 232 | switch (state) 233 | { 234 | case open_connection: 235 | Serial.println(F("Connecting to the NTRIP caster...")); 236 | if (beginClient((int *)&socketNum, (bool *)&connectionOpen)) // Try to open the connection to the caster 237 | { 238 | Serial.println(F("Connected to the NTRIP caster! Press any key to disconnect...")); 239 | state = check_connection_and_wait_for_keypress; // Move on 240 | } 241 | else 242 | { 243 | Serial.print(F("Could not connect to the caster. Trying again in 5 seconds.")); 244 | for (int i = 0; i < 5; i++) 245 | { 246 | delay(1000); 247 | Serial.print(F(".")); 248 | } 249 | Serial.println(); 250 | } 251 | break; 252 | 253 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 254 | 255 | case check_connection_and_wait_for_keypress: 256 | // If the connection has dropped or timed out, or if the user has pressed a key 257 | if ((checkConnection((int)socketNum, (bool)connectionOpen) == false) || (keyPressed())) 258 | { 259 | state = close_connection; // Move on 260 | } 261 | delay(50); 262 | break; 263 | 264 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 265 | 266 | case close_connection: 267 | Serial.println(F("Closing the connection to the NTRIP caster...")); 268 | closeConnection((int *)&socketNum, (bool *)&connectionOpen); 269 | Serial.println(F("Press any key to reconnect...")); 270 | state = waiting_for_keypress; // Move on 271 | break; 272 | 273 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 274 | 275 | case waiting_for_keypress: 276 | // Wait for the user to press a key 277 | checkConnection((int)socketNum, (bool)connectionOpen); // 'Check' the connection - to print the latest PVT data 278 | if (keyPressed()) 279 | state = open_connection; // Move on 280 | break; 281 | } 282 | } 283 | 284 | //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 285 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example16_GNSS_NTRIP_Caster__Polling/secrets.h: -------------------------------------------------------------------------------- 1 | //Your WiFi credentials 2 | const char ssid[] = "yourSSID"; 3 | const char password[] = "yourPassword"; 4 | 5 | //RTK2Go works well and is free 6 | //const char casterHost[] = "rtk2go.com"; 7 | //const uint16_t casterPort = 2101; 8 | //const char casterUser[] = "myEmail@test.com"; //User must provide their own email address to use RTK2Go 9 | //const char casterUserPW[] = ""; 10 | //const char mountPoint[] = "bldr_SparkFun1"; //The mount point you want to get data from 11 | 12 | //Emlid Caster also works well and is free 13 | //const char casterHost[] = "caster.emlid.com"; 14 | //const uint16_t casterPort = 2101; 15 | //const char casterUser[] = "u99696"; //User name and pw must be obtained through their web portal 16 | //const char casterUserPW[] = "466zez"; 17 | //const char mountPoint[] = "MP1979"; //The mount point you want to get data from 18 | 19 | // Skylark (Swift Navigation) is awesome - but requires a subscription: 20 | // https://www.swiftnav.com/skylark 21 | // https://account.swiftnav.com/sign-up 22 | // Use the promo-code ONEMONTHFREE for a free one month access to Skylark on one device 23 | const char casterHost[] = "na.skylark.swiftnav.com"; // na = North Americs L1+L2; eu = Europe L1+L2 24 | const uint16_t casterPort = 2101; 25 | const char casterUser[] = "NTRIPusername+accountSubdomain"; // This is generated when you add a device to your Skylark account 26 | const char casterUserPW[] = "devicePassword"; 27 | const char mountPoint[] = "CRS"; // The mount point you want to get data from. Select CRS (Cloud Reference Station) for the ZED-F9x 28 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example17_ThingSpeak_MQTT/SARA-R5_Example17_ThingSpeak_MQTT.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | ThingSpeak (MQTT) 7 | 8 | Written by: Paul Clark 9 | Date: November 14th 2023 10 | 11 | This example uses the SARA's mobile data connection and MQTT to publish random temperatures on ThingSpeak. 12 | It also subscribes to the same topic (channel) so you can read the data back again! 13 | 14 | See: https://thingspeak.com/ 15 | 16 | And: https://uk.mathworks.com/help/thingspeak/mqtt-basics.html#responsive_offcanvas 17 | 18 | You will need to: 19 | Create a ThingSpeak User Account – https://thingspeak.com/login 20 | Create a new Channel by selecting Channels, My Channels, and then New Channel 21 | Note the Channel ID and copy&paste it into myChannelID below 22 | Click on the Devices drop-down at the top of the screen and select MQTT 23 | Create a new MQTT Device using "Add a new device". Give it a name 24 | Authorize the New Channel you created above, then Add Channel, then Add Device 25 | Copy the Username, Client ID and password into myUsername, myClientID and myPassword below 26 | The random temperature reading will be added to the channel as "Field 1" 27 | 28 | Feel like supporting open source hardware? 29 | Buy a board from SparkFun! 30 | 31 | Licence: MIT 32 | Please see LICENSE.md for full details 33 | 34 | */ 35 | 36 | #include 37 | 38 | // ThingSpeak via MQTT Publish 39 | 40 | String brokerName = "mqtt3.thingspeak.com"; // MQTT Broker 41 | 42 | const int brokerPort = 1883; // MQTT port (TCP, no encryption) 43 | 44 | String myUsername = "OAAxOjYHIwooJykfCiYoEx0"; 45 | 46 | String myClientID = "OAAxOjYHIwooJykfCiYoEx0"; 47 | 48 | String myPassword = "RqY/6L246tULLVWUzCqJBX/V"; 49 | 50 | String myChannelID = "1225363"; // Public View: https://thingspeak.com/channels/1225363 51 | 52 | // SARA-R5 53 | 54 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 55 | 56 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 57 | #define saraSerial Serial1 58 | 59 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 60 | //SoftwareSerial saraSerial(8, 9); 61 | 62 | // Create a SARA_R5 object to use throughout the sketch 63 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 64 | // but we can start the SARA without a power pin. It just means we need to manually 65 | // turn the power on if required! ;-D 66 | SARA_R5 mySARA; 67 | 68 | // Create a SARA_R5 object to use throughout the sketch 69 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 70 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 71 | // the pin name is G2 which is connected to pin AD34. 72 | // Change the pin number if required. 73 | //SARA_R5 mySARA(34); 74 | 75 | // processMQTTcommandResult is provided to the SARA-R5 library via a 76 | // callback setter -- setMQTTCommandCallback. (See the end of setup()) 77 | void processMQTTcommandResult(int command, int result) 78 | { 79 | Serial.println(); 80 | Serial.print(F("MQTT Command Result: command: ")); 81 | Serial.print(command); 82 | Serial.print(F(" result: ")); 83 | Serial.print(result); 84 | if (result == 0) 85 | Serial.print(F(" (fail)")); 86 | if (result == 1) 87 | Serial.print(F(" (success)")); 88 | Serial.println(); 89 | 90 | // Get and print the most recent MQTT protocol error 91 | int error_class; 92 | int error_code; 93 | mySARA.getMQTTprotocolError(&error_class, &error_code); 94 | Serial.print(F("Most recent MQTT protocol error: class: ")); 95 | Serial.print(error_class); 96 | Serial.print(F(" code: ")); 97 | Serial.print(error_code); 98 | if (error_code == 0) 99 | Serial.print(F(" (no error)")); 100 | Serial.println(); 101 | } 102 | 103 | void setup() 104 | { 105 | delay(1000); 106 | 107 | String currentOperator = ""; 108 | 109 | Serial.begin(115200); // Start the serial console 110 | 111 | // Wait for user to press key to begin 112 | Serial.println(F("SARA-R5 Example")); 113 | Serial.println(F("Wait for the SARA NI LED to light up - then press any key to begin")); 114 | 115 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 116 | ; 117 | while (Serial.available()) // Empty the serial RX buffer 118 | Serial.read(); 119 | 120 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 121 | 122 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 123 | // Comment the next line if required 124 | mySARA.invertPowerPin(true); 125 | 126 | // Initialize the SARA 127 | if (mySARA.begin(saraSerial, 115200) ) 128 | { 129 | Serial.println(F("SARA-R5 connected!")); 130 | } 131 | else 132 | { 133 | Serial.println(F("Unable to communicate with the SARA.")); 134 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 135 | while (1) ; // Loop forever on fail 136 | } 137 | Serial.println(); 138 | 139 | // First check to see if we're connected to an operator: 140 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 141 | { 142 | Serial.print(F("Connected to: ")); 143 | Serial.println(currentOperator); 144 | } 145 | else 146 | { 147 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 148 | while (1) 149 | ; // Do nothing more 150 | } 151 | 152 | // Deactivate the PSD profile - in case one is already active 153 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_DEACTIVATE) != SARA_R5_SUCCESS) 154 | { 155 | Serial.println(F("Warning: performPDPaction (deactivate profile) failed. Probably because no profile was active.")); 156 | } 157 | 158 | // Load the PSD profile from NVM - these were saved by a previous example 159 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_LOAD) != SARA_R5_SUCCESS) 160 | { 161 | Serial.println(F("performPDPaction (load from NVM) failed! Freezing...")); 162 | while (1) 163 | ; // Do nothing more 164 | } 165 | 166 | // Activate the PSD profile 167 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_ACTIVATE) != SARA_R5_SUCCESS) 168 | { 169 | Serial.println(F("performPDPaction (activate profile) failed! Freezing...")); 170 | while (1) 171 | ; // Do nothing more 172 | } 173 | 174 | // Set up the MQTT command callback 175 | mySARA.setMQTTCommandCallback(processMQTTcommandResult); 176 | 177 | // Disable the security profile 178 | mySARA.setMQTTsecure(false); 179 | 180 | // Set Client ID 181 | mySARA.setMQTTclientId(myClientID); 182 | 183 | // Set the broker name and port 184 | mySARA.setMQTTserver(brokerName, brokerPort); 185 | 186 | // Set the user name and password 187 | mySARA.setMQTTcredentials(myUsername, myPassword); 188 | 189 | // Connect 190 | if (mySARA.connectMQTT() == SARA_R5_SUCCESS) 191 | Serial.println(F("MQTT connect: success")); 192 | else 193 | Serial.println(F("MQTT connect: failed!")); 194 | 195 | // The LTE modem has difficulties subscribing/unsubscribing more than one topic at the same time. 196 | // We can only start one operation at a time wait for the URC and add a extra delay before we can 197 | // do the next operation. 198 | // Wait for ~2 seconds 199 | for (int i = 0; i < 200; i++) 200 | { 201 | mySARA.bufferedPoll(); // Keep processing data from the SARA 202 | delay(10); 203 | } 204 | 205 | // Subscribe to the channel topic, so we can read the data back again 206 | String subscribeTopic = "channels/" + myChannelID + "/subscribe/fields/field1"; 207 | if (mySARA.subscribeMQTTtopic(0, subscribeTopic) == SARA_R5_SUCCESS) // QoS = 0 208 | Serial.println(F("MQTT subscribe: success")); 209 | else 210 | Serial.println(F("MQTT subscribe: failed!")); 211 | 212 | // Wait for ~2 seconds 213 | for (int i = 0; i < 200; i++) 214 | { 215 | mySARA.bufferedPoll(); // Keep processing data from the SARA 216 | delay(10); 217 | } 218 | } 219 | 220 | void loop() 221 | { 222 | float temperature = ((float)random(2000,3000)) / 100.0; // Create a random temperature between 20 and 30 223 | 224 | // Send data using MQTT Publish 225 | String Topic = "channels/" + myChannelID + "/publish"; 226 | String DataField = "field1=" + String(temperature) + "&status=MQTTPUBLISH"; 227 | 228 | Serial.println(); 229 | Serial.print(F("Publishing a temperature of ")); 230 | Serial.print(String(temperature)); 231 | Serial.println(F(" to ThingSpeak")); 232 | 233 | // Publish the text message 234 | mySARA.mqttPublishTextMsg(Topic, DataField.c_str(), 0, true); // QoS = 0, retain = true 235 | 236 | // Wait for ~10 seconds 237 | for (int i = 0; i < 1000; i++) 238 | { 239 | mySARA.bufferedPoll(); // Keep processing data from the SARA 240 | delay(10); 241 | } 242 | 243 | // Check for any received data 244 | // The MQTT API does not allow getting the size before actually reading the data. 245 | // So we have to allocate a big enough buffer. 246 | const int MQTT_MAX_MSG_SIZE = 1024; 247 | static uint8_t buf[MQTT_MAX_MSG_SIZE]; 248 | String topic; 249 | int len = -1; 250 | int qos = -1; 251 | if (mySARA.readMQTT(&qos, &topic, buf, MQTT_MAX_MSG_SIZE, &len) == SARA_R5_SUCCESS) 252 | { 253 | if (len > 0) 254 | { 255 | Serial.println(); 256 | Serial.print(F("Subscribed MQTT data: ")); 257 | Serial.write((const char *)buf, len); 258 | Serial.println(); 259 | } 260 | } 261 | 262 | // Wait for ~10 seconds 263 | for (int i = 0; i < 1000; i++) 264 | { 265 | mySARA.bufferedPoll(); // Keep processing data from the SARA 266 | delay(10); 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example1_GNSS_GPRMC/SARA-R5_Example1_GNSS_GPRMC.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | GNSS GPRMC 7 | 8 | Written by: Paul Clark 9 | Date: November 18th 2020 10 | 11 | This example enables the SARA-R5nnM8S' built-in GNSS receiver and reads the GPRMC message to 12 | get position, speed and time data. 13 | 14 | Feel like supporting open source hardware? 15 | Buy a board from SparkFun! 16 | 17 | Licence: MIT 18 | Please see LICENSE.md for full details 19 | 20 | */ 21 | 22 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 23 | 24 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 25 | #define saraSerial Serial1 26 | 27 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 28 | //SoftwareSerial saraSerial(8, 9); 29 | 30 | // Create a SARA_R5 object to use throughout the sketch 31 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 32 | // but we can start the SARA without a power pin. It just means we need to manually 33 | // turn the power on if required! ;-D 34 | SARA_R5 mySARA; 35 | 36 | // Create a SARA_R5 object to use throughout the sketch 37 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 38 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 39 | // the pin name is G2 which is connected to pin AD34. 40 | // Change the pin number if required. 41 | //SARA_R5 mySARA(34); 42 | 43 | PositionData gps; 44 | SpeedData spd; 45 | ClockData clk; 46 | boolean valid; 47 | 48 | #define GPS_POLL_RATE 5000 // Read GPS every 5 seconds 49 | unsigned long lastGpsPoll = 0; 50 | 51 | void setup() 52 | { 53 | Serial.begin(115200); // Start the serial console 54 | 55 | // Wait for user to press key to begin 56 | Serial.println(F("SARA-R5 Example")); 57 | Serial.println(F("Press any key to begin GNSS'ing")); 58 | 59 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 60 | ; 61 | while (Serial.available()) // Empty the serial RX buffer 62 | Serial.read(); 63 | 64 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 65 | 66 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 67 | // Comment the next line if required 68 | mySARA.invertPowerPin(true); 69 | 70 | // Initialize the SARA 71 | if (mySARA.begin(saraSerial, 9600) ) { 72 | Serial.println(F("SARA-R5 connected!")); 73 | } 74 | 75 | // Enable power for the GNSS active antenna 76 | // On the MicroMod Asset Tracker, the SARA GPIO2 pin is used to control power for the antenna. 77 | // We need to pull GPIO2 (Pin 23) high to enable the power. 78 | mySARA.setGpioMode(mySARA.GPIO2, mySARA.GPIO_OUTPUT, 1); 79 | 80 | // From the u-blox SARA-R5 Positioning Implementation Application Note UBX-20012413 - R01 81 | // To enable the PPS output we need to: 82 | // Configure GPIO6 for TIME_PULSE_OUTPUT - .init does this 83 | // Enable the timing information request with +UTIMEIND=1 - setUtimeIndication() 84 | // Reset the time offset configuration with +UTIMECFG=0,0 - setUtimeConfiguration() 85 | // Request PPS output using GNSS+LTE (Best effort) with +UTIME=1,1 - setUtimeMode() 86 | // The bits that don't seem to be mentioned in the documentation are: 87 | // +UTIME=1,1 also enables the GNSS module and so we don't need to call gpsPower. 88 | // +UTIME=1,1 only works when the GNSS module if off. It returns an ERROR if the GNSS is already on. 89 | 90 | // Enable the timing information request (URC) 91 | //mySARA.setUtimeIndication(); // Use default (SARA_R5_UTIME_URC_CONFIGURATION_ENABLED) 92 | 93 | // Clear the time offset 94 | mySARA.setUtimeConfiguration(); // Use default offset (offsetNanoseconds = 0, offsetSeconds = 0) 95 | 96 | // Set the UTIME mode to pulse-per-second output using a best effort from GNSS and LTE 97 | mySARA.setUtimeMode(); // Use defaults (mode = SARA_R5_UTIME_MODE_PPS, sensor = SARA_R5_UTIME_SENSOR_GNSS_LTE) 98 | 99 | mySARA.gpsEnableRmc(); // Enable GPRMC messages 100 | } 101 | 102 | void loop() 103 | { 104 | if ((lastGpsPoll == 0) || (lastGpsPoll + GPS_POLL_RATE < millis())) 105 | { 106 | // Call (mySARA.gpsGetRmc to get coordinate, speed, and timing data 107 | // from the GPS module. Valid can be used to check if the GPS is 108 | // reporting valid data 109 | if (mySARA.gpsGetRmc(&gps, &spd, &clk, &valid) == SARA_R5_SUCCESS) 110 | { 111 | printGPS(); 112 | lastGpsPoll = millis(); 113 | } 114 | else 115 | { 116 | delay(1000); // If RMC read fails, wait a second and try again 117 | } 118 | } 119 | } 120 | 121 | void printGPS(void) 122 | { 123 | Serial.println(); 124 | Serial.println("UTC: " + String(gps.utc)); 125 | Serial.print("Time: "); 126 | if (clk.time.hour < 10) Serial.print('0'); // Print leading 0 127 | Serial.print(String(clk.time.hour) + ":"); 128 | if (clk.time.minute < 10) Serial.print('0'); // Print leading 0 129 | Serial.print(String(clk.time.minute) + ":"); 130 | if (clk.time.second < 10) Serial.print('0'); // Print leading 0 131 | Serial.print(String(clk.time.second) + "."); 132 | if (clk.time.ms < 10) Serial.print('0'); // Print leading 0 133 | Serial.println(String(clk.time.ms)); 134 | Serial.println("Latitude: " + String(gps.lat, 7)); 135 | Serial.println("Longitude: " + String(gps.lon, 7)); 136 | Serial.println("Speed: " + String(spd.speed, 4) + " @ " + String(spd.cog, 4)); 137 | Serial.println("Date (MM/DD/YY): " + String(clk.date.month) + "/" + 138 | String(clk.date.day) + "/" + String(clk.date.year)); 139 | Serial.println("Magnetic variation: " + String(spd.magVar)); 140 | Serial.println("Status: " + String(gps.status)); 141 | Serial.println("Mode: " + String(gps.mode)); 142 | Serial.println(); 143 | } 144 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example2_Identification/SARA-R5_Example2_Identification.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Identification 7 | 8 | Written by: Paul Clark 9 | Date: November 18th 2020 10 | 11 | This example demonstrates how to read the SARA's: 12 | Manufacturer identification 13 | Model identification 14 | Firmware version identification 15 | Product Serial No. 16 | IMEI identification 17 | IMSI identification 18 | SIM CCID 19 | Subscriber number 20 | Capabilities 21 | SIM state 22 | 23 | Feel like supporting open source hardware? 24 | Buy a board from SparkFun! 25 | 26 | Licence: MIT 27 | Please see LICENSE.md for full details 28 | 29 | */ 30 | 31 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 32 | 33 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 34 | #define saraSerial Serial1 35 | 36 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 37 | //SoftwareSerial saraSerial(8, 9); 38 | 39 | // Create a SARA_R5 object to use throughout the sketch 40 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 41 | // but we can start the SARA without a power pin. It just means we need to manually 42 | // turn the power on if required! ;-D 43 | SARA_R5 mySARA; 44 | 45 | // Create a SARA_R5 object to use throughout the sketch 46 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 47 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 48 | // the pin name is G2 which is connected to pin AD34. 49 | // Change the pin number if required. 50 | //SARA_R5 mySARA(34); 51 | 52 | // Map SIM states to more readable strings 53 | String simStateString[] = 54 | { 55 | "Not present", // 0 56 | "PIN needed", // 1 57 | "PIN blocked", // 2 58 | "PUK blocked", // 3 59 | "Not operational", // 4 60 | "Restricted", // 5 61 | "Operational" // 6 62 | }; 63 | 64 | // processSIMstate is provided to the SARA-R5 library via a 65 | // callback setter -- setSIMstateReadCallback. (See setup()) 66 | void processSIMstate(SARA_R5_sim_states_t state) 67 | { 68 | Serial.println(); 69 | Serial.print(F("SIM state: ")); 70 | Serial.print(String(state)); 71 | Serial.println(); 72 | } 73 | 74 | void setup() 75 | { 76 | Serial.begin(115200); // Start the serial console 77 | 78 | // Wait for user to press key to begin 79 | Serial.println(F("SARA-R5 Example")); 80 | Serial.println(F("Press any key to begin")); 81 | 82 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 83 | ; 84 | while (Serial.available()) // Empty the serial RX buffer 85 | Serial.read(); 86 | 87 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 88 | 89 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 90 | // Comment the next line if required 91 | mySARA.invertPowerPin(true); 92 | 93 | // Initialize the SARA 94 | if (mySARA.begin(saraSerial, 9600) ) 95 | { 96 | Serial.println(F("SARA-R5 connected!")); 97 | } 98 | else 99 | { 100 | Serial.println(F("Unable to communicate with the SARA.")); 101 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 102 | while (1) ; // Loop forever on fail 103 | } 104 | Serial.println(); 105 | 106 | Serial.println("Manufacturer ID: " + String(mySARA.getManufacturerID())); 107 | Serial.println("Model ID: " + String(mySARA.getModelID())); 108 | Serial.println("Firmware Version: " + String(mySARA.getFirmwareVersion())); 109 | Serial.println("Product Serial No.: " + String(mySARA.getSerialNo())); 110 | Serial.println("IMEI: " + String(mySARA.getIMEI())); 111 | Serial.println("IMSI: " + String(mySARA.getIMSI())); 112 | Serial.println("SIM CCID: " + String(mySARA.getCCID())); 113 | Serial.println("Subscriber No.: " + String(mySARA.getSubscriberNo())); 114 | Serial.println("Capabilities: " + String(mySARA.getCapabilities())); 115 | 116 | // Set a callback to return the SIM state once requested 117 | mySARA.setSIMstateReportCallback(&processSIMstate); 118 | // Now enable SIM state reporting for states 0 to 6 (by setting the reporting mode LSb) 119 | if (mySARA.setSIMstateReportingMode(1) == SARA_R5_SUCCESS) 120 | Serial.println("SIM state reports requested..."); 121 | // You can disable the SIM staus reports again by calling assetTracker.setSIMstateReportingMode(0) 122 | } 123 | 124 | void loop() 125 | { 126 | mySARA.poll(); // Keep processing data from the SARA so we can extract the SIM status 127 | } 128 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example2_Identification_ESPSoftwareSerial/SARA-R5_Example2_Identification_ESPSoftwareSerial.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Identification - using ESPSoftwareSerial 7 | 8 | Written by: Paul Clark 9 | Date: December 29th 2021 10 | 11 | This example demonstrates how to read the SARA's: 12 | Manufacturer identification 13 | Model identification 14 | Firmware version identification 15 | Product Serial No. 16 | IMEI identification 17 | IMSI identification 18 | SIM CCID 19 | Subscriber number 20 | Capabilities 21 | SIM state 22 | 23 | The ESP32 core doesn't include SoftwareSerial. Instead we use the library by Peter Lerup and Dirk O. Kaar: 24 | https://github.com/plerup/espsoftwareserial 25 | 26 | Feel like supporting open source hardware? 27 | Buy a board from SparkFun! 28 | 29 | Licence: MIT 30 | Please see LICENSE.md for full details 31 | 32 | */ 33 | 34 | // Include SoftwareSerial.h _before_ including SparkFun_u-blox_SARA-R5_Arduino_Library.h 35 | // to allow the SARA-R5 library to detect SoftwareSerial.h using an #if __has_include 36 | #include //Click here to get the library: http://librarymanager/All#ESPSoftwareSerial_ESP8266/ESP32 37 | 38 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 39 | 40 | // Create a SoftwareSerial object to pass to the SARA-R5 library 41 | // Note: we need to call saraSerial.begin and saraSerial.end in setup() - see below for details 42 | SoftwareSerial saraSerial; 43 | 44 | // Create a SARA_R5 object to use throughout the sketch 45 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 46 | // but we can start the SARA without a power pin. It just means we need to manually 47 | // turn the power on if required! ;-D 48 | SARA_R5 mySARA; 49 | 50 | // Create a SARA_R5 object to use throughout the sketch 51 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 52 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 53 | // the pin name is G2 which is connected to pin AD34. 54 | // Change the pin number if required. 55 | //SARA_R5 mySARA(34); 56 | 57 | // Map SIM states to more readable strings 58 | String simStateString[] = 59 | { 60 | "Not present", // 0 61 | "PIN needed", // 1 62 | "PIN blocked", // 2 63 | "PUK blocked", // 3 64 | "Not operational", // 4 65 | "Restricted", // 5 66 | "Operational" // 6 67 | }; 68 | 69 | // processSIMstate is provided to the SARA-R5 library via a 70 | // callback setter -- setSIMstateReadCallback. (See setup()) 71 | void processSIMstate(SARA_R5_sim_states_t state) 72 | { 73 | Serial.println(); 74 | Serial.print(F("SIM state: ")); 75 | Serial.print(String(state)); 76 | Serial.println(); 77 | } 78 | 79 | void setup() 80 | { 81 | Serial.begin(115200); // Start the serial console 82 | 83 | // Wait for user to press key to begin 84 | Serial.println(F("SARA-R5 Example")); 85 | Serial.println(F("Press any key to begin")); 86 | 87 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 88 | ; 89 | while (Serial.available()) // Empty the serial RX buffer 90 | Serial.read(); 91 | 92 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 93 | 94 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 95 | // Comment the next line if required 96 | mySARA.invertPowerPin(true); 97 | 98 | // ESPSoftwareSerial does not like repeated .begin's without a .end in between. 99 | // We need to .begin and .end the saraSerial port here, before the mySARA.begin, to set up the pin numbers etc. 100 | // E.g. to use: 57600 baud; 8 databits, no parity, 1 stop bit; RXD on pin 33; TXD on pin 32; no inversion. 101 | Serial.println(F("Configuring SoftwareSerial saraSerial")); 102 | saraSerial.begin(57600, SWSERIAL_8N1, 33, 32, false); 103 | saraSerial.end(); 104 | 105 | // Initialize the SARA 106 | if (mySARA.begin(saraSerial, 57600) ) 107 | { 108 | Serial.println(F("SARA-R5 connected!")); 109 | } 110 | else 111 | { 112 | Serial.println(F("Unable to communicate with the SARA.")); 113 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 114 | while (1) ; // Loop forever on fail 115 | } 116 | Serial.println(); 117 | 118 | Serial.println("Manufacturer ID: " + String(mySARA.getManufacturerID())); 119 | Serial.println("Model ID: " + String(mySARA.getModelID())); 120 | Serial.println("Firmware Version: " + String(mySARA.getFirmwareVersion())); 121 | Serial.println("Product Serial No.: " + String(mySARA.getSerialNo())); 122 | Serial.println("IMEI: " + String(mySARA.getIMEI())); 123 | Serial.println("IMSI: " + String(mySARA.getIMSI())); 124 | Serial.println("SIM CCID: " + String(mySARA.getCCID())); 125 | Serial.println("Subscriber No.: " + String(mySARA.getSubscriberNo())); 126 | Serial.println("Capabilities: " + String(mySARA.getCapabilities())); 127 | 128 | // Set a callback to return the SIM state once requested 129 | mySARA.setSIMstateReportCallback(&processSIMstate); 130 | // Now enable SIM state reporting for states 0 to 6 (by setting the reporting mode LSb) 131 | if (mySARA.setSIMstateReportingMode(1) == SARA_R5_SUCCESS) 132 | Serial.println("SIM state reports requested..."); 133 | // You can disable the SIM staus reports again by calling assetTracker.setSIMstateReportingMode(0) 134 | } 135 | 136 | void loop() 137 | { 138 | mySARA.poll(); // Keep processing data from the SARA so we can extract the SIM status 139 | } 140 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example3_NetworkInfo/SARA-R5_Example3_NetworkInfo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Network Info 7 | 8 | Written by: Paul Clark 9 | Date: November 18th 2020 10 | 11 | This example demonstrates how to register the SARA on the selected network. 12 | 13 | Feel like supporting open source hardware? 14 | Buy a board from SparkFun! 15 | 16 | Licence: MIT 17 | Please see LICENSE.md for full details 18 | 19 | */ 20 | 21 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 22 | 23 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 24 | #define saraSerial Serial1 25 | 26 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 27 | //SoftwareSerial saraSerial(8, 9); 28 | 29 | // Create a SARA_R5 object to use throughout the sketch 30 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 31 | // but we can start the SARA without a power pin. It just means we need to manually 32 | // turn the power on if required! ;-D 33 | SARA_R5 mySARA; 34 | 35 | // Create a SARA_R5 object to use throughout the sketch 36 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 37 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 38 | // the pin name is G2 which is connected to pin AD34. 39 | // Change the pin number if required. 40 | //SARA_R5 mySARA(34); 41 | 42 | // Map registration status messages to more readable strings 43 | String registrationString[] = 44 | { 45 | "Not registered", // 0 46 | "Registered, home", // 1 47 | "Searching for operator", // 2 48 | "Registration denied", // 3 49 | "Registration unknown", // 4 50 | "Registered, roaming", // 5 51 | "Registered, home (SMS only)", // 6 52 | "Registered, roaming (SMS only)", // 7 53 | "Registered, emergency service only", // 8 54 | "Registered, home, CSFB not preferred", // 9 55 | "Registered, roaming, CSFB not prefered" // 10 56 | }; 57 | 58 | // Network operator can be set to e.g.: 59 | // MNO_SW_DEFAULT -- DEFAULT (Undefined / regulatory) 60 | // MNO_SIM_ICCID -- SIM DEFAULT 61 | // MNO_ATT -- AT&T 62 | // MNO_VERIZON -- Verizon 63 | // MNO_TELSTRA -- Telstra 64 | // MNO_TMO -- T-Mobile US 65 | // MNO_CT -- China Telecom 66 | // MNO_SPRINT 67 | // MNO_VODAFONE 68 | // MNO_NTT_DOCOMO 69 | // MNO_TELUS 70 | // MNO_SOFTBANK 71 | // MNO_DT -- Deutsche Telekom 72 | // MNO_US_CELLULAR 73 | // MNO_SKT 74 | // MNO_GLOBAL -- SARA factory-programmed value 75 | // MNO_STD_EUROPE 76 | // MNO_STD_EU_NOEPCO 77 | 78 | // If you are based in Europe, you will (probably) need to select MNO_STD_EUROPE 79 | 80 | const mobile_network_operator_t MOBILE_NETWORK_OPERATOR = MNO_GLOBAL; 81 | 82 | void setup() 83 | { 84 | Serial.begin(115200); // Start the serial console 85 | 86 | // Wait for user to press key to begin 87 | Serial.println(F("SARA-R5 Example")); 88 | Serial.println(F("Press any key to begin")); 89 | 90 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 91 | ; 92 | while (Serial.available()) // Empty the serial RX buffer 93 | Serial.read(); 94 | 95 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 96 | 97 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 98 | // Comment the next line if required 99 | mySARA.invertPowerPin(true); 100 | 101 | // Initialize the SARA 102 | if (mySARA.begin(saraSerial, 9600) ) 103 | { 104 | Serial.println(F("SARA-R5 connected!")); 105 | } 106 | else 107 | { 108 | Serial.println(F("Unable to communicate with the SARA.")); 109 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 110 | while (1) ; // Loop forever on fail 111 | } 112 | Serial.println(); 113 | 114 | if (!mySARA.setNetworkProfile(MOBILE_NETWORK_OPERATOR)) 115 | { 116 | Serial.println(F("Error setting network. Try cycling the power.")); 117 | while (1) ; 118 | } 119 | 120 | Serial.println(F("Network profile set. Ready to go!")); 121 | 122 | // RSSI: Received signal strength: 123 | Serial.println("RSSI: " + String(mySARA.rssi())); 124 | // Registration Status 125 | int regStatus = mySARA.registration(); 126 | if ((regStatus >= 0) && (regStatus <= 10)) 127 | { 128 | Serial.println("Network registration: " + registrationString[regStatus]); 129 | } 130 | 131 | // Print the Context IDs, Access Point Names and IP Addresses 132 | Serial.println(F("Available PDP (Packet Data Protocol) APNs (Access Point Names) and IP Addresses:")); 133 | Serial.println(F("Context ID:\tAPN Name:\tIP Address:")); 134 | for (int cid = 0; cid < SARA_R5_NUM_PDP_CONTEXT_IDENTIFIERS; cid++) 135 | { 136 | String apn = ""; 137 | IPAddress ip(0, 0, 0, 0); 138 | mySARA.getAPN(cid, &apn, &ip); 139 | if (apn.length() > 0) 140 | { 141 | Serial.print(cid); 142 | Serial.print(F("\t")); 143 | Serial.print(apn); 144 | Serial.print(F("\t")); 145 | Serial.println(ip); 146 | } 147 | } 148 | 149 | Serial.println(); 150 | 151 | if (regStatus > 0) 152 | { 153 | Serial.println(F("All set. Go to the next example!")); 154 | } 155 | } 156 | 157 | void loop() 158 | { 159 | // Do nothing. Now that we're registered move on to the next example. 160 | } 161 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example4_RegisterOperator/SARA-R5_Example4_RegisterOperator.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Register Operator 7 | 8 | Written by: Paul Clark 9 | Date: November 18th 2020 10 | 11 | This example demonstrates how to register the SARA with a network operator. 12 | 13 | Feel like supporting open source hardware? 14 | Buy a board from SparkFun! 15 | 16 | Licence: MIT 17 | Please see LICENSE.md for full details 18 | 19 | */ 20 | 21 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 22 | 23 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 24 | #define saraSerial Serial1 25 | 26 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 27 | //SoftwareSerial saraSerial(8, 9); 28 | 29 | // Create a SARA_R5 object to use throughout the sketch 30 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 31 | // but we can start the SARA without a power pin. It just means we need to manually 32 | // turn the power on if required! ;-D 33 | SARA_R5 mySARA; 34 | 35 | // Create a SARA_R5 object to use throughout the sketch 36 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 37 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 38 | // the pin name is G2 which is connected to pin AD34. 39 | // Change the pin number if required. 40 | //SARA_R5 mySARA(34); 41 | 42 | // Map registration status messages to more readable strings 43 | String registrationString[] = 44 | { 45 | "Not registered", // 0 46 | "Registered, home", // 1 47 | "Searching for operator", // 2 48 | "Registration denied", // 3 49 | "Registration unknown", // 4 50 | "Registered, roaming", // 5 51 | "Registered, home (SMS only)", // 6 52 | "Registered, roaming (SMS only)", // 7 53 | "Registered, emergency service only", // 8 54 | "Registered, home, CSFB not preferred", // 9 55 | "Registered, roaming, CSFB not prefered" // 10 56 | }; 57 | 58 | // Network operator can be set to e.g.: 59 | // MNO_SW_DEFAULT -- DEFAULT (Undefined / regulatory) 60 | // MNO_SIM_ICCID -- SIM DEFAULT 61 | // MNO_ATT -- AT&T 62 | // MNO_VERIZON -- Verizon 63 | // MNO_TELSTRA -- Telstra 64 | // MNO_TMO -- T-Mobile US 65 | // MNO_CT -- China Telecom 66 | // MNO_SPRINT 67 | // MNO_VODAFONE 68 | // MNO_NTT_DOCOMO 69 | // MNO_TELUS 70 | // MNO_SOFTBANK 71 | // MNO_DT -- Deutsche Telekom 72 | // MNO_US_CELLULAR 73 | // MNO_SKT 74 | // MNO_GLOBAL -- SARA factory-programmed value 75 | // MNO_STD_EUROPE 76 | // MNO_STD_EU_NOEPCO 77 | 78 | // MNO_GLOBAL is the factory-programmed default 79 | // If you are in Europe, you may find no operators unless you choose MNO_STD_EUROPE 80 | const mobile_network_operator_t MOBILE_NETWORK_OPERATOR = MNO_GLOBAL; 81 | 82 | const String MOBILE_NETWORK_STRINGS[] = {"default (Undefined/Regulatory)", "SIM ICCID", "AT&T", "Verizon", 83 | "Telstra", "T-Mobile US", "China Telecom", "Sprint", "Vodafone", "NTT DoCoMo", "Telus", "SoftBank", 84 | "Deutsche Telekom", "US Cellular", "SKT", "global (factory default)", "standard Europe", 85 | "standard Europe No-ePCO", "NOT RECOGNIZED"}; 86 | 87 | // Convert the operator number into an index for MOBILE_NETWORK_STRINGS 88 | int convertOperatorNumber( mobile_network_operator_t mno) 89 | { 90 | switch (mno) 91 | { 92 | case 0: 93 | case 1: 94 | case 2: 95 | case 3: 96 | case 4: 97 | case 5: 98 | case 6: 99 | return ((int)mno); 100 | break; 101 | case 8: 102 | return 7; 103 | break; 104 | case 19: 105 | return 8; 106 | break; 107 | case 20: 108 | return 9; 109 | break; 110 | case 21: 111 | return 10; 112 | break; 113 | case 28: 114 | return 11; 115 | break; 116 | case 31: 117 | return 12; 118 | break; 119 | case 32: 120 | return 13; 121 | break; 122 | case 39: 123 | return 14; 124 | break; 125 | case 90: 126 | return 15; 127 | break; 128 | case 100: 129 | return 16; 130 | break; 131 | case 101: 132 | return 17; 133 | break; 134 | default: // NOT RECOGNIZED 135 | return 18; 136 | break; 137 | } 138 | } 139 | 140 | // This defines the size of the ops struct array. To narrow the operator 141 | // list, set MOBILE_NETWORK_OPERATOR to AT&T, Verizon etc. instead 142 | // of MNO_SW_DEFAULT. 143 | #define MAX_OPERATORS 10 144 | 145 | // Uncomment this line if you want to be able to communicate directly with the SARA in the main loop 146 | //#define DEBUG_PASSTHROUGH_ENABLED 147 | 148 | void setup() 149 | { 150 | int opsAvailable; 151 | struct operator_stats ops[MAX_OPERATORS]; 152 | String currentOperator = ""; 153 | bool newConnection = true; 154 | 155 | Serial.begin(115200); // Start the serial console 156 | 157 | // Wait for user to press key to begin 158 | Serial.println(F("SARA-R5 Example")); 159 | Serial.println(F("Press any key to begin")); 160 | 161 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 162 | ; 163 | while (Serial.available()) // Empty the serial RX buffer 164 | Serial.read(); 165 | 166 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 167 | 168 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 169 | // Comment the next line if required 170 | mySARA.invertPowerPin(true); 171 | 172 | // Initialize the SARA 173 | if (mySARA.begin(saraSerial, 9600) ) 174 | { 175 | Serial.println(F("SARA-R5 connected!")); 176 | } 177 | else 178 | { 179 | Serial.println(F("Unable to communicate with the SARA.")); 180 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 181 | while (1) ; // Loop forever on fail 182 | } 183 | Serial.println(); 184 | 185 | // First check to see if we're already connected to an operator: 186 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) { 187 | Serial.print(F("Already connected to: ")); 188 | Serial.println(currentOperator); 189 | // If already connected provide the option to type y to connect to new operator 190 | Serial.println(F("Press y to connect to a new operator, or any other key to continue.\r\n")); 191 | while (!Serial.available()) ; 192 | if (Serial.read() != 'y') 193 | { 194 | newConnection = false; 195 | } 196 | else 197 | { 198 | mySARA.deregisterOperator(); // Deregister from the current operator so we can connect to a new one 199 | } 200 | while (Serial.available()) Serial.read(); 201 | } 202 | 203 | if (newConnection) { 204 | // Set MNO to either Verizon, T-Mobile, AT&T, Telstra, etc. 205 | // This will narrow the operator options during our scan later 206 | Serial.println(F("Setting mobile-network operator")); 207 | if (mySARA.setNetworkProfile(MOBILE_NETWORK_OPERATOR)) 208 | { 209 | Serial.print(F("Set mobile network operator to ")); 210 | Serial.println(MOBILE_NETWORK_STRINGS[convertOperatorNumber(MOBILE_NETWORK_OPERATOR)] + "\r\n"); 211 | } 212 | else 213 | { 214 | Serial.println(F("Error setting MNO. Try cycling the power. Freezing...")); 215 | while (1) ; 216 | } 217 | 218 | // Wait for user to press button before initiating network scan. 219 | Serial.println(F("Press any key scan for networks..")); 220 | serialWait(); 221 | 222 | Serial.println(F("Scanning for networks...this may take up to 3 minutes\r\n")); 223 | // mySARA.getOperators takes in a operator_stats struct pointer and max number of 224 | // structs to scan for, then fills up those objects with operator names and numbers 225 | opsAvailable = mySARA.getOperators(ops, MAX_OPERATORS); // This will block for up to 3 minutes 226 | 227 | if (opsAvailable > 0) 228 | { 229 | // Pretty-print operators we found: 230 | Serial.println("Found " + String(opsAvailable) + " operators:"); 231 | printOperators(ops, opsAvailable); 232 | Serial.println(String(opsAvailable + 1) + ": use automatic selection"); 233 | Serial.println(); 234 | 235 | // Wait until the user presses a key to initiate an operator connection 236 | Serial.println("Press 1-" + String(opsAvailable + 1) + " to select an operator."); 237 | char c = 0; 238 | bool selected = false; 239 | while (!selected) { 240 | while (!Serial.available()) ; 241 | c = Serial.read(); 242 | int selection = c - '0'; 243 | if ((selection >= 1) && (selection <= (opsAvailable + 1))) { 244 | selected = true; 245 | Serial.println("Connecting to option " + String(selection)); 246 | if (selection == (opsAvailable + 1)) 247 | { 248 | if (mySARA.automaticOperatorSelection() == SARA_R5_SUCCESS) 249 | { 250 | Serial.println("Automatic operator selection: successful\r\n"); 251 | } 252 | else 253 | { 254 | Serial.println(F("Automatic operator selection: error. Reset and try again, or try another network.")); 255 | } 256 | } 257 | else 258 | { 259 | if (mySARA.registerOperator(ops[selection - 1]) == SARA_R5_SUCCESS) 260 | { 261 | Serial.println("Network " + ops[selection - 1].longOp + " registered\r\n"); 262 | } 263 | else 264 | { 265 | Serial.println(F("Error connecting to operator. Reset and try again, or try another network.")); 266 | } 267 | } 268 | } 269 | } 270 | } 271 | else 272 | { 273 | Serial.println(F("Did not find an operator. Double-check SIM and antenna, reset and try again, or try another network.")); 274 | while (1) ; 275 | } 276 | } 277 | 278 | // At the very end print connection information 279 | printInfo(); 280 | } 281 | 282 | void loop() 283 | { 284 | // Loop provides a debugging interface. 285 | if (saraSerial.available()) { 286 | Serial.write((char) saraSerial.read()); 287 | } 288 | #ifdef DEBUG_PASSTHROUGH_ENABLED 289 | if (Serial.available()) { 290 | saraSerial.write((char) Serial.read()); 291 | } 292 | #endif 293 | } 294 | 295 | void printInfo(void) { 296 | String currentApn = ""; 297 | IPAddress ip(0, 0, 0, 0); 298 | String currentOperator = ""; 299 | 300 | Serial.println(F("Connection info:")); 301 | Serial.println(F("Context ID:\tAPN Name:\tIP Address:")); 302 | for (int cid = 0; cid < SARA_R5_NUM_PDP_CONTEXT_IDENTIFIERS; cid++) 303 | { 304 | String apn = ""; 305 | IPAddress ip(0, 0, 0, 0); 306 | mySARA.getAPN(cid, &apn, &ip); 307 | if (apn.length() > 0) 308 | { 309 | Serial.print(cid); 310 | Serial.print(F("\t")); 311 | Serial.print(apn); 312 | Serial.print(F("\t")); 313 | Serial.println(ip); 314 | } 315 | } 316 | 317 | // Operator name or number 318 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 319 | { 320 | Serial.print(F("Operator: ")); 321 | Serial.println(currentOperator); 322 | } 323 | 324 | // Received signal strength 325 | Serial.println("RSSI: " + String(mySARA.rssi())); 326 | Serial.println(); 327 | } 328 | 329 | void printOperators(struct operator_stats * ops, int operatorsAvailable) 330 | { 331 | for (int i = 0; i < operatorsAvailable; i++) 332 | { 333 | Serial.print(String(i + 1) + ": "); 334 | Serial.print(ops[i].longOp + " (" + String(ops[i].numOp) + ") - "); 335 | switch (ops[i].stat) 336 | { 337 | case 0: 338 | Serial.print(F("UNKNOWN")); 339 | break; 340 | case 1: 341 | Serial.print(F("AVAILABLE")); 342 | break; 343 | case 2: 344 | Serial.print(F("CURRENT")); 345 | break; 346 | case 3: 347 | Serial.print(F("FORBIDDEN")); 348 | break; 349 | } 350 | switch (ops[i].act) 351 | { 352 | case 0: 353 | Serial.print(F(" - GSM")); 354 | break; 355 | case 2: 356 | Serial.print(F(" - UTRAN")); 357 | break; 358 | case 3: 359 | Serial.print(F(" - GSM/GPRS with EDGE")); 360 | break; 361 | case 7: 362 | Serial.print(F(" - LTE")); // SARA-R5 only supports LTE 363 | break; 364 | } 365 | Serial.println(); 366 | } 367 | Serial.println(); 368 | } 369 | 370 | void serialWait() 371 | { 372 | while (Serial.available()) Serial.read(); 373 | while (!Serial.available()) ; 374 | delay(100); 375 | while (Serial.available()) Serial.read(); 376 | } 377 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example5_ReceiveSMS/SARA-R5_Example5_ReceiveSMS.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Receive SMS 7 | 8 | Written by: Paul Clark 9 | Date: November 18th 2020 10 | 11 | This example demonstrates how to receive SMS messages using the SARA. 12 | 13 | Feel like supporting open source hardware? 14 | Buy a board from SparkFun! 15 | 16 | Licence: MIT 17 | Please see LICENSE.md for full details 18 | 19 | */ 20 | 21 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 22 | 23 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 24 | #define saraSerial Serial1 25 | 26 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 27 | //SoftwareSerial saraSerial(8, 9); 28 | 29 | // Create a SARA_R5 object to use throughout the sketch 30 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 31 | // but we can start the SARA without a power pin. It just means we need to manually 32 | // turn the power on if required! ;-D 33 | SARA_R5 mySARA; 34 | 35 | // Create a SARA_R5 object to use throughout the sketch 36 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 37 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 38 | // the pin name is G2 which is connected to pin AD34. 39 | // Change the pin number if required. 40 | //SARA_R5 mySARA(34); 41 | 42 | void setup() 43 | { 44 | String currentOperator = ""; 45 | 46 | Serial.begin(115200); // Start the serial console 47 | 48 | // Wait for user to press key to begin 49 | Serial.println(F("SARA-R5 Example")); 50 | Serial.println(F("Press any key to begin")); 51 | 52 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 53 | ; 54 | while (Serial.available()) // Empty the serial RX buffer 55 | Serial.read(); 56 | 57 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 58 | 59 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 60 | // Comment the next line if required 61 | mySARA.invertPowerPin(true); 62 | 63 | // Initialize the SARA 64 | if (mySARA.begin(saraSerial, 9600) ) 65 | { 66 | Serial.println(F("SARA-R5 connected!")); 67 | } 68 | else 69 | { 70 | Serial.println(F("Unable to communicate with the SARA.")); 71 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 72 | while (1) ; // Loop forever on fail 73 | } 74 | Serial.println(); 75 | 76 | // First check to see if we're connected to an operator: 77 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 78 | { 79 | Serial.print(F("Connected to: ")); 80 | Serial.println(currentOperator); 81 | } 82 | else 83 | { 84 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 85 | while (1) 86 | ; // Do nothing more 87 | } 88 | 89 | while (Serial.available()) // Empty the serial RX buffer 90 | Serial.read(); 91 | } 92 | 93 | void loop() 94 | { 95 | static bool printReadMessages = true; // Print all messages once. Then only print new messages. Unless a message is deleted. 96 | static int previousUsed = -1; // Store the previous number of used memory locations 97 | 98 | // Read the number of used and total messages 99 | int used; 100 | int total; 101 | if (mySARA.getPreferredMessageStorage(&used, &total) != SARA_R5_SUCCESS) 102 | { 103 | Serial.println(F("An error occurred when trying to read ME memory!")); 104 | } 105 | else 106 | { 107 | if ((used != previousUsed) || printReadMessages) // Has a new message arrived? Or was the delete menu opened? 108 | { 109 | Serial.print(F("\r\nNumber of used memory locations: ")); 110 | Serial.println(used); 111 | Serial.print(F("Total number of memory locations: ")); 112 | Serial.println(total); 113 | Serial.println(); 114 | 115 | int memoryLocation = 1; 116 | int foundMessages = 0; 117 | // Keep reading until we find all the messages or we reach the end of the memory 118 | while ((foundMessages < used) && (memoryLocation <= total)) 119 | { 120 | String unread = ""; 121 | String from = ""; 122 | String dateTime = ""; 123 | String message = ""; 124 | // Read the message from this location. Reading from empty message locations returns an ERROR 125 | // unread can be: "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT" 126 | // If the location is empty, readSMSmessage will return a SARA_R5_ERROR_UNEXPECTED_RESPONSE 127 | if (mySARA.readSMSmessage(memoryLocation, &unread, &from, &dateTime, &message) == SARA_R5_SUCCESS) 128 | { 129 | if (printReadMessages || (unread == "REC UNREAD")) 130 | { 131 | Serial.print(F("Message location: ")); 132 | Serial.println(memoryLocation); 133 | Serial.print(F("Status: ")); 134 | Serial.println(unread); 135 | Serial.print(F("Originator: ")); 136 | Serial.println(from); 137 | Serial.print(F("Date and time: ")); 138 | Serial.println(dateTime); 139 | Serial.println(message); 140 | Serial.println(); 141 | } 142 | foundMessages++; // We found a message 143 | } 144 | memoryLocation++; // Move on to the next memory location 145 | } 146 | 147 | printReadMessages = false; 148 | previousUsed = used; // Update previousUsed 149 | 150 | Serial.println(F("Waiting for a new message...")); 151 | Serial.println(); 152 | Serial.println(F("Hit any key to delete a message...")); 153 | Serial.println(); 154 | } 155 | } 156 | 157 | int delayCount = 0; 158 | while (delayCount < 5000) 159 | { 160 | delay(1); // Delay for five seconds, unless the user presses a key 161 | delayCount++; 162 | 163 | if (Serial.available()) 164 | { 165 | Serial.println(F("To delete a single message: enter its location followed by LF / Newline")); 166 | Serial.println(F("To delete all read messages: enter r followed by LF / Newline")); 167 | Serial.println(F("To delete all read and sent messages: enter s followed by LF / Newline")); 168 | Serial.println(F("To delete all read, sent and unsent messages: enter u followed by LF / Newline")); 169 | Serial.println(F("To delete all messages, including unread messages: enter a followed by LF / Newline")); 170 | Serial.println(F("To exit: enter LF / Newline")); 171 | 172 | Serial.read(); // Read and discard the char that opened the menu 173 | 174 | int location = 0; 175 | bool selected = false; 176 | while (!selected) 177 | { 178 | while (!Serial.available()) ; // Wait for a character to arrive 179 | char c = Serial.read(); // Read it 180 | if (c == '\n') // Is it a LF? 181 | { 182 | if ((location >= 1) && (location <= total)) // Delete a single message at location 183 | { 184 | if (mySARA.deleteSMSmessage(location) == SARA_R5_SUCCESS) 185 | { 186 | Serial.println(F("\r\nMessage deleted!\r\n")); 187 | printReadMessages = true; 188 | } 189 | else 190 | { 191 | Serial.println(F("\r\nMessage not deleted!\r\n")); 192 | } 193 | } 194 | else if (location == 1001) // r 195 | { 196 | if (mySARA.deleteReadSMSmessages() == SARA_R5_SUCCESS) 197 | { 198 | Serial.println(F("\r\nRead messages deleted!\r\n")); 199 | printReadMessages = true; 200 | } 201 | else 202 | { 203 | Serial.println(F("\r\nMessages not deleted!\r\n")); 204 | } 205 | } 206 | else if (location == 1002) // s 207 | { 208 | if (mySARA.deleteReadSentSMSmessages() == SARA_R5_SUCCESS) 209 | { 210 | Serial.println(F("\r\nRead and sent messages deleted!\r\n")); 211 | printReadMessages = true; 212 | } 213 | else 214 | { 215 | Serial.println(F("\r\nMessages not deleted!\r\n")); 216 | } 217 | } 218 | else if (location == 1003) // u 219 | { 220 | if (mySARA.deleteReadSentUnsentSMSmessages() == SARA_R5_SUCCESS) 221 | { 222 | Serial.println(F("\r\nRead, sent and unsent messages deleted!\r\n")); 223 | printReadMessages = true; 224 | } 225 | else 226 | { 227 | Serial.println(F("\r\nMessages not deleted!\r\n")); 228 | } 229 | } 230 | else if (location == 1004) // a 231 | { 232 | if (mySARA.deleteAllSMSmessages() == SARA_R5_SUCCESS) 233 | { 234 | Serial.println(F("\r\nAll messages deleted!\r\n")); 235 | printReadMessages = true; 236 | } 237 | else 238 | { 239 | Serial.println(F("\r\nMessages not deleted!\r\n")); 240 | } 241 | } 242 | else 243 | Serial.println(F("\r\nExit...\r\n")); 244 | selected = true; 245 | } 246 | else if ((c >= '0') && (c <= '9')) 247 | { 248 | location *= 10; // Multiply by 10 249 | location += c - '0'; // Add the digit 250 | } 251 | else if (c == 'r') 252 | { 253 | location = 1001; 254 | } 255 | else if (c == 's') 256 | { 257 | location = 1002; 258 | } 259 | else if (c == 'u') 260 | { 261 | location = 1003; 262 | } 263 | else if (c == 'a') 264 | { 265 | location = 1004; 266 | } 267 | } 268 | 269 | delayCount = 5000; 270 | } 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example6_SendSMS/SARA-R5_Example6_SendSMS.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Send SMS 7 | 8 | Written by: Paul Clark 9 | Date: November 18th 2020 10 | 11 | This example demonstrates how to send SMS messages using the SARA. 12 | 13 | Feel like supporting open source hardware? 14 | Buy a board from SparkFun! 15 | 16 | Licence: MIT 17 | Please see LICENSE.md for full details 18 | 19 | */ 20 | 21 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 22 | 23 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 24 | #define saraSerial Serial1 25 | 26 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 27 | //SoftwareSerial saraSerial(8, 9); 28 | 29 | // Create a SARA_R5 object to use throughout the sketch 30 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 31 | // but we can start the SARA without a power pin. It just means we need to manually 32 | // turn the power on if required! ;-D 33 | SARA_R5 mySARA; 34 | 35 | // Create a SARA_R5 object to use throughout the sketch 36 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 37 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 38 | // the pin name is G2 which is connected to pin AD34. 39 | // Change the pin number if required. 40 | //SARA_R5 mySARA(34); 41 | 42 | void setup() 43 | { 44 | String currentOperator = ""; 45 | 46 | Serial.begin(115200); // Start the serial console 47 | 48 | // Wait for user to press key to begin 49 | Serial.println(F("SARA-R5 Example")); 50 | Serial.println(F("Press any key to begin")); 51 | 52 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 53 | ; 54 | while (Serial.available()) // Empty the serial RX buffer 55 | Serial.read(); 56 | 57 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 58 | 59 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 60 | // Comment the next line if required 61 | mySARA.invertPowerPin(true); 62 | 63 | // Initialize the SARA 64 | if (mySARA.begin(saraSerial, 9600) ) 65 | { 66 | Serial.println(F("SARA-R5 connected!")); 67 | } 68 | else 69 | { 70 | Serial.println(F("Unable to communicate with the SARA.")); 71 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 72 | while (1) ; // Loop forever on fail 73 | } 74 | Serial.println(); 75 | 76 | // First check to see if we're connected to an operator: 77 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 78 | { 79 | Serial.print(F("Connected to: ")); 80 | Serial.println(currentOperator); 81 | } 82 | else 83 | { 84 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 85 | while (1) 86 | ; // Do nothing more 87 | } 88 | 89 | Serial.println(); 90 | Serial.println(F("*** Set the Serial Monitor line ending to Newline ***")); 91 | } 92 | 93 | void loop() 94 | { 95 | String destinationNumber = ""; 96 | String message = ""; 97 | boolean keepGoing = true; 98 | 99 | Serial.println(); 100 | Serial.println(F("Enter the destination number (followed by LF / Newline): ")); 101 | 102 | while (keepGoing) 103 | { 104 | if (Serial.available()) 105 | { 106 | char c = Serial.read(); 107 | if (c == '\n') 108 | { 109 | keepGoing = false; // Stop if we receive a newline 110 | } 111 | else 112 | { 113 | destinationNumber += c; // Add serial characters to the destination number 114 | } 115 | } 116 | } 117 | 118 | keepGoing = true; 119 | Serial.println(); 120 | Serial.println(F("Enter the message (followed by LF): ")); 121 | 122 | while (keepGoing) 123 | { 124 | if (Serial.available()) 125 | { 126 | char c = Serial.read(); 127 | if (c == '\n') 128 | { 129 | keepGoing = false; // Stop if we receive a newline 130 | } 131 | else 132 | { 133 | message += c; // Add serial characters to the destination number 134 | } 135 | } 136 | } 137 | 138 | // Once we receive a newline, send the text. 139 | Serial.println("Sending: \"" + message + "\" to " + destinationNumber); 140 | // Call mySARA.sendSMS(String number, String message) to send an SMS message. 141 | if (mySARA.sendSMS(destinationNumber, message) == SARA_R5_SUCCESS) 142 | { 143 | Serial.println(F("sendSMS was successful")); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example7_ConfigurePacketSwitchedData/SARA-R5_Example7_ConfigurePacketSwitchedData.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Configure Packet Switched Data 7 | 8 | Written by: Paul Clark 9 | Date: November 18th 2020 10 | 11 | This example demonstrates how to configure Packet Switched Data on the SARA-R5. 12 | 13 | The earlier examples let you configure the network profile and select an operator. 14 | The default operator - defined in your SIM - will be allocated to "Context ID 1". 15 | This example defines a Packet Switched Data Profile ID, based on the selected Context ID, and then activates it. 16 | The profile parameters are also saved to NVM so they can be used by the next examples. 17 | The only complicated bit is that - strictly - we need to disconnect from the network first in order to find out what 18 | the defined IP type is for the chosen Context ID - as opposed to what is granted by the network. However, we'll 19 | take a guess that it is the default (IPv4v6). You can change this if required by editing the call to setPDPconfiguration. 20 | 21 | Feel like supporting open source hardware? 22 | Buy a board from SparkFun! 23 | 24 | Licence: MIT 25 | Please see LICENSE.md for full details 26 | 27 | */ 28 | 29 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 30 | 31 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 32 | #define saraSerial Serial1 33 | 34 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 35 | //SoftwareSerial saraSerial(8, 9); 36 | 37 | // Create a SARA_R5 object to use throughout the sketch 38 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 39 | // but we can start the SARA without a power pin. It just means we need to manually 40 | // turn the power on if required! ;-D 41 | SARA_R5 mySARA; 42 | 43 | // Create a SARA_R5 object to use throughout the sketch 44 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 45 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 46 | // the pin name is G2 which is connected to pin AD34. 47 | // Change the pin number if required. 48 | //SARA_R5 mySARA(34); 49 | 50 | // processPSDAction is provided to the SARA-R5 library via a 51 | // callback setter -- setPSDActionCallback. (See setup()) 52 | void processPSDAction(int result, IPAddress ip) 53 | { 54 | Serial.println(); 55 | Serial.print(F("PSD Action: result: ")); 56 | Serial.print(String(result)); 57 | if (result == 0) 58 | Serial.print(F(" (success)")); 59 | Serial.print(F(" IP Address: \"")); 60 | Serial.print(String(ip[0])); 61 | Serial.print(F(".")); 62 | Serial.print(String(ip[1])); 63 | Serial.print(F(".")); 64 | Serial.print(String(ip[2])); 65 | Serial.print(F(".")); 66 | Serial.print(String(ip[3])); 67 | Serial.println(F("\"")); 68 | } 69 | 70 | void setup() 71 | { 72 | String currentOperator = ""; 73 | 74 | Serial.begin(115200); // Start the serial console 75 | 76 | // Wait for user to press key to begin 77 | Serial.println(F("SARA-R5 Example")); 78 | Serial.println(F("Press any key to begin")); 79 | 80 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 81 | ; 82 | while (Serial.available()) // Empty the serial RX buffer 83 | Serial.read(); 84 | 85 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 86 | 87 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 88 | // Comment the next line if required 89 | mySARA.invertPowerPin(true); 90 | 91 | // Initialize the SARA 92 | if (mySARA.begin(saraSerial, 9600) ) 93 | { 94 | Serial.println(F("SARA-R5 connected!")); 95 | } 96 | else 97 | { 98 | Serial.println(F("Unable to communicate with the SARA.")); 99 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 100 | while (1) ; // Loop forever on fail 101 | } 102 | Serial.println(); 103 | 104 | // First check to see if we're connected to an operator: 105 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 106 | { 107 | Serial.print(F("Connected to: ")); 108 | Serial.println(currentOperator); 109 | } 110 | else 111 | { 112 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 113 | while (1) 114 | ; // Do nothing more 115 | } 116 | 117 | int minCID = SARA_R5_NUM_PDP_CONTEXT_IDENTIFIERS; // Keep a record of the highest and lowest CIDs 118 | int maxCID = 0; 119 | 120 | Serial.println(F("The available Context IDs are:")); 121 | Serial.println(F("Context ID:\tAPN Name:\tIP Address:")); 122 | for (int cid = 0; cid < SARA_R5_NUM_PDP_CONTEXT_IDENTIFIERS; cid++) 123 | { 124 | String apn = ""; 125 | IPAddress ip(0, 0, 0, 0); 126 | mySARA.getAPN(cid, &apn, &ip); 127 | if (apn.length() > 0) 128 | { 129 | Serial.print(cid); 130 | Serial.print(F("\t")); 131 | Serial.print(apn); 132 | Serial.print(F("\t")); 133 | Serial.println(ip); 134 | } 135 | if (cid < minCID) 136 | minCID = cid; // Record the lowest CID 137 | if (cid > maxCID) 138 | maxCID = cid; // Record the highest CID 139 | } 140 | Serial.println(); 141 | 142 | Serial.println(F("Which Context ID do you want to use for your Packet Switched Data connection?")); 143 | Serial.println(F("Please enter the number (followed by LF / Newline): ")); 144 | 145 | char c = 0; 146 | bool selected = false; 147 | int selection = 0; 148 | while (!selected) 149 | { 150 | while (!Serial.available()) ; // Wait for a character to arrive 151 | c = Serial.read(); // Read it 152 | if (c == '\n') // Is it a LF? 153 | { 154 | if ((selection >= minCID) && (selection <= maxCID)) 155 | { 156 | selected = true; 157 | Serial.println("Using CID: " + String(selection)); 158 | } 159 | else 160 | { 161 | Serial.println(F("Invalid CID. Please try again:")); 162 | selection = 0; 163 | } 164 | } 165 | else 166 | { 167 | selection *= 10; // Multiply selection by 10 168 | selection += c - '0'; // Add the new digit to selection 169 | } 170 | } 171 | 172 | // Deactivate the profile 173 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_DEACTIVATE) != SARA_R5_SUCCESS) 174 | { 175 | Serial.println(F("Warning: performPDPaction (deactivate profile) failed. Probably because no profile was active.")); 176 | } 177 | 178 | // Map PSD profile 0 to the selected CID 179 | if (mySARA.setPDPconfiguration(0, SARA_R5_PSD_CONFIG_PARAM_MAP_TO_CID, selection) != SARA_R5_SUCCESS) 180 | { 181 | Serial.println(F("setPDPconfiguration (map to CID) failed! Freezing...")); 182 | while (1) 183 | ; // Do nothing more 184 | } 185 | 186 | // Set the protocol type - this needs to match the defined IP type for the CID (as opposed to what was granted by the network) 187 | if (mySARA.setPDPconfiguration(0, SARA_R5_PSD_CONFIG_PARAM_PROTOCOL, SARA_R5_PSD_PROTOCOL_IPV4V6_V4_PREF) != SARA_R5_SUCCESS) 188 | // You _may_ need to change the protocol type: ----------------------------------------^ 189 | { 190 | Serial.println(F("setPDPconfiguration (set protocol type) failed! Freezing...")); 191 | while (1) 192 | ; // Do nothing more 193 | } 194 | 195 | // Set a callback to process the results of the PSD Action 196 | mySARA.setPSDActionCallback(&processPSDAction); 197 | 198 | // Activate the profile 199 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_ACTIVATE) != SARA_R5_SUCCESS) 200 | { 201 | Serial.println(F("performPDPaction (activate profile) failed! Freezing...")); 202 | while (1) 203 | ; // Do nothing more 204 | } 205 | 206 | for (int i = 0; i < 100; i++) // Wait for up to a second for the PSD Action URC to arrive 207 | { 208 | mySARA.poll(); // Keep processing data from the SARA so we can process the PSD Action 209 | delay(10); 210 | } 211 | 212 | // Save the profile to NVM - so we can load it again in the later examples 213 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_STORE) != SARA_R5_SUCCESS) 214 | { 215 | Serial.println(F("performPDPaction (save to NVM) failed! Freezing...")); 216 | while (1) 217 | ; // Do nothing more 218 | } 219 | 220 | } 221 | 222 | void loop() 223 | { 224 | mySARA.poll(); // Keep processing data from the SARA so we can process URCs from the PSD Action 225 | } 226 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example8_Ping/SARA-R5_Example8_Ping.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | Ping 7 | 8 | Written by: Paul Clark 9 | Date: November 18th 2020 10 | 11 | This example uses the SARA's mobile data connection to ping a server. 12 | 13 | Feel like supporting open source hardware? 14 | Buy a board from SparkFun! 15 | 16 | Licence: MIT 17 | Please see LICENSE.md for full details 18 | 19 | */ 20 | 21 | #include 22 | 23 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 24 | 25 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 26 | #define saraSerial Serial1 27 | 28 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 29 | //SoftwareSerial saraSerial(8, 9); 30 | 31 | // Create a SARA_R5 object to use throughout the sketch 32 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 33 | // but we can start the SARA without a power pin. It just means we need to manually 34 | // turn the power on if required! ;-D 35 | SARA_R5 mySARA; 36 | 37 | // Create a SARA_R5 object to use throughout the sketch 38 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 39 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 40 | // the pin name is G2 which is connected to pin AD34. 41 | // Change the pin number if required. 42 | //SARA_R5 mySARA(34); 43 | 44 | String pingMe = ""; // The name of the server we are going to ping 45 | 46 | // processPingResult is provided to the SARA-R5 library via a 47 | // callback setter -- setPingCallback. (See the end of setup()) 48 | void processPingResult(int retry, int p_size, String remote_hostname, IPAddress ip, int ttl, long rtt) 49 | { 50 | Serial.println(); 51 | Serial.print(F("Ping Result: Retry #:")); 52 | Serial.print(retry); 53 | Serial.print(F(" Ping Size (Bytes):")); 54 | Serial.print(p_size); 55 | Serial.print(F(" Remote Host:\"")); 56 | Serial.print(remote_hostname); 57 | Serial.print(F("\" IP Address:\"")); 58 | Serial.print(String(ip[0])); 59 | Serial.print(F(".")); 60 | Serial.print(String(ip[1])); 61 | Serial.print(F(".")); 62 | Serial.print(String(ip[2])); 63 | Serial.print(F(".")); 64 | Serial.print(String(ip[3])); 65 | Serial.print(F("\" Time To Live (hops):")); 66 | Serial.print(ttl); 67 | Serial.print(F(" Round Trip (ms):")); 68 | Serial.print(rtt); 69 | Serial.println(); 70 | } 71 | 72 | void setup() 73 | { 74 | String currentOperator = ""; 75 | 76 | Serial.begin(115200); // Start the serial console 77 | 78 | // Wait for user to press key to begin 79 | Serial.println(F("SARA-R5 Example")); 80 | Serial.println(F("Press any key to begin")); 81 | 82 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 83 | ; 84 | while (Serial.available()) // Empty the serial RX buffer 85 | Serial.read(); 86 | 87 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 88 | 89 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 90 | // Comment the next line if required 91 | mySARA.invertPowerPin(true); 92 | 93 | // Initialize the SARA 94 | if (mySARA.begin(saraSerial, 9600) ) 95 | { 96 | Serial.println(F("SARA-R5 connected!")); 97 | } 98 | else 99 | { 100 | Serial.println(F("Unable to communicate with the SARA.")); 101 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 102 | while (1) ; // Loop forever on fail 103 | } 104 | Serial.println(); 105 | 106 | // First check to see if we're connected to an operator: 107 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 108 | { 109 | Serial.print(F("Connected to: ")); 110 | Serial.println(currentOperator); 111 | } 112 | else 113 | { 114 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 115 | while (1) 116 | ; // Do nothing more 117 | } 118 | 119 | // Deactivate the profile - in case one is already active 120 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_DEACTIVATE) != SARA_R5_SUCCESS) 121 | { 122 | Serial.println(F("Warning: performPDPaction (deactivate profile) failed. Probably because no profile was active.")); 123 | } 124 | 125 | // Load the profile from NVM - these were saved by a previous example 126 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_LOAD) != SARA_R5_SUCCESS) 127 | { 128 | Serial.println(F("performPDPaction (load from NVM) failed! Freezing...")); 129 | while (1) 130 | ; // Do nothing more 131 | } 132 | 133 | // Activate the profile 134 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_ACTIVATE) != SARA_R5_SUCCESS) 135 | { 136 | Serial.println(F("performPDPaction (activate profile) failed! Freezing...")); 137 | while (1) 138 | ; // Do nothing more 139 | } 140 | 141 | Serial.println(); 142 | Serial.println(F("*** Set the Serial Monitor line ending to Newline ***")); 143 | 144 | Serial.println(); 145 | Serial.println(F("Enter the name of the server you want to ping (followed by LF / Newline): ")); 146 | 147 | // Set a callback to process the Ping result 148 | mySARA.setPingCallback(&processPingResult); 149 | } 150 | 151 | void loop() 152 | { 153 | if (Serial.available()) 154 | { 155 | char c = Serial.read(); 156 | if (c == '\n') 157 | { 158 | // Newline received so let's do that ping! 159 | mySARA.ping(pingMe); // Use the default parameters 160 | 161 | // Use custom parameters 162 | //int retries = 4; // number of retries 163 | //int p_size = 32; // packet size (bytes) 164 | //unsigned long timeout = 5000; // timeout (ms) 165 | //int ttl = 32; // Time To Live 166 | //mySARA.ping(pingMe, retries, p_size, timeout, ttl); 167 | 168 | pingMe = ""; // Clear the server name for the next try 169 | } 170 | else 171 | { 172 | // Add serial characters to the server address 173 | pingMe += c; 174 | } 175 | } 176 | 177 | mySARA.poll(); // Keep processing data from the SARA so we can catch the Ping result 178 | } 179 | -------------------------------------------------------------------------------- /examples/SARA-R5_Example9_ThingSpeak/SARA-R5_Example9_ThingSpeak.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | SARA-R5 Example 4 | =============== 5 | 6 | ThingSpeak (HTTP POST / GET) 7 | 8 | Written by: Paul Clark 9 | Date: November 18th 2020 10 | 11 | This example uses the SARA's mobile data connection to send random temperatures to ThingSpeak using HTTP POST or GET. 12 | https://thingspeak.com/ 13 | 14 | You will need to: 15 | Create a ThingSpeak User Account – https://thingspeak.com/login 16 | Create a new Channel by selecting Channels, My Channels, and then New Channel 17 | Note the Write API Key and copy&paste it into myWriteAPIKey below 18 | The random temperature reading will be added to the channel as "Field 1" 19 | 20 | Feel like supporting open source hardware? 21 | Buy a board from SparkFun! 22 | 23 | Licence: MIT 24 | Please see LICENSE.md for full details 25 | 26 | */ 27 | 28 | #include 29 | 30 | // ThingSpeak via HTTP POST / GET 31 | 32 | String myWriteAPIKey = "PFIOEXW1VF21T7O6"; // Change this to your API key 33 | 34 | String serverName = "api.thingspeak.com"; // Domain Name for HTTP POST / GET 35 | 36 | // SARA-R5 37 | 38 | #include //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_SARA-R5_Arduino_Library 39 | 40 | // Uncomment the next line to connect to the SARA-R5 using hardware Serial1 41 | #define saraSerial Serial1 42 | 43 | // Uncomment the next line to create a SoftwareSerial object to pass to the SARA-R5 library instead 44 | //SoftwareSerial saraSerial(8, 9); 45 | 46 | // Create a SARA_R5 object to use throughout the sketch 47 | // Usually we would tell the library which GPIO pin to use to control the SARA power (see below), 48 | // but we can start the SARA without a power pin. It just means we need to manually 49 | // turn the power on if required! ;-D 50 | SARA_R5 mySARA; 51 | 52 | // Create a SARA_R5 object to use throughout the sketch 53 | // We need to tell the library what GPIO pin is connected to the SARA power pin. 54 | // If you're using the MicroMod Asset Tracker and the MicroMod Artemis Processor Board, 55 | // the pin name is G2 which is connected to pin AD34. 56 | // Change the pin number if required. 57 | //SARA_R5 mySARA(34); 58 | 59 | // processHTTPcommandResult is provided to the SARA-R5 library via a 60 | // callback setter -- setHTTPCommandCallback. (See the end of setup()) 61 | void processHTTPcommandResult(int profile, int command, int result) 62 | { 63 | Serial.println(); 64 | Serial.print(F("HTTP Command Result: profile: ")); 65 | Serial.print(profile); 66 | Serial.print(F(" command: ")); 67 | Serial.print(command); 68 | Serial.print(F(" result: ")); 69 | Serial.print(result); 70 | if (result == 0) 71 | Serial.print(F(" (fail)")); 72 | if (result == 1) 73 | Serial.print(F(" (success)")); 74 | Serial.println(); 75 | 76 | // Get and print the most recent HTTP protocol error 77 | int error_class; 78 | int error_code; 79 | mySARA.getHTTPprotocolError(0, &error_class, &error_code); 80 | Serial.print(F("Most recent HTTP protocol error: class: ")); 81 | Serial.print(error_class); 82 | Serial.print(F(" code: ")); 83 | Serial.print(error_code); 84 | if (error_code == 0) 85 | Serial.print(F(" (no error)")); 86 | Serial.println(); 87 | 88 | // Read and print the HTTP POST result 89 | String postResult = ""; 90 | mySARA.getFileContents("post_response.txt", &postResult); 91 | Serial.print(F("HTTP command result was: ")); 92 | Serial.println(postResult); 93 | 94 | Serial.println(); 95 | } 96 | 97 | void setup() 98 | { 99 | String currentOperator = ""; 100 | 101 | Serial.begin(115200); // Start the serial console 102 | 103 | // Wait for user to press key to begin 104 | Serial.println(F("SARA-R5 Example")); 105 | Serial.println(F("Press any key to begin")); 106 | 107 | while (!Serial.available()) // Wait for the user to press a key (send any serial character) 108 | ; 109 | while (Serial.available()) // Empty the serial RX buffer 110 | Serial.read(); 111 | 112 | //mySARA.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial 113 | 114 | // For the MicroMod Asset Tracker, we need to invert the power pin so it pulls high instead of low 115 | // Comment the next line if required 116 | mySARA.invertPowerPin(true); 117 | 118 | // Initialize the SARA 119 | if (mySARA.begin(saraSerial, 9600) ) 120 | { 121 | Serial.println(F("SARA-R5 connected!")); 122 | } 123 | else 124 | { 125 | Serial.println(F("Unable to communicate with the SARA.")); 126 | Serial.println(F("Manually power-on (hold the SARA On button for 3 seconds) on and try again.")); 127 | while (1) ; // Loop forever on fail 128 | } 129 | Serial.println(); 130 | 131 | // First check to see if we're connected to an operator: 132 | if (mySARA.getOperator(¤tOperator) == SARA_R5_SUCCESS) 133 | { 134 | Serial.print(F("Connected to: ")); 135 | Serial.println(currentOperator); 136 | } 137 | else 138 | { 139 | Serial.print(F("The SARA is not yet connected to an operator. Please use the previous examples to connect. Or wait and retry. Freezing...")); 140 | while (1) 141 | ; // Do nothing more 142 | } 143 | 144 | // Deactivate the PSD profile - in case one is already active 145 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_DEACTIVATE) != SARA_R5_SUCCESS) 146 | { 147 | Serial.println(F("Warning: performPDPaction (deactivate profile) failed. Probably because no profile was active.")); 148 | } 149 | 150 | // Load the PSD profile from NVM - these were saved by a previous example 151 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_LOAD) != SARA_R5_SUCCESS) 152 | { 153 | Serial.println(F("performPDPaction (load from NVM) failed! Freezing...")); 154 | while (1) 155 | ; // Do nothing more 156 | } 157 | 158 | // Activate the PSD profile 159 | if (mySARA.performPDPaction(0, SARA_R5_PSD_ACTION_ACTIVATE) != SARA_R5_SUCCESS) 160 | { 161 | Serial.println(F("performPDPaction (activate profile) failed! Freezing...")); 162 | while (1) 163 | ; // Do nothing more 164 | } 165 | 166 | // Reset HTTP profile 0 167 | mySARA.resetHTTPprofile(0); 168 | 169 | // Set the server name 170 | mySARA.setHTTPserverName(0, serverName); 171 | 172 | // Use HTTPS 173 | mySARA.setHTTPsecure(0, false); // Setting this to true causes the POST / GET to fail. Not sure why... 174 | 175 | // Set a callback to process the HTTP command result 176 | mySARA.setHTTPCommandCallback(&processHTTPcommandResult); 177 | } 178 | 179 | void loop() 180 | { 181 | float temperature = ((float)random(2000,3000)) / 100.0; // Create a random temperature between 20 and 30 182 | 183 | //--- 184 | 185 | // Send data using HTTP POST 186 | String httpRequestData = "api_key=" + myWriteAPIKey + "&field1=" + String(temperature); 187 | 188 | Serial.print(F("POSTing a temperature of ")); 189 | Serial.print(String(temperature)); 190 | Serial.println(F(" to ThingSpeak")); 191 | 192 | // Send HTTP POST request to /update. The reponse will be written to post_response.txt in the SARA's file system 193 | mySARA.sendHTTPPOSTdata(0, "/update", "post_response.txt", httpRequestData, SARA_R5_HTTP_CONTENT_APPLICATION_X_WWW); 194 | 195 | //--- 196 | 197 | // // Send data using HTTP GET 198 | // String path = "/update?api_key=" + myWriteAPIKey + "&field1=" + String(temperature); 199 | // 200 | // Serial.print(F("Send a temperature of ")); 201 | // Serial.print(String(temperature)); 202 | // Serial.println(F(" to ThingSpeak using HTTP GET")); 203 | // 204 | // // Send HTTP POST request to /update. The reponse will be written to post_response.txt in the SARA's file system 205 | // mySARA.sendHTTPGET(0, path, "post_response.txt"); 206 | 207 | //--- 208 | 209 | // Wait for 20 seconds 210 | for (int i = 0; i < 20000; i++) 211 | { 212 | mySARA.poll(); // Keep processing data from the SARA so we can catch the HTTP command result 213 | delay(1); 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /img/Contributing.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_u-blox_SARA-R5_Arduino_Library/c9cb44d27401b968b1ef7cf6f63e487447b3155a/img/Contributing.JPG -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes KEYWORD1 7 | ####################################### 8 | 9 | SARA_R5 KEYWORD1 10 | SARA_R5_flow_control_t KEYWORD1 11 | mobile_network_operator_t KEYWORD1 12 | SARA_R5_error_t KEYWORD1 13 | SARA_R5_registration_status_t KEYWORD1 14 | DateData KEYWORD1 15 | TimeData KEYWORD1 16 | ClockData KEYWORD1 17 | PositionData KEYWORD1 18 | SpeedData KEYWORD1 19 | operator_stats KEYWORD1 20 | SARA_R5_socket_protocol_t KEYWORD1 21 | SARA_R5_message_format_t KEYWORD1 22 | SARA_R5_utime_mode_t KEYWORD1 23 | SARA_R5_utime_sensor_t KEYWORD1 24 | SARA_R5_utime_urc_configuration_t KEYWORD1 25 | SARA_R5_sim_states_t KEYWORD1 26 | SARA_R5_http_op_codes_t KEYWORD1 27 | SARA_R5_http_commands_t KEYWORD1 28 | SARA_R5_http_content_types_t KEYWORD1 29 | SARA_R5_mqtt_nv_parameter_t KEYWORD1 30 | SARA_R5_mqtt_profile_opcode_t KEYWORD1 31 | SARA_R5_mqtt_command_opcode_t KEYWORD1 32 | SARA_R5_pdp_configuration_parameter_t KEYWORD1 33 | SARA_R5_pdp_protocol_type_t KEYWORD1 34 | SARA_R5_pdp_actions_t KEYWORD1 35 | SARA_R5_sec_profile_parameter_t KEYWORD1 36 | SARA_R5_sec_profile_certval_op_code_t KEYWORD1 37 | SARA_R5_sec_profile_tls_op_code_t KEYWORD1 38 | SARA_R5_sec_profile_suite_op_code_t KEYWORD1 39 | SARA_R5_sec_manager_opcode_t KEYWORD1 40 | SARA_R5_sec_manager_parameter_t KEYWORD1 41 | SARA_R5_functionality_t KEYWORD1 42 | SARA_R5_pdp_type KEYWORD1 43 | SARA_R5_l2p_t KEYWORD1 44 | SARA_R5_gpio_t KEYWORD1 45 | SARA_R5_gpio_mode_t KEYWORD1 46 | gnss_system_t KEYWORD1 47 | gnss_aiding_mode_t KEYWORD1 48 | 49 | ####################################### 50 | # Methods and Functions KEYWORD2 51 | ####################################### 52 | 53 | begin KEYWORD2 54 | enableDebugging KEYWORD2 55 | enableAtDebugging KEYWORD2 56 | invertPowerPin KEYWORD2 57 | modulePowerOff KEYWORD2 58 | modulePowerOn KEYWORD2 59 | bufferedPoll KEYWORD2 60 | processReadEvent KEYWORD2 61 | poll KEYWORD2 62 | setSocketListenCallback KEYWORD2 63 | setSocketReadCallback KEYWORD2 64 | setSocketReadCallbackPlus KEYWORD2 65 | setSocketCloseCallback KEYWORD2 66 | setGpsReadCallback KEYWORD2 67 | setSIMstateReportCallback KEYWORD2 68 | setPSDActionCallback KEYWORD2 69 | setPingCallback KEYWORD2 70 | setHTTPCommandCallback KEYWORD2 71 | setMQTTCommandCallback KEYWORD2 72 | setRegistrationCallback KEYWORD2 73 | setEpsRegistrationCallback KEYWORD2 74 | write KEYWORD2 75 | at KEYWORD2 76 | enableEcho KEYWORD2 77 | getManufacturerID KEYWORD2 78 | getModelID KEYWORD2 79 | getFirmwareVersion KEYWORD2 80 | getSerialNo KEYWORD2 81 | getIMEI KEYWORD2 82 | getIMSI KEYWORD2 83 | getCCID KEYWORD2 84 | getSubscriberNo KEYWORD2 85 | getCapabilities KEYWORD2 86 | reset KEYWORD2 87 | clock KEYWORD2 88 | setClock KEYWORD2 89 | autoTimeZoneForBegin KEYWORD2 90 | autoTimeZone KEYWORD2 91 | setUtimeMode KEYWORD2 92 | getUtimeMode KEYWORD2 93 | setUtimeIndication KEYWORD2 94 | getUtimeIndication KEYWORD2 95 | setUtimeConfiguration KEYWORD2 96 | getUtimeConfiguration KEYWORD2 97 | rssi KEYWORD2 98 | registration KEYWORD2 99 | setNetworkProfile KEYWORD2 100 | getNetworkProfile KEYWORD2 101 | setAPN KEYWORD2 102 | getAPN KEYWORD2 103 | getSimStatus KEYWORD2 104 | setSimPin KEYWORD2 105 | setSIMstateReportingMode KEYWORD2 106 | getSIMstateReportingMode KEYWORD2 107 | enterPPP KEYWORD2 108 | getOperators KEYWORD2 109 | registerOperator KEYWORD2 110 | automaticOperatorSelection KEYWORD2 111 | getOperator KEYWORD2 112 | deregisterOperator KEYWORD2 113 | setSMSMessageFormat KEYWORD2 114 | sendSMS KEYWORD2 115 | getPreferredMessageStorage KEYWORD2 116 | readSMSmessage KEYWORD2 117 | deleteSMSmessage KEYWORD2 118 | deleteReadSMSmessages KEYWORD2 119 | deleteReadSentSMSmessages KEYWORD2 120 | deleteReadSentUnsentSMSmessages KEYWORD2 121 | deleteAllSMSmessages KEYWORD2 122 | setBaud KEYWORD2 123 | setFlowControl KEYWORD2 124 | setGpioMode KEYWORD2 125 | getGpioMode KEYWORD2 126 | socketOpen KEYWORD2 127 | socketClose KEYWORD2 128 | socketConnect KEYWORD2 129 | socketWrite KEYWORD2 130 | socketWriteUDP KEYWORD2 131 | socketRead KEYWORD2 132 | socketReadAvailable KEYWORD2 133 | socketReadUDP KEYWORD2 134 | socketReadAvailableUDP KEYWORD2 135 | socketListen KEYWORD2 136 | socketDirectLinkMode KEYWORD2 137 | socketDirectLinkTimeTrigger KEYWORD2 138 | socketDirectLinkDataLengthTrigger KEYWORD2 139 | socketDirectLinkCharacterTrigger KEYWORD2 140 | socketDirectLinkCongestionTimer KEYWORD2 141 | querySocketType KEYWORD2 142 | querySocketLastError KEYWORD2 143 | querySocketTotalBytesSent KEYWORD2 144 | querySocketTotalBytesReceived KEYWORD2 145 | querySocketRemoteIPAddress KEYWORD2 146 | querySocketStatusTCP KEYWORD2 147 | querySocketOutUnackData KEYWORD2 148 | socketSetSecure KEYWORD2 149 | socketGetLastError KEYWORD2 150 | lastRemoteIP KEYWORD2 151 | ping KEYWORD2 152 | resetHTTPprofile KEYWORD2 153 | setHTTPserverIPaddress KEYWORD2 154 | setHTTPserverName KEYWORD2 155 | setHTTPusername KEYWORD2 156 | setHTTPpassword KEYWORD2 157 | setHTTPauthentication KEYWORD2 158 | setHTTPserverPort KEYWORD2 159 | setHTTPcustomHeader KEYWORD2 160 | setHTTPsecure KEYWORD2 161 | getHTTPprotocolError KEYWORD2 162 | sendHTTPGET KEYWORD2 163 | sendHTTPPOSTdata KEYWORD2 164 | sendHTTPPOSTfile KEYWORD2 165 | nvMQTT KEYWORD2 166 | setMQTTclientId KEYWORD2 167 | setMQTTserver KEYWORD2 168 | setMQTTcredentials KEYWORD2 169 | setMQTTsecure KEYWORD2 170 | connectMQTT KEYWORD2 171 | disconnectMQTT KEYWORD2 172 | subscribeMQTTtopic KEYWORD2 173 | unsubscribeMQTTtopic KEYWORD2 174 | readMQTT KEYWORD2 175 | mqttPublishTextMsg KEYWORD2 176 | mqttPublishBinaryMsg KEYWORD2 177 | mqttPublishFromFile KEYWORD2 178 | getMQTTprotocolError KEYWORD2 179 | resetSecurityProfile KEYWORD2 180 | configSecurityProfileString KEYWORD2 181 | configSecurityProfile KEYWORD2 182 | setSecurityManager KEYWORD2 183 | setPDPconfiguration KEYWORD2 184 | performPDPaction KEYWORD2 185 | activatePDPcontext KEYWORD2 186 | getNetworkAssignedIPAddress KEYWORD2 187 | isGPSon KEYWORD2 188 | gpsPower KEYWORD2 189 | # gpsEnableClock KEYWORD2 190 | # gpsGetClock KEYWORD2 191 | # gpsEnableFix KEYWORD2 192 | # gpsGetFix KEYWORD2 193 | # gpsEnablePos KEYWORD2 194 | # gpsGetPos KEYWORD2 195 | # gpsEnableSat KEYWORD2 196 | # gpsGetSat KEYWORD2 197 | gpsEnableRmc KEYWORD2 198 | gpsGetRmc KEYWORD2 199 | # gpsEnableSpeed KEYWORD2 200 | # gpsGetSpeed KEYWORD2 201 | gpsRequest KEYWORD2 202 | gpsAidingServerConf KEYWORD2 203 | getFileContents KEYWORD2 204 | appendFileContents KEYWORD2 205 | getFileSize KEYWORD2 206 | deleteFile KEYWORD2 207 | functionality KEYWORD2 208 | sendCustomCommandWithResponse KEYWORD2 209 | 210 | ####################################### 211 | # Constants LITERAL1 212 | ####################################### 213 | 214 | SARA_R5_DISABLE_FLOW_CONTROL LITERAL1 215 | SARA_R5_ENABLE_FLOW_CONTROL LITERAL1 216 | MNO_INVALID LITERAL1 217 | MNO_SW_DEFAULT LITERAL1 218 | MNO_SIM_ICCID LITERAL1 219 | MNO_ATT LITERAL1 220 | MNO_VERIZON LITERAL1 221 | MNO_TELSTRA LITERAL1 222 | MNO_TMO LITERAL1 223 | MNO_CT LITERAL1 224 | MNO_SPRINT LITERAL1 225 | MNO_VODAFONE LITERAL1 226 | MNO_NTT_DOCOMO LITERAL1 227 | MNO_TELUS LITERAL1 228 | MNO_SOFTBANK LITERAL1 229 | MNO_DT LITERAL1 230 | MNO_US_CELLULAR LITERAL1 231 | MNO_SKT LITERAL1 232 | MNO_GLOBAL LITERAL1 233 | MNO_STD_EUROPE LITERAL1 234 | MNO_STD_EU_NOEPCO LITERAL1 235 | SARA_R5_ERROR_INVALID LITERAL1 236 | SARA_R5_ERROR_SUCCESS LITERAL1 237 | SARA_R5_ERROR_OUT_OF_MEMORY LITERAL1 238 | SARA_R5_ERROR_TIMEOUT LITERAL1 239 | SARA_R5_ERROR_UNEXPECTED_PARAM LITERAL1 240 | SARA_R5_ERROR_UNEXPECTED_RESPONSE LITERAL1 241 | SARA_R5_ERROR_NO_RESPONSE LITERAL1 242 | SARA_R5_ERROR_DEREGISTERED LITERAL1 243 | SARA_R5_ERROR_ERROR LITERAL1 244 | SARA_R5_SUCCESS LITERAL1 245 | SARA_R5_REGISTRATION_INVALID LITERAL1 246 | SARA_R5_REGISTRATION_NOT_REGISTERED LITERAL1 247 | SARA_R5_REGISTRATION_HOME LITERAL1 248 | SARA_R5_REGISTRATION_SEARCHING LITERAL1 249 | SARA_R5_REGISTRATION_DENIED LITERAL1 250 | SARA_R5_REGISTRATION_UNKNOWN LITERAL1 251 | SARA_R5_REGISTRATION_ROAMING LITERAL1 252 | SARA_R5_REGISTRATION_HOME_SMS_ONLY LITERAL1 253 | SARA_R5_REGISTRATION_ROAMING_SMS_ONLY LITERAL1 254 | SARA_R5_REGISTRATION_EMERGENCY_SERV_ONLY LITERAL1 255 | SARA_R5_REGISTRATION_HOME_CSFB_NOT_PREFERRED LITERAL1 256 | SARA_R5_REGISTRATION_ROAMING_CSFB_NOT_PREFERRED LITERAL1 257 | day LITERAL1 258 | month LITERAL1 259 | year LITERAL1 260 | hour LITERAL1 261 | minute LITERAL1 262 | second LITERAL1 263 | ms LITERAL1 264 | tzh LITERAL1 265 | tzm LITERAL1 266 | date LITERAL1 267 | time LITERAL1 268 | utc LITERAL1 269 | lat LITERAL1 270 | lon LITERAL1 271 | alt LITERAL1 272 | mode LITERAL1 273 | status LITERAL1 274 | speed LITERAL1 275 | cog LITERAL1 276 | magVar LITERAL1 277 | stat LITERAL1 278 | shortOp LITERAL1 279 | longOp LITERAL1 280 | numOp LITERAL1 281 | act LITERAL1 282 | SARA_R5_TCP LITERAL1 283 | SARA_R5_UDP LITERAL1 284 | SARA_R5_MESSAGE_FORMAT_PDU LITERAL1 285 | SARA_R5_MESSAGE_FORMAT_TEXT LITERAL1 286 | SARA_R5_UTIME_MODE_STOP LITERAL1 287 | SARA_R5_UTIME_MODE_PPS LITERAL1 288 | SARA_R5_UTIME_MODE_ONE_SHOT LITERAL1 289 | SARA_R5_UTIME_MODE_EXT_INT LITERAL1 290 | SARA_R5_UTIME_SENSOR_NONE LITERAL1 291 | SARA_R5_UTIME_SENSOR_GNSS_LTE LITERAL1 292 | SARA_R5_UTIME_SENSOR_LTE LITERAL1 293 | SARA_R5_UTIME_URC_CONFIGURATION_DISABLED LITERAL1 294 | SARA_R5_UTIME_URC_CONFIGURATION_ENABLED LITERAL1 295 | SARA_R5_SIM_NOT_PRESENT LITERAL1 296 | SARA_R5_SIM_PIN_NEEDED LITERAL1 297 | SARA_R5_SIM_PIN_BLOCKED LITERAL1 298 | SARA_R5_SIM_PUK_BLOCKED LITERAL1 299 | SARA_R5_SIM_NOT_OPERATIONAL LITERAL1 300 | SARA_R5_SIM_RESTRICTED LITERAL1 301 | SARA_R5_SIM_OPERATIONAL LITERAL1 302 | SARA_R5_HTTP_OP_CODE_SERVER_IP LITERAL1 303 | SARA_R5_HTTP_OP_CODE_SERVER_NAME LITERAL1 304 | SARA_R5_HTTP_OP_CODE_USERNAME LITERAL1 305 | SARA_R5_HTTP_OP_CODE_PASSWORD LITERAL1 306 | SARA_R5_HTTP_OP_CODE_AUTHENTICATION LITERAL1 307 | SARA_R5_HTTP_OP_CODE_SERVER_PORT LITERAL1 308 | SARA_R5_HTTP_OP_CODE_SECURE LITERAL1 309 | SARA_R5_HTTP_OP_CODE_REQUEST_TIMEOUT LITERAL1 310 | SARA_R5_HTTP_OP_CODE_ADD_CUSTOM_HEADERS LITERAL1 311 | SARA_R5_HTTP_COMMAND_HEAD LITERAL1 312 | SARA_R5_HTTP_COMMAND_GET LITERAL1 313 | SARA_R5_HTTP_COMMAND_DELETE LITERAL1 314 | SARA_R5_HTTP_COMMAND_PUT LITERAL1 315 | SARA_R5_HTTP_COMMAND_POST_FILE LITERAL1 316 | SARA_R5_HTTP_COMMAND_POST_DATA LITERAL1 317 | SARA_R5_HTTP_COMMAND_GET_FOTA LITERAL1 318 | SARA_R5_HTTP_CONTENT_APPLICATION_X_WWW LITERAL1 319 | SARA_R5_HTTP_CONTENT_TEXT_PLAIN LITERAL1 320 | SARA_R5_HTTP_CONTENT_APPLICATION_OCTET LITERAL1 321 | SARA_R5_HTTP_CONTENT_MULTIPART_FORM LITERAL1 322 | SARA_R5_HTTP_CONTENT_APPLICATION_JSON LITERAL1 323 | SARA_R5_HTTP_CONTENT_APPLICATION_XML LITERAL1 324 | SARA_R5_HTTP_CONTENT_USER_DEFINED LITERAL1 325 | SARA_R5_PSD_CONFIG_PARAM_PROTOCOL LITERAL1 326 | SARA_R5_PSD_CONFIG_PARAM_APN LITERAL1 327 | SARA_R5_PSD_CONFIG_PARAM_DNS1 LITERAL1 328 | SARA_R5_PSD_CONFIG_PARAM_DNS2 LITERAL1 329 | SARA_R5_PSD_CONFIG_PARAM_MAP_TO_CID LITERAL1 330 | SARA_R5_PSD_PROTOCOL_IPV4 LITERAL1 331 | SARA_R5_PSD_PROTOCOL_IPV6 LITERAL1 332 | SARA_R5_PSD_PROTOCOL_IPV4V6_V4_PREF LITERAL1 333 | SARA_R5_PSD_PROTOCOL_IPV4V6_V6_PREF LITERAL1 334 | SARA_R5_PSD_ACTION_RESET LITERAL1 335 | SARA_R5_PSD_ACTION_STORE LITERAL1 336 | SARA_R5_PSD_ACTION_LOAD LITERAL1 337 | SARA_R5_PSD_ACTION_ACTIVATE LITERAL1 338 | SARA_R5_PSD_ACTION_DEACTIVATE LITERAL1 339 | MINIMUM_FUNCTIONALITY LITERAL1 340 | FULL_FUNCTIONALITY LITERAL1 341 | AIRPLANE_MODE LITERAL1 342 | SIM_TOOLKIT_ENABLE_DEDICATED LITERAL1 343 | SIM_TOOLKIT_DISABLE_DEDICATED LITERAL1 344 | SIM_TOOLKIT_ENABLE_RAW LITERAL1 345 | FAST_SAFE_POWER_OFF LITERAL1 346 | SILENT_RESET_WITH_SIM LITERAL1 347 | PDP_TYPE_INVALID LITERAL1 348 | PDP_TYPE_IP LITERAL1 349 | PDP_TYPE_NONIP LITERAL1 350 | PDP_TYPE_IPV4V6 LITERAL1 351 | PDP_TYPE_IPV6 LITERAL1 352 | L2P_DEFAULT LITERAL1 353 | L2P_PPP LITERAL1 354 | L2P_M_HEX LITERAL1 355 | L2P_M_RAW_IP LITERAL1 356 | L2P_M_OPT_PPP LITERAL1 357 | GPIO1 LITERAL1 358 | GPIO2 LITERAL1 359 | GPIO3 LITERAL1 360 | GPIO4 LITERAL1 361 | GPIO5 LITERAL1 362 | GPIO6 LITERAL1 363 | GPIO_MODE_INVALID LITERAL1 364 | GPIO_OUTPUT LITERAL1 365 | GPIO_INPUT LITERAL1 366 | NETWORK_STATUS LITERAL1 367 | GNSS_SUPPLY_ENABLE LITERAL1 368 | GNSS_DATA_READY LITERAL1 369 | GNSS_RTC_SHARING LITERAL1 370 | JAMMING_DETECTION LITERAL1 371 | SIM_CARD_DETECTION LITERAL1 372 | HEADSET_DETECTION LITERAL1 373 | GSM_TX_BURST_INDICATION LITERAL1 374 | MODULE_STATUS_INDICATION LITERAL1 375 | MODULE_OPERATING_MODE_INDICATION LITERAL1 376 | I2S_DIGITAL_AUDIO_INTERFACE LITERAL1 377 | SPI_SERIAL_INTERFACE LITERAL1 378 | MASTER_CLOCK_GENRATION LITERAL1 379 | UART_INTERFACE LITERAL1 380 | WIFI_ENABLE LITERAL1 381 | RING_INDICATION LITERAL1 382 | LAST_GASP_ENABLE LITERAL1 383 | EXTERNAL_GNSS_ANTENNA LITERAL1 384 | TIME_PULSE_GNSS LITERAL1 385 | TIME_PULSE_OUTPUT LITERAL1 386 | TIMESTAMP LITERAL1 387 | FAST_POWER_OFF LITERAL1 388 | LWM2M_PULSE LITERAL1 389 | HARDWARE_FLOW_CONTROL LITERAL1 390 | ANTENNA_TUNING LITERAL1 391 | EXT_GNSS_TIME_PULSE LITERAL1 392 | EXT_GNSS_TIMESTAMP LITERAL1 393 | DTR_MODE LITERAL1 394 | KHZ_32768_OUT LITERAL1 395 | PAD_DISABLED LITERAL1 396 | SARA_R5_TCP_SOCKET_STATUS_INACTIVE LITERAL1 397 | SARA_R5_TCP_SOCKET_STATUS_LISTEN LITERAL1 398 | SARA_R5_TCP_SOCKET_STATUS_SYN_SENT LITERAL1 399 | SARA_R5_TCP_SOCKET_STATUS_SYN_RCVD LITERAL1 400 | SARA_R5_TCP_SOCKET_STATUS_ESTABLISHED LITERAL1 401 | SARA_R5_TCP_SOCKET_STATUS_FIN_WAIT_1 LITERAL1 402 | SARA_R5_TCP_SOCKET_STATUS_FIN_WAIT_2 LITERAL1 403 | SARA_R5_TCP_SOCKET_STATUS_CLOSE_WAIT LITERAL1 404 | SARA_R5_TCP_SOCKET_STATUS_CLOSING LITERAL1 405 | SARA_R5_TCP_SOCKET_STATUS_LAST_ACK LITERAL1 406 | SARA_R5_TCP_SOCKET_STATUS_TIME_WAIT LITERAL1 407 | GNSS_SYSTEM_GPS LITERAL1 408 | GNSS_SYSTEM_SBAS LITERAL1 409 | GNSS_SYSTEM_GALILEO LITERAL1 410 | GNSS_SYSTEM_BEIDOU LITERAL1 411 | GNSS_SYSTEM_IMES LITERAL1 412 | GNSS_SYSTEM_QZSS LITERAL1 413 | GNSS_SYSTEM_GLONASS LITERAL1 414 | GNSS_AIDING_MODE_NONE LITERAL1 415 | GNSS_AIDING_MODE_AUTOMATIC LITERAL1 416 | GNSS_AIDING_MODE_ASSISTNOW_OFFLINE LITERAL1 417 | GNSS_AIDING_MODE_ASSISTNOW_ONLINE LITERAL1 418 | GNSS_AIDING_MODE_ASSISTNOW_AUTONOMOUS LITERAL1 419 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SparkFun u-blox SARA-R5 Arduino Library 2 | version=1.1.13 3 | author=SparkFun Electronics 4 | maintainer=SparkFun Electronics 5 | sentence=Library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud

6 | paragraph=An Arduino library for the u-blox SARA-R5 LTE-M / NB-IoT modules with secure cloud, as used on the SparkFun MicroMod Asset Tracker and the SparkFun LTE GNSS Breakout - SARA-R5.

v1.1 has had a thorough update and includes new features and examples. This library now supports up to 7 simultaneous TCP or UDP sockets. There are new examples to show how to play ping pong with both TCP and UDP sockets.

v1.1 also supports binary data transfers correctly. There are new examples showing how you can integrate this library with the SparkFun u-blox GNSS Arduino Library, to use the SARA-R5 to: download AssistNow Online and Offline data and push it to the GNSS; open a connection to a NTRIP Caster (such as RTK2go, Skylark or Emlid Caster) and push RTK correction data to the GNSS.
7 | category=Communication 8 | url=https://github.com/sparkfun/SparkFun_u-blox_SARA-R5_Arduino_Library 9 | architectures=* 10 | --------------------------------------------------------------------------------