├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── examples ├── 01_QuickStart_LED │ └── QuickStart_LED.ino ├── 02_QuickStart_DHT11 │ └── QuickStart_DHT11.ino ├── 03_AntoSimple │ └── AntoSimple.ino ├── 04_Basic_MQTT │ └── Basic_MQTT.ino └── 05_Basic_HTTP │ └── Basic_HTTP.ino ├── keywords.txt ├── library.properties └── src ├── AntoCommon.h ├── AntoHTTP.cpp ├── AntoHTTP.h ├── AntoIO.cpp ├── AntoIO.h ├── AntoMQTT.cpp ├── AntoMQTT.h ├── AntoWiFi.h ├── json ├── ArduinoJson.h ├── include │ ├── ArduinoJson.h │ └── ArduinoJson │ │ ├── Arduino │ │ ├── Print.hpp │ │ └── String.hpp │ │ ├── Configuration.hpp │ │ ├── DynamicJsonBuffer.hpp │ │ ├── Internals │ │ ├── BlockJsonBuffer.hpp │ │ ├── Comments.hpp │ │ ├── DummyPrint.hpp │ │ ├── DynamicStringBuilder.hpp │ │ ├── Encoding.hpp │ │ ├── ForceInline.hpp │ │ ├── IndentedPrint.hpp │ │ ├── JsonBufferAllocated.hpp │ │ ├── JsonFloat.hpp │ │ ├── JsonInteger.hpp │ │ ├── JsonParser.hpp │ │ ├── JsonPrintable.hpp │ │ ├── JsonVariantContent.hpp │ │ ├── JsonVariantType.hpp │ │ ├── JsonWriter.hpp │ │ ├── List.hpp │ │ ├── ListConstIterator.hpp │ │ ├── ListIterator.hpp │ │ ├── ListNode.hpp │ │ ├── Parse.hpp │ │ ├── Prettyfier.hpp │ │ ├── ReferenceType.hpp │ │ ├── StaticStringBuilder.hpp │ │ ├── StreamPrintAdapter.hpp │ │ └── Unparsed.hpp │ │ ├── JsonArray.hpp │ │ ├── JsonArray.ipp │ │ ├── JsonArraySubscript.hpp │ │ ├── JsonBuffer.hpp │ │ ├── JsonObject.hpp │ │ ├── JsonObject.ipp │ │ ├── JsonObjectKey.hpp │ │ ├── JsonObjectSubscript.hpp │ │ ├── JsonPair.hpp │ │ ├── JsonVariant.hpp │ │ ├── JsonVariant.ipp │ │ ├── JsonVariantBase.hpp │ │ ├── StaticJsonBuffer.hpp │ │ └── TypeTraits │ │ ├── EnableIf.hpp │ │ ├── IsFloatingPoint.hpp │ │ ├── IsIntegral.hpp │ │ ├── IsReference.hpp │ │ ├── IsSame.hpp │ │ ├── RemoveConst.hpp │ │ └── RemoveReference.hpp └── src │ ├── ArduinoJson.h │ ├── CMakeLists.txt │ ├── Internals │ ├── Comments.cpp │ ├── Encoding.cpp │ ├── IndentedPrint.cpp │ ├── JsonParser.cpp │ ├── List.cpp │ ├── Prettyfier.cpp │ └── StaticStringBuilder.cpp │ ├── JsonArray.cpp │ ├── JsonBuffer.cpp │ ├── JsonObject.cpp │ └── JsonVariant.cpp ├── mqtt ├── MQTTClient.h ├── MQTTTest.h ├── Network.cpp ├── Network.h ├── Timer.cpp ├── Timer.h ├── YunMQTTClient.cpp ├── YunMQTTClient.h └── lib │ ├── FP.h │ ├── MQTTClient.h │ ├── MQTTConnect.h │ ├── MQTTConnectClient.c │ ├── MQTTDeserializePublish.c │ ├── MQTTPacket.c │ ├── MQTTPacket.h │ ├── MQTTPublish.h │ ├── MQTTSerializePublish.c │ ├── MQTTSubscribe.h │ ├── MQTTSubscribeClient.c │ ├── MQTTUnsubscribe.h │ └── MQTTUnsubscribeClient.c └── wifimanager ├── WiFiManager.cpp └── WiFiManager.h /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .* 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.7.3 (2017-06-18) 2 | * remove number from the names of example folders for library manager compatability 3 | ## 0.7.2 (2017-04-15) 4 | * add shortcuts from AntoHTTP and AntoMQTT to AntoIO 5 | ## 0.7.1 (2017-04-10) 6 | * add reconnect procedure inside `AntoMQTT::loop()` 7 | ## 0.7.0 (2017-04-10) 8 | * distract arrived messages in `AntoMQTT::messageHandler()` into [thing, channel, payload] 9 | ## 0.6.4 (2017-04-10) 10 | * add `AntoIO::begin()` to simplify the process 11 | ## 0.6.3 (2017-04-09) 12 | * add `AntoIO::http.setHost()` and `AntoIO::mqtt.setHost()` functions to change URL of the server 13 | ## 0.6.2 (2017-04-09) 14 | * remove username and password parameters from `AntoIO::mqtt.connect()` 15 | ## 0.6.1 (2017-04-09) 16 | * MQTT over SSL/TLS supported 17 | * New structure of the library 18 | ## 0.5.2 (2016-06-16) 19 | * Add new overload methods for `AntoIO::pub()` (Integer, String, Character and Floating point) 20 | * Edit example BasicMQTT 21 | ## 0.5.0 (2016-06-16) 22 | * Add WiFi Manager (Smart config) 23 | * Add example read temperature and humidity from DHT11 and send to server 24 | ## 0.4.1 (2016-05-31) 25 | * Change client ID in MQTT connection 26 | * Reformat API 27 | * Add quick start anto example 28 | ## 0.3.0 (2016-05-30) 29 | * Add MQTT subscribe or HTTP request for data service 30 | ## 0.2.0 (2016-04-23) 31 | * Add MQTT client 32 | * Modify HTTP request method 33 | ## 0.1.1 (2016-01-09) 34 | * Delete internal libraries 35 | ## 0.1.0 (2015-11-28) 36 | * Add Get/Set data channel via HTTP 37 | * First release 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 AntoIO, Srikote Naewchampa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Anto client library for ESP8266-Arduino 2 | ESP8266-AntoIO provides common and easy way to connect your ESP8266 to Anto.io IoT platform service. 3 | 4 | ## Stable version 5 | 0.7.3 6 | 7 | ## Quick start 8 | 9 | 10 | ## Port 11 | Make sure that your network or firewall are allowed to connect following port 12 | * HTTP: 80 13 | * MQTT: 1883 14 | 15 | ## Installation 16 | * Download and install virtual COM port for hardware connection 17 | > For NodeMCU version 0.9 18 | > For NodeMCU Version 1.0 19 | * Download and install Arduino IDE 1.6.9 or above from https://www.arduino.cc/en/Main/Software 20 | * After installation completed, open Arduino IDE and click Preferences 21 | * Enter `http://arduino.esp8266.com/stable/package_esp8266com_index.json` in Additional Board Manager URLs 22 | * Install ES8266 main library by go to Tools > Boards Manager. Search for `esp8266` and click install 23 | * Download this library from and extract your file into folder `Documents\Arduino\Libraries` 24 | * Register and login to and start build your IoT project 25 | * Have fun & Share! 26 | 27 | ## Quick start usage example - Control 3 LED ## 28 | ```c++ 29 | #include 30 | 31 | const char *ssid = "your access point SSID"; 32 | const char *pass = "access point password"; 33 | const char *user = "your username"; 34 | const char *token = "your token"; 35 | const char *thing = "your thing"; 36 | 37 | // initialize AntoIO instance 38 | AntoIO anto(user, token, thing); 39 | 40 | int value = 0; 41 | 42 | void setup() { 43 | Serial.begin(115200); 44 | delay(10); 45 | 46 | Serial.println(); 47 | Serial.println(); 48 | Serial.print("Anto library version: "); 49 | Serial.println(anto.getVersion()); 50 | 51 | 52 | Serial.print("\nTrying to connect "); 53 | Serial.print(ssid); 54 | Serial.println("..."); 55 | 56 | anto.begin(ssid, pass, messageReceived); 57 | Serial.println("\nConnected Anto done"); 58 | 59 | //Subscript Channels 60 | anto.sub("LED1"); 61 | anto.sub("LED2"); 62 | anto.sub("LED3"); 63 | 64 | //Port output 65 | pinMode(D1,OUTPUT); 66 | pinMode(D2,OUTPUT); 67 | pinMode(D3,OUTPUT); 68 | } 69 | 70 | void loop() { 71 | anto.mqtt.loop(); 72 | } 73 | 74 | 75 | // a callback function for arriving data. 76 | void messageReceived(String thing, String channel, String payload) { 77 | 78 | Serial.print("Recieved: "); 79 | Serial.print(thing); 80 | Serial.print("/"); 81 | Serial.print(channel); 82 | Serial.print("-> "); 83 | Serial.println(payload); 84 | 85 | if(channel.equals("LED1")){ 86 | value = payload.toInt(); 87 | if(value == 1){ 88 | digitalWrite(D1,HIGH); 89 | } 90 | else{ 91 | digitalWrite(D1,LOW); 92 | } 93 | 94 | } 95 | else if(channel.equals("LED2")){ 96 | value = payload.toInt(); 97 | if(value == 1){ 98 | digitalWrite(D2,HIGH); 99 | } 100 | else{ 101 | digitalWrite(D2,LOW); 102 | } 103 | } 104 | else if(channel.equals("LED3")){ 105 | value = payload.toInt(); 106 | if(value == 1){ 107 | digitalWrite(D3,HIGH); 108 | } 109 | else{ 110 | digitalWrite(D3,LOW); 111 | } 112 | } 113 | } 114 | ``` 115 | 116 | ###### TODO ###### 117 | - Fix `AntoMQTT::messageHandler()` after reconnected from `AntoIO::mqtt.loop()` 118 | - Other callback functions (OnPublished, OnDisconnected, OnConnected) 119 | - Request via HTTPS 120 | - Increase speed of keep-alive message 121 | - Timer interrupt and remove `AntoMQTT::loop()` 122 | -------------------------------------------------------------------------------- /examples/01_QuickStart_LED/QuickStart_LED.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example is meant to be used as a starting point 3 | * for working with Anto.io services 4 | * 5 | * 2017/06/17 6 | * by Anto.io team 7 | * 8 | */ 9 | 10 | #include 11 | 12 | const char *ssid = "your access point SSID"; 13 | const char *pass = "access point password"; 14 | const char *user = "your username"; 15 | const char *token = "your token"; 16 | const char *thing = "your thing"; 17 | 18 | // initialize AntoIO instance 19 | AntoIO anto(user, token, thing); 20 | 21 | int value = 0; 22 | 23 | void setup() { 24 | Serial.begin(115200); 25 | delay(10); 26 | 27 | Serial.println(); 28 | Serial.println(); 29 | Serial.print("Anto library version: "); 30 | Serial.println(anto.getVersion()); 31 | 32 | 33 | Serial.print("\nTrying to connect "); 34 | Serial.print(ssid); 35 | Serial.println("..."); 36 | 37 | anto.begin(ssid, pass, messageReceived); 38 | Serial.println("\nConnected Anto done"); 39 | 40 | //Subscript Channels 41 | anto.sub("LED1"); 42 | anto.sub("LED2"); 43 | anto.sub("LED3"); 44 | 45 | //Port output 46 | pinMode(D1,OUTPUT); 47 | pinMode(D2,OUTPUT); 48 | pinMode(D3,OUTPUT); 49 | } 50 | 51 | void loop() { 52 | anto.mqtt.loop(); 53 | } 54 | 55 | 56 | // a callback function for arriving data. 57 | void messageReceived(String thing, String channel, String payload) { 58 | 59 | Serial.print("Recieved: "); 60 | Serial.print(thing); 61 | Serial.print("/"); 62 | Serial.print(channel); 63 | Serial.print("-> "); 64 | Serial.println(payload); 65 | 66 | if(channel.equals("LED1")){ 67 | value = payload.toInt(); 68 | if(value == 1){ 69 | digitalWrite(D1,HIGH); 70 | } 71 | else{ 72 | digitalWrite(D1,LOW); 73 | } 74 | 75 | } 76 | else if(channel.equals("LED2")){ 77 | value = payload.toInt(); 78 | if(value == 1){ 79 | digitalWrite(D2,HIGH); 80 | } 81 | else{ 82 | digitalWrite(D2,LOW); 83 | } 84 | } 85 | else if(channel.equals("LED3")){ 86 | value = payload.toInt(); 87 | if(value == 1){ 88 | digitalWrite(D3,HIGH); 89 | } 90 | else{ 91 | digitalWrite(D3,LOW); 92 | } 93 | } 94 | } 95 | 96 | 97 | -------------------------------------------------------------------------------- /examples/02_QuickStart_DHT11/QuickStart_DHT11.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example is meant to be used as a starting point 3 | * for working with Anto.io services and DHT sensor module 4 | * 5 | * 2017/06/17 6 | * by Anto.io team 7 | * 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #define DHTPIN 2 //port D4 14 | #define DHTTYPE DHT11 15 | 16 | const char *ssid = "your access point SSID"; 17 | const char *pass = "access point password"; 18 | const char *user = "your username"; 19 | const char *token = "your token"; 20 | const char *thing = "your thing"; 21 | 22 | // initialize AntoIO instance 23 | AntoIO anto(user, token, thing); 24 | 25 | //initialize dht instance 26 | DHT dht(DHTPIN,DHTTYPE); 27 | 28 | void setup() { 29 | Serial.begin(115200); 30 | delay(10); 31 | 32 | Serial.println(); 33 | Serial.println(); 34 | Serial.print("Anto library version: "); 35 | Serial.println(anto.getVersion()); 36 | 37 | Serial.print("\nTrying to connect "); 38 | Serial.print(ssid); 39 | Serial.println("..."); 40 | 41 | anto.begin(ssid, pass, messageReceived); 42 | Serial.println("\nConnected Anto done"); 43 | 44 | //dht start 45 | dht.begin(); 46 | } 47 | 48 | 49 | void loop() { 50 | anto.mqtt.loop(); 51 | 52 | if (!anto.mqtt.isConnected()) 53 | Serial.println("Disconnected"); 54 | 55 | float temp = dht.readTemperature(); 56 | float humid = dht.readHumidity(); 57 | 58 | Serial.print("TEMP: "); 59 | Serial.println(temp); 60 | 61 | Serial.print("HUMID: "); 62 | Serial.println(humid); 63 | 64 | if(temp >= 0){ 65 | anto.pub("Temp",temp); 66 | } 67 | 68 | if(humid >= 0){ 69 | anto.pub("Humid",humid); 70 | } 71 | 72 | delay(1000); 73 | } 74 | 75 | // a callback function for arriving data. 76 | void messageReceived(String thing, String channel, String payload) { 77 | Serial.print("Recieved: "); 78 | Serial.print(thing); 79 | Serial.print("/"); 80 | Serial.print(channel); 81 | Serial.print("-> "); 82 | Serial.println(payload); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /examples/03_AntoSimple/AntoSimple.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example is meant to be used for beginner 3 | * 4 | * 2017/04/14 5 | * by Anto.io team 6 | * 7 | */ 8 | 9 | #include 10 | 11 | const char *ssid = "your access point SSID"; 12 | const char *pass = "access point password"; 13 | const char *user = "your username"; 14 | const char *token = "your token"; 15 | const char *thing = "your thing"; 16 | 17 | AntoIO anto(user, token, thing); 18 | 19 | void setup() { 20 | Serial.begin(9600); 21 | anto.begin(ssid, pass, messageReceived); 22 | anto.sub("channel"); 23 | } 24 | 25 | void loop() { 26 | anto.loop(); 27 | anto.pub("other channel", 1); 28 | 29 | delay(3000); 30 | } 31 | 32 | void messageReceived(String thing, String channel, String payload) { 33 | Serial.print("Recieved: "); 34 | Serial.print(thing); 35 | Serial.print("/"); 36 | Serial.print(channel); 37 | Serial.print("-> "); 38 | Serial.println(payload); 39 | } 40 | -------------------------------------------------------------------------------- /examples/04_Basic_MQTT/Basic_MQTT.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example is meant to be used as a starting point 3 | * for working with MQTT publish and subscribe 4 | * 5 | * 2017/02/07 6 | * by Anto.io team 7 | * 8 | */ 9 | 10 | #include 11 | 12 | const char *ssid = "your access point SSID"; 13 | const char *pass = "access point password"; 14 | const char *user = "your username"; 15 | const char *token = "your token"; 16 | const char *thing = "your thing"; 17 | 18 | AntoIO anto(user, token, thing); 19 | 20 | uint8_t loopCount = 0; 21 | 22 | void setup() { 23 | Serial.begin(9600); 24 | 25 | Serial.println(); 26 | Serial.println(); 27 | Serial.print("Anto library version: "); 28 | Serial.println(anto.getVersion()); 29 | 30 | Serial.print("\nTrying to connect "); 31 | Serial.print(ssid); 32 | Serial.println("..."); 33 | 34 | while (!anto.wifi.begin(ssid, pass)); 35 | Serial.println("\nConnected, trying to connect to broker..."); 36 | 37 | // the last boolean argument is for indicating 38 | // that you want this connection to be secured 39 | // by TLS or not. 40 | // 41 | // Secured connection will be 42 | // slower than secured one. 43 | while (!anto.mqtt.connect(true)); 44 | Serial.println("\nConnected"); 45 | 46 | anto.mqtt.onData(messageReceived); 47 | anto.mqtt.sub("channel"); 48 | } 49 | 50 | void loop() { 51 | anto.mqtt.loop(); 52 | 53 | ++loopCount; 54 | 55 | anto.mqtt.pub("other_channel", (loopCount % 2 ? "value" : "other_value")); 56 | 57 | delay(3000); 58 | } 59 | 60 | // a callback function for arriving data. 61 | void messageReceived(String thing, String channel, String payload) { 62 | Serial.print("Recieved: "); 63 | Serial.print(thing); 64 | Serial.print("/"); 65 | Serial.print(channel); 66 | Serial.print("-> "); 67 | Serial.println(payload); 68 | } 69 | -------------------------------------------------------------------------------- /examples/05_Basic_HTTP/Basic_HTTP.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * This example is meant to be used as a starting point 3 | * for working with HTTP request 4 | * 5 | * 2017/02/07 6 | * by Anto.io team 7 | * 8 | */ 9 | 10 | #include 11 | 12 | const char *ssid = "your access point SSID"; 13 | const char *pass = "access point password"; 14 | const char *user = "your username"; 15 | const char *token = "your token"; 16 | const char *thing = "your thing"; 17 | 18 | // initialize AntoIO instance 19 | AntoIO anto(user, token, thing); 20 | // for counting how many loop has passed 21 | uint8_t loopCount = 0; 22 | 23 | void setup() { 24 | Serial.begin(9600); 25 | 26 | Serial.println(); 27 | Serial.println(); 28 | Serial.print("Anto library version: "); 29 | Serial.println(anto.getVersion()); 30 | 31 | Serial.print("\nTrying to connect "); 32 | Serial.print(ssid); 33 | Serial.println("..."); 34 | while (!anto.wifi.begin(ssid, pass)); 35 | Serial.println("\nConnected"); 36 | } 37 | 38 | void loop() { 39 | ++loopCount; 40 | 41 | // test updating digital, analog and string value 42 | testUpdateDigital(loopCount); 43 | testUpdateAnalog(loopCount); 44 | testUpdateString(loopCount); 45 | delay(3000); 46 | 47 | // test reading digital, analog and string value 48 | testGetDigital(); 49 | testGetAnalog(); 50 | testGetString(); 51 | delay(3000); 52 | 53 | // test requesting data service 54 | testService(); 55 | delay(3000); 56 | } 57 | 58 | void testService(void) 59 | { 60 | String str; 61 | 62 | Serial.println("requesting 'gas.95e20.price' data service ..."); 63 | 64 | // request for gas.95e20.price data service 65 | // and store the service value in 'str' 66 | if (anto.http.request(str, "gas.95e20.price")) 67 | Serial.println(str); 68 | else 69 | Serial.println("Error"); 70 | } 71 | 72 | void testUpdateDigital(uint8_t i) 73 | { 74 | Serial.println("Updating 'your_digital_channel' channel ..."); 75 | 76 | // if 'loopCount' is even number, update 'your_digital_channel' channel to 0 77 | // otherwise, update it to 1 78 | if (anto.http.digitalUpdate("your_digital_channel", (i % 2 ? 0 : 1))) 79 | Serial.println("Done"); 80 | else 81 | Serial.println("Error"); 82 | } 83 | 84 | void testUpdateAnalog(uint8_t i) 85 | { 86 | Serial.println("Updating 'your_analog_channel' channel ..."); 87 | 88 | // if 'loopCount' is even number, update 'your_analog_channel' channel to 1234 89 | // otherwise, update it to 5678 90 | if (anto.http.analogUpdate("your_analog_channel", (i % 2 ? 1234 : 5678))) 91 | Serial.println("Done"); 92 | else 93 | Serial.println("Error"); 94 | } 95 | 96 | void testUpdateString(uint8_t i) 97 | { 98 | Serial.println("Updating 'your_string_channel' channel ..."); 99 | 100 | // if 'loopCount' is even number, update 'your_string_channel' channel to Kohpai 101 | // otherwise, update it to George 102 | if (anto.http.stringUpdate("your_string_channel", (i % 2 ? "Kohpai" : "George"))) 103 | Serial.println("Done"); 104 | else 105 | Serial.println("Error"); 106 | } 107 | 108 | void testGetDigital(void) 109 | { 110 | bool i = 0; 111 | 112 | Serial.println("Getting 'your_digital_channel' channel ..."); 113 | 114 | // get 'your_digital_channel' channel value and store it in 'i' 115 | if (anto.http.digitalGet(i, "your_digital_channel")) 116 | Serial.println(i); 117 | else 118 | Serial.println("Error"); 119 | } 120 | 121 | void testGetAnalog(void) 122 | { 123 | int32_t i; 124 | 125 | Serial.println("Getting 'your_analog_channel' channel ..."); 126 | 127 | // get 'your_analog_channel' channel value and store it in 'i' 128 | if (anto.http.analogGet(i, "your_analog_channel")) 129 | Serial.println(i); 130 | else 131 | Serial.println("Error"); 132 | } 133 | 134 | void testGetString(void) 135 | { 136 | String str; 137 | 138 | Serial.println("Getting 'your_string_channel' channel ..."); 139 | 140 | // get 'your_string_channel' channel value and store it in 'str' 141 | if (anto.http.stringGet(str, "your_string_channel")) 142 | Serial.println(str); 143 | else 144 | Serial.println("Error"); 145 | } 146 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Anto-ESP8266-Arduino 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | AntoIO KEYWORD1 10 | AntoHTTP KEYWORD1 11 | AntoMQTT KEYWORD1 12 | AntoWiFi KEYWORD1 13 | 14 | ####################################### 15 | # Methods and Functions (KEYWORD2) 16 | ####################################### 17 | 18 | smartconfig KEYWORD2 19 | 20 | digitalUpdate KEYWORD2 21 | analogUpdate KEYWORD2 22 | stringUpdate KEYWORD2 23 | digitalGet KEYWORD2 24 | analogGet KEYWORD2 25 | stringGet KEYWORD2 26 | httpRequest KEYWORD2 27 | request KEYWORD2 28 | removeHeader KEYWORD2 29 | setHost KEYWORD2 30 | 31 | getVersion KEYWORD2 32 | begin KEYWORD2 33 | 34 | loop KEYWORD2 35 | onData KEYWORD2 36 | disconnect KEYWORD2 37 | isConnected KEYWORD2 38 | connect KEYWORD2 39 | pub KEYWORD2 40 | sub KEYWORD2 41 | service KEYWORD2 42 | 43 | ####################################### 44 | # Constants (LITERAL1) 45 | ####################################### 46 | 47 | ANTO_MQTT_PORT LITERAL1 48 | ANTO_MQTTS_PORT LITERAL1 49 | ANTO_RAND_STR_LEN LITERAL1 50 | ANTO_GET LITERAL1 51 | ANTO_SET LITERAL1 52 | ANTO_VER LITERAL1 53 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=anto-esp8266-arduino 2 | version=0.7.3 3 | author=Anto.io developers 4 | maintainer=Anto.io developers 5 | sentence=Enables ESP8266 to connect to Anto.io IoT platform. 6 | paragraph=ESP8266-AntoIO provides common and easy method to publish/retrive data from/to Anto.io 7 | category=Communication 8 | url=https://github.com/AntoIOT/anto-esp8266-arduino 9 | architectures=esp8266 10 | -------------------------------------------------------------------------------- /src/AntoCommon.h: -------------------------------------------------------------------------------- 1 | #ifndef ANTO_COMMON_H 2 | #define ANTO_COMMON_H 3 | 4 | #define ANTO_VER "v0.7.2" 5 | 6 | #endif /* ifndef ANTO_COMMON_H */ 7 | -------------------------------------------------------------------------------- /src/AntoHTTP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "json/ArduinoJson.h" 4 | #include "AntoHTTP.h" 5 | 6 | #define ANTO_GET "/channel/get/" 7 | #define ANTO_SET "/channel/set/" 8 | 9 | bool AntoHTTP::digitalUpdate( 10 | const char* thing, 11 | const char* channel, 12 | bool value) 13 | { 14 | String str; 15 | String arg; 16 | 17 | arg = String(ANTO_SET) + 18 | _token+ "/" + 19 | thing+ "/" + 20 | channel + "/" + 21 | (value ? "1" : "0"); 22 | 23 | if (!httpRequest(str, _host, arg)) 24 | return false; 25 | 26 | removeHeader(str); 27 | 28 | if (isResponseSuccess(str)) 29 | return true; 30 | else 31 | return false; 32 | } 33 | 34 | bool AntoHTTP::analogUpdate( 35 | const char* thing, 36 | const char* channel, 37 | int32_t value) 38 | { 39 | String str; 40 | String arg; 41 | 42 | arg = String(ANTO_SET) + 43 | _token + "/" + 44 | thing + "/" + 45 | channel + "/" + 46 | String(value); 47 | 48 | if (!httpRequest(str, _host, arg)) 49 | return false; 50 | 51 | removeHeader(str); 52 | 53 | if (isResponseSuccess(str)) 54 | return true; 55 | else 56 | return false; 57 | } 58 | 59 | 60 | bool AntoHTTP::stringUpdate( 61 | const char* thing, 62 | const char* channel, 63 | const char* value) 64 | { 65 | String str; 66 | String arg; 67 | 68 | arg = String(ANTO_SET) + 69 | _token + "/" + 70 | thing + "/" + 71 | channel + "/" + value; 72 | 73 | if (!httpRequest(str, _host, arg)) 74 | return false; 75 | 76 | removeHeader(str); 77 | 78 | if (isResponseSuccess(str)) 79 | return true; 80 | else 81 | return false; 82 | } 83 | 84 | bool AntoHTTP::digitalGet(bool &val, const char* thing, const char* channel) 85 | { 86 | String str; 87 | String arg; 88 | StaticJsonBuffer<200> jsonBuffer; 89 | 90 | arg = String(ANTO_GET) + 91 | _token + "/" + 92 | thing + "/" + 93 | channel; 94 | 95 | if (!httpRequest(str, _host, arg)) 96 | return false; 97 | 98 | removeHeader(str); 99 | JsonObject& root = jsonBuffer.parseObject(str); 100 | 101 | if (!root.success()) 102 | return false; 103 | 104 | if (root["result"] == true) { 105 | val = (root["value"] == 1); 106 | return true; 107 | } else { 108 | return false; 109 | } 110 | } 111 | 112 | bool AntoHTTP::analogGet(int32_t &val, const char* thing, const char* channel) 113 | { 114 | String str; 115 | String arg; 116 | StaticJsonBuffer<200> jsonBuffer; 117 | 118 | arg = String(ANTO_GET) + 119 | _token + "/" + 120 | thing + "/" + 121 | channel; 122 | 123 | if (!httpRequest(str, _host, arg)) 124 | return false; 125 | 126 | removeHeader(str); 127 | JsonObject& root = jsonBuffer.parseObject(str); 128 | 129 | if (!root.success()) 130 | return false; 131 | 132 | if (root["result"] == true) { 133 | val = root["value"]; 134 | return true; 135 | } else { 136 | return false; 137 | } 138 | } 139 | 140 | bool AntoHTTP::stringGet(String &val, const char* thing, const char* channel) 141 | { 142 | String str; 143 | String arg; 144 | StaticJsonBuffer<200> jsonBuffer; 145 | 146 | val = String(""); 147 | arg = String(ANTO_GET) + 148 | _token 149 | + "/" + thing 150 | + "/" + channel; 151 | 152 | if (!httpRequest(str, _host, arg)) 153 | return false; 154 | 155 | removeHeader(str); 156 | JsonObject& root = jsonBuffer.parseObject(str); 157 | 158 | if (!root.success()) 159 | return false; 160 | 161 | if (root["result"] == true) { 162 | val = String((const char*)root["value"]); 163 | return true; 164 | } else { 165 | return false; 166 | } 167 | } 168 | 169 | bool AntoHTTP::httpRequest(String &result, const char *host, String arg) 170 | { 171 | WiFiClient client; 172 | uint8_t count; 173 | 174 | result = String(""); 175 | 176 | for (count = 10; count && !client.connect(host, 80); --count); 177 | 178 | if (!count) 179 | return false; 180 | 181 | client.print(String("GET ")+arg+" HTTP/1.1\r\n"+"Host: "+host+"\r\n\r\n"); 182 | 183 | for (count = 50; count && !client.available(); --count) delay(100); 184 | 185 | if (!count) 186 | return false; 187 | 188 | while (client.available()) 189 | result += client.readStringUntil('\r'); 190 | 191 | // return (str = removeHeader(str)); 192 | return true; 193 | } 194 | 195 | bool AntoHTTP::request(String &val, const char *service) 196 | { 197 | String str; 198 | String arg; 199 | StaticJsonBuffer<200> jsonBuffer; 200 | 201 | val = String(""); 202 | arg = String("/request/") + _token + "/" + service; 203 | 204 | if (!httpRequest(str, _host, arg)) 205 | return false; 206 | 207 | removeHeader(str); 208 | JsonObject& root = jsonBuffer.parseObject(str); 209 | 210 | if (!root.success()) 211 | return false; 212 | 213 | if (root["result"] == true) { 214 | val = String((const char*)root["value"]); 215 | return true; 216 | } else { 217 | return false; 218 | } 219 | } 220 | 221 | void AntoHTTP::removeHeader(String &str) 222 | { 223 | uint32_t index = str.indexOf("\n\n"); 224 | 225 | str.remove(0, index + 2); 226 | } 227 | 228 | bool AntoHTTP::isResponseSuccess(String json) 229 | { 230 | StaticJsonBuffer<200> jsonBuffer; 231 | 232 | JsonObject& root = jsonBuffer.parseObject(json); 233 | 234 | if (!root.success()) 235 | return false; 236 | 237 | return root["result"]; 238 | } 239 | -------------------------------------------------------------------------------- /src/AntoHTTP.h: -------------------------------------------------------------------------------- 1 | #ifndef ANTO_HTTP_H 2 | #define ANTO_HTTP_H 3 | 4 | #include 5 | 6 | class AntoHTTP 7 | { 8 | public: 9 | AntoHTTP(const char *token, const char *thing): 10 | _token(token), _thing(thing) 11 | { 12 | _host = (char *) malloc(sizeof("api.anto.io")); 13 | strcpy(_host, "api.anto.io"); 14 | } 15 | 16 | bool digitalUpdate(const char* channel, bool value) 17 | { 18 | return digitalUpdate(_thing, channel, value); 19 | } 20 | 21 | bool digitalUpdate(const char* thing, const char* channel, bool value); 22 | 23 | bool analogUpdate(const char* channel, int32_t value) 24 | { 25 | return analogUpdate(_thing, channel, value); 26 | } 27 | 28 | bool analogUpdate( 29 | const char* thing, 30 | const char* channel, 31 | int32_t value); 32 | 33 | bool stringUpdate(const char* channel, const char* value) 34 | { 35 | return stringUpdate(_thing, channel, value); 36 | } 37 | 38 | bool stringUpdate( 39 | const char* thing, 40 | const char* channel, 41 | const char* value); 42 | 43 | bool digitalGet(bool &val, const char* channel) 44 | { 45 | return digitalGet(val, _thing, channel); 46 | } 47 | 48 | bool digitalGet(bool &val, const char* thing, const char* channel); 49 | 50 | bool analogGet(int32_t &val, const char* channel) 51 | { 52 | return analogGet(val, _thing, channel); 53 | } 54 | 55 | bool analogGet(int32_t &val, const char* thing, const char* channel); 56 | 57 | bool stringGet(String &val, const char* channel) 58 | { 59 | return stringGet(val, _thing, channel); 60 | } 61 | 62 | bool stringGet(String &val, const char* thing, const char* channel); 63 | bool request(String &val, const char *arg); 64 | bool httpRequest(String &result, const char *host, String arg); 65 | void removeHeader(String &str); 66 | 67 | void setHost(const char *host) 68 | { 69 | free(_host); 70 | 71 | _host = (char *) malloc(sizeof(host)); 72 | strcpy(_host, host); 73 | } 74 | 75 | private: 76 | bool isResponseSuccess(String json); 77 | 78 | const char 79 | *_token, 80 | *_thing; 81 | 82 | char *_host; 83 | 84 | }; 85 | 86 | #endif /* ifndef ANTO_HTTP_H */ 87 | -------------------------------------------------------------------------------- /src/AntoIO.cpp: -------------------------------------------------------------------------------- 1 | #include "AntoIO.h" 2 | 3 | const char* AntoIO::getVersion(void) 4 | { 5 | static const char *ver = ANTO_VER; 6 | 7 | return ver; 8 | } 9 | 10 | void AntoIO::printArtWork(void) 11 | { 12 | Serial.println(" _ _"); 13 | Serial.println(" / \\ _ __ | |_ ___"); 14 | Serial.println(" / _ \\ | '_ \\| __/ _ \\ "); 15 | Serial.println(" / ___ \\| | | | || (_) |"); 16 | Serial.println("/_/ \\_\\_| |_|\\__\\___/ "); 17 | Serial.println(); 18 | } 19 | 20 | void AntoIO::begin( 21 | const char *ssid, 22 | const char* pwd, 23 | onMsg onData, 24 | bool secure) 25 | { 26 | while (!this->wifi.begin(ssid, pwd)); 27 | Serial.print("\n\nWiFi Connected to "); 28 | Serial.println(ssid); 29 | Serial.print("IP: "); 30 | Serial.println(WiFi.localIP()); 31 | 32 | while (!this->mqtt.connect(secure)); 33 | Serial.println("Broker Connected"); 34 | 35 | printArtWork(); 36 | 37 | Serial.print("Anto library version: "); 38 | Serial.println(this->getVersion()); 39 | Serial.println(); 40 | 41 | this->mqtt.onData(onData); 42 | } 43 | -------------------------------------------------------------------------------- /src/AntoIO.h: -------------------------------------------------------------------------------- 1 | #ifndef ANTO_IO_H 2 | #define ANTO_IO_H 3 | 4 | #include "AntoMQTT.h" 5 | #include "AntoWiFi.h" 6 | #include "AntoHTTP.h" 7 | #include "AntoCommon.h" 8 | 9 | class AntoIO 10 | { 11 | public: 12 | AntoMQTT mqtt; 13 | AntoWiFi wifi; 14 | AntoHTTP http; 15 | 16 | AntoIO(const char *user, const char *token, const char *thing): 17 | _user(user), 18 | _token(token), 19 | _thing(thing), 20 | mqtt(user, token, thing), 21 | http(token, thing), 22 | wifi() 23 | { } 24 | 25 | const char* getVersion(void); 26 | 27 | void begin( 28 | const char *ssid, 29 | const char* pwd, 30 | onMsg onData, 31 | bool secure = false); 32 | 33 | /* ============= START OF HTTP SECION ============= */ 34 | 35 | bool digitalUpdate(const char* channel, bool value) 36 | { 37 | return this->http.digitalUpdate(channel, value); 38 | } 39 | 40 | bool digitalUpdate(const char* thing, const char* channel, bool value) 41 | { 42 | return this->http.digitalUpdate(thing, channel, value); 43 | } 44 | 45 | bool analogUpdate(const char* channel, int32_t value) 46 | { 47 | return this->http.analogUpdate(channel, value); 48 | } 49 | 50 | bool analogUpdate( 51 | const char* thing, 52 | const char* channel, 53 | int32_t value) 54 | { 55 | return this->http.analogUpdate(thing, channel, value); 56 | } 57 | 58 | bool stringUpdate(const char* channel, const char* value) 59 | { 60 | return this->http.stringUpdate(channel, value); 61 | } 62 | 63 | bool stringUpdate( 64 | const char* thing, 65 | const char* channel, 66 | const char* value) 67 | { 68 | return this->http.stringUpdate(thing, channel, value); 69 | } 70 | 71 | bool digitalGet(bool &val, const char* channel) 72 | { 73 | return this->http.digitalGet(val, channel); 74 | } 75 | 76 | bool digitalGet(bool &val, const char* thing, const char* channel) 77 | { 78 | return this->http.digitalGet(val, thing, channel); 79 | } 80 | 81 | bool analogGet(int32_t &val, const char* channel) 82 | { 83 | return this->http.analogGet(val, channel); 84 | } 85 | 86 | bool analogGet(int32_t &val, const char* thing, const char* channel) 87 | { 88 | return this->http.analogGet(val, thing, channel); 89 | } 90 | 91 | bool stringGet(String &val, const char* channel) 92 | { 93 | return this->http.stringGet(val, channel); 94 | } 95 | 96 | bool stringGet(String &val, const char* thing, const char* channel) 97 | { 98 | return this->http.stringGet(val, thing, channel); 99 | } 100 | 101 | bool request(String &val, const char *arg) 102 | { 103 | return this->http.request(val, arg); 104 | } 105 | 106 | bool httpRequest(String &result, const char *host, String arg) 107 | { 108 | return this->http.httpRequest(result, host, arg); 109 | } 110 | 111 | void removeHeader(String &str) 112 | { 113 | this->http.removeHeader(str); 114 | } 115 | 116 | /* ============= END OF HTTP SECION ============= */ 117 | 118 | /* ============= START OF MQTT SECION ============= */ 119 | 120 | void loop(void) { this->mqtt.loop(); } 121 | 122 | void onData(onMsg onData) { this->mqtt.onData(onData); } 123 | 124 | bool disconnect(void) { return this->mqtt.disconnect(); } 125 | 126 | bool isConnected(void) { return this->mqtt.isConnected(); } 127 | 128 | bool connect( bool secure = false, const char * client_id = "") 129 | { 130 | return this->mqtt.connect(secure, client_id); 131 | } 132 | 133 | bool pub(const char *channel, const char *msg, 134 | int qos = 0, bool retain = false) 135 | { 136 | return this->mqtt.pub(channel, msg, qos, retain); 137 | } 138 | 139 | bool pub(const char *channel, String& msg, 140 | int qos = 0, bool retain = false) 141 | { 142 | return this->mqtt.pub(channel, msg, qos, retain); 143 | } 144 | 145 | bool pub(String& channel, const char *msg, 146 | int qos = 0, bool retain = false) 147 | { 148 | return this->mqtt.pub(channel, msg, qos, retain); 149 | } 150 | 151 | bool pub(String& channel, String& msg, 152 | int qos = 0, bool retain = false) 153 | { 154 | return this->mqtt.pub(channel, msg, qos, retain); 155 | } 156 | 157 | bool pub(const char *channel, int msg, 158 | int qos = 0, bool retain = false) 159 | { 160 | return this->mqtt.pub(channel, msg, qos, retain); 161 | } 162 | 163 | bool pub(String& channel, int msg, 164 | int qos = 0, bool retain = false) 165 | { 166 | return this->mqtt.pub(channel, msg, qos, retain); 167 | } 168 | 169 | bool pub(const char *channel, double msg, 170 | int qos = 0, bool retain = false) 171 | { 172 | return this->mqtt.pub(channel, msg, qos, retain); 173 | } 174 | 175 | bool pub(String& channel, double msg, 176 | int qos = 0, bool retain = false) 177 | { 178 | return this->mqtt.pub(channel, msg, qos, retain); 179 | } 180 | 181 | bool pub(const char *thing, const char *channel, const char *msg, 182 | int qos = 0, bool retain = false) 183 | { 184 | return this->mqtt.pub(thing, channel, msg, qos, retain); 185 | } 186 | 187 | bool pub(String& thing, String& channel, String& msg, 188 | int qos = 0, bool retain = false) 189 | { 190 | return this->mqtt.pub(thing, channel, msg, qos, retain); 191 | } 192 | 193 | bool sub(const char *channel, int qos = 0) 194 | { 195 | return this->mqtt.sub(channel, qos); 196 | } 197 | 198 | bool sub(String& channel, int qos = 0) 199 | { 200 | return this->mqtt.sub(channel, qos); 201 | } 202 | 203 | bool sub(const char *thing, const char *channel, int qos = 0) 204 | { 205 | return this->mqtt.sub(thing, channel, qos); 206 | } 207 | 208 | bool sub(String& thing, String& channel, int qos = 0) 209 | { 210 | return this->mqtt.sub(thing, channel, qos); 211 | } 212 | 213 | bool service(const char *name, int qos = 0) 214 | { 215 | return this->mqtt.service(name, qos); 216 | } 217 | 218 | /* ============= START OF MQTT SECION ============= */ 219 | 220 | 221 | private: 222 | void printArtWork(void); 223 | 224 | const char 225 | *_user, 226 | *_token, 227 | *_thing; 228 | }; 229 | 230 | #endif 231 | -------------------------------------------------------------------------------- /src/AntoMQTT.cpp: -------------------------------------------------------------------------------- 1 | #include "AntoMQTT.h" 2 | #include "AntoCommon.h" 3 | 4 | #define ANTO_MQTT_PORT 1883 5 | #define ANTO_MQTTS_PORT 1884 6 | #define ANTO_RAND_STR_LEN 10 7 | 8 | static void gen_random(char *s, const uint8_t len) 9 | { 10 | const char alphanum[] = 11 | "0123456789" 12 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 13 | "abcdefghijklmnopqrstuvwxyz"; 14 | 15 | for (int i = 0; i < len; ++i) 16 | s[i] = alphanum[random(300) % (sizeof(alphanum) - 1)]; 17 | 18 | s[len] = 0; 19 | } 20 | 21 | bool AntoMQTT::connect( 22 | bool secure, 23 | const char * client_id) 24 | { 25 | uint8_t count; 26 | String clientId(ANTO_VER); 27 | 28 | clientId += '-'; 29 | clientId += this->_user; 30 | clientId += '-'; 31 | 32 | if (client_id[0] == 0) { 33 | char randString[ANTO_RAND_STR_LEN + 1]; 34 | 35 | randomSeed(analogRead(0)); 36 | gen_random(randString, ANTO_RAND_STR_LEN); 37 | 38 | clientId += randString; 39 | } else { 40 | clientId += client_id; 41 | 42 | free(_lastConnClientId); 43 | _lastConnClientId = (char *) malloc(sizeof(client_id)); 44 | strcpy(_lastConnClientId, client_id); 45 | } 46 | 47 | char buf[clientId.length() + 1]; 48 | 49 | clientId.toCharArray(buf, clientId.length() + 1); 50 | 51 | if (secure) 52 | this->_mqtt.begin( 53 | _host, 54 | ANTO_MQTTS_PORT, 55 | this->_nets, this, 56 | &AntoMQTT::messageHandler); 57 | else 58 | this->_mqtt.begin( 59 | _host, 60 | ANTO_MQTT_PORT, 61 | this->_net, 62 | this, 63 | &AntoMQTT::messageHandler); 64 | 65 | for ( 66 | count = 50; 67 | count && (!this->_mqtt.connect(buf, this->_user, this->_token)); 68 | --count) 69 | delay(100); 70 | 71 | _lastConnSecure = secure; 72 | 73 | if (count == 0) 74 | return false; 75 | else 76 | return true; 77 | } 78 | 79 | bool AntoMQTT::pub(const char *channel, const char *msg, 80 | int qos, bool retain) 81 | { 82 | return pub(this->_thing, channel, msg, qos, retain); 83 | } 84 | 85 | bool AntoMQTT::pub(const char *channel, String& msg, 86 | int qos, bool retain) 87 | { 88 | String ch(channel); 89 | String th(this->_thing); 90 | 91 | return pub(th, ch, msg, qos, retain); 92 | } 93 | 94 | bool AntoMQTT::pub(String& channel, const char *msg, 95 | int qos, bool retain) 96 | { 97 | String m(msg); 98 | String th(this->_thing); 99 | 100 | return pub(th, channel, m, qos, retain); 101 | } 102 | 103 | bool AntoMQTT::pub(String& channel, String& msg, 104 | int qos, bool retain) 105 | { 106 | String th(this->_thing); 107 | 108 | return pub(th, channel, msg, qos, retain); 109 | } 110 | 111 | bool AntoMQTT::pub(const char *channel, int msg, 112 | int qos, bool retain) 113 | { 114 | String m(msg); 115 | String ch(channel); 116 | String th(this->_thing); 117 | 118 | return pub(th, ch, m, qos, retain); 119 | } 120 | 121 | bool AntoMQTT::pub(String& channel, int msg, 122 | int qos, bool retain) 123 | { 124 | String m(msg); 125 | String th(this->_thing); 126 | 127 | return pub(th, channel, m, qos, retain); 128 | } 129 | 130 | bool AntoMQTT::pub(const char *channel, double msg, int qos, bool retain) 131 | { 132 | String m(msg); 133 | String ch(channel); 134 | String th(this->_thing); 135 | 136 | return pub(th, ch, m, qos, retain); 137 | } 138 | 139 | bool AntoMQTT::pub(String& channel, double msg, int qos, bool retain) 140 | { 141 | String m(msg); 142 | String th(this->_thing); 143 | 144 | return pub(th, channel, m, qos, retain); 145 | } 146 | 147 | bool AntoMQTT::pub(const char *thing, const char *channel, const char *msg, 148 | int qos, bool retain) 149 | { 150 | String topic("channel/"); 151 | String message(msg); 152 | 153 | topic += this->_user; 154 | topic += "/"; 155 | topic += thing; 156 | topic += "/"; 157 | topic += channel; 158 | 159 | return this->_mqtt.publish(topic, message); 160 | } 161 | 162 | bool AntoMQTT::pub(String& thing, String& channel, String& msg, 163 | int qos, bool retain) 164 | { 165 | String topic("channel/"); 166 | 167 | topic += this->_user; 168 | topic += "/"; 169 | topic += thing; 170 | topic += "/"; 171 | topic += channel; 172 | 173 | return this->_mqtt.publish(topic, msg); 174 | } 175 | 176 | bool AntoMQTT::sub(const char *channel, int qos) 177 | { 178 | return sub(this->_thing, channel, qos); 179 | } 180 | 181 | bool AntoMQTT::sub(String& channel, int qos) 182 | { 183 | String th(this->_thing); 184 | 185 | return sub(th, channel, qos); 186 | } 187 | 188 | bool AntoMQTT::sub(const char *thing, const char *channel, int qos) 189 | { 190 | String topic("channel/"); 191 | 192 | topic += this->_user; 193 | topic += "/"; 194 | topic += thing; 195 | topic += "/"; 196 | topic += channel; 197 | 198 | return this->_mqtt.subscribe(topic, this); 199 | } 200 | 201 | bool AntoMQTT::sub(String& thing, String& channel, int qos) 202 | { 203 | String topic("channel/"); 204 | 205 | topic += this->_user; 206 | topic += "/"; 207 | topic += thing; 208 | topic += "/"; 209 | topic += channel; 210 | 211 | return this->_mqtt.subscribe(topic, this); 212 | } 213 | 214 | bool AntoMQTT::service(const char *name, int qos) 215 | { 216 | String service("service/"); 217 | service += name; 218 | 219 | return this->_mqtt.subscribe(service, this); 220 | } 221 | 222 | void AntoMQTT::messageHandler(MQTT::MessageData &messageData) 223 | { 224 | MQTT::Message &message = messageData.message; 225 | 226 | // null terminate topic to create String object 227 | int len = messageData.topicName.lenstring.len; 228 | char topic[len+1]; 229 | memcpy(topic, messageData.topicName.lenstring.data, (size_t)len); 230 | topic[len] = '\0'; 231 | 232 | char *channel = strrchr(topic, '/') + 1; 233 | *(channel - 1) = '\0'; 234 | char *thing = strrchr(topic, '/') + 1; 235 | 236 | // get payload 237 | char * payload = (char *)message.payload; 238 | 239 | // null terminate payload if enough space is available 240 | if(message.payloadlen < MQTT_BUFFER_SIZE) { 241 | payload[message.payloadlen] = '\0'; 242 | } 243 | 244 | if (this->_onData) 245 | _onData(String(thing), String(channel), String(payload)); 246 | // messageReceived(String(topic), String(payload), (char*)message.payload, (unsigned int)message.payloadlen); 247 | } 248 | -------------------------------------------------------------------------------- /src/AntoMQTT.h: -------------------------------------------------------------------------------- 1 | #ifndef ANTO_MQTT_H 2 | #define ANTO_MQTT_H 3 | 4 | #include 5 | #include 6 | 7 | #include "mqtt/MQTTClient.h" 8 | 9 | typedef void (*onMsg) (String, String, String); 10 | 11 | class AntoMQTT 12 | { 13 | public: 14 | AntoMQTT(const char *user, const char *token, const char *thing): 15 | _mqtt(), _nets(), _net(), _user(user), 16 | _token(token), _thing(thing),_lastConnSecure(false), 17 | _onData(NULL) 18 | { 19 | _host = (char *) malloc(sizeof("service.anto.io")); 20 | strcpy(_host, "service.anto.io"); 21 | 22 | _lastConnClientId = (char *) malloc(1); 23 | *_lastConnClientId = '\0'; 24 | } 25 | 26 | void loop(void) 27 | { 28 | this->_mqtt.loop(); 29 | 30 | if (!(this->_mqtt.connected())) 31 | while (!this->connect(_lastConnSecure, _lastConnClientId)) 32 | delay(500); 33 | 34 | delay(100); 35 | } 36 | 37 | void onData(onMsg onData) 38 | { 39 | this->_onData = onData; 40 | } 41 | 42 | bool disconnect(void) 43 | { 44 | return this->_mqtt.disconnect(); 45 | } 46 | 47 | bool isConnected(void) 48 | { 49 | return this->_mqtt.connected(); 50 | } 51 | 52 | bool connect( bool secure = false, const char * client_id = ""), 53 | 54 | pub(const char *channel, const char *msg, 55 | int qos = 0, bool retain = false), 56 | pub(const char *channel, String& msg, 57 | int qos = 0, bool retain = false), 58 | pub(String& channel, const char *msg, 59 | int qos = 0, bool retain = false), 60 | pub(String& channel, String& msg, 61 | int qos = 0, bool retain = false), 62 | pub(const char *channel, int msg, 63 | int qos = 0, bool retain = false), 64 | pub(String& channel, int msg, 65 | int qos = 0, bool retain = false), 66 | pub(const char *channel, double msg, 67 | int qos = 0, bool retain = false), 68 | pub(String& channel, double msg, 69 | int qos = 0, bool retain = false), 70 | pub(const char *thing, const char *channel, const char *msg, 71 | int qos = 0, bool retain = false), 72 | pub(String& thing, String& channel, String& msg, 73 | int qos = 0, bool retain = false), 74 | 75 | sub(const char *channel, int qos = 0), 76 | sub(String& channel, int qos = 0), 77 | sub(const char *thing, const char *channel, int qos = 0), 78 | sub(String& thing, String& channel, int qos = 0), 79 | 80 | service(const char *name, int qos = 0); 81 | 82 | void setHost(const char *host) 83 | { 84 | free(_host); 85 | 86 | _host = (char *) malloc(sizeof(host)); 87 | strcpy(_host, host); 88 | } 89 | 90 | private: 91 | MQTTClient _mqtt; 92 | WiFiClientSecure _nets; 93 | WiFiClient _net; 94 | 95 | void messageHandler(MQTT::MessageData &messageData); 96 | 97 | const char 98 | *_user, 99 | *_token, 100 | *_thing; 101 | 102 | char 103 | *_host, 104 | *_lastConnClientId; 105 | 106 | bool _lastConnSecure; 107 | 108 | onMsg _onData; 109 | }; 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /src/AntoWiFi.h: -------------------------------------------------------------------------------- 1 | #ifndef ANTO_WIFI_H 2 | #define ANTO_WIFI_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "wifimanager/WiFiManager.h" 9 | 10 | class AntoWiFi 11 | { 12 | public: 13 | AntoWiFi(void) { } 14 | 15 | bool smartConfig(void) 16 | { 17 | wifiManager.setDebugOutput(false); 18 | wifiManager.autoConnect("Anto Smart Config"); 19 | 20 | return true; 21 | } 22 | 23 | // timeout is under development 24 | bool begin( 25 | const char* ssid, 26 | const char *passphrase, 27 | uint16_t timeout = 0) 28 | { 29 | bool result = false; 30 | uint8_t count; 31 | 32 | WiFi.begin(ssid, passphrase); 33 | 34 | for (count = 50; count && (!WiFi.isConnected()); --count) 35 | delay(100); 36 | 37 | if (count) 38 | result = true; 39 | 40 | return result; 41 | } 42 | 43 | private: 44 | WiFiManager wifiManager; 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/json/ArduinoJson.h: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | // About this file 9 | // --------------- 10 | // This file is here for [PlatformIO](http://platformio.org/). 11 | // It must be present in the root for the tool to find it. 12 | // Feel free to ignore this file if your working in another environment. 13 | 14 | #include "include/ArduinoJson.h" 15 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson.h: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "ArduinoJson/DynamicJsonBuffer.hpp" 9 | #include "ArduinoJson/JsonArray.hpp" 10 | #include "ArduinoJson/JsonObject.hpp" 11 | #include "ArduinoJson/StaticJsonBuffer.hpp" 12 | 13 | using namespace ArduinoJson; 14 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Arduino/Print.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #ifndef ARDUINO 11 | 12 | #include "../Internals/JsonFloat.hpp" 13 | #include "../Internals/JsonInteger.hpp" 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #if defined(_MSC_VER) && _MSC_VER <= 1800 20 | // snprintf has been added in Visual Studio 2015 21 | #define ARDUINOJSON_SNPRINTF _snprintf 22 | #else 23 | #define ARDUINOJSON_SNPRINTF snprintf 24 | #endif 25 | 26 | // This class reproduces Arduino's Print class 27 | class Print { 28 | public: 29 | virtual ~Print() {} 30 | 31 | virtual size_t write(uint8_t) = 0; 32 | 33 | size_t print(const char* s) { 34 | size_t n = 0; 35 | while (*s) { 36 | n += write(*s++); 37 | } 38 | return n; 39 | } 40 | 41 | size_t print(ArduinoJson::Internals::JsonFloat value, int digits = 2) { 42 | char tmp[32]; 43 | 44 | // https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L220 45 | bool isBigDouble = value > 4294967040.0 || value < -4294967040.0; 46 | 47 | if (isBigDouble) { 48 | // Arduino's implementation prints "ovf" 49 | // We prefer using the scientific notation, since we have sprintf 50 | ARDUINOJSON_SNPRINTF(tmp, sizeof(tmp), "%g", value); 51 | } else { 52 | // Here we have the exact same output as Arduino's implementation 53 | ARDUINOJSON_SNPRINTF(tmp, sizeof(tmp), "%.*f", digits, value); 54 | } 55 | 56 | return print(tmp); 57 | } 58 | 59 | size_t print(ArduinoJson::Internals::JsonInteger value) { 60 | // see http://clc-wiki.net/wiki/K%26R2_solutions:Chapter_3:Exercise_4 61 | char buffer[22]; 62 | 63 | size_t n = 0; 64 | if (value < 0) { 65 | value = -value; 66 | n += write('-'); 67 | } 68 | uint8_t i = 0; 69 | do { 70 | ArduinoJson::Internals::JsonInteger digit = value % 10; 71 | value /= 10; 72 | buffer[i++] = static_cast(digit >= 0 ? '0' + digit : '0' - digit); 73 | } while (value); 74 | 75 | while (i > 0) { 76 | n += write(buffer[--i]); 77 | } 78 | 79 | return n; 80 | } 81 | 82 | size_t println() { return write('\r') + write('\n'); } 83 | }; 84 | 85 | #else 86 | 87 | #include 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Arduino/String.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #ifndef ARDUINO 11 | 12 | #include 13 | typedef std::string String; 14 | 15 | #else 16 | 17 | #include 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Configuration.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #ifdef ARDUINO // assume this is an embedded platform 11 | 12 | // store using float instead of double to reduce the memory usage (issue #134) 13 | #ifndef ARDUINOJSON_USE_DOUBLE 14 | #define ARDUINOJSON_USE_DOUBLE 0 15 | #endif 16 | 17 | // store using a long because it usually match the size of a float. 18 | #ifndef ARDUINOJSON_USE_LONG_LONG 19 | #define ARDUINOJSON_USE_LONG_LONG 0 20 | #endif 21 | #ifndef ARDUINOJSON_USE_INT64 22 | #define ARDUINOJSON_USE_INT64 0 23 | #endif 24 | 25 | // arduino doesn't support STL stream 26 | #ifndef ARDUINOJSON_ENABLE_STD_STREAM 27 | #define ARDUINOJSON_ENABLE_STD_STREAM 0 28 | #endif 29 | 30 | #ifndef ARDUINOJSON_ENABLE_ALIGNMENT 31 | #ifdef ARDUINO_ARCH_AVR 32 | // alignment isn't needed for 8-bit AVR 33 | #define ARDUINOJSON_ENABLE_ALIGNMENT 0 34 | #else 35 | // but must processor needs pointer to be align on word size 36 | #define ARDUINOJSON_ENABLE_ALIGNMENT 1 37 | #endif 38 | #endif 39 | 40 | #else // assume this is a computer 41 | 42 | // on a computer we have plenty of memory so we can use doubles 43 | #ifndef ARDUINOJSON_USE_DOUBLE 44 | #define ARDUINOJSON_USE_DOUBLE 1 45 | #endif 46 | 47 | // use long long when available 48 | #ifndef ARDUINOJSON_USE_LONG_LONG 49 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) 50 | #define ARDUINOJSON_USE_LONG_LONG 1 51 | #else 52 | #define ARDUINOJSON_USE_LONG_LONG 0 53 | #endif 54 | #endif 55 | 56 | // use _int64 on old versions of Visual Studio 57 | #ifndef ARDUINOJSON_USE_INT64 58 | #if defined(_MSC_VER) && _MSC_VER <= 1700 59 | #define ARDUINOJSON_USE_INT64 1 60 | #else 61 | #define ARDUINOJSON_USE_INT64 0 62 | #endif 63 | #endif 64 | 65 | // on a computer, we can assume that the STL is there 66 | #ifndef ARDUINOJSON_ENABLE_STD_STREAM 67 | #define ARDUINOJSON_ENABLE_STD_STREAM 1 68 | #endif 69 | 70 | #ifndef ARDUINOJSON_ENABLE_ALIGNMENT 71 | // even if not required, most cpu's are faster with aligned pointers 72 | #define ARDUINOJSON_ENABLE_ALIGNMENT 1 73 | #endif 74 | 75 | #endif 76 | 77 | #if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64 78 | #error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together 79 | #endif 80 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/DynamicJsonBuffer.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "Internals/BlockJsonBuffer.hpp" 11 | 12 | namespace ArduinoJson { 13 | // Implements a JsonBuffer with dynamic memory allocation. 14 | // You are strongly encouraged to consider using StaticJsonBuffer which is much 15 | // more suitable for embedded systems. 16 | typedef Internals::BlockJsonBuffer 17 | DynamicJsonBuffer; 18 | } 19 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/BlockJsonBuffer.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../JsonBuffer.hpp" 11 | 12 | #include 13 | 14 | namespace ArduinoJson { 15 | namespace Internals { 16 | class DefaultAllocator { 17 | public: 18 | void* allocate(size_t size) { return malloc(size); } 19 | void deallocate(void* pointer) { free(pointer); } 20 | }; 21 | 22 | template 23 | class BlockJsonBuffer : public JsonBuffer { 24 | struct Block; 25 | struct EmptyBlock { 26 | Block* next; 27 | size_t capacity; 28 | size_t size; 29 | }; 30 | struct Block : EmptyBlock { 31 | uint8_t data[1]; 32 | }; 33 | 34 | public: 35 | BlockJsonBuffer(size_t initialSize = 256) 36 | : _head(NULL), _nextBlockSize(initialSize) {} 37 | 38 | ~BlockJsonBuffer() { 39 | Block* currentBlock = _head; 40 | 41 | while (currentBlock != NULL) { 42 | Block* nextBlock = currentBlock->next; 43 | _allocator.deallocate(currentBlock); 44 | currentBlock = nextBlock; 45 | } 46 | } 47 | 48 | size_t size() const { 49 | size_t total = 0; 50 | for (const Block* b = _head; b; b = b->next) total += b->size; 51 | return total; 52 | } 53 | 54 | protected: 55 | virtual void* alloc(size_t bytes) { 56 | return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes); 57 | } 58 | 59 | private: 60 | bool canAllocInHead(size_t bytes) const { 61 | return _head != NULL && _head->size + bytes <= _head->capacity; 62 | } 63 | 64 | void* allocInHead(size_t bytes) { 65 | void* p = _head->data + _head->size; 66 | _head->size += round_size_up(bytes); 67 | return p; 68 | } 69 | 70 | void* allocInNewBlock(size_t bytes) { 71 | size_t capacity = _nextBlockSize; 72 | if (bytes > capacity) capacity = bytes; 73 | if (!addNewBlock(capacity)) return NULL; 74 | _nextBlockSize *= 2; 75 | return allocInHead(bytes); 76 | } 77 | 78 | bool addNewBlock(size_t capacity) { 79 | size_t bytes = sizeof(EmptyBlock) + capacity; 80 | Block* block = static_cast(_allocator.allocate(bytes)); 81 | if (block == NULL) return false; 82 | block->capacity = capacity; 83 | block->size = 0; 84 | block->next = _head; 85 | _head = block; 86 | return true; 87 | } 88 | 89 | TAllocator _allocator; 90 | Block* _head; 91 | size_t _nextBlockSize; 92 | }; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/Comments.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | namespace ArduinoJson { 11 | namespace Internals { 12 | const char *skipSpacesAndComments(const char *ptr); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/DummyPrint.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Arduino/Print.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | 15 | // A dummy Print implementation used in JsonPrintable::measureLength() 16 | class DummyPrint : public Print { 17 | public: 18 | virtual size_t write(uint8_t) { return 1; } 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/DynamicStringBuilder.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Arduino/Print.hpp" 11 | #include "../Arduino/String.hpp" 12 | 13 | namespace ArduinoJson { 14 | namespace Internals { 15 | 16 | // A Print implementation that allows to write in a String 17 | class DynamicStringBuilder : public Print { 18 | public: 19 | DynamicStringBuilder(String &str) : _str(str) {} 20 | 21 | virtual size_t write(uint8_t c) { 22 | // Need to cast to char, otherwise String will print a number (issue #120) 23 | _str += static_cast(c); 24 | return 1; 25 | } 26 | 27 | private: 28 | DynamicStringBuilder &operator=(const DynamicStringBuilder &); 29 | 30 | String &_str; 31 | }; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/Encoding.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Arduino/Print.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | 15 | class Encoding { 16 | public: 17 | // Optimized for code size on a 8-bit AVR 18 | static char escapeChar(char c) { 19 | const char *p = _escapeTable; 20 | while (p[0] && p[1] != c) { 21 | p += 2; 22 | } 23 | return p[0]; 24 | } 25 | 26 | // Optimized for code size on a 8-bit AVR 27 | static char unescapeChar(char c) { 28 | const char *p = _escapeTable + 4; 29 | for (;;) { 30 | if (p[0] == '\0') return c; 31 | if (p[0] == c) return p[1]; 32 | p += 2; 33 | } 34 | } 35 | 36 | private: 37 | static const char _escapeTable[]; 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/ForceInline.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #ifdef _MSC_VER 11 | #define FORCE_INLINE __forceinline 12 | #else 13 | #define FORCE_INLINE __attribute__((always_inline)) 14 | #endif 15 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/IndentedPrint.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Arduino/Print.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | 15 | // Decorator on top of Print to allow indented output. 16 | // This class is used by JsonPrintable::prettyPrintTo() but can also be used 17 | // for your own purpose, like logging. 18 | class IndentedPrint : public Print { 19 | public: 20 | explicit IndentedPrint(Print &p) : sink(&p) { 21 | level = 0; 22 | tabSize = 2; 23 | isNewLine = true; 24 | } 25 | 26 | virtual size_t write(uint8_t); 27 | 28 | // Adds one level of indentation 29 | void indent() { 30 | if (level < MAX_LEVEL) level++; 31 | } 32 | 33 | // Removes one level of indentation 34 | void unindent() { 35 | if (level > 0) level--; 36 | } 37 | 38 | // Set the number of space printed for each level of indentation 39 | void setTabSize(uint8_t n) { 40 | if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE; 41 | } 42 | 43 | private: 44 | Print *sink; 45 | uint8_t level : 4; 46 | uint8_t tabSize : 3; 47 | bool isNewLine : 1; 48 | 49 | size_t writeTabs(); 50 | 51 | static const int MAX_LEVEL = 15; // because it's only 4 bits 52 | static const int MAX_TAB_SIZE = 7; // because it's only 3 bits 53 | }; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/JsonBufferAllocated.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../JsonBuffer.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | 15 | class JsonBufferAllocated { 16 | public: 17 | void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() { 18 | if (!jsonBuffer) return NULL; 19 | return jsonBuffer->alloc(n); 20 | } 21 | 22 | void operator delete(void *, JsonBuffer *) throw() {} 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/JsonFloat.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Configuration.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | 15 | #if ARDUINOJSON_USE_DOUBLE 16 | typedef double JsonFloat; 17 | #else 18 | typedef float JsonFloat; 19 | #endif 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/JsonInteger.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Configuration.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | 15 | #if ARDUINOJSON_USE_LONG_LONG 16 | typedef long long JsonInteger; 17 | #elif ARDUINOJSON_USE_INT64 18 | typedef __int64 JsonInteger; 19 | #else 20 | typedef long JsonInteger; 21 | #endif 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/JsonParser.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../JsonBuffer.hpp" 11 | #include "../JsonVariant.hpp" 12 | 13 | namespace ArduinoJson { 14 | namespace Internals { 15 | 16 | // Parse JSON string to create JsonArrays and JsonObjects 17 | // This internal class is not indended to be used directly. 18 | // Instead, use JsonBuffer.parseArray() or .parseObject() 19 | class JsonParser { 20 | public: 21 | JsonParser(JsonBuffer *buffer, char *json, uint8_t nestingLimit) 22 | : _buffer(buffer), 23 | _readPtr(json ? json : ""), 24 | _writePtr(json), 25 | _nestingLimit(nestingLimit) {} 26 | 27 | JsonArray &parseArray(); 28 | JsonObject &parseObject(); 29 | 30 | private: 31 | bool skip(char charToSkip); 32 | 33 | const char *parseString(); 34 | bool parseAnythingTo(JsonVariant *destination); 35 | FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination); 36 | 37 | inline bool parseArrayTo(JsonVariant *destination); 38 | inline bool parseObjectTo(JsonVariant *destination); 39 | inline bool parseStringTo(JsonVariant *destination); 40 | 41 | JsonBuffer *_buffer; 42 | const char *_readPtr; 43 | char *_writePtr; 44 | uint8_t _nestingLimit; 45 | }; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/JsonPrintable.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Configuration.hpp" 11 | #include "DummyPrint.hpp" 12 | #include "IndentedPrint.hpp" 13 | #include "JsonWriter.hpp" 14 | #include "Prettyfier.hpp" 15 | #include "StaticStringBuilder.hpp" 16 | #include "DynamicStringBuilder.hpp" 17 | 18 | #if ARDUINOJSON_ENABLE_STD_STREAM 19 | #include "StreamPrintAdapter.hpp" 20 | #endif 21 | 22 | namespace ArduinoJson { 23 | namespace Internals { 24 | 25 | // Implements all the overloads of printTo() and prettyPrintTo() 26 | // Caution: this class use a template parameter to avoid virtual methods. 27 | // This is a bit curious but allows to reduce the size of JsonVariant, JsonArray 28 | // and JsonObject. 29 | template 30 | class JsonPrintable { 31 | public: 32 | size_t printTo(Print &print) const { 33 | JsonWriter writer(print); 34 | downcast().writeTo(writer); 35 | return writer.bytesWritten(); 36 | } 37 | 38 | #if ARDUINOJSON_ENABLE_STD_STREAM 39 | std::ostream &printTo(std::ostream &os) const { 40 | StreamPrintAdapter adapter(os); 41 | printTo(adapter); 42 | return os; 43 | } 44 | #endif 45 | 46 | size_t printTo(char *buffer, size_t bufferSize) const { 47 | StaticStringBuilder sb(buffer, bufferSize); 48 | return printTo(sb); 49 | } 50 | 51 | size_t printTo(String &str) const { 52 | DynamicStringBuilder sb(str); 53 | return printTo(sb); 54 | } 55 | 56 | size_t prettyPrintTo(IndentedPrint &print) const { 57 | Prettyfier p(print); 58 | return printTo(p); 59 | } 60 | 61 | size_t prettyPrintTo(char *buffer, size_t bufferSize) const { 62 | StaticStringBuilder sb(buffer, bufferSize); 63 | return prettyPrintTo(sb); 64 | } 65 | 66 | size_t prettyPrintTo(Print &print) const { 67 | IndentedPrint indentedPrint = IndentedPrint(print); 68 | return prettyPrintTo(indentedPrint); 69 | } 70 | 71 | size_t prettyPrintTo(String &str) const { 72 | DynamicStringBuilder sb(str); 73 | return prettyPrintTo(sb); 74 | } 75 | 76 | size_t measureLength() const { 77 | DummyPrint dp; 78 | return printTo(dp); 79 | } 80 | 81 | size_t measurePrettyLength() const { 82 | DummyPrint dp; 83 | return prettyPrintTo(dp); 84 | } 85 | 86 | private: 87 | const T &downcast() const { return *static_cast(this); } 88 | }; 89 | 90 | #if ARDUINOJSON_ENABLE_STD_STREAM 91 | template 92 | inline std::ostream &operator<<(std::ostream &os, const JsonPrintable &v) { 93 | return v.printTo(os); 94 | } 95 | #endif 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/JsonVariantContent.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "JsonFloat.hpp" 11 | #include "JsonInteger.hpp" 12 | 13 | namespace ArduinoJson { 14 | 15 | // Forward declarations 16 | class JsonArray; 17 | class JsonObject; 18 | 19 | namespace Internals { 20 | // A union that defines the actual content of a JsonVariant. 21 | // The enum JsonVariantType determines which member is in use. 22 | union JsonVariantContent { 23 | JsonFloat asFloat; // used for double and float 24 | JsonInteger asInteger; // used for bool, char, short, int and longs 25 | const char* asString; // asString can be null 26 | JsonArray* asArray; // asArray cannot be null 27 | JsonObject* asObject; // asObject cannot be null 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/JsonVariantType.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | namespace ArduinoJson { 11 | class JsonArray; 12 | class JsonObject; 13 | 14 | namespace Internals { 15 | 16 | // Enumerated type to know the current type of a JsonVariant. 17 | // The value determines which member of JsonVariantContent is used. 18 | enum JsonVariantType { 19 | JSON_UNDEFINED, // the JsonVariant has not been initialized 20 | JSON_UNPARSED, // the JsonVariant contains an unparsed string 21 | JSON_STRING, // the JsonVariant stores a const char* 22 | JSON_BOOLEAN, // the JsonVariant stores a bool 23 | JSON_INTEGER, // the JsonVariant stores an integer 24 | JSON_ARRAY, // the JsonVariant stores a pointer to a JsonArray 25 | JSON_OBJECT, // the JsonVariant stores a pointer to a JsonObject 26 | 27 | // The following values are reserved for float values 28 | // Multiple values are used for double, depending on the number of decimal 29 | // digits that must be printed in the JSON output. 30 | // This little trick allow to save one extra member in JsonVariant 31 | JSON_FLOAT_0_DECIMALS 32 | // JSON_FLOAT_1_DECIMAL 33 | // JSON_FLOAT_2_DECIMALS 34 | // ... 35 | }; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/JsonWriter.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Arduino/Print.hpp" 11 | #include "Encoding.hpp" 12 | #include "ForceInline.hpp" 13 | #include "JsonFloat.hpp" 14 | #include "JsonInteger.hpp" 15 | 16 | namespace ArduinoJson { 17 | namespace Internals { 18 | 19 | // Writes the JSON tokens to a Print implementation 20 | // This class is used by: 21 | // - JsonArray::writeTo() 22 | // - JsonObject::writeTo() 23 | // - JsonVariant::writeTo() 24 | // Its derived by PrettyJsonWriter that overrides some members to add 25 | // indentation. 26 | class JsonWriter { 27 | public: 28 | explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {} 29 | 30 | // Returns the number of bytes sent to the Print implementation. 31 | // This is very handy for implementations of printTo() that must return the 32 | // number of bytes written. 33 | size_t bytesWritten() const { return _length; } 34 | 35 | void beginArray() { write('['); } 36 | void endArray() { write(']'); } 37 | 38 | void beginObject() { write('{'); } 39 | void endObject() { write('}'); } 40 | 41 | void writeColon() { write(':'); } 42 | void writeComma() { write(','); } 43 | 44 | void writeBoolean(bool value) { write(value ? "true" : "false"); } 45 | 46 | void writeString(const char *value) { 47 | if (!value) { 48 | write("null"); 49 | } else { 50 | write('\"'); 51 | while (*value) writeChar(*value++); 52 | write('\"'); 53 | } 54 | } 55 | 56 | void writeChar(char c) { 57 | char specialChar = Encoding::escapeChar(c); 58 | if (specialChar) { 59 | write('\\'); 60 | write(specialChar); 61 | } else { 62 | write(c); 63 | } 64 | } 65 | 66 | void writeInteger(JsonInteger value) { _length += _sink.print(value); } 67 | 68 | void writeFloat(JsonFloat value, uint8_t decimals) { 69 | _length += _sink.print(value, decimals); 70 | } 71 | 72 | void writeRaw(const char *s) { return write(s); } 73 | 74 | protected: 75 | void write(char c) { _length += _sink.write(c); } 76 | FORCE_INLINE void write(const char *s) { _length += _sink.print(s); } 77 | 78 | Print &_sink; 79 | size_t _length; 80 | 81 | private: 82 | JsonWriter &operator=(const JsonWriter &); // cannot be assigned 83 | }; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/List.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../JsonBuffer.hpp" 11 | #include "ListConstIterator.hpp" 12 | #include "ListIterator.hpp" 13 | 14 | namespace ArduinoJson { 15 | namespace Internals { 16 | 17 | // A singly linked list of T. 18 | // The linked list is composed of ListNode. 19 | // It is derived by JsonArray and JsonObject 20 | template 21 | class List { 22 | public: 23 | typedef T value_type; 24 | typedef ListNode node_type; 25 | typedef ListIterator iterator; 26 | typedef ListConstIterator const_iterator; 27 | 28 | // Creates an empty List attached to a JsonBuffer. 29 | // The JsonBuffer allows to allocate new nodes. 30 | // When buffer is NULL, the List is not able to grow and success() returns 31 | // false. This is used to identify bad memory allocations and parsing 32 | // failures. 33 | explicit List(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {} 34 | 35 | // Returns true if the object is valid 36 | // Would return false in the following situation: 37 | // - the memory allocation failed (StaticJsonBuffer was too small) 38 | // - the JSON parsing failed 39 | bool success() const { return _buffer != NULL; } 40 | 41 | // Returns the numbers of elements in the list. 42 | // For a JsonObject, it would return the number of key-value pairs 43 | size_t size() const; 44 | 45 | iterator begin() { return iterator(_firstNode); } 46 | iterator end() { return iterator(NULL); } 47 | 48 | const_iterator begin() const { return const_iterator(_firstNode); } 49 | const_iterator end() const { return const_iterator(NULL); } 50 | 51 | protected: 52 | node_type *addNewNode(); 53 | void removeNode(node_type *nodeToRemove); 54 | 55 | JsonBuffer *_buffer; 56 | node_type *_firstNode; 57 | }; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/ListConstIterator.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "ListNode.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | 15 | // A read-only forward itertor for List 16 | template 17 | class ListConstIterator { 18 | public: 19 | explicit ListConstIterator(const ListNode *node = NULL) : _node(node) {} 20 | 21 | const T &operator*() const { return _node->content; } 22 | const T *operator->() { return &_node->content; } 23 | 24 | bool operator==(const ListConstIterator &other) const { 25 | return _node == other._node; 26 | } 27 | 28 | bool operator!=(const ListConstIterator &other) const { 29 | return _node != other._node; 30 | } 31 | 32 | ListConstIterator &operator++() { 33 | if (_node) _node = _node->next; 34 | return *this; 35 | } 36 | 37 | private: 38 | const ListNode *_node; 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/ListIterator.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "ListNode.hpp" 11 | #include "ListConstIterator.hpp" 12 | 13 | namespace ArduinoJson { 14 | namespace Internals { 15 | 16 | // A read-write forward iterator for List 17 | template 18 | class ListIterator { 19 | public: 20 | explicit ListIterator(ListNode *node = NULL) : _node(node) {} 21 | 22 | T &operator*() const { return _node->content; } 23 | T *operator->() { return &_node->content; } 24 | 25 | bool operator==(const ListIterator &other) const { 26 | return _node == other._node; 27 | } 28 | 29 | bool operator!=(const ListIterator &other) const { 30 | return _node != other._node; 31 | } 32 | 33 | ListIterator &operator++() { 34 | if (_node) _node = _node->next; 35 | return *this; 36 | } 37 | 38 | operator ListConstIterator() const { return ListConstIterator(_node); } 39 | 40 | private: 41 | ListNode *_node; 42 | }; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/ListNode.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include // for NULL 11 | 12 | #include "JsonBufferAllocated.hpp" 13 | 14 | namespace ArduinoJson { 15 | namespace Internals { 16 | 17 | // A node for a singly-linked list. 18 | // Used by List and its iterators. 19 | template 20 | struct ListNode : public Internals::JsonBufferAllocated { 21 | ListNode() : next(NULL) {} 22 | 23 | ListNode *next; 24 | T content; 25 | }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/Parse.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | template 15 | TFloat parse(const char *); 16 | 17 | template <> 18 | inline float parse(const char *s) { 19 | return static_cast(strtod(s, NULL)); 20 | } 21 | 22 | template <> 23 | inline double parse(const char *s) { 24 | return strtod(s, NULL); 25 | } 26 | 27 | template <> 28 | inline long parse(const char *s) { 29 | return strtol(s, NULL, 10); 30 | } 31 | 32 | template <> 33 | inline int parse(const char *s) { 34 | return atoi(s); 35 | } 36 | 37 | #if ARDUINOJSON_USE_LONG_LONG 38 | template <> 39 | inline long long parse(const char *s) { 40 | return strtoll(s, NULL, 10); 41 | } 42 | #endif 43 | 44 | #if ARDUINOJSON_USE_INT64 45 | template <> 46 | inline __int64 parse<__int64>(const char *s) { 47 | return _strtoi64(s, NULL, 10); 48 | } 49 | #endif 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/Prettyfier.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "IndentedPrint.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | 15 | // Converts a compact JSON string into an indented one. 16 | class Prettyfier : public Print { 17 | public: 18 | explicit Prettyfier(IndentedPrint& p) : _sink(p) { 19 | _previousChar = 0; 20 | _inString = false; 21 | } 22 | 23 | virtual size_t write(uint8_t); 24 | 25 | private: 26 | Prettyfier& operator=(const Prettyfier&); // cannot be assigned 27 | 28 | bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; } 29 | 30 | size_t handleStringChar(uint8_t); 31 | size_t handleMarkupChar(uint8_t); 32 | 33 | size_t handleBlockClose(uint8_t); 34 | size_t handleBlockOpen(uint8_t); 35 | size_t handleColon(); 36 | size_t handleComma(); 37 | size_t handleQuoteOpen(); 38 | size_t handleNormalChar(uint8_t); 39 | size_t indentIfNeeded(); 40 | size_t unindentIfNeeded(); 41 | 42 | uint8_t _previousChar; 43 | IndentedPrint& _sink; 44 | bool _inString; 45 | }; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/ReferenceType.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | namespace ArduinoJson { 11 | namespace Internals { 12 | 13 | // A type that is meant to be used by reference only (JsonArray and JsonObject) 14 | class ReferenceType { 15 | public: 16 | bool operator==(const ReferenceType& other) const { 17 | // two JsonArray are equal if they are the same instance 18 | // (we don't compare the content) 19 | return this == &other; 20 | } 21 | 22 | bool operator!=(const ReferenceType& other) const { return this != &other; } 23 | 24 | protected: 25 | ReferenceType() {} 26 | 27 | private: 28 | // copy constructor is private 29 | ReferenceType(const ReferenceType&); 30 | 31 | // copy operator is private 32 | ReferenceType& operator=(const ReferenceType&); 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/StaticStringBuilder.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Arduino/Print.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace Internals { 14 | 15 | // A Print implementation that allows to write in a char[] 16 | class StaticStringBuilder : public Print { 17 | public: 18 | StaticStringBuilder(char *buf, size_t size) 19 | : buffer(buf), capacity(size - 1), length(0) { 20 | buffer[0] = '\0'; 21 | } 22 | 23 | virtual size_t write(uint8_t c); 24 | 25 | private: 26 | char *buffer; 27 | size_t capacity; 28 | size_t length; 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/StreamPrintAdapter.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Configuration.hpp" 11 | 12 | #if ARDUINOJSON_ENABLE_STD_STREAM 13 | 14 | #include "../Arduino/Print.hpp" 15 | 16 | #include 17 | 18 | namespace ArduinoJson { 19 | namespace Internals { 20 | 21 | class StreamPrintAdapter : public Print { 22 | public: 23 | explicit StreamPrintAdapter(std::ostream& os) : _os(os) {} 24 | 25 | virtual size_t write(uint8_t c) { 26 | _os << static_cast(c); 27 | return 1; 28 | } 29 | 30 | private: 31 | // cannot be assigned 32 | StreamPrintAdapter& operator=(const StreamPrintAdapter&); 33 | 34 | std::ostream& _os; 35 | }; 36 | } 37 | } 38 | 39 | #endif // ARDUINOJSON_ENABLE_STD_STREAM 40 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/Internals/Unparsed.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | namespace ArduinoJson { 11 | namespace Internals { 12 | class Unparsed { 13 | public: 14 | explicit Unparsed(const char* str) : _str(str) {} 15 | operator const char*() const { return _str; } 16 | 17 | private: 18 | const char* _str; 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonArray.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "Internals/JsonBufferAllocated.hpp" 11 | #include "Internals/JsonPrintable.hpp" 12 | #include "Internals/List.hpp" 13 | #include "Internals/ReferenceType.hpp" 14 | #include "JsonVariant.hpp" 15 | #include "TypeTraits/EnableIf.hpp" 16 | #include "TypeTraits/IsFloatingPoint.hpp" 17 | #include "TypeTraits/IsReference.hpp" 18 | #include "TypeTraits/IsSame.hpp" 19 | 20 | // Returns the size (in bytes) of an array with n elements. 21 | // Can be very handy to determine the size of a StaticJsonBuffer. 22 | #define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \ 23 | (sizeof(JsonArray) + (NUMBER_OF_ELEMENTS) * sizeof(JsonArray::node_type)) 24 | 25 | namespace ArduinoJson { 26 | 27 | // Forward declarations 28 | class JsonObject; 29 | class JsonBuffer; 30 | class JsonArraySubscript; 31 | 32 | // An array of JsonVariant. 33 | // 34 | // The constructor is private, instances must be created via 35 | // JsonBuffer::createArray() or JsonBuffer::parseArray(). 36 | // A JsonArray can be serialized to a JSON string via JsonArray::printTo(). 37 | // It can also be deserialized from a JSON string via JsonBuffer::parseArray(). 38 | class JsonArray : public Internals::JsonPrintable, 39 | public Internals::ReferenceType, 40 | public Internals::List, 41 | public Internals::JsonBufferAllocated { 42 | public: 43 | // A meta-function that returns true if type T can be used in 44 | // JsonArray::set() 45 | template 46 | struct CanSet { 47 | static const bool value = JsonVariant::IsConstructibleFrom::value || 48 | TypeTraits::IsSame::value || 49 | TypeTraits::IsSame::value; 50 | }; 51 | 52 | // Create an empty JsonArray attached to the specified JsonBuffer. 53 | // You should not call this constructor directly. 54 | // Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray(). 55 | explicit JsonArray(JsonBuffer *buffer) 56 | : Internals::List(buffer) {} 57 | 58 | // Gets the value at the specified index 59 | FORCE_INLINE JsonVariant operator[](size_t index) const; 60 | 61 | // Gets or sets the value at specified index 62 | FORCE_INLINE JsonArraySubscript operator[](size_t index); 63 | 64 | // Adds the specified value at the end of the array. 65 | // 66 | // bool add(bool); 67 | // bool add(char); 68 | // bool add(long); 69 | // bool add(int); 70 | // bool add(short); 71 | // bool add(float value); 72 | // bool add(double value); 73 | // bool add(const char*); 74 | template 75 | FORCE_INLINE bool add( 76 | T value, 77 | typename TypeTraits::EnableIf< 78 | CanSet::value && !TypeTraits::IsReference::value>::type * = 0) { 79 | return addNode(value); 80 | } 81 | // bool add(const String&) 82 | // bool add(const JsonVariant&); 83 | // bool add(JsonArray&); 84 | // bool add(JsonObject&); 85 | template 86 | FORCE_INLINE bool add( 87 | const T &value, 88 | typename TypeTraits::EnableIf::value>::type * = 0) { 89 | return addNode(const_cast(value)); 90 | } 91 | // bool add(float value, uint8_t decimals); 92 | // bool add(double value, uint8_t decimals); 93 | template 94 | FORCE_INLINE bool add( 95 | T value, uint8_t decimals, 96 | typename TypeTraits::EnableIf::value>::type 97 | * = 0) { 98 | return addNode(JsonVariant(value, decimals)); 99 | } 100 | 101 | // Sets the value at specified index. 102 | // 103 | // bool set(size_t index, bool value); 104 | // bool set(size_t index, long value); 105 | // bool set(size_t index, int value); 106 | // bool set(size_t index, short value); 107 | template 108 | FORCE_INLINE bool set( 109 | size_t index, T value, 110 | typename TypeTraits::EnableIf< 111 | CanSet::value && !TypeTraits::IsReference::value>::type * = 0) { 112 | return setNodeAt(index, value); 113 | } 114 | // bool set(size_t index, const String&) 115 | // bool set(size_t index, const JsonVariant&); 116 | // bool set(size_t index, JsonArray&); 117 | // bool set(size_t index, JsonObject&); 118 | template 119 | FORCE_INLINE bool set( 120 | size_t index, const T &value, 121 | typename TypeTraits::EnableIf::value>::type * = 0) { 122 | return setNodeAt(index, const_cast(value)); 123 | } 124 | // bool set(size_t index, float value, uint8_t decimals = 2); 125 | // bool set(size_t index, double value, uint8_t decimals = 2); 126 | template 127 | FORCE_INLINE bool set( 128 | size_t index, T value, uint8_t decimals, 129 | typename TypeTraits::EnableIf::value>::type 130 | * = 0) { 131 | return setNodeAt(index, JsonVariant(value, decimals)); 132 | } 133 | 134 | // Gets the value at the specified index. 135 | FORCE_INLINE JsonVariant get(size_t index) const; 136 | 137 | // Gets the value at the specified index. 138 | template 139 | FORCE_INLINE T get(size_t index) const; 140 | 141 | // Check the type of the value at specified index. 142 | template 143 | FORCE_INLINE bool is(size_t index) const; 144 | 145 | // Creates a JsonArray and adds a reference at the end of the array. 146 | // It's a shortcut for JsonBuffer::createArray() and JsonArray::add() 147 | JsonArray &createNestedArray(); 148 | 149 | // Creates a JsonObject and adds a reference at the end of the array. 150 | // It's a shortcut for JsonBuffer::createObject() and JsonArray::add() 151 | JsonObject &createNestedObject(); 152 | 153 | // Removes element at specified index. 154 | void removeAt(size_t index); 155 | 156 | // Returns a reference an invalid JsonArray. 157 | // This object is meant to replace a NULL pointer. 158 | // This is used when memory allocation or JSON parsing fail. 159 | static JsonArray &invalid() { return _invalid; } 160 | 161 | // Serialize the array to the specified JsonWriter. 162 | void writeTo(Internals::JsonWriter &writer) const; 163 | 164 | private: 165 | node_type *getNodeAt(size_t index) const; 166 | 167 | template 168 | bool setNodeAt(size_t index, TValue value); 169 | 170 | template 171 | bool addNode(TValue); 172 | 173 | template 174 | FORCE_INLINE bool setNodeValue(node_type *, T value); 175 | 176 | // The instance returned by JsonArray::invalid() 177 | static JsonArray _invalid; 178 | }; 179 | } 180 | 181 | #include "JsonArray.ipp" 182 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonArray.ipp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "JsonArray.hpp" 11 | #include "JsonObject.hpp" 12 | #include "JsonArraySubscript.hpp" 13 | 14 | namespace ArduinoJson { 15 | 16 | inline JsonArraySubscript JsonArray::operator[](size_t index) { 17 | return JsonArraySubscript(*this, index); 18 | } 19 | 20 | inline JsonVariant JsonArray::operator[](size_t index) const { 21 | return get(index); 22 | } 23 | 24 | template 25 | inline bool JsonArray::addNode(TValue value) { 26 | node_type *node = addNewNode(); 27 | return node != NULL && setNodeValue(node, value); 28 | } 29 | 30 | template 31 | inline bool JsonArray::setNodeAt(size_t index, TValue value) { 32 | node_type *node = getNodeAt(index); 33 | return node != NULL && setNodeValue(node, value); 34 | } 35 | 36 | template 37 | inline bool JsonArray::setNodeValue(node_type *node, TValue value) { 38 | node->content = value; 39 | return true; 40 | } 41 | 42 | template <> 43 | inline bool JsonArray::setNodeValue(node_type *node, String &value) { 44 | const char *copy = _buffer->strdup(value); 45 | if (!copy) return false; 46 | node->content = copy; 47 | return true; 48 | } 49 | 50 | inline JsonVariant JsonArray::get(size_t index) const { 51 | node_type *node = getNodeAt(index); 52 | return node ? node->content : JsonVariant(); 53 | } 54 | 55 | template 56 | inline T JsonArray::get(size_t index) const { 57 | node_type *node = getNodeAt(index); 58 | return node ? node->content.as() : JsonVariant::invalid(); 59 | } 60 | 61 | template 62 | inline bool JsonArray::is(size_t index) const { 63 | node_type *node = getNodeAt(index); 64 | return node ? node->content.is() : false; 65 | } 66 | 67 | template 68 | inline const JsonArraySubscript JsonVariantBase::operator[]( 69 | int index) const { 70 | return asArray()[index]; 71 | } 72 | 73 | template <> 74 | inline JsonArray &JsonVariant::invalid() { 75 | return JsonArray::invalid(); 76 | } 77 | 78 | template <> 79 | inline JsonArray const &JsonVariant::invalid() { 80 | return JsonArray::invalid(); 81 | } 82 | 83 | inline JsonArray &JsonVariant::asArray() const { 84 | if (_type == Internals::JSON_ARRAY) return *_content.asArray; 85 | return JsonArray::invalid(); 86 | } 87 | 88 | inline JsonArray &JsonArray::createNestedArray() { 89 | if (!_buffer) return JsonArray::invalid(); 90 | JsonArray &array = _buffer->createArray(); 91 | add(array); 92 | return array; 93 | } 94 | 95 | inline JsonArray &JsonObject::createNestedArray(JsonObjectKey key) { 96 | if (!_buffer) return JsonArray::invalid(); 97 | JsonArray &array = _buffer->createArray(); 98 | setNodeAt(key, array); 99 | return array; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonArraySubscript.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "Configuration.hpp" 11 | #include "JsonVariantBase.hpp" 12 | 13 | #ifdef _MSC_VER 14 | #pragma warning(push) 15 | #pragma warning(disable : 4522) 16 | #endif 17 | 18 | namespace ArduinoJson { 19 | class JsonArraySubscript : public JsonVariantBase { 20 | public: 21 | FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index) 22 | : _array(array), _index(index) {} 23 | 24 | JsonArraySubscript& operator=(const JsonArraySubscript& src) { 25 | _array.set(_index, src); 26 | return *this; 27 | } 28 | 29 | template 30 | typename TypeTraits::EnableIf::value, 31 | JsonArraySubscript>::type& 32 | operator=(const T& src) { 33 | _array.set(_index, const_cast(src)); 34 | return *this; 35 | } 36 | 37 | template 38 | typename TypeTraits::EnableIf::value, 39 | JsonArraySubscript>::type& 40 | operator=(T src) { 41 | _array.set(_index, src); 42 | return *this; 43 | } 44 | 45 | FORCE_INLINE bool success() const { return _index < _array.size(); } 46 | 47 | FORCE_INLINE operator JsonVariant() const { return _array.get(_index); } 48 | 49 | template 50 | FORCE_INLINE T as() const { 51 | return _array.get(_index); 52 | } 53 | 54 | template 55 | FORCE_INLINE bool is() const { 56 | return _array.is(_index); 57 | } 58 | 59 | void writeTo(Internals::JsonWriter& writer) const { 60 | _array.get(_index).writeTo(writer); 61 | } 62 | 63 | template 64 | void set(TValue value) { 65 | _array.set(_index, value); 66 | } 67 | 68 | private: 69 | JsonArray& _array; 70 | const size_t _index; 71 | }; 72 | 73 | #if ARDUINOJSON_ENABLE_STD_STREAM 74 | inline std::ostream& operator<<(std::ostream& os, 75 | const JsonArraySubscript& source) { 76 | return source.printTo(os); 77 | } 78 | #endif 79 | 80 | } // namespace ArduinoJson 81 | 82 | #ifdef _MSC_VER 83 | #pragma warning(pop) 84 | #endif 85 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonBuffer.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include // for size_t 11 | #include // for uint8_t 12 | #include 13 | 14 | #include "Arduino/String.hpp" 15 | #include "JsonVariant.hpp" 16 | 17 | #if defined(__clang__) 18 | #pragma clang diagnostic ignored "-Wnon-virtual-dtor" 19 | #elif defined(__GNUC__) 20 | #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" 21 | #endif 22 | 23 | namespace ArduinoJson { 24 | class JsonArray; 25 | class JsonObject; 26 | 27 | // Entry point for using the library. 28 | // 29 | // Handle the memory management (done in derived classes) and calls the parser. 30 | // This abstract class is implemented by StaticJsonBuffer which implements a 31 | // fixed memory allocation. 32 | class JsonBuffer { 33 | public: 34 | // CAUTION: NO VIRTUAL DESTRUCTOR! 35 | // If we add a virtual constructor the Arduino compiler will add malloc() and 36 | // free() to the binary, adding 706 useless bytes. 37 | // virtual ~JsonBuffer() {} 38 | 39 | // Allocates an empty JsonArray. 40 | // 41 | // Returns a reference to the new JsonArray or JsonArray::invalid() if the 42 | // allocation fails. 43 | JsonArray &createArray(); 44 | 45 | // Allocates an empty JsonObject. 46 | // 47 | // Returns a reference to the new JsonObject or JsonObject::invalid() if the 48 | // allocation fails. 49 | JsonObject &createObject(); 50 | 51 | // Allocates and populate a JsonArray from a JSON string. 52 | // 53 | // The First argument is a pointer to the JSON string, the memory must be 54 | // writable 55 | // because the parser will insert null-terminators and replace escaped chars. 56 | // 57 | // The second argument set the nesting limit (see comment on DEFAULT_LIMIT) 58 | // 59 | // Returns a reference to the new JsonObject or JsonObject::invalid() if the 60 | // allocation fails. 61 | JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT); 62 | 63 | // Same with a const char*. 64 | // With this overload, the JsonBuffer will make a copy of the string 65 | JsonArray &parseArray(const char *json, uint8_t nesting = DEFAULT_LIMIT) { 66 | return parseArray(strdup(json), nesting); 67 | } 68 | 69 | // Same as above with a String class 70 | JsonArray &parseArray(const String &json, uint8_t nesting = DEFAULT_LIMIT) { 71 | return parseArray(json.c_str(), nesting); 72 | } 73 | 74 | // Allocates and populate a JsonObject from a JSON string. 75 | // 76 | // The First argument is a pointer to the JSON string, the memory must be 77 | // writable 78 | // because the parser will insert null-terminators and replace escaped chars. 79 | // 80 | // The second argument set the nesting limit (see comment on DEFAULT_LIMIT) 81 | // 82 | // Returns a reference to the new JsonObject or JsonObject::invalid() if the 83 | // allocation fails. 84 | JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT); 85 | 86 | // Same with a const char*. 87 | // With this overload, the JsonBuffer will make a copy of the string 88 | JsonObject &parseObject(const char *json, uint8_t nesting = DEFAULT_LIMIT) { 89 | return parseObject(strdup(json), nesting); 90 | } 91 | 92 | // Same as above with a String class 93 | JsonObject &parseObject(const String &json, uint8_t nesting = DEFAULT_LIMIT) { 94 | return parseObject(json.c_str(), nesting); 95 | } 96 | 97 | // Duplicate a string 98 | char *strdup(const char *src) { 99 | return src ? strdup(src, strlen(src)) : NULL; 100 | } 101 | char *strdup(const String &src) { return strdup(src.c_str(), src.length()); } 102 | 103 | // Allocates n bytes in the JsonBuffer. 104 | // Return a pointer to the allocated memory or NULL if allocation fails. 105 | virtual void *alloc(size_t size) = 0; 106 | 107 | protected: 108 | // Preserve aligment if nessary 109 | static FORCE_INLINE size_t round_size_up(size_t bytes) { 110 | #if ARDUINOJSON_ENABLE_ALIGNMENT 111 | const size_t x = sizeof(void *) - 1; 112 | return (bytes + x) & ~x; 113 | #else 114 | return bytes; 115 | #endif 116 | } 117 | 118 | private: 119 | char *strdup(const char *, size_t); 120 | 121 | // Default value of nesting limit of parseArray() and parseObject(). 122 | // 123 | // The nesting limit is a contain on the level of nesting allowed in the 124 | // JSON 125 | // string. 126 | // If set to 0, only a flat array or objects can be parsed. 127 | // If set to 1, the object can contain nested arrays or objects but only 1 128 | // level deep. 129 | // And bigger values will allow more level of nesting. 130 | // 131 | // The purpose of this feature is to prevent stack overflow that could 132 | // lead to 133 | // a security risk. 134 | static const uint8_t DEFAULT_LIMIT = 10; 135 | }; 136 | } 137 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonObject.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "Arduino/String.hpp" 11 | #include "Internals/JsonBufferAllocated.hpp" 12 | #include "Internals/JsonPrintable.hpp" 13 | #include "Internals/List.hpp" 14 | #include "Internals/ReferenceType.hpp" 15 | #include "JsonPair.hpp" 16 | #include "TypeTraits/EnableIf.hpp" 17 | #include "TypeTraits/IsFloatingPoint.hpp" 18 | #include "TypeTraits/IsReference.hpp" 19 | #include "TypeTraits/IsSame.hpp" 20 | 21 | // Returns the size (in bytes) of an object with n elements. 22 | // Can be very handy to determine the size of a StaticJsonBuffer. 23 | #define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \ 24 | (sizeof(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type)) 25 | 26 | namespace ArduinoJson { 27 | 28 | // Forward declarations 29 | class JsonArray; 30 | class JsonBuffer; 31 | 32 | // A dictionary of JsonVariant indexed by string (char*) 33 | // 34 | // The constructor is private, instances must be created via 35 | // JsonBuffer::createObject() or JsonBuffer::parseObject(). 36 | // A JsonObject can be serialized to a JSON string via JsonObject::printTo(). 37 | // It can also be deserialized from a JSON string via JsonBuffer::parseObject(). 38 | class JsonObject : public Internals::JsonPrintable, 39 | public Internals::ReferenceType, 40 | public Internals::List, 41 | public Internals::JsonBufferAllocated { 42 | public: 43 | // A meta-function that returns true if type T can be used in 44 | // JsonObject::set() 45 | template 46 | struct CanSet { 47 | static const bool value = JsonVariant::IsConstructibleFrom::value || 48 | TypeTraits::IsSame::value || 49 | TypeTraits::IsSame::value; 50 | }; 51 | 52 | // Create an empty JsonArray attached to the specified JsonBuffer. 53 | // You should not use this constructor directly. 54 | // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject(). 55 | FORCE_INLINE explicit JsonObject(JsonBuffer* buffer) 56 | : Internals::List(buffer) {} 57 | 58 | // Gets or sets the value associated with the specified key. 59 | FORCE_INLINE JsonObjectSubscript operator[](const char* key); 60 | FORCE_INLINE JsonObjectSubscript operator[](const String& key); 61 | 62 | // Gets the value associated with the specified key. 63 | FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const; 64 | 65 | // Sets the specified key with the specified value. 66 | // bool set(TKey key, bool value); 67 | // bool set(TKey key, char value); 68 | // bool set(TKey key, long value); 69 | // bool set(TKey key, int value); 70 | // bool set(TKey key, short value); 71 | // bool set(TKey key, float value); 72 | // bool set(TKey key, double value); 73 | // bool set(TKey key, const char* value); 74 | template 75 | FORCE_INLINE bool set( 76 | JsonObjectKey key, T value, 77 | typename TypeTraits::EnableIf< 78 | CanSet::value && !TypeTraits::IsReference::value>::type* = 0) { 79 | return setNodeAt(key, value); 80 | } 81 | // bool set(Key, String&); 82 | // bool set(Key, JsonArray&); 83 | // bool set(Key, JsonObject&); 84 | // bool set(Key, JsonVariant&); 85 | template 86 | FORCE_INLINE bool set( 87 | JsonObjectKey key, const T& value, 88 | typename TypeTraits::EnableIf::value>::type* = 0) { 89 | return setNodeAt(key, const_cast(value)); 90 | } 91 | // bool set(Key, float value, uint8_t decimals); 92 | // bool set(Key, double value, uint8_t decimals); 93 | template 94 | FORCE_INLINE bool set( 95 | JsonObjectKey key, TValue value, uint8_t decimals, 96 | typename TypeTraits::EnableIf< 97 | TypeTraits::IsFloatingPoint::value>::type* = 0) { 98 | return setNodeAt(key, JsonVariant(value, decimals)); 99 | } 100 | 101 | // Gets the value associated with the specified key. 102 | FORCE_INLINE JsonVariant get(JsonObjectKey) const; 103 | 104 | // Gets the value associated with the specified key. 105 | template 106 | FORCE_INLINE T get(JsonObjectKey) const; 107 | 108 | // Checks the type of the value associated with the specified key. 109 | template 110 | FORCE_INLINE bool is(JsonObjectKey) const; 111 | 112 | // Creates and adds a JsonArray. 113 | // This is a shortcut for JsonBuffer::createArray() and JsonObject::add(). 114 | FORCE_INLINE JsonArray& createNestedArray(JsonObjectKey key); 115 | 116 | // Creates and adds a JsonObject. 117 | // This is a shortcut for JsonBuffer::createObject() and JsonObject::add(). 118 | FORCE_INLINE JsonObject& createNestedObject(JsonObjectKey key); 119 | 120 | // Tells weither the specified key is present and associated with a value. 121 | FORCE_INLINE bool containsKey(JsonObjectKey key) const; 122 | 123 | // Removes the specified key and the associated value. 124 | void remove(JsonObjectKey key); 125 | 126 | // Returns a reference an invalid JsonObject. 127 | // This object is meant to replace a NULL pointer. 128 | // This is used when memory allocation or JSON parsing fail. 129 | static JsonObject& invalid() { return _invalid; } 130 | 131 | // Serialize the object to the specified JsonWriter 132 | void writeTo(Internals::JsonWriter& writer) const; 133 | 134 | private: 135 | // Returns the list node that matches the specified key. 136 | node_type* getNodeAt(const char* key) const; 137 | 138 | node_type* getOrCreateNodeAt(const char* key); 139 | 140 | template 141 | FORCE_INLINE bool setNodeAt(JsonObjectKey key, T value); 142 | 143 | FORCE_INLINE bool setNodeKey(node_type*, JsonObjectKey key); 144 | 145 | template 146 | FORCE_INLINE bool setNodeValue(node_type*, T value); 147 | 148 | // The instance returned by JsonObject::invalid() 149 | static JsonObject _invalid; 150 | }; 151 | } 152 | 153 | #include "JsonObject.ipp" 154 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonObject.ipp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "JsonArray.hpp" 11 | #include "JsonObject.hpp" 12 | #include "JsonObjectSubscript.hpp" 13 | 14 | namespace ArduinoJson { 15 | 16 | inline JsonVariant JsonObject::get(JsonObjectKey key) const { 17 | node_type *node = getNodeAt(key.c_str()); 18 | return node ? node->content.value : JsonVariant(); 19 | } 20 | 21 | template 22 | inline T JsonObject::get(JsonObjectKey key) const { 23 | node_type *node = getNodeAt(key.c_str()); 24 | return node ? node->content.value.as() : JsonVariant::invalid(); 25 | } 26 | 27 | template 28 | inline bool JsonObject::is(JsonObjectKey key) const { 29 | node_type *node = getNodeAt(key.c_str()); 30 | return node ? node->content.value.is() : false; 31 | } 32 | 33 | inline JsonObjectSubscript JsonObject::operator[]( 34 | const char *key) { 35 | return JsonObjectSubscript(*this, key); 36 | } 37 | 38 | inline JsonObjectSubscript JsonObject::operator[]( 39 | const String &key) { 40 | return JsonObjectSubscript(*this, key); 41 | } 42 | 43 | inline JsonVariant JsonObject::operator[](JsonObjectKey key) const { 44 | return get(key); 45 | } 46 | 47 | inline bool JsonObject::containsKey(JsonObjectKey key) const { 48 | return getNodeAt(key.c_str()) != NULL; 49 | } 50 | 51 | inline void JsonObject::remove(JsonObjectKey key) { 52 | removeNode(getNodeAt(key.c_str())); 53 | } 54 | 55 | template 56 | inline bool JsonObject::setNodeAt(JsonObjectKey key, T value) { 57 | node_type *node = getNodeAt(key.c_str()); 58 | if (!node) { 59 | node = addNewNode(); 60 | if (!node || !setNodeKey(node, key)) 61 | return false; 62 | } 63 | return setNodeValue(node, value); 64 | } 65 | 66 | inline bool JsonObject::setNodeKey(node_type *node, JsonObjectKey key) { 67 | if (key.needs_copy()) { 68 | node->content.key = _buffer->strdup(key.c_str()); 69 | if (node->content.key == NULL) return false; 70 | } else { 71 | node->content.key = key.c_str(); 72 | } 73 | return true; 74 | } 75 | 76 | template 77 | inline bool JsonObject::setNodeValue(node_type *node, TValue value) { 78 | node->content.value = value; 79 | return true; 80 | } 81 | 82 | template <> 83 | inline bool JsonObject::setNodeValue(node_type *node, String &value) { 84 | node->content.value = _buffer->strdup(value); 85 | return node->content.value; 86 | } 87 | 88 | template <> 89 | inline bool JsonObject::setNodeValue(node_type *node, const String &value) { 90 | node->content.value = _buffer->strdup(value); 91 | return node->content.value; 92 | } 93 | 94 | template 95 | inline const JsonObjectSubscript JsonVariantBase:: 96 | operator[](const char *key) const { 97 | return asObject()[key]; 98 | } 99 | 100 | template 101 | inline const JsonObjectSubscript JsonVariantBase:: 102 | operator[](const String &key) const { 103 | return asObject()[key]; 104 | } 105 | 106 | template <> 107 | inline JsonObject const &JsonVariant::invalid() { 108 | return JsonObject::invalid(); 109 | } 110 | 111 | template <> 112 | inline JsonObject &JsonVariant::invalid() { 113 | return JsonObject::invalid(); 114 | } 115 | 116 | inline JsonObject &JsonVariant::asObject() const { 117 | if (_type == Internals::JSON_OBJECT) return *_content.asObject; 118 | return JsonObject::invalid(); 119 | } 120 | 121 | inline JsonObject &JsonObject::createNestedObject(JsonObjectKey key) { 122 | if (!_buffer) return JsonObject::invalid(); 123 | JsonObject &array = _buffer->createObject(); 124 | setNodeAt(key, array); 125 | return array; 126 | } 127 | 128 | inline JsonObject &JsonArray::createNestedObject() { 129 | if (!_buffer) return JsonObject::invalid(); 130 | JsonObject &object = _buffer->createObject(); 131 | add(object); 132 | return object; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonObjectKey.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "Arduino/String.hpp" 11 | 12 | namespace ArduinoJson { 13 | 14 | // Represents a key in a JsonObject 15 | class JsonObjectKey { 16 | public: 17 | JsonObjectKey(const char* key) : _value(key), _needs_copy(false) {} 18 | JsonObjectKey(const String& key) : _value(key.c_str()), _needs_copy(true) {} 19 | 20 | const char* c_str() const { return _value; } 21 | bool needs_copy() const { return _needs_copy; } 22 | 23 | private: 24 | const char* _value; 25 | bool _needs_copy; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonObjectSubscript.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "Configuration.hpp" 11 | #include "JsonVariantBase.hpp" 12 | #include "TypeTraits/EnableIf.hpp" 13 | 14 | #ifdef _MSC_VER 15 | #pragma warning(push) 16 | #pragma warning(disable : 4522) 17 | #endif 18 | 19 | namespace ArduinoJson { 20 | 21 | template 22 | class JsonObjectSubscript : public JsonVariantBase > { 23 | public: 24 | FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key) 25 | : _object(object), _key(key) {} 26 | 27 | JsonObjectSubscript& operator=(const JsonObjectSubscript& src) { 28 | _object.set(_key, src); 29 | return *this; 30 | } 31 | 32 | template 33 | typename TypeTraits::EnableIf::value, 34 | JsonObjectSubscript >::type& 35 | operator=(const T& src) { 36 | _object.set(_key, const_cast(src)); 37 | return *this; 38 | } 39 | 40 | template 41 | typename TypeTraits::EnableIf::value, 42 | JsonObjectSubscript >::type& 43 | operator=(T src) { 44 | _object.set(_key, src); 45 | return *this; 46 | } 47 | 48 | FORCE_INLINE bool success() const { return _object.containsKey(_key); } 49 | 50 | FORCE_INLINE operator JsonVariant() const { return _object.get(_key); } 51 | 52 | template 53 | FORCE_INLINE TValue as() const { 54 | return _object.get(_key); 55 | } 56 | 57 | template 58 | FORCE_INLINE bool is() const { 59 | return _object.is(_key); 60 | } 61 | 62 | template 63 | FORCE_INLINE bool set(TValue value) { 64 | return _object.set(_key, value); 65 | } 66 | 67 | template 68 | FORCE_INLINE bool set(TValue value, uint8_t decimals) { 69 | return _object.set(_key, value, decimals); 70 | } 71 | 72 | FORCE_INLINE JsonVariant get() { return _object.get(_key); } 73 | 74 | void writeTo(Internals::JsonWriter& writer) const { 75 | _object.get(_key).writeTo(writer); 76 | } 77 | 78 | private: 79 | JsonObject& _object; 80 | TKey _key; 81 | }; 82 | 83 | #if ARDUINOJSON_ENABLE_STD_STREAM 84 | inline std::ostream& operator<<( 85 | std::ostream& os, const JsonObjectSubscript& source) { 86 | return source.printTo(os); 87 | } 88 | 89 | inline std::ostream& operator<<( 90 | std::ostream& os, const JsonObjectSubscript& source) { 91 | return source.printTo(os); 92 | } 93 | #endif 94 | 95 | } // namespace ArduinoJson 96 | 97 | #ifdef _MSC_VER 98 | #pragma warning(pop) 99 | #endif 100 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonPair.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "JsonObjectKey.hpp" 11 | #include "JsonVariant.hpp" 12 | 13 | namespace ArduinoJson { 14 | 15 | // A key value pair for JsonObject. 16 | struct JsonPair { 17 | const char* key; 18 | JsonVariant value; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonVariant.ipp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "Configuration.hpp" 11 | #include "JsonVariant.hpp" 12 | #include "Internals/Parse.hpp" 13 | 14 | #include 15 | 16 | namespace ArduinoJson { 17 | 18 | inline JsonVariant::JsonVariant(bool value) { 19 | using namespace Internals; 20 | _type = JSON_BOOLEAN; 21 | _content.asInteger = static_cast(value); 22 | } 23 | 24 | inline JsonVariant::JsonVariant(const char *value) { 25 | _type = Internals::JSON_STRING; 26 | _content.asString = value; 27 | } 28 | 29 | inline JsonVariant::JsonVariant(Internals::Unparsed value) { 30 | _type = Internals::JSON_UNPARSED; 31 | _content.asString = value; 32 | } 33 | 34 | inline JsonVariant::JsonVariant(JsonArray &array) { 35 | _type = Internals::JSON_ARRAY; 36 | _content.asArray = &array; 37 | } 38 | 39 | inline JsonVariant::JsonVariant(JsonObject &object) { 40 | _type = Internals::JSON_OBJECT; 41 | _content.asObject = &object; 42 | } 43 | 44 | template 45 | inline T JsonVariant::invalid() { 46 | return T(); 47 | } 48 | 49 | template 50 | inline bool JsonVariant::is() const { 51 | return false; 52 | } 53 | 54 | template <> // in .cpp 55 | bool JsonVariant::is() const; 56 | 57 | template <> // in .cpp 58 | bool JsonVariant::is() const; 59 | 60 | template <> // int .cpp 61 | bool JsonVariant::is() const; 62 | 63 | template <> 64 | inline bool JsonVariant::is() const { 65 | return _type == Internals::JSON_STRING; 66 | } 67 | 68 | template <> 69 | inline bool JsonVariant::is() const { 70 | return is(); 71 | } 72 | 73 | template <> 74 | inline bool JsonVariant::is() const { 75 | return _type == Internals::JSON_ARRAY; 76 | } 77 | 78 | template <> 79 | inline bool JsonVariant::is() const { 80 | return _type == Internals::JSON_ARRAY; 81 | } 82 | 83 | template <> 84 | inline bool JsonVariant::is() const { 85 | return _type == Internals::JSON_OBJECT; 86 | } 87 | 88 | template <> 89 | inline bool JsonVariant::is() const { 90 | return _type == Internals::JSON_OBJECT; 91 | } 92 | 93 | template <> 94 | inline bool JsonVariant::is() const { 95 | return is(); 96 | } 97 | 98 | template <> 99 | inline bool JsonVariant::is() const { 100 | return is(); 101 | } 102 | 103 | template <> 104 | inline bool JsonVariant::is() const { 105 | return is(); 106 | } 107 | 108 | template <> 109 | inline bool JsonVariant::is() const { 110 | return is(); 111 | } 112 | 113 | template <> 114 | inline bool JsonVariant::is() const { 115 | return is(); 116 | } 117 | 118 | template <> 119 | inline bool JsonVariant::is() const { 120 | return is(); 121 | } 122 | 123 | template <> 124 | inline bool JsonVariant::is() const { 125 | return is(); 126 | } 127 | 128 | inline Internals::JsonInteger JsonVariant::asInteger() const { 129 | if (_type == Internals::JSON_INTEGER || _type == Internals::JSON_BOOLEAN) 130 | return _content.asInteger; 131 | 132 | if (_type >= Internals::JSON_FLOAT_0_DECIMALS) 133 | return static_cast(_content.asFloat); 134 | 135 | if ((_type == Internals::JSON_STRING || _type == Internals::JSON_UNPARSED) && 136 | _content.asString) { 137 | if (!strcmp("true", _content.asString)) return 1; 138 | return Internals::parse(_content.asString); 139 | } 140 | 141 | return 0L; 142 | } 143 | 144 | #if ARDUINOJSON_ENABLE_STD_STREAM 145 | inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) { 146 | return source.printTo(os); 147 | } 148 | #endif 149 | 150 | } // namespace ArduinoJson 151 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/JsonVariantBase.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "Internals/ForceInline.hpp" 11 | #include "JsonObjectKey.hpp" 12 | 13 | namespace ArduinoJson { 14 | 15 | // Forward declarations. 16 | class JsonArraySubscript; 17 | template 18 | class JsonObjectSubscript; 19 | 20 | template 21 | class JsonVariantBase : public Internals::JsonPrintable { 22 | public: 23 | FORCE_INLINE const char *asString() const { return as(); } 24 | 25 | // Gets the variant as an array. 26 | // Returns a reference to the JsonArray or JsonArray::invalid() if the 27 | // variant 28 | // is not an array. 29 | FORCE_INLINE operator JsonArray &() const { return as(); } 30 | FORCE_INLINE JsonArray &asArray() const { return as(); } 31 | 32 | // Gets the variant as an object. 33 | // Returns a reference to the JsonObject or JsonObject::invalid() if the 34 | // variant is not an object. 35 | FORCE_INLINE operator JsonObject &() const { return as(); } 36 | FORCE_INLINE JsonObject &asObject() const { return as(); } 37 | 38 | template 39 | FORCE_INLINE operator T() const { 40 | return as(); 41 | } 42 | 43 | template 44 | FORCE_INLINE const T as() const { 45 | return impl()->template as(); 46 | } 47 | 48 | // Mimics an array or an object. 49 | // Returns the size of the array or object if the variant has that type. 50 | // Returns 0 if the variant is neither an array nor an object 51 | size_t size() const { return asArray().size() + asObject().size(); } 52 | 53 | // Mimics an array. 54 | // Returns the element at specified index if the variant is an array. 55 | // Returns JsonVariant::invalid() if the variant is not an array. 56 | FORCE_INLINE const JsonArraySubscript operator[](int index) const; 57 | 58 | // Mimics an object. 59 | // Returns the value associated with the specified key if the variant is 60 | // an object. 61 | // Return JsonVariant::invalid() if the variant is not an object. 62 | FORCE_INLINE const JsonObjectSubscript operator[]( 63 | const char *key) const; 64 | FORCE_INLINE const JsonObjectSubscript operator[]( 65 | const String &key) const; 66 | 67 | // Serialize the variant to a JsonWriter 68 | void writeTo(Internals::JsonWriter &writer) const; 69 | 70 | private: 71 | const TImpl *impl() const { return static_cast(this); } 72 | }; 73 | 74 | template 75 | inline bool operator==(const JsonVariantBase &left, TComparand right) { 76 | return left.template as() == right; 77 | } 78 | 79 | template 80 | inline bool operator==(TComparand left, const JsonVariantBase &right) { 81 | return left == right.template as(); 82 | } 83 | 84 | template 85 | inline bool operator!=(const JsonVariantBase &left, TComparand right) { 86 | return left.template as() != right; 87 | } 88 | 89 | template 90 | inline bool operator!=(TComparand left, const JsonVariantBase &right) { 91 | return left != right.template as(); 92 | } 93 | 94 | template 95 | inline bool operator<=(const JsonVariantBase &left, TComparand right) { 96 | return left.template as() <= right; 97 | } 98 | 99 | template 100 | inline bool operator<=(TComparand left, const JsonVariantBase &right) { 101 | return left <= right.template as(); 102 | } 103 | 104 | template 105 | inline bool operator>=(const JsonVariantBase &left, TComparand right) { 106 | return left.template as() >= right; 107 | } 108 | 109 | template 110 | inline bool operator>=(TComparand left, const JsonVariantBase &right) { 111 | return left >= right.template as(); 112 | } 113 | 114 | template 115 | inline bool operator<(const JsonVariantBase &left, TComparand right) { 116 | return left.template as() < right; 117 | } 118 | 119 | template 120 | inline bool operator<(TComparand left, const JsonVariantBase &right) { 121 | return left < right.template as(); 122 | } 123 | 124 | template 125 | inline bool operator>(const JsonVariantBase &left, TComparand right) { 126 | return left.template as() > right; 127 | } 128 | 129 | template 130 | inline bool operator>(TComparand left, const JsonVariantBase &right) { 131 | return left > right.template as(); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/StaticJsonBuffer.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "JsonBuffer.hpp" 11 | 12 | namespace ArduinoJson { 13 | 14 | // Implements a JsonBuffer with fixed memory allocation. 15 | // The template paramenter CAPACITY specifies the capacity of the buffer in 16 | // bytes. 17 | template 18 | class StaticJsonBuffer : public JsonBuffer { 19 | public: 20 | explicit StaticJsonBuffer() : _size(0) {} 21 | 22 | size_t capacity() const { return CAPACITY; } 23 | size_t size() const { return _size; } 24 | 25 | virtual void* alloc(size_t bytes) { 26 | if (_size + bytes > CAPACITY) return NULL; 27 | void* p = &_buffer[_size]; 28 | _size += round_size_up(bytes); 29 | return p; 30 | } 31 | 32 | private: 33 | uint8_t _buffer[CAPACITY]; 34 | size_t _size; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/TypeTraits/EnableIf.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | namespace ArduinoJson { 11 | namespace TypeTraits { 12 | 13 | // A meta-function that return the type T if Condition is true. 14 | template 15 | struct EnableIf {}; 16 | 17 | template 18 | struct EnableIf { 19 | typedef T type; 20 | }; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "IsSame.hpp" 11 | 12 | namespace ArduinoJson { 13 | namespace TypeTraits { 14 | 15 | // A meta-function that returns true if T is a floating point type 16 | template 17 | struct IsFloatingPoint { 18 | static const bool value = IsSame::value || IsSame::value; 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/TypeTraits/IsIntegral.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | #include "../Configuration.hpp" 11 | #include "IsSame.hpp" 12 | 13 | #include 14 | 15 | namespace ArduinoJson { 16 | namespace TypeTraits { 17 | 18 | // A meta-function that returns true if T is an integral type. 19 | template 20 | struct IsIntegral { 21 | static const bool value = TypeTraits::IsSame::value || 22 | TypeTraits::IsSame::value || 23 | TypeTraits::IsSame::value || 24 | TypeTraits::IsSame::value || 25 | TypeTraits::IsSame::value || 26 | TypeTraits::IsSame::value || 27 | TypeTraits::IsSame::value || 28 | TypeTraits::IsSame::value || 29 | #if ARDUINOJSON_USE_LONG_LONG 30 | TypeTraits::IsSame::value || 31 | TypeTraits::IsSame::value || 32 | #endif 33 | 34 | #if ARDUINOJSON_USE_INT64 35 | TypeTraits::IsSame::value || 36 | TypeTraits::IsSame::value || 37 | #endif 38 | TypeTraits::IsSame::value; 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/TypeTraits/IsReference.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | namespace ArduinoJson { 11 | namespace TypeTraits { 12 | 13 | // A meta-function that returns true if T is a reference 14 | template 15 | struct IsReference { 16 | static const bool value = false; 17 | }; 18 | 19 | template 20 | struct IsReference { 21 | static const bool value = true; 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/TypeTraits/IsSame.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | namespace ArduinoJson { 11 | namespace TypeTraits { 12 | 13 | // A meta-function that returns true if types T and U are the same. 14 | template 15 | struct IsSame { 16 | static const bool value = false; 17 | }; 18 | 19 | template 20 | struct IsSame { 21 | static const bool value = true; 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/TypeTraits/RemoveConst.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | namespace ArduinoJson { 11 | namespace TypeTraits { 12 | 13 | // A meta-function that return the type T without the const modifier 14 | template 15 | struct RemoveConst { 16 | typedef T type; 17 | }; 18 | template 19 | struct RemoveConst { 20 | typedef T type; 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/json/include/ArduinoJson/TypeTraits/RemoveReference.hpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #pragma once 9 | 10 | namespace ArduinoJson { 11 | namespace TypeTraits { 12 | 13 | // A meta-function that return the type T without the reference modifier. 14 | template 15 | struct RemoveReference { 16 | typedef T type; 17 | }; 18 | template 19 | struct RemoveReference { 20 | typedef T type; 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/json/src/ArduinoJson.h: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | // About this file 9 | // --------------- 10 | // This file is here to please the Arduino IDE. It must be present in the src/ 11 | // for the IDE to find it. Feel free to ignore this file if your working in 12 | // another environment 13 | 14 | #include "../include/ArduinoJson.h" 15 | -------------------------------------------------------------------------------- /src/json/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright Benoit Blanchon 2014-2016 2 | # MIT License 3 | # 4 | # Arduino JSON library 5 | # https://github.com/bblanchon/ArduinoJson 6 | # If you like this project, please add a star! 7 | 8 | file(GLOB_RECURSE HPP_FILES ../include/*.hpp) 9 | file(GLOB_RECURSE IPP_FILES ../include/*.ipp) 10 | file(GLOB_RECURSE CPP_FILES *.cpp) 11 | 12 | if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") 13 | add_compile_options( 14 | -fno-exceptions 15 | -fno-rtti 16 | -pedantic 17 | -Wall 18 | -Wcast-align 19 | -Wcast-qual 20 | -Wconversion 21 | -Wctor-dtor-privacy 22 | -Wdisabled-optimization 23 | -Werror 24 | -Wextra 25 | -Wformat=2 26 | -Winit-self 27 | -Wmissing-include-dirs 28 | -Wno-parentheses 29 | -Wno-sign-conversion 30 | -Wno-unused 31 | -Wno-variadic-macros 32 | -Wnon-virtual-dtor 33 | -Wold-style-cast 34 | -Woverloaded-virtual 35 | -Wredundant-decls 36 | -Wshadow 37 | -Wsign-promo 38 | -Wstrict-overflow=5 39 | -Wundef 40 | ) 41 | endif() 42 | 43 | if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") 44 | add_compile_options( 45 | -Wstrict-null-sentinel 46 | ) 47 | 48 | if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.5) 49 | add_compile_options(-Wlogical-op) # the flag exists in 4.4 but is buggy 50 | endif() 51 | 52 | if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.6) 53 | add_compile_options(-Wnoexcept) 54 | endif() 55 | endif() 56 | 57 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 58 | add_compile_options( 59 | -Wc++11-compat 60 | -Wdeprecated-register 61 | ) 62 | endif() 63 | 64 | if(MSVC) 65 | add_definitions(-D_CRT_SECURE_NO_WARNINGS) 66 | add_compile_options(-W4) 67 | endif() 68 | 69 | add_library(ArduinoJson ${CPP_FILES} ${HPP_FILES} ${IPP_FILES}) 70 | 71 | target_include_directories(ArduinoJson INTERFACE ${CMAKE_CURRENT_LIST_DIR}/../include) 72 | -------------------------------------------------------------------------------- /src/json/src/Internals/Comments.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../../include/ArduinoJson/Internals/Comments.hpp" 9 | 10 | inline static const char *skipCStyleComment(const char *ptr) { 11 | ptr += 2; 12 | for (;;) { 13 | if (ptr[0] == '\0') return ptr; 14 | if (ptr[0] == '*' && ptr[1] == '/') return ptr + 2; 15 | ptr++; 16 | } 17 | } 18 | 19 | inline static const char *skipCppStyleComment(const char *ptr) { 20 | ptr += 2; 21 | for (;;) { 22 | if (ptr[0] == '\0' || ptr[0] == '\n') return ptr; 23 | ptr++; 24 | } 25 | } 26 | 27 | const char *ArduinoJson::Internals::skipSpacesAndComments(const char *ptr) { 28 | for (;;) { 29 | switch (ptr[0]) { 30 | case ' ': 31 | case '\t': 32 | case '\r': 33 | case '\n': 34 | ptr++; 35 | continue; 36 | case '/': 37 | switch (ptr[1]) { 38 | case '*': 39 | ptr = skipCStyleComment(ptr); 40 | break; 41 | case '/': 42 | ptr = skipCppStyleComment(ptr); 43 | break; 44 | default: 45 | return ptr; 46 | } 47 | break; 48 | default: 49 | return ptr; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/json/src/Internals/Encoding.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../../include/ArduinoJson/Internals/Encoding.hpp" 9 | 10 | // How to escape special chars: 11 | // _escapeTable[2*i+1] => the special char 12 | // _escapeTable[2*i] => the char to use instead 13 | const char ArduinoJson::Internals::Encoding::_escapeTable[] = 14 | "\"\"\\\\b\bf\fn\nr\rt\t"; 15 | -------------------------------------------------------------------------------- /src/json/src/Internals/IndentedPrint.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../../include/ArduinoJson/Internals/IndentedPrint.hpp" 9 | 10 | using namespace ArduinoJson::Internals; 11 | 12 | size_t IndentedPrint::write(uint8_t c) { 13 | size_t n = 0; 14 | 15 | if (isNewLine) n += writeTabs(); 16 | 17 | n += sink->write(c); 18 | 19 | isNewLine = c == '\n'; 20 | 21 | return n; 22 | } 23 | 24 | inline size_t IndentedPrint::writeTabs() { 25 | size_t n = 0; 26 | 27 | for (int i = 0; i < level * tabSize; i++) n += sink->write(' '); 28 | 29 | return n; 30 | } 31 | -------------------------------------------------------------------------------- /src/json/src/Internals/JsonParser.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../../include/ArduinoJson/Internals/JsonParser.hpp" 9 | 10 | #include "../../include/ArduinoJson/Internals/Comments.hpp" 11 | #include "../../include/ArduinoJson/Internals/Encoding.hpp" 12 | #include "../../include/ArduinoJson/JsonArray.hpp" 13 | #include "../../include/ArduinoJson/JsonBuffer.hpp" 14 | #include "../../include/ArduinoJson/JsonObject.hpp" 15 | 16 | using namespace ArduinoJson; 17 | using namespace ArduinoJson::Internals; 18 | 19 | bool JsonParser::skip(char charToSkip) { 20 | const char *ptr = skipSpacesAndComments(_readPtr); 21 | if (*ptr != charToSkip) return false; 22 | ptr++; 23 | _readPtr = skipSpacesAndComments(ptr); 24 | return true; 25 | } 26 | 27 | bool JsonParser::parseAnythingTo(JsonVariant *destination) { 28 | if (_nestingLimit == 0) return false; 29 | _nestingLimit--; 30 | bool success = parseAnythingToUnsafe(destination); 31 | _nestingLimit++; 32 | return success; 33 | } 34 | 35 | inline bool JsonParser::parseAnythingToUnsafe(JsonVariant *destination) { 36 | _readPtr = skipSpacesAndComments(_readPtr); 37 | 38 | switch (*_readPtr) { 39 | case '[': 40 | return parseArrayTo(destination); 41 | 42 | case '{': 43 | return parseObjectTo(destination); 44 | 45 | default: 46 | return parseStringTo(destination); 47 | } 48 | } 49 | 50 | JsonArray &JsonParser::parseArray() { 51 | // Create an empty array 52 | JsonArray &array = _buffer->createArray(); 53 | 54 | // Check opening braket 55 | if (!skip('[')) goto ERROR_MISSING_BRACKET; 56 | if (skip(']')) goto SUCCESS_EMPTY_ARRAY; 57 | 58 | // Read each value 59 | for (;;) { 60 | // 1 - Parse value 61 | JsonVariant value; 62 | if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE; 63 | if (!array.add(value)) goto ERROR_NO_MEMORY; 64 | 65 | // 2 - More values? 66 | if (skip(']')) goto SUCCES_NON_EMPTY_ARRAY; 67 | if (!skip(',')) goto ERROR_MISSING_COMMA; 68 | } 69 | 70 | SUCCESS_EMPTY_ARRAY: 71 | SUCCES_NON_EMPTY_ARRAY: 72 | return array; 73 | 74 | ERROR_INVALID_VALUE: 75 | ERROR_MISSING_BRACKET: 76 | ERROR_MISSING_COMMA: 77 | ERROR_NO_MEMORY: 78 | return JsonArray::invalid(); 79 | } 80 | 81 | bool JsonParser::parseArrayTo(JsonVariant *destination) { 82 | JsonArray &array = parseArray(); 83 | if (!array.success()) return false; 84 | 85 | *destination = array; 86 | return true; 87 | } 88 | 89 | JsonObject &JsonParser::parseObject() { 90 | // Create an empty object 91 | JsonObject &object = _buffer->createObject(); 92 | 93 | // Check opening brace 94 | if (!skip('{')) goto ERROR_MISSING_BRACE; 95 | if (skip('}')) goto SUCCESS_EMPTY_OBJECT; 96 | 97 | // Read each key value pair 98 | for (;;) { 99 | // 1 - Parse key 100 | const char *key = parseString(); 101 | if (!key) goto ERROR_INVALID_KEY; 102 | if (!skip(':')) goto ERROR_MISSING_COLON; 103 | 104 | // 2 - Parse value 105 | JsonVariant value; 106 | if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE; 107 | if (!object.set(key, value)) goto ERROR_NO_MEMORY; 108 | 109 | // 3 - More keys/values? 110 | if (skip('}')) goto SUCCESS_NON_EMPTY_OBJECT; 111 | if (!skip(',')) goto ERROR_MISSING_COMMA; 112 | } 113 | 114 | SUCCESS_EMPTY_OBJECT: 115 | SUCCESS_NON_EMPTY_OBJECT: 116 | return object; 117 | 118 | ERROR_INVALID_KEY: 119 | ERROR_INVALID_VALUE: 120 | ERROR_MISSING_BRACE: 121 | ERROR_MISSING_COLON: 122 | ERROR_MISSING_COMMA: 123 | ERROR_NO_MEMORY: 124 | return JsonObject::invalid(); 125 | } 126 | 127 | bool JsonParser::parseObjectTo(JsonVariant *destination) { 128 | JsonObject &object = parseObject(); 129 | if (!object.success()) return false; 130 | 131 | *destination = object; 132 | return true; 133 | } 134 | 135 | static inline bool isInRange(char c, char min, char max) { 136 | return min <= c && c <= max; 137 | } 138 | 139 | static inline bool isLetterOrNumber(char c) { 140 | return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') || 141 | isInRange(c, 'A', 'Z') || c == '-' || c == '.'; 142 | } 143 | 144 | static inline bool isQuote(char c) { return c == '\'' || c == '\"'; } 145 | 146 | const char *JsonParser::parseString() { 147 | const char *readPtr = _readPtr; 148 | char *writePtr = _writePtr; 149 | 150 | char c = *readPtr; 151 | 152 | if (isQuote(c)) { // quotes 153 | char stopChar = c; 154 | for (;;) { 155 | c = *++readPtr; 156 | if (c == '\0') break; 157 | 158 | if (c == stopChar) { 159 | readPtr++; 160 | break; 161 | } 162 | 163 | if (c == '\\') { 164 | // replace char 165 | c = Encoding::unescapeChar(*++readPtr); 166 | if (c == '\0') break; 167 | } 168 | 169 | *writePtr++ = c; 170 | } 171 | } else { // no quotes 172 | for (;;) { 173 | if (!isLetterOrNumber(c)) break; 174 | *writePtr++ = c; 175 | c = *++readPtr; 176 | } 177 | } 178 | // end the string here 179 | *writePtr++ = '\0'; 180 | 181 | const char *startPtr = _writePtr; 182 | 183 | // update end ptr 184 | _readPtr = readPtr; 185 | _writePtr = writePtr; 186 | 187 | // return pointer to unquoted string 188 | return startPtr; 189 | } 190 | 191 | bool JsonParser::parseStringTo(JsonVariant *destination) { 192 | bool hasQuotes = isQuote(_readPtr[0]); 193 | const char *value = parseString(); 194 | if (value == NULL) return false; 195 | if (hasQuotes) { 196 | *destination = value; 197 | } else { 198 | *destination = Unparsed(value); 199 | } 200 | return true; 201 | } 202 | -------------------------------------------------------------------------------- /src/json/src/Internals/List.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../../include/ArduinoJson/Internals/List.hpp" 9 | 10 | #include "../../include/ArduinoJson/JsonPair.hpp" 11 | #include "../../include/ArduinoJson/JsonVariant.hpp" 12 | 13 | using namespace ArduinoJson; 14 | using namespace ArduinoJson::Internals; 15 | 16 | template 17 | size_t List::size() const { 18 | size_t nodeCount = 0; 19 | for (node_type *node = _firstNode; node; node = node->next) nodeCount++; 20 | return nodeCount; 21 | } 22 | 23 | template 24 | typename List::node_type *List::addNewNode() { 25 | node_type *newNode = new (_buffer) node_type(); 26 | 27 | if (_firstNode) { 28 | node_type *lastNode = _firstNode; 29 | while (lastNode->next) lastNode = lastNode->next; 30 | lastNode->next = newNode; 31 | } else { 32 | _firstNode = newNode; 33 | } 34 | 35 | return newNode; 36 | } 37 | 38 | template 39 | void List::removeNode(node_type *nodeToRemove) { 40 | if (!nodeToRemove) return; 41 | if (nodeToRemove == _firstNode) { 42 | _firstNode = nodeToRemove->next; 43 | } else { 44 | for (node_type *node = _firstNode; node; node = node->next) 45 | if (node->next == nodeToRemove) node->next = nodeToRemove->next; 46 | } 47 | } 48 | 49 | template class ArduinoJson::Internals::List; 50 | template class ArduinoJson::Internals::List; 51 | -------------------------------------------------------------------------------- /src/json/src/Internals/Prettyfier.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../../include/ArduinoJson/Internals/Prettyfier.hpp" 9 | 10 | using namespace ArduinoJson::Internals; 11 | 12 | size_t Prettyfier::write(uint8_t c) { 13 | size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c); 14 | _previousChar = c; 15 | return n; 16 | } 17 | 18 | inline size_t Prettyfier::handleStringChar(uint8_t c) { 19 | bool isQuote = c == '"' && _previousChar != '\\'; 20 | 21 | if (isQuote) _inString = false; 22 | 23 | return _sink.write(c); 24 | } 25 | 26 | inline size_t Prettyfier::handleMarkupChar(uint8_t c) { 27 | switch (c) { 28 | case '{': 29 | case '[': 30 | return handleBlockOpen(c); 31 | 32 | case '}': 33 | case ']': 34 | return handleBlockClose(c); 35 | 36 | case ':': 37 | return handleColon(); 38 | 39 | case ',': 40 | return handleComma(); 41 | 42 | case '"': 43 | return handleQuoteOpen(); 44 | 45 | default: 46 | return handleNormalChar(c); 47 | } 48 | } 49 | 50 | inline size_t Prettyfier::handleBlockOpen(uint8_t c) { 51 | return indentIfNeeded() + _sink.write(c); 52 | } 53 | 54 | inline size_t Prettyfier::handleBlockClose(uint8_t c) { 55 | return unindentIfNeeded() + _sink.write(c); 56 | } 57 | 58 | inline size_t Prettyfier::handleColon() { 59 | return _sink.write(':') + _sink.write(' '); 60 | } 61 | 62 | inline size_t Prettyfier::handleComma() { 63 | return _sink.write(',') + _sink.println(); 64 | } 65 | 66 | inline size_t Prettyfier::handleQuoteOpen() { 67 | _inString = true; 68 | return indentIfNeeded() + _sink.write('"'); 69 | } 70 | 71 | inline size_t Prettyfier::handleNormalChar(uint8_t c) { 72 | return indentIfNeeded() + _sink.write(c); 73 | } 74 | 75 | size_t Prettyfier::indentIfNeeded() { 76 | if (!inEmptyBlock()) return 0; 77 | 78 | _sink.indent(); 79 | return _sink.println(); 80 | } 81 | 82 | size_t Prettyfier::unindentIfNeeded() { 83 | if (inEmptyBlock()) return 0; 84 | 85 | _sink.unindent(); 86 | return _sink.println(); 87 | } 88 | -------------------------------------------------------------------------------- /src/json/src/Internals/StaticStringBuilder.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../../include/ArduinoJson/Internals/StaticStringBuilder.hpp" 9 | 10 | using namespace ArduinoJson::Internals; 11 | 12 | size_t StaticStringBuilder::write(uint8_t c) { 13 | if (length >= capacity) return 0; 14 | 15 | buffer[length++] = c; 16 | buffer[length] = '\0'; 17 | return 1; 18 | } 19 | -------------------------------------------------------------------------------- /src/json/src/JsonArray.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../include/ArduinoJson/JsonArray.hpp" 9 | 10 | #include "../include/ArduinoJson/JsonBuffer.hpp" 11 | #include "../include/ArduinoJson/JsonObject.hpp" 12 | 13 | using namespace ArduinoJson; 14 | using namespace ArduinoJson::Internals; 15 | 16 | JsonArray JsonArray::_invalid(NULL); 17 | 18 | JsonArray::node_type *JsonArray::getNodeAt(size_t index) const { 19 | node_type *node = _firstNode; 20 | while (node && index--) node = node->next; 21 | return node; 22 | } 23 | 24 | void JsonArray::removeAt(size_t index) { removeNode(getNodeAt(index)); } 25 | 26 | void JsonArray::writeTo(JsonWriter &writer) const { 27 | writer.beginArray(); 28 | 29 | const node_type *child = _firstNode; 30 | while (child) { 31 | child->content.writeTo(writer); 32 | 33 | child = child->next; 34 | if (!child) break; 35 | 36 | writer.writeComma(); 37 | } 38 | 39 | writer.endArray(); 40 | } 41 | -------------------------------------------------------------------------------- /src/json/src/JsonBuffer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../include/ArduinoJson/JsonBuffer.hpp" 9 | 10 | #include "../include/ArduinoJson/Internals/JsonParser.hpp" 11 | #include "../include/ArduinoJson/JsonArray.hpp" 12 | #include "../include/ArduinoJson/JsonObject.hpp" 13 | 14 | using namespace ArduinoJson; 15 | using namespace ArduinoJson::Internals; 16 | 17 | JsonArray &JsonBuffer::createArray() { 18 | JsonArray *ptr = new (this) JsonArray(this); 19 | return ptr ? *ptr : JsonArray::invalid(); 20 | } 21 | 22 | JsonObject &JsonBuffer::createObject() { 23 | JsonObject *ptr = new (this) JsonObject(this); 24 | return ptr ? *ptr : JsonObject::invalid(); 25 | } 26 | 27 | JsonArray &JsonBuffer::parseArray(char *json, uint8_t nestingLimit) { 28 | JsonParser parser(this, json, nestingLimit); 29 | return parser.parseArray(); 30 | } 31 | 32 | JsonObject &JsonBuffer::parseObject(char *json, uint8_t nestingLimit) { 33 | JsonParser parser(this, json, nestingLimit); 34 | return parser.parseObject(); 35 | } 36 | 37 | char *JsonBuffer::strdup(const char *source, size_t length) { 38 | size_t size = length + 1; 39 | char *dest = static_cast(alloc(size)); 40 | if (dest != NULL) memcpy(dest, source, size); 41 | return dest; 42 | } 43 | -------------------------------------------------------------------------------- /src/json/src/JsonObject.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../include/ArduinoJson/JsonObject.hpp" 9 | 10 | #include // for strcmp 11 | 12 | #include "../include/ArduinoJson/Internals/StaticStringBuilder.hpp" 13 | #include "../include/ArduinoJson/JsonArray.hpp" 14 | #include "../include/ArduinoJson/JsonBuffer.hpp" 15 | 16 | using namespace ArduinoJson; 17 | using namespace ArduinoJson::Internals; 18 | 19 | JsonObject JsonObject::_invalid(NULL); 20 | 21 | JsonObject::node_type *JsonObject::getNodeAt(const char *key) const { 22 | for (node_type *node = _firstNode; node; node = node->next) { 23 | if (!strcmp(node->content.key, key)) return node; 24 | } 25 | return NULL; 26 | } 27 | 28 | void JsonObject::writeTo(JsonWriter &writer) const { 29 | writer.beginObject(); 30 | 31 | const node_type *node = _firstNode; 32 | while (node) { 33 | writer.writeString(node->content.key); 34 | writer.writeColon(); 35 | node->content.value.writeTo(writer); 36 | 37 | node = node->next; 38 | if (!node) break; 39 | 40 | writer.writeComma(); 41 | } 42 | 43 | writer.endObject(); 44 | } 45 | -------------------------------------------------------------------------------- /src/json/src/JsonVariant.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Benoit Blanchon 2014-2016 2 | // MIT License 3 | // 4 | // Arduino JSON library 5 | // https://github.com/bblanchon/ArduinoJson 6 | // If you like this project, please add a star! 7 | 8 | #include "../include/ArduinoJson/JsonVariant.hpp" 9 | 10 | #include "../include/ArduinoJson/JsonArray.hpp" 11 | #include "../include/ArduinoJson/JsonObject.hpp" 12 | 13 | #include // for errno 14 | #include // for strtol, strtod 15 | 16 | using namespace ArduinoJson::Internals; 17 | 18 | namespace ArduinoJson { 19 | 20 | const char *JsonVariant::asString() const { 21 | if (_type == JSON_UNPARSED && _content.asString && 22 | !strcmp("null", _content.asString)) 23 | return NULL; 24 | if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString; 25 | return NULL; 26 | } 27 | 28 | JsonFloat JsonVariant::asFloat() const { 29 | if (_type >= JSON_FLOAT_0_DECIMALS) return _content.asFloat; 30 | 31 | if (_type == JSON_INTEGER || _type == JSON_BOOLEAN) 32 | return static_cast(_content.asInteger); 33 | 34 | if ((_type == JSON_STRING || _type == JSON_UNPARSED) && _content.asString) 35 | return parse(_content.asString); 36 | 37 | return 0.0; 38 | } 39 | 40 | String JsonVariant::toString() const { 41 | String s; 42 | if ((_type == JSON_STRING || _type == JSON_UNPARSED) && 43 | _content.asString != NULL) 44 | s = _content.asString; 45 | else 46 | printTo(s); 47 | return s; 48 | } 49 | 50 | template <> 51 | bool JsonVariant::is() const { 52 | if (_type == JSON_BOOLEAN) return true; 53 | 54 | if (_type != JSON_UNPARSED || _content.asString == NULL) return false; 55 | 56 | return !strcmp(_content.asString, "true") || 57 | !strcmp(_content.asString, "false"); 58 | } 59 | 60 | template <> 61 | bool JsonVariant::is() const { 62 | if (_type == JSON_INTEGER) return true; 63 | 64 | if (_type != JSON_UNPARSED || _content.asString == NULL) return false; 65 | 66 | char *end; 67 | errno = 0; 68 | strtol(_content.asString, &end, 10); 69 | 70 | return *end == '\0' && errno == 0; 71 | } 72 | 73 | template <> 74 | bool JsonVariant::is() const { 75 | if (_type >= JSON_FLOAT_0_DECIMALS) return true; 76 | 77 | if (_type != JSON_UNPARSED || _content.asString == NULL) return false; 78 | 79 | char *end; 80 | errno = 0; 81 | strtod(_content.asString, &end); 82 | 83 | return *end == '\0' && errno == 0 && !is(); 84 | } 85 | 86 | void JsonVariant::writeTo(JsonWriter &writer) const { 87 | if (_type == JSON_ARRAY) 88 | _content.asArray->writeTo(writer); 89 | 90 | else if (_type == JSON_OBJECT) 91 | _content.asObject->writeTo(writer); 92 | 93 | else if (_type == JSON_STRING) 94 | writer.writeString(_content.asString); 95 | 96 | else if (_type == JSON_UNPARSED) 97 | writer.writeRaw(_content.asString); 98 | 99 | else if (_type == JSON_INTEGER) 100 | writer.writeInteger(_content.asInteger); 101 | 102 | else if (_type == JSON_BOOLEAN) 103 | writer.writeBoolean(_content.asInteger != 0); 104 | 105 | else if (_type >= JSON_FLOAT_0_DECIMALS) { 106 | uint8_t decimals = static_cast(_type - JSON_FLOAT_0_DECIMALS); 107 | writer.writeFloat(_content.asFloat, decimals); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/mqtt/MQTTClient.h: -------------------------------------------------------------------------------- 1 | #ifndef MQTT_CLIENT_H 2 | #define MQTT_CLIENT_H 3 | 4 | #ifndef MQTT_BUFFER_SIZE 5 | #define MQTT_BUFFER_SIZE 128 6 | #endif 7 | 8 | #define MQTTCLIENT_QOS1 0 9 | #define MQTTCLIENT_QOS2 0 10 | 11 | #include 12 | #include 13 | #include 14 | #include "lib/MQTTClient.h" 15 | #include "Network.h" 16 | #include "Timer.h" 17 | 18 | typedef struct { 19 | char * topic; 20 | char * payload; 21 | unsigned int length; 22 | boolean retained; 23 | } MQTTMessage; 24 | 25 | template 26 | class MQTTClient { 27 | private: 28 | Network network; 29 | MQTT::Client * client; 30 | MQTTPacket_connectData options; 31 | const char * hostname; 32 | int port; 33 | void MQTTClient_messageHandler(MQTT::MessageData &messageData); 34 | public: 35 | MQTTClient(); 36 | boolean begin(const char * hostname, Client& client, AntoMQTT *antoMqtt, void (AntoMQTT::*messageHandler) (MQTT::MessageData&)); 37 | boolean begin(const char * hostname, int port, Client& client, AntoMQTT *antoMqtt, void (AntoMQTT::*messageHandler) (MQTT::MessageData&)); 38 | void setWill(const char * topic); 39 | void setWill(const char * topic, const char * payload); 40 | boolean connect(const char * clientId); 41 | boolean connect(const char * clientId, const char* username, const char* password); 42 | boolean publish(String topic); 43 | boolean publish(String topic, String payload); 44 | boolean publish(const char * topic, String payload); 45 | boolean publish(const char * topic, const char * payload); 46 | boolean publish(const char * topic, char * payload, unsigned int length); 47 | boolean publish(MQTTMessage * message); 48 | boolean subscribe(String topic, AntoMQTT *antoMqtt); 49 | boolean subscribe(const char * topic, AntoMQTT *antoMqtt); 50 | boolean unsubscribe(String topic); 51 | boolean unsubscribe(const char * topic); 52 | void loop(); 53 | boolean connected(); 54 | boolean disconnect(); 55 | }; 56 | 57 | template 58 | MQTTClient::MQTTClient() {} 59 | 60 | template 61 | boolean MQTTClient::begin(const char * hostname, Client& client, AntoMQTT *antoMqtt, void (AntoMQTT::*messageHandler) (MQTT::MessageData&)) { 62 | return this->begin(hostname, 1883, client, antoMqtt, messageHandler); 63 | } 64 | 65 | template 66 | boolean MQTTClient::begin(const char * _hostname, int _port, Client& _client, AntoMQTT *antoMqtt, void (AntoMQTT::*messageHandler) (MQTT::MessageData&)) { 67 | this->client = new MQTT::Client(this->network); 68 | this->network.setClient(&_client); 69 | this->client->setDefaultMessageHandler(antoMqtt, messageHandler); 70 | this->hostname = _hostname; 71 | this->port = _port; 72 | this->options = MQTTPacket_connectData_initializer; 73 | 74 | return true; 75 | } 76 | 77 | template 78 | void MQTTClient::setWill(const char * topic) { 79 | this->setWill(topic, ""); 80 | } 81 | 82 | template 83 | void MQTTClient::setWill(const char * topic, const char * payload) { 84 | this->options.willFlag = 0x1; 85 | this->options.will.topicName.cstring = (char*)topic; 86 | this->options.will.message.cstring = (char*)payload; 87 | } 88 | 89 | template 90 | boolean MQTTClient::connect(const char * clientId) { 91 | return this->connect(clientId, NULL, NULL); 92 | } 93 | 94 | template 95 | boolean MQTTClient::connect(const char * clientId, const char * username, const char * password) { 96 | if(!this->network.connect((char*)this->hostname, this->port)) { 97 | return false; 98 | } 99 | 100 | this->options.clientID.cstring = (char*)clientId; 101 | if(username && password) { 102 | this->options.username.cstring = (char*)username; 103 | this->options.password.cstring = (char*)password; 104 | } 105 | 106 | return this->client->connect(this->options) == MQTT::SUCCESS; 107 | } 108 | 109 | template 110 | boolean MQTTClient::publish(String topic) { 111 | return this->publish(topic.c_str(), ""); 112 | } 113 | 114 | template 115 | boolean MQTTClient::publish(String topic, String payload) { 116 | return this->publish(topic.c_str(), payload.c_str()); 117 | } 118 | 119 | template 120 | boolean MQTTClient::publish(const char * topic, String payload) { 121 | return this->publish(topic, payload.c_str()); 122 | } 123 | 124 | template 125 | boolean MQTTClient::publish(const char * topic, const char * payload) { 126 | return this->publish(topic, (char*)payload, (unsigned int)strlen(payload)); 127 | } 128 | 129 | template 130 | boolean MQTTClient::publish(const char * topic, char * payload, unsigned int length) { 131 | MQTT::Message message; 132 | message.qos = MQTT::QOS0; 133 | message.retained = false; 134 | message.dup = false; 135 | message.payload = payload; 136 | message.payloadlen = length; 137 | 138 | return client->publish(topic, message) == MQTT::SUCCESS; 139 | } 140 | 141 | template 142 | boolean MQTTClient::publish(MQTTMessage * message) { 143 | MQTT::Message _message; 144 | _message.qos = MQTT::QOS0; 145 | _message.retained = message->retained; 146 | _message.dup = false; 147 | _message.payload = message->payload; 148 | _message.payloadlen = message->length; 149 | 150 | return client->publish(message->topic, _message) == MQTT::SUCCESS; 151 | } 152 | 153 | template 154 | boolean MQTTClient::subscribe(String topic, AntoMQTT *antoMqtt) { 155 | return this->subscribe(topic.c_str(), antoMqtt); 156 | } 157 | 158 | template 159 | boolean MQTTClient::subscribe(const char * topic, AntoMQTT *antoMqtt) { 160 | return client->subscribe(topic, MQTT::QOS0, antoMqtt, NULL) == MQTT::SUCCESS; 161 | } 162 | 163 | template 164 | boolean MQTTClient::unsubscribe(String topic) { 165 | return this->unsubscribe(topic.c_str()); 166 | } 167 | 168 | template 169 | boolean MQTTClient::unsubscribe(const char * topic) { 170 | return client->unsubscribe(topic) == MQTT::SUCCESS; 171 | } 172 | 173 | template 174 | void MQTTClient::loop() { 175 | if(!this->network.connected() && this->client->isConnected()) { 176 | // the following call will not send a packet but reset the instance 177 | // to allow proper reconnection 178 | this->client->disconnect(); 179 | } 180 | 181 | this->client->yield(); 182 | } 183 | 184 | template 185 | boolean MQTTClient::connected() { 186 | return this->client->isConnected(); 187 | } 188 | 189 | template 190 | boolean MQTTClient::disconnect() { 191 | return this->client->disconnect() == MQTT::SUCCESS; 192 | } 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /src/mqtt/MQTTTest.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class MQTTTest { 5 | public: 6 | void run(T *client); 7 | void message(String topic, String payload); 8 | private: 9 | T *client; 10 | void printResult(boolean res); 11 | boolean testMessage(const char * topic, const char * payload); 12 | boolean newMessage = false; 13 | boolean passedTest = false; 14 | String testTopic; 15 | String testPayload; 16 | boolean testConnectivity(boolean test); 17 | }; 18 | 19 | /* Methods */ 20 | 21 | template 22 | void MQTTTest::run(T *client) { 23 | this->client = client; 24 | 25 | Serial.println("Starting tests..."); 26 | 27 | Serial.print("[Test 1] Connect: "); 28 | this->printResult(this->client->connect("arduino-mqtt-test", "try", "try") && this->testConnectivity(true)); 29 | 30 | Serial.print("[Test 2] Subscribe & Publish: "); 31 | this->client->subscribe("arduino-mqtt-test/topic1"); 32 | this->client->publish("arduino-mqtt-test/topic1", "test"); 33 | this->printResult(this->testMessage("arduino-mqtt-test/topic1", "test")); 34 | 35 | Serial.print("[Test 3] Unsubscribe: "); 36 | this->client->subscribe("arduino-mqtt-test/topic2"); 37 | this->client->subscribe("arduino-mqtt-test/topic3"); 38 | this->client->unsubscribe("arduino-mqtt-test/topic2"); 39 | this->client->publish("arduino-mqtt-test/topic2", "test"); 40 | this->client->publish("arduino-mqtt-test/topic3", "test"); 41 | this->printResult(this->testMessage("arduino-mqtt-test/topic3", "test")); 42 | 43 | Serial.print("[Test 4] Disconnect: "); 44 | this->client->disconnect(); 45 | this->printResult(this->testConnectivity(false)); 46 | 47 | Serial.println("Tests finished!"); 48 | } 49 | 50 | template 51 | void MQTTTest::message(String topic, String payload) { 52 | this->newMessage = true; 53 | this->passedTest = topic.equals(this->testTopic) && payload.equals(this->testPayload); 54 | } 55 | 56 | /* Helpers */ 57 | 58 | template 59 | void MQTTTest::printResult(boolean res) { 60 | res ? Serial.println("SUCCESS") : Serial.println("FAILED"); 61 | } 62 | 63 | template 64 | boolean MQTTTest::testMessage(const char *topic, const char *payload) { 65 | this->testTopic = String(topic); 66 | this->testPayload = String(payload); 67 | 68 | while(!this->newMessage) { 69 | this->client->loop(); 70 | } 71 | 72 | boolean ret = this->passedTest; 73 | this->newMessage = false; 74 | this->passedTest = false; 75 | 76 | return ret; 77 | } 78 | 79 | template 80 | boolean MQTTTest::testConnectivity(boolean test) { 81 | while(this->client->connected() != test) { 82 | this->client->loop(); 83 | } 84 | 85 | return this->client->connected() == test; 86 | } 87 | -------------------------------------------------------------------------------- /src/mqtt/Network.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Network.h" 3 | 4 | void Network::setClient(Client * _client) { 5 | this->client = _client; 6 | } 7 | 8 | int Network::connect(char* hostname, int port) { 9 | return this->client->connect(hostname, port); 10 | } 11 | 12 | int Network::read(unsigned char* buffer, int len, int timeout) { 13 | if(!client->connected()) { 14 | return -1; // return an error 15 | } 16 | 17 | if(this->client->available() == 0) { 18 | return 0; // nothing to read 19 | } 20 | 21 | this->client->setTimeout(timeout); 22 | return this->client->readBytes(buffer, len); 23 | } 24 | 25 | int Network::write(unsigned char* buffer, int len, int timeout) { 26 | if(!client->connected()) { 27 | return -1; // return an error 28 | } 29 | 30 | client->setTimeout(timeout); 31 | return client->write((uint8_t*)buffer, len); 32 | } 33 | 34 | boolean Network::connected() { 35 | return client->connected(); 36 | } 37 | 38 | int Network::disconnect() { 39 | client->stop(); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /src/mqtt/Network.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Network { 4 | private: 5 | Client* client; 6 | public: 7 | void setClient(Client * client); 8 | int connect(char* hostname, int port); 9 | int read(unsigned char* buffer, int len, int timeout); 10 | int write(unsigned char* buffer, int len, int timeout); 11 | boolean connected(); 12 | int disconnect(); 13 | }; 14 | -------------------------------------------------------------------------------- /src/mqtt/Timer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Timer.h" 3 | 4 | Timer::Timer() { 5 | this->interval_end_ms = 0L; 6 | } 7 | 8 | Timer::Timer(int ms) { 9 | countdown_ms(ms); 10 | } 11 | 12 | bool Timer::expired() { 13 | return (interval_end_ms > 0L) && (millis() >= interval_end_ms); 14 | } 15 | 16 | void Timer::countdown_ms(unsigned long ms) { 17 | interval_end_ms = millis() + ms; 18 | } 19 | 20 | void Timer::countdown(int seconds) { 21 | countdown_ms((unsigned long)seconds * 1000L); 22 | } 23 | 24 | int Timer::left_ms() { 25 | return interval_end_ms - millis(); 26 | } 27 | -------------------------------------------------------------------------------- /src/mqtt/Timer.h: -------------------------------------------------------------------------------- 1 | class Timer { 2 | public: 3 | Timer(); 4 | Timer(int ms); 5 | bool expired(); 6 | void countdown_ms(unsigned long ms); 7 | void countdown(int seconds); 8 | int left_ms(); 9 | private: 10 | unsigned long interval_end_ms; 11 | }; 12 | -------------------------------------------------------------------------------- /src/mqtt/YunMQTTClient.cpp: -------------------------------------------------------------------------------- 1 | #include "YunMQTTClient.h" 2 | 3 | #ifdef YUN_MQTT_CLIENT_ENABLED 4 | 5 | #include 6 | 7 | YunMQTTClient::YunMQTTClient() {} 8 | 9 | boolean YunMQTTClient::begin(const char * hostname) { 10 | return this->begin(hostname, 1883); 11 | } 12 | 13 | boolean YunMQTTClient::begin(const char * hostname, int port) { 14 | this->hostname = hostname; 15 | this->port = port; 16 | 17 | return this->updateBridge(); 18 | } 19 | 20 | boolean YunMQTTClient::updateBridge() { 21 | Process p; 22 | 23 | int r1 = p.runShellCommand(F("mkdir -p /usr/arduino-mqtt")); 24 | int r2 = p.runShellCommand(F("wget -N https://raw.githubusercontent.com/256dpi/arduino-mqtt/v1.10.1/yun/mqtt.py --no-check-certificate -P /usr/arduino-mqtt")); 25 | int r3 = p.runShellCommand(F("wget -N https://raw.githubusercontent.com/256dpi/arduino-mqtt/v1.10.1/yun/bridge.py --no-check-certificate -P /usr/arduino-mqtt")); 26 | 27 | return r1 == 0 && r2 == 0 && r3 == 0; 28 | } 29 | 30 | void YunMQTTClient::setWill(const char * topic) { 31 | this->setWill(topic, ""); 32 | } 33 | 34 | void YunMQTTClient::setWill(const char * topic, const char * payload) { 35 | this->willTopic = topic; 36 | this->willPayload = payload; 37 | } 38 | 39 | void YunMQTTClient::setTls(const char * caCerts) { 40 | this->tlsCaCerts = caCerts; 41 | } 42 | 43 | boolean YunMQTTClient::connect(const char * clientId) { 44 | return this->connect(clientId, "", ""); 45 | } 46 | 47 | boolean YunMQTTClient::connect(const char * clientId, const char * username, const char * password) { 48 | this->process.begin(F("python")); 49 | this->process.addParameter(F("-u")); 50 | this->process.addParameter(F("/usr/arduino-mqtt/bridge.py")); 51 | this->process.runAsynchronously(); 52 | this->process.setTimeout(10000); 53 | 54 | // wait for script to launch 55 | this->process.readStringUntil('\n'); 56 | 57 | // set will if available 58 | if(strlen(this->willTopic) > 0) { 59 | this->process.print(F("w:")); 60 | this->process.print(this->willTopic); 61 | this->process.print(F(":")); 62 | this->process.print(strlen(this->willPayload)); 63 | this->process.print(F(";")); 64 | this->process.print(this->willPayload); 65 | this->process.print(F("\n")); 66 | } 67 | 68 | // set TLS if available 69 | if(strlen(this->tlsCaCerts) > 0) { 70 | this->process.print("t:"); 71 | this->process.print(this->tlsCaCerts); 72 | this->process.print(";\n"); 73 | } 74 | 75 | // send connect request 76 | this->process.print(F("c:")); 77 | this->process.print(this->hostname); 78 | this->process.print(F(":")); 79 | this->process.print(this->port); 80 | this->process.print(F(":")); 81 | this->process.print(clientId); 82 | if(strlen(username) > 0 && strlen(password) > 0) { 83 | this->process.print(F(":")); 84 | this->process.print(username); 85 | this->process.print(F(":")); 86 | this->process.print(password); 87 | } 88 | this->process.print(F(";\n")); 89 | 90 | // wait for answer 91 | String ret = this->process.readStringUntil('\n'); 92 | this->alive = ret.equals(F("a;")); 93 | 94 | if(!this->alive) { 95 | this->process.close(); 96 | return false; 97 | } 98 | 99 | return true; 100 | } 101 | 102 | void YunMQTTClient::publish(String topic) { 103 | this->publish(topic.c_str(), ""); 104 | } 105 | 106 | void YunMQTTClient::publish(String topic, String payload) { 107 | this->publish(topic.c_str(), payload.c_str()); 108 | } 109 | 110 | void YunMQTTClient::publish(const char * topic, String payload) { 111 | this->publish(topic, payload.c_str()); 112 | } 113 | 114 | void YunMQTTClient::publish(const char * topic, const char * payload) { 115 | this->publish(topic, (char*)payload, strlen(payload)); 116 | } 117 | 118 | void YunMQTTClient::publish(const char * topic, char * payload, unsigned int length) { 119 | // send publish request 120 | this->process.print(F("p:")); 121 | this->process.print(topic); 122 | this->process.print(F(":")); 123 | this->process.print(length); 124 | this->process.print(F(";")); 125 | 126 | for(int i=0; iprocess.write(payload[i]); 128 | } 129 | 130 | this->process.print(F("\n")); 131 | } 132 | 133 | void YunMQTTClient::subscribe(String topic) { 134 | this->subscribe(topic.c_str()); 135 | } 136 | 137 | void YunMQTTClient::subscribe(const char * topic) { 138 | // send subscribe request 139 | this->process.print(F("s:")); 140 | this->process.print(topic); 141 | this->process.print(F(";\n")); 142 | } 143 | 144 | void YunMQTTClient::unsubscribe(String topic) { 145 | this->unsubscribe(topic.c_str()); 146 | } 147 | 148 | void YunMQTTClient::unsubscribe(const char * topic) { 149 | // send unsubscribe request 150 | this->process.print(F("u:")); 151 | this->process.print(topic); 152 | this->process.print(F(";\n")); 153 | } 154 | 155 | void YunMQTTClient::loop() { 156 | int av = this->process.available(); 157 | if(av > 0) { 158 | String ret = process.readStringUntil(';'); 159 | 160 | if(ret.startsWith("m")) { 161 | int startTopic = 2; 162 | int endTopic = ret.indexOf(':', startTopic + 1); 163 | String topic = ret.substring(startTopic, endTopic); 164 | 165 | int startPayloadLength = endTopic + 1; 166 | int endPayloadLength = ret.indexOf(':', startPayloadLength + 1); 167 | int payloadLength = ret.substring(startPayloadLength, endPayloadLength).toInt(); 168 | 169 | char buf[payloadLength+1]; 170 | process.readBytes(buf, payloadLength); 171 | buf[payloadLength] = '\0'; 172 | 173 | messageReceived(topic, String(buf), buf, payloadLength); 174 | } else if(ret.startsWith("e")) { 175 | this->alive = false; 176 | this->process.close(); 177 | } 178 | 179 | process.readStringUntil('\n'); 180 | } 181 | } 182 | 183 | boolean YunMQTTClient::connected() { 184 | return this->process.running() && this->alive; 185 | } 186 | 187 | void YunMQTTClient::disconnect() { 188 | // send disconnect request 189 | this->process.print(F("d;\n")); 190 | } 191 | 192 | #endif //YUN_MQTT_CLIENT_ENABLED 193 | -------------------------------------------------------------------------------- /src/mqtt/YunMQTTClient.h: -------------------------------------------------------------------------------- 1 | #ifndef YUN_MQTT_CLIENT_H 2 | #define YUN_MQTT_CLIENT_H 3 | 4 | 5 | #if defined(SERIAL_PORT_LINUXBRIDGE) || defined(SERIAL_PORT_HARDWARE) || \ 6 | defined(SERIAL_PORT_HARDWARE_OPEN) || defined(__AVR_ATmega32U4__) || \ 7 | defined(ARDUINO_AVR_YUN) 8 | #define YUN_MQTT_CLIENT_ENABLED 1 9 | #endif 10 | 11 | #ifdef YUN_MQTT_CLIENT_ENABLED 12 | 13 | #include 14 | #include 15 | 16 | void messageReceived(String topic, String payload, char * bytes, unsigned int length); 17 | 18 | class YunMQTTClient { 19 | private: 20 | Process process; 21 | const char * hostname; 22 | int port; 23 | const char * willTopic = ""; 24 | const char * willPayload = ""; 25 | const char * tlsCaCerts = ""; 26 | boolean alive = false; 27 | boolean updateBridge(); 28 | public: 29 | YunMQTTClient(); 30 | boolean begin(const char * hostname); 31 | boolean begin(const char * hostname, int port); 32 | void setWill(const char * topic); 33 | void setWill(const char * topic, const char * payload); 34 | void setTls(const char * caCerts); 35 | boolean connect(const char * clientId); 36 | boolean connect(const char * clientId, const char* username, const char* password); 37 | void publish(String topic); 38 | void publish(String topic, String payload); 39 | void publish(const char * topic, String payload); 40 | void publish(const char * topic, const char * payload); 41 | void publish(const char * topic, char * payload, unsigned int length); 42 | void subscribe(String topic); 43 | void subscribe(const char * topic); 44 | void unsubscribe(String topic); 45 | void unsubscribe(const char * topic); 46 | void loop(); 47 | boolean connected(); 48 | void disconnect(); 49 | }; 50 | 51 | #endif //YUN_MQTT_CLIENT_ENABLED 52 | #endif //YUN_MQTT_CLIENT_H 53 | -------------------------------------------------------------------------------- /src/mqtt/lib/FP.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2013, 2014 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Sam Grove - initial API and implementation and/or initial documentation 15 | * Ian Craggs - added attached and detached member functions 16 | * Sam Grove - removed need for FP.cpp 17 | *******************************************************************************/ 18 | 19 | #ifndef FP_H 20 | #define FP_H 21 | 22 | /** Example using the FP Class with global functions 23 | * @code 24 | * #include "mbed.h" 25 | * #include "FP.h" 26 | * 27 | * FPfp; 28 | * DigitalOut myled(LED1); 29 | * 30 | * void handler(bool value) 31 | * { 32 | * myled = value; 33 | * return; 34 | * } 35 | * 36 | * int main() 37 | * { 38 | * fp.attach(&handler); 39 | * 40 | * while(1) 41 | * { 42 | * fp(1); 43 | * wait(0.2); 44 | * fp(0); 45 | * wait(0.2); 46 | * } 47 | * } 48 | * @endcode 49 | */ 50 | 51 | /** Example using the FP Class with different class member functions 52 | * @code 53 | * #include "mbed.h" 54 | * #include "FP.h" 55 | * 56 | * FPfp; 57 | * DigitalOut myled(LED4); 58 | * 59 | * class Wrapper 60 | * { 61 | * public: 62 | * Wrapper(){} 63 | * 64 | * void handler(bool value) 65 | * { 66 | * myled = value; 67 | * return; 68 | * } 69 | * }; 70 | * 71 | * int main() 72 | * { 73 | * Wrapper wrapped; 74 | * fp.attach(&wrapped, &Wrapper::handler); 75 | * 76 | * while(1) 77 | * { 78 | * fp(1); 79 | * wait(0.2); 80 | * fp(0); 81 | * wait(0.2); 82 | * } 83 | * } 84 | * @endcode 85 | */ 86 | 87 | /** Example using the FP Class with member FP and member function 88 | * @code 89 | * #include "mbed.h" 90 | * #include "FP.h" 91 | * 92 | * DigitalOut myled(LED2); 93 | * 94 | * class Wrapper 95 | * { 96 | * public: 97 | * Wrapper() 98 | * { 99 | * fp.attach(this, &Wrapper::handler); 100 | * } 101 | * 102 | * void handler(bool value) 103 | * { 104 | * myled = value; 105 | * return; 106 | * } 107 | * 108 | * FPfp; 109 | * }; 110 | * 111 | * int main() 112 | * { 113 | * Wrapper wrapped; 114 | * 115 | * while(1) 116 | * { 117 | * wrapped.fp(1); 118 | * wait(0.2); 119 | * wrapped.fp(0); 120 | * wait(0.2); 121 | * } 122 | * } 123 | * @endcode 124 | */ 125 | 126 | /** 127 | * @class FP 128 | * @brief API for managing Function Pointers 129 | */ 130 | template 131 | class FP 132 | { 133 | public: 134 | /** Create the FP object - only one callback can be attached to the object, that is 135 | * a member function or a global function, not both at the same time 136 | */ 137 | FP() 138 | { 139 | obj_callback = 0; 140 | c_callback = 0; 141 | } 142 | 143 | /** Add a callback function to the object 144 | * @param item - Address of the initialized object 145 | * @param member - Address of the member function (dont forget the scope that the function is defined in) 146 | */ 147 | template 148 | void attach(T *item, retT (T::*method)(argT)) 149 | { 150 | obj_callback = (FPtrDummy *)(item); 151 | method_callback = (retT (FPtrDummy::*)(argT))(method); 152 | return; 153 | } 154 | 155 | /** Add a callback function to the object 156 | * @param function - The address of a globally defined function 157 | */ 158 | void attach(retT (*function)(argT)) 159 | { 160 | c_callback = function; 161 | } 162 | 163 | /** Invoke the function attached to the class 164 | * @param arg - An argument that is passed into the function handler that is called 165 | * @return The return from the function hanlder called by this class 166 | */ 167 | retT operator()(argT arg) const 168 | { 169 | if( 0 != c_callback ) { 170 | return obj_callback ? (obj_callback->*method_callback)(arg) : (*c_callback)(arg); 171 | } 172 | return (retT)0; 173 | } 174 | 175 | /** Determine if an callback is currently hooked 176 | * @return 1 if a method is hooked, 0 otherwise 177 | */ 178 | bool attached() 179 | { 180 | return obj_callback || c_callback; 181 | } 182 | 183 | /** Release a function from the callback hook 184 | */ 185 | void detach() 186 | { 187 | obj_callback = 0; 188 | c_callback = 0; 189 | } 190 | 191 | private: 192 | 193 | // empty type used for casting 194 | class FPtrDummy; 195 | 196 | FPtrDummy *obj_callback; 197 | 198 | /** 199 | * @union Funciton 200 | * @brief Member or global callback function 201 | */ 202 | union { 203 | retT (*c_callback)(argT); /*!< Footprint for a global function */ 204 | retT (FPtrDummy::*method_callback)(argT); /*!< Footprint for a member function */ 205 | }; 206 | }; 207 | 208 | #endif 209 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTConnect.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Xiang Rong - 442039 Add makefile to Embedded C client 16 | *******************************************************************************/ 17 | 18 | #ifndef MQTTCONNECT_H_ 19 | #define MQTTCONNECT_H_ 20 | 21 | #if !defined(DLLImport) 22 | #define DLLImport 23 | #endif 24 | #if !defined(DLLExport) 25 | #define DLLExport 26 | #endif 27 | 28 | 29 | typedef union 30 | { 31 | unsigned char all; /**< all connect flags */ 32 | #if defined(REVERSED) 33 | struct 34 | { 35 | unsigned int username : 1; /**< 3.1 user name */ 36 | unsigned int password : 1; /**< 3.1 password */ 37 | unsigned int willRetain : 1; /**< will retain setting */ 38 | unsigned int willQoS : 2; /**< will QoS value */ 39 | unsigned int will : 1; /**< will flag */ 40 | unsigned int cleansession : 1; /**< clean session flag */ 41 | unsigned int : 1; /**< unused */ 42 | } bits; 43 | #else 44 | struct 45 | { 46 | unsigned int : 1; /**< unused */ 47 | unsigned int cleansession : 1; /**< cleansession flag */ 48 | unsigned int will : 1; /**< will flag */ 49 | unsigned int willQoS : 2; /**< will QoS value */ 50 | unsigned int willRetain : 1; /**< will retain setting */ 51 | unsigned int password : 1; /**< 3.1 password */ 52 | unsigned int username : 1; /**< 3.1 user name */ 53 | } bits; 54 | #endif 55 | } MQTTConnectFlags; /**< connect flags byte */ 56 | 57 | 58 | 59 | /** 60 | * Defines the MQTT "Last Will and Testament" (LWT) settings for 61 | * the connect packet. 62 | */ 63 | typedef struct 64 | { 65 | /** The eyecatcher for this structure. must be MQTW. */ 66 | char struct_id[4]; 67 | /** The version number of this structure. Must be 0 */ 68 | int struct_version; 69 | /** The LWT topic to which the LWT message will be published. */ 70 | MQTTString topicName; 71 | /** The LWT payload. */ 72 | MQTTString message; 73 | /** 74 | * The retained flag for the LWT message (see MQTTAsync_message.retained). 75 | */ 76 | unsigned char retained; 77 | /** 78 | * The quality of service setting for the LWT message (see 79 | * MQTTAsync_message.qos and @ref qos). 80 | */ 81 | char qos; 82 | } MQTTPacket_willOptions; 83 | 84 | 85 | #define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 } 86 | 87 | 88 | typedef struct 89 | { 90 | /** The eyecatcher for this structure. must be MQTC. */ 91 | char struct_id[4]; 92 | /** The version number of this structure. Must be 0 */ 93 | int struct_version; 94 | /** Version of MQTT to be used. 3 = 3.1 4 = 3.1.1 95 | */ 96 | unsigned char MQTTVersion; 97 | MQTTString clientID; 98 | unsigned short keepAliveInterval; 99 | unsigned char cleansession; 100 | unsigned char willFlag; 101 | MQTTPacket_willOptions will; 102 | MQTTString username; 103 | MQTTString password; 104 | } MQTTPacket_connectData; 105 | 106 | typedef union 107 | { 108 | unsigned char all; /**< all connack flags */ 109 | #if defined(REVERSED) 110 | struct 111 | { 112 | unsigned int sessionpresent : 1; /**< session present flag */ 113 | unsigned int : 7; /**< unused */ 114 | } bits; 115 | #else 116 | struct 117 | { 118 | unsigned int : 7; /**< unused */ 119 | unsigned int sessionpresent : 1; /**< session present flag */ 120 | } bits; 121 | #endif 122 | } MQTTConnackFlags; /**< connack flags byte */ 123 | 124 | #define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \ 125 | MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} } 126 | 127 | DLLExport int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options); 128 | DLLExport int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len); 129 | 130 | DLLExport int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent); 131 | DLLExport int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen); 132 | 133 | DLLExport int MQTTSerialize_disconnect(unsigned char* buf, int buflen); 134 | DLLExport int MQTTSerialize_pingreq(unsigned char* buf, int buflen); 135 | 136 | #endif /* MQTTCONNECT_H_ */ 137 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTConnectClient.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTPacket.h" 18 | 19 | #include 20 | 21 | /** 22 | * Determines the length of the MQTT connect packet that would be produced using the supplied connect options. 23 | * @param options the options to be used to build the connect packet 24 | * @return the length of buffer needed to contain the serialized version of the packet 25 | */ 26 | int MQTTSerialize_connectLength(MQTTPacket_connectData* options) 27 | { 28 | int len = 0; 29 | 30 | 31 | if (options->MQTTVersion == 3) 32 | len = 12; /* variable depending on MQTT or MQIsdp */ 33 | else if (options->MQTTVersion == 4) 34 | len = 10; 35 | 36 | len += MQTTstrlen(options->clientID)+2; 37 | if (options->willFlag) 38 | len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2; 39 | if (options->username.cstring || options->username.lenstring.data) 40 | len += MQTTstrlen(options->username)+2; 41 | if (options->password.cstring || options->password.lenstring.data) 42 | len += MQTTstrlen(options->password)+2; 43 | 44 | return len; 45 | } 46 | 47 | 48 | /** 49 | * Serializes the connect options into the buffer. 50 | * @param buf the buffer into which the packet will be serialized 51 | * @param len the length in bytes of the supplied buffer 52 | * @param options the options to be used to build the connect packet 53 | * @return serialized length, or error if 0 54 | */ 55 | int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options) 56 | { 57 | unsigned char *ptr = buf; 58 | MQTTHeader header = {0}; 59 | MQTTConnectFlags flags = {0}; 60 | int len = 0; 61 | int rc = -1; 62 | 63 | if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen) 64 | { 65 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 66 | goto exit; 67 | } 68 | 69 | header.byte = 0; 70 | header.bits.type = CONNECT; 71 | writeChar(&ptr, header.byte); /* write header */ 72 | 73 | ptr += MQTTPacket_encode(ptr, len); /* write remaining length */ 74 | 75 | if (options->MQTTVersion == 4) 76 | { 77 | writeCString(&ptr, "MQTT"); 78 | writeChar(&ptr, (char) 4); 79 | } 80 | else 81 | { 82 | writeCString(&ptr, "MQIsdp"); 83 | writeChar(&ptr, (char) 3); 84 | } 85 | 86 | flags.all = 0; 87 | flags.bits.cleansession = options->cleansession; 88 | flags.bits.will = (options->willFlag) ? 1 : 0; 89 | if (flags.bits.will) 90 | { 91 | flags.bits.willQoS = options->will.qos; 92 | flags.bits.willRetain = options->will.retained; 93 | } 94 | 95 | if (options->username.cstring || options->username.lenstring.data) 96 | flags.bits.username = 1; 97 | if (options->password.cstring || options->password.lenstring.data) 98 | flags.bits.password = 1; 99 | 100 | writeChar(&ptr, flags.all); 101 | writeInt(&ptr, options->keepAliveInterval); 102 | writeMQTTString(&ptr, options->clientID); 103 | if (options->willFlag) 104 | { 105 | writeMQTTString(&ptr, options->will.topicName); 106 | writeMQTTString(&ptr, options->will.message); 107 | } 108 | if (flags.bits.username) 109 | writeMQTTString(&ptr, options->username); 110 | if (flags.bits.password) 111 | writeMQTTString(&ptr, options->password); 112 | 113 | rc = ptr - buf; 114 | 115 | exit: 116 | return rc; 117 | } 118 | 119 | 120 | /** 121 | * Deserializes the supplied (wire) buffer into connack data - return code 122 | * @param sessionPresent the session present flag returned (only for MQTT 3.1.1) 123 | * @param connack_rc returned integer value of the connack return code 124 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 125 | * @param len the length in bytes of the data in the supplied buffer 126 | * @return error code. 1 is success, 0 is failure 127 | */ 128 | int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen) 129 | { 130 | MQTTHeader header = {0}; 131 | unsigned char* curdata = buf; 132 | unsigned char* enddata = NULL; 133 | int rc = 0; 134 | int mylen; 135 | MQTTConnackFlags flags = {0}; 136 | 137 | header.byte = readChar(&curdata); 138 | if (header.bits.type != CONNACK) 139 | goto exit; 140 | 141 | curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 142 | enddata = curdata + mylen; 143 | if (enddata - curdata < 2) 144 | goto exit; 145 | 146 | flags.all = readChar(&curdata); 147 | *sessionPresent = flags.bits.sessionpresent; 148 | *connack_rc = readChar(&curdata); 149 | 150 | rc = 1; 151 | exit: 152 | return rc; 153 | } 154 | 155 | 156 | /** 157 | * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket 158 | * @param buf the buffer into which the packet will be serialized 159 | * @param buflen the length in bytes of the supplied buffer, to avoid overruns 160 | * @param packettype the message type 161 | * @return serialized length, or error if 0 162 | */ 163 | int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype) 164 | { 165 | MQTTHeader header = {0}; 166 | int rc = -1; 167 | unsigned char *ptr = buf; 168 | 169 | if (buflen < 2) 170 | { 171 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 172 | goto exit; 173 | } 174 | header.byte = 0; 175 | header.bits.type = packettype; 176 | writeChar(&ptr, header.byte); /* write header */ 177 | 178 | ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */ 179 | rc = ptr - buf; 180 | exit: 181 | return rc; 182 | } 183 | 184 | 185 | /** 186 | * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket 187 | * @param buf the buffer into which the packet will be serialized 188 | * @param buflen the length in bytes of the supplied buffer, to avoid overruns 189 | * @return serialized length, or error if 0 190 | */ 191 | int MQTTSerialize_disconnect(unsigned char* buf, int buflen) 192 | { 193 | return MQTTSerialize_zero(buf, buflen, DISCONNECT); 194 | } 195 | 196 | 197 | /** 198 | * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket 199 | * @param buf the buffer into which the packet will be serialized 200 | * @param buflen the length in bytes of the supplied buffer, to avoid overruns 201 | * @return serialized length, or error if 0 202 | */ 203 | int MQTTSerialize_pingreq(unsigned char* buf, int buflen) 204 | { 205 | return MQTTSerialize_zero(buf, buflen, PINGREQ); 206 | } 207 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTDeserializePublish.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTPacket.h" 18 | #include 19 | 20 | #define min(a, b) ((a < b) ? 1 : 0) 21 | 22 | /** 23 | * Deserializes the supplied (wire) buffer into publish data 24 | * @param dup returned integer - the MQTT dup flag 25 | * @param qos returned integer - the MQTT QoS value 26 | * @param retained returned integer - the MQTT retained flag 27 | * @param packetid returned integer - the MQTT packet identifier 28 | * @param topicName returned MQTTString - the MQTT topic in the publish 29 | * @param payload returned byte buffer - the MQTT publish payload 30 | * @param payloadlen returned integer - the length of the MQTT payload 31 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 32 | * @param buflen the length in bytes of the data in the supplied buffer 33 | * @return error code. 1 is success 34 | */ 35 | int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName, 36 | unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen) 37 | { 38 | MQTTHeader header = {0}; 39 | unsigned char* curdata = buf; 40 | unsigned char* enddata = NULL; 41 | int rc = 0; 42 | int mylen = 0; 43 | 44 | header.byte = readChar(&curdata); 45 | if (header.bits.type != PUBLISH) 46 | goto exit; 47 | *dup = header.bits.dup; 48 | *qos = header.bits.qos; 49 | *retained = header.bits.retain; 50 | 51 | curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 52 | enddata = curdata + mylen; 53 | 54 | if (!readMQTTLenString(topicName, &curdata, enddata) || 55 | enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */ 56 | goto exit; 57 | 58 | if (*qos > 0) 59 | *packetid = readInt(&curdata); 60 | 61 | *payloadlen = enddata - curdata; 62 | *payload = curdata; 63 | rc = 1; 64 | exit: 65 | return rc; 66 | } 67 | 68 | 69 | 70 | /** 71 | * Deserializes the supplied (wire) buffer into an ack 72 | * @param packettype returned integer - the MQTT packet type 73 | * @param dup returned integer - the MQTT dup flag 74 | * @param packetid returned integer - the MQTT packet identifier 75 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 76 | * @param buflen the length in bytes of the data in the supplied buffer 77 | * @return error code. 1 is success, 0 is failure 78 | */ 79 | int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen) 80 | { 81 | MQTTHeader header = {0}; 82 | unsigned char* curdata = buf; 83 | unsigned char* enddata = NULL; 84 | int rc = 0; 85 | int mylen; 86 | 87 | header.byte = readChar(&curdata); 88 | *dup = header.bits.dup; 89 | *packettype = header.bits.type; 90 | 91 | curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 92 | enddata = curdata + mylen; 93 | 94 | if (enddata - curdata < 2) 95 | goto exit; 96 | *packetid = readInt(&curdata); 97 | 98 | rc = 1; 99 | exit: 100 | return rc; 101 | } 102 | 103 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTPacket.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Xiang Rong - 442039 Add makefile to Embedded C client 16 | *******************************************************************************/ 17 | 18 | #ifndef MQTTPACKET_H_ 19 | #define MQTTPACKET_H_ 20 | 21 | #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ 22 | extern "C" { 23 | #endif 24 | 25 | #if defined(WIN32_DLL) || defined(WIN64_DLL) 26 | #define DLLImport __declspec(dllimport) 27 | #define DLLExport __declspec(dllexport) 28 | #elif defined(LINUX_SO) 29 | #define DLLImport extern 30 | #define DLLExport __attribute__ ((visibility ("default"))) 31 | #else 32 | #define DLLImport 33 | #define DLLExport 34 | #endif 35 | 36 | enum errors 37 | { 38 | MQTTPACKET_BUFFER_TOO_SHORT = -2, 39 | MQTTPACKET_READ_ERROR = -1, 40 | MQTTPACKET_READ_COMPLETE 41 | }; 42 | 43 | enum msgTypes 44 | { 45 | CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, 46 | PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, 47 | PINGREQ, PINGRESP, DISCONNECT 48 | }; 49 | 50 | /** 51 | * Bitfields for the MQTT header byte. 52 | */ 53 | typedef union 54 | { 55 | unsigned char byte; /**< the whole byte */ 56 | #if defined(REVERSED) 57 | struct 58 | { 59 | unsigned int type : 4; /**< message type nibble */ 60 | unsigned int dup : 1; /**< DUP flag bit */ 61 | unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ 62 | unsigned int retain : 1; /**< retained flag bit */ 63 | } bits; 64 | #else 65 | struct 66 | { 67 | unsigned int retain : 1; /**< retained flag bit */ 68 | unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ 69 | unsigned int dup : 1; /**< DUP flag bit */ 70 | unsigned int type : 4; /**< message type nibble */ 71 | } bits; 72 | #endif 73 | } MQTTHeader; 74 | 75 | typedef struct 76 | { 77 | int len; 78 | char* data; 79 | } MQTTLenString; 80 | 81 | typedef struct 82 | { 83 | char* cstring; 84 | MQTTLenString lenstring; 85 | } MQTTString; 86 | 87 | #define MQTTString_initializer {NULL, {0, NULL}} 88 | 89 | int MQTTstrlen(MQTTString mqttstring); 90 | 91 | #include "MQTTConnect.h" 92 | #include "MQTTPublish.h" 93 | #include "MQTTSubscribe.h" 94 | #include "MQTTUnsubscribe.h" 95 | 96 | int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid); 97 | int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen); 98 | 99 | int MQTTPacket_len(int rem_len); 100 | int MQTTPacket_equals(MQTTString* a, char* b); 101 | 102 | int MQTTPacket_encode(unsigned char* buf, int length); 103 | int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value); 104 | int MQTTPacket_decodeBuf(unsigned char* buf, int* value); 105 | 106 | int readInt(unsigned char** pptr); 107 | char readChar(unsigned char** pptr); 108 | void writeChar(unsigned char** pptr, char c); 109 | void writeInt(unsigned char** pptr, int anInt); 110 | int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata); 111 | void writeCString(unsigned char** pptr, const char* string); 112 | void writeMQTTString(unsigned char** pptr, MQTTString mqttstring); 113 | 114 | DLLExport int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int)); 115 | 116 | typedef struct { 117 | int (*getfn)(void *, unsigned char*, int); /* must return -1 for error, 0 for call again, or the number of bytes read */ 118 | void *sck; /* pointer to whatever the system may use to identify the transport */ 119 | int multiplier; 120 | int rem_len; 121 | int len; 122 | char state; 123 | }MQTTTransport; 124 | 125 | int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp); 126 | 127 | #ifdef __cplusplus /* If this is a C++ compiler, use C linkage */ 128 | } 129 | #endif 130 | 131 | 132 | #endif /* MQTTPACKET_H_ */ 133 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTPublish.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Xiang Rong - 442039 Add makefile to Embedded C client 16 | *******************************************************************************/ 17 | 18 | #ifndef MQTTPUBLISH_H_ 19 | #define MQTTPUBLISH_H_ 20 | 21 | #if !defined(DLLImport) 22 | #define DLLImport 23 | #endif 24 | #if !defined(DLLExport) 25 | #define DLLExport 26 | #endif 27 | 28 | DLLExport int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid, 29 | MQTTString topicName, unsigned char* payload, int payloadlen); 30 | 31 | DLLExport int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName, 32 | unsigned char** payload, int* payloadlen, unsigned char* buf, int len); 33 | 34 | DLLExport int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid); 35 | DLLExport int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid); 36 | DLLExport int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid); 37 | 38 | #endif /* MQTTPUBLISH_H_ */ 39 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTSerializePublish.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144 16 | *******************************************************************************/ 17 | 18 | #include "MQTTPacket.h" 19 | 20 | #include 21 | 22 | 23 | /** 24 | * Determines the length of the MQTT publish packet that would be produced using the supplied parameters 25 | * @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0) 26 | * @param topicName the topic name to be used in the publish 27 | * @param payloadlen the length of the payload to be sent 28 | * @return the length of buffer needed to contain the serialized version of the packet 29 | */ 30 | int MQTTSerialize_publishLength(int qos, MQTTString topicName, int payloadlen) 31 | { 32 | int len = 0; 33 | 34 | len += 2 + MQTTstrlen(topicName) + payloadlen; 35 | if (qos > 0) 36 | len += 2; /* packetid */ 37 | return len; 38 | } 39 | 40 | 41 | /** 42 | * Serializes the supplied publish data into the supplied buffer, ready for sending 43 | * @param buf the buffer into which the packet will be serialized 44 | * @param buflen the length in bytes of the supplied buffer 45 | * @param dup integer - the MQTT dup flag 46 | * @param qos integer - the MQTT QoS value 47 | * @param retained integer - the MQTT retained flag 48 | * @param packetid integer - the MQTT packet identifier 49 | * @param topicName MQTTString - the MQTT topic in the publish 50 | * @param payload byte buffer - the MQTT publish payload 51 | * @param payloadlen integer - the length of the MQTT payload 52 | * @return the length of the serialized data. <= 0 indicates error 53 | */ 54 | int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid, 55 | MQTTString topicName, unsigned char* payload, int payloadlen) 56 | { 57 | unsigned char *ptr = buf; 58 | MQTTHeader header = {0}; 59 | int rem_len = 0; 60 | int rc = 0; 61 | 62 | if (MQTTPacket_len(rem_len = MQTTSerialize_publishLength(qos, topicName, payloadlen)) > buflen) 63 | { 64 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 65 | goto exit; 66 | } 67 | 68 | header.bits.type = PUBLISH; 69 | header.bits.dup = dup; 70 | header.bits.qos = qos; 71 | header.bits.retain = retained; 72 | writeChar(&ptr, header.byte); /* write header */ 73 | 74 | ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */; 75 | 76 | writeMQTTString(&ptr, topicName); 77 | 78 | if (qos > 0) 79 | writeInt(&ptr, packetid); 80 | 81 | memcpy(ptr, payload, payloadlen); 82 | ptr += payloadlen; 83 | 84 | rc = ptr - buf; 85 | 86 | exit: 87 | return rc; 88 | } 89 | 90 | 91 | 92 | /** 93 | * Serializes the ack packet into the supplied buffer. 94 | * @param buf the buffer into which the packet will be serialized 95 | * @param buflen the length in bytes of the supplied buffer 96 | * @param type the MQTT packet type 97 | * @param dup the MQTT dup flag 98 | * @param packetid the MQTT packet identifier 99 | * @return serialized length, or error if 0 100 | */ 101 | int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char packettype, unsigned char dup, unsigned short packetid) 102 | { 103 | MQTTHeader header = {0}; 104 | int rc = 0; 105 | unsigned char *ptr = buf; 106 | 107 | if (buflen < 4) 108 | { 109 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 110 | goto exit; 111 | } 112 | header.bits.type = packettype; 113 | header.bits.dup = dup; 114 | header.bits.qos = (packettype == PUBREL) ? 1 : 0; 115 | writeChar(&ptr, header.byte); /* write header */ 116 | 117 | ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */ 118 | writeInt(&ptr, packetid); 119 | rc = ptr - buf; 120 | exit: 121 | return rc; 122 | } 123 | 124 | 125 | /** 126 | * Serializes a puback packet into the supplied buffer. 127 | * @param buf the buffer into which the packet will be serialized 128 | * @param buflen the length in bytes of the supplied buffer 129 | * @param packetid integer - the MQTT packet identifier 130 | * @return serialized length, or error if 0 131 | */ 132 | int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid) 133 | { 134 | return MQTTSerialize_ack(buf, buflen, PUBACK, 0, packetid); 135 | } 136 | 137 | 138 | /** 139 | * Serializes a pubrel packet into the supplied buffer. 140 | * @param buf the buffer into which the packet will be serialized 141 | * @param buflen the length in bytes of the supplied buffer 142 | * @param dup integer - the MQTT dup flag 143 | * @param packetid integer - the MQTT packet identifier 144 | * @return serialized length, or error if 0 145 | */ 146 | int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid) 147 | { 148 | return MQTTSerialize_ack(buf, buflen, PUBREL, dup, packetid); 149 | } 150 | 151 | 152 | /** 153 | * Serializes a pubrel packet into the supplied buffer. 154 | * @param buf the buffer into which the packet will be serialized 155 | * @param buflen the length in bytes of the supplied buffer 156 | * @param packetid integer - the MQTT packet identifier 157 | * @return serialized length, or error if 0 158 | */ 159 | int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid) 160 | { 161 | return MQTTSerialize_ack(buf, buflen, PUBCOMP, 0, packetid); 162 | } 163 | 164 | 165 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTSubscribe.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Xiang Rong - 442039 Add makefile to Embedded C client 16 | *******************************************************************************/ 17 | 18 | #ifndef MQTTSUBSCRIBE_H_ 19 | #define MQTTSUBSCRIBE_H_ 20 | 21 | #if !defined(DLLImport) 22 | #define DLLImport 23 | #endif 24 | #if !defined(DLLExport) 25 | #define DLLExport 26 | #endif 27 | 28 | DLLExport int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, 29 | int count, MQTTString topicFilters[], int requestedQoSs[]); 30 | 31 | DLLExport int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, 32 | int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], unsigned char* buf, int len); 33 | 34 | DLLExport int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs); 35 | 36 | DLLExport int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int len); 37 | 38 | 39 | #endif /* MQTTSUBSCRIBE_H_ */ 40 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTSubscribeClient.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTPacket.h" 18 | 19 | #include 20 | 21 | /** 22 | * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters 23 | * @param count the number of topic filter strings in topicFilters 24 | * @param topicFilters the array of topic filter strings to be used in the publish 25 | * @return the length of buffer needed to contain the serialized version of the packet 26 | */ 27 | int MQTTSerialize_subscribeLength(int count, MQTTString topicFilters[]) 28 | { 29 | int i; 30 | int len = 2; /* packetid */ 31 | 32 | for (i = 0; i < count; ++i) 33 | len += 2 + MQTTstrlen(topicFilters[i]) + 1; /* length + topic + req_qos */ 34 | return len; 35 | } 36 | 37 | 38 | /** 39 | * Serializes the supplied subscribe data into the supplied buffer, ready for sending 40 | * @param buf the buffer into which the packet will be serialized 41 | * @param buflen the length in bytes of the supplied bufferr 42 | * @param dup integer - the MQTT dup flag 43 | * @param packetid integer - the MQTT packet identifier 44 | * @param count - number of members in the topicFilters and reqQos arrays 45 | * @param topicFilters - array of topic filter names 46 | * @param requestedQoSs - array of requested QoS 47 | * @return the length of the serialized data. <= 0 indicates error 48 | */ 49 | int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, int count, 50 | MQTTString topicFilters[], int requestedQoSs[]) 51 | { 52 | unsigned char *ptr = buf; 53 | MQTTHeader header = {0}; 54 | int rem_len = 0; 55 | int rc = 0; 56 | int i = 0; 57 | 58 | if (MQTTPacket_len(rem_len = MQTTSerialize_subscribeLength(count, topicFilters)) > buflen) 59 | { 60 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 61 | goto exit; 62 | } 63 | 64 | header.byte = 0; 65 | header.bits.type = SUBSCRIBE; 66 | header.bits.dup = dup; 67 | header.bits.qos = 1; 68 | writeChar(&ptr, header.byte); /* write header */ 69 | 70 | ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */; 71 | 72 | writeInt(&ptr, packetid); 73 | 74 | for (i = 0; i < count; ++i) 75 | { 76 | writeMQTTString(&ptr, topicFilters[i]); 77 | writeChar(&ptr, requestedQoSs[i]); 78 | } 79 | 80 | rc = ptr - buf; 81 | exit: 82 | return rc; 83 | } 84 | 85 | 86 | 87 | /** 88 | * Deserializes the supplied (wire) buffer into suback data 89 | * @param packetid returned integer - the MQTT packet identifier 90 | * @param maxcount - the maximum number of members allowed in the grantedQoSs array 91 | * @param count returned integer - number of members in the grantedQoSs array 92 | * @param grantedQoSs returned array of integers - the granted qualities of service 93 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 94 | * @param buflen the length in bytes of the data in the supplied buffer 95 | * @return error code. 1 is success, 0 is failure 96 | */ 97 | int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int buflen) 98 | { 99 | MQTTHeader header = {0}; 100 | unsigned char* curdata = buf; 101 | unsigned char* enddata = NULL; 102 | int rc = 0; 103 | int mylen; 104 | 105 | header.byte = readChar(&curdata); 106 | if (header.bits.type != SUBACK) 107 | goto exit; 108 | 109 | curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 110 | enddata = curdata + mylen; 111 | if (enddata - curdata < 2) 112 | goto exit; 113 | 114 | *packetid = readInt(&curdata); 115 | 116 | *count = 0; 117 | while (curdata < enddata) 118 | { 119 | if (*count > maxcount) 120 | { 121 | rc = -1; 122 | goto exit; 123 | } 124 | grantedQoSs[(*count)++] = readChar(&curdata); 125 | } 126 | 127 | rc = 1; 128 | exit: 129 | return rc; 130 | } 131 | 132 | 133 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTUnsubscribe.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Xiang Rong - 442039 Add makefile to Embedded C client 16 | *******************************************************************************/ 17 | 18 | #ifndef MQTTUNSUBSCRIBE_H_ 19 | #define MQTTUNSUBSCRIBE_H_ 20 | 21 | #if !defined(DLLImport) 22 | #define DLLImport 23 | #endif 24 | #if !defined(DLLExport) 25 | #define DLLExport 26 | #endif 27 | 28 | DLLExport int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, 29 | int count, MQTTString topicFilters[]); 30 | 31 | DLLExport int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int max_count, int* count, MQTTString topicFilters[], 32 | unsigned char* buf, int len); 33 | 34 | DLLExport int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid); 35 | 36 | DLLExport int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int len); 37 | 38 | #endif /* MQTTUNSUBSCRIBE_H_ */ 39 | -------------------------------------------------------------------------------- /src/mqtt/lib/MQTTUnsubscribeClient.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTPacket.h" 18 | 19 | #include 20 | 21 | /** 22 | * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters 23 | * @param count the number of topic filter strings in topicFilters 24 | * @param topicFilters the array of topic filter strings to be used in the publish 25 | * @return the length of buffer needed to contain the serialized version of the packet 26 | */ 27 | int MQTTSerialize_unsubscribeLength(int count, MQTTString topicFilters[]) 28 | { 29 | int i; 30 | int len = 2; /* packetid */ 31 | 32 | for (i = 0; i < count; ++i) 33 | len += 2 + MQTTstrlen(topicFilters[i]); /* length + topic*/ 34 | return len; 35 | } 36 | 37 | 38 | /** 39 | * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending 40 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 41 | * @param buflen the length in bytes of the data in the supplied buffer 42 | * @param dup integer - the MQTT dup flag 43 | * @param packetid integer - the MQTT packet identifier 44 | * @param count - number of members in the topicFilters array 45 | * @param topicFilters - array of topic filter names 46 | * @return the length of the serialized data. <= 0 indicates error 47 | */ 48 | int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, 49 | int count, MQTTString topicFilters[]) 50 | { 51 | unsigned char *ptr = buf; 52 | MQTTHeader header = {0}; 53 | int rem_len = 0; 54 | int rc = -1; 55 | int i = 0; 56 | 57 | if (MQTTPacket_len(rem_len = MQTTSerialize_unsubscribeLength(count, topicFilters)) > buflen) 58 | { 59 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 60 | goto exit; 61 | } 62 | 63 | header.byte = 0; 64 | header.bits.type = UNSUBSCRIBE; 65 | header.bits.dup = dup; 66 | header.bits.qos = 1; 67 | writeChar(&ptr, header.byte); /* write header */ 68 | 69 | ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */; 70 | 71 | writeInt(&ptr, packetid); 72 | 73 | for (i = 0; i < count; ++i) 74 | writeMQTTString(&ptr, topicFilters[i]); 75 | 76 | rc = ptr - buf; 77 | exit: 78 | return rc; 79 | } 80 | 81 | 82 | /** 83 | * Deserializes the supplied (wire) buffer into unsuback data 84 | * @param packetid returned integer - the MQTT packet identifier 85 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 86 | * @param buflen the length in bytes of the data in the supplied buffer 87 | * @return error code. 1 is success, 0 is failure 88 | */ 89 | int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen) 90 | { 91 | unsigned char type = 0; 92 | unsigned char dup = 0; 93 | int rc = 0; 94 | 95 | rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen); 96 | if (type == UNSUBACK) 97 | rc = 1; 98 | return rc; 99 | } 100 | 101 | 102 | --------------------------------------------------------------------------------