Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Michael Krumpus
2019-03-30 13:47:49 -05:00
62 changed files with 4384 additions and 1042 deletions

22
.gitignore vendored
View File

@@ -14,16 +14,24 @@
.cproject .cproject
.project .project
.settings .settings
# Markers
.development
# Extras
extras/docs/*
.pioenvs .pioenvs
.piolibdeps .piolibdeps
.clang_complete .clang_complete
.gcc-flags.json .gcc-flags.json
platformio.ini platformio.ini
lib/readme.txt lib/readme.txt
include/readme.txt
.vscode/*
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
# Markers
.development
# Extras
extras/docs/*
extras/Module Datasheets/*
extras/Older Command Manuals/*
extras/Older Command Manuals/*
extras/At Command Manuals - Unsupported/*

View File

@@ -18,23 +18,30 @@ env:
- PLATFORMIO_CI_SRC=tools/FactoryReset - PLATFORMIO_CI_SRC=tools/FactoryReset
# Arduino test # Arduino test
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM900' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M590' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_ESP8266' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_UBLOX' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_BG96' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_BG96' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_ESP8266' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M95' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M590' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_MC60' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM808' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM7000' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_UBLOX' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
# Energia test # Energia test
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM900' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=energia' --board=lplm4f120h5qr" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M590' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_ESP8266' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_UBLOX' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_BG96' --project-option='framework=energia' --board=lplm4f120h5qr" - PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_BG96' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_ESP8266' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M95' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M590' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_MC60' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM808' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM7000' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_UBLOX' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=energia' --board=lplm4f120h5qr"
# Disabled due to a bug in Energia readBytes implementation # Disabled due to a bug in Energia readBytes implementation
#- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=energia' --board=lplm4f120h5qr" #- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=energia' --board=lplm4f120h5qr"
@@ -58,5 +65,7 @@ install:
- platformio lib -g install 89 415 1202 1286 - platformio lib -g install 89 415 1202 1286
- platformio lib -g update - platformio lib -g update
- platformio lib update - platformio lib update
- platformio lib list
- platformio lib -g list
script: make travis-build script: make travis-build

View File

@@ -18,7 +18,7 @@ You can also join our chat:
[![Gitter](https://img.shields.io/gitter/room/vshymanskyy/TinyGSM.svg)](https://gitter.im/tinygsm) [![Gitter](https://img.shields.io/gitter/room/vshymanskyy/TinyGSM.svg)](https://gitter.im/tinygsm)
### Arduino Client interface support ### Arduino Client interface support
This library is easy to integrate with lots of sketches, which use Ethernet or WiFi. This library is easy to integrate with lots of sketches which use Ethernet or WiFi.
**PubSubClient ([MQTT](http://mqtt.org/))**, **[Blynk](http://blynk.cc)**, **HTTP Client** and **File Download** examples are provided. **PubSubClient ([MQTT](http://mqtt.org/))**, **[Blynk](http://blynk.cc)**, **HTTP Client** and **File Download** examples are provided.
![examples](/extras/examples.png) ![examples](/extras/examples.png)
@@ -29,38 +29,40 @@ The complete WebClient example for Arduino Uno (via Software Serial) takes littl
Sketch uses 15022 bytes (46%) of program storage space. Maximum is 32256 bytes. Sketch uses 15022 bytes (46%) of program storage space. Maximum is 32256 bytes.
Global variables use 574 bytes (28%) of dynamic memory, leaving 1474 bytes for local variables. Maximum is 2048 bytes. Global variables use 574 bytes (28%) of dynamic memory, leaving 1474 bytes for local variables. Maximum is 2048 bytes.
``` ```
Arduino GSM library uses 15868 bytes (49%) of Flash and 1113 bytes (54%) of RAM in a similar scenario. Arduino GSM library uses 15868 bytes (49%) of Flash and 1113 bytes (54%) of RAM in a similar scenario.
TinyGSM also pulls data gently from the modem (whenever possible), so it can operate on very little RAM. TinyGSM also pulls data gently from the modem (whenever possible), so it can operate on very little RAM.
**Now, you have more space for your experiments.** **Now, you have more space for your experiments.**
## Features ## Features
Feature \ Modem | SIM8xx | u-Blox | A6/A7/A20 | M590 | ESP8266 | XBee Feature \ Modem | SIM8xx | u-Blox | A6/A7/A20 | Neoway M590| ESP8266 |Digi XBee|Quectel BG96|Quectel M95|Quectel MC60(E)| SIM7000 |
--- | --- | --- | --- | --- | --- | --- --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
**Data connections** **Data connections**
TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |
UDP | ◌ | ◌ | | | | ◌ UDP | ◌ | ◌ | | | | ◌ | ◌ | | | ◌ |
SSL/TLS (HTTPS) | ✔¹ | ✔ | 🅧 | 🅧 | ✔¹ | ✔¹ SSL/TLS (HTTPS) | ✔¹ | ✔ | x | x | ✔ | ✔ | ◌ | | | ◌ |
**USSD** **USSD**
Sending USSD requests | ✔ | | ✔ | ✔ | 🅧 | Sending USSD requests | ✔ | | ✔ | ✔ | x | | | | | ✔ |
Decoding 7,8,16-bit response | ✔ | | ✔ | ✔ | 🅧 | Decoding 7,8,16-bit response | ✔ | | ✔ | ✔ | x | | | | | ✔ |
**SMS** **SMS**
Sending | ✔ | ✔ | ✔ | ✔ | 🅧 | ✔ Sending | ✔ | ✔ | ✔ | ✔ | x | ✔ | ✔ | ✔ | ✔ | ✔ |
Sending Unicode | ✔ | | ◌ | 🅧 | 🅧 | Sending Unicode | ✔ | | ◌ | x | x | | ✔ | ✔ | ✔ | ✔ |
Reading | | | | | 🅧 | Reading | | | | | x | | | | | |
Incoming message event | | | | ? | 🅧 | Incoming message event | | | | ? | x | | | | | |
**Calls** **Calls**
Dial, hangup | ✔ | | ✔ | 🅧 | 🅧 | 🅧 Dial, hangup | ✔ | | ✔ | x | x | x | | | | |
Receiving calls | ✔ | | ✔ | 🅧 | 🅧 | 🅧 Receiving calls | ✔ | | ✔ | x | x | x | | | | |
Incoming event (RING) | ◌ | | ◌ | 🅧 | 🅧 | 🅧 Incoming event (RING) | ◌ | | ◌ | x | x | x | | | | |
DTMF sending | ✔ | | ✔ | 🅧 | 🅧 | 🅧 DTMF sending | ✔ | | ✔ | x | x | x | | | | |
DTMF decoding | ◌ | | 🅧 | 🅧 | 🅧 | 🅧 DTMF decoding | ◌ | | x | x | x | x | | | | |
**Location** **Location**
GSM location service | ✔ | ✔ | 🅧 | 🅧 | 🅧 | ✔ GSM location service | ✔ | ✔ | x | x | x | x | | x | ✔ | ✔ |
GPS/GNSS | ✔¹ | 🅧 | ◌¹ | 🅧 | 🅧 | 🅧 GPS/GNSS | ✔¹ | x | ◌¹ | x | x | x | | x | | ✔ |
**Credits**
Primary Author/Contributor |[vshymanskyy](https://github.com/vshymanskyy)|[vshymanskyy](https://github.com/vshymanskyy)|[vshymanskyy](https://github.com/vshymanskyy)|[vshymanskyy](https://github.com/vshymanskyy)|[vshymanskyy](https://github.com/vshymanskyy)|[SRGDamia1](https://github.com/SRGDamia1/)|[vshymanskyy](https://github.com/vshymanskyy) |[replicadeltd](https://github.com/replicadeltd)|[V1pr](https://github.com/V1pr)|[captFuture](https://github.com/captFuture/)|
✔ - implemented◌ - planned🅧 - not available on this modem ✔ - implemented◌ - plannedx - not available on this modem
¹ - only some device models or firmware revisions have this feature (SIM8xx R14.18, A7, etc.) ¹ - only some device models or firmware revisions have this feature (SIM8xx R14.18, A7, etc.)
## Supported modems ## Supported modems
@@ -70,8 +72,11 @@ GPS/GNSS | ✔¹ | 🅧 | ◌¹ | 🅧 |
- ESP8266 (AT commands interface, similar to GSM modems) - ESP8266 (AT commands interface, similar to GSM modems)
- Digi XBee WiFi and Cellular (using XBee command mode) - Digi XBee WiFi and Cellular (using XBee command mode)
- Neoway M590 - Neoway M590
- u-blox Cellular Modems (LEON-G100, LISA-U2xx, SARA-G3xx, SARA-U2xx, TOBY-L2xx, LARA-R2xx, MPCI-L2xx) - u-blox Cellular Modems (many modules including LEON-G100, LISA-U2xx, SARA-G3xx, SARA-U2xx, TOBY-L2xx, LARA-R2xx, MPCI-L2xx, SARA-R4xx, SARA-N4xx, _but NOT SARA-N2xx_)
- Quectel BG96 ***(alpha)*** - Quectel BG96 ***(alpha)***
- Quectel M95 ***(alpha)***
- Quectel MC60 ***(alpha)***
- SIMCom SIM7000 series ***(alpha)***
### Supported boards/modules ### Supported boards/modules
- Arduino MKR GSM 1400 - Arduino MKR GSM 1400
@@ -84,9 +89,9 @@ GPS/GNSS | ✔¹ | 🅧 | ◌¹ | 🅧 |
- ... other modules, based on supported modems. Some boards require [**special configuration**](https://github.com/vshymanskyy/TinyGSM/wiki/Board-configuration). - ... other modules, based on supported modems. Some boards require [**special configuration**](https://github.com/vshymanskyy/TinyGSM/wiki/Board-configuration).
More modems may be supported later: More modems may be supported later:
- [ ] Quectel M10, M35, M95, UG95, EC21
- [ ] Sequans Monarch LTE Cat M1/NB1 - [ ] Sequans Monarch LTE Cat M1/NB1
- [ ] SIMCom SIM5320, SIM5360, SIM5216, SIM7xxx - [ ] Quectel M10, UG95
- [ ] SIMCom SIM5320, SIM5360, SIM5216
- [ ] Telit GL865 - [ ] Telit GL865
- [ ] ZTE MG2639 - [ ] ZTE MG2639
- [ ] Hi-Link HLK-RM04 - [ ] Hi-Link HLK-RM04
@@ -98,9 +103,9 @@ Watch this repo for new updates! And of course, contributions are welcome ;)
[![Donate BountySource](https://img.shields.io/badge/Donate-BountySource-149E5E.svg)](https://salt.bountysource.com/checkout/amount?team=tinygsm-dev) [![Donate BountySource](https://img.shields.io/badge/Donate-BountySource-149E5E.svg)](https://salt.bountysource.com/checkout/amount?team=tinygsm-dev)
[![Donate Bitcoin](https://img.shields.io/badge/Donate-Bitcoin-orange.svg)](http://tny.im/aen) [![Donate Bitcoin](https://img.shields.io/badge/Donate-Bitcoin-orange.svg)](http://tny.im/aen)
If you have found TinyGSM to be useful in your work, research or company, please consider making a donation to the project commensurate with your resources. Any amount helps! If you have found TinyGSM to be useful in your work, research or company, please consider making a donation to the project commensurate with your resources. Any amount helps!
**All donations will be used strictly to fund the development of TinyGSM:** **All donations will be used strictly to fund the development of TinyGSM:**
- Covering cellular network expences - Covering cellular network expenses
- Buying new hardware and modems for integration - Buying new hardware and modems for integration
- Bounty Budget (to reward other developers for their contributions) - Bounty Budget (to reward other developers for their contributions)
- Implementing new features - Implementing new features
@@ -111,10 +116,10 @@ If you have found TinyGSM to be useful in your work, research or company, please
1. Using your phone: 1. Using your phone:
- Disable PIN code on the SIM card - Disable PIN code on the SIM card
- Check your balance - Check your balance
- Check that APN,User,Pass are correct and you have internet - Check that APN, User, Pass are correct and you have internet
2. Ensure the SIM card is correctly inserted into the module 2. Ensure the SIM card is correctly inserted into the module
3. Ensure that GSM antenna is firmly attached 3. Ensure that GSM antenna is firmly attached
4. Check if serial connection is working (Hardware Serial is recommended) 4. Check if serial connection is working (Hardware Serial is recommended)
Send an ```AT``` command using [this sketch](tools/AT_Debug/AT_Debug.ino) Send an ```AT``` command using [this sketch](tools/AT_Debug/AT_Debug.ino)
If you have any issues: If you have any issues:
@@ -127,20 +132,20 @@ If you have any issues:
## How does it work? ## How does it work?
Many GSM modems, WiFi and radio modules can be controlled by sending AT commands over Serial. Many GSM modems, WiFi and radio modules can be controlled by sending AT commands over Serial.
TinyGSM knows which commands to send, and how to handle AT responses, and wraps that into standard Arduino Client interface. TinyGSM knows which commands to send, and how to handle AT responses, and wraps that into standard Arduino Client interface.
## API Reference ## API Reference
For GPRS data streams, this library provides the standard [Arduino Client](https://www.arduino.cc/en/Reference/ClientConstructor) interface. For GPRS data streams, this library provides the standard [Arduino Client](https://www.arduino.cc/en/Reference/ClientConstructor) interface.
For additional functions, please refer to [this example sketch](examples/AllFunctions/AllFunctions.ino) For additional functions, please refer to [this example sketch](examples/AllFunctions/AllFunctions.ino)
## Troubleshooting ## Troubleshooting
### Diagnostics sketch ### Diagnostics sketch
Use this sketch to diagnose your SIM card and GPRS connection: Use this sketch to diagnose your SIM card and GPRS connection:
File -> Examples -> TynyGSM -> tools -> [Diagnostics](https://github.com/vshymanskyy/TinyGSM/blob/master/tools/Diagnostics/Diagnostics.ino) File -> Examples -> TinyGSM -> tools -> [Diagnostics](https://github.com/vshymanskyy/TinyGSM/blob/master/tools/Diagnostics/Diagnostics.ino)
### Ensure stable data & power connection ### Ensure stable data & power connection
@@ -153,10 +158,10 @@ So this actually solves stability problems in **many** cases:
### SoftwareSerial problems ### SoftwareSerial problems
When using ```SoftwareSerial``` (on Uno, Nano, etc), the speed **115200** may not work. When using ```SoftwareSerial``` (on Uno, Nano, etc), the speed **115200** may not work.
Try selecting **57600**, **38400**, or even lower - the one that works best for you. Try selecting **57600**, **38400**, or even lower - the one that works best for you.
In some cases **9600** is unstable, but using **38400** helps, etc. In some cases **9600** is unstable, but using **38400** helps, etc.
Be sure to set correct TX/RX pins in the sketch. Please note that not every Arduino pin can serve as TX or RX pin. Be sure to set correct TX/RX pins in the sketch. Please note that not every Arduino pin can serve as TX or RX pin.
**Read more about SoftSerial options and configuration [here](https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html) and [here](https://www.arduino.cc/en/Reference/SoftwareSerial).** **Read more about SoftSerial options and configuration [here](https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html) and [here](https://www.arduino.cc/en/Reference/SoftwareSerial).**
### ESP32 HardwareSerial ### ESP32 HardwareSerial
@@ -171,15 +176,15 @@ Please [refer to this comment](https://github.com/vshymanskyy/TinyGSM/issues/102
### Broken initial configuration ### Broken initial configuration
Sometimes (especially if you played with AT comands), your module configuration may become invalid. Sometimes (especially if you played with AT commands), your module configuration may become invalid.
This may result in problems such as: This may result in problems such as:
* Can't connect to the GPRS network * Can't connect to the GPRS network
* Can't connect to the server * Can't connect to the server
* Sent/recieved data contains invalid bytes * Sent/received data contains invalid bytes
* etc. * etc.
To return module to **Factory Defaults**, use this sketch: To return module to **Factory Defaults**, use this sketch:
File -> Examples -> TinyGSM -> tools -> [FactoryReset](https://github.com/vshymanskyy/TinyGSM/blob/master/tools/FactoryReset/FactoryReset.ino) File -> Examples -> TinyGSM -> tools -> [FactoryReset](https://github.com/vshymanskyy/TinyGSM/blob/master/tools/FactoryReset/FactoryReset.ino)
### Goouuu Tech IOT-GA6 vs AI-Thinker A6 confusion ### Goouuu Tech IOT-GA6 vs AI-Thinker A6 confusion

View File

@@ -1,7 +1,7 @@
/************************************************************** /**************************************************************
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
* NOTE: * NOTE:
* Some of the functions may be unavailable for your modem. * Some of the functions may be unavailable for your modem.
@@ -10,14 +10,20 @@
**************************************************************/ **************************************************************/
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 //#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808 // #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_SIM900
#define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
// Set serial for debug console (to the Serial Monitor, speed 115200) // Set serial for debug console (to the Serial Monitor, speed 115200)
#define SerialMon Serial #define SerialMon Serial
@@ -34,6 +40,22 @@
//#define DUMP_AT_COMMANDS //#define DUMP_AT_COMMANDS
#define TINY_GSM_DEBUG SerialMon #define TINY_GSM_DEBUG SerialMon
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 38400
/*
* Test enabled
*/
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_CALL true
#define TINY_GSM_USE_SMS true
#define TINY_GSM_USE_USSD true
// powerdown modem after tests
#define TINY_GSM_POWERDOWN false
// set GSM PIN, if any
#define GSM_PIN ""
// Set phone numbers, if you want to test SMS and Calls // Set phone numbers, if you want to test SMS and Calls
//#define SMS_TARGET "+380xxxxxxxxx" //#define SMS_TARGET "+380xxxxxxxxx"
//#define CALL_TARGET "+380xxxxxxxxx" //#define CALL_TARGET "+380xxxxxxxxx"
@@ -64,7 +86,7 @@ void setup() {
delay(3000); delay(3000);
// Set GSM module baud rate // Set GSM module baud rate
TinyGsmAutoBaud(SerialAT); TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX);
} }
void loop() { void loop() {
@@ -73,6 +95,10 @@ void loop() {
// To skip it, call init() instead of restart() // To skip it, call init() instead of restart()
DBG("Initializing modem..."); DBG("Initializing modem...");
if (!modem.restart()) { if (!modem.restart()) {
DBG("Failed to restart modem, delaying 10s and retrying");
delay(3000);
// restart autobaud in case GSM just rebooted
TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX);
delay(10000); delay(10000);
return; return;
} }
@@ -80,8 +106,10 @@ void loop() {
String modemInfo = modem.getModemInfo(); String modemInfo = modem.getModemInfo();
DBG("Modem:", modemInfo); DBG("Modem:", modemInfo);
// Unlock your SIM card with a PIN // Unlock your SIM card with a PIN if needed
//modem.simUnlock("1234"); if ( GSM_PIN && modem.getSimStatus() != 3 ) {
modem.simUnlock(GSM_PIN);
}
DBG("Waiting for network..."); DBG("Waiting for network...");
if (!modem.waitForNetwork()) { if (!modem.waitForNetwork()) {
@@ -93,6 +121,7 @@ void loop() {
DBG("Network connected"); DBG("Network connected");
} }
#if TINY_GSM_USE_GPRS
DBG("Connecting to", apn); DBG("Connecting to", apn);
if (!modem.gprsConnect(apn, user, pass)) { if (!modem.gprsConnect(apn, user, pass)) {
delay(10000); delay(10000);
@@ -110,7 +139,7 @@ void loop() {
String cop = modem.getOperator(); String cop = modem.getOperator();
DBG("Operator:", cop); DBG("Operator:", cop);
IPAddress local = modem.localIP(); IPAddress local = modem.localIP();
DBG("Local IP:", local); DBG("Local IP:", local);
@@ -130,25 +159,26 @@ void loop() {
DBG("GSM location:", gsmLoc); DBG("GSM location:", gsmLoc);
// This is only supported on SIMxxx series // This is only supported on SIMxxx series
String gsmTime = modem.getGSMDateTime(DATE_TIME); // String gsmTime = modem.getGSMDateTime(DATE_TIME);
DBG("GSM Time:", gsmTime); // DBG("GSM Time:", gsmTime);
String gsmDate = modem.getGSMDateTime(DATE_DATE); // String gsmDate = modem.getGSMDateTime(DATE_DATE);
DBG("GSM Date:", gsmDate); // DBG("GSM Date:", gsmDate);
String ussd_balance = modem.sendUSSD("*111#"); String ussd_balance = modem.sendUSSD("*111#");
DBG("Balance (USSD):", ussd_balance); DBG("Balance (USSD):", ussd_balance);
String ussd_phone_num = modem.sendUSSD("*161#"); String ussd_phone_num = modem.sendUSSD("*161#");
DBG("Phone number (USSD):", ussd_phone_num); DBG("Phone number (USSD):", ussd_phone_num);
#endif
#if defined(TINY_GSM_MODEM_SIM808) #if defined(TINY_GSM_MODEM_HAS_GPS)
modem.enableGPS(); modem.enableGPS();
String gps_raw = modem.getGPSraw(); String gps_raw = modem.getGPSraw();
modem.disableGPS(); modem.disableGPS();
DBG("GPS raw data:", gps_raw); DBG("GPS raw data:", gps_raw);
#endif #endif
#if defined(SMS_TARGET) #if TINY_GSM_USE_SMS && defined(SMS_TARGET)
res = modem.sendSMS(SMS_TARGET, String("Hello from ") + imei); res = modem.sendSMS(SMS_TARGET, String("Hello from ") + imei);
DBG("SMS:", res ? "OK" : "fail"); DBG("SMS:", res ? "OK" : "fail");
@@ -157,7 +187,7 @@ void loop() {
DBG("UTF16 SMS:", res ? "OK" : "fail"); DBG("UTF16 SMS:", res ? "OK" : "fail");
#endif #endif
#if defined(CALL_TARGET) #if TINY_GSM_USE_CALL && defined(CALL_TARGET)
DBG("Calling:", CALL_TARGET); DBG("Calling:", CALL_TARGET);
// This is NOT supported on M590 // This is NOT supported on M590
@@ -182,21 +212,24 @@ void loop() {
} }
#endif #endif
#if TINY_GSM_USE_GPRS
modem.gprsDisconnect(); modem.gprsDisconnect();
if (!modem.isGprsConnected()) { if (!modem.isGprsConnected()) {
DBG("GPRS disconnected"); DBG("GPRS disconnected");
} else { } else {
DBG("GPRS disconnect: Failed."); DBG("GPRS disconnect: Failed.");
} }
#endif
#if TINY_GSM_POWERDOWN
// Try to power-off (modem may decide to restart automatically) // Try to power-off (modem may decide to restart automatically)
// To turn off modem completely, please use Reset/Enable pins // To turn off modem completely, please use Reset/Enable pins
modem.poweroff(); modem.poweroff();
DBG("Poweroff."); DBG("Poweroff.");
#endif
// Do nothing forevermore // Do nothing forevermore
while (true) { while (true) {
modem.maintain(); modem.maintain();
} }
} }

View File

@@ -4,7 +4,7 @@
* https://github.com/blynkkk/blynk-library/releases/latest * https://github.com/blynkkk/blynk-library/releases/latest
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
************************************************************** **************************************************************
* *
@@ -30,13 +30,18 @@
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 #define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266 // #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE // #define TINY_GSM_MODEM_XBEE
@@ -95,4 +100,3 @@ void loop()
{ {
Blynk.run(); Blynk.run();
} }

View File

@@ -5,7 +5,7 @@
* or from http://librarymanager/all#CRC32+checksum * or from http://librarymanager/all#CRC32+checksum
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
* ATTENTION! Downloading big files requires of knowledge of * ATTENTION! Downloading big files requires of knowledge of
* the TinyGSM internals and some modem specifics, * the TinyGSM internals and some modem specifics,
@@ -15,13 +15,18 @@
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 #define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266 // #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE // #define TINY_GSM_MODEM_XBEE
@@ -204,4 +209,3 @@ void loop() {
delay(1000); delay(1000);
} }
} }

View File

@@ -8,25 +8,43 @@
* or from http://librarymanager/all#ArduinoHttpClient * or from http://librarymanager/all#ArduinoHttpClient
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
* For more HTTP API examples, see ArduinoHttpClient library * For more HTTP API examples, see ArduinoHttpClient library
* *
* NOTE: This example does NOT work with the XBee because the
* HttpClient library does not empty to serial buffer fast enough
* and the buffer overflow causes the HttpClient library to stall.
**************************************************************/ **************************************************************/
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 #define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266 // #define TINY_GSM_MODEM_ESP8266
// Increase RX buffer if needed // Increase RX buffer to capture the entire response
//#define TINY_GSM_RX_BUFFER 512 // Chips without internal buffering (A6/A7, ESP8266, M590)
// need enough space in the buffer for the entire response
// else data will be lost (and the http library will fail).
#define TINY_GSM_RX_BUFFER 650
// See the debugging, if wanted
//#define TINY_GSM_DEBUG Serial
//#define LOGGING
// Add a reception delay, if needed
//#define TINY_GSM_YIELD() { delay(1); }
#include <TinyGsmClient.h> #include <TinyGsmClient.h>
#include <ArduinoHttpClient.h> #include <ArduinoHttpClient.h>
@@ -48,8 +66,10 @@
// Your GPRS credentials // Your GPRS credentials
// Leave empty, if missing user or pass // Leave empty, if missing user or pass
const char apn[] = "YourAPN"; const char apn[] = "YourAPN";
const char user[] = ""; const char gprsUser[] = "";
const char pass[] = ""; const char gprsPass[] = "";
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "SSIDpw";
// Server details // Server details
const char server[] = "vsh.pp.ua"; const char server[] = "vsh.pp.ua";
@@ -71,6 +91,7 @@ void setup() {
// Set console baud rate // Set console baud rate
SerialMon.begin(115200); SerialMon.begin(115200);
delay(10); delay(10);
SerialMon.println(F("Wait..."));
// Set GSM module baud rate // Set GSM module baud rate
SerialAT.begin(115200); SerialAT.begin(115200);
@@ -90,6 +111,17 @@ void setup() {
} }
void loop() { void loop() {
if (modem.hasWifi()) {
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" OK");
}
SerialMon.print(F("Waiting for network...")); SerialMon.print(F("Waiting for network..."));
if (!modem.waitForNetwork()) { if (!modem.waitForNetwork()) {
SerialMon.println(" fail"); SerialMon.println(" fail");
@@ -98,14 +130,16 @@ void loop() {
} }
SerialMon.println(" OK"); SerialMon.println(" OK");
SerialMon.print(F("Connecting to ")); if (modem.hasGPRS()) {
SerialMon.print(apn); SerialMon.print(F("Connecting to "));
if (!modem.gprsConnect(apn, user, pass)) { SerialMon.print(apn);
SerialMon.println(" fail"); if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
delay(10000); SerialMon.println(" fail");
return; delay(10000);
return;
}
SerialMon.println(" OK");
} }
SerialMon.println(" OK");
SerialMon.print(F("Performing HTTP GET request... ")); SerialMon.print(F("Performing HTTP GET request... "));
int err = http.get(resource); int err = http.get(resource);
@@ -116,16 +150,18 @@ void loop() {
} }
int status = http.responseStatusCode(); int status = http.responseStatusCode();
SerialMon.print(F("Response status code: "));
SerialMon.println(status); SerialMon.println(status);
if (!status) { if (!status) {
delay(10000); delay(10000);
return; return;
} }
SerialMon.println(F("Response Headers:"));
while (http.headerAvailable()) { while (http.headerAvailable()) {
String headerName = http.readHeaderName(); String headerName = http.readHeaderName();
String headerValue = http.readHeaderValue(); String headerValue = http.readHeaderValue();
//SerialMon.println(headerName + " : " + headerValue); SerialMon.println(" " + headerName + " : " + headerValue);
} }
int length = http.contentLength(); int length = http.contentLength();
@@ -157,4 +193,3 @@ void loop() {
delay(1000); delay(1000);
} }
} }

View File

@@ -8,9 +8,9 @@
* or from http://librarymanager/all#ArduinoHttpClient * or from http://librarymanager/all#ArduinoHttpClient
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
* SSL/TLS is currently supported only with: SIM8xx, uBlox * SSL/TLS is currently supported only with: SIM8xx, uBlox, ESP8266
* *
* For more HTTP API examples, see ArduinoHttpClient library * For more HTTP API examples, see ArduinoHttpClient library
* *
@@ -19,10 +19,22 @@
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 #define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808 // #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_ESP8266
// Increase RX buffer if needed // Increase RX buffer to capture the entire response
//#define TINY_GSM_RX_BUFFER 512 // Chips without internal buffering (ESP8266)
// need enough space in the buffer for the entire response
// else data will be lost (and the http library will fail).
#define TINY_GSM_RX_BUFFER 650
// See the debugging, if wanted
//#define TINY_GSM_DEBUG Serial
//#define LOGGING
// Add a reception delay, if needed
//#define TINY_GSM_YIELD() { delay(1); }
#include <TinyGsmClient.h> #include <TinyGsmClient.h>
#include <ArduinoHttpClient.h> #include <ArduinoHttpClient.h>
@@ -44,8 +56,10 @@
// Your GPRS credentials // Your GPRS credentials
// Leave empty, if missing user or pass // Leave empty, if missing user or pass
const char apn[] = "YourAPN"; const char apn[] = "YourAPN";
const char user[] = ""; const char gprsUser[] = "";
const char pass[] = ""; const char gprsPass[] = "";
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "SSIDpw";
// Server details // Server details
const char server[] = "vsh.pp.ua"; const char server[] = "vsh.pp.ua";
@@ -67,6 +81,7 @@ void setup() {
// Set console baud rate // Set console baud rate
SerialMon.begin(115200); SerialMon.begin(115200);
delay(10); delay(10);
SerialMon.println(F("Wait..."));
// Set GSM module baud rate // Set GSM module baud rate
SerialAT.begin(115200); SerialAT.begin(115200);
@@ -91,6 +106,17 @@ void setup() {
} }
void loop() { void loop() {
if (modem.hasWifi()) {
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" OK");
}
SerialMon.print(F("Waiting for network...")); SerialMon.print(F("Waiting for network..."));
if (!modem.waitForNetwork()) { if (!modem.waitForNetwork()) {
SerialMon.println(" fail"); SerialMon.println(" fail");
@@ -99,14 +125,16 @@ void loop() {
} }
SerialMon.println(" OK"); SerialMon.println(" OK");
SerialMon.print(F("Connecting to ")); if (modem.hasGPRS()) {
SerialMon.print(apn); SerialMon.print(F("Connecting to "));
if (!modem.gprsConnect(apn, user, pass)) { SerialMon.print(apn);
SerialMon.println(" fail"); if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
delay(10000); SerialMon.println(" fail");
return; delay(10000);
return;
}
SerialMon.println(" OK");
} }
SerialMon.println(" OK");
SerialMon.print(F("Performing HTTPS GET request... ")); SerialMon.print(F("Performing HTTPS GET request... "));
http.connectionKeepAlive(); // Currently, this is needed for HTTPS http.connectionKeepAlive(); // Currently, this is needed for HTTPS
@@ -118,16 +146,18 @@ void loop() {
} }
int status = http.responseStatusCode(); int status = http.responseStatusCode();
SerialMon.print(F("Response status code: "));
SerialMon.println(status); SerialMon.println(status);
if (!status) { if (!status) {
delay(10000); delay(10000);
return; return;
} }
SerialMon.println(F("Response Headers:"));
while (http.headerAvailable()) { while (http.headerAvailable()) {
String headerName = http.readHeaderName(); String headerName = http.readHeaderName();
String headerValue = http.readHeaderValue(); String headerValue = http.readHeaderValue();
//SerialMon.println(headerName + " : " + headerValue); SerialMon.println(" " + headerName + " : " + headerValue);
} }
int length = http.contentLength(); int length = http.contentLength();
@@ -159,4 +189,3 @@ void loop() {
delay(1000); delay(1000);
} }
} }

View File

@@ -5,7 +5,7 @@
* or from http://librarymanager/all#PubSubClient * or from http://librarymanager/all#PubSubClient
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
* For more MQTT examples, see PubSubClient library * For more MQTT examples, see PubSubClient library
* *
@@ -29,13 +29,18 @@
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 #define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266 // #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE // #define TINY_GSM_MODEM_XBEE
@@ -171,4 +176,3 @@ void mqttCallback(char* topic, byte* payload, unsigned int len) {
mqtt.publish(topicLedStatus, ledStatus ? "1" : "0"); mqtt.publish(topicLedStatus, ledStatus ? "1" : "0");
} }
} }

View File

@@ -4,24 +4,37 @@
* It can be used to perform HTTP/RESTful API calls. * It can be used to perform HTTP/RESTful API calls.
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
**************************************************************/ **************************************************************/
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 #define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266 // #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
// Increase RX buffer if needed // Increase RX buffer if needed
//#define TINY_GSM_RX_BUFFER 512 //#define TINY_GSM_RX_BUFFER 512
// See the debugging, if wanted
//#define TINY_GSM_DEBUG Serial
//#define LOGGING
// Add a reception delay, if needed
//#define TINY_GSM_YIELD() { delay(1); }
#include <TinyGsmClient.h> #include <TinyGsmClient.h>
// Uncomment this if you want to see all AT commands // Uncomment this if you want to see all AT commands
@@ -44,8 +57,10 @@
// Your GPRS credentials // Your GPRS credentials
// Leave empty, if missing user or pass // Leave empty, if missing user or pass
const char apn[] = "YourAPN"; const char apn[] = "YourAPN";
const char user[] = ""; const char gprsUser[] = "";
const char pass[] = ""; const char gprsPass[] = "";
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "SSIDpw";
// Server details // Server details
const char server[] = "vsh.pp.ua"; const char server[] = "vsh.pp.ua";
@@ -71,9 +86,13 @@ void setup() {
// Set console baud rate // Set console baud rate
SerialMon.begin(115200); SerialMon.begin(115200);
delay(10); delay(10);
SerialMon.println(F("Wait..."));
pinMode(23, OUTPUT);
digitalWrite(23, LOW);
// Set GSM module baud rate // Set GSM module baud rate
SerialAT.begin(115200); SerialAT.begin(9600);
delay(3000); delay(3000);
// Restart takes quite some time // Restart takes quite some time
@@ -90,6 +109,26 @@ void setup() {
} }
void loop() { void loop() {
if (modem.hasWifi()) {
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" OK");
}
else if (modem.getModemName().indexOf("XBee") >= 0) {
SerialMon.print(F("Setting APN"));
if (!modem.gprsConnect(apn)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" OK");
}
SerialMon.print(F("Waiting for network...")); SerialMon.print(F("Waiting for network..."));
if (!modem.waitForNetwork()) { if (!modem.waitForNetwork()) {
SerialMon.println(" fail"); SerialMon.println(" fail");
@@ -98,14 +137,16 @@ void loop() {
} }
SerialMon.println(" OK"); SerialMon.println(" OK");
SerialMon.print(F("Connecting to ")); if (modem.hasGPRS()) {
SerialMon.print(apn); SerialMon.print(F("Connecting to "));
if (!modem.gprsConnect(apn, user, pass)) { SerialMon.print(apn);
SerialMon.println(" fail"); if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
delay(10000); SerialMon.println(" fail");
return; delay(10000);
return;
}
SerialMon.println(" OK");
} }
SerialMon.println(" OK");
SerialMon.print(F("Connecting to ")); SerialMon.print(F("Connecting to "));
SerialMon.print(server); SerialMon.print(server);
@@ -137,12 +178,17 @@ void loop() {
client.stop(); client.stop();
SerialMon.println(F("Server disconnected")); SerialMon.println(F("Server disconnected"));
modem.gprsDisconnect(); if (modem.hasWifi()) {
SerialMon.println(F("GPRS disconnected")); modem.networkDisconnect();
SerialMon.println(F("WiFi disconnected"));
}
else {
modem.gprsDisconnect();
SerialMon.println(F("GPRS disconnected"));
}
// Do nothing forevermore // Do nothing forevermore
while (true) { while (true) {
delay(1000); delay(1000);
} }
} }

View File

@@ -4,7 +4,7 @@
* It can be used to perform HTTP/RESTful API calls. * It can be used to perform HTTP/RESTful API calls.
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
**************************************************************/ **************************************************************/

View File

@@ -8,7 +8,7 @@
* or from http://librarymanager/all#ArduinoHttpClient * or from http://librarymanager/all#ArduinoHttpClient
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
* For more HTTP API examples, see ArduinoHttpClient library * For more HTTP API examples, see ArduinoHttpClient library
* *

View File

@@ -3,7 +3,7 @@
* This sketch uploads SSL certificates to the SIM8xx * This sketch uploads SSL certificates to the SIM8xx
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
**************************************************************/ **************************************************************/

View File

@@ -1,14 +1,16 @@
{ {
"name": "TinyGSM", "name": "TinyGSM",
"version": "0.3.5", "version": "0.6.1",
"description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900, SIM900A, SIM900D, SIM908, SIM968", "description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports many GSM, LTE, and WiFi modules with AT command interfaces.",
"keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968", "keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM7000, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968, M95, MC60, MC60E, BG96, ublox, Quectel, SIMCOM, AI Thinker, LTE, LTE-M",
"authors": "authors":
{ [
{
"name": "Volodymyr Shymanskyy", "name": "Volodymyr Shymanskyy",
"url": "https://github.com/vshymanskyy", "url": "https://github.com/vshymanskyy",
"maintainer": true "maintainer": true
}, }
],
"repository": "repository":
{ {
"type": "git", "type": "git",

View File

@@ -1,9 +1,9 @@
name=TinyGSM name=TinyGSM
version=0.3.5 version=0.6.1
author=Volodymyr Shymanskyy author=Volodymyr Shymanskyy
maintainer=Volodymyr Shymanskyy maintainer=Volodymyr Shymanskyy
sentence=A small Arduino library for GPRS modules, that just works. sentence=A small Arduino library for GPRS modules, that just works.
paragraph=Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968 paragraph=Includes examples for Blynk, MQTT, File Download, and Web Client. Supports many GSM, LTE, and WiFi modules with AT command interfaces.
category=Communication category=Communication
url=https://github.com/vshymanskyy/TinyGSM url=https://github.com/vshymanskyy/TinyGSM
architectures=* architectures=*

View File

@@ -9,16 +9,9 @@
#ifndef TinyGsmClient_h #ifndef TinyGsmClient_h
#define TinyGsmClient_h #define TinyGsmClient_h
#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM868) || defined(TINY_GSM_MODEM_UBLOX) || defined(TINY_GSM_MODEM_ESP8266) #if defined(TINY_GSM_MODEM_SIM800)
#define TINY_GSM_MODEM_HAS_SSL
#endif
#if defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868) || defined(TINY_GSM_MODEM_A7)
#define TINY_GSM_MODEM_HAS_GPS
#endif
#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900)
#define TINY_GSM_MODEM_HAS_GPRS #define TINY_GSM_MODEM_HAS_GPRS
#define TINY_GSM_MODEM_HAS_SSL
#include <TinyGsmClientSIM800.h> #include <TinyGsmClientSIM800.h>
typedef TinyGsmSim800 TinyGsm; typedef TinyGsmSim800 TinyGsm;
typedef TinyGsmSim800::GsmClient TinyGsmClient; typedef TinyGsmSim800::GsmClient TinyGsmClient;
@@ -26,18 +19,41 @@
#elif defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868) #elif defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868)
#define TINY_GSM_MODEM_HAS_GPRS #define TINY_GSM_MODEM_HAS_GPRS
#define TINY_GSM_MODEM_HAS_SSL
#define TINY_GSM_MODEM_HAS_GPS
#include <TinyGsmClientSIM808.h> #include <TinyGsmClientSIM808.h>
typedef TinyGsmSim808 TinyGsm; typedef TinyGsmSim808 TinyGsm;
typedef TinyGsmSim808::GsmClient TinyGsmClient; typedef TinyGsmSim808::GsmClient TinyGsmClient;
typedef TinyGsmSim808::GsmClientSecure TinyGsmClientSecure; typedef TinyGsmSim808::GsmClientSecure TinyGsmClientSecure;
#elif defined(TINY_GSM_MODEM_SIM900)
#define TINY_GSM_MODEM_HAS_GPRS
#include <TinyGsmClientSIM800.h>
typedef TinyGsmSim800 TinyGsm;
typedef TinyGsmSim800::GsmClient TinyGsmClient;
#elif defined(TINY_GSM_MODEM_SIM7000)
#define TINY_GSM_MODEM_HAS_GPRS
#define TINY_GSM_MODEM_HAS_GPS
#include <TinyGsmClientSIM7000.h>
typedef TinyGsmSim7000 TinyGsm;
typedef TinyGsmSim7000::GsmClient TinyGsmClient;
typedef TinyGsmSim7000::GsmClientSecure TinyGsmClientSecure;
#elif defined(TINY_GSM_MODEM_UBLOX) #elif defined(TINY_GSM_MODEM_UBLOX)
#define TINY_GSM_MODEM_HAS_GPRS #define TINY_GSM_MODEM_HAS_GPRS
#define TINY_GSM_MODEM_HAS_SSL
#include <TinyGsmClientUBLOX.h> #include <TinyGsmClientUBLOX.h>
typedef TinyGsmUBLOX TinyGsm; typedef TinyGsmUBLOX TinyGsm;
typedef TinyGsmUBLOX::GsmClient TinyGsmClient; typedef TinyGsmUBLOX::GsmClient TinyGsmClient;
typedef TinyGsmUBLOX::GsmClientSecure TinyGsmClientSecure; typedef TinyGsmUBLOX::GsmClientSecure TinyGsmClientSecure;
#elif defined(TINY_GSM_MODEM_M95)
#define TINY_GSM_MODEM_HAS_GPRS
#include <TinyGsmClientM95.h>
typedef TinyGsmM95 TinyGsm;
typedef TinyGsmM95::GsmClient TinyGsmClient;
#elif defined(TINY_GSM_MODEM_BG96) #elif defined(TINY_GSM_MODEM_BG96)
#define TINY_GSM_MODEM_HAS_GPRS #define TINY_GSM_MODEM_HAS_GPRS
#include <TinyGsmClientBG96.h> #include <TinyGsmClientBG96.h>
@@ -56,8 +72,16 @@
typedef TinyGsmM590 TinyGsm; typedef TinyGsmM590 TinyGsm;
typedef TinyGsmM590::GsmClient TinyGsmClient; typedef TinyGsmM590::GsmClient TinyGsmClient;
#elif defined(TINY_GSM_MODEM_MC60) || defined(TINY_GSM_MODEM_MC60E)
#include <TinyGsmClientMC60.h>
#define TINY_GSM_MODEM_HAS_GPRS
#define TINY_GSM_MODEM_HAS_GPS
typedef TinyGsmMC60 TinyGsm;
typedef TinyGsmMC60::GsmClient TinyGsmClient;
#elif defined(TINY_GSM_MODEM_ESP8266) #elif defined(TINY_GSM_MODEM_ESP8266)
#define TINY_GSM_MODEM_HAS_WIFI #define TINY_GSM_MODEM_HAS_WIFI
#define TINY_GSM_MODEM_HAS_SSL
#include <TinyGsmClientESP8266.h> #include <TinyGsmClientESP8266.h>
typedef TinyGsmESP8266 TinyGsm; typedef TinyGsmESP8266 TinyGsm;
typedef TinyGsmESP8266::GsmClient TinyGsmClient; typedef TinyGsmESP8266::GsmClient TinyGsmClient;
@@ -66,6 +90,7 @@
#elif defined(TINY_GSM_MODEM_XBEE) #elif defined(TINY_GSM_MODEM_XBEE)
#define TINY_GSM_MODEM_HAS_GPRS #define TINY_GSM_MODEM_HAS_GPRS
#define TINY_GSM_MODEM_HAS_WIFI #define TINY_GSM_MODEM_HAS_WIFI
#define TINY_GSM_MODEM_HAS_SSL
#include <TinyGsmClientXBee.h> #include <TinyGsmClientXBee.h>
typedef TinyGsmXBee TinyGsm; typedef TinyGsmXBee TinyGsm;
typedef TinyGsmXBee::GsmClient TinyGsmClient; typedef TinyGsmXBee::GsmClient TinyGsmClient;

View File

@@ -8,13 +8,10 @@
#ifndef TinyGsmClientA6_h #ifndef TinyGsmClientA6_h
#define TinyGsmClientA6_h #define TinyGsmClientA6_h
//#pragma message("TinyGSM: TinyGsmClientA6")
//#define TINY_GSM_DEBUG Serial //#define TINY_GSM_DEBUG Serial
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 256
#endif
#define TINY_GSM_MUX_COUNT 8 #define TINY_GSM_MUX_COUNT 8
#include <TinyGsmCommon.h> #include <TinyGsmCommon.h>
@@ -38,22 +35,10 @@ enum RegStatus {
REG_UNKNOWN = 4, REG_UNKNOWN = 4,
}; };
//============================================================================//
//============================================================================//
// Declaration of the TinyGsmA6 Class
//============================================================================//
//============================================================================//
class TinyGsmA6 class TinyGsmA6 : public TinyGsmModem
{ {
//============================================================================//
//============================================================================//
// The Internal A6 Client Class
//============================================================================//
//============================================================================//
public: public:
class GsmClient : public Client class GsmClient : public Client
@@ -127,7 +112,7 @@ public:
virtual int available() { virtual int available() {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
if (!rx.size() && sock_connected) { if (!rx.size()) {
at->maintain(); at->maintain();
} }
return rx.size(); return rx.size();
@@ -136,7 +121,8 @@ public:
virtual int read(uint8_t *buf, size_t size) { virtual int read(uint8_t *buf, size_t size) {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
size_t cnt = 0; size_t cnt = 0;
while (cnt < size) { uint32_t _startMillis = millis();
while (cnt < size && millis() - _startMillis < _timeout) {
size_t chunk = TinyGsmMin(size-cnt, rx.size()); size_t chunk = TinyGsmMin(size-cnt, rx.size());
if (chunk > 0) { if (chunk > 0) {
rx.get(buf, chunk); rx.get(buf, chunk);
@@ -147,7 +133,6 @@ public:
// TODO: Read directly into user buffer? // TODO: Read directly into user buffer?
if (!rx.size() && sock_connected) { if (!rx.size() && sock_connected) {
at->maintain(); at->maintain();
//break;
} }
} }
return cnt; return cnt;
@@ -185,28 +170,11 @@ private:
RxFifo rx; RxFifo rx;
}; };
//============================================================================//
//============================================================================//
// The A6 does not have a secure client!
//============================================================================//
//============================================================================//
//============================================================================//
//============================================================================//
// The A6 Modem Functions
//============================================================================//
//============================================================================//
public: public:
#ifdef GSM_DEFAULT_STREAM
TinyGsmA6(Stream& stream = GSM_DEFAULT_STREAM)
#else
TinyGsmA6(Stream& stream) TinyGsmA6(Stream& stream)
#endif : TinyGsmModem(stream), stream(stream)
: stream(stream)
{ {
memset(sockets, 0, sizeof(sockets)); memset(sockets, 0, sizeof(sockets));
} }
@@ -214,11 +182,9 @@ public:
/* /*
* Basic functions * Basic functions
*/ */
bool begin() {
return init();
}
bool init() { bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) { if (!testAT()) {
return false; return false;
} }
@@ -226,16 +192,24 @@ public:
if (waitResponse() != 1) { if (waitResponse() != 1) {
return false; return false;
} }
sendAT(GF("+CMEE=0")); sendAT(GF("+CMEE=0")); // Turn off verbose errors
waitResponse(); waitResponse();
sendAT(GF("+CMER=3,0,0,2")); // Set unsolicited result code output destination
sendAT(GF("+CMER=3,0,0,2"));
waitResponse(); waitResponse();
DBG(GF("### Modem:"), getModemName());
getSimStatus(); getSimStatus();
return true; return true;
} }
String getModemName() {
#if defined(TINY_GSM_MODEM_A6)
return "AI-Thinker A6";
#elif defined(TINY_GSM_MODEM_A7)
return "AI-Thinker A7";
#endif
return "AI-Thinker A6";
}
void setBaud(unsigned long baud) { void setBaud(unsigned long baud) {
sendAT(GF("+IPR="), baud); sendAT(GF("+IPR="), baud);
} }
@@ -243,10 +217,7 @@ public:
bool testAT(unsigned long timeout = 10000L) { bool testAT(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) { for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF("")); sendAT(GF(""));
if (waitResponse(200) == 1) { if (waitResponse(200) == 1) return true;
delay(100);
return true;
}
delay(100); delay(100);
} }
return false; return false;
@@ -279,6 +250,14 @@ public:
return false; return false;
} }
bool hasWifi() {
return false;
}
bool hasGPRS() {
return true;
}
/* /*
* Power functions * Power functions
*/ */
@@ -380,7 +359,7 @@ public:
* Generic network functions * Generic network functions
*/ */
int getSignalQuality() { int16_t getSignalQuality() {
sendAT(GF("+CSQ")); sendAT(GF("+CSQ"));
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
return 99; return 99;
@@ -395,20 +374,6 @@ public:
return (s == REG_OK_HOME || s == REG_OK_ROAMING); return (s == REG_OK_HOME || s == REG_OK_ROAMING);
} }
bool waitForNetwork(unsigned long timeout = 60000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
if (isNetworkConnected()) {
return true;
}
delay(250);
}
return false;
}
/*
* WiFi functions
*/
/* /*
* GPRS functions * GPRS functions
*/ */
@@ -467,6 +432,10 @@ public:
return (res == 1); return (res == 1);
} }
/*
* IP Address functions
*/
String getLocalIP() { String getLocalIP() {
sendAT(GF("+CIFSR")); sendAT(GF("+CIFSR"));
String res; String res;
@@ -479,10 +448,6 @@ public:
return res; return res;
} }
IPAddress localIP() {
return TinyGsmIpFromString(getLocalIP());
}
/* /*
* Phone Call functions * Phone Call functions
*/ */
@@ -621,7 +586,7 @@ public:
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
int getBattPercent() { int8_t getBattPercent() {
sendAT(GF("+CBC?")); sendAT(GF("+CBC?"));
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
return false; return false;
@@ -632,6 +597,10 @@ public:
return res; return res;
} }
/*
* Client related functions
*/
protected: protected:
bool modemConnect(const char* host, uint16_t port, uint8_t* mux) { bool modemConnect(const char* host, uint16_t port, uint8_t* mux) {
@@ -654,7 +623,7 @@ protected:
return (1 == rsp); return (1 == rsp);
} }
int modemSend(const void* buff, size_t len, uint8_t mux) { int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+CIPSEND="), mux, ',', len); sendAT(GF("+CIPSEND="), mux, ',', len);
if (waitResponse(2000L, GF(GSM_NL ">")) != 1) { if (waitResponse(2000L, GF(GSM_NL ">")) != 1) {
return 0; return 0;
@@ -676,31 +645,9 @@ protected:
public: public:
/* Utilities */ /*
Utilities
template<typename T> */
void streamWrite(T last) {
stream.print(last);
}
template<typename T, typename... Args>
void streamWrite(T head, Args... tail) {
stream.print(head);
streamWrite(tail...);
}
bool streamSkipUntil(char c) {
const unsigned long timeout = 1000L;
unsigned long startMillis = millis();
while (millis() - startMillis < timeout) {
while (millis() - startMillis < timeout && !stream.available()) {
TINY_GSM_YIELD();
}
if (stream.read() == c)
return true;
}
return false;
}
template<typename... Args> template<typename... Args>
void sendAT(Args... cmd) { void sendAT(Args... cmd) {

View File

@@ -8,14 +8,11 @@
#ifndef TinyGsmClientBG96_h #ifndef TinyGsmClientBG96_h
#define TinyGsmClientBG96_h #define TinyGsmClientBG96_h
//#pragma message("TinyGSM: TinyGsmClientBG96")
//#define TINY_GSM_DEBUG Serial //#define TINY_GSM_DEBUG Serial
//#define TINY_GSM_USE_HEX //#define TINY_GSM_USE_HEX
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 64
#endif
#define TINY_GSM_MUX_COUNT 12 #define TINY_GSM_MUX_COUNT 12
#include <TinyGsmCommon.h> #include <TinyGsmCommon.h>
@@ -39,22 +36,10 @@ enum RegStatus {
REG_UNKNOWN = 4, REG_UNKNOWN = 4,
}; };
//============================================================================//
//============================================================================//
// Declaration of the TinyGsmBG96 Class
//============================================================================//
//============================================================================//
class TinyGsmBG96 class TinyGsmBG96 : public TinyGsmModem
{ {
//============================================================================//
//============================================================================//
// The Internal BG96 Client Class
//============================================================================//
//============================================================================//
public: public:
class GsmClient : public Client class GsmClient : public Client
@@ -104,10 +89,21 @@ public:
virtual void stop() { virtual void stop() {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
// Read and dump anything remaining in the modem's internal buffer.
// The socket will appear open in response to connected() even after it
// closes until all data is read from the buffer.
// Doing it this way allows the external mcu to find and get all of the data
// that it wants from the socket even if it was closed externally.
rx.clear();
at->maintain();
while (sock_available > 0) {
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
rx.clear();
at->maintain();
}
at->sendAT(GF("+QICLOSE="), mux); at->sendAT(GF("+QICLOSE="), mux);
sock_connected = false; sock_connected = false;
at->waitResponse(); at->waitResponse();
rx.clear();
} }
virtual size_t write(const uint8_t *buf, size_t size) { virtual size_t write(const uint8_t *buf, size_t size) {
@@ -190,46 +186,31 @@ private:
RxFifo rx; RxFifo rx;
}; };
//============================================================================//
//============================================================================//
// The BG96 Secure Client
//============================================================================//
//============================================================================//
// class GsmClientSecure : public GsmClient
// {
// public:
// GsmClientSecure() {}
//
// GsmClientSecure(TinyGsmBG96& modem, uint8_t mux = 1)
// : GsmClient(modem, mux)
// {}
//
// public:
// virtual int connect(const char *host, uint16_t port) {
// stop();
// TINY_GSM_YIELD();
// rx.clear();
// sock_connected = at->modemConnect(host, port, mux, true);
// return sock_connected;
// }
// };
class GsmClientSecure : public GsmClient
{
public:
GsmClientSecure() {}
GsmClientSecure(TinyGsmBG96& modem, uint8_t mux = 1)
: GsmClient(modem, mux)
{}
public:
virtual int connect(const char *host, uint16_t port) {
stop();
TINY_GSM_YIELD();
rx.clear();
sock_connected = at->modemConnect(host, port, mux, true);
return sock_connected;
}
};
//============================================================================//
//============================================================================//
// The BG96 Modem Functions
//============================================================================//
//============================================================================//
public: public:
#ifdef GSM_DEFAULT_STREAM
TinyGsmBG96(Stream& stream = GSM_DEFAULT_STREAM)
#else
TinyGsmBG96(Stream& stream) TinyGsmBG96(Stream& stream)
#endif : TinyGsmModem(stream), stream(stream)
: stream(stream)
{ {
memset(sockets, 0, sizeof(sockets)); memset(sockets, 0, sizeof(sockets));
} }
@@ -237,11 +218,9 @@ public:
/* /*
* Basic functions * Basic functions
*/ */
bool begin() {
return init();
}
bool init() { bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) { if (!testAT()) {
return false; return false;
} }
@@ -249,10 +228,15 @@ public:
if (waitResponse() != 1) { if (waitResponse() != 1) {
return false; return false;
} }
DBG(GF("### Modem:"), getModemName());
getSimStatus(); getSimStatus();
return true; return true;
} }
String getModemName() {
return "Quectel BG96";
}
void setBaud(unsigned long baud) { void setBaud(unsigned long baud) {
sendAT(GF("+IPR="), baud); sendAT(GF("+IPR="), baud);
} }
@@ -260,10 +244,7 @@ public:
bool testAT(unsigned long timeout = 10000L) { bool testAT(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) { for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF("")); sendAT(GF(""));
if (waitResponse(200) == 1) { if (waitResponse(200) == 1) return true;
delay(100);
return true;
}
delay(100); delay(100);
} }
return false; return false;
@@ -307,6 +288,14 @@ public:
return false; // TODO: For now return false; // TODO: For now
} }
bool hasWifi() {
return false;
}
bool hasGPRS() {
return true;
}
/* /*
* Power functions * Power functions
*/ */
@@ -324,8 +313,9 @@ public:
} }
bool poweroff() { bool poweroff() {
sendAT(GF("+QPOWD")); sendAT(GF("+QPOWD=1"));
return waitResponse(GF("POWERED DOWN")) == 1; // TODO waitResponse(300); // returns OK first
return waitResponse(300, GF("POWERED DOWN")) == 1;
} }
bool radioOff() { bool radioOff() {
@@ -413,7 +403,7 @@ public:
* Generic network functions * Generic network functions
*/ */
int getSignalQuality() { int16_t getSignalQuality() {
sendAT(GF("+CSQ")); sendAT(GF("+CSQ"));
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
return 99; return 99;
@@ -428,42 +418,30 @@ public:
return (s == REG_OK_HOME || s == REG_OK_ROAMING); return (s == REG_OK_HOME || s == REG_OK_ROAMING);
} }
bool waitForNetwork(unsigned long timeout = 60000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
if (isNetworkConnected()) {
return true;
}
delay(250);
}
return false;
}
/*
* WiFi functions
*/
/* /*
* GPRS functions * GPRS functions
*/ */
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) { bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
gprsDisconnect(); gprsDisconnect();
//Configure the TCPIP Context
sendAT(GF("+QICSGP=1,1,\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\"")); sendAT(GF("+QICSGP=1,1,\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\""));
if (waitResponse() != 1) { if (waitResponse() != 1) {
return false; return false;
} }
//Activate GPRS/CSD Context
sendAT(GF("+QIACT=1")); sendAT(GF("+QIACT=1"));
if (waitResponse(150000L) != 1) { if (waitResponse(150000L) != 1) {
return false; return false;
} }
//Attach to Packet Domain service - is this necessary?
sendAT(GF("+CGATT=1")); sendAT(GF("+CGATT=1"));
if (waitResponse(60000L) != 1) { if (waitResponse(60000L) != 1) {
return false; return false;
} }
return true; return true;
} }
@@ -485,15 +463,16 @@ public:
if (res != 1) if (res != 1)
return false; return false;
return localIP() != 0; return localIP() != IPAddress(0,0,0,0);
} }
/*
* IP Address functions
*/
String getLocalIP() { String getLocalIP() {
sendAT(GF("+CGPADDR=1")); sendAT(GF("+QILOCIP"));
if (waitResponse(10000L, GF(GSM_NL "+CGPADDR:")) != 1) { stream.readStringUntil('\n');
return "";
}
streamSkipUntil(',');
String res = stream.readStringUntil('\n'); String res = stream.readStringUntil('\n');
if (waitResponse() != 1) { if (waitResponse() != 1) {
return ""; return "";
@@ -501,10 +480,6 @@ public:
return res; return res;
} }
IPAddress localIP() {
return TinyGsmIpFromString(getLocalIP());
}
/* /*
* Phone Call functions * Phone Call functions
*/ */
@@ -560,6 +535,8 @@ public:
bool sendSMS_UTF16(const String& number, const void* text, size_t len) { bool sendSMS_UTF16(const String& number, const void* text, size_t len) {
sendAT(GF("+CMGF=1")); sendAT(GF("+CMGF=1"));
waitResponse(); waitResponse();
sendAT(GF("+CSCS=\"HEX\""));
waitResponse();
sendAT(GF("+CSMP=17,167,0,8")); sendAT(GF("+CSMP=17,167,0,8"));
waitResponse(); waitResponse();
@@ -592,14 +569,42 @@ public:
/* /*
* Battery functions * Battery functions
*/ */
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_IMPLEMENTED;
int getBattPercent() TINY_GSM_ATTR_NOT_IMPLEMENTED; // Use: float vBatt = modem.getBattVoltage() / 1000.0;
uint16_t getBattVoltage() {
sendAT(GF("+CBC"));
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
return 0;
}
streamSkipUntil(','); // Skip
streamSkipUntil(','); // Skip
uint16_t res = stream.readStringUntil(',').toInt();
waitResponse();
return res;
}
int8_t getBattPercent() {
sendAT(GF("+CBC"));
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
return false;
}
stream.readStringUntil(',');
int res = stream.readStringUntil(',').toInt();
waitResponse();
return res;
}
/*
* Client related functions
*/
protected: protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
int rsp; int rsp;
// <PDPcontextID>(1-16), <connectID>(0-11),"TCP/UDP/TCP LISTENER/UDP SERVICE",
// "<IP_address>/<domain_name>",<remote_port>,<local_port>,<access_mode>(0-2 0=buffer)
sendAT(GF("+QIOPEN=1,"), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(",0,0")); sendAT(GF("+QIOPEN=1,"), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(",0,0"));
rsp = waitResponse(); rsp = waitResponse();
@@ -616,7 +621,7 @@ protected:
return (0 == rsp); return (0 == rsp);
} }
int modemSend(const void* buff, size_t len, uint8_t mux) { int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+QISEND="), mux, ',', len); sendAT(GF("+QISEND="), mux, ',', len);
if (waitResponse(GF(">")) != 1) { if (waitResponse(GF(">")) != 1) {
return 0; return 0;
@@ -685,31 +690,9 @@ protected:
public: public:
/* Utilities */ /*
Utilities
template<typename T> */
void streamWrite(T last) {
stream.print(last);
}
template<typename T, typename... Args>
void streamWrite(T head, Args... tail) {
stream.print(head);
streamWrite(tail...);
}
bool streamSkipUntil(char c) {
const unsigned long timeout = 1000L;
unsigned long startMillis = millis();
while (millis() - startMillis < timeout) {
while (millis() - startMillis < timeout && !stream.available()) {
TINY_GSM_YIELD();
}
if (stream.read() == c)
return true;
}
return false;
}
template<typename... Args> template<typename... Args>
void sendAT(Args... cmd) { void sendAT(Args... cmd) {

View File

@@ -8,13 +8,10 @@
#ifndef TinyGsmClientESP8266_h #ifndef TinyGsmClientESP8266_h
#define TinyGsmClientESP8266_h #define TinyGsmClientESP8266_h
//#pragma message("TinyGSM: TinyGsmClientESP8266")
//#define TINY_GSM_DEBUG Serial //#define TINY_GSM_DEBUG Serial
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 512
#endif
#define TINY_GSM_MUX_COUNT 5 #define TINY_GSM_MUX_COUNT 5
#include <TinyGsmCommon.h> #include <TinyGsmCommon.h>
@@ -38,22 +35,10 @@ enum RegStatus {
}; };
//============================================================================//
//============================================================================//
// Declaration of the TinyGsmESP8266 Class
//============================================================================//
//============================================================================//
class TinyGsmESP8266 : public TinyGsmModem
class TinyGsmESP8266
{ {
//============================================================================//
//============================================================================//
// The ESP8266 Internal Client Class
//============================================================================//
//============================================================================//
public: public:
class GsmClient : public Client class GsmClient : public Client
@@ -124,7 +109,7 @@ public:
virtual int available() { virtual int available() {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
if (!rx.size() && sock_connected) { if (!rx.size()) {
at->maintain(); at->maintain();
} }
return rx.size(); return rx.size();
@@ -133,7 +118,8 @@ public:
virtual int read(uint8_t *buf, size_t size) { virtual int read(uint8_t *buf, size_t size) {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
size_t cnt = 0; size_t cnt = 0;
while (cnt < size) { uint32_t _startMillis = millis();
while (cnt < size && millis() - _startMillis < _timeout) {
size_t chunk = TinyGsmMin(size-cnt, rx.size()); size_t chunk = TinyGsmMin(size-cnt, rx.size());
if (chunk > 0) { if (chunk > 0) {
rx.get(buf, chunk); rx.get(buf, chunk);
@@ -144,7 +130,6 @@ public:
// TODO: Read directly into user buffer? // TODO: Read directly into user buffer?
if (!rx.size() && sock_connected) { if (!rx.size() && sock_connected) {
at->maintain(); at->maintain();
//break;
} }
} }
return cnt; return cnt;
@@ -182,12 +167,6 @@ private:
RxFifo rx; RxFifo rx;
}; };
//============================================================================//
//============================================================================//
// The Secure ESP8266 Client Class
//============================================================================//
//============================================================================//
class GsmClientSecure : public GsmClient class GsmClientSecure : public GsmClient
{ {
@@ -209,20 +188,10 @@ public:
}; };
//============================================================================//
//============================================================================//
// The ESP8266 Modem Functions
//============================================================================//
//============================================================================//
public: public:
#ifdef GSM_DEFAULT_STREAM
TinyGsmESP8266(Stream& stream = GSM_DEFAULT_STREAM)
#else
TinyGsmESP8266(Stream& stream) TinyGsmESP8266(Stream& stream)
#endif : TinyGsmModem(stream), stream(stream)
: stream(stream)
{ {
memset(sockets, 0, sizeof(sockets)); memset(sockets, 0, sizeof(sockets));
} }
@@ -230,11 +199,9 @@ public:
/* /*
* Basic functions * Basic functions
*/ */
bool begin() {
return init();
}
bool init() { bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) { if (!testAT()) {
return false; return false;
} }
@@ -250,20 +217,22 @@ public:
if (waitResponse() != 1) { if (waitResponse() != 1) {
return false; return false;
} }
DBG(GF("### Modem:"), getModemName());
return true; return true;
} }
String getModemName() {
return "ESP8266";
}
void setBaud(unsigned long baud) { void setBaud(unsigned long baud) {
sendAT(GF("+IPR="), baud); sendAT(GF("+UART_CUR="), baud, "8,1,0,0");
} }
bool testAT(unsigned long timeout = 10000L) { bool testAT(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) { for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF("")); sendAT(GF(""));
if (waitResponse(200) == 1) { if (waitResponse(200) == 1) return true;
delay(100);
return true;
}
delay(100); delay(100);
} }
return false; return false;
@@ -294,6 +263,14 @@ public:
return true; return true;
} }
bool hasWifi() {
return true;
}
bool hasGPRS() {
return false;
}
/* /*
* Power functions * Power functions
*/ */
@@ -313,7 +290,10 @@ public:
return init(); return init();
} }
bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED; bool poweroff() {
sendAT(GF("+GSLP=0")); // Power down indefinitely - until manually reset!
return waitResponse() == 1;
}
bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED; bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
@@ -335,7 +315,7 @@ public:
* Generic network functions * Generic network functions
*/ */
int getSignalQuality() { int16_t getSignalQuality() {
sendAT(GF("+CWJAP_CUR?")); sendAT(GF("+CWJAP_CUR?"));
int res1 = waitResponse(GF("No AP"), GF("+CWJAP_CUR:")); int res1 = waitResponse(GF("No AP"), GF("+CWJAP_CUR:"));
if (res1 != 2) { if (res1 != 2) {
@@ -390,6 +370,10 @@ public:
return retVal; return retVal;
} }
/*
* IP Address functions
*/
String getLocalIP() { String getLocalIP() {
sendAT(GF("+CIPSTA_CUR??")); sendAT(GF("+CIPSTA_CUR??"));
int res1 = waitResponse(GF("ERROR"), GF("+CWJAP_CUR:")); int res1 = waitResponse(GF("ERROR"), GF("+CWJAP_CUR:"));
@@ -401,32 +385,10 @@ public:
return res2; return res2;
} }
IPAddress localIP() {
return TinyGsmIpFromString(getLocalIP());
}
/* /*
* GPRS functions * Client related functions
*/ */
/*
* Messaging functions
*/
/*
* Location functions
*/
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
/*
* Battery functions
*/
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
protected: protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
@@ -444,7 +406,7 @@ protected:
return (1 == rsp); return (1 == rsp);
} }
int modemSend(const void* buff, size_t len, uint8_t mux) { int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+CIPSEND="), mux, ',', len); sendAT(GF("+CIPSEND="), mux, ',', len);
if (waitResponse(GF(">")) != 1) { if (waitResponse(GF(">")) != 1) {
return 0; return 0;
@@ -464,31 +426,9 @@ protected:
public: public:
/* Utilities */ /*
Utilities
template<typename T> */
void streamWrite(T last) {
stream.print(last);
}
template<typename T, typename... Args>
void streamWrite(T head, Args... tail) {
stream.print(head);
streamWrite(tail...);
}
bool streamSkipUntil(char c) {
const unsigned long timeout = 1000L;
unsigned long startMillis = millis();
while (millis() - startMillis < timeout) {
while (millis() - startMillis < timeout && !stream.available()) {
TINY_GSM_YIELD();
}
if (stream.read() == c)
return true;
}
return false;
}
template<typename... Args> template<typename... Args>
void sendAT(Args... cmd) { void sendAT(Args... cmd) {

View File

@@ -8,13 +8,10 @@
#ifndef TinyGsmClientM590_h #ifndef TinyGsmClientM590_h
#define TinyGsmClientM590_h #define TinyGsmClientM590_h
//#pragma message("TinyGSM: TinyGsmClientM590")
//#define TINY_GSM_DEBUG Serial //#define TINY_GSM_DEBUG Serial
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 256
#endif
#define TINY_GSM_MUX_COUNT 2 #define TINY_GSM_MUX_COUNT 2
#include <TinyGsmCommon.h> #include <TinyGsmCommon.h>
@@ -39,22 +36,9 @@ enum RegStatus {
}; };
//============================================================================// class TinyGsmM590 : public TinyGsmModem
//============================================================================//
// Declaration of the TinyGsmM590 Class
//============================================================================//
//============================================================================//
class TinyGsmM590
{ {
//============================================================================//
//============================================================================//
// The M590 Internal Client Class
//============================================================================//
//============================================================================//
public: public:
class GsmClient : public Client class GsmClient : public Client
@@ -134,7 +118,8 @@ public:
virtual int read(uint8_t *buf, size_t size) { virtual int read(uint8_t *buf, size_t size) {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
size_t cnt = 0; size_t cnt = 0;
while (cnt < size) { uint32_t _startMillis = millis();
while (cnt < size && millis() - _startMillis < _timeout) {
size_t chunk = TinyGsmMin(size-cnt, rx.size()); size_t chunk = TinyGsmMin(size-cnt, rx.size());
if (chunk > 0) { if (chunk > 0) {
rx.get(buf, chunk); rx.get(buf, chunk);
@@ -143,9 +128,8 @@ public:
continue; continue;
} }
// TODO: Read directly into user buffer? // TODO: Read directly into user buffer?
if (!rx.size() && sock_connected) { if (!rx.size()) {
at->maintain(); at->maintain();
//break;
} }
} }
return cnt; return cnt;
@@ -183,28 +167,11 @@ private:
RxFifo rx; RxFifo rx;
}; };
//============================================================================//
//============================================================================//
// The M590 Has no Secure client!
//============================================================================//
//============================================================================//
//============================================================================//
//============================================================================//
// The M590 Modem Functions
//============================================================================//
//============================================================================//
public: public:
#ifdef GSM_DEFAULT_STREAM
TinyGsmM590(Stream& stream = GSM_DEFAULT_STREAM)
#else
TinyGsmM590(Stream& stream) TinyGsmM590(Stream& stream)
#endif : TinyGsmModem(stream), stream(stream)
: stream(stream)
{ {
memset(sockets, 0, sizeof(sockets)); memset(sockets, 0, sizeof(sockets));
} }
@@ -212,11 +179,9 @@ public:
/* /*
* Basic functions * Basic functions
*/ */
bool begin() {
return init();
}
bool init() { bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) { if (!testAT()) {
return false; return false;
} }
@@ -228,11 +193,15 @@ public:
sendAT(GF("+CMEE=2")); sendAT(GF("+CMEE=2"));
waitResponse(); waitResponse();
#endif #endif
DBG(GF("### Modem:"), getModemName());
getSimStatus(); getSimStatus();
return true; return true;
} }
String getModemName() {
return "Neoway M590";
}
void setBaud(unsigned long baud) { void setBaud(unsigned long baud) {
sendAT(GF("+IPR="), baud); sendAT(GF("+IPR="), baud);
} }
@@ -240,10 +209,7 @@ public:
bool testAT(unsigned long timeout = 10000L) { bool testAT(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) { for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF("")); sendAT(GF(""));
if (waitResponse(200) == 1) { if (waitResponse(200) == 1) return true;
delay(100);
return true;
}
delay(100); delay(100);
} }
return false; return false;
@@ -284,6 +250,14 @@ public:
return false; return false;
} }
bool hasWifi() {
return false;
}
bool hasGPRS() {
return true;
}
/* /*
* Power functions * Power functions
*/ */
@@ -389,7 +363,7 @@ public:
* Generic network functions * Generic network functions
*/ */
int getSignalQuality() { int16_t getSignalQuality() {
sendAT(GF("+CSQ")); sendAT(GF("+CSQ"));
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
return 99; return 99;
@@ -404,20 +378,6 @@ public:
return (s == REG_OK_HOME || s == REG_OK_ROAMING); return (s == REG_OK_HOME || s == REG_OK_ROAMING);
} }
bool waitForNetwork(unsigned long timeout = 60000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
if (isNetworkConnected()) {
return true;
}
delay(250);
}
return false;
}
/*
* WiFi functions
*/
/* /*
* GPRS functions * GPRS functions
*/ */
@@ -474,6 +434,10 @@ public:
return res == 1; return res == 1;
} }
/*
* IP Address functions
*/
String getLocalIP() { String getLocalIP() {
sendAT(GF("+XIIC?")); sendAT(GF("+XIIC?"));
if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) { if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) {
@@ -486,10 +450,6 @@ public:
return res; return res;
} }
IPAddress localIP() {
return TinyGsmIpFromString(getLocalIP());
}
/* /*
* Phone Call functions * Phone Call functions
*/ */
@@ -563,7 +523,11 @@ public:
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE; int8_t getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
/*
* Client related functions
*/
protected: protected:
@@ -587,7 +551,7 @@ protected:
return false; return false;
} }
int modemSend(const void* buff, size_t len, uint8_t mux) { int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+TCPSEND="), mux, ',', len); sendAT(GF("+TCPSEND="), mux, ',', len);
if (waitResponse(GF(">")) != 1) { if (waitResponse(GF(">")) != 1) {
return 0; return 0;
@@ -622,31 +586,9 @@ protected:
public: public:
/* Utilities */ /*
Utilities
template<typename T> */
void streamWrite(T last) {
stream.print(last);
}
template<typename T, typename... Args>
void streamWrite(T head, Args... tail) {
stream.print(head);
streamWrite(tail...);
}
bool streamSkipUntil(char c) {
const unsigned long timeout = 1000L;
unsigned long startMillis = millis();
while (millis() - startMillis < timeout) {
while (millis() - startMillis < timeout && !stream.available()) {
TINY_GSM_YIELD();
}
if (stream.read() == c)
return true;
}
return false;
}
template<typename... Args> template<typename... Args>
void sendAT(Args... cmd) { void sendAT(Args... cmd) {

848
src/TinyGsmClientM95.h Normal file
View File

@@ -0,0 +1,848 @@
/**
* @file TinyGsmClientM95.h
* @author Volodymyr Shymanskyy, Pacman Pereira, and Replicade Ltd.
* @license LGPL-3.0
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy, (c)2017 Replicade Ltd. <http://www.replicade.com>
* @date Nov 2016
*/
#ifndef TinyGsmClientM95_h
#define TinyGsmClientM95_h
//#pragma message("TinyGSM: TinyGsmClientM95")
//#define TINY_GSM_DEBUG Serial
//#define TINY_GSM_USE_HEX
#define TINY_GSM_MUX_COUNT 6
#include <TinyGsmCommon.h>
#define GSM_NL "\r\n"
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
enum SimStatus {
SIM_ERROR = 0,
SIM_READY = 1,
SIM_LOCKED = 2,
};
enum RegStatus {
REG_UNREGISTERED = 0,
REG_SEARCHING = 2,
REG_DENIED = 3,
REG_OK_HOME = 1,
REG_OK_ROAMING = 5,
REG_UNKNOWN = 4,
};
class TinyGsmM95 : public TinyGsmModem
{
public:
class GsmClient : public Client
{
friend class TinyGsmM95;
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
public:
GsmClient() {}
GsmClient(TinyGsmM95& modem, uint8_t mux = 1) {
init(&modem, mux);
}
bool init(TinyGsmM95* modem, uint8_t mux = 1) {
this->at = modem;
this->mux = mux;
sock_available = 0;
sock_connected = false;
got_data = false;
at->sockets[mux] = this;
return true;
}
public:
virtual int connect(const char *host, uint16_t port) {
stop();
TINY_GSM_YIELD();
rx.clear();
sock_connected = at->modemConnect(host, port, mux);
return sock_connected;
}
virtual int connect(IPAddress ip, uint16_t port) {
String host; host.reserve(16);
host += ip[0];
host += ".";
host += ip[1];
host += ".";
host += ip[2];
host += ".";
host += ip[3];
return connect(host.c_str(), port);
}
virtual void stop() {
TINY_GSM_YIELD();
// Read and dump anything remaining in the modem's internal buffer.
// The socket will appear open in response to connected() even after it
// closes until all data is read from the buffer.
// Doing it this way allows the external mcu to find and get all of the data
// that it wants from the socket even if it was closed externally.
rx.clear();
at->maintain();
while (sock_available > 0) {
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
rx.clear();
at->maintain();
}
at->sendAT(GF("+QICLOSE="), mux);
sock_connected = false;
at->waitResponse(60000L, GF("CLOSED"), GF("CLOSE OK"), GF("ERROR"));
}
virtual size_t write(const uint8_t *buf, size_t size) {
TINY_GSM_YIELD();
at->maintain();
return at->modemSend(buf, size, mux);
}
virtual size_t write(uint8_t c) {
return write(&c, 1);
}
virtual size_t write(const char *str) {
if (str == NULL) return 0;
return write((const uint8_t *)str, strlen(str));
}
virtual int available() {
TINY_GSM_YIELD();
if (!rx.size()) {
at->maintain();
}
return rx.size() + sock_available;
}
virtual int read(uint8_t *buf, size_t size) {
TINY_GSM_YIELD();
at->maintain();
size_t cnt = 0;
while (cnt < size) {
size_t chunk = TinyGsmMin(size-cnt, rx.size());
if (chunk > 0) {
rx.get(buf, chunk);
buf += chunk;
cnt += chunk;
continue;
}
// TODO: Read directly into user buffer?
at->maintain();
if (sock_available > 0) {
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
} else {
break;
}
}
return cnt;
}
virtual int read() {
uint8_t c;
if (read(&c, 1) == 1) {
return c;
}
return -1;
}
virtual int peek() { return -1; } //TODO
virtual void flush() { at->stream.flush(); }
virtual uint8_t connected() {
if (available()) {
return true;
}
return sock_connected;
}
virtual operator bool() { return connected(); }
/*
* Extended API
*/
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
private:
TinyGsmM95* at;
uint8_t mux;
uint16_t sock_available;
bool sock_connected;
bool got_data;
RxFifo rx;
};
// class GsmClientSecure : public GsmClient
// {
// public:
// GsmClientSecure() {}
//
// GsmClientSecure(TinyGsmm95& modem, uint8_t mux = 1)
// : GsmClient(modem, mux)
// {}
//
// public:
// virtual int connect(const char *host, uint16_t port) {
// stop();
// TINY_GSM_YIELD();
// rx.clear();
// sock_connected = at->modemConnect(host, port, mux, true);
// return sock_connected;
// }
// };
public:
TinyGsmM95(Stream& stream)
: TinyGsmModem(stream), stream(stream)
{
memset(sockets, 0, sizeof(sockets));
}
/*
* Basic functions
*/
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("&FZE0")); // Factory + Reset + Echo Off
if (waitResponse() != 1) {
return false;
}
#ifdef TINY_GSM_DEBUG
sendAT(GF("+CMEE=2"));
waitResponse();
#endif
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
}
String getModemName() {
return "Quectel M95";
}
void setBaud(unsigned long baud) {
sendAT(GF("+IPR="), baud);
}
bool testAT(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF(""));
if (waitResponse(200) == 1) return true;
delay(100);
}
return false;
}
void maintain() {
for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) {
GsmClient* sock = sockets[mux];
if (sock && sock->got_data) {
sock->got_data = false;
sock->sock_available = modemGetAvailable(mux);
}
}
while (stream.available()) {
waitResponse(10, NULL, NULL);
}
}
bool factoryDefault() {
sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write
waitResponse();
sendAT(GF("+IPR=0")); // Auto-baud
waitResponse();
sendAT(GF("&W")); // Write configuration
return waitResponse() == 1;
}
String getModemInfo() {
sendAT(GF("I"));
String res;
if (waitResponse(1000L, res) != 1) {
return "";
}
res.replace(GSM_NL "OK" GSM_NL, "");
res.replace(GSM_NL, " ");
res.trim();
return res;
}
bool hasSSL() {
return false; // TODO: For now
}
bool hasWifi() {
return false;
}
bool hasGPRS() {
return true;
}
/*
* Power functions
*/
bool restart() {
if (!testAT()) {
return false;
}
sendAT(GF("+CFUN=0"));
if (waitResponse(10000L, GF("NORMAL POWER DOWN"), GF("OK"), GF("FAIL")) == 3) {
return false;
}
sendAT(GF("+CFUN=1"));
if (waitResponse(10000L, GF("Call Ready"), GF("OK"), GF("FAIL")) == 3) {
return false;
}
return init();
}
bool poweroff() {
sendAT(GF("+QPOWD=1"));
return waitResponse(300, GF("NORMAL POWER DOWN")) == 1;
}
bool radioOff() {
sendAT(GF("+CFUN=0"));
if (waitResponse(10000L) != 1) {
return false;
}
delay(3000);
return true;
}
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
/*
* SIM card functions
*/
bool simUnlock(const char *pin) {
sendAT(GF("+CPIN=\""), pin, GF("\""));
return waitResponse() == 1;
}
String getSimCCID() {
sendAT(GF("+ICCID"));
if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) {
return "";
}
String res = stream.readStringUntil('\n');
waitResponse();
res.trim();
return res;
}
String getIMEI() {
sendAT(GF("+GSN"));
if (waitResponse(GF(GSM_NL)) != 1) {
return "";
}
String res = stream.readStringUntil('\n');
waitResponse();
res.trim();
return res;
}
SimStatus getSimStatus(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF("+CPIN?"));
if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) {
delay(1000);
continue;
}
int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"));
waitResponse();
switch (status) {
case 2:
case 3: return SIM_LOCKED;
case 1: return SIM_READY;
default: return SIM_ERROR;
}
}
return SIM_ERROR;
}
RegStatus getRegistrationStatus() {
sendAT(GF("+CREG?"));
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
return REG_UNKNOWN;
}
streamSkipUntil(','); // Skip format (0)
int status = stream.readStringUntil('\n').toInt();
waitResponse();
return (RegStatus)status;
}
String getOperator() {
sendAT(GF("+COPS?"));
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
return "";
}
streamSkipUntil('"'); // Skip mode and format
String res = stream.readStringUntil('"');
waitResponse();
return res;
}
/*
* Generic network functions
*/
int16_t getSignalQuality() {
sendAT(GF("+CSQ"));
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
return 99;
}
int res = stream.readStringUntil(',').toInt();
waitResponse();
return res;
}
bool isNetworkConnected() {
RegStatus s = getRegistrationStatus();
return (s == REG_OK_HOME || s == REG_OK_ROAMING);
}
void setHostFormat( bool useDottedQuad ) {
if ( useDottedQuad ) {
sendAT(GF("+QIDNSIP=0"));
} else {
sendAT(GF("+QIDNSIP=1"));
}
waitResponse();
}
/*
* GPRS functions
*/
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
gprsDisconnect();
// select foreground context 0 = VIRTUAL_UART_1
sendAT(GF("+QIFGCNT=0"));
if (waitResponse() != 1) {
return false;
}
//Select GPRS (=1) as the Bearer
sendAT(GF("+QICSGP=1,\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\""));
if (waitResponse() != 1) {
return false;
}
//Start TCPIP Task and Set APN, User Name and Password
sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd, "\"" );
if (waitResponse() != 1) {
return false;
}
//Activate GPRS/CSD Context
sendAT(GF("+QIACT"));
if (waitResponse(10000) != 1) {
return false;
}
//Enable multiple TCP/IP connections
sendAT(GF("+QIMUX=1"));
if (waitResponse() != 1) {
return false;
}
//Request an IP header for received data ("IPD(data length):")
sendAT(GF("+QIHEAD=1"));
if (waitResponse() != 1) {
return false;
}
//Set Method to Handle Received TCP/IP Data - Retrieve Data by Command
sendAT(GF("+QINDI=1"));
if (waitResponse() != 1) {
return false;
}
return true;
}
bool gprsDisconnect() {
sendAT(GF("+QIDEACT"));
return waitResponse(60000L, GF("DEACT OK"), GF("ERROR")) == 1;
}
bool isGprsConnected() {
sendAT(GF("+CGATT?"));
if (waitResponse(GF(GSM_NL "+CGATT:")) != 1) {
return false;
}
int res = stream.readStringUntil('\n').toInt();
waitResponse();
if (res != 1)
return false;
return localIP() != IPAddress(0,0,0,0);
}
/*
* IP Address functions
*/
String getLocalIP() {
sendAT(GF("+QILOCIP"));
stream.readStringUntil('\n');
String res = stream.readStringUntil('\n');
res.trim();
return res;
}
/*
* Messaging functions
*/
String sendUSSD(const String& code) {
sendAT(GF("+CMGF=1"));
waitResponse();
sendAT(GF("+CSCS=\"HEX\""));
waitResponse();
sendAT(GF("+CUSD=1,\""), code, GF("\""));
if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) {
return "";
}
stream.readStringUntil('"');
String hex = stream.readStringUntil('"');
stream.readStringUntil(',');
int dcs = stream.readStringUntil('\n').toInt();
if (waitResponse() != 1) {
return "";
}
if (dcs == 15) {
return TinyGsmDecodeHex8bit(hex);
} else if (dcs == 72) {
return TinyGsmDecodeHex16bit(hex);
} else {
return hex;
}
}
bool sendSMS(const String& number, const String& text) {
sendAT(GF("+CMGF=1"));
waitResponse();
//Set GSM 7 bit default alphabet (3GPP TS 23.038)
sendAT(GF("+CSCS=\"GSM\""));
waitResponse();
sendAT(GF("+CMGS=\""), number, GF("\""));
if (waitResponse(GF(">")) != 1) {
return false;
}
stream.print(text);
stream.write((char)0x1A);
stream.flush();
return waitResponse(60000L) == 1;
}
bool sendSMS_UTF16(const String& number, const void* text, size_t len) {
sendAT(GF("+CMGF=1"));
waitResponse();
sendAT(GF("+CSCS=\"HEX\""));
waitResponse();
sendAT(GF("+CSMP=17,167,0,8"));
waitResponse();
sendAT(GF("+CMGS=\""), number, GF("\""));
if (waitResponse(GF(">")) != 1) {
return false;
}
uint16_t* t = (uint16_t*)text;
for (size_t i=0; i<len; i++) {
uint8_t c = t[i] >> 8;
if (c < 0x10) { stream.print('0'); }
stream.print(c, HEX);
c = t[i] & 0xFF;
if (c < 0x10) { stream.print('0'); }
stream.print(c, HEX);
}
stream.write((char)0x1A);
stream.flush();
return waitResponse(60000L) == 1;
}
/** Delete all SMS */
bool deleteAllSMS() {
sendAT(GF("+QMGDA=6"));
if (waitResponse(waitResponse(60000L, GF("OK"), GF("ERROR")) == 1) ) {
return true;
}
return false;
}
/*
* Phone Call functions
*/
bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE;
bool callAnswer() TINY_GSM_ATTR_NOT_AVAILABLE;
bool callNumber(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE;
bool callHangup() TINY_GSM_ATTR_NOT_AVAILABLE;
/*
* Location functions
*/
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
/*
* Battery functions
*/
// Use: float vBatt = modem.getBattVoltage() / 1000.0;
uint16_t getBattVoltage() {
sendAT(GF("+CBC"));
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
return 0;
}
streamSkipUntil(','); // Skip
streamSkipUntil(','); // Skip
uint16_t res = stream.readStringUntil(',').toInt();
waitResponse();
return res;
}
int8_t getBattPercent() {
sendAT(GF("+CBC"));
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
return false;
}
stream.readStringUntil(',');
int res = stream.readStringUntil(',').toInt();
waitResponse();
return res;
}
/*
* Client related functions
*/
protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
sendAT(GF("+QIOPEN="), mux, GF("\"TCP"), GF("\",\""), host, GF("\","), port);
int rsp = waitResponse(75000L,
GF("CONNECT OK" GSM_NL),
GF("CONNECT FAIL" GSM_NL),
GF("ALREADY CONNECT" GSM_NL));
return (1 == rsp);
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+QISEND="), mux, ',', len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
stream.write((uint8_t*)buff, len);
stream.flush();
if (waitResponse(GF(GSM_NL "SEND OK")) != 1) {
return 0;
}
bool allAcknowledged = false;
// bool failed = false;
while ( !allAcknowledged ) {
sendAT( GF("+QISACK"));
if (waitResponse(5000L, GF(GSM_NL "+QISACK:")) != 1) {
return -1;
} else {
streamSkipUntil(','); /** Skip total */
streamSkipUntil(','); /** Skip acknowledged data size */
if ( stream.readStringUntil('\n').toInt() == 0 ) {
allAcknowledged = true;
}
}
}
waitResponse(5000L);
// streamSkipUntil(','); // Skip mux
// return stream.readStringUntil('\n').toInt();
return 1;
}
size_t modemRead(size_t size, uint8_t mux) {
sendAT(GF("+QIRD="), mux, ',', size);
if (waitResponse(GF("+QIRD:")) != 1) {
return 0;
}
size_t len = stream.readStringUntil('\n').toInt();
for (size_t i=0; i<len; i++) {
while (!stream.available()) { TINY_GSM_YIELD(); }
char c = stream.read();
sockets[mux]->rx.put(c);
}
waitResponse();
DBG("### READ:", mux, ",", len);
return len;
}
size_t modemGetAvailable(uint8_t mux) {
sendAT(GF("+QIRD="), mux, GF(",0"));
size_t result = 0;
if (waitResponse(GF("+QIRD:")) == 1) {
streamSkipUntil(','); // Skip total received
streamSkipUntil(','); // Skip have read
result = stream.readStringUntil('\n').toInt();
DBG("### STILL:", mux, "has", result);
waitResponse();
}
if (!result) {
sockets[mux]->sock_connected = modemGetConnected(mux);
}
return result;
}
bool modemGetConnected(uint8_t mux) {
sendAT(GF("+QISTATE=1,"), mux);
//+QISTATE: 0,"TCP","151.139.237.11",80,5087,4,1,0,0,"uart1"
if (waitResponse(GF("+QISTATE:")))
return false;
streamSkipUntil(','); // Skip mux
streamSkipUntil(','); // Skip socket type
streamSkipUntil(','); // Skip remote ip
streamSkipUntil(','); // Skip remote port
streamSkipUntil(','); // Skip local port
int res = stream.readStringUntil(',').toInt(); // socket state
waitResponse();
// 0 Initial, 1 Opening, 2 Connected, 3 Listening, 4 Closing
return 2 == res;
}
public:
/*
Utilities
*/
template<typename... Args>
void sendAT(Args... cmd) {
streamWrite("AT", cmd..., GSM_NL);
stream.flush();
TINY_GSM_YIELD();
//DBG("### AT:", cmd...);
}
// TODO: Optimize this!
uint8_t waitResponse(uint32_t timeout, String& data,
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
{
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
int index = 0;
unsigned long startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
int a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += (char)a;
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+QIRD:"))) {
streamSkipUntil(','); // Skip the context
streamSkipUntil(','); // Skip the role
int mux = stream.readStringUntil('\n').toInt();
DBG("### Got Data:", mux);
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int nl = data.lastIndexOf(GSM_NL, data.length()-8);
int coma = data.indexOf(',', nl+2);
int mux = data.substring(nl+2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
}
}
} while (millis() - startMillis < timeout);
finish:
if (!index) {
data.trim();
if (data.length()) {
DBG("### Unhandled:", data);
}
data = "";
}
//DBG('<', index, '>');
return index;
}
uint8_t waitResponse(uint32_t timeout,
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
{
String data;
return waitResponse(timeout, data, r1, r2, r3, r4, r5);
}
uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
{
return waitResponse(1000, r1, r2, r3, r4, r5);
}
public:
Stream& stream;
protected:
GsmClient* sockets[TINY_GSM_MUX_COUNT];
};
#endif

880
src/TinyGsmClientMC60.h Normal file
View File

@@ -0,0 +1,880 @@
/**
* @file TinyGsmClientMC60.h
* @author Volodymyr Shymanskyy
* @license LGPL-3.0
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
* @date Nov 2016
*
* @MC60 support added by Tamas Dajka 2017.10.15 - with fixes by Sara Damiano
*
*/
#ifndef TinyGsmClientMC60_h
#define TinyGsmClientMC60_h
//#pragma message("TinyGSM: TinyGsmClientMC60")
//#define TINY_GSM_DEBUG Serial
//#define TINY_GSM_USE_HEX
#define TINY_GSM_MUX_COUNT 6
#include <TinyGsmCommon.h>
#define GSM_NL "\r\n"
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
enum SimStatus {
SIM_ERROR = 0,
SIM_READY = 1,
SIM_LOCKED = 2,
SIM_ANTITHEFT_LOCKED = 3,
};
enum RegStatus {
REG_UNREGISTERED = 0,
REG_SEARCHING = 2,
REG_DENIED = 3,
REG_OK_HOME = 1,
REG_OK_ROAMING = 5,
REG_UNKNOWN = 4,
};
class TinyGsmMC60 : public TinyGsmModem
{
public:
class GsmClient : public Client
{
friend class TinyGsmMC60;
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
public:
GsmClient() {}
GsmClient(TinyGsmMC60& modem, uint8_t mux = 1) {
init(&modem, mux);
}
bool init(TinyGsmMC60* modem, uint8_t mux = 1) {
this->at = modem;
this->mux = mux;
sock_available = 0;
sock_connected = false;
got_data = false;
at->sockets[mux] = this;
return true;
}
public:
virtual int connect(const char *host, uint16_t port) {
stop();
TINY_GSM_YIELD();
rx.clear();
sock_connected = at->modemConnect(host, port, mux);
return sock_connected;
}
virtual int connect(IPAddress ip, uint16_t port) {
String host; host.reserve(16);
host += ip[0];
host += ".";
host += ip[1];
host += ".";
host += ip[2];
host += ".";
host += ip[3];
return connect(host.c_str(), port);
}
virtual void stop() {
TINY_GSM_YIELD();
// Read and dump anything remaining in the modem's internal buffer.
// The socket will appear open in response to connected() even after it
// closes until all data is read from the buffer.
// Doing it this way allows the external mcu to find and get all of the data
// that it wants from the socket even if it was closed externally.
rx.clear();
at->maintain();
while (sock_available > 0) {
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
rx.clear();
at->maintain();
}
at->sendAT(GF("+QICLOSE="), mux);
sock_connected = false;
at->waitResponse(60000L, GF("CLOSED"), GF("CLOSE OK"), GF("ERROR"));
}
virtual size_t write(const uint8_t *buf, size_t size) {
TINY_GSM_YIELD();
at->maintain();
return at->modemSend(buf, size, mux);
}
virtual size_t write(uint8_t c) {
return write(&c, 1);
}
virtual size_t write(const char *str) {
if (str == NULL) return 0;
return write((const uint8_t *)str, strlen(str));
}
virtual int available() {
TINY_GSM_YIELD();
if (!rx.size()) {
at->maintain();
}
return rx.size() + sock_available;
}
virtual int read(uint8_t *buf, size_t size) {
TINY_GSM_YIELD();
at->maintain();
size_t cnt = 0;
while (cnt < size) {
size_t chunk = TinyGsmMin(size-cnt, rx.size());
if (chunk > 0) {
rx.get(buf, chunk);
buf += chunk;
cnt += chunk;
continue;
}
// TODO: Read directly into user buffer?
at->maintain();
if (sock_available > 0) {
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
} else {
break;
}
}
return cnt;
}
virtual int read() {
uint8_t c;
if (read(&c, 1) == 1) {
return c;
}
return -1;
}
virtual int peek() { return -1; } //TODO
virtual void flush() { at->stream.flush(); }
virtual uint8_t connected() {
if (available()) {
return true;
}
return sock_connected;
}
virtual operator bool() { return connected(); }
/*
* Extended API
*/
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
private:
TinyGsmMC60* at;
uint8_t mux;
uint16_t sock_available;
bool sock_connected;
bool got_data;
RxFifo rx;
};
// class GsmClientSecure : public GsmClient
// {
// public:
// GsmClientSecure() {}
//
// GsmClientSecure(TinyGsmMC60& modem, uint8_t mux = 1)
// : GsmClient(modem, mux)
// {}
//
// public:
// virtual int connect(const char *host, uint16_t port) {
// stop();
// TINY_GSM_YIELD();
// rx.clear();
// sock_connected = at->modemConnect(host, port, mux, true);
// return sock_connected;
// }
// };
public:
TinyGsmMC60(Stream& stream)
: TinyGsmModem(stream), stream(stream)
{
memset(sockets, 0, sizeof(sockets));
}
/*
* Basic functions
*/
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("&FZ")); // Factory + Reset
waitResponse();
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
}
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
}
String getModemName() {
#if defined(TINY_GSM_MODEM_MC60)
return "Quectel MC60";
#elif defined(TINY_GSM_MODEM_MC60E)
return "Quectel MC60E";
#endif
return "Quectel MC60";
}
void setBaud(unsigned long baud) {
sendAT(GF("+IPR="), baud);
}
bool testAT(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF(""));
if (waitResponse(200) == 1) return true;
delay(100);
}
return false;
}
void maintain() {
for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) {
GsmClient* sock = sockets[mux];
if (sock && sock->got_data) {
sock->got_data = false;
sock->sock_available = modemGetAvailable(mux);
}
}
while (stream.available()) {
waitResponse(10, NULL, NULL);
}
}
bool factoryDefault() {
sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write
waitResponse();
sendAT(GF("+IPR=0")); // Auto-baud
waitResponse();
sendAT(GF("&W")); // Write configuration
return waitResponse() == 1;
}
String getModemInfo() {
sendAT(GF("I"));
String res;
if (waitResponse(1000L, res) != 1) {
return "";
}
res.replace(GSM_NL "OK" GSM_NL, "");
res.replace(GSM_NL, " ");
res.trim();
return res;
}
/*
* under development
*/
// bool hasSSL() {
// sendAT(GF("+QIPSSL=?"));
// if (waitResponse(GF(GSM_NL "+CIPSSL:")) != 1) {
// return false;
// }
// return waitResponse() == 1;
// }
bool hasSSL() {
return false; // TODO: For now
}
bool hasWifi() {
return false;
}
bool hasGPRS() {
return true;
}
/*
* Power functions
*/
bool restart() {
if (!testAT()) {
return false;
}
sendAT(GF("+CFUN=0"));
if (waitResponse(10000L) != 1) {
return false;
}
sendAT(GF("+CFUN=1,1"));
if (waitResponse(10000L) != 1) {
return false;
}
delay(3000);
return init();
}
bool poweroff() {
sendAT(GF("+QPOWD=1"));
return waitResponse(GF("NORMAL POWER DOWN")) == 1;
}
bool radioOff() {
if (!testAT()) {
return false;
}
sendAT(GF("+CFUN=0"));
if (waitResponse(10000L) != 1) {
return false;
}
delay(3000);
return true;
}
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
/*
* SIM card functions
*/
bool simUnlock(const char *pin) {
sendAT(GF("+CPIN=\""), pin, GF("\""));
return waitResponse() == 1;
}
String getSimCCID() {
sendAT(GF("+ICCID"));
if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) {
return "";
}
String res = stream.readStringUntil('\n');
waitResponse();
res.trim();
return res;
}
String getIMEI() {
sendAT(GF("+GSN"));
if (waitResponse(GF(GSM_NL)) != 1) {
return "";
}
String res = stream.readStringUntil('\n');
waitResponse();
res.trim();
return res;
}
SimStatus getSimStatus(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF("+CPIN?"));
if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) {
delay(1000);
continue;
}
int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED"), GF("PH_SIM PIN"), GF("PH_SIM PUK"));
waitResponse();
switch (status) {
case 2:
case 3: return SIM_LOCKED;
case 5:
case 6: return SIM_ANTITHEFT_LOCKED;
case 1: return SIM_READY;
default: return SIM_ERROR;
}
}
return SIM_ERROR;
}
RegStatus getRegistrationStatus() {
sendAT(GF("+CREG?"));
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
return REG_UNKNOWN;
}
streamSkipUntil(','); // Skip format (0)
int status = stream.readStringUntil('\n').toInt();
waitResponse();
return (RegStatus)status;
}
String getOperator() {
sendAT(GF("+COPS?"));
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
return "";
}
streamSkipUntil('"'); // Skip mode and format
String res = stream.readStringUntil('"');
waitResponse();
return res;
}
/*
* Generic network functions
*/
int16_t getSignalQuality() {
sendAT(GF("+CSQ"));
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
return 99;
}
int res = stream.readStringUntil(',').toInt();
waitResponse();
return res;
}
bool isNetworkConnected() {
RegStatus s = getRegistrationStatus();
return (s == REG_OK_HOME || s == REG_OK_ROAMING);
}
/*
* GPRS functions
*/
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
gprsDisconnect();
// select foreground context 0 = VIRTUAL_UART_1
sendAT(GF("+QIFGCNT=0"));
if (waitResponse() != 1) {
return false;
}
//Select GPRS (=1) as the Bearer
sendAT(GF("+QICSGP=1,\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\""));
if (waitResponse() != 1) {
return false;
}
//Define PDP context - is this necessary?
sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"');
waitResponse();
// Activate PDP context - is this necessary?
sendAT(GF("+CGACT=1,1"));
waitResponse(60000L);
//Start TCPIP Task and Set APN, User Name and Password
sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd, "\"" );
if (waitResponse() != 1) {
return false;
}
//Activate GPRS/CSD Context
sendAT(GF("+QIACT"));
if (waitResponse(60000L) != 1) {
return false;
}
//Enable multiple TCP/IP connections
sendAT(GF("+QIMUX=1"));
if (waitResponse() != 1) {
return false;
}
//Request an IP header for received data ("IPD(data length):")
sendAT(GF("+QIHEAD=1"));
if (waitResponse() != 1) {
return false;
}
//Set Method to Handle Received TCP/IP Data - Retrieve Data by Command
sendAT(GF("+QINDI=1"));
if (waitResponse() != 1) {
return false;
}
// Check that we have a local IP address
if (localIP() != 0) {
return true;
}
return false;
}
bool gprsDisconnect() {
sendAT(GF("+QIDEACT"));
return waitResponse(60000L, GF("DEACT OK"), GF("ERROR")) == 1;
}
bool isGprsConnected() {
sendAT(GF("+CGATT?"));
if (waitResponse(GF(GSM_NL "+CGATT:")) != 1) {
return false;
}
int res = stream.readStringUntil('\n').toInt();
waitResponse();
if (res != 1)
return false;
return localIP() != IPAddress(0,0,0,0);
}
/*
* IP Address functions
*/
String getLocalIP() {
sendAT(GF("+QILOCIP"));
stream.readStringUntil('\n');
String res = stream.readStringUntil('\n');
res.trim();
return res;
}
/*
* Messaging functions
*/
String sendUSSD(const String& code) {
sendAT(GF("+CMGF=1"));
waitResponse();
sendAT(GF("+CSCS=\"HEX\""));
waitResponse();
sendAT(GF("+CUSD=1,\""), code, GF("\""));
if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) {
return "";
}
stream.readStringUntil('"');
String hex = stream.readStringUntil('"');
stream.readStringUntil(',');
int dcs = stream.readStringUntil('\n').toInt();
if (waitResponse() != 1) {
return "";
}
if (dcs == 15) {
return TinyGsmDecodeHex8bit(hex);
} else if (dcs == 72) {
return TinyGsmDecodeHex16bit(hex);
} else {
return hex;
}
}
bool sendSMS(const String& number, const String& text) {
sendAT(GF("+CMGF=1"));
waitResponse();
//Set GSM 7 bit default alphabet (3GPP TS 23.038)
sendAT(GF("+CSCS=\"GSM\""));
waitResponse();
sendAT(GF("+CMGS=\""), number, GF("\""));
if (waitResponse(GF(">")) != 1) {
return false;
}
stream.print(text);
stream.write((char)0x1A);
stream.flush();
return waitResponse(60000L) == 1;
}
bool sendSMS_UTF16(const String& number, const void* text, size_t len) {
sendAT(GF("+CMGF=1"));
waitResponse();
sendAT(GF("+CSCS=\"HEX\""));
waitResponse();
sendAT(GF("+CSMP=17,167,0,8"));
waitResponse();
sendAT(GF("+CMGS=\""), number, GF("\""));
if (waitResponse(GF(">")) != 1) {
return false;
}
uint16_t* t = (uint16_t*)text;
for (size_t i=0; i<len; i++) {
uint8_t c = t[i] >> 8;
if (c < 0x10) { stream.print('0'); }
stream.print(c, HEX);
c = t[i] & 0xFF;
if (c < 0x10) { stream.print('0'); }
stream.print(c, HEX);
}
stream.write((char)0x1A);
stream.flush();
return waitResponse(60000L) == 1;
}
/** Delete all SMS */
bool deleteAllSMS() {
sendAT(GF("+QMGDA=6"));
if (waitResponse(waitResponse(60000L, GF("OK"), GF("ERROR")) == 1) ) {
return true;
}
return false;
}
/*
* Location functions
*/
String getGsmLocation() {
sendAT(GF("+CIPGSMLOC=1,1"));
if (waitResponse(10000L, GF(GSM_NL "+CIPGSMLOC:")) != 1) {
return "";
}
String res = stream.readStringUntil('\n');
waitResponse();
res.trim();
return res;
}
/*
* Battery functions
*/
// Use: float vBatt = modem.getBattVoltage() / 1000.0;
uint16_t getBattVoltage() {
sendAT(GF("+CBC"));
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
return 0;
}
streamSkipUntil(','); // Skip
streamSkipUntil(','); // Skip
uint16_t res = stream.readStringUntil(',').toInt();
waitResponse();
return res;
}
int8_t getBattPercent() {
sendAT(GF("+CBC"));
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
return false;
}
stream.readStringUntil(',');
int res = stream.readStringUntil(',').toInt();
waitResponse();
return res;
}
/*
* Client related functions
*/
protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
sendAT(GF("+QIOPEN="), mux, GF("\"TCP"), GF("\",\""), host, GF("\","), port);
int rsp = waitResponse(75000L,
GF("CONNECT OK" GSM_NL),
GF("CONNECT FAIL" GSM_NL),
GF("ALREADY CONNECT" GSM_NL));
return (1 == rsp);
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+QISEND="), mux, ',', len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
stream.write((uint8_t*)buff, len);
stream.flush();
if (waitResponse(GF(GSM_NL "SEND OK")) != 1) {
return 0;
}
bool allAcknowledged = false;
// bool failed = false;
while ( !allAcknowledged ) {
sendAT( GF("+QISACK"));
if (waitResponse(5000L, GF(GSM_NL "+QISACK:")) != 1) {
return -1;
} else {
streamSkipUntil(','); /** Skip total */
streamSkipUntil(','); /** Skip acknowledged data size */
if ( stream.readStringUntil('\n').toInt() == 0 ) {
allAcknowledged = true;
}
}
}
waitResponse(5000L);
// streamSkipUntil(','); // Skip mux
// return stream.readStringUntil('\n').toInt();
return 1;
}
size_t modemRead(size_t size, uint8_t mux) {
sendAT(GF("+QIRD="), mux, ',', size);
if (waitResponse(GF("+QIRD:")) != 1) {
return 0;
}
size_t len = stream.readStringUntil('\n').toInt();
for (size_t i=0; i<len; i++) {
while (!stream.available()) { TINY_GSM_YIELD(); }
char c = stream.read();
sockets[mux]->rx.put(c);
}
waitResponse();
DBG("### READ:", mux, ",", len);
return len;
}
size_t modemGetAvailable(uint8_t mux) {
sendAT(GF("+QIRD="), mux, GF(",0"));
size_t result = 0;
if (waitResponse(GF("+QIRD:")) == 1) {
streamSkipUntil(','); // Skip total received
streamSkipUntil(','); // Skip have read
result = stream.readStringUntil('\n').toInt();
DBG("### STILL:", mux, "has", result);
waitResponse();
}
if (!result) {
sockets[mux]->sock_connected = modemGetConnected(mux);
}
return result;
}
bool modemGetConnected(uint8_t mux) {
sendAT(GF("+QISTATE=1,"), mux);
//+QISTATE: 0,"TCP","151.139.237.11",80,5087,4,1,0,0,"uart1"
if (waitResponse(GF("+QISTATE:")))
return false;
streamSkipUntil(','); // Skip mux
streamSkipUntil(','); // Skip socket type
streamSkipUntil(','); // Skip remote ip
streamSkipUntil(','); // Skip remote port
streamSkipUntil(','); // Skip local port
int res = stream.readStringUntil(',').toInt(); // socket state
waitResponse();
// 0 Initial, 1 Opening, 2 Connected, 3 Listening, 4 Closing
return 2 == res;
}
public:
/*
Utilities
*/
template<typename... Args>
void sendAT(Args... cmd) {
streamWrite("AT", cmd..., GSM_NL);
stream.flush();
TINY_GSM_YIELD();
//DBG("### AT:", cmd...);
}
// TODO: Optimize this!
uint8_t waitResponse(uint32_t timeout, String& data,
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL, GsmConstStr r6=NULL)
{
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
String r6s(r6); r6s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s, ",", r6s);*/
data.reserve(64);
int index = 0;
unsigned long startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
int a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += (char)a;
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (r6 && data.endsWith(r6)) {
index = 6;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+QIRD:"))) {
streamSkipUntil(','); // Skip the context
streamSkipUntil(','); // Skip the role
int mux = stream.readStringUntil('\n').toInt();
DBG("### Got Data:", mux);
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int nl = data.lastIndexOf(GSM_NL, data.length()-8);
int coma = data.indexOf(',', nl+2);
int mux = data.substring(nl+2, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
}
}
} while (millis() - startMillis < timeout);
finish:
if (!index) {
data.trim();
if (data.length()) {
DBG("### Unhandled:", data);
}
data = "";
}
//DBG('<', index, '>');
return index;
}
uint8_t waitResponse(uint32_t timeout,
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL, GsmConstStr r6=NULL)
{
String data;
return waitResponse(timeout, data, r1, r2, r3, r4, r5, r6);
}
uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL, GsmConstStr r6=NULL)
{
return waitResponse(1000, r1, r2, r3, r4, r5, r6);
}
public:
Stream& stream;
protected:
GsmClient* sockets[TINY_GSM_MUX_COUNT];
};
#endif

1099
src/TinyGsmClientSIM7000.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -8,14 +8,11 @@
#ifndef TinyGsmClientSIM800_h #ifndef TinyGsmClientSIM800_h
#define TinyGsmClientSIM800_h #define TinyGsmClientSIM800_h
//#pragma message("TinyGSM: TinyGsmClientSIM800")
//#define TINY_GSM_DEBUG Serial //#define TINY_GSM_DEBUG Serial
//#define TINY_GSM_USE_HEX //#define TINY_GSM_USE_HEX
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 64
#endif
#define TINY_GSM_MUX_COUNT 5 #define TINY_GSM_MUX_COUNT 5
#include <TinyGsmCommon.h> #include <TinyGsmCommon.h>
@@ -45,7 +42,7 @@ enum TinyGSMDateTimeFormat {
DATE_DATE = 2 DATE_DATE = 2
}; };
class TinyGsmSim800 class TinyGsmSim800 : public TinyGsmModem
{ {
public: public:
@@ -98,10 +95,21 @@ public:
virtual void stop() { virtual void stop() {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
at->sendAT(GF("+CIPCLOSE="), mux); // Read and dump anything remaining in the modem's internal buffer.
// The socket will appear open in response to connected() even after it
// closes until all data is read from the buffer.
// Doing it this way allows the external mcu to find and get all of the data
// that it wants from the socket even if it was closed externally.
rx.clear();
at->maintain();
while (sock_available > 0) {
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
rx.clear();
at->maintain();
}
at->sendAT(GF("+CIPCLOSE="), mux, GF(",1")); // Quick close
sock_connected = false; sock_connected = false;
at->waitResponse(); at->waitResponse();
rx.clear();
} }
virtual size_t write(const uint8_t *buf, size_t size) { virtual size_t write(const uint8_t *buf, size_t size) {
@@ -121,11 +129,11 @@ public:
virtual int available() { virtual int available() {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
if (!rx.size() && sock_connected) { if (!rx.size()) {
// Workaround: sometimes SIM800 forgets to notify about data arrival. // Workaround: sometimes SIM800 forgets to notify about data arrival.
// TODO: Currently we ping the module periodically, // TODO: Currently we ping the module periodically,
// but maybe there's a better indicator that we need to poll // but maybe there's a better indicator that we need to poll
if (millis() - prev_check > 500) { if (millis() - prev_check > 250) {
got_data = true; got_data = true;
prev_check = millis(); prev_check = millis();
} }
@@ -138,7 +146,7 @@ public:
TINY_GSM_YIELD(); TINY_GSM_YIELD();
at->maintain(); at->maintain();
size_t cnt = 0; size_t cnt = 0;
while (cnt < size && sock_connected) { while (cnt < size) {
size_t chunk = TinyGsmMin(size-cnt, rx.size()); size_t chunk = TinyGsmMin(size-cnt, rx.size());
if (chunk > 0) { if (chunk > 0) {
rx.get(buf, chunk); rx.get(buf, chunk);
@@ -146,10 +154,17 @@ public:
cnt += chunk; cnt += chunk;
continue; continue;
} }
// TODO: Read directly into user buffer? // Workaround: sometimes SIM800 forgets to notify about data arrival.
// TODO: Currently we ping the module periodically,
// but maybe there's a better indicator that we need to poll
if (millis() - prev_check > 250) {
got_data = true;
prev_check = millis();
}
at->maintain(); at->maintain();
// TODO: Read directly into user buffer?
if (sock_available > 0) { if (sock_available > 0) {
at->modemRead(rx.free(), mux); sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
} else { } else {
break; break;
} }
@@ -192,6 +207,7 @@ private:
RxFifo rx; RxFifo rx;
}; };
class GsmClientSecure : public GsmClient class GsmClientSecure : public GsmClient
{ {
public: public:
@@ -211,10 +227,11 @@ public:
} }
}; };
public: public:
TinyGsmSim800(Stream& stream) TinyGsmSim800(Stream& stream)
: stream(stream) : TinyGsmModem(stream), stream(stream)
{ {
memset(sockets, 0, sizeof(sockets)); memset(sockets, 0, sizeof(sockets));
} }
@@ -222,11 +239,9 @@ public:
/* /*
* Basic functions * Basic functions
*/ */
bool begin() {
return init();
}
bool init() { bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) { if (!testAT()) {
return false; return false;
} }
@@ -236,10 +251,24 @@ public:
if (waitResponse() != 1) { if (waitResponse() != 1) {
return false; return false;
} }
DBG(GF("### Modem:"), getModemName());
getSimStatus(); getSimStatus();
return true; return true;
} }
String getModemName() {
#if defined(TINY_GSM_MODEM_SIM800)
return "SIMCom SIM800";
#elif defined(TINY_GSM_MODEM_SIM808)
return "SIMCom SIM808";
#elif defined(TINY_GSM_MODEM_SIM868)
return "SIMCom SIM868";
#elif defined(TINY_GSM_MODEM_SIM900)
return "SIMCom SIM900";
#endif
return "SIMCom SIM800";
}
void setBaud(unsigned long baud) { void setBaud(unsigned long baud) {
sendAT(GF("+IPR="), baud); sendAT(GF("+IPR="), baud);
} }
@@ -248,10 +277,7 @@ public:
//streamWrite(GF("AAAAA" GSM_NL)); // TODO: extra A's to help detect the baud rate //streamWrite(GF("AAAAA" GSM_NL)); // TODO: extra A's to help detect the baud rate
for (unsigned long start = millis(); millis() - start < timeout; ) { for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF("")); sendAT(GF(""));
if (waitResponse(200) == 1) { if (waitResponse(200) == 1) return true;
delay(100);
return true;
}
delay(100); delay(100);
} }
return false; return false;
@@ -309,6 +335,14 @@ public:
#endif #endif
} }
bool hasWifi() {
return false;
}
bool hasGPRS() {
return true;
}
/* /*
* Power functions * Power functions
*/ */
@@ -402,10 +436,10 @@ public:
int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED")); int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED"));
waitResponse(); waitResponse();
switch (status) { switch (status) {
case 2: case 2:
case 3: return SIM_LOCKED; case 3: return SIM_LOCKED;
case 1: return SIM_READY; case 1: return SIM_READY;
default: return SIM_ERROR; default: return SIM_ERROR;
} }
} }
return SIM_ERROR; return SIM_ERROR;
@@ -437,7 +471,7 @@ public:
* Generic network functions * Generic network functions
*/ */
int getSignalQuality() { int16_t getSignalQuality() {
sendAT(GF("+CSQ")); sendAT(GF("+CSQ"));
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
return 99; return 99;
@@ -452,16 +486,6 @@ public:
return (s == REG_OK_HOME || s == REG_OK_ROAMING); return (s == REG_OK_HOME || s == REG_OK_ROAMING);
} }
bool waitForNetwork(unsigned long timeout = 60000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
if (isNetworkConnected()) {
return true;
}
delay(250);
}
return false;
}
/* /*
* GPRS functions * GPRS functions
*/ */
@@ -582,6 +606,10 @@ public:
return true; return true;
} }
/*
* IP Address functions
*/
String getLocalIP() { String getLocalIP() {
sendAT(GF("+CIFSR;E0")); sendAT(GF("+CIFSR;E0"));
String res; String res;
@@ -594,9 +622,6 @@ public:
return res; return res;
} }
IPAddress localIP() {
return TinyGsmIpFromString(getLocalIP());
}
/* /*
* Phone Call functions * Phone Call functions
@@ -780,7 +805,7 @@ public:
return res; return res;
} }
int getBattPercent() { int8_t getBattPercent() {
sendAT(GF("+CBC")); sendAT(GF("+CBC"));
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
return false; return false;
@@ -791,6 +816,10 @@ public:
return res; return res;
} }
/*
* Client related functions
*/
protected: protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
@@ -813,7 +842,7 @@ protected:
return (1 == rsp); return (1 == rsp);
} }
int modemSend(const void* buff, size_t len, uint8_t mux) { int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+CIPSEND="), mux, ',', len); sendAT(GF("+CIPSEND="), mux, ',', len);
if (waitResponse(GF(">")) != 1) { if (waitResponse(GF(">")) != 1) {
return 0; return 0;
@@ -885,30 +914,9 @@ protected:
public: public:
/* Utilities */ /*
Utilities
template<typename T> */
void streamWrite(T last) {
stream.print(last);
}
template<typename T, typename... Args>
void streamWrite(T head, Args... tail) {
stream.print(head);
streamWrite(tail...);
}
bool streamSkipUntil(const char c, const unsigned long timeout = 3000L) {
unsigned long startMillis = millis();
while (millis() - startMillis < timeout) {
while (millis() - startMillis < timeout && !stream.available()) {
TINY_GSM_YIELD();
}
if (stream.read() == c)
return true;
}
return false;
}
template<typename... Args> template<typename... Args>
void sendAT(Args... cmd) { void sendAT(Args... cmd) {
@@ -984,6 +992,7 @@ finish:
} }
data = ""; data = "";
} }
//DBG('<', index, '>');
return index; return index;
} }

View File

@@ -8,16 +8,11 @@
#ifndef TinyGsmClientSIM808_h #ifndef TinyGsmClientSIM808_h
#define TinyGsmClientSIM808_h #define TinyGsmClientSIM808_h
//#pragma message("TinyGSM: TinyGsmClientSIM808")
#include <TinyGsmClientSIM800.h> #include <TinyGsmClientSIM800.h>
//============================================================================//
//============================================================================//
// Declaration and Definitio of the TinyGsmSim808 Class
//============================================================================//
//============================================================================//
class TinyGsmSim808: public TinyGsmSim800 class TinyGsmSim808: public TinyGsmSim800
{ {
@@ -33,7 +28,7 @@ public:
// enable GPS // enable GPS
bool enableGPS() { bool enableGPS() {
uint16_t state; // uint16_t state;
sendAT(GF("+CGNSPWR=1")); sendAT(GF("+CGNSPWR=1"));
if (waitResponse() != 1) { if (waitResponse() != 1) {
@@ -44,7 +39,7 @@ public:
} }
bool disableGPS() { bool disableGPS() {
uint16_t state; // uint16_t state;
sendAT(GF("+CGNSPWR=0")); sendAT(GF("+CGNSPWR=0"));
if (waitResponse() != 1) { if (waitResponse() != 1) {
@@ -71,7 +66,7 @@ public:
// works only with ans SIM808 V2 // works only with ans SIM808 V2
bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) { bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) {
//String buffer = ""; //String buffer = "";
char chr_buffer[12]; // char chr_buffer[12];
bool fix = false; bool fix = false;
sendAT(GF("+CGNSINF")); sendAT(GF("+CGNSINF"));

View File

@@ -8,14 +8,11 @@
#ifndef TinyGsmClientUBLOX_h #ifndef TinyGsmClientUBLOX_h
#define TinyGsmClientUBLOX_h #define TinyGsmClientUBLOX_h
//#pragma message("TinyGSM: TinyGsmClientUBLOX")
//#define TINY_GSM_DEBUG Serial //#define TINY_GSM_DEBUG Serial
#if !defined(TINY_GSM_RX_BUFFER) #define TINY_GSM_MUX_COUNT 7
#define TINY_GSM_RX_BUFFER 64
#endif
#define TINY_GSM_MUX_COUNT 5
#include <TinyGsmCommon.h> #include <TinyGsmCommon.h>
@@ -39,22 +36,10 @@ enum RegStatus {
REG_UNKNOWN = 4, REG_UNKNOWN = 4,
}; };
//============================================================================//
//============================================================================//
// Declaration of the TinyGsmUBLOX Class
//============================================================================//
//============================================================================//
class TinyGsmUBLOX class TinyGsmUBLOX : public TinyGsmModem
{ {
//============================================================================//
//============================================================================//
// The UBLOX Internal Client Class
//============================================================================//
//============================================================================//
public: public:
class GsmClient : public Client class GsmClient : public Client
@@ -65,14 +50,15 @@ class GsmClient : public Client
public: public:
GsmClient() {} GsmClient() {}
GsmClient(TinyGsmUBLOX& modem, uint8_t mux = 1) { GsmClient(TinyGsmUBLOX& modem, uint8_t mux = 0) {
init(&modem, mux); init(&modem, mux);
} }
bool init(TinyGsmUBLOX* modem, uint8_t mux = 1) { bool init(TinyGsmUBLOX* modem, uint8_t mux = 0) {
this->at = modem; this->at = modem;
this->mux = mux; this->mux = mux;
sock_available = 0; sock_available = 0;
prev_check = 0;
sock_connected = false; sock_connected = false;
got_data = false; got_data = false;
return true; return true;
@@ -80,11 +66,24 @@ public:
public: public:
virtual int connect(const char *host, uint16_t port) { virtual int connect(const char *host, uint16_t port) {
stop(); if (sock_connected) {
stop();
// If we're creating a new connection on the same client, we need to wait
// until the async close has finished on Cat-M modems.
// After close has completed, the +UUSOCL should appear.
if (at->isCatM) {
DBG("Waiting for +UUSOCL URC on", mux);
for (unsigned long start = millis(); millis() - start < 120000L; ) {
at->maintain();
if (!sock_connected) break;
}
}
}
TINY_GSM_YIELD(); TINY_GSM_YIELD();
rx.clear(); rx.clear();
sock_connected = at->modemConnect(host, port, &mux); sock_connected = at->modemConnect(host, port, &mux);
at->sockets[mux] = this; at->sockets[mux] = this;
at->maintain();
return sock_connected; return sock_connected;
} }
@@ -102,10 +101,22 @@ public:
virtual void stop() { virtual void stop() {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
at->sendAT(GF("+USOCL="), mux); // Read and dump anything remaining in the modem's internal buffer.
sock_connected = false; // The socket will appear open in response to connected() even after it
at->waitResponse(); // closes until all data is read from the buffer.
// Doing it this way allows the external mcu to find and get all of the data
// that it wants from the socket even if it was closed externally.
rx.clear(); rx.clear();
at->maintain();
while (sock_available > 0) {
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
rx.clear();
at->maintain();
}
at->modemDisconnect(mux);
// We don't actually know if the CatM modem has finished closing because
// we're using an "asynchronous" close
if (!at->isCatM) sock_connected = false;
} }
virtual size_t write(const uint8_t *buf, size_t size) { virtual size_t write(const uint8_t *buf, size_t size) {
@@ -125,7 +136,14 @@ public:
virtual int available() { virtual int available() {
TINY_GSM_YIELD(); TINY_GSM_YIELD();
if (!rx.size() && sock_connected) { if (!rx.size()) {
// Workaround: sometimes SARA R410 forgets to notify about data arrival.
// TODO: Currently we ping the module periodically,
// but maybe there's a better indicator that we need to poll
if (millis() - prev_check > 250) {
got_data = true;
prev_check = millis();
}
at->maintain(); at->maintain();
} }
return rx.size() + sock_available; return rx.size() + sock_available;
@@ -143,8 +161,15 @@ public:
cnt += chunk; cnt += chunk;
continue; continue;
} }
// TODO: Read directly into user buffer? // Workaround: sometimes SARA R410 forgets to notify about data arrival.
// TODO: Currently we ping the module periodically,
// but maybe there's a better indicator that we need to poll
if (millis() - prev_check > 250) {
got_data = true;
prev_check = millis();
}
at->maintain(); at->maintain();
// TODO: Read directly into user buffer?
if (sock_available > 0) { if (sock_available > 0) {
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux); sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
} else { } else {
@@ -183,17 +208,12 @@ private:
TinyGsmUBLOX* at; TinyGsmUBLOX* at;
uint8_t mux; uint8_t mux;
uint16_t sock_available; uint16_t sock_available;
uint32_t prev_check;
bool sock_connected; bool sock_connected;
bool got_data; bool got_data;
RxFifo rx; RxFifo rx;
}; };
//============================================================================//
//============================================================================//
// The Secure UBLOX Client Class
//============================================================================//
//============================================================================//
class GsmClientSecure : public GsmClient class GsmClientSecure : public GsmClient
{ {
@@ -211,36 +231,27 @@ public:
rx.clear(); rx.clear();
sock_connected = at->modemConnect(host, port, &mux, true); sock_connected = at->modemConnect(host, port, &mux, true);
at->sockets[mux] = this; at->sockets[mux] = this;
at->maintain();
return sock_connected; return sock_connected;
} }
}; };
//============================================================================//
//============================================================================//
// The UBLOX Modem Functions
//============================================================================//
//============================================================================//
public: public:
#ifdef GSM_DEFAULT_STREAM
TinyGsmUBLOX(Stream& stream = GSM_DEFAULT_STREAM)
#else
TinyGsmUBLOX(Stream& stream) TinyGsmUBLOX(Stream& stream)
#endif : TinyGsmModem(stream), stream(stream)
: stream(stream)
{ {
memset(sockets, 0, sizeof(sockets)); memset(sockets, 0, sizeof(sockets));
isCatM = false; // For SARA R4 and N4 series
} }
/* /*
* Basic functions * Basic functions
*/ */
bool begin(const char* pin = NULL) {
return init(pin);
}
bool init(const char* pin = NULL) { bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) { if (!testAT()) {
return false; return false;
} }
@@ -248,11 +259,52 @@ public:
if (waitResponse() != 1) { if (waitResponse() != 1) {
return false; return false;
} }
#ifdef TINY_GSM_DEBUG
sendAT(GF("+CMEE=2")); // turn on verbose error codes
#else
sendAT(GF("+CMEE=0")); // turn off error codes
#endif
waitResponse();
String name = getModemName();
DBG(GF("### Modem:"), name);
if (name.startsWith("u-blox SARA-R4") or name.startsWith("u-blox SARA-N4")) {
isCatM = true;
}
else if (name.startsWith("u-blox SARA-N2")) {
DBG(GF("### SARA N2 NB-IoT modems not supported!"), name);
}
int ret = getSimStatus(); int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) { if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin); simUnlock(pin);
return (getSimStatus() == SIM_READY);
} }
return (getSimStatus() == SIM_READY); // if the sim is ready, or it's locked but no pin has been provided, return true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
sendAT(GF("+CGMI"));
String res1;
if (waitResponse(1000L, res1) != 1) {
return "u-blox Cellular Modem";
}
res1.replace(GSM_NL "OK" GSM_NL, "");
res1.trim();
sendAT(GF("+GMM"));
String res2;
if (waitResponse(1000L, res2) != 1) {
return "u-blox Cellular Modem";
}
res2.replace(GSM_NL "OK" GSM_NL, "");
res2.trim();
return res1 + String(' ') + res2;
} }
void setBaud(unsigned long baud) { void setBaud(unsigned long baud) {
@@ -262,10 +314,7 @@ public:
bool testAT(unsigned long timeout = 10000L) { bool testAT(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) { for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF("")); sendAT(GF(""));
if (waitResponse(200) == 1) { if (waitResponse(200) == 1) return true;
delay(100);
return true;
}
delay(100); delay(100);
} }
return false; return false;
@@ -280,15 +329,21 @@ public:
} }
} }
while (stream.available()) { while (stream.available()) {
waitResponse(10, NULL, NULL); waitResponse(15, NULL, NULL);
} }
} }
bool factoryDefault() { bool factoryDefault() {
sendAT(GF("+UFACTORY=0,1")); // Factory + Reset + Echo Off if (!isCatM) {
waitResponse(); sendAT(GF("+UFACTORY=0,1")); // No factory restore, erase NVM
sendAT(GF("+CFUN=16")); // Auto-baud waitResponse();
return waitResponse() == 1; sendAT(GF("+CFUN=16")); // Reset
return waitResponse() == 1;
}
else {
sendAT(GF("&F")); // Resets the current profile, other NVM not affected
return waitResponse() == 1;
}
} }
String getModemInfo() { String getModemInfo() {
@@ -307,6 +362,14 @@ public:
return true; return true;
} }
bool hasWifi() {
return false;
}
bool hasGPRS() {
return true;
}
/* /*
* Power functions * Power functions
*/ */
@@ -315,15 +378,25 @@ public:
if (!testAT()) { if (!testAT()) {
return false; return false;
} }
sendAT(GF("+CFUN=16")); if (!isCatM)
{
sendAT(GF("+CFUN=16"));
}
else
{
sendAT(GF("+CFUN=15"));
}
if (waitResponse(10000L) != 1) { if (waitResponse(10000L) != 1) {
return false; return false;
} }
delay(3000); delay(3000); // TODO: Verify delay timing here
return init(); return init();
} }
bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED; bool poweroff() {
sendAT(GF("+CPWROFF"));
return waitResponse(40000L) == 1;
}
bool radioOff() { bool radioOff() {
sendAT(GF("+CFUN=0")); sendAT(GF("+CFUN=0"));
@@ -387,9 +460,17 @@ public:
} }
RegStatus getRegistrationStatus() { RegStatus getRegistrationStatus() {
sendAT(GF("+CGREG?")); if (isCatM) { // Check EPS registration for LTE modules
if (waitResponse(GF(GSM_NL "+CGREG:")) != 1) { sendAT(GF("+CEREG?"));
return REG_UNKNOWN; if (waitResponse(GF(GSM_NL "+CEREG:")) != 1) {
return REG_UNKNOWN;
}
}
else {
sendAT(GF("+CGREG?")); // Check GPRS registration for others
if (waitResponse(GF(GSM_NL "+CGREG:")) != 1) {
return REG_UNKNOWN;
}
} }
streamSkipUntil(','); // Skip format (0) streamSkipUntil(','); // Skip format (0)
int status = stream.readStringUntil('\n').toInt(); int status = stream.readStringUntil('\n').toInt();
@@ -412,7 +493,7 @@ public:
* Generic network functions * Generic network functions
*/ */
int getSignalQuality() { int16_t getSignalQuality() {
sendAT(GF("+CSQ")); sendAT(GF("+CSQ"));
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) { if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
return 99; return 99;
@@ -424,70 +505,118 @@ public:
bool isNetworkConnected() { bool isNetworkConnected() {
RegStatus s = getRegistrationStatus(); RegStatus s = getRegistrationStatus();
return (s == REG_OK_HOME || s == REG_OK_ROAMING); if (s == REG_OK_HOME || s == REG_OK_ROAMING)
return true;
else if (s == REG_UNKNOWN) // for some reason, it can hang at unknown..
return isGprsConnected();
else return false;
} }
bool waitForNetwork(unsigned long timeout = 60000L) { bool setURAT( uint8_t urat ) {
for (unsigned long start = millis(); millis() - start < timeout; ) { // AT+URAT=<SelectedAcT>[,<PreferredAct>[,<2ndPreferredAct>]]
if (isNetworkConnected()) {
return true; sendAT(GF("+COPS=2")); // Deregister from network
} if (waitResponse() != 1) {
delay(250); return false;
} }
return false; sendAT(GF("+URAT="), urat); // Radio Access Technology (RAT) selection
if (waitResponse() != 1) {
return false;
}
sendAT(GF("+COPS=0")); // Auto-register to the network
if (waitResponse() != 1) {
return false;
}
return restart();
} }
/*
* WiFi functions
*/
/* /*
* GPRS functions * GPRS functions
*/ */
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) { bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
gprsDisconnect(); gprsDisconnect();
sendAT(GF("+CGATT=1")); sendAT(GF("+CGATT=1")); // attach to GPRS
if (waitResponse(60000L) != 1) { if (waitResponse(360000L) != 1) {
return false; return false;
} }
sendAT(GF("+UPSD=0,1,\""), apn, '"'); // Using CGDCONT sets up an "external" PCP context, i.e. a data connection
waitResponse(); // using the external IP stack (e.g. Windows dial up) and PPP link over the
// serial interface. This is the only command set supported by the LTE-M
// and LTE NB-IoT modules (SARA-R4xx, SARA-N4xx)
if (user && strlen(user) > 0) { // Setting up the PSD profile/PDP context with the UPSD commands sets up an
sendAT(GF("+UPSD=0,2,\""), user, '"'); // "internal" PDP context, i.e. a data connection using the internal IP
// stack and related AT commands for sockets. This is what we're using for
// all of the other modules.
if (isCatM) {
if (user && strlen(user) > 0) {
sendAT(GF("+CGAUTH=1,0,\""), user, GF("\",\""), pwd, '"'); // Set the authentication
waitResponse();
}
sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"'); // Define PDP context 1
waitResponse(); waitResponse();
sendAT(GF("+CGACT=1,1")); // activate PDP profile/context 1
if (waitResponse(150000L) != 1) {
return false;
}
return true;
} }
if (pwd && strlen(pwd) > 0) {
sendAT(GF("+UPSD=0,3,\""), pwd, '"'); else {
sendAT(GF("+UPSD=0,1,\""), apn, '"'); // Set APN for PSD profile 0
waitResponse(); waitResponse();
}
sendAT(GF("+UPSD=0,7,\"0.0.0.0\"")); // Dynamic IP if (user && strlen(user) > 0) {
waitResponse(); sendAT(GF("+UPSD=0,2,\""), user, '"'); // Set user for PSD profile 0
waitResponse();
}
if (pwd && strlen(pwd) > 0) {
sendAT(GF("+UPSD=0,3,\""), pwd, '"'); // Set password for PSD profile 0
waitResponse();
}
sendAT(GF("+UPSDA=0,3")); sendAT(GF("+UPSD=0,7,\"0.0.0.0\"")); // Dynamic IP on PSD profile 0
if (waitResponse(60000L) != 1) { waitResponse();
return false;
}
// Open a GPRS context sendAT(GF("+UPSDA=0,3")); // Activate the PDP context associated with profile 0
sendAT(GF("+UPSND=0,8")); if (waitResponse(360000L) != 1) {
if (waitResponse(GF(",8,1")) != 1) { return false;
return false; }
sendAT(GF("+UPSND=0,8")); // Activate PSD profile 0
if (waitResponse(GF(",8,1")) != 1) {
return false;
}
waitResponse();
return true;
} }
waitResponse();
return true;
} }
bool gprsDisconnect() { bool gprsDisconnect() {
sendAT(GF("+UPSDA=0,4"));
if (waitResponse(60000L) != 1)
return false;
sendAT(GF("+CGATT=0")); // LTE-M and NB-IoT modules do not support UPSx commands
if (waitResponse(60000L) != 1) if (isCatM) {
sendAT(GF("+CGACT=1,0")); // Deactivate PDP context 1
if (waitResponse(40000L) != 1) {
return false;
}
}
else {
sendAT(GF("+UPSDA=0,4")); // Deactivate the PDP context associated with profile 0
if (waitResponse(360000L) != 1)
return false;
}
sendAT(GF("+CGATT=0")); // detach from GPRS
if (waitResponse(360000L) != 1)
return false; return false;
return true; return true;
@@ -503,25 +632,40 @@ public:
if (res != 1) if (res != 1)
return false; return false;
return localIP() != 0; return localIP() != IPAddress(0,0,0,0);
} }
/*
* IP Address functions
*/
String getLocalIP() { String getLocalIP() {
sendAT(GF("+UPSND=0,0")); // LTE-M and NB-IoT modules do not support UPSx commands
if (waitResponse(GF(GSM_NL "+UPSND:")) != 1) { if (isCatM) {
return ""; sendAT(GF("+CGPADDR"));
if (waitResponse(GF(GSM_NL "+CGPADDR:")) != 1) {
return "";
}
streamSkipUntil(','); // Skip context id
String res = stream.readStringUntil('\r');
if (waitResponse() != 1) {
return "";
}
return res;
} }
streamSkipUntil(','); // Skip PSD profile else {
streamSkipUntil('\"'); // Skip request type sendAT(GF("+UPSND=0,0"));
String res = stream.readStringUntil('\"'); if (waitResponse(GF(GSM_NL "+UPSND:")) != 1) {
if (waitResponse() != 1) { return "";
return ""; }
streamSkipUntil(','); // Skip PSD profile
streamSkipUntil('\"'); // Skip request type
String res = stream.readStringUntil('\"');
if (waitResponse() != 1) {
return "";
}
return res;
} }
return res;
}
IPAddress localIP() {
return TinyGsmIpFromString(getLocalIP());
} }
/* /*
@@ -580,7 +724,7 @@ public:
*/ */
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE; uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
int getBattPercent() { int8_t getBattPercent() {
sendAT(GF("+CIND?")); sendAT(GF("+CIND?"));
if (waitResponse(GF(GSM_NL "+CIND:")) != 1) { if (waitResponse(GF(GSM_NL "+CIND:")) != 1) {
return 0; return 0;
@@ -591,11 +735,15 @@ public:
return res; return res;
} }
/*
* Client related functions
*/
protected: protected:
bool modemConnect(const char* host, uint16_t port, uint8_t* mux, bool ssl = false) { bool modemConnect(const char* host, uint16_t port, uint8_t* mux, bool ssl = false) {
sendAT(GF("+USOCR=6")); sendAT(GF("+USOCR=6")); // create a socket
if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) { if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) { // reply is +USOCR: ## of socket created
return false; return false;
} }
*mux = stream.readStringUntil('\n').toInt(); *mux = stream.readStringUntil('\n').toInt();
@@ -614,12 +762,28 @@ protected:
//sendAT(GF("+USOSO="), *mux, GF(",6,2,30000")); //sendAT(GF("+USOSO="), *mux, GF(",6,2,30000"));
//waitResponse(); //waitResponse();
// connect on the allocated socket
// TODO: Use faster "asynchronous" connection?
// We would have to wait for the +UUSOCO URC to verify connection
sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port); sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port);
int rsp = waitResponse(75000L); int rsp = waitResponse(120000L);
return (1 == rsp); return (1 == rsp);
} }
int modemSend(const void* buff, size_t len, uint8_t mux) { bool modemDisconnect(uint8_t mux) {
TINY_GSM_YIELD();
if (isCatM) { // These modems allow a faster "asynchronous" close
sendAT(GF("+USOCL="), mux, GF(",1"));
int rsp = waitResponse(120000L);
return (1 == rsp); // but it still can take up to 120s to get a response
}
else { // no async close
sendAT(GF("+USOCL="), mux);
return (1 == waitResponse());
}
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+USOWR="), mux, ',', len); sendAT(GF("+USOWR="), mux, ',', len);
if (waitResponse(GF("@")) != 1) { if (waitResponse(GF("@")) != 1) {
return 0; return 0;
@@ -634,6 +798,7 @@ protected:
streamSkipUntil(','); // Skip mux streamSkipUntil(','); // Skip mux
int sent = stream.readStringUntil('\n').toInt(); int sent = stream.readStringUntil('\n').toInt();
waitResponse(); waitResponse();
maintain(); // look for a very quick response
return sent; return sent;
} }
@@ -659,12 +824,15 @@ protected:
size_t modemGetAvailable(uint8_t mux) { size_t modemGetAvailable(uint8_t mux) {
sendAT(GF("+USORD="), mux, ",0"); sendAT(GF("+USORD="), mux, ",0");
size_t result = 0; size_t result = 0;
if (waitResponse(GF(GSM_NL "+USORD:")) == 1) { uint8_t res = waitResponse(GF(GSM_NL "+USORD:"));
// Will give error "operation not allowed" when attempting to read a socket
// that you have already told to close
if (res == 1) {
streamSkipUntil(','); // Skip mux streamSkipUntil(','); // Skip mux
result = stream.readStringUntil('\n').toInt(); result = stream.readStringUntil('\n').toInt();
waitResponse(); waitResponse();
} }
if (!result) { if (!result && res != 2 && res != 3) { // Don't check modemGetConnected after an error
sockets[mux]->sock_connected = modemGetConnected(mux); sockets[mux]->sock_connected = modemGetConnected(mux);
} }
return result; return result;
@@ -672,43 +840,34 @@ protected:
bool modemGetConnected(uint8_t mux) { bool modemGetConnected(uint8_t mux) {
sendAT(GF("+USOCTL="), mux, ",10"); sendAT(GF("+USOCTL="), mux, ",10");
if (waitResponse(GF(GSM_NL "+USOCTL:")) != 1) uint8_t res = waitResponse(GF(GSM_NL "+USOCTL:"));
if (res != 1)
return false; return false;
streamSkipUntil(','); // Skip mux streamSkipUntil(','); // Skip mux
streamSkipUntil(','); // Skip type streamSkipUntil(','); // Skip type
int result = stream.readStringUntil('\n').toInt(); int result = stream.readStringUntil('\n').toInt();
// 0: the socket is in INACTIVE status (it corresponds to CLOSED status
// defined in RFC793 "TCP Protocol Specification" [112])
// 1: the socket is in LISTEN status
// 2: the socket is in SYN_SENT status
// 3: the socket is in SYN_RCVD status
// 4: the socket is in ESTABILISHED status
// 5: the socket is in FIN_WAIT_1 status
// 6: the socket is in FIN_WAIT_2 status
// 7: the sokcet is in CLOSE_WAIT status
// 8: the socket is in CLOSING status
// 9: the socket is in LAST_ACK status
// 10: the socket is in TIME_WAIT status
waitResponse(); waitResponse();
return result != 0; return (result != 0);
} }
public: public:
/* Utilities */ /*
Utilities
template<typename T> */
void streamWrite(T last) {
stream.print(last);
}
template<typename T, typename... Args>
void streamWrite(T head, Args... tail) {
stream.print(head);
streamWrite(tail...);
}
bool streamSkipUntil(char c) {
const unsigned long timeout = 1000L;
unsigned long startMillis = millis();
while (millis() - startMillis < timeout) {
while (millis() - startMillis < timeout && !stream.available()) {
TINY_GSM_YIELD();
}
if (stream.read() == c)
return true;
}
return false;
}
template<typename... Args> template<typename... Args>
void sendAT(Args... cmd) { void sendAT(Args... cmd) {
@@ -802,6 +961,7 @@ public:
protected: protected:
GsmClient* sockets[TINY_GSM_MUX_COUNT]; GsmClient* sockets[TINY_GSM_MUX_COUNT];
bool isCatM;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,9 @@
#ifndef TinyGsmCommon_h #ifndef TinyGsmCommon_h
#define TinyGsmCommon_h #define TinyGsmCommon_h
// The current library version number
#define TINYGSM_VERSION "0.6.1"
#if defined(SPARK) || defined(PARTICLE) #if defined(SPARK) || defined(PARTICLE)
#include "Particle.h" #include "Particle.h"
#elif defined(ARDUINO) #elif defined(ARDUINO)
@@ -31,6 +34,10 @@
#define TINY_GSM_YIELD() { delay(0); } #define TINY_GSM_YIELD() { delay(0); }
#endif #endif
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 256
#endif
#define TINY_GSM_ATTR_NOT_AVAILABLE __attribute__((error("Not available on this modem type"))) #define TINY_GSM_ATTR_NOT_AVAILABLE __attribute__((error("Not available on this modem type")))
#define TINY_GSM_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented"))) #define TINY_GSM_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented")))
@@ -69,6 +76,7 @@ namespace {
} }
} }
#else #else
#define DBG_PLAIN(...)
#define DBG(...) #define DBG(...)
#endif #endif
@@ -194,4 +202,137 @@ String TinyGsmDecodeHex16bit(String &instr) {
return result; return result;
} }
class TinyGsmModem
{
public:
TinyGsmModem(Stream& stream)
: stream(stream)
{}
/*
* Basic functions
*/
// Prepare the modem for further functionality
virtual bool init(const char* pin = NULL) = 0;
// Begin is redundant with init
virtual bool begin(const char* pin = NULL) {
return init(pin);
}
// Returns a string with the chip name
virtual String getModemName() = 0;
// Sets the serial communication baud rate
virtual void setBaud(unsigned long baud) = 0;
// Checks that the modem is responding to standard AT commands
virtual bool testAT(unsigned long timeout = 10000L) = 0;
// Holds open communication with the modem waiting for data to come in
virtual void maintain() = 0;
// Resets all modem chip settings to factor defaults
virtual bool factoryDefault() = 0;
// Returns the response to a get info request. The format varies by modem.
virtual String getModemInfo() = 0;
// Answers whether types of communication are available on this modem
virtual bool hasSSL() = 0;
virtual bool hasWifi() = 0;
virtual bool hasGPRS() = 0;
/*
* Power functions
*/
virtual bool restart() = 0;
virtual bool poweroff() = 0;
/*
* SIM card functions - only apply to cellular modems
*/
virtual bool simUnlock(const char *pin) { return false; }
virtual String getSimCCID() { return ""; }
virtual String getIMEI() { return ""; }
virtual String getOperator() { return ""; }
/*
* Generic network functions
*/
virtual int16_t getSignalQuality() = 0;
// NOTE: this returns whether the modem is registered on the cellular or WiFi
// network NOT whether GPRS or other internet connections are available
virtual bool isNetworkConnected() = 0;
virtual bool waitForNetwork(unsigned long timeout = 60000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
if (isNetworkConnected()) {
return true;
}
delay(250);
}
return false;
}
/*
* WiFi functions - only apply to WiFi modems
*/
virtual bool networkConnect(const char* ssid, const char* pwd) { return false; }
virtual bool networkDisconnect() { return false; }
/*
* GPRS functions - only apply to cellular modems
*/
virtual bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
return false;
}
virtual bool gprsDisconnect() { return false; }
virtual bool isGprsConnected() { return false; }
/*
* IP Address functions
*/
virtual String getLocalIP() = 0;
virtual IPAddress localIP() {
return TinyGsmIpFromString(getLocalIP());
}
/*
Utilities
*/
template<typename T>
void streamWrite(T last) {
stream.print(last);
}
template<typename T, typename... Args>
void streamWrite(T head, Args... tail) {
stream.print(head);
streamWrite(tail...);
}
bool streamSkipUntil(const char c, const unsigned long timeout = 1000L) {
unsigned long startMillis = millis();
while (millis() - startMillis < timeout) {
while (millis() - startMillis < timeout && !stream.available()) {
TINY_GSM_YIELD();
}
if (stream.read() == c)
return true;
}
return false;
}
public:
Stream& stream;
};
#endif #endif

View File

@@ -4,19 +4,23 @@
* and allows direct AT commands access * and allows direct AT commands access
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
**************************************************************/ **************************************************************/
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 #define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266 // #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE // #define TINY_GSM_MODEM_XBEE
@@ -79,4 +83,3 @@ void loop() {
delay(0); delay(0);
} }
} }

View File

@@ -4,7 +4,7 @@
* between an Arduino and the modem. * between an Arduino and the modem.
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
**************************************************************/ **************************************************************/

View File

@@ -5,19 +5,23 @@
* or from http://librarymanager/all#StreamDebugger * or from http://librarymanager/all#StreamDebugger
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
**************************************************************/ **************************************************************/
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 #define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266 // #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE // #define TINY_GSM_MODEM_XBEE
@@ -183,4 +187,3 @@ void loop() {
delay(1000); delay(1000);
} }
} }

View File

@@ -5,19 +5,23 @@
* or from http://librarymanager/all#StreamDebugger * or from http://librarymanager/all#StreamDebugger
* *
* TinyGSM Getting Started guide: * TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme * https://tiny.cc/tinygsm-readme
* *
**************************************************************/ **************************************************************/
// Select your modem: // Select your modem:
#define TINY_GSM_MODEM_SIM800 #define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_UBLOX // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266 // #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE // #define TINY_GSM_MODEM_XBEE
@@ -67,4 +71,3 @@ void setup() {
void loop() { void loop() {
} }

View File

@@ -3,6 +3,7 @@
* DO NOT USE THIS - this is just a compilation test! * DO NOT USE THIS - this is just a compilation test!
* *
**************************************************************/ **************************************************************/
// #define TINY_GSM_MODEM_SIM800
#include <TinyGsmClient.h> #include <TinyGsmClient.h>
@@ -77,4 +78,3 @@ void loop() {
modem.networkDisconnect(); modem.networkDisconnect();
#endif #endif
} }