├── LICENSE
├── README.md
├── examples
├── 01_Particle
│ └── 01_Particle.ino
└── 02_Particle_Electron
│ └── 02_Particle_Electron.ino
├── library.properties
├── src
├── Adapters
│ ├── BlynkParticle.h
│ ├── BlynkParticleBearSSL.h
│ └── BlynkSerial.h
├── Blynk
│ ├── BlynkApi.h
│ ├── BlynkConfig.h
│ ├── BlynkConsole.h
│ ├── BlynkDateTime.h
│ ├── BlynkDebug.h
│ ├── BlynkDetectDevice.h
│ ├── BlynkEveryN.h
│ ├── BlynkHandlers.h
│ ├── BlynkHelpers.h
│ ├── BlynkParam.h
│ ├── BlynkProtocol.h
│ ├── BlynkProtocolDefs.h
│ ├── BlynkTemplates.h
│ ├── BlynkTimer.h
│ ├── BlynkUtility.h
│ └── BlynkWidgetBase.h
├── BlynkApiParticle.h
├── BlynkMultiClient.h
├── BlynkSimpleParticle.h
├── BlynkSimpleParticleSSL.h
├── BlynkSimpleSerialBLE.h
├── BlynkSimpleStream.h
├── BlynkWidgets.h
├── WidgetLCD.h
├── WidgetLED.h
├── WidgetMap.h
├── WidgetTerminal.h
├── WidgetTimeInput.h
├── blynk.cpp
├── blynk.h
└── utility
│ ├── BlynkDateTime.h
│ ├── BlynkDebug.cpp
│ ├── BlynkFifo.h
│ ├── BlynkHandlers.cpp
│ ├── BlynkHelpers.cpp
│ ├── BlynkStreamMulti.h
│ ├── BlynkStreamNull.h
│ ├── BlynkTimeUtils.cpp
│ ├── BlynkTimer.cpp
│ └── BlynkUtility.h
└── verification.txt
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015 Volodymyr Shymanskyy
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://vshymanskyy.github.io/StandWithUkraine)
2 |
3 | # Blynk C++ Library [](https://twitter.com/intent/tweet?text=Build%20your%20IoT%20App%20in%20minutes,%20right%20on%20your%20smartphone!&url=https://github.com/blynkkk/blynk-library&via=blynk_app&hashtags=IoT,iOS,Android,Arduino,ESP8266,ESP32,RaspberryPi)
4 |
5 | [](https://github.com/blynkkk/blynk-library/releases/latest)
6 | [](https://github.com/blynkkk/blynk-library/releases/latest)
7 | [](https://github.com/blynkkk/blynk-library/stargazers)
8 | [](https://github.com/blynkkk/blynk-library/issues)
9 | [](https://travis-ci.org/blynkkk/blynk-library)
10 | [](https://github.com/blynkkk/blynk-library/blob/master/LICENSE)
11 |
12 | If you like **Blynk** - give it a star, or fork it and contribute!
13 | [](https://github.com/blynkkk/blynk-library/stargazers)
14 | [](https://github.com/blynkkk/blynk-library/network)
15 | __________
16 |
17 | ### Blynk is a unique IoT platform for connecting any hardware to the cloud, designing apps to control them, and managing your deployed products at scale.
18 |
19 | - With Blynk Library you can connect **over 400 hardware models** (including ESP8266, ESP32, NodeMCU, all Arduinos, Raspberry Pi, Particle, Texas Instruments, etc.) to the Blynk Cloud.
20 |
21 | - With Blynk apps for **iOS** and **Android** apps you can easily drag-n-drop graphic interfaces for any DIY or commercial project. It's a pure WYSIWG experience: no coding on iOS or Android required.
22 |
23 | - Hardware can connect to Blynk Cloud over the Internet using hardware connectivity available on your board (like ESP32), or with the use of various shields (Ethernet, WiFi, GSM, LTE, etc). Blynk Cloud is available for every user of Blynk **for free**.
24 |
25 | 
26 |
27 | ## Downloads
28 |
29 | **Blynk [Arduino Library](https://github.com/blynkkk/blynk-library/releases/latest)**
30 |
31 | **Blynk Mobile App:
32 | [
Google Play](https://play.google.com/store/apps/details?id=cloud.blynk) |
33 | [
App Store](https://apps.apple.com/us/app/blynk-iot/id1559317868)**
34 |
35 | ## Quickstart: Particle Gen2 / Gen3
36 |
37 | * Download the Blynk app ([App Store](https://apps.apple.com/us/app/blynk-iot/id1559317868), [Google Play](https://play.google.com/store/apps/details?id=cloud.blynk))
38 | * Get the Auth Token from the app
39 | * Import this library to Particle Build IDE.
40 | * Update Auth Token in the example sketch and upload it to your device
41 |
42 | ## Documentation and other helpful links
43 |
44 | [The list of supported hardware](https://docs.blynk.io/en/blynk.edgent-firmware-api/supported-boards) - supported boards, Ethernet, WiFi, Cellular...
45 | [Full Blynk Documentation](https://docs.blynk.io) - a complete guide on Blynk features
46 | [Community (Forum)](http://community.blynk.cc) - join a 500,000 Blynk community to ask questions and share ideas
47 | [Code Examples Browser](http://examples.blynk.cc) - browse examples to explore Blynk possibilities
48 | [Official Website](https://blynk.io)
49 |
50 | **Social Media:**
51 |
52 | [Facebook](https://www.fb.com/blynkapp) |
53 | [Twitter](https://twitter.com/blynk_app) |
54 | [Youtube](https://www.youtube.com/blynk) |
55 | [Instagram](https://www.instagram.com/blynk.iot/) |
56 | [LinkedIn](https://www.linkedin.com/company/b-l-y-n-k/)
57 |
58 | ## Blynk libraries for other platforms
59 | * [Python, MicroPython](https://github.com/blynkkk/lib-python)
60 |
61 | ## Libraries by community
62 | * [Python, MicroPython](https://github.com/vshymanskyy/blynk-library-python)
63 | * [Particle](https://github.com/vshymanskyy/blynk-library-particle)
64 | * [Lua, OpenWrt, NodeMCU](https://github.com/vshymanskyy/blynk-library-lua)
65 | * [OpenWrt packages](https://github.com/vshymanskyy/blynk-library-openwrt)
66 | * [MBED](https://developer.mbed.org/users/vshymanskyy/code/Blynk/)
67 | * [Node-RED for Blynk IoT](https://flows.nodered.org/node/node-red-contrib-blynk-iot)
68 |
69 | ## Contributing
70 | We accept contributions from our community: stability bugfixes, new hardware support, or any other improvements.
71 | [Here](https://github.com/blynkkk/blynk-library/labels/help%20wanted) is a list of what you could help with.
72 |
73 | ### License
74 | This project is released under The MIT License (MIT)
75 |
--------------------------------------------------------------------------------
/examples/01_Particle/01_Particle.ino:
--------------------------------------------------------------------------------
1 | /*************************************************************
2 | Blynk is a platform with iOS and Android apps to control
3 | Arduino, Raspberry Pi and the likes over the Internet.
4 | You can easily build graphic interfaces for all your
5 | projects by simply dragging and dropping widgets.
6 |
7 | Downloads, docs, tutorials: http://www.blynk.cc
8 | Sketch generator: http://examples.blynk.cc
9 | Blynk community: http://community.blynk.cc
10 | Follow us: http://www.fb.com/blynkapp
11 | http://twitter.com/blynk_app
12 |
13 | Blynk library is licensed under MIT license
14 | This example code is in public domain.
15 |
16 | *************************************************************
17 |
18 | No coding required for direct digital/analog pin operations!
19 |
20 | *************************************************************/
21 |
22 | #define BLYNK_PRINT Serial // Set serial output for debug prints
23 | //#define BLYNK_DEBUG // Uncomment this to see detailed prints
24 |
25 | /* Fill in information from Blynk Device Info here */
26 | //#define BLYNK_TEMPLATE_ID "TMPxxxxxx"
27 | //#define BLYNK_TEMPLATE_NAME "Device"
28 | //#define BLYNK_AUTH_TOKEN "YourAuthToken"
29 |
30 | #include
31 |
32 | // Attach a Button widget (mode: Switch) to the Digital pin 7 - and control the built-in blue led.
33 | // Attach a Graph widget to Analog pin 1
34 | // Attach a Gauge widget to Analog pin 2
35 |
36 | void setup()
37 | {
38 | Serial.begin(9600);
39 | delay(5000); // Allow board to settle
40 |
41 | Blynk.begin(BLYNK_AUTH_TOKEN);
42 | }
43 |
44 | // Attach a Button widget (mode: Push) to the Virtual pin 1 - and send sweet tweets!
45 | BLYNK_WRITE(V1) {
46 | if (param.asInt() == 1) { // On button down...
47 | // Pushing notification to the app!
48 | // Note:
49 | // We allow 1 notification per minute for now.
50 | Blynk.logEvent("", "You pressed the button and I know it ;)");
51 | }
52 | }
53 |
54 | // Attach a ZeRGBa widget (mode: Merge) to the Virtual pin 2 - and control the built-in RGB led!
55 | BLYNK_WRITE(V2) {
56 | int r = param[0].asInt();
57 | int g = param[1].asInt();
58 | int b = param[2].asInt();
59 | if (r > 0 || g > 0 || b > 0) {
60 | RGB.control(true);
61 | RGB.color(r, g, b);
62 | } else {
63 | RGB.control(false);
64 | }
65 | }
66 |
67 | void loop()
68 | {
69 | Blynk.run();
70 | }
71 |
--------------------------------------------------------------------------------
/examples/02_Particle_Electron/02_Particle_Electron.ino:
--------------------------------------------------------------------------------
1 | /*************************************************************
2 | Blynk is a platform with iOS and Android apps to control
3 | Arduino, Raspberry Pi and the likes over the Internet.
4 | You can easily build graphic interfaces for all your
5 | projects by simply dragging and dropping widgets.
6 |
7 | Downloads, docs, tutorials: http://www.blynk.cc
8 | Sketch generator: http://examples.blynk.cc
9 | Blynk community: http://community.blynk.cc
10 | Follow us: http://www.fb.com/blynkapp
11 | http://twitter.com/blynk_app
12 |
13 | Blynk library is licensed under MIT license
14 | This example code is in public domain.
15 |
16 | *************************************************************
17 |
18 | No coding required for direct digital/analog pin operations!
19 |
20 | *************************************************************/
21 |
22 | #define BLYNK_PRINT Serial // Set serial output for debug prints
23 | //#define BLYNK_DEBUG // Uncomment this to see detailed prints
24 |
25 | /* Fill in information from Blynk Device Info here */
26 | //#define BLYNK_TEMPLATE_ID "TMPxxxxxx"
27 | //#define BLYNK_TEMPLATE_NAME "Device"
28 | //#define BLYNK_AUTH_TOKEN "YourAuthToken"
29 |
30 | // Uncomment this, if you want to set network credentials
31 | //#include "cellular_hal.h"
32 | //STARTUP(cellular_credentials_set("broadband", "", "", NULL));
33 |
34 | // Run "ping blynk-cloud.com", and set Blynk IP to the shown address
35 | #define BLYNK_IP IPAddress(45,55,130,102)
36 |
37 | // Set Blynk hertbeat interval.
38 | // Each heartbeat uses ~90 bytes of data.
39 | #define BLYNK_HEARTBEAT 60
40 |
41 | // Set Particle keep-alive ping interval.
42 | // Each ping uses 121 bytes of data.
43 | #define PARTICLE_KEEPALIVE 20
44 |
45 | #include
46 |
47 | void setup() {
48 | Serial.begin(9600);
49 | Particle.keepAlive(PARTICLE_KEEPALIVE);
50 | Blynk.begin(BLYNK_AUTH_TOKEN, BLYNK_IP);
51 | }
52 |
53 | void loop() {
54 | Blynk.run();
55 | }
56 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=blynk
2 | version=1.3.2
3 | author=Volodymyr Shymanskyy
4 | license=MIT
5 | maintainer=Volodymyr Shymanskyy
6 | sentence=Build a smartphone app for your project in minutes!
7 | category=Communication
8 | url=https://blynk.io
9 | repository=https://github.com/vshymanskyy/blynk-library-particle.git
10 | architectures=*
11 | includes=Blynk.h
12 |
--------------------------------------------------------------------------------
/src/Adapters/BlynkParticle.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkParticle.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Mar 2015
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkParticle_h
12 | #define BlynkParticle_h
13 |
14 | #include "BlynkApiParticle.h"
15 | #include "Blynk/BlynkProtocol.h"
16 |
17 | class BlynkTransportParticle
18 | {
19 | public:
20 | BlynkTransportParticle()
21 | : domain(NULL), port(0), actual_port(0)
22 | {}
23 |
24 | void begin(IPAddress a, uint16_t p) {
25 | domain = NULL;
26 | port = p;
27 | addr = a;
28 | }
29 |
30 | void begin(const char* d, uint16_t p) {
31 | domain = d;
32 | port = p;
33 | }
34 |
35 | bool _connectToPort(uint16_t p) {
36 | bool isConn = false;
37 | if (domain) {
38 | BLYNK_LOG4(BLYNK_F("Connecting to "), domain, ':', p);
39 | isConn = (1 == client.connect(domain, p));
40 | } else {
41 | BLYNK_LOG_IP("Connecting to ", addr);
42 | isConn = (1 == client.connect(addr, p));
43 | }
44 | actual_port = isConn ? p : 0;
45 | return isConn;
46 | }
47 |
48 | bool connect() {
49 | bool isConn = _connectToPort(port);
50 | if (!isConn) {
51 | // If port is 80 or 8080, try an alternative port
52 | if (port == 80) {
53 | isConn = _connectToPort(8080);
54 | } else if (port == 8080) {
55 | isConn = _connectToPort(80);
56 | }
57 | }
58 | return isConn;
59 | }
60 |
61 | uint16_t getActualPort() const {
62 | return actual_port;
63 | }
64 |
65 | void disconnect() { client.stop(); }
66 |
67 | size_t read(void* buf, size_t len) {
68 | return client.readBytes((char*)buf, len);
69 | }
70 |
71 | size_t write(const void* buf, size_t len) {
72 | return client.write((const uint8_t*)buf, len);
73 | }
74 |
75 | void flush() { client.flush(); }
76 | bool connected() { return client.connected(); }
77 | int available() { return client.available(); }
78 |
79 | private:
80 | TCPClient client;
81 | IPAddress addr;
82 | const char* domain;
83 | uint16_t port;
84 | uint16_t actual_port;
85 | };
86 |
87 | class BlynkParticle
88 | : public BlynkProtocol
89 | {
90 | typedef BlynkProtocol Base;
91 | public:
92 | BlynkParticle(BlynkTransportParticle& transp)
93 | : Base(transp)
94 | {}
95 |
96 | void config(const char* auth,
97 | const char* domain = BLYNK_DEFAULT_DOMAIN,
98 | uint16_t port = BLYNK_DEFAULT_PORT)
99 | {
100 | Base::begin(auth);
101 | this->conn.begin(domain, port);
102 | }
103 |
104 | void config(const char* auth,
105 | IPAddress addr,
106 | uint16_t port = BLYNK_DEFAULT_PORT)
107 | {
108 | Base::begin(auth);
109 | this->conn.begin(addr, port);
110 | }
111 |
112 | void begin( const char* auth,
113 | const char* domain = BLYNK_DEFAULT_DOMAIN,
114 | uint16_t port = BLYNK_DEFAULT_PORT)
115 | {
116 | BlynkDelay(3000); // Give the board time to settle
117 | config(auth, domain, port);
118 | while(this->connect() != true) {}
119 | }
120 |
121 | void begin( const char* auth,
122 | IPAddress addr,
123 | uint16_t port = BLYNK_DEFAULT_PORT)
124 | {
125 | BlynkDelay(3000); // Give the board time to settle
126 | config(auth, addr, port);
127 | while(this->connect() != true) {}
128 | }
129 | private:
130 |
131 | };
132 |
133 | #endif
134 |
--------------------------------------------------------------------------------
/src/Adapters/BlynkParticleBearSSL.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkParticleBearSSL.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2022 Volodymyr Shymanskyy
6 | * @date Mar 2022
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkParticleBearSSL_h
12 | #define BlynkParticleBearSSL_h
13 |
14 | #include
15 | #include
16 |
17 | #include
18 |
19 | class BlynkTransportParticle
20 | {
21 | public:
22 | BlynkTransportParticle()
23 | : client(tcpclient), domain(NULL), port(0)
24 | { }
25 |
26 | static
27 | unsigned long getTime() {
28 | return 1654280000; // TODO
29 | }
30 |
31 | void begin(IPAddress a, uint16_t p) {
32 | domain = NULL;
33 | port = p;
34 | addr = a;
35 | }
36 |
37 | void begin(const char* d, uint16_t p) {
38 | domain = d;
39 | port = p;
40 | }
41 |
42 | bool connect() {
43 | ArduinoBearSSL.onGetTime(getTime);
44 | if (domain) {
45 | BLYNK_LOG4(BLYNK_F("Connecting to "), domain, ':', port);
46 | if (client.connect(domain, port)) {
47 | BLYNK_LOG("Certificate OK");
48 | return true;
49 | } else {
50 | BLYNK_LOG("Connection failed");
51 | }
52 | } else {
53 | BLYNK_LOG_IP("Connecting to ", addr);
54 | //return (1 == client.connect(addr, port));
55 | }
56 | return 0;
57 | }
58 |
59 | void disconnect() { client.stop(); }
60 |
61 | size_t read(void* buf, size_t len) {
62 | return client.readBytes((char*)buf, len);
63 | }
64 |
65 | size_t write(const void* buf, size_t len) {
66 | return client.write((const uint8_t*)buf, len);
67 | }
68 |
69 | void flush() { client.flush(); }
70 | bool connected() { return client.connected(); }
71 | int available() { return client.available(); }
72 |
73 | private:
74 | TCPClient tcpclient;
75 | BearSSLClient client;
76 | IPAddress addr;
77 | const char* domain;
78 | uint16_t port;
79 | };
80 |
81 | class BlynkParticle
82 | : public BlynkProtocol
83 | {
84 | typedef BlynkProtocol Base;
85 | public:
86 | BlynkParticle(BlynkTransportParticle& transp)
87 | : Base(transp)
88 | {}
89 |
90 | void config(const char* auth,
91 | const char* domain = BLYNK_DEFAULT_DOMAIN,
92 | uint16_t port = BLYNK_DEFAULT_PORT)
93 | {
94 | Base::begin(auth);
95 | this->conn.begin(domain, port);
96 | }
97 |
98 | void config(const char* auth,
99 | IPAddress addr,
100 | uint16_t port = BLYNK_DEFAULT_PORT)
101 | {
102 | Base::begin(auth);
103 | this->conn.begin(addr, port);
104 | }
105 |
106 | void begin( const char* auth,
107 | const char* domain = BLYNK_DEFAULT_DOMAIN,
108 | uint16_t port = BLYNK_DEFAULT_PORT)
109 | {
110 | BlynkDelay(3000); // Give the board time to settle
111 | config(auth, domain, port);
112 | while(this->connect() != true) {}
113 | }
114 |
115 | void begin( const char* auth,
116 | IPAddress addr,
117 | uint16_t port = BLYNK_DEFAULT_PORT)
118 | {
119 | BlynkDelay(3000); // Give the board time to settle
120 | config(auth, addr, port);
121 | while(this->connect() != true) {}
122 | }
123 | private:
124 |
125 | };
126 |
127 | #endif
128 |
--------------------------------------------------------------------------------
/src/Adapters/BlynkSerial.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkSerial.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkStream_h
12 | #define BlynkStream_h
13 |
14 | #ifndef BLYNK_INFO_CONNECTION
15 | #define BLYNK_INFO_CONNECTION "Serial"
16 | #endif
17 |
18 | #ifdef PARTICLE
19 | #include
20 | #else
21 | #include
22 | #endif
23 | #include
24 |
25 | class BlynkTransportStream
26 | {
27 | public:
28 | BlynkTransportStream()
29 | : stream(NULL), conn(0)
30 | {}
31 |
32 | // IP redirect not available
33 | void begin(char BLYNK_UNUSED *h, uint16_t BLYNK_UNUSED p) {}
34 |
35 | void begin(Stream& s) {
36 | stream = &s;
37 | }
38 |
39 | bool connect() {
40 | BLYNK_LOG1(BLYNK_F("Connecting..."));
41 | stream->flush();
42 | return conn = true;
43 | }
44 | void disconnect() { conn = false; }
45 |
46 | size_t read(void* buf, size_t len) {
47 | char* beg = (char*)buf;
48 | char* end = beg + len;
49 | millis_time_t startMillis = BlynkMillis();
50 | while ((beg < end) && (BlynkMillis() - startMillis < BLYNK_TIMEOUT_MS)) {
51 | int c = stream->read();
52 | if (c < 0)
53 | continue;
54 | *beg++ = (char)c;
55 | }
56 | return beg-(char*)buf;
57 | }
58 | size_t write(const void* buf, size_t len) {
59 | stream->write((const uint8_t*)buf, len);
60 | return len;
61 | }
62 |
63 | bool connected() { return conn; }
64 | int available() { return stream->available(); }
65 |
66 | protected:
67 | Stream* stream;
68 | bool conn;
69 | };
70 |
71 | class BlynkStream
72 | : public BlynkProtocol
73 | {
74 | typedef BlynkProtocol Base;
75 | public:
76 | BlynkStream(BlynkTransportStream& transp)
77 | : Base(transp)
78 | {}
79 |
80 | void config(Stream& stream,
81 | const char* auth)
82 | {
83 | Base::begin(auth);
84 | this->conn.begin(stream);
85 | }
86 |
87 | void begin(Stream& stream, const char* auth) {
88 | config(stream, auth);
89 | while(this->connect() != true) {}
90 | }
91 | };
92 |
93 | #endif
94 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkApi.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkApi.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief High-level functions
8 | *
9 | */
10 |
11 | #ifndef BlynkApi_h
12 | #define BlynkApi_h
13 |
14 | // back-compat
15 |
16 | #ifdef BOARD_FIRMWARE_TYPE
17 | #define BLYNK_FIRMWARE_TYPE BOARD_FIRMWARE_TYPE
18 | #endif
19 |
20 | #ifdef BOARD_FIRMWARE_VERSION
21 | #define BLYNK_FIRMWARE_VERSION BOARD_FIRMWARE_VERSION
22 | #endif
23 |
24 | #ifdef BOARD_TEMPLATE_ID
25 | #define BLYNK_TEMPLATE_ID BOARD_TEMPLATE_ID
26 | #endif
27 |
28 | // end of back-compat
29 |
30 | #if !defined(BLYNK_FIRMWARE_TYPE) && defined(BLYNK_TEMPLATE_ID)
31 | #define BLYNK_FIRMWARE_TYPE BLYNK_TEMPLATE_ID
32 | #endif
33 |
34 | #if !defined(BLYNK_FIRMWARE_VERSION)
35 | #define BLYNK_FIRMWARE_VERSION "0.0.0"
36 | #endif
37 |
38 | #if !defined(BLYNK_TEMPLATE_ID) || !defined(BLYNK_TEMPLATE_NAME)
39 | #error "Please specify your BLYNK_TEMPLATE_ID and BLYNK_TEMPLATE_NAME"
40 | #endif
41 |
42 | #include
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include
48 |
49 | #if defined(BLYNK_EXPERIMENTAL)
50 | #include
51 | #endif
52 |
53 | /**
54 | * Represents high-level functions of Blynk
55 | */
56 | template
57 | class BlynkApi
58 | {
59 | public:
60 | BlynkApi()
61 | : groupState(GROUP_NONE)
62 | , groupTs(0)
63 | {
64 | }
65 |
66 | #ifdef DOXYGEN // These API here are only for the documentation
67 |
68 | /**
69 | * Connects to the server.
70 | * Blocks until connected or timeout happens.
71 | * May take less or more then timeout value.
72 | *
73 | * @param timeout Connection timeout
74 | * @returns True if connected to the server
75 | */
76 | bool connect(unsigned long timeout = BLYNK_TIMEOUT_MS*3);
77 |
78 | /**
79 | * Disconnects from the server.
80 | * It will not try to reconnect, until connect() is called
81 | */
82 | void disconnect();
83 |
84 | /**
85 | * @returns True if connected to the server
86 | */
87 | bool connected();
88 |
89 | /**
90 | * Performs Blynk-related housekeeping
91 | * and processes incoming commands
92 | *
93 | * @param available True if there is incoming data to process
94 | * Only used when user manages connection manually.
95 | */
96 | bool run(bool available = false);
97 |
98 | #endif // DOXYGEN
99 |
100 | /**
101 | * Sends value to a Virtual Pin
102 | *
103 | * @param pin Virtual Pin number
104 | * @param data Value to be sent
105 | */
106 | template
107 | void virtualWrite(int pin, Args... values) {
108 | char mem[BLYNK_MAX_SENDBYTES];
109 | BlynkParam cmd(mem, 0, sizeof(mem));
110 | cmd.add("vw");
111 | cmd.add(pin);
112 | cmd.add_multi(values...);
113 | static_cast(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, cmd.getBuffer(), cmd.getLength()-1);
114 | }
115 |
116 | /**
117 | * Sends buffer to a Virtual Pin
118 | *
119 | * @param pin Virtual Pin number
120 | * @param buff Data buffer
121 | * @param len Length of data
122 | */
123 | void virtualWriteBinary(int pin, const void* buff, size_t len) {
124 | char mem[8];
125 | BlynkParam cmd(mem, 0, sizeof(mem));
126 | cmd.add("vw");
127 | cmd.add(pin);
128 | static_cast(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, cmd.getBuffer(), cmd.getLength(), buff, len);
129 | }
130 |
131 | /**
132 | * Sends BlynkParam to a Virtual Pin
133 | *
134 | * @param pin Virtual Pin number
135 | * @param param
136 | */
137 | void virtualWrite(int pin, const BlynkParam& param) {
138 | virtualWriteBinary(pin, param.getBuffer(), param.getLength()-1);
139 | }
140 |
141 | void virtualWrite(int pin, const BlynkParamAllocated& param) {
142 | virtualWriteBinary(pin, param.getBuffer(), param.getLength()-1);
143 | }
144 |
145 | /**
146 | * Command grouping
147 | */
148 | void beginGroup() {
149 | if (GROUP_STARTED != groupState) {
150 | groupState = GROUP_PENDING;
151 | groupTs = 0;
152 | }
153 | }
154 |
155 | void beginGroup(uint64_t timestamp) {
156 | if (GROUP_STARTED != groupState) {
157 | groupState = GROUP_PENDING;
158 | groupTs = timestamp;
159 | }
160 | }
161 |
162 | void endGroup() {
163 | if (GROUP_STARTED == groupState) {
164 | char mem[4];
165 | BlynkParam cmd(mem, 0, sizeof(mem));
166 | cmd.add("e");
167 | static_cast(this)->sendCmd(BLYNK_CMD_GROUP, 0, cmd.getBuffer(), cmd.getLength()-1);
168 | }
169 | groupState = GROUP_NONE;
170 | }
171 |
172 | /**
173 | * Handler helpers
174 | */
175 | void callWriteHandler(BlynkReq& req, const BlynkParam& param) {
176 | WidgetWriteHandler handler = GetWriteHandler(req.pin);
177 | if (handler && (handler != BlynkWidgetWrite)) {
178 | handler(req, param);
179 | } else {
180 | BlynkWidgetWriteDefault(req, param);
181 | }
182 | }
183 |
184 | void callReadHandler(BlynkReq& req) {
185 | WidgetReadHandler handler = GetReadHandler(req.pin);
186 | if (handler && (handler != BlynkWidgetRead)) {
187 | handler(req);
188 | } else {
189 | BlynkWidgetReadDefault(req);
190 | }
191 | }
192 |
193 | /**
194 | * Requests Server to re-send current values for all widgets.
195 | */
196 | void syncAll() {
197 | static_cast(this)->sendCmd(BLYNK_CMD_HARDWARE_SYNC);
198 | }
199 |
200 | /**
201 | * Sends internal command
202 | */
203 | template
204 | void sendInternal(Args... params) {
205 | char mem[BLYNK_MAX_SENDBYTES];
206 | BlynkParam cmd(mem, 0, sizeof(mem));
207 | cmd.add_multi(params...);
208 | static_cast(this)->sendCmd(BLYNK_CMD_INTERNAL, 0, cmd.getBuffer(), cmd.getLength()-1);
209 | }
210 |
211 | /**
212 | * Requests App or Server to re-send current value of a Virtual Pin.
213 | * This will probably cause user-defined BLYNK_WRITE handler to be called.
214 | *
215 | * @param pin Virtual Pin number
216 | */
217 | template
218 | void syncVirtual(Args... pins) {
219 | char mem[BLYNK_MAX_SENDBYTES];
220 | BlynkParam cmd(mem, 0, sizeof(mem));
221 | cmd.add("vr");
222 | cmd.add_multi(pins...);
223 | static_cast(this)->sendCmd(BLYNK_CMD_HARDWARE_SYNC, 0, cmd.getBuffer(), cmd.getLength()-1);
224 | }
225 |
226 | /**
227 | * Sets property of a Widget
228 | *
229 | * @experimental
230 | *
231 | * @param pin Virtual Pin number
232 | * @param property Property name ("label", "labels", "color", ...)
233 | * @param value Property value
234 | */
235 | template
236 | void setProperty(int pin, const T& property, Args... values) {
237 | char mem[BLYNK_MAX_SENDBYTES];
238 | BlynkParam cmd(mem, 0, sizeof(mem));
239 | cmd.add(pin);
240 | cmd.add(property);
241 | cmd.add_multi(values...);
242 | static_cast(this)->sendCmd(BLYNK_CMD_PROPERTY, 0, cmd.getBuffer(), cmd.getLength()-1);
243 | }
244 |
245 | template
246 | void setProperty(int pin, const T& property, const BlynkParam& param) {
247 | char mem[32];
248 | BlynkParam cmd(mem, 0, sizeof(mem));
249 | cmd.add(pin);
250 | cmd.add(property);
251 | static_cast(this)->sendCmd(BLYNK_CMD_PROPERTY, 0, cmd.getBuffer(), cmd.getLength(), param.getBuffer(), param.getLength()-1);
252 | }
253 |
254 | template
255 | void setProperty(int pin, const T& property, const BlynkParamAllocated& param) {
256 | char mem[32];
257 | BlynkParam cmd(mem, 0, sizeof(mem));
258 | cmd.add(pin);
259 | cmd.add(property);
260 | static_cast(this)->sendCmd(BLYNK_CMD_PROPERTY, 0, cmd.getBuffer(), cmd.getLength(), param.getBuffer(), param.getLength()-1);
261 | }
262 |
263 | template
264 | void logEvent(const NAME& event_name) {
265 | char mem[BLYNK_MAX_SENDBYTES];
266 | BlynkParam cmd(mem, 0, sizeof(mem));
267 | cmd.add(event_name);
268 | static_cast(this)->sendCmd(BLYNK_CMD_EVENT_LOG, 0, cmd.getBuffer(), cmd.getLength()-1);
269 | }
270 |
271 | template
272 | void logEvent(const NAME& event_name, const DESCR& description) {
273 | char mem[BLYNK_MAX_SENDBYTES];
274 | BlynkParam cmd(mem, 0, sizeof(mem));
275 | cmd.add(event_name);
276 | cmd.add(description);
277 | static_cast(this)->sendCmd(BLYNK_CMD_EVENT_LOG, 0, cmd.getBuffer(), cmd.getLength()-1);
278 | }
279 |
280 | template
281 | void resolveEvent(const NAME& event_name) {
282 | char mem[BLYNK_MAX_SENDBYTES];
283 | BlynkParam cmd(mem, 0, sizeof(mem));
284 | cmd.add(event_name);
285 | static_cast(this)->sendCmd(BLYNK_CMD_EVENT_CLEAR, 0, cmd.getBuffer(), cmd.getLength()-1);
286 | }
287 |
288 | template
289 | void resolveAllEvents(const NAME& event_name) {
290 | char mem[BLYNK_MAX_SENDBYTES];
291 | BlynkParam cmd(mem, 0, sizeof(mem));
292 | cmd.add(event_name);
293 | cmd.add("all");
294 | static_cast(this)->sendCmd(BLYNK_CMD_EVENT_CLEAR, 0, cmd.getBuffer(), cmd.getLength()-1);
295 | }
296 |
297 | #if defined(BLYNK_EXPERIMENTAL)
298 | // Attention!
299 | // Every function in this section may be changed, removed or renamed.
300 |
301 | /**
302 | * Refreshes value of a widget by running
303 | * user-defined BLYNK_READ handler of a pin.
304 | *
305 | * @experimental
306 | *
307 | * @param pin Virtual Pin number
308 | */
309 | void refresh(int pin) {
310 | if (WidgetReadHandler handler = GetReadHandler(pin)) {
311 | BlynkReq req = { 0, BLYNK_SUCCESS, (uint8_t)pin };
312 | handler(req);
313 | }
314 | }
315 |
316 | /**
317 | * Delays for N milliseconds, handling server communication in background.
318 | *
319 | * @experimental
320 | * @warning Should be used very carefully, especially on platforms with small RAM.
321 | *
322 | * @param ms Milliseconds to wait
323 | */
324 | void delay(unsigned long ms) {
325 | uint16_t start = (uint16_t)micros();
326 | while (ms > 0) {
327 | static_cast(this)->run();
328 | #if !defined(BLYNK_NO_YIELD)
329 | yield();
330 | #endif
331 | if (((uint16_t)micros() - start) >= 1000) {
332 | ms--;
333 | start += 1000;
334 | }
335 | }
336 | }
337 |
338 | #endif
339 |
340 | protected:
341 | void processCmd(const void* buff, size_t len);
342 | void sendInfo();
343 |
344 | void sendPendingGroup() {
345 | if (GROUP_PENDING == groupState) {
346 | // Set groupState here as sendCmd is recursive
347 | groupState = GROUP_STARTED;
348 | if (groupTs) {
349 | char mem[24];
350 | BlynkParam cmd(mem, 0, sizeof(mem));
351 | cmd.add("t");
352 | cmd.add(groupTs);
353 | static_cast(this)->sendCmd(BLYNK_CMD_GROUP, 0, cmd.getBuffer(), cmd.getLength()-1);
354 | } else {
355 | char mem[4];
356 | BlynkParam cmd(mem, 0, sizeof(mem));
357 | cmd.add("b");
358 | static_cast(this)->sendCmd(BLYNK_CMD_GROUP, 0, cmd.getBuffer(), cmd.getLength()-1);
359 | }
360 | }
361 | }
362 |
363 | protected:
364 | enum GroupState {
365 | GROUP_NONE,
366 | GROUP_PENDING,
367 | GROUP_STARTED,
368 | } groupState;
369 | uint64_t groupTs;
370 |
371 | };
372 |
373 |
374 | #endif
375 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkConfig.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkConfig.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief Configuration of different aspects of library
8 | *
9 | */
10 |
11 | #ifndef BlynkConfig_h
12 | #define BlynkConfig_h
13 |
14 | #include
15 |
16 | /***************************************************
17 | * Change these settings to match your need
18 | ***************************************************/
19 | #define BLYNK_DEFAULT_DOMAIN "blynk.cloud"
20 | #define BLYNK_DEFAULT_PORT 80
21 | #define BLYNK_DEFAULT_PORT_SSL 443
22 |
23 | /***************************************************
24 | * Professional settings
25 | ***************************************************/
26 | // Library version.
27 | #define BLYNK_VERSION "1.3.2"
28 |
29 | #define BLYNK_NEW_LIBRARY
30 |
31 | // Heartbeat period in seconds.
32 | #ifndef BLYNK_HEARTBEAT
33 | #define BLYNK_HEARTBEAT 45
34 | #endif
35 |
36 | // Network timeout in milliseconds.
37 | #ifndef BLYNK_TIMEOUT_MS
38 | #define BLYNK_TIMEOUT_MS 6000UL
39 | #endif
40 |
41 | // Limit the amount of outgoing commands per second.
42 | #ifndef BLYNK_MSG_LIMIT
43 | #define BLYNK_MSG_LIMIT 15
44 | #endif
45 |
46 | // Limit the incoming command length.
47 | #ifndef BLYNK_MAX_READBYTES
48 | #define BLYNK_MAX_READBYTES 256
49 | #endif
50 |
51 | // Limit the outgoing command length.
52 | #ifndef BLYNK_MAX_SENDBYTES
53 | #define BLYNK_MAX_SENDBYTES 128
54 | #endif
55 |
56 | // Uncomment to disable built-in analog and digital operations.
57 | //#define BLYNK_NO_BUILTIN
58 |
59 | // Uncomment to enable debug prints.
60 | //#define BLYNK_DEBUG
61 |
62 | // Uncomment to force-enable 128 virtual pins
63 | //#define BLYNK_USE_128_VPINS
64 |
65 | // Uncomment to disable fancy logo
66 | //#define BLYNK_NO_FANCY_LOGO
67 |
68 | // Uncomment to enable 3D fancy logo
69 | //#define BLYNK_FANCY_LOGO_3D
70 |
71 | // Uncomment to enable experimental functions.
72 | //#define BLYNK_EXPERIMENTAL
73 |
74 | // Uncomment to disable all float/double usage
75 | //#define BLYNK_NO_FLOAT
76 |
77 | // Uncomment to switch to direct-connect mode
78 | //#define BLYNK_USE_DIRECT_CONNECT
79 |
80 |
81 | // Uncomment to append command body to header (uses more RAM)
82 | //#define BLYNK_SEND_ATOMIC
83 |
84 | // Split whole command into chunks (in bytes)
85 | //#define BLYNK_SEND_CHUNK 64
86 |
87 | // Wait after sending each chunk (in milliseconds)
88 | //#define BLYNK_SEND_THROTTLE 10
89 |
90 | #endif
91 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkConsole.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkConsole.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2020 Volodymyr Shymanskyy
6 | * @date Oct 2020
7 | * @brief Console Utility
8 | *
9 | */
10 |
11 | #ifndef BlynkConsole_h
12 | #define BlynkConsole_h
13 |
14 | #include
15 | #include
16 |
17 | #define BLYNK_CONSOLE_MAX_COMMANDS 64
18 | #define BLYNK_CONSOLE_INPUT_BUFFER 256
19 | #define BLYNK_CONSOLE_USE_STREAM
20 |
21 | #ifdef BLYNK_CONSOLE_USE_STREAM
22 | #include
23 | #endif
24 |
25 | #if defined(ARDUINO_AMEBA)
26 | #include // for strncasecmp
27 | #endif
28 |
29 | class BlynkConsole
30 | {
31 | private:
32 |
33 | #ifdef BLYNK_HAS_FUNCTIONAL_H
34 | typedef std::function HandlerSimp;
35 | typedef std::function HandlerArgs;
36 | typedef std::function HandlerParams;
37 | #else
38 | typedef void (*HandlerSimp)();
39 | typedef void (*HandlerArgs)(int argc, const char** argv);
40 | typedef void (*HandlerParams)(const BlynkParam ¶m);
41 | #endif
42 | enum HandlerType {
43 | SIMPLE,
44 | WITH_ARGS,
45 | WITH_PARAMS,
46 | SUB_CONSOLE
47 | };
48 |
49 | class CmdHandler {
50 | public:
51 | const char* cmd;
52 | HandlerType type;
53 | union {
54 | HandlerSimp* f_simp;
55 | HandlerArgs* f_args;
56 | HandlerParams* f_params;
57 | BlynkConsole* f_cons;
58 | };
59 | CmdHandler() = default;
60 | CmdHandler(const char* s, HandlerSimp* f)
61 | : cmd(s), type(SIMPLE), f_simp(f)
62 | {}
63 | CmdHandler(const char* s, HandlerArgs* f)
64 | : cmd(s), type(WITH_ARGS), f_args(f)
65 | {}
66 | CmdHandler(const char* s, HandlerParams* f)
67 | : cmd(s), type(WITH_PARAMS), f_params(f)
68 | {}
69 | CmdHandler(const char* s, BlynkConsole* f)
70 | : cmd(s), type(SUB_CONSOLE), f_cons(f)
71 | {}
72 | };
73 |
74 | public:
75 |
76 | enum ProcessResult {
77 | PROCESSED,
78 | SKIPPED,
79 | EXECUTED,
80 | NOT_FOUND,
81 | };
82 |
83 | BlynkConsole() {
84 | reset_buff();
85 |
86 | #if defined(BLYNK_CONSOLE_USE_STREAM) && defined(BLYNK_HAS_FUNCTIONAL_H)
87 | help = [=]() {
88 | if (!stream) return;
89 | stream->print("Available commands: ");
90 | for (size_t i=0; iprint(handler.cmd);
93 | if (i < commandsQty-1) { stream->print(", "); }
94 | }
95 | stream->println();
96 | };
97 |
98 | addCommand("help", help);
99 | addCommand("?", help);
100 | #endif
101 |
102 | }
103 |
104 | #ifdef BLYNK_CONSOLE_USE_STREAM
105 | void print() {}
106 |
107 | template
108 | void print(T val) {
109 | if (stream) stream->print(val);
110 | }
111 |
112 | template
113 | void print(T1 val1, T2 val2) {
114 | if (stream) stream->print(val1, val2);
115 | }
116 |
117 | void printf(const char *fmt, ... ) {
118 | if (stream) {
119 | char buf[256];
120 | va_list args;
121 | va_start (args, fmt);
122 | vsnprintf(buf, sizeof(buf), (char*)fmt, args);
123 | va_end (args);
124 | stream->print(buf);
125 | }
126 | }
127 | #endif
128 |
129 | void addCommand(const char* cmd, HandlerSimp h) {
130 | if (commandsQty >= BLYNK_CONSOLE_MAX_COMMANDS) return;
131 | commands[commandsQty++] = CmdHandler(cmd, new HandlerSimp(h));
132 | }
133 |
134 | void addCommand(const char* cmd, HandlerArgs h) {
135 | if (commandsQty >= BLYNK_CONSOLE_MAX_COMMANDS) return;
136 | commands[commandsQty++] = CmdHandler(cmd, new HandlerArgs(h));
137 | }
138 |
139 | void addCommand(const char* cmd, HandlerParams h) {
140 | if (commandsQty >= BLYNK_CONSOLE_MAX_COMMANDS) return;
141 | commands[commandsQty++] = CmdHandler(cmd, new HandlerParams(h));
142 | }
143 |
144 | void addCommand(const char* cmd, BlynkConsole* h) {
145 | if (commandsQty >= BLYNK_CONSOLE_MAX_COMMANDS || !h) return;
146 | #ifdef BLYNK_CONSOLE_USE_STREAM
147 | h->begin(stream);
148 | #endif
149 | commands[commandsQty++] = CmdHandler(cmd, h);
150 | }
151 |
152 | void addCommand(const char* cmd, BlynkConsole& h) {
153 | addCommand(cmd, &h);
154 | }
155 |
156 | ProcessResult process(char c) {
157 | if (cmdPtr >= cmdBuff+sizeof(cmdBuff)) {
158 | reset_buff();
159 | }
160 |
161 | *(cmdPtr++) = c;
162 | if (c == '\n' || c == '\r') {
163 | return runCommandInBuff();
164 | }
165 | return PROCESSED;
166 | }
167 |
168 | ProcessResult runCommand(const char* cmd) {
169 | strncpy(cmdBuff, cmd, sizeof(cmdBuff));
170 | cmdBuff[sizeof(cmdBuff)-1] = '\0';
171 | cmdPtr = cmdBuff + strlen(cmdBuff);
172 | return runCommandInBuff();
173 | }
174 |
175 | private:
176 |
177 | ProcessResult runCommandInBuff() {
178 | char* argv[16];
179 | int argc = split_argv(cmdBuff, argv, 16);
180 | if (argc <= 0) {
181 | return SKIPPED;
182 | }
183 | #ifdef BLYNK_CONSOLE_USE_STREAM
184 | if (stream) stream->println();
185 | #endif
186 | ProcessResult ret = runCommand(argc, (const char**)argv);
187 | reset_buff();
188 | return ret;
189 | }
190 |
191 | ProcessResult runCommand(int argc, const char** argv) {
192 | for (size_t i=0; i 0 && len < BLYNK_CONSOLE_INPUT_BUFFER) {
205 | char mem[len];
206 | BlynkParam param(mem, 0, sizeof(mem));
207 | for (int i = 1; i < argc; i++) {
208 | param.add(argv[i]);
209 | }
210 | (*(handler.f_params))(param);
211 | }
212 | break;
213 | }
214 | case SUB_CONSOLE:
215 | if (argc < 2) return NOT_FOUND;
216 | return handler.f_cons->runCommand(argc-1, (const char**)(argv+1));
217 | }
218 | return EXECUTED;
219 | }
220 | }
221 | return NOT_FOUND;
222 | }
223 |
224 | public:
225 |
226 | #ifdef BLYNK_CONSOLE_USE_STREAM
227 |
228 | void begin(Stream& s) {
229 | stream = &s;
230 | }
231 |
232 | void begin(Stream* s) {
233 | stream = s;
234 | }
235 |
236 | Stream& getStream() {
237 | return *stream;
238 | }
239 |
240 | void run() {
241 | while (stream && stream->available()) {
242 | char c = stream->read();
243 | switch (process(c)) {
244 | case SKIPPED: break;
245 | case PROCESSED:
246 | stream->print(c);
247 | break;
248 | case NOT_FOUND:
249 | stream->println("Command not found.");
250 | // Fall-through
251 | case EXECUTED:
252 | stream->print(">");
253 | break;
254 | }
255 | }
256 | }
257 | #endif
258 |
259 | private:
260 | CmdHandler commands[BLYNK_CONSOLE_MAX_COMMANDS];
261 | unsigned commandsQty = 0;
262 |
263 | char* cmdPtr;
264 | char cmdBuff[BLYNK_CONSOLE_INPUT_BUFFER];
265 |
266 | #ifdef BLYNK_CONSOLE_USE_STREAM
267 | Stream* stream = nullptr;
268 | HandlerSimp help;
269 | #endif
270 |
271 | void reset_buff() {
272 | memset(cmdBuff, 0, sizeof(cmdBuff));
273 | cmdPtr = cmdBuff;
274 | }
275 |
276 | static
277 | void unescape(char* buff)
278 | {
279 | char* outp = buff;
280 | while (*buff) {
281 | if (*buff == '\\') {
282 | switch (*(buff+1)) {
283 | case '0': *outp++ = '\0'; break;
284 | case 'b': *outp++ = '\b'; break;
285 | case 'n': *outp++ = '\n'; break;
286 | case 'r': *outp++ = '\r'; break;
287 | case 't': *outp++ = '\t'; break;
288 | case 'x': {
289 | char hex[3] = { *(buff+2), *(buff+3), '\0' };
290 | *outp = strtol(hex, NULL, 16);
291 | buff += 2; outp += 1;
292 | break;
293 | }
294 | // Otherwise just pass the letter
295 | // Also handles '\\'
296 | default: *outp++ = *(buff+1); break;
297 | }
298 | buff += 2;
299 | } else {
300 | *outp++ = *buff++;
301 | }
302 | }
303 | *outp = '\0';
304 | }
305 |
306 | static
307 | int split_argv(char *str, char** argv, int argv_capacity)
308 | {
309 | int result = 0;
310 | char* curr = str;
311 | int len = 0;
312 | memset(argv, 0, sizeof(char*)*argv_capacity);
313 | for (int i = 0; str[i] != '\0' && result < (argv_capacity-1); i++) {
314 | if (strchr(" \n\r\t", str[i])) {
315 | if (len) { // Found space after non-space
316 | str[i] = '\0';
317 | unescape(curr);
318 | argv[result++] = curr;
319 | len = 0;
320 | }
321 | } else {
322 | if (!len) { // Found non-space after space
323 | curr = &str[i];
324 | }
325 | len++;
326 | }
327 | }
328 | // Add final argument, if needed
329 | if (len && result < (argv_capacity-1)) {
330 | unescape(curr);
331 | argv[result++] = curr;
332 | }
333 | return result;
334 | }
335 |
336 | };
337 |
338 | #endif // BlynkConsole
339 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkDateTime.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkDateTime.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2016 Volodymyr Shymanskyy
6 | * @date Aug 2016
7 | * @brief DateTime implementation
8 | *
9 | */
10 |
11 | #ifndef BlynkDateTime_h
12 | #define BlynkDateTime_h
13 |
14 | #include
15 |
16 | typedef int64_t blynk_time_t;
17 |
18 | struct blynk_tm *blynk_gmtime_r(const blynk_time_t *time, struct blynk_tm *tm);
19 | blynk_time_t blynk_mk_gmtime(struct blynk_tm *tm);
20 | int blynk_compute_sun(int8_t month, int8_t day, double latitude, double longitude, bool rise);
21 |
22 | static inline
23 | bool isTimeValid(blynk_time_t t_sec) {
24 | return t_sec > 1609459200; // 01 Jan 2021
25 | }
26 |
27 | struct blynk_tm {
28 | int8_t tm_sec; // seconds after the minute 0-59 (max 61)
29 | int8_t tm_min; // minutes after the hour 0-59
30 | int8_t tm_hour; // minutes after the hour 0-23
31 | int8_t tm_mday; // day of the month 1-31
32 | int8_t tm_wday; // days since Sunday 0-6
33 | int8_t tm_mon; // months since January 0-11
34 | int16_t tm_year; // years since 1900
35 | int16_t tm_yday; // days since January 1 0-365
36 | };
37 |
38 | #define BLYNK_SECS_PER_MIN (60UL)
39 | #define BLYNK_SECS_PER_HOUR (3600UL)
40 | #define BLYNK_SECS_PER_DAY (BLYNK_SECS_PER_HOUR * 24UL)
41 | #define BLYNK_SECS_PER_WEEK (BLYNK_SECS_PER_DAY * 7UL)
42 |
43 | static const char* DOW_STR[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
44 |
45 | class BlynkTime {
46 |
47 | public:
48 | static BlynkTime invalid() { return BlynkTime(); }
49 |
50 | static BlynkTime computeSunRise(int8_t month, int8_t day, double latitude, double longitude) {
51 | int minutes = blynk_compute_sun(month, day, latitude, longitude, true);
52 | if (minutes < 0) return invalid();
53 | return BlynkTime(0, minutes, 0);
54 | }
55 |
56 | static BlynkTime computeSunSet(int8_t month, int8_t day, double latitude, double longitude) {
57 | int minutes = blynk_compute_sun(month, day, latitude, longitude, false);
58 | if (minutes < 0) return invalid();
59 | return BlynkTime(0, minutes, 0);
60 | }
61 |
62 |
63 | BlynkTime() : mTime(-1) {}
64 |
65 | BlynkTime(const BlynkTime& t) : mTime(t.mTime) {}
66 |
67 | BlynkTime(long seconds) : mTime(seconds % BLYNK_SECS_PER_DAY) {}
68 |
69 | BlynkTime(int hour, int minute, int second)
70 | {
71 | mTime = (hour * BLYNK_SECS_PER_HOUR + minute * BLYNK_SECS_PER_MIN + second) % BLYNK_SECS_PER_DAY;
72 | }
73 |
74 | int second() const { return (mTime % BLYNK_SECS_PER_MIN); }
75 | int minute() const { return (mTime / BLYNK_SECS_PER_MIN) % BLYNK_SECS_PER_MIN; }
76 | int hour() const { return (mTime / BLYNK_SECS_PER_HOUR); }
77 |
78 | int hour12() const {
79 | int h = hour();
80 | if (h == 0)
81 | return 12; // 12 midnight
82 | else if (h > 12)
83 | return h - 12;
84 | return h;
85 | }
86 |
87 | bool isAM() const { return !isPM(); }
88 | bool isPM() const { return (hour() >= 12); }
89 |
90 | void adjustSeconds(int sec) {
91 | if (isValid()) {
92 | mTime = (mTime + sec) % BLYNK_SECS_PER_DAY;
93 | }
94 | }
95 |
96 | blynk_time_t getUnixOffset() const { return mTime; }
97 |
98 | bool isValid() const { return mTime < BLYNK_SECS_PER_DAY; }
99 | operator bool() const { return isValid(); }
100 |
101 | bool operator != (const BlynkTime& t) const { return mTime != t.mTime; }
102 | bool operator == (const BlynkTime& t) const { return mTime == t.mTime; }
103 | bool operator >= (const BlynkTime& t) const { return mTime >= t.mTime; }
104 | bool operator <= (const BlynkTime& t) const { return mTime <= t.mTime; }
105 | bool operator > (const BlynkTime& t) const { return mTime > t.mTime; }
106 | bool operator < (const BlynkTime& t) const { return mTime < t.mTime; }
107 |
108 | BlynkTime& operator = (const BlynkTime& t) { mTime = t.mTime; return *this; }
109 |
110 | private:
111 | uint32_t mTime;
112 | };
113 |
114 | class BlynkDateTime {
115 |
116 | public:
117 | static BlynkDateTime invalid() { return BlynkDateTime(); }
118 |
119 | BlynkDateTime() : mTime(0) {}
120 |
121 | BlynkDateTime(const BlynkDateTime& t)
122 | {
123 | mTime = t.mTime;
124 | blynk_gmtime_r(&mTime, &mTm);
125 | }
126 |
127 | BlynkDateTime(blynk_time_t t)
128 | {
129 | mTime = t;
130 | blynk_gmtime_r(&mTime, &mTm);
131 | }
132 |
133 | BlynkDateTime(int hour, int minute, int second, int day, int month, int year)
134 | {
135 | mTm.tm_hour = hour;
136 | mTm.tm_min = minute;
137 | mTm.tm_sec = second;
138 |
139 | mTm.tm_mday = day;
140 | mTm.tm_mon = month - 1;
141 | mTm.tm_year = year - 1900;
142 |
143 | mTime = blynk_mk_gmtime(&mTm);
144 | }
145 |
146 | BlynkDateTime(const BlynkTime& time, int day, int month, int year)
147 | : BlynkDateTime(time.hour(), time.minute(), time.second(), day, month, year)
148 | {}
149 |
150 | BlynkDateTime(const BlynkTime& time, const BlynkDateTime& date)
151 | : BlynkDateTime(time.hour(), time.minute(), time.second(), date.day(), date.month(), date.year())
152 | {}
153 |
154 | int second() const { return mTm.tm_sec; }
155 | int minute() const { return mTm.tm_min; }
156 | int hour() const { return mTm.tm_hour; }
157 | int day() const { return mTm.tm_mday; }
158 | int month() const { return 1 + mTm.tm_mon; }
159 | int year() const { return 1900 + mTm.tm_year; }
160 |
161 | int yearday() const { return 1 + mTm.tm_yday; } // 1 = Jan 1, 2 = Jan 2 ...
162 | int weekday() const { return mTm.tm_wday; } // 0 = Sun, 1 = Mon ...
163 |
164 | // Deprecated: // 1 = Mon, ..., 7 = Sun
165 | int day_of_week() const { return mTm.tm_wday == 0 ? 7 : mTm.tm_wday; }
166 | int day_of_year() const { return 1 + mTm.tm_yday; }
167 | const char* dow_str() const { return DOW_STR[mTm.tm_wday % 7]; }
168 |
169 | int weak_of_year() const {
170 | int julian = yearday();
171 | int dow = mTm.tm_wday;
172 | int dowJan1 = BlynkDateTime(0,0,0, 1,1,year()).weekday();
173 | int weekNum = ((julian + 6) / 7);
174 | if (dow < dowJan1) {
175 | ++weekNum;
176 | }
177 | return (weekNum);
178 | }
179 |
180 | int getSecsToday() const { return mTime % BLYNK_SECS_PER_DAY; }
181 | int getSecsThisWeek() const { return (mTm.tm_wday * BLYNK_SECS_PER_DAY) + getSecsToday(); }
182 | BlynkDateTime getPrevMidnight() const { return BlynkDateTime((mTime / BLYNK_SECS_PER_DAY) * BLYNK_SECS_PER_DAY); }
183 | BlynkDateTime getNextMidnight() const { return BlynkDateTime((mTime / BLYNK_SECS_PER_DAY) * BLYNK_SECS_PER_DAY + BLYNK_SECS_PER_DAY); }
184 | BlynkDateTime getPrevSunday() const { return BlynkDateTime(mTime - getSecsThisWeek()); }
185 | BlynkDateTime getNextSunday() const { return BlynkDateTime(mTime - getSecsThisWeek() + BLYNK_SECS_PER_WEEK); }
186 |
187 | int hour12() const {
188 | int h = hour();
189 | if (h == 0)
190 | return 12; // 12 midnight
191 | else if (h > 12)
192 | return h - 12;
193 | return h;
194 | }
195 |
196 | bool isAM() const { return !isPM(); }
197 | bool isPM() const { return (hour() >= 12); }
198 |
199 | void adjustSeconds(int sec) {
200 | if (isValid()) {
201 | mTime += sec;
202 | blynk_gmtime_r(&mTime, &mTm);
203 | }
204 | }
205 |
206 | //tm& getTm() { return mTm; }
207 | blynk_time_t getUnix() const { return mTime; }
208 |
209 | bool isValid() const { return mTime != 0; }
210 | operator blynk_time_t() const { return mTime; }
211 |
212 | bool operator != (const BlynkDateTime& t) const { return mTime != t.mTime; }
213 | bool operator == (const BlynkDateTime& t) const { return mTime == t.mTime; }
214 | bool operator >= (const BlynkDateTime& t) const { return mTime >= t.mTime; }
215 | bool operator <= (const BlynkDateTime& t) const { return mTime <= t.mTime; }
216 | bool operator > (const BlynkDateTime& t) const { return mTime > t.mTime; }
217 | bool operator < (const BlynkDateTime& t) const { return mTime < t.mTime; }
218 |
219 | private:
220 | blynk_tm mTm;
221 | blynk_time_t mTime;
222 | };
223 |
224 | #endif
225 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkDebug.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkDebug.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief Debug utilities
8 | *
9 | */
10 |
11 | #ifndef BlynkDebug_h
12 | #define BlynkDebug_h
13 |
14 | #include
15 | #include
16 |
17 | #include
18 | #ifdef ESP8266
19 | extern "C" {
20 | #include "ets_sys.h"
21 | #include "os_type.h"
22 | #include "mem.h"
23 | }
24 | #else
25 | #include
26 | #endif
27 |
28 | #if defined(ARDUINO_ARCH_ARC32)
29 | typedef uint64_t millis_time_t;
30 | #else
31 | typedef uint32_t millis_time_t;
32 | #endif
33 |
34 | void BlynkDelay(millis_time_t ms);
35 | millis_time_t BlynkMillis();
36 | size_t BlynkFreeRam();
37 | void BlynkReset() BLYNK_NORETURN;
38 | void BlynkFatal() BLYNK_NORETURN;
39 | bool BlynkResetImplemented();
40 |
41 | #if defined(BLYNK_DEBUG_ALL) && !(__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__))
42 | #warning "Compiler features not enabled -> please contact yor board vendor to enable c++0x"
43 | #endif
44 |
45 | // Diagnostic defines
46 |
47 | #define BLYNK_FATAL(msg) { BLYNK_LOG1(msg); BlynkFatal(); }
48 | #define BLYNK_LOG_RAM() { BLYNK_LOG2(BLYNK_F("Free RAM: "), BlynkFreeRam()); }
49 | #define BLYNK_LOG_FN() BLYNK_LOG3(BLYNK_F(__FUNCTION__), '@', __LINE__);
50 | #define BLYNK_LOG_TROUBLE(t) BLYNK_LOG2(BLYNK_F("Trouble detected: http://docs.blynk.cc/#troubleshooting-"), t)
51 |
52 | #ifndef BLYNK_PRINT
53 | #undef BLYNK_DEBUG
54 | #endif
55 |
56 | #ifdef BLYNK_DEBUG_ALL
57 | #define BLYNK_DEBUG
58 | #endif
59 |
60 | #ifdef BLYNK_PRINT
61 |
62 | #if defined(ARDUINO) || defined(SPARK) || defined(PARTICLE)
63 |
64 | #if defined(ARDUINO_ARCH_ARC32)
65 | // This will cause error - on purpose
66 | #define BLYNK_LOG(msg, ...) BLYNK_LOG_UNAVAILABLE(msg, ##__VA_ARGS__)
67 | #else
68 | #define BLYNK_LOG(msg, ...) blynk_dbg_print(BLYNK_PSTR(msg), ##__VA_ARGS__)
69 | #endif
70 |
71 | #define BLYNK_LOG1(p1) { BLYNK_LOG_TIME(); BLYNK_PRINT.println(p1); }
72 | #define BLYNK_LOG2(p1,p2) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(p1); BLYNK_PRINT.println(p2); }
73 | #define BLYNK_LOG3(p1,p2,p3) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(p1); BLYNK_PRINT.print(p2); BLYNK_PRINT.println(p3); }
74 | #define BLYNK_LOG4(p1,p2,p3,p4) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(p1); BLYNK_PRINT.print(p2); BLYNK_PRINT.print(p3); BLYNK_PRINT.println(p4); }
75 | #define BLYNK_LOG6(p1,p2,p3,p4,p5,p6) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(p1); BLYNK_PRINT.print(p2); BLYNK_PRINT.print(p3); BLYNK_PRINT.print(p4); BLYNK_PRINT.print(p5); BLYNK_PRINT.println(p6); }
76 | #define BLYNK_LOG_IP(msg, ip) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(BLYNK_F(msg)); \
77 | BLYNK_PRINT.print(ip[0]); BLYNK_PRINT.print('.'); \
78 | BLYNK_PRINT.print(ip[1]); BLYNK_PRINT.print('.'); \
79 | BLYNK_PRINT.print(ip[2]); BLYNK_PRINT.print('.'); \
80 | BLYNK_PRINT.println(ip[3]); }
81 | #define BLYNK_LOG_IP_REV(msg, ip) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(BLYNK_F(msg)); \
82 | BLYNK_PRINT.print(ip[3]); BLYNK_PRINT.print('.'); \
83 | BLYNK_PRINT.print(ip[2]); BLYNK_PRINT.print('.'); \
84 | BLYNK_PRINT.print(ip[1]); BLYNK_PRINT.print('.'); \
85 | BLYNK_PRINT.println(ip[0]); }
86 |
87 | static inline
88 | void BLYNK_LOG_TIME() {
89 | BLYNK_PRINT.print('[');
90 | BLYNK_PRINT.print(BlynkMillis());
91 | BLYNK_PRINT.print(BLYNK_F("] "));
92 | }
93 |
94 | #ifdef BLYNK_DEBUG
95 | #include
96 | #define BLYNK_DBG_BREAK() { for(;;); }
97 | #define BLYNK_ASSERT(expr) { if(!(expr)) { BLYNK_LOG2(BLYNK_F("Assertion failed: "), BLYNK_F(#expr)); BLYNK_DBG_BREAK() } }
98 |
99 | static inline
100 | void BLYNK_DBG_DUMP(const char* msg, const void* addr, size_t len) {
101 | if (len) {
102 | BLYNK_LOG_TIME();
103 | BLYNK_PRINT.print(msg);
104 | int l2 = len;
105 | const uint8_t* octets = (const uint8_t*)addr;
106 | bool prev_print = true;
107 | while (l2--) {
108 | const uint8_t c = *octets++ & 0xFF;
109 | if (c > 32 && c < 127) {
110 | if (!prev_print) { BLYNK_PRINT.print(']'); }
111 | BLYNK_PRINT.print((char)c);
112 | prev_print = true;
113 | } else {
114 | BLYNK_PRINT.print(prev_print?'[':'|');
115 | if (c < 0x10) { BLYNK_PRINT.print('0'); }
116 | BLYNK_PRINT.print(c, HEX);
117 | prev_print = false;
118 | }
119 | }
120 | if (!prev_print) {
121 | BLYNK_PRINT.print(']');
122 | }
123 | BLYNK_PRINT.println();
124 | }
125 | }
126 | #endif
127 |
128 | #if !defined(ARDUINO_ARCH_ARC32)
129 | #include
130 | #include
131 |
132 | static inline
133 | void blynk_dbg_print(const char* BLYNK_PROGMEM fmt, ...)
134 | {
135 | va_list ap;
136 | va_start(ap, fmt);
137 | char buff[128];
138 | BLYNK_PRINT.print('[');
139 | BLYNK_PRINT.print(BlynkMillis());
140 | BLYNK_PRINT.print(BLYNK_F("] "));
141 | #if defined(__AVR__)
142 | vsnprintf_P(buff, sizeof(buff), fmt, ap);
143 | #else
144 | vsnprintf(buff, sizeof(buff), fmt, ap);
145 | #endif
146 | BLYNK_PRINT.println(buff);
147 | va_end(ap);
148 | }
149 | #endif // ARDUINO_ARCH_ARC32
150 |
151 | #elif defined(__MBED__)
152 |
153 | #define BLYNK_LOG(msg, ...) { BLYNK_PRINT.printf("[%ld] " msg BLYNK_NEWLINE, BlynkMillis(), ##__VA_ARGS__); }
154 | #define BLYNK_LOG1(p1) { BLYNK_LOG(p1);}
155 | #define BLYNK_LOG2(p1,p2) { BLYNK_LOG(p1,p2);}
156 | #define BLYNK_LOG3(p1,p2,p3) { BLYNK_LOG(p1,p2,p3);}
157 | #define BLYNK_LOG4(p1,p2,p3,p4) { BLYNK_LOG(p1,p2,p3,p4);}
158 | #define BLYNK_LOG6(p1,p2,p3,p4,p5,p6) { BLYNK_LOG(p1,p2,p3,p4,p5,p6);}
159 |
160 | #define BLYNK_LOG_TIME() BLYNK_PRINT.printf("[%ld]", BlynkMillis());
161 |
162 | #ifdef BLYNK_DEBUG
163 | #define BLYNK_DBG_BREAK() raise(SIGTRAP);
164 | #define BLYNK_ASSERT(expr) assert(expr)
165 |
166 | static inline
167 | void BLYNK_DBG_DUMP(const char* msg, const void* addr, size_t len) {
168 | BLYNK_LOG_TIME();
169 | BLYNK_PRINT.printf(msg);
170 | int l2 = len;
171 | const uint8_t* octets = (const uint8_t*)addr;
172 | bool prev_print = true;
173 | while (l2--) {
174 | const uint8_t c = *octets++ & 0xFF;
175 | if (c > 32 && c < 127) {
176 | if (!prev_print) { BLYNK_PRINT.putc(']'); }
177 | BLYNK_PRINT.putc((char)c);
178 | prev_print = true;
179 | } else {
180 | BLYNK_PRINT.putc(prev_print?'[':'|');
181 | BLYNK_PRINT.printf("%02x", c);
182 | prev_print = false;
183 | }
184 | }
185 | BLYNK_PRINT.printf("%s" BLYNK_NEWLINE, prev_print?"":"]");
186 | }
187 | #endif
188 |
189 | #elif defined(LINUX)
190 |
191 | #include
192 | #include
193 | #include
194 | #include
195 | #include
196 |
197 | #include
198 | using namespace std;
199 | #define BLYNK_LOG(msg, ...) { fprintf(BLYNK_PRINT, "[%ld] " msg BLYNK_NEWLINE, BlynkMillis(), ##__VA_ARGS__); }
200 | #define BLYNK_LOG1(p1) { BLYNK_LOG_TIME(); cout << p1 << endl; }
201 | #define BLYNK_LOG2(p1,p2) { BLYNK_LOG_TIME(); cout << p1 << p2 << endl; }
202 | #define BLYNK_LOG3(p1,p2,p3) { BLYNK_LOG_TIME(); cout << p1 << p2 << p3 << endl; }
203 | #define BLYNK_LOG4(p1,p2,p3,p4) { BLYNK_LOG_TIME(); cout << p1 << p2 << p3 << p4 << endl; }
204 | #define BLYNK_LOG6(p1,p2,p3,p4,p5,p6) { BLYNK_LOG_TIME(); cout << p1 << p2 << p3 << p4 << p5 << p6 << endl; }
205 |
206 | #define BLYNK_LOG_TIME() cout << '[' << BlynkMillis() << "] ";
207 |
208 | #ifdef BLYNK_DEBUG
209 | #define BLYNK_DBG_BREAK() raise(SIGTRAP);
210 | #define BLYNK_ASSERT(expr) assert(expr)
211 |
212 | static inline
213 | void BLYNK_DBG_DUMP(const char* msg, const void* addr, size_t len) {
214 | BLYNK_LOG_TIME();
215 | fprintf(BLYNK_PRINT, "%s", msg);
216 | int l2 = len;
217 | const uint8_t* octets = (const uint8_t*)addr;
218 | bool prev_print = true;
219 | while (l2--) {
220 | const uint8_t c = *octets++ & 0xFF;
221 | if (c > 32 && c < 127) {
222 | if (!prev_print) { fputc(']', BLYNK_PRINT); }
223 | fputc((char)c, BLYNK_PRINT);
224 | prev_print = true;
225 | } else {
226 | fputc(prev_print?'[':'|', BLYNK_PRINT);
227 | fprintf(BLYNK_PRINT, "%02x", c);
228 | prev_print = false;
229 | }
230 | }
231 | fprintf(BLYNK_PRINT, "%s" BLYNK_NEWLINE, prev_print?"":"]");
232 | }
233 | #endif
234 |
235 | #else
236 |
237 | #warning "Cannot detect platform"
238 |
239 | #endif
240 |
241 | #endif
242 |
243 | #ifndef BLYNK_LOG
244 | #define BLYNK_LOG(...)
245 | #define BLYNK_LOG1(p1)
246 | #define BLYNK_LOG2(p1,p2)
247 | #define BLYNK_LOG3(p1,p2,p3)
248 | #define BLYNK_LOG4(p1,p2,p3,p4)
249 | #define BLYNK_LOG6(p1,p2,p3,p4,p5,p6)
250 | #define BLYNK_LOG_IP(msg, ip)
251 | #define BLYNK_LOG_IP_REV(msg, ip)
252 | #endif
253 |
254 | #ifndef BLYNK_DBG_BREAK
255 | #define BLYNK_DBG_BREAK()
256 | #define BLYNK_ASSERT(expr)
257 | #define BLYNK_DBG_DUMP(msg, addr, len)
258 | #endif
259 |
260 | #endif
261 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkEveryN.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef BLYNKEVERYN_H
3 | #define BLYNKEVERYN_H
4 |
5 | #include
6 |
7 | millis_time_t blynk_count_millis() {
8 | const millis_time_t ms = BlynkMillis();
9 | return ms;
10 | }
11 |
12 | uint16_t blynk_count_seconds16() {
13 | const millis_time_t ms = BlynkMillis();
14 | return (ms / 1000);
15 | }
16 |
17 | uint16_t blynk_count_minutes16()
18 | {
19 | const millis_time_t ms = BlynkMillis();
20 | return (ms / (60000L)) & 0xFFFF;
21 | }
22 |
23 | uint8_t blynk_count_hours8()
24 | {
25 | const millis_time_t ms = BlynkMillis();
26 | return (ms / (3600000L)) & 0xFF;
27 | }
28 |
29 | template
30 | class BlynkPeriodic {
31 | public:
32 | T mPrev;
33 | T mPeriod;
34 |
35 | BlynkPeriodic() { reset(); mPeriod = 1; };
36 | BlynkPeriodic(T period) { reset(); setPeriod(period); };
37 | void setPeriod( T period) { mPeriod = period; };
38 | T getTime() { return (T)(timeGetter()); };
39 | T getPeriod() { return mPeriod; };
40 | T getElapsed() { return getTime() - mPrev; }
41 | T getRemaining() { return mPeriod - getElapsed(); }
42 | T getLastTriggerTime() { return mPrev; }
43 | bool ready() {
44 | bool isReady = (getElapsed() >= mPeriod);
45 | if( isReady ) { reset(); }
46 | return isReady;
47 | }
48 | void reset() { mPrev = getTime(); };
49 | void trigger() { mPrev = getTime() - mPeriod; };
50 |
51 | operator bool() { return ready(); }
52 | };
53 |
54 | typedef BlynkPeriodic BlynkEveryNMillis;
55 | typedef BlynkPeriodic BlynkEveryNSeconds;
56 | typedef BlynkPeriodic BlynkEveryNMinutes;
57 | typedef BlynkPeriodic BlynkEveryNHours;
58 |
59 | #define BLYNK_EVERY_N_MILLIS_I(NAME,N) static BlynkEveryNMillis NAME(N); if(NAME)
60 | #define BLYNK_EVERY_N_SECONDS_I(NAME,N) static BlynkEveryNSeconds NAME(N); if(NAME)
61 | #define BLYNK_EVERY_N_MINUTES_I(NAME,N) static BlynkEveryNMinutes NAME(N); if(NAME)
62 | #define BLYNK_EVERY_N_HOURS_I(NAME,N) static BlynkEveryNHours NAME(N); if(NAME)
63 |
64 | #define BLYNK_EVERY_N_MILLIS(N) BLYNK_EVERY_N_MILLIS_I(BLYNK_CONCAT2(PER, __COUNTER__),N)
65 | #define BLYNK_EVERY_N_SECONDS(N) BLYNK_EVERY_N_SECONDS_I(BLYNK_CONCAT2(PER, __COUNTER__),N)
66 | #define BLYNK_EVERY_N_MINUTES(N) BLYNK_EVERY_N_MINUTES_I(BLYNK_CONCAT2(PER, __COUNTER__),N)
67 | #define BLYNK_EVERY_N_HOURS(N) BLYNK_EVERY_N_HOURS_I(BLYNK_CONCAT2(PER, __COUNTER__),N)
68 |
69 | #endif
70 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkHandlers.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkHandlers.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief Handlers for virtual pin operations
8 | *
9 | */
10 |
11 | #ifndef BlynkHandlers_h
12 | #define BlynkHandlers_h
13 |
14 | #include
15 | #include
16 |
17 | // Helper macro
18 |
19 | #define V0 0
20 | #define V1 1
21 | #define V2 2
22 | #define V3 3
23 | #define V4 4
24 | #define V5 5
25 | #define V6 6
26 | #define V7 7
27 | #define V8 8
28 | #define V9 9
29 | #define V10 10
30 | #define V11 11
31 | #define V12 12
32 | #define V13 13
33 | #define V14 14
34 | #define V15 15
35 | #define V16 16
36 | #define V17 17
37 | #define V18 18
38 | #define V19 19
39 | #define V20 20
40 | #define V21 21
41 | #define V22 22
42 | #define V23 23
43 | #define V24 24
44 | #define V25 25
45 | #define V26 26
46 | #define V27 27
47 | #define V28 28
48 | #define V29 29
49 | #define V30 30
50 | #define V31 31
51 | #ifdef BLYNK_USE_128_VPINS
52 | #define V32 32
53 | #define V33 33
54 | #define V34 34
55 | #define V35 35
56 | #define V36 36
57 | #define V37 37
58 | #define V38 38
59 | #define V39 39
60 | #define V40 40
61 | #define V41 41
62 | #define V42 42
63 | #define V43 43
64 | #define V44 44
65 | #define V45 45
66 | #define V46 46
67 | #define V47 47
68 | #define V48 48
69 | #define V49 49
70 | #define V50 50
71 | #define V51 51
72 | #define V52 52
73 | #define V53 53
74 | #define V54 54
75 | #define V55 55
76 | #define V56 56
77 | #define V57 57
78 | #define V58 58
79 | #define V59 59
80 | #define V60 60
81 | #define V61 61
82 | #define V62 62
83 | #define V63 63
84 | #define V64 64
85 | #define V65 65
86 | #define V66 66
87 | #define V67 67
88 | #define V68 68
89 | #define V69 69
90 | #define V70 70
91 | #define V71 71
92 | #define V72 72
93 | #define V73 73
94 | #define V74 74
95 | #define V75 75
96 | #define V76 76
97 | #define V77 77
98 | #define V78 78
99 | #define V79 79
100 | #define V80 80
101 | #define V81 81
102 | #define V82 82
103 | #define V83 83
104 | #define V84 84
105 | #define V85 85
106 | #define V86 86
107 | #define V87 87
108 | #define V88 88
109 | #define V89 89
110 | #define V90 90
111 | #define V91 91
112 | #define V92 92
113 | #define V93 93
114 | #define V94 94
115 | #define V95 95
116 | #define V96 96
117 | #define V97 97
118 | #define V98 98
119 | #define V99 99
120 | #define V100 100
121 | #define V101 101
122 | #define V102 102
123 | #define V103 103
124 | #define V104 104
125 | #define V105 105
126 | #define V106 106
127 | #define V107 107
128 | #define V108 108
129 | #define V109 109
130 | #define V110 110
131 | #define V111 111
132 | #define V112 112
133 | #define V113 113
134 | #define V114 114
135 | #define V115 115
136 | #define V116 116
137 | #define V117 117
138 | #define V118 118
139 | #define V119 119
140 | #define V120 120
141 | #define V121 121
142 | #define V122 122
143 | #define V123 123
144 | #define V124 124
145 | #define V125 125
146 | #define V126 126
147 | #define V127 127
148 | #endif
149 |
150 | // Initial syntax:
151 | #define BLYNK_WRITE_2(pin) \
152 | void BlynkWidgetWrite ## pin (BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED ¶m)
153 |
154 | #define BLYNK_READ_2(pin) \
155 | void BlynkWidgetRead ## pin (BlynkReq BLYNK_UNUSED &request)
156 |
157 | #define BLYNK_WRITE_DEFAULT() BLYNK_WRITE_2(Default)
158 | #define BLYNK_READ_DEFAULT() BLYNK_READ_2(Default)
159 |
160 | #define BLYNK_WRITE(pin) BLYNK_WRITE_2(pin)
161 | #define BLYNK_READ(pin) BLYNK_READ_2(pin)
162 |
163 | // New, more readable syntax:
164 | #define BLYNK_IN_2(pin) \
165 | void BlynkWidgetWrite ## pin (BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED &getValue)
166 |
167 | #define BLYNK_OUT_2(pin) \
168 | void BlynkWidgetRead ## pin (BlynkReq BLYNK_UNUSED &request)
169 |
170 | #define BLYNK_INPUT_DEFAULT() BLYNK_IN_2(Default)
171 | #define BLYNK_OUTPUT_DEFAULT() BLYNK_OUT_2(Default)
172 |
173 | #define BLYNK_INPUT(pin) BLYNK_IN_2(pin)
174 | #define BLYNK_OUTPUT(pin) BLYNK_OUT_2(pin)
175 |
176 | // Additional handlers
177 | #define BLYNK_CONNECTED() void BlynkOnConnected()
178 | #define BLYNK_DISCONNECTED() void BlynkOnDisconnected()
179 |
180 | // Advanced functions
181 |
182 | #define BLYNK_VAR_INT(name, pin) \
183 | int name; \
184 | BLYNK_WRITE(pin) { name = param.asInt(); } \
185 | BLYNK_READ(pin) { Blynk.virtualWrite(pin, name); }
186 |
187 | #define BLYNK_VAR_LONG(name, pin) \
188 | long name; \
189 | BLYNK_WRITE(pin) { name = param.asLong(); } \
190 | BLYNK_READ(pin) { Blynk.virtualWrite(pin, name); }
191 |
192 | #ifndef BLYNK_NO_FLOAT
193 | #define BLYNK_VAR_DOUBLE(name, pin) \
194 | double name; \
195 | BLYNK_WRITE(pin) { name = param.asDouble(); } \
196 | BLYNK_READ(pin) { Blynk.virtualWrite(pin, name); }
197 | #endif
198 |
199 | #ifdef ARDUINO
200 | #define BLYNK_VAR_STRING(name, pin) \
201 | String name; \
202 | BLYNK_WRITE(pin) { name = param.asStr(); } \
203 | BLYNK_READ(pin) { Blynk.virtualWrite(pin, name); }
204 | #endif
205 |
206 | // Default read/write handlers (you can redefine them in your code)
207 | #ifdef __cplusplus
208 | extern "C" {
209 | #endif
210 |
211 | struct BlynkReq
212 | {
213 | uint16_t pin;
214 | };
215 |
216 | typedef void (*WidgetReadHandler)(BlynkReq BLYNK_UNUSED &request);
217 | typedef void (*WidgetWriteHandler)(BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED ¶m);
218 |
219 | WidgetReadHandler GetReadHandler(uint8_t pin);
220 | WidgetWriteHandler GetWriteHandler(uint8_t pin);
221 |
222 | // Declare placeholders
223 | BLYNK_READ();
224 | BLYNK_WRITE();
225 | void BlynkNoOpCbk();
226 |
227 | // Declare all pin handlers (you can redefine them in your code)
228 | BLYNK_CONNECTED();
229 | BLYNK_DISCONNECTED();
230 |
231 | // Internal Virtual Pins
232 | BLYNK_WRITE(InternalPinACON);
233 | BLYNK_WRITE(InternalPinADIS);
234 | BLYNK_WRITE(InternalPinRTC);
235 | BLYNK_WRITE(InternalPinUTC);
236 | BLYNK_WRITE(InternalPinOTA);
237 | BLYNK_WRITE(InternalPinMETA);
238 | BLYNK_WRITE(InternalPinVFS);
239 | BLYNK_WRITE(InternalPinDBG);
240 |
241 | // Aliases
242 | //#define BLYNK_APP_CONNECTED() BLYNK_WRITE(InternalPinACON)
243 | //#define BLYNK_APP_DISCONNECTED() BLYNK_WRITE(InternalPinADIS)
244 |
245 | // Regular Virtual Pins
246 | BLYNK_READ_DEFAULT();
247 | BLYNK_WRITE_DEFAULT();
248 |
249 | BLYNK_READ(0 );
250 | BLYNK_READ(1 );
251 | BLYNK_READ(2 );
252 | BLYNK_READ(3 );
253 | BLYNK_READ(4 );
254 | BLYNK_READ(5 );
255 | BLYNK_READ(6 );
256 | BLYNK_READ(7 );
257 | BLYNK_READ(8 );
258 | BLYNK_READ(9 );
259 | BLYNK_READ(10);
260 | BLYNK_READ(11);
261 | BLYNK_READ(12);
262 | BLYNK_READ(13);
263 | BLYNK_READ(14);
264 | BLYNK_READ(15);
265 | BLYNK_READ(16);
266 | BLYNK_READ(17);
267 | BLYNK_READ(18);
268 | BLYNK_READ(19);
269 | BLYNK_READ(20);
270 | BLYNK_READ(21);
271 | BLYNK_READ(22);
272 | BLYNK_READ(23);
273 | BLYNK_READ(24);
274 | BLYNK_READ(25);
275 | BLYNK_READ(26);
276 | BLYNK_READ(27);
277 | BLYNK_READ(28);
278 | BLYNK_READ(29);
279 | BLYNK_READ(30);
280 | BLYNK_READ(31);
281 | #ifdef BLYNK_USE_128_VPINS
282 | BLYNK_READ(32);
283 | BLYNK_READ(33);
284 | BLYNK_READ(34);
285 | BLYNK_READ(35);
286 | BLYNK_READ(36);
287 | BLYNK_READ(37);
288 | BLYNK_READ(38);
289 | BLYNK_READ(39);
290 | BLYNK_READ(40);
291 | BLYNK_READ(41);
292 | BLYNK_READ(42);
293 | BLYNK_READ(43);
294 | BLYNK_READ(44);
295 | BLYNK_READ(45);
296 | BLYNK_READ(46);
297 | BLYNK_READ(47);
298 | BLYNK_READ(48);
299 | BLYNK_READ(49);
300 | BLYNK_READ(50);
301 | BLYNK_READ(51);
302 | BLYNK_READ(52);
303 | BLYNK_READ(53);
304 | BLYNK_READ(54);
305 | BLYNK_READ(55);
306 | BLYNK_READ(56);
307 | BLYNK_READ(57);
308 | BLYNK_READ(58);
309 | BLYNK_READ(59);
310 | BLYNK_READ(60);
311 | BLYNK_READ(61);
312 | BLYNK_READ(62);
313 | BLYNK_READ(63);
314 | BLYNK_READ(64);
315 | BLYNK_READ(65);
316 | BLYNK_READ(66);
317 | BLYNK_READ(67);
318 | BLYNK_READ(68);
319 | BLYNK_READ(69);
320 | BLYNK_READ(70);
321 | BLYNK_READ(71);
322 | BLYNK_READ(72);
323 | BLYNK_READ(73);
324 | BLYNK_READ(74);
325 | BLYNK_READ(75);
326 | BLYNK_READ(76);
327 | BLYNK_READ(77);
328 | BLYNK_READ(78);
329 | BLYNK_READ(79);
330 | BLYNK_READ(80);
331 | BLYNK_READ(81);
332 | BLYNK_READ(82);
333 | BLYNK_READ(83);
334 | BLYNK_READ(84);
335 | BLYNK_READ(85);
336 | BLYNK_READ(86);
337 | BLYNK_READ(87);
338 | BLYNK_READ(88);
339 | BLYNK_READ(89);
340 | BLYNK_READ(90);
341 | BLYNK_READ(91);
342 | BLYNK_READ(92);
343 | BLYNK_READ(93);
344 | BLYNK_READ(94);
345 | BLYNK_READ(95);
346 | BLYNK_READ(96);
347 | BLYNK_READ(97);
348 | BLYNK_READ(98);
349 | BLYNK_READ(99);
350 | BLYNK_READ(100);
351 | BLYNK_READ(101);
352 | BLYNK_READ(102);
353 | BLYNK_READ(103);
354 | BLYNK_READ(104);
355 | BLYNK_READ(105);
356 | BLYNK_READ(106);
357 | BLYNK_READ(107);
358 | BLYNK_READ(108);
359 | BLYNK_READ(109);
360 | BLYNK_READ(110);
361 | BLYNK_READ(111);
362 | BLYNK_READ(112);
363 | BLYNK_READ(113);
364 | BLYNK_READ(114);
365 | BLYNK_READ(115);
366 | BLYNK_READ(116);
367 | BLYNK_READ(117);
368 | BLYNK_READ(118);
369 | BLYNK_READ(119);
370 | BLYNK_READ(120);
371 | BLYNK_READ(121);
372 | BLYNK_READ(122);
373 | BLYNK_READ(123);
374 | BLYNK_READ(124);
375 | BLYNK_READ(125);
376 | BLYNK_READ(126);
377 | BLYNK_READ(127);
378 | #endif
379 |
380 | BLYNK_WRITE(0 );
381 | BLYNK_WRITE(1 );
382 | BLYNK_WRITE(2 );
383 | BLYNK_WRITE(3 );
384 | BLYNK_WRITE(4 );
385 | BLYNK_WRITE(5 );
386 | BLYNK_WRITE(6 );
387 | BLYNK_WRITE(7 );
388 | BLYNK_WRITE(8 );
389 | BLYNK_WRITE(9 );
390 | BLYNK_WRITE(10);
391 | BLYNK_WRITE(11);
392 | BLYNK_WRITE(12);
393 | BLYNK_WRITE(13);
394 | BLYNK_WRITE(14);
395 | BLYNK_WRITE(15);
396 | BLYNK_WRITE(16);
397 | BLYNK_WRITE(17);
398 | BLYNK_WRITE(18);
399 | BLYNK_WRITE(19);
400 | BLYNK_WRITE(20);
401 | BLYNK_WRITE(21);
402 | BLYNK_WRITE(22);
403 | BLYNK_WRITE(23);
404 | BLYNK_WRITE(24);
405 | BLYNK_WRITE(25);
406 | BLYNK_WRITE(26);
407 | BLYNK_WRITE(27);
408 | BLYNK_WRITE(28);
409 | BLYNK_WRITE(29);
410 | BLYNK_WRITE(30);
411 | BLYNK_WRITE(31);
412 | #ifdef BLYNK_USE_128_VPINS
413 | BLYNK_WRITE(32);
414 | BLYNK_WRITE(33);
415 | BLYNK_WRITE(34);
416 | BLYNK_WRITE(35);
417 | BLYNK_WRITE(36);
418 | BLYNK_WRITE(37);
419 | BLYNK_WRITE(38);
420 | BLYNK_WRITE(39);
421 | BLYNK_WRITE(40);
422 | BLYNK_WRITE(41);
423 | BLYNK_WRITE(42);
424 | BLYNK_WRITE(43);
425 | BLYNK_WRITE(44);
426 | BLYNK_WRITE(45);
427 | BLYNK_WRITE(46);
428 | BLYNK_WRITE(47);
429 | BLYNK_WRITE(48);
430 | BLYNK_WRITE(49);
431 | BLYNK_WRITE(50);
432 | BLYNK_WRITE(51);
433 | BLYNK_WRITE(52);
434 | BLYNK_WRITE(53);
435 | BLYNK_WRITE(54);
436 | BLYNK_WRITE(55);
437 | BLYNK_WRITE(56);
438 | BLYNK_WRITE(57);
439 | BLYNK_WRITE(58);
440 | BLYNK_WRITE(59);
441 | BLYNK_WRITE(60);
442 | BLYNK_WRITE(61);
443 | BLYNK_WRITE(62);
444 | BLYNK_WRITE(63);
445 | BLYNK_WRITE(64);
446 | BLYNK_WRITE(65);
447 | BLYNK_WRITE(66);
448 | BLYNK_WRITE(67);
449 | BLYNK_WRITE(68);
450 | BLYNK_WRITE(69);
451 | BLYNK_WRITE(70);
452 | BLYNK_WRITE(71);
453 | BLYNK_WRITE(72);
454 | BLYNK_WRITE(73);
455 | BLYNK_WRITE(74);
456 | BLYNK_WRITE(75);
457 | BLYNK_WRITE(76);
458 | BLYNK_WRITE(77);
459 | BLYNK_WRITE(78);
460 | BLYNK_WRITE(79);
461 | BLYNK_WRITE(80);
462 | BLYNK_WRITE(81);
463 | BLYNK_WRITE(82);
464 | BLYNK_WRITE(83);
465 | BLYNK_WRITE(84);
466 | BLYNK_WRITE(85);
467 | BLYNK_WRITE(86);
468 | BLYNK_WRITE(87);
469 | BLYNK_WRITE(88);
470 | BLYNK_WRITE(89);
471 | BLYNK_WRITE(90);
472 | BLYNK_WRITE(91);
473 | BLYNK_WRITE(92);
474 | BLYNK_WRITE(93);
475 | BLYNK_WRITE(94);
476 | BLYNK_WRITE(95);
477 | BLYNK_WRITE(96);
478 | BLYNK_WRITE(97);
479 | BLYNK_WRITE(98);
480 | BLYNK_WRITE(99);
481 | BLYNK_WRITE(100);
482 | BLYNK_WRITE(101);
483 | BLYNK_WRITE(102);
484 | BLYNK_WRITE(103);
485 | BLYNK_WRITE(104);
486 | BLYNK_WRITE(105);
487 | BLYNK_WRITE(106);
488 | BLYNK_WRITE(107);
489 | BLYNK_WRITE(108);
490 | BLYNK_WRITE(109);
491 | BLYNK_WRITE(110);
492 | BLYNK_WRITE(111);
493 | BLYNK_WRITE(112);
494 | BLYNK_WRITE(113);
495 | BLYNK_WRITE(114);
496 | BLYNK_WRITE(115);
497 | BLYNK_WRITE(116);
498 | BLYNK_WRITE(117);
499 | BLYNK_WRITE(118);
500 | BLYNK_WRITE(119);
501 | BLYNK_WRITE(120);
502 | BLYNK_WRITE(121);
503 | BLYNK_WRITE(122);
504 | BLYNK_WRITE(123);
505 | BLYNK_WRITE(124);
506 | BLYNK_WRITE(125);
507 | BLYNK_WRITE(126);
508 | BLYNK_WRITE(127);
509 | #endif
510 |
511 | #ifdef __cplusplus
512 | }
513 | #endif
514 |
515 | #endif
516 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkHelpers.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkHelpers.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2016 Volodymyr Shymanskyy
6 | * @date May 2016
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkHelpers_h
12 | #define BlynkHelpers_h
13 |
14 | #if defined(SPARK) || defined(PARTICLE)
15 | #include "application.h"
16 | #endif
17 |
18 | #if defined(ARDUINO)
19 | #if ARDUINO >= 100
20 | #include
21 | #else
22 | #include
23 | #endif
24 | #endif
25 |
26 | #if defined(LINUX)
27 | #if defined(RASPBERRY)
28 | #include
29 | #endif
30 | #endif
31 |
32 | #include
33 | #include
34 |
35 | // General defines
36 |
37 | #define BLYNK_NEWLINE "\r\n"
38 |
39 | #define BLYNK_CONCAT(a, b) a ## b
40 | #define BLYNK_CONCAT2(a, b) BLYNK_CONCAT(a, b)
41 |
42 | #define BLYNK_STRINGIFY(x) #x
43 | #define BLYNK_TOSTRING(x) BLYNK_STRINGIFY(x)
44 |
45 | #define BLYNK_COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
46 |
47 | #define BLYNK_ATTR_PACKED __attribute__ ((__packed__))
48 | #define BLYNK_NORETURN __attribute__ ((noreturn))
49 | #define BLYNK_UNUSED __attribute__ ((__unused__))
50 | #define BLYNK_DEPRECATED __attribute__ ((deprecated))
51 | #define BLYNK_CONSTRUCTOR __attribute__ ((constructor))
52 | #define BLYNK_FALLTHROUGH __attribute__ ((fallthrough))
53 |
54 | // Causes problems on some platforms
55 | #define BLYNK_FORCE_INLINE inline //__attribute__((always_inline))
56 |
57 | #if !defined(BLYNK_RUN_YIELD)
58 | #if defined(BLYNK_NO_YIELD)
59 | #define BLYNK_RUN_YIELD() {}
60 | #elif defined(SPARK) || defined(PARTICLE)
61 | #define BLYNK_RUN_YIELD() { Particle.process(); }
62 | #elif !defined(ARDUINO) || (ARDUINO < 151)
63 | #define BLYNK_RUN_YIELD() {}
64 | #else
65 | #define BLYNK_RUN_YIELD() { BlynkDelay(0); }
66 | #endif
67 | #endif
68 |
69 | #if defined(__AVR__)
70 | #include
71 | #define BLYNK_HAS_PROGMEM
72 | #define BLYNK_PROGMEM PROGMEM
73 | #define BLYNK_F(s) F(s)
74 | #define BLYNK_PSTR(s) PSTR(s)
75 | #else
76 | #define BLYNK_PROGMEM
77 | #define BLYNK_F(s) s
78 | #define BLYNK_PSTR(s) s
79 | #endif
80 |
81 | #if defined(__has_include)
82 | #if __has_include()
83 | #include
84 | #define BLYNK_HAS_FUNCTIONAL_H
85 | #endif
86 | #endif
87 |
88 | #if defined(BLYNK_MULTITHREADED)
89 | #include
90 |
91 | #define BLYNK_MUTEX_DECL(x) std::mutex x
92 | #define BLYNK_MUTEX_GUARD(x) std::lock_guard BLYNK_CONCAT2(lg_, __LINE__)(x)
93 | #else
94 | #define BLYNK_MUTEX_DECL(x)
95 | #define BLYNK_MUTEX_GUARD(x)
96 | #endif
97 |
98 | #ifdef ARDUINO_AVR_DIGISPARK
99 | typedef fstr_t __FlashStringHelper;
100 | #endif
101 |
102 | #endif /* BlynkHelpers_h */
103 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkParam.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkParam.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief Container for handler parameters
8 | *
9 | */
10 |
11 | #ifndef BlynkParam_h
12 | #define BlynkParam_h
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | #define BLYNK_PARAM_KV(k, v) k "\0" v "\0"
20 | #define BLYNK_PARAM_PLACEHOLDER_64 "PlaceholderPlaceholderPlaceholderPlaceholderPlaceholderPlaceholder"
21 |
22 | #if !defined(BLYNK_NO_FLOAT)
23 | extern char* dtostrf_internal(double number, signed char width, unsigned char prec, char *s);
24 | #endif
25 |
26 | #if !defined(BLYNK_NO_LONGLONG)
27 | extern long long atoll_internal(const char *s);
28 | extern char* lltoa_internal(long long val, char* buf, unsigned buf_len, int base);
29 | extern char* ulltoa_internal(unsigned long long val, char* buf, unsigned buf_len, int base);
30 | #endif
31 |
32 | class BlynkParam
33 | {
34 | public:
35 | class iterator
36 | {
37 | public:
38 | iterator(const char* c, const char* l) : ptr(c), limit(l) {}
39 | static iterator invalid() { return iterator(NULL, NULL); }
40 |
41 | operator const char* () const { return asStr(); }
42 | operator int () const { return asInt(); }
43 | const char* asStr() const { return ptr; }
44 | const char* asString() const { return ptr; }
45 | int asInt() const { if(!isValid()) return 0; return atoi(ptr); }
46 | long asLong() const { if(!isValid()) return 0; return atol(ptr); }
47 | #if !defined(BLYNK_NO_LONGLONG) && defined(BLYNK_USE_INTERNAL_ATOLL)
48 | long long asLongLong() const { return atoll_internal(ptr); }
49 | #elif !defined(BLYNK_NO_LONGLONG)
50 | long long asLongLong() const { return atoll(ptr); }
51 | #endif
52 | #if !defined(BLYNK_NO_FLOAT)
53 | double asDouble() const { if(!isValid()) return 0; return atof(ptr); }
54 | float asFloat() const { if(!isValid()) return 0; return atof(ptr); }
55 | #endif
56 | bool isValid() const { return ptr != NULL && ptr < limit; }
57 | bool isEmpty() const { if(!isValid()) return true; return *ptr == '\0'; }
58 |
59 | bool operator < (const iterator& it) const { return ptr < it.ptr; }
60 | bool operator >= (const iterator& it) const { return ptr >= it.ptr; }
61 |
62 | iterator& operator ++() {
63 | if(isValid()) {
64 | ptr += strlen(ptr) + 1;
65 | }
66 | return *this;
67 | }
68 | private:
69 | const char* ptr;
70 | const char* limit;
71 | };
72 |
73 | public:
74 | explicit
75 | BlynkParam(const void* addr, size_t length)
76 | : buff((char*)addr), len(length), buff_size(length)
77 | {}
78 |
79 | explicit
80 | BlynkParam(void* addr, size_t length, size_t buffsize)
81 | : buff((char*)addr), len(length), buff_size(buffsize)
82 | {}
83 |
84 | const char* asStr() const { return buff; }
85 | const char* asString() const { return buff; }
86 | int asInt() const { return atoi(buff); }
87 | long asLong() const { return atol(buff); }
88 | #if !defined(BLYNK_NO_LONGLONG) && defined(BLYNK_USE_INTERNAL_ATOLL)
89 | long long asLongLong() const { return atoll_internal(buff); }
90 | #elif !defined(BLYNK_NO_LONGLONG)
91 | long long asLongLong() const { return atoll(buff); }
92 | #endif
93 | #if !defined(BLYNK_NO_FLOAT)
94 | double asDouble() const { return atof(buff); }
95 | float asFloat() const { return atof(buff); }
96 | #endif
97 | bool isEmpty() const { return *buff == '\0'; }
98 |
99 | iterator begin() const { return iterator(buff, buff+len); }
100 | iterator end() const { return iterator(buff+len, buff+len); }
101 |
102 | iterator operator[](int index) const;
103 | iterator operator[](const char* key) const;
104 |
105 | void* getBuffer() const { return (void*)buff; }
106 | size_t getLength() const { return len; }
107 | size_t getBuffSize() const { return buff_size; }
108 |
109 | // Modification
110 | void clear() { len = 0; }
111 |
112 | void add(int value);
113 | void add(unsigned int value);
114 | void add(long value);
115 | void add(unsigned long value);
116 | void add(long long value);
117 | void add(unsigned long long value);
118 | #ifndef BLYNK_NO_FLOAT
119 | void add(float value);
120 | void add(double value);
121 | #endif
122 | void add(const char* str);
123 | #if defined(ARDUINO) || defined(SPARK) || defined(PARTICLE)
124 | void add(const String& str);
125 | #if defined(BLYNK_HAS_PROGMEM)
126 | void add(const __FlashStringHelper* str);
127 | #endif
128 | #endif
129 |
130 | template
131 | void add_multi(T last) {
132 | add(last);
133 | }
134 |
135 | template
136 | void add_multi(T head, Args... tail) {
137 | add(head);
138 | add_multi(tail...);
139 | }
140 |
141 | template
142 | void add_key(const char* key, const TV& val) {
143 | add(key);
144 | add(val);
145 | }
146 |
147 | void remove_key(const char* key);
148 |
149 | void add_raw(const void* b, size_t l);
150 |
151 | protected:
152 | char* buff;
153 | size_t len;
154 | size_t buff_size;
155 | };
156 |
157 |
158 | class BlynkParamAllocated
159 | : public BlynkParam
160 | {
161 | public:
162 | BlynkParamAllocated(size_t size)
163 | : BlynkParam(malloc(size), 0, size)
164 | {}
165 | ~BlynkParamAllocated() {
166 | free(buff);
167 | }
168 | };
169 |
170 | inline
171 | BlynkParam::iterator BlynkParam::operator[](int index) const
172 | {
173 | const iterator e = end();
174 | for (iterator it = begin(); it < e; ++it) {
175 | if (!index--) {
176 | return it;
177 | }
178 | }
179 | return iterator::invalid();
180 | }
181 |
182 | inline
183 | BlynkParam::iterator BlynkParam::operator[](const char* key) const
184 | {
185 | const iterator e = end();
186 | for (iterator it = begin(); it < e; ++it) {
187 | if (!strcmp(it.asStr(), key)) {
188 | return ++it;
189 | }
190 | ++it;
191 | if (it >= e) break;
192 | }
193 | return iterator::invalid();
194 | }
195 |
196 | inline
197 | void BlynkParam::remove_key(const char* key)
198 | {
199 | bool found;
200 | do {
201 | found = false;
202 | const iterator e = end();
203 | for (iterator it = begin(); it < e; ++it) {
204 | if (!strcmp(it.asStr(), key)) {
205 | const char* key = it.asStr();
206 | ++it; ++it;
207 | const char* next = it.asStr();
208 | memmove((void*)key, next, (buff+len)-next);
209 | len -= (next-key);
210 | found = true;
211 | break;
212 | }
213 | ++it;
214 | if (it >= e) break;
215 | }
216 | } while (found);
217 | }
218 |
219 | inline
220 | void BlynkParam::add_raw(const void* b, size_t l)
221 | {
222 | if (len + l > buff_size)
223 | return;
224 | memcpy(buff+len, b, l);
225 | len += l;
226 | }
227 |
228 | inline
229 | void BlynkParam::add(const char* str)
230 | {
231 | if (str == NULL) {
232 | buff[len++] = '\0';
233 | return;
234 | }
235 | add_raw(str, strlen(str)+1);
236 | }
237 |
238 | #if defined(ARDUINO) || defined(SPARK) || defined(PARTICLE)
239 | inline
240 | void BlynkParam::add(const String& str)
241 | {
242 | #if defined(ARDUINO_AVR_DIGISPARK) \
243 | || defined(__ARDUINO_X86__) \
244 | || defined(__RFduino__)
245 |
246 | size_t len = str.length()+1;
247 | char buff[len];
248 | const_cast(str).toCharArray(buff, len);
249 | add_raw(buff, len);
250 | #else
251 | add(str.c_str());
252 | #endif
253 | }
254 |
255 | #if defined(BLYNK_HAS_PROGMEM)
256 |
257 | inline
258 | void BlynkParam::add(const __FlashStringHelper* ifsh)
259 | {
260 | PGM_P p = reinterpret_cast(ifsh);
261 | size_t l = strlen_P(p) + 1;
262 | if (len + l > buff_size)
263 | return;
264 | memcpy_P(buff+len, p, l);
265 | len += l;
266 | buff[len] = '\0';
267 | }
268 |
269 | #endif
270 |
271 | #endif
272 |
273 | #if defined(__AVR__) || defined (ARDUINO_ARCH_ARC32)
274 |
275 | #include
276 |
277 | inline
278 | void BlynkParam::add(int value)
279 | {
280 | char str[2 + 3 * sizeof(value)];
281 | itoa(value, str, 10);
282 | add(str);
283 | }
284 |
285 | inline
286 | void BlynkParam::add(unsigned int value)
287 | {
288 | char str[1 + 3 * sizeof(value)];
289 | utoa(value, str, 10);
290 | add(str);
291 | }
292 |
293 | inline
294 | void BlynkParam::add(long value)
295 | {
296 | char str[2 + 3 * sizeof(value)];
297 | ltoa(value, str, 10);
298 | add(str);
299 | }
300 |
301 | inline
302 | void BlynkParam::add(unsigned long value)
303 | {
304 | char str[1 + 3 * sizeof(value)];
305 | ultoa(value, str, 10);
306 | add(str);
307 | }
308 |
309 | #if !defined(BLYNK_NO_LONGLONG)
310 |
311 | inline
312 | void BlynkParam::add(long long value)
313 | {
314 | char str[2 + 3 * sizeof(value)];
315 | add(lltoa_internal(value, str, sizeof(str), 10));
316 | }
317 |
318 | inline
319 | void BlynkParam::add(unsigned long long value)
320 | {
321 | char str[1 + 3 * sizeof(value)];
322 | add(ulltoa_internal(value, str, sizeof(str), 10));
323 | }
324 |
325 | #endif
326 |
327 | #ifndef BLYNK_NO_FLOAT
328 |
329 | inline
330 | void BlynkParam::add(float value)
331 | {
332 | char str[33];
333 | dtostrf(value, 5, 3, str);
334 | add(str);
335 | }
336 |
337 | inline
338 | void BlynkParam::add(double value)
339 | {
340 | char str[33];
341 | dtostrf(value, 5, 7, str);
342 | add(str);
343 | }
344 | #endif
345 |
346 | #else
347 |
348 | #include
349 |
350 | inline
351 | void BlynkParam::add(int value)
352 | {
353 | len += snprintf(buff+len, buff_size-len, "%i", value)+1;
354 | }
355 |
356 | inline
357 | void BlynkParam::add(unsigned int value)
358 | {
359 | len += snprintf(buff+len, buff_size-len, "%u", value)+1;
360 | }
361 |
362 | inline
363 | void BlynkParam::add(long value)
364 | {
365 | len += snprintf(buff+len, buff_size-len, "%li", value)+1;
366 | }
367 |
368 | inline
369 | void BlynkParam::add(unsigned long value)
370 | {
371 | len += snprintf(buff+len, buff_size-len, "%lu", value)+1;
372 | }
373 |
374 | inline
375 | void BlynkParam::add(long long value)
376 | {
377 | len += snprintf(buff+len, buff_size-len, "%lli", value)+1;
378 | }
379 |
380 | inline
381 | void BlynkParam::add(unsigned long long value)
382 | {
383 | len += snprintf(buff+len, buff_size-len, "%llu", value)+1;
384 | }
385 |
386 | #ifndef BLYNK_NO_FLOAT
387 |
388 | #if defined(BLYNK_USE_INTERNAL_DTOSTRF)
389 |
390 | inline
391 | void BlynkParam::add(float value)
392 | {
393 | char str[33];
394 | dtostrf_internal(value, 5, 3, str);
395 | add(str);
396 | }
397 |
398 | inline
399 | void BlynkParam::add(double value)
400 | {
401 | char str[33];
402 | dtostrf_internal(value, 5, 7, str);
403 | add(str);
404 | }
405 |
406 | #else
407 |
408 | inline
409 | void BlynkParam::add(float value)
410 | {
411 | len += snprintf(buff+len, buff_size-len, "%2.3f", value)+1;
412 | }
413 |
414 | inline
415 | void BlynkParam::add(double value)
416 | {
417 | len += snprintf(buff+len, buff_size-len, "%2.7f", value)+1;
418 | }
419 |
420 | #endif
421 |
422 | #endif
423 |
424 | #endif
425 |
426 |
427 | #endif
428 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkProtocol.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkProtocol.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief Blynk protocol implementation
8 | *
9 | */
10 |
11 | #ifndef BlynkProtocol_h
12 | #define BlynkProtocol_h
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | template
21 | class BlynkProtocol
22 | : public BlynkApi< BlynkProtocol >
23 | {
24 | friend class BlynkApi< BlynkProtocol >;
25 | public:
26 | enum BlynkState {
27 | CONNECTING,
28 | CONNECTED,
29 | DISCONNECTED,
30 | TOKEN_INVALID,
31 | };
32 |
33 | BlynkProtocol(Transp& transp)
34 | : conn(transp)
35 | , authkey(NULL)
36 | , redir_serv(NULL)
37 | , lastActivityIn(0)
38 | , lastActivityOut(0)
39 | , lastHeartbeat(0)
40 | , msgIdOut(0)
41 | , msgIdOutOverride(0)
42 | , nesting(0)
43 | , state(CONNECTING)
44 | {}
45 |
46 | bool connected() const { return state == CONNECTED; }
47 |
48 | bool isTokenInvalid() const { return state == TOKEN_INVALID; }
49 |
50 | bool connect(uint32_t timeout = BLYNK_TIMEOUT_MS*3) {
51 | conn.disconnect();
52 | state = CONNECTING;
53 | millis_time_t started = BlynkMillis();
54 | while ((state != CONNECTED) &&
55 | (BlynkMillis() - started < timeout))
56 | {
57 | run();
58 | }
59 | return state == CONNECTED;
60 | }
61 |
62 | void disconnect() {
63 | conn.disconnect();
64 | state = DISCONNECTED;
65 | BLYNK_LOG1(BLYNK_F("Disconnected"));
66 | }
67 |
68 | bool run(bool avail = false);
69 |
70 | // TODO: Fixme
71 | void startSession() {
72 | conn.connect();
73 | state = CONNECTING;
74 | msgIdOut = 0;
75 | lastHeartbeat = lastActivityIn = lastActivityOut = (BlynkMillis() - 5000UL);
76 | }
77 |
78 | void sendCmd(uint8_t cmd, uint16_t id = 0, const void* data = NULL, size_t length = 0, const void* data2 = NULL, size_t length2 = 0);
79 |
80 | void sendResponse(BlynkStatus rsp, uint16_t id = 0) {
81 | sendCmd(BLYNK_CMD_RESPONSE, id, NULL, rsp);
82 | }
83 |
84 | void printBanner() {
85 | #if defined(BLYNK_NO_FANCY_LOGO)
86 | BLYNK_LOG1(BLYNK_F("Blynk v" BLYNK_VERSION " on " BLYNK_INFO_DEVICE
87 | BLYNK_NEWLINE
88 | " #StandWithUkraine https://bit.ly/swua" BLYNK_NEWLINE
89 | BLYNK_NEWLINE
90 | ));
91 | #else
92 | BLYNK_LOG1(BLYNK_F(BLYNK_NEWLINE
93 | " ___ __ __" BLYNK_NEWLINE
94 | " / _ )/ /_ _____ / /__" BLYNK_NEWLINE
95 | " / _ / / // / _ \\/ '_/" BLYNK_NEWLINE
96 | " /____/_/\\_, /_//_/_/\\_\\" BLYNK_NEWLINE
97 | " /___/ v" BLYNK_VERSION " on " BLYNK_INFO_DEVICE BLYNK_NEWLINE
98 | BLYNK_NEWLINE
99 | " #StandWithUkraine https://bit.ly/swua" BLYNK_NEWLINE
100 | BLYNK_NEWLINE
101 | ));
102 | #endif
103 | }
104 |
105 | uint16_t getNextMsgId();
106 |
107 | private:
108 |
109 | void internalReconnect() {
110 | state = CONNECTING;
111 | conn.disconnect();
112 | BlynkOnDisconnected();
113 | }
114 |
115 | int readHeader(BlynkHeader& hdr);
116 |
117 | protected:
118 | void begin(const char* auth) {
119 | this->authkey = auth;
120 | lastHeartbeat = lastActivityIn = lastActivityOut = (BlynkMillis() - 5000UL);
121 | #if !defined(BLYNK_NO_DEFAULT_BANNER)
122 | printBanner();
123 | #endif
124 | }
125 |
126 | bool processInput(void);
127 |
128 | Transp& conn;
129 |
130 | private:
131 | const char* authkey;
132 | char* redir_serv;
133 | millis_time_t lastActivityIn;
134 | millis_time_t lastActivityOut;
135 | union {
136 | millis_time_t lastHeartbeat;
137 | millis_time_t lastLogin;
138 | };
139 | uint16_t msgIdOut;
140 | uint16_t msgIdOutOverride;
141 | uint8_t nesting;
142 | BLYNK_MUTEX_DECL(mutex);
143 | protected:
144 | BlynkState state;
145 | };
146 |
147 | template
148 | bool BlynkProtocol::run(bool avail)
149 | {
150 | BLYNK_RUN_YIELD();
151 |
152 | if (state == DISCONNECTED) {
153 | return false;
154 | }
155 |
156 | // Detect nesting
157 | BlynkHelperAutoInc guard(nesting);
158 | if (msgIdOutOverride || nesting > 2) {
159 | //BLYNK_LOG1(BLYNK_F("Nested run() skipped"));
160 | return true;
161 | }
162 |
163 | if (conn.connected()) {
164 | while (avail || conn.available() > 0) {
165 | //BLYNK_LOG2(BLYNK_F("Available: "), conn.available());
166 | //const unsigned long t = micros();
167 | if (!processInput()) {
168 | conn.disconnect();
169 | // TODO: Only when in direct mode?
170 | #ifdef BLYNK_USE_DIRECT_CONNECT
171 | state = CONNECTING;
172 | #endif
173 | BlynkOnDisconnected();
174 | return false;
175 | }
176 | avail = false;
177 | //BLYNK_LOG2(BLYNK_F("Proc time: "), micros() - t);
178 | }
179 | }
180 |
181 | const millis_time_t t = BlynkMillis();
182 |
183 | // Update connection status after running commands
184 | const bool tconn = conn.connected();
185 |
186 | if (state == CONNECTED) {
187 | if (!tconn) {
188 | lastHeartbeat = t;
189 | internalReconnect();
190 | return false;
191 | }
192 |
193 | if (t - lastActivityIn > (1000UL * BLYNK_HEARTBEAT + BLYNK_TIMEOUT_MS*3)) {
194 | #ifdef BLYNK_DEBUG
195 | BLYNK_LOG6(BLYNK_F("Heartbeat timeout: "), t, BLYNK_F(", "), lastActivityIn, BLYNK_F(", "), lastHeartbeat);
196 | #else
197 | BLYNK_LOG1(BLYNK_F("Heartbeat timeout"));
198 | #endif
199 | internalReconnect();
200 | return false;
201 | } else if ((t - lastActivityIn > 1000UL * BLYNK_HEARTBEAT ||
202 | t - lastActivityOut > 1000UL * BLYNK_HEARTBEAT) &&
203 | t - lastHeartbeat > BLYNK_TIMEOUT_MS)
204 | {
205 | // Send ping if we didn't either send or receive something
206 | // for BLYNK_HEARTBEAT seconds
207 | sendCmd(BLYNK_CMD_PING);
208 | lastHeartbeat = t;
209 | }
210 | } else if (state == CONNECTING) {
211 | #ifdef BLYNK_USE_DIRECT_CONNECT
212 | if (!tconn)
213 | conn.connect();
214 | #else
215 | if (tconn && (t - lastLogin > BLYNK_TIMEOUT_MS)) {
216 | BLYNK_LOG1(BLYNK_F("Login timeout"));
217 | conn.disconnect();
218 | state = CONNECTING;
219 | return false;
220 | } else if (!tconn && (t - lastLogin > 5000UL)) {
221 | conn.disconnect();
222 | if (!conn.connect()) {
223 | lastLogin = t;
224 | return false;
225 | }
226 |
227 | msgIdOut = 1;
228 | sendCmd(BLYNK_CMD_HW_LOGIN, 1, authkey, strlen(authkey));
229 | lastLogin = lastActivityOut;
230 | return true;
231 | }
232 | #endif
233 | }
234 | return true;
235 | }
236 |
237 | template
238 | BLYNK_FORCE_INLINE
239 | bool BlynkProtocol::processInput(void)
240 | {
241 | BlynkHeader hdr;
242 | const int ret = readHeader(hdr);
243 |
244 | if (ret == 0) {
245 | return true; // Considered OK (no data on input)
246 | }
247 |
248 | if (ret < 0 || hdr.msg_id == 0) {
249 | #ifdef BLYNK_DEBUG
250 | BLYNK_LOG2(BLYNK_F("Bad hdr len: "), ret);
251 | #endif
252 | return false;
253 | }
254 |
255 | if (hdr.type == BLYNK_CMD_RESPONSE) {
256 | lastActivityIn = BlynkMillis();
257 |
258 | #ifndef BLYNK_USE_DIRECT_CONNECT
259 | if (state == CONNECTING && (1 == hdr.msg_id)) {
260 | switch (hdr.length) {
261 | case BLYNK_SUCCESS:
262 | case BLYNK_ALREADY_REGISTERED:
263 | BLYNK_LOG3(BLYNK_F("Ready (ping: "), lastActivityIn-lastHeartbeat, BLYNK_F("ms)."));
264 | lastHeartbeat = lastActivityIn;
265 | state = CONNECTED;
266 | #ifdef BLYNK_DEBUG
267 | if (size_t ram = BlynkFreeRam()) {
268 | BLYNK_LOG2(BLYNK_F("Free RAM: "), ram);
269 | }
270 | #endif
271 | this->sendInfo();
272 | BLYNK_RUN_YIELD();
273 | BlynkOnConnected();
274 | return true;
275 | case BLYNK_INVALID_TOKEN:
276 | BLYNK_LOG1(BLYNK_F("Invalid auth token"));
277 | state = TOKEN_INVALID;
278 | break;
279 | default:
280 | BLYNK_LOG2(BLYNK_F("Connect failed. code: "), hdr.length);
281 | }
282 | return false;
283 | }
284 | if (BLYNK_NOT_AUTHENTICATED == hdr.length) {
285 | return false;
286 | }
287 | #endif
288 | // TODO: return code may indicate App presence
289 | return true;
290 | }
291 |
292 | if (hdr.length > BLYNK_MAX_READBYTES) {
293 | BLYNK_LOG2(BLYNK_F("Packet too big: "), hdr.length);
294 | // TODO: Flush
295 | internalReconnect();
296 | return true;
297 | }
298 |
299 | uint8_t inputBuffer[hdr.length+1]; // Add 1 to zero-terminate
300 | if (hdr.length != conn.read(inputBuffer, hdr.length)) {
301 | #ifdef BLYNK_DEBUG
302 | BLYNK_LOG1(BLYNK_F("Can't read body"));
303 | #endif
304 | return false;
305 | }
306 | inputBuffer[hdr.length] = '\0';
307 |
308 | BLYNK_DBG_DUMP(">", inputBuffer, hdr.length);
309 |
310 | lastActivityIn = BlynkMillis();
311 |
312 | switch (hdr.type)
313 | {
314 | case BLYNK_CMD_HW_LOGIN: {
315 | #ifdef BLYNK_USE_DIRECT_CONNECT
316 | if (strncmp(authkey, (char*)inputBuffer, 32)) {
317 | BLYNK_LOG1(BLYNK_F("Invalid token"));
318 | sendResponse(BLYNK_INVALID_TOKEN, hdr.msg_id);
319 | break;
320 | }
321 | #endif
322 | if (state == CONNECTING) {
323 | BLYNK_LOG1(BLYNK_F("Ready"));
324 | state = CONNECTED;
325 | #ifdef BLYNK_DEBUG
326 | if (size_t ram = BlynkFreeRam()) {
327 | BLYNK_LOG2(BLYNK_F("Free RAM: "), ram);
328 | }
329 | #endif
330 | this->sendInfo();
331 | BLYNK_RUN_YIELD();
332 | BlynkOnConnected();
333 | }
334 | sendResponse(BLYNK_SUCCESS, hdr.msg_id);
335 | } break;
336 | case BLYNK_CMD_PING: {
337 | sendResponse(BLYNK_SUCCESS, hdr.msg_id);
338 | } break;
339 | case BLYNK_CMD_REDIRECT: {
340 | if (!redir_serv) {
341 | redir_serv = (char*)malloc(64);
342 | }
343 | BlynkParam param(inputBuffer, hdr.length);
344 | uint16_t redir_port = BLYNK_DEFAULT_PORT;
345 |
346 | BlynkParam::iterator it = param.begin();
347 | if (it >= param.end())
348 | return false;
349 |
350 | strncpy(redir_serv, it.asStr(), 64);
351 | redir_serv[63] = '\0';
352 |
353 | if (++it < param.end())
354 | redir_port = it.asLong();
355 | BLYNK_LOG4(BLYNK_F("Redirecting to "), redir_serv, ':', redir_port);
356 | conn.disconnect();
357 | conn.begin(redir_serv, redir_port);
358 | state = CONNECTING;
359 | lastHeartbeat = lastActivityIn = lastActivityOut = (BlynkMillis() - 5000UL);
360 | } break;
361 | case BLYNK_CMD_HARDWARE:
362 | case BLYNK_CMD_BRIDGE: {
363 | msgIdOutOverride = hdr.msg_id;
364 | this->processCmd(inputBuffer, hdr.length);
365 | msgIdOutOverride = 0;
366 | } break;
367 | case BLYNK_CMD_INTERNAL: {
368 | BlynkReq req = { 0 };
369 | BlynkParam param(inputBuffer, hdr.length);
370 | BlynkParam::iterator it = param.begin();
371 | if (it >= param.end())
372 | return true;
373 |
374 | uint32_t cmd32;
375 | memcpy(&cmd32, it.asStr(), sizeof(cmd32));
376 |
377 | ++it;
378 | char* start = (char*)(it).asStr();
379 | unsigned length = hdr.length - (start - (char*)inputBuffer);
380 | BlynkParam param2(start, length);
381 |
382 | msgIdOutOverride = hdr.msg_id;
383 | switch (cmd32) {
384 | case BLYNK_INT_RTC: BlynkWidgetWriteInternalPinRTC(req, param2); break;
385 | case BLYNK_INT_UTC: BlynkWidgetWriteInternalPinUTC(req, param2); break;
386 | case BLYNK_INT_OTA: BlynkWidgetWriteInternalPinOTA(req, param2); break;
387 | case BLYNK_INT_ACON: BlynkWidgetWriteInternalPinACON(req, param2); break;
388 | case BLYNK_INT_ADIS: BlynkWidgetWriteInternalPinADIS(req, param2); break;
389 | case BLYNK_INT_META: BlynkWidgetWriteInternalPinMETA(req, param2); break;
390 | case BLYNK_INT_VFS: BlynkWidgetWriteInternalPinVFS(req, param2); break;
391 | case BLYNK_INT_DBG: BlynkWidgetWriteInternalPinDBG(req, param2); break;
392 | #ifdef BLYNK_DEBUG
393 | default: BLYNK_LOG2(BLYNK_F("Invalid internal cmd:"), param.asStr());
394 | #endif
395 | }
396 | msgIdOutOverride = 0;
397 | } break;
398 | case BLYNK_CMD_DEBUG_PRINT: {
399 | if (hdr.length) {
400 | BLYNK_LOG2(BLYNK_F("Server: "), (char*)inputBuffer);
401 | }
402 | } break;
403 | default: {
404 | #ifdef BLYNK_DEBUG
405 | BLYNK_LOG2(BLYNK_F("Invalid header type: "), hdr.type);
406 | #endif
407 | // TODO: Flush
408 | internalReconnect();
409 | } break;
410 | }
411 |
412 | return true;
413 | }
414 |
415 | template
416 | int BlynkProtocol::readHeader(BlynkHeader& hdr)
417 | {
418 | size_t rlen = conn.read(&hdr, sizeof(hdr));
419 | if (rlen == 0) {
420 | return 0;
421 | }
422 |
423 | if (sizeof(hdr) != rlen) {
424 | return -1;
425 | }
426 |
427 | BLYNK_DBG_DUMP(">", &hdr, sizeof(BlynkHeader));
428 |
429 | hdr.msg_id = ntohs(hdr.msg_id);
430 | hdr.length = ntohs(hdr.length);
431 |
432 | return rlen;
433 | }
434 |
435 | #ifndef BLYNK_SEND_THROTTLE
436 | #define BLYNK_SEND_THROTTLE 0
437 | #endif
438 |
439 | #ifndef BLYNK_SEND_CHUNK
440 | #define BLYNK_SEND_CHUNK 1024 // Just a big number
441 | #endif
442 |
443 | template
444 | void BlynkProtocol::sendCmd(uint8_t cmd, uint16_t id, const void* data, size_t length, const void* data2, size_t length2)
445 | {
446 | if (!conn.connected() || (cmd != BLYNK_CMD_RESPONSE && cmd != BLYNK_CMD_PING && cmd != BLYNK_CMD_HW_LOGIN && state != CONNECTED) ) {
447 | #ifdef BLYNK_DEBUG_ALL
448 | BLYNK_LOG2(BLYNK_F("Cmd skipped:"), cmd);
449 | #endif
450 | return;
451 | }
452 |
453 | #if defined(BLYNK_MSG_LIMIT) && BLYNK_MSG_LIMIT > 0
454 | if (cmd >= BLYNK_CMD_BRIDGE && cmd <= BLYNK_CMD_HARDWARE) {
455 | const millis_time_t allowed_time = BlynkMax(lastActivityOut, lastActivityIn) + 1000/BLYNK_MSG_LIMIT;
456 | int32_t wait_time = allowed_time - BlynkMillis();
457 | if (wait_time >= 0) {
458 | #ifdef BLYNK_DEBUG_ALL
459 | BLYNK_LOG2(BLYNK_F("Waiting:"), wait_time);
460 | #endif
461 | while (wait_time >= 0) {
462 | run();
463 | wait_time = allowed_time - BlynkMillis();
464 | }
465 | } else if (nesting == 0) {
466 | run();
467 | }
468 | }
469 | #endif
470 |
471 | BlynkApi< BlynkProtocol >::sendPendingGroup();
472 |
473 | BLYNK_MUTEX_GUARD(mutex);
474 |
475 | if (0 == id) {
476 | id = getNextMsgId();
477 | }
478 |
479 | const size_t full_length = (sizeof(BlynkHeader)) +
480 | (data ? length : 0) +
481 | (data2 ? length2 : 0);
482 |
483 | #if defined(BLYNK_SEND_ATOMIC) || defined(ESP8266) || defined(ESP32) || defined(SPARK) || defined(PARTICLE) || defined(ENERGIA)
484 | // Those have more RAM and like single write at a time...
485 |
486 | uint8_t buff[full_length];
487 |
488 | BlynkHeader* hdr = (BlynkHeader*)buff;
489 | hdr->type = cmd;
490 | hdr->msg_id = htons(id);
491 | hdr->length = htons(length+length2);
492 |
493 | size_t pos = sizeof(BlynkHeader);
494 | if (data && length) {
495 | memcpy(buff + pos, data, length);
496 | pos += length;
497 | }
498 | if (data2 && length2) {
499 | memcpy(buff + pos, data2, length2);
500 | }
501 |
502 | size_t wlen = 0;
503 | while (wlen < full_length) {
504 | const size_t chunk = BlynkMin(size_t(BLYNK_SEND_CHUNK), full_length - wlen);
505 | BLYNK_DBG_DUMP("<", buff + wlen, chunk);
506 | const size_t w = conn.write(buff + wlen, chunk);
507 | BlynkDelay(BLYNK_SEND_THROTTLE);
508 | if (w == 0) {
509 | #ifdef BLYNK_DEBUG
510 | BLYNK_LOG1(BLYNK_F("Cmd error"));
511 | #endif
512 | conn.disconnect();
513 | state = CONNECTING;
514 | BlynkOnDisconnected();
515 | return;
516 | }
517 | wlen += w;
518 | }
519 |
520 | #else
521 |
522 | BlynkHeader hdr;
523 | hdr.type = cmd;
524 | hdr.msg_id = htons(id);
525 | hdr.length = htons(length+length2);
526 |
527 | BLYNK_DBG_DUMP("<", &hdr, sizeof(hdr));
528 | size_t wlen = conn.write(&hdr, sizeof(hdr));
529 | BlynkDelay(BLYNK_SEND_THROTTLE);
530 |
531 | if (cmd != BLYNK_CMD_RESPONSE) {
532 | if (length) {
533 | BLYNK_DBG_DUMP("<", data, length);
534 | wlen += conn.write(data, length);
535 | BlynkDelay(BLYNK_SEND_THROTTLE);
536 | }
537 | if (length2) {
538 | BLYNK_DBG_DUMP("<", data2, length2);
539 | wlen += conn.write(data2, length2);
540 | BlynkDelay(BLYNK_SEND_THROTTLE);
541 | }
542 | }
543 |
544 | #endif
545 |
546 | if (wlen != full_length) {
547 | #ifdef BLYNK_DEBUG
548 | BLYNK_LOG4(BLYNK_F("Sent "), wlen, '/', full_length);
549 | #endif
550 | internalReconnect();
551 | return;
552 | }
553 |
554 | lastActivityOut = BlynkMillis();
555 |
556 | }
557 |
558 | template
559 | uint16_t BlynkProtocol::getNextMsgId()
560 | {
561 | if (msgIdOutOverride != 0)
562 | return msgIdOutOverride;
563 | if (++msgIdOut == 0)
564 | msgIdOut = 1;
565 | return msgIdOut;
566 | }
567 |
568 | #endif
569 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkProtocolDefs.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkProtocolDefs.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief Blynk protocol definitions
8 | *
9 | */
10 |
11 | #ifndef BlynkProtocolDefs_h
12 | #define BlynkProtocolDefs_h
13 |
14 | enum BlynkCmd
15 | {
16 | BLYNK_CMD_RESPONSE = 0,
17 |
18 | BLYNK_CMD_PING = 6,
19 |
20 | BLYNK_CMD_BRIDGE = 15,
21 | BLYNK_CMD_HARDWARE_SYNC = 16,
22 | BLYNK_CMD_INTERNAL = 17,
23 | BLYNK_CMD_PROPERTY = 19,
24 | BLYNK_CMD_HARDWARE = 20,
25 | BLYNK_CMD_GROUP = 21,
26 |
27 | BLYNK_CMD_HW_LOGIN = 29,
28 |
29 | BLYNK_CMD_REDIRECT = 41,
30 | BLYNK_CMD_DEBUG_PRINT = 55,
31 | BLYNK_CMD_EVENT_LOG = 64,
32 | BLYNK_CMD_EVENT_CLEAR = 65
33 | };
34 |
35 | enum BlynkStatus
36 | {
37 | BLYNK_SUCCESS = 200,
38 | BLYNK_QUOTA_LIMIT_EXCEPTION = 1,
39 | BLYNK_ILLEGAL_COMMAND = 2,
40 | BLYNK_NOT_REGISTERED = 3,
41 | BLYNK_ALREADY_REGISTERED = 4,
42 | BLYNK_NOT_AUTHENTICATED = 5,
43 | BLYNK_NOT_ALLOWED = 6,
44 | BLYNK_DEVICE_NOT_IN_NETWORK = 7,
45 | BLYNK_NO_ACTIVE_DASHBOARD = 8,
46 | BLYNK_INVALID_TOKEN = 9,
47 | BLYNK_ILLEGAL_COMMAND_BODY = 11,
48 | BLYNK_GET_GRAPH_DATA_EXCEPTION = 12,
49 | BLYNK_NO_DATA_EXCEPTION = 17,
50 | BLYNK_DEVICE_WENT_OFFLINE = 18,
51 | BLYNK_SERVER_EXCEPTION = 19,
52 |
53 | BLYNK_NTF_INVALID_BODY = 13,
54 | BLYNK_NTF_NOT_AUTHORIZED = 14,
55 | BLYNK_NTF_ECXEPTION = 15,
56 |
57 | BLYNK_TIMEOUT = 16,
58 |
59 | BLYNK_NOT_SUPPORTED_VERSION = 20,
60 | BLYNK_ENERGY_LIMIT = 21,
61 |
62 | BLYNK_OPERATION_ACCEPT = 23,
63 | BLYNK_OPERATION_DECLINE = 24,
64 | };
65 |
66 | struct BlynkHeader
67 | {
68 | uint8_t type;
69 | uint16_t msg_id;
70 | uint16_t length;
71 | }
72 | BLYNK_ATTR_PACKED;
73 |
74 | #if defined(ESP32) || defined(ESP8266)
75 | #include
76 | #elif !defined(htons) && (defined(ARDUINO) || defined(PARTICLE) || defined(__MBED__))
77 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
78 | #define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) )
79 | #define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \
80 | ((x)<< 8 & 0x00FF0000UL) | \
81 | ((x)>> 8 & 0x0000FF00UL) | \
82 | ((x)>>24 & 0x000000FFUL) )
83 | #define ntohs(x) htons(x)
84 | #define ntohl(x) htonl(x)
85 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
86 | #define htons(x) (x)
87 | #define htonl(x) (x)
88 | #define ntohs(x) (x)
89 | #define ntohl(x) (x)
90 | #else
91 | #error "Byte order not defined"
92 | #endif
93 | #endif
94 |
95 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
96 | #define BLYNK_STR_16(a,b) ((uint16_t(a) << 0) | (uint16_t(b) << 8))
97 | #define BLYNK_STR_32(a,b,c,d) ((uint32_t(a) << 0) | (uint32_t(b) << 8) | (uint32_t(c) << 16) | (uint32_t(d) << 24))
98 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
99 | #define BLYNK_STR_16(a,b) ((uint16_t(b) << 0) | (uint16_t(a) << 8))
100 | #define BLYNK_STR_32(a,b,c,d) ((uint32_t(d) << 0) | (uint32_t(c) << 8) | (uint32_t(b) << 16) | (uint32_t(a) << 24))
101 | #else
102 | #error byte order problem
103 | #endif
104 |
105 | #define BLYNK_HW_PM BLYNK_STR_16('p','m')
106 | #define BLYNK_HW_DW BLYNK_STR_16('d','w')
107 | #define BLYNK_HW_DR BLYNK_STR_16('d','r')
108 | #define BLYNK_HW_AW BLYNK_STR_16('a','w')
109 | #define BLYNK_HW_AR BLYNK_STR_16('a','r')
110 | #define BLYNK_HW_VW BLYNK_STR_16('v','w')
111 | #define BLYNK_HW_VR BLYNK_STR_16('v','r')
112 |
113 | #define BLYNK_INT_RTC BLYNK_STR_32('r','t','c',0)
114 | #define BLYNK_INT_UTC BLYNK_STR_32('u','t','c',0)
115 | #define BLYNK_INT_OTA BLYNK_STR_32('o','t','a',0)
116 | #define BLYNK_INT_VFS BLYNK_STR_32('v','f','s',0)
117 | #define BLYNK_INT_DBG BLYNK_STR_32('d','b','g',0)
118 | #define BLYNK_INT_ACON BLYNK_STR_32('a','c','o','n')
119 | #define BLYNK_INT_ADIS BLYNK_STR_32('a','d','i','s')
120 | #define BLYNK_INT_META BLYNK_STR_32('m','e','t','a')
121 |
122 | #endif
123 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkTemplates.h:
--------------------------------------------------------------------------------
1 | class BlynkStackOnly
2 | {
3 | protected:
4 | BlynkStackOnly() {}
5 | ~BlynkStackOnly() {}
6 |
7 | private:
8 | /// @brief Declared as private to prevent usage of dynamic memory
9 | void* operator new(size_t size);
10 | /// @brief Declared as private to prevent usage of dynamic memory
11 | void operator delete(void *p);
12 | };
13 |
14 | class BlynkNonCopyable
15 | {
16 | protected:
17 | BlynkNonCopyable(){}
18 | ~BlynkNonCopyable(){}
19 |
20 | private:
21 | /// @brief Declared as private to prevent usage of copy constructor
22 | BlynkNonCopyable(const BlynkNonCopyable&);
23 | /// @brief Declared as private to prevent usage of assignment operator
24 | BlynkNonCopyable& operator=(const BlynkNonCopyable&);
25 | };
26 |
27 | template
28 | class BlynkSingleton
29 | : public BlynkNonCopyable
30 | {
31 | public:
32 | /** @brief Returns the instance of the singleton type
33 | When called for the first time, the singleton instance will be
34 | created. All subsequent calls will return a reference to the
35 | previously created instance.
36 | @return The singleton instance
37 | */
38 | static T* instance()
39 | {
40 | static T instance;
41 | return &instance;
42 | }
43 | protected:
44 | BlynkSingleton() {}
45 | ~BlynkSingleton() {}
46 | };
47 |
48 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkTimer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SimpleTimer.h
3 | *
4 | * SimpleTimer - A timer library for Arduino.
5 | * Author: mromani@ottotecnica.com
6 | * Copyright (c) 2010 OTTOTECNICA Italy
7 | *
8 | * Modifications by Bill Knight 18March2017
9 | *
10 | * This library is free software; you can redistribute it
11 | * and/or modify it under the terms of the GNU Lesser
12 | * General Public License as published by the Free Software
13 | * Foundation; either version 2.1 of the License, or (at
14 | * your option) any later version.
15 | *
16 | * This library is distributed in the hope that it will
17 | * be useful, but WITHOUT ANY WARRANTY; without even the
18 | * implied warranty of MERCHANTABILITY or FITNESS FOR A
19 | * PARTICULAR PURPOSE. See the GNU Lesser General Public
20 | * License for more details.
21 | *
22 | * You should have received a copy of the GNU Lesser
23 | * General Public License along with this library; if not,
24 | * write to the Free Software Foundation, Inc.,
25 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 | *
27 | */
28 |
29 | #ifndef BLYNKTIMER_H
30 | #define BLYNKTIMER_H
31 |
32 | #include
33 |
34 | // Replace SimpleTimer
35 | #define SIMPLETIMER_H
36 | #define SimpleTimer BlynkTimer
37 |
38 | #ifndef BLYNK_MAX_TIMERS
39 | #define BLYNK_MAX_TIMERS 16
40 | #endif
41 |
42 | class SimpleTimer {
43 | #ifdef BLYNK_HAS_FUNCTIONAL_H
44 | typedef std::function timer_callback;
45 | #else
46 | typedef void (*timer_callback)(void);
47 | #endif
48 | typedef void (*timer_callback_p)(void *);
49 |
50 | public:
51 | // maximum number of timers
52 | const static int MAX_TIMERS = BLYNK_MAX_TIMERS;
53 |
54 | // setTimer() constants
55 | const static int RUN_FOREVER = 0;
56 | const static int RUN_ONCE = 1;
57 |
58 | class Handle {
59 | public:
60 | Handle()
61 | : st(NULL), id(-1)
62 | {}
63 |
64 | Handle(SimpleTimer* t, int i)
65 | : st(t), id(i)
66 | {}
67 |
68 | ~Handle() {
69 | }
70 |
71 | operator int() const {
72 | return id;
73 | }
74 |
75 | operator bool() const {
76 | return isValid();
77 | }
78 |
79 | void operator() (void) const {
80 | if (isValid()) st->executeNow(id);
81 | }
82 |
83 | bool isValid() const { return st && id >= 0; }
84 | void changeInterval(unsigned long d) {
85 | if (isValid()) st->changeInterval(id, d);
86 | }
87 | void deleteTimer() { if (isValid()) st->deleteTimer(id); invalidate(); }
88 | void restartTimer() { if (isValid()) st->restartTimer(id); }
89 | bool isEnabled() { return isValid() && st->isEnabled(id); }
90 | void enable() { if (isValid()) st->enable(id); }
91 | void disable() { if (isValid()) st->disable(id); }
92 | void toggle() { if (isValid()) st->toggle(id); }
93 |
94 | private:
95 | void invalidate() { st = NULL; id = -1; }
96 |
97 | SimpleTimer* st;
98 | int id;
99 | };
100 |
101 | // constructor
102 | SimpleTimer();
103 |
104 | void init();
105 |
106 | // this function must be called inside loop()
107 | void run();
108 |
109 | // Timer will call function 'f' every 'd' milliseconds forever
110 | // returns the timer number (numTimer) on success or
111 | // -1 on failure (f == NULL) or no free timers
112 | Handle setInterval(unsigned long d, const timer_callback& f) {
113 | return Handle(this, setupTimer(d, f, RUN_FOREVER));
114 | }
115 |
116 | // Timer will call function 'f' with parameter 'p' every 'd' milliseconds forever
117 | // returns the timer number (numTimer) on success or
118 | // -1 on failure (f == NULL) or no free timers
119 | Handle setInterval(unsigned long d, timer_callback_p f, void* p) {
120 | return Handle(this, setupTimer(d, f, p, RUN_FOREVER));
121 | }
122 |
123 | // Timer will call function 'f' after 'd' milliseconds one time
124 | // returns the timer number (numTimer) on success or
125 | // -1 on failure (f == NULL) or no free timers
126 | Handle setTimeout(unsigned long d, const timer_callback& f) {
127 | return Handle(this, setupTimer(d, f, RUN_ONCE));
128 | }
129 |
130 | // Timer will call function 'f' with parameter 'p' after 'd' milliseconds one time
131 | // returns the timer number (numTimer) on success or
132 | // -1 on failure (f == NULL) or no free timers
133 | Handle setTimeout(unsigned long d, timer_callback_p f, void* p) {
134 | return Handle(this, setupTimer(d, f, p, RUN_ONCE));
135 | }
136 |
137 | // Timer will call function 'f' every 'd' milliseconds 'n' times
138 | // returns the timer number (numTimer) on success or
139 | // -1 on failure (f == NULL) or no free timers
140 | Handle setTimer(unsigned long d, const timer_callback& f, unsigned n) {
141 | return Handle(this, setupTimer(d, f, n));
142 | }
143 |
144 | // Timer will call function 'f' with parameter 'p' every 'd' milliseconds 'n' times
145 | // returns the timer number (numTimer) on success or
146 | // -1 on failure (f == NULL) or no free timers
147 | Handle setTimer(unsigned long d, timer_callback_p f, void* p, unsigned n) {
148 | return Handle(this, setupTimer(d, f, p, n));
149 | }
150 |
151 | // updates interval of the specified timer
152 | bool changeInterval(unsigned numTimer, unsigned long d);
153 |
154 | // destroy the specified timer
155 | void deleteTimer(unsigned numTimer);
156 |
157 | // restart the specified timer
158 | void restartTimer(unsigned numTimer);
159 |
160 | // remove delay to next execution
161 | void executeNow(unsigned numTimer);
162 |
163 | // returns true if the specified timer is enabled
164 | bool isEnabled(unsigned numTimer);
165 |
166 | // enables the specified timer
167 | void enable(unsigned numTimer);
168 |
169 | // disables the specified timer
170 | void disable(unsigned numTimer);
171 |
172 | // enables all timers
173 | void enableAll();
174 |
175 | // disables all timers
176 | void disableAll();
177 |
178 | // enables the specified timer if it's currently disabled,
179 | // and vice-versa
180 | void toggle(unsigned numTimer);
181 |
182 | // returns the number of used timers
183 | unsigned getNumTimers();
184 |
185 | // returns the number of available timers
186 | unsigned getNumAvailableTimers() { return MAX_TIMERS - numTimers; };
187 |
188 | private:
189 | // deferred call constants
190 | const static int DEFCALL_DONTRUN = 0; // don't call the callback function
191 | const static int DEFCALL_RUNONLY = 1; // call the callback function but don't delete the timer
192 | const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer
193 |
194 | // low level function to initialize and enable a new timer
195 | // returns the timer number (numTimer) on success or
196 | // -1 on failure (f == NULL) or no free timers
197 | int setupTimer(unsigned long d, const timer_callback& f, unsigned n);
198 | int setupTimer(unsigned long d, timer_callback_p f, void* p, unsigned n);
199 |
200 | bool isValidTimer(unsigned id) {
201 | return timer[id].callback || timer[id].callback_p;
202 | }
203 |
204 | // find the first available slot
205 | int findFirstFreeSlot();
206 |
207 | typedef struct {
208 | unsigned long prev_millis; // value returned by the millis() function in the previous run() call
209 |
210 | timer_callback callback;
211 | timer_callback_p callback_p;
212 |
213 | void* param; // function parameter
214 | bool hasParam; // true if callback takes a parameter
215 | unsigned long delay; // delay value
216 | unsigned maxNumRuns; // number of runs to be executed
217 | unsigned numRuns; // number of executed runs
218 | bool enabled; // true if enabled
219 | unsigned toBeCalled; // deferred function call (sort of) - N.B.: only used in run()
220 | } timer_t;
221 |
222 | timer_t timer[MAX_TIMERS];
223 |
224 | // actual number of timers in use (-1 means uninitialized)
225 | int numTimers;
226 | };
227 |
228 | #endif
229 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkUtility.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkUtility.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jun 2015
7 | * @brief Utility functions
8 | *
9 | */
10 |
11 | #ifndef BlynkUtility_h
12 | #define BlynkUtility_h
13 |
14 | #include
15 |
16 | template
17 | const T& BlynkMin(const T& a, const T& b)
18 | {
19 | return (b < a) ? b : a;
20 | }
21 |
22 | template
23 | const T& BlynkMax(const T& a, const T& b)
24 | {
25 | return (b < a) ? a : b;
26 | }
27 |
28 |
29 | template
30 | T BlynkMathMap(T x, T2 in_min, T2 in_max, T2 out_min, T2 out_max)
31 | {
32 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
33 | }
34 |
35 | template
36 | T BlynkMathClamp(T val, T2 low, T2 high)
37 | {
38 | return (val < low) ? low : ((val > high) ? high : val);
39 | }
40 |
41 | template
42 | T BlynkMathClampMap(T x, T2 in_min, T2 in_max, T2 out_min, T2 out_max)
43 | {
44 | x = BlynkMathClamp(x, in_min, in_max);
45 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
46 | }
47 |
48 | template
49 | class BlynkMovingAverage {
50 | public:
51 | BlynkMovingAverage() {
52 | reset();
53 | }
54 |
55 | void reset() {
56 | _first = true;
57 | _avg = 0;
58 | }
59 |
60 | bool hasValue() const {
61 | return !_first;
62 | }
63 |
64 | T get() const {
65 | return _avg;
66 | }
67 |
68 | double getFloat() const {
69 | return _avg;
70 | }
71 |
72 | T push(T value) {
73 | if (_first) {
74 | _avg = value;
75 | _first = false;
76 | } else {
77 | _avg -= _avg/N;
78 | _avg += double(value)/N;
79 | }
80 | return _avg;
81 | }
82 |
83 | private:
84 | bool _first;
85 | double _avg;
86 | };
87 |
88 | template
89 | void BlynkAverageSample (T& avg, const T& input) {
90 | avg -= avg/WSIZE;
91 | const T add = input/WSIZE;
92 | // Fix for shorter delays
93 | if (add > 0)
94 | avg += add;
95 | else
96 | avg -= 1;
97 | }
98 |
99 | static inline
100 | int BlynkRSSI2SQ(int dBm) {
101 | if(dBm <= -100) {
102 | return 0;
103 | } else if(dBm >= -50) {
104 | return 100;
105 | } else {
106 | return 2 * (dBm + 100);
107 | }
108 | }
109 |
110 | static inline
111 | int BlynkSQ2RSSI(int quality) {
112 | if(quality <= 0) {
113 | return -100;
114 | } else if(quality >= 100) {
115 | return -50;
116 | } else {
117 | return (quality / 2) - 100;
118 | }
119 | }
120 |
121 | static inline
122 | uint32_t BlynkCRC32(const void* data, size_t length, uint32_t previousCrc32 = 0)
123 | {
124 | const uint32_t Polynomial = 0xEDB88320;
125 | uint32_t crc = ~previousCrc32;
126 | unsigned char* current = (unsigned char*)data;
127 | while (length--) {
128 | crc ^= *current++;
129 | for (unsigned int j = 0; j < 8; j++) {
130 | crc = (crc >> 1) ^ (-int(crc & 1) & Polynomial);
131 | }
132 | }
133 | return ~crc;
134 | }
135 |
136 | static inline
137 | bool BlynkStrMatch(const char* pat, const char* txt) {
138 | const long n = strlen(txt);
139 | const long m = strlen(pat);
140 |
141 | if (m == 0)
142 | return (n == 0);
143 |
144 | long i = 0, j = 0, index_txt = -1,
145 | index_pat = -1;
146 |
147 | while (i < n) {
148 | if (j < m && txt[i] == pat[j]) {
149 | i++;
150 | j++;
151 | } else if (j < m && pat[j] == '?') {
152 | i++;
153 | j++;
154 | } else if (j < m && pat[j] == '*') {
155 | index_txt = i;
156 | index_pat = j;
157 | j++;
158 | } else if (index_pat != -1) {
159 | j = index_pat + 1;
160 | i = index_txt + 1;
161 | index_txt++;
162 | } else {
163 | return false;
164 | }
165 | }
166 |
167 | while (j < m && pat[j] == '*') {
168 | j++;
169 | }
170 |
171 | if (j == m) {
172 | return true;
173 | }
174 |
175 | return false;
176 | }
177 |
178 | class BlynkHelperAutoInc {
179 | public:
180 | BlynkHelperAutoInc(uint8_t& counter) : c(counter) { ++c; }
181 | ~BlynkHelperAutoInc() { --c; }
182 | private:
183 | uint8_t& c;
184 | };
185 |
186 | #define BlynkBitSet(value, bit) ((value) |= (1UL << (bit)))
187 | #define BlynkBitClear(value, bit) ((value) &= ~(1UL << (bit)))
188 | #define BlynkBitRead(value, bit) (((value) >> (bit)) & 0x01)
189 | #define BlynkBitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
190 |
191 | #endif
192 |
--------------------------------------------------------------------------------
/src/Blynk/BlynkWidgetBase.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkWidgetBase.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2016 Volodymyr Shymanskyy
6 | * @date Nov 2016
7 | * @brief
8 | */
9 |
10 | #ifndef BlynkWidgetBase_h
11 | #define BlynkWidgetBase_h
12 |
13 | #include
14 |
15 | class BlynkWidgetBase
16 | {
17 | public:
18 | BlynkWidgetBase(uint8_t vPin) : mPin(vPin) {}
19 | void setVPin(uint8_t vPin) { mPin = vPin; }
20 |
21 | void onWrite(BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED ¶m) {
22 | BLYNK_LOG1(BLYNK_F("BlynkWidgetBase::onWrite should not be called"));
23 | }
24 |
25 | template
26 | void setLabel(Args... args) {
27 | Blynk.setProperty(mPin, "label", args...);
28 | }
29 |
30 | template
31 | void setColor(Args... args) {
32 | Blynk.setProperty(mPin, "color", args...);
33 | }
34 |
35 | template
36 | void setMin(Args... args) {
37 | Blynk.setProperty(mPin, "min", args...);
38 | }
39 |
40 | template
41 | void setMax(Args... args) {
42 | Blynk.setProperty(mPin, "max", args...);
43 | }
44 |
45 | protected:
46 | uint8_t mPin;
47 | };
48 |
49 | class BlynkAttachWidgetHelper {
50 | public:
51 | template
52 | explicit BlynkAttachWidgetHelper(T& widget, uint8_t vPin) {
53 | widget.setVPin(vPin);
54 | }
55 | };
56 |
57 | // Could use __attribute__ ((constructor)), but hope for better portability
58 | #define BLYNK_ATTACH_WIDGET(widget, pin) \
59 | BlynkAttachWidgetHelper BLYNK_CONCAT2(blnk_widget_helper_, __COUNTER__)((widget), (pin)); \
60 | BLYNK_WRITE(pin) { (widget).onWrite(request, param); }
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/src/BlynkApiParticle.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkApiParticle.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Mar 2015
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkApiParticle_h
12 | #define BlynkApiParticle_h
13 |
14 | #include "Blynk/BlynkApi.h"
15 | #include "Particle.h"
16 |
17 | template
18 | BLYNK_FORCE_INLINE
19 | void BlynkApi::sendInfo()
20 | {
21 | static const char profile[] BLYNK_PROGMEM = "blnkinf\0"
22 |
23 | // Firmware info
24 | #if defined(BLYNK_NCP_VERSION)
25 | BLYNK_PARAM_KV("ncp" , BLYNK_NCP_VERSION)
26 | #else
27 | BLYNK_PARAM_KV("mcu" , BLYNK_FIRMWARE_VERSION)
28 | #endif
29 | #ifdef BLYNK_FIRMWARE_TYPE
30 | BLYNK_PARAM_KV("fw-type", BLYNK_FIRMWARE_TYPE)
31 | #endif
32 | BLYNK_PARAM_KV("build" , __DATE__ " " __TIME__)
33 | BLYNK_PARAM_KV("blynk" , BLYNK_VERSION)
34 |
35 | // Protocol setup
36 | BLYNK_PARAM_KV("h-beat" , BLYNK_TOSTRING(BLYNK_HEARTBEAT))
37 | BLYNK_PARAM_KV("buff-in", BLYNK_TOSTRING(BLYNK_MAX_READBYTES))
38 |
39 | // Additional info
40 | #ifdef BLYNK_INFO_DEVICE
41 | BLYNK_PARAM_KV("dev" , BLYNK_INFO_DEVICE)
42 | #endif
43 | #ifdef BLYNK_INFO_CPU
44 | BLYNK_PARAM_KV("cpu" , BLYNK_INFO_CPU)
45 | #endif
46 | #ifdef BLYNK_INFO_CONNECTION
47 | BLYNK_PARAM_KV("con" , BLYNK_INFO_CONNECTION)
48 | #endif
49 | "\0"
50 | ;
51 | const size_t profile_len = sizeof(profile)-8-2;
52 |
53 | char mem_dyn[64];
54 | BlynkParam profile_dyn(mem_dyn, 0, sizeof(mem_dyn));
55 | #ifdef BLYNK_TEMPLATE_ID
56 | {
57 | const char* tmpl = BLYNK_TEMPLATE_ID;
58 | if (tmpl && strlen(tmpl)) {
59 | profile_dyn.add_key("tmpl", tmpl);
60 | }
61 | }
62 | #endif
63 |
64 | #ifdef BLYNK_HAS_PROGMEM
65 | char mem[profile_len];
66 | memcpy_P(mem, profile+8, profile_len);
67 | static_cast(this)->sendCmd(BLYNK_CMD_INTERNAL, 0, mem, profile_len, profile_dyn.getBuffer(), profile_dyn.getLength()-1);
68 | #else
69 | static_cast(this)->sendCmd(BLYNK_CMD_INTERNAL, 0, profile+8, profile_len, profile_dyn.getBuffer(), profile_dyn.getLength()-1);
70 | #endif
71 | return;
72 | }
73 |
74 |
75 | // Check if analog pins can be referenced by name on this device
76 | #if defined(analogInputToDigitalPin)
77 | #define BLYNK_DECODE_PIN(it) (((it).asStr()[0] == 'A') ? analogInputToDigitalPin(atoi((it).asStr()+1)) : (it).asInt())
78 | #else
79 | #define BLYNK_DECODE_PIN(it) ((it).asInt())
80 |
81 | #if defined(BLYNK_DEBUG_ALL)
82 | #pragma message "analogInputToDigitalPin not defined"
83 | #endif
84 | #endif
85 |
86 | template
87 | BLYNK_FORCE_INLINE
88 | void BlynkApi::processCmd(const void* buff, size_t len)
89 | {
90 | BlynkParam param((void*)buff, len);
91 | BlynkParam::iterator it = param.begin();
92 | if (it >= param.end())
93 | return;
94 | const char* cmd = it.asStr();
95 | uint16_t cmd16;
96 | memcpy(&cmd16, cmd, sizeof(cmd16));
97 | if (++it >= param.end())
98 | return;
99 |
100 | const uint8_t pin = BLYNK_DECODE_PIN(it);
101 |
102 | switch(cmd16) {
103 |
104 | #ifndef BLYNK_NO_BUILTIN
105 |
106 | case BLYNK_HW_PM: {
107 | while (it < param.end()) {
108 | const uint8_t pin = BLYNK_DECODE_PIN(it);
109 | ++it;
110 | if (!strcmp(it.asStr(), "in")) {
111 | pinMode(pin, INPUT);
112 | } else if (!strcmp(it.asStr(), "out") || !strcmp(it.asStr(), "pwm")) {
113 | pinMode(pin, OUTPUT);
114 | #ifdef INPUT_PULLUP
115 | } else if (!strcmp(it.asStr(), "pu")) {
116 | pinMode(pin, INPUT_PULLUP);
117 | #endif
118 | #ifdef INPUT_PULLDOWN
119 | } else if (!strcmp(it.asStr(), "pd")) {
120 | pinMode(pin, INPUT_PULLDOWN);
121 | #endif
122 | } else {
123 | #ifdef BLYNK_DEBUG
124 | BLYNK_LOG4(BLYNK_F("Invalid pin "), pin, BLYNK_F(" mode "), it.asStr());
125 | #endif
126 | }
127 | ++it;
128 | }
129 | } break;
130 | case BLYNK_HW_DR: {
131 | char mem[16];
132 | BlynkParam rsp(mem, 0, sizeof(mem));
133 | rsp.add("dw");
134 | rsp.add(pin);
135 | rsp.add(digitalRead(pin));
136 | static_cast(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, rsp.getBuffer(), rsp.getLength()-1);
137 | } break;
138 | case BLYNK_HW_DW: {
139 | // Should be 1 parameter (value)
140 | if (++it >= param.end())
141 | return;
142 |
143 | #ifdef ESP8266
144 | // Disable PWM...
145 | analogWrite(pin, 0);
146 | #endif
147 | #ifndef BLYNK_MINIMIZE_PINMODE_USAGE
148 | pinMode(pin, OUTPUT);
149 | #endif
150 | digitalWrite(pin, it.asInt() ? HIGH : LOW);
151 | } break;
152 | case BLYNK_HW_AR: {
153 | char mem[16];
154 | BlynkParam rsp(mem, 0, sizeof(mem));
155 | rsp.add("aw");
156 | rsp.add(pin);
157 | rsp.add(analogRead(pin));
158 | static_cast(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, rsp.getBuffer(), rsp.getLength()-1);
159 | } break;
160 | case BLYNK_HW_AW: {
161 | // Should be 1 parameter (value)
162 | if (++it >= param.end())
163 | return;
164 |
165 | #ifndef BLYNK_MINIMIZE_PINMODE_USAGE
166 | pinMode(pin, OUTPUT);
167 | #endif
168 | analogWrite(pin, it.asInt());
169 | } break;
170 |
171 | #endif
172 |
173 | case BLYNK_HW_VR: {
174 | BlynkReq req = { pin };
175 | callReadHandler(req);
176 | } break;
177 | case BLYNK_HW_VW: {
178 | ++it;
179 | char* start = (char*)it.asStr();
180 | BlynkParam param2(start, len - (start - (char*)buff));
181 | BlynkReq req = { pin };
182 | callWriteHandler(req, param2);
183 | } break;
184 | default:
185 | BLYNK_LOG2(BLYNK_F("Invalid HW cmd: "), cmd);
186 | static_cast(this)->sendCmd(BLYNK_CMD_RESPONSE, static_cast(this)->msgIdOutOverride, NULL, BLYNK_ILLEGAL_COMMAND);
187 | }
188 | }
189 |
190 | #endif
191 |
--------------------------------------------------------------------------------
/src/BlynkMultiClient.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkMultiClient.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2022 Volodymyr Shymanskyy
6 | * @date Oct 2022
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkMultiClient_h
12 | #define BlynkMultiClient_h
13 |
14 | static const char BLYNK_DEFAULT_ROOT_CA[] =
15 | #include
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #ifndef BLYNK_MAX_CLIENT_QTY
22 | #define BLYNK_MAX_CLIENT_QTY 4
23 | #endif
24 |
25 | template
26 | class BlynkArduinoClientMulti
27 | : public BlynkArduinoClientGen
28 | {
29 | struct Entry {
30 | String name;
31 | T* client;
32 | uint16_t port;
33 | };
34 | public:
35 | BlynkArduinoClientMulti() {}
36 |
37 | void addClient(const String& name, T& c, uint16_t port = BLYNK_DEFAULT_PORT_SSL) {
38 | if (_conn_qty == 0) {
39 | BlynkArduinoClientGen::setClient(&c);
40 | BlynkArduinoClientGen::port = port;
41 | }
42 | if (_conn_qty < BLYNK_MAX_CLIENT_QTY) {
43 | Entry& e = _conn_array[_conn_qty++];
44 | e.name = name;
45 | e.client = &c;
46 | e.port = port;
47 | }
48 | }
49 |
50 | bool connect() {
51 | for (int i = 0; i < _conn_qty; i++) {
52 | BlynkArduinoClientGen::setClient(_conn_array[i].client);
53 | BlynkArduinoClientGen::port = _conn_array[i].port;
54 | if (BlynkArduinoClientGen::connect()) {
55 | BLYNK_LOG2(_conn_array[i].name, BLYNK_F(" connection OK"));
56 | return true;
57 | } else {
58 | BLYNK_LOG2(_conn_array[i].name, BLYNK_F(" connection failed"));
59 | }
60 | }
61 | return false;
62 | }
63 |
64 | void disconnect() {
65 | BlynkArduinoClientGen::isConn = false;
66 | for (int i = 0; i < _conn_qty; i++) {
67 | _conn_array[i].client->stop();
68 | }
69 | }
70 |
71 | private:
72 | Entry _conn_array[BLYNK_MAX_CLIENT_QTY];
73 | int _conn_qty = 0;
74 | };
75 |
76 | template
77 | class BlynkMultiClient
78 | : public BlynkProtocol
79 | {
80 | typedef BlynkProtocol Base;
81 | public:
82 | BlynkMultiClient(Transport& transp)
83 | : Base(transp)
84 | {}
85 |
86 | template
87 | void addClient(const String& name, T& client, uint16_t port = BLYNK_DEFAULT_PORT_SSL) {
88 | this->conn.addClient(name, client, port);
89 | }
90 |
91 | void config(const char* auth,
92 | const char* domain = BLYNK_DEFAULT_DOMAIN)
93 | {
94 | Base::begin(auth);
95 | this->conn.begin(domain, 0);
96 | }
97 |
98 | void config(const char* auth,
99 | IPAddress ip)
100 | {
101 | Base::begin(auth);
102 | this->conn.begin(ip, 0);
103 | }
104 |
105 | };
106 |
107 | typedef BlynkArduinoClientMulti BlynkTransport;
108 |
109 | #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_BLYNK)
110 | static BlynkTransport _blynkTransport;
111 |
112 | BlynkMultiClient Blynk(_blynkTransport);
113 | #else
114 | extern BlynkMultiClient Blynk;
115 | #endif
116 |
117 | #include
118 |
119 | #endif
120 |
--------------------------------------------------------------------------------
/src/BlynkSimpleParticle.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkSimpleParticle.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Mar 2015
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkSimpleParticle_h
12 | #define BlynkSimpleParticle_h
13 |
14 | #include
15 |
16 | #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_BLYNK)
17 | static BlynkTransportParticle _blynkTransport;
18 | BlynkParticle Blynk(_blynkTransport);
19 | #else
20 | extern BlynkParticle Blynk;
21 | #endif
22 |
23 | #include "BlynkWidgets.h"
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/src/BlynkSimpleParticleSSL.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkSimpleParticle.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2022 Volodymyr Shymanskyy
6 | * @date Mar 2022
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkSimpleParticle_h
12 | #define BlynkSimpleParticle_h
13 |
14 | #include
15 |
16 | #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_BLYNK)
17 | static BlynkTransportParticle _blynkTransport;
18 | BlynkParticle Blynk(_blynkTransport);
19 | #else
20 | extern BlynkParticle Blynk;
21 | #endif
22 |
23 | #include
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/src/BlynkSimpleSerialBLE.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkSerialBLE.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2016 Volodymyr Shymanskyy
6 | * @date Mar 2016
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkSerialBLE_h
12 | #define BlynkSerialBLE_h
13 |
14 | #ifndef BLYNK_INFO_CONNECTION
15 | #define BLYNK_INFO_CONNECTION "SerialBLE"
16 | #endif
17 |
18 | #define BLYNK_SEND_ATOMIC
19 | #define BLYNK_SEND_CHUNK 20
20 | #define BLYNK_SEND_THROTTLE 40
21 | #define BLYNK_NO_INFO
22 |
23 | #include
24 |
25 | #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_BLYNK)
26 | BlynkTransportStream _blynkTransport;
27 | BlynkStream Blynk(_blynkTransport);
28 | #else
29 | extern BlynkStream Blynk;
30 | #endif
31 |
32 | #include
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/src/BlynkSimpleStream.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkSimpleStream.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2016 Volodymyr Shymanskyy
6 | * @date Mar 2016
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef BlynkSimpleStream_h
12 | #define BlynkSimpleStream_h
13 |
14 | #ifndef BLYNK_INFO_CONNECTION
15 | #define BLYNK_INFO_CONNECTION "Stream"
16 | #endif
17 |
18 | #include
19 |
20 | #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_BLYNK)
21 | BlynkTransportStream _blynkTransport;
22 | BlynkStream Blynk(_blynkTransport);
23 | #else
24 | extern BlynkStream Blynk;
25 | #endif
26 |
27 | #include
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/src/BlynkWidgets.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkWidgets.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Mar 2015
7 | * @brief
8 | */
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | // Cannot auto-include as these have library dependencies
17 | //#include
18 |
19 | template
20 | class VPinWriteOnChange {
21 | T prev;
22 | const int vpin;
23 | public:
24 | VPinWriteOnChange(int v)
25 | : vpin(v)
26 | {}
27 |
28 | VPinWriteOnChange& operator= (const T& value) {
29 | update(value);
30 | return *this;
31 | }
32 |
33 | void set(const T& value) {
34 | prev = value;
35 | }
36 |
37 | void update(const T& value) {
38 | if (value != prev) {
39 | prev = value;
40 | report();
41 | }
42 | }
43 |
44 | void report() {
45 | Blynk.virtualWrite(vpin, prev);
46 | }
47 | };
48 |
--------------------------------------------------------------------------------
/src/WidgetLCD.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file WidgetLCD.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Mar 2015
7 | * @brief
8 | */
9 |
10 | #ifndef WidgetLCD_h
11 | #define WidgetLCD_h
12 |
13 | #include
14 |
15 | class WidgetLCD
16 | : public BlynkWidgetBase
17 | {
18 | public:
19 | WidgetLCD(uint8_t vPin) : BlynkWidgetBase(vPin) {}
20 |
21 | void clear() {
22 | Blynk.virtualWrite(mPin, "clr");
23 | }
24 |
25 | template
26 | void print(int x, int y, const T& str) {
27 | char mem[BLYNK_MAX_SENDBYTES];
28 | BlynkParam cmd(mem, 0, sizeof(mem));
29 | cmd.add("p");
30 | cmd.add(x);
31 | cmd.add(y);
32 | cmd.add(str);
33 | Blynk.virtualWrite(mPin, cmd);
34 | }
35 |
36 | };
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/src/WidgetLED.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file WidgetLED.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Apr 2015
7 | * @brief
8 | */
9 |
10 | #ifndef WidgetLED_h
11 | #define WidgetLED_h
12 |
13 | #include
14 |
15 | class WidgetLED
16 | : public BlynkWidgetBase
17 | {
18 | public:
19 | WidgetLED(uint8_t vPin)
20 | : BlynkWidgetBase(vPin)
21 | , mValue(0)
22 | {}
23 |
24 | uint8_t getValue() const {
25 | return mValue;
26 | }
27 |
28 | void setValue(uint8_t value) {
29 | mValue = value;
30 | Blynk.virtualWrite(mPin, value);
31 | }
32 |
33 | void on() {
34 | setValue(255);
35 | }
36 |
37 | void off() {
38 | setValue(0);
39 | }
40 |
41 | private:
42 | uint8_t mValue;
43 | };
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/src/WidgetMap.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file WidgetMap.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2016 Volodymyr Shymanskyy
6 | * @date Nov 2016
7 | * @brief
8 | */
9 |
10 | #ifndef WidgetMap_h
11 | #define WidgetMap_h
12 |
13 | #include
14 |
15 | class WidgetMap
16 | : public BlynkWidgetBase
17 | {
18 | public:
19 | WidgetMap(uint8_t vPin) : BlynkWidgetBase(vPin) {}
20 |
21 | void clear() {
22 | Blynk.virtualWrite(mPin, "clr");
23 | }
24 |
25 | template
26 | void location(const T1& index, const T2& lat, const T3& lon, const T4& value) {
27 | Blynk.virtualWrite(mPin, index, lat, lon, value);
28 | }
29 |
30 | };
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/src/WidgetTerminal.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file WidgetTerminal.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief
8 | */
9 |
10 | #ifndef WidgetTerminal_h
11 | #define WidgetTerminal_h
12 |
13 | #ifndef BLYNK_TERMINAL_BUFF_OUT
14 | #define BLYNK_TERMINAL_BUFF_OUT 250
15 | #endif
16 | #ifndef BLYNK_TERMINAL_BUFF_IN
17 | #define BLYNK_TERMINAL_BUFF_IN BLYNK_MAX_READBYTES
18 | #endif
19 |
20 | #if defined(ARDUINO) && !(defined(LINUX) || defined(__MBED__))
21 | #define BLYNK_USE_STREAM_CLASS
22 | #elif defined(SPARK) || defined(PARTICLE)
23 | #define BLYNK_USE_STREAM_CLASS
24 | #endif
25 |
26 | #include
27 | #include
28 |
29 | #ifdef BLYNK_USE_STREAM_CLASS
30 | #include
31 | #endif
32 |
33 | class WidgetTerminal
34 | : public BlynkWidgetBase
35 | #ifdef BLYNK_USE_STREAM_CLASS
36 | , public Stream
37 | #endif
38 | {
39 | public:
40 | WidgetTerminal(uint8_t vPin = -1)
41 | : BlynkWidgetBase(vPin)
42 | , mOutQty(0)
43 | {}
44 |
45 | virtual ~WidgetTerminal() {}
46 |
47 | /*
48 | * Writing
49 | */
50 |
51 | virtual size_t write(uint8_t byte) {
52 | mOutBuf[mOutQty++] = byte;
53 | if (byte == '\n' && Blynk.connected()) {
54 | flush();
55 | }
56 | if (mOutQty >= sizeof(mOutBuf)) {
57 | flush();
58 | }
59 | return 1;
60 | }
61 |
62 | virtual void flush() {
63 | if (mOutQty) {
64 | Blynk.virtualWriteBinary(mPin, mOutBuf, mOutQty);
65 | mOutQty = 0;
66 | }
67 | }
68 |
69 | /*
70 | * Reading
71 | */
72 |
73 | virtual int read() { return mRxBuff.readable() ? mRxBuff.get() : -1; }
74 | virtual int available() { return mRxBuff.size(); }
75 | virtual int peek() { return mRxBuff.readable() ? mRxBuff.peek() : -1; }
76 |
77 | void process(const BlynkParam& param) {
78 | mRxBuff.put((uint8_t*)param.getBuffer(), param.getLength());
79 |
80 | if (mAppendCR) { mRxBuff.put('\r'); }
81 | if (mAppendLF) { mRxBuff.put('\n'); }
82 | }
83 |
84 | void onWrite(BlynkReq BLYNK_UNUSED &request, const BlynkParam& param) {
85 | process(param);
86 | }
87 |
88 | /*
89 | * Extra
90 | */
91 |
92 | void clear() {
93 | mOutQty = 0;
94 | Blynk.virtualWrite(mPin, "clr");
95 | }
96 |
97 | // Append '\r' on input
98 | void autoAppendCR(bool v = true) {
99 | mAppendCR = v;
100 | }
101 |
102 | // Append '\n' on input
103 | void autoAppendLF(bool v = true) {
104 | mAppendLF = v;
105 | }
106 |
107 | #ifdef BLYNK_USE_STREAM_CLASS
108 |
109 | using Stream::write;
110 |
111 | virtual size_t write(const void* buff, size_t len) {
112 | return write((char*)buff, len);
113 | }
114 |
115 | #else
116 |
117 | virtual size_t write(const void* buff, size_t len) {
118 | uint8_t* buf = (uint8_t*)buff;
119 | size_t left = len;
120 | while (left--) {
121 | write(*buf++);
122 | }
123 | return len;
124 | }
125 |
126 | virtual size_t write(const char* str) {
127 | return write(str, strlen(str));
128 | }
129 |
130 | #endif
131 |
132 | private:
133 | typedef BlynkFifo InputFifo;
134 |
135 | bool mAppendCR = false;
136 | bool mAppendLF = false;
137 | InputFifo mRxBuff;
138 |
139 | uint8_t mOutBuf[BLYNK_TERMINAL_BUFF_OUT];
140 | unsigned mOutQty;
141 | };
142 |
143 | #endif
144 |
--------------------------------------------------------------------------------
/src/WidgetTimeInput.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file WidgetTimeInput.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Aug 2016
7 | * @brief
8 | *
9 | */
10 |
11 | #ifndef WidgetTimeInput_h
12 | #define WidgetTimeInput_h
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | class TimeInputParam
19 | {
20 | public:
21 | enum TimeMode {
22 | TIME_UNDEFINED,
23 | TIME_SUNSET,
24 | TIME_SUNRISE,
25 | TIME_SPECIFIED
26 | };
27 |
28 | TimeInputParam(const BlynkParam& param)
29 | {
30 | mStartMode = TIME_UNDEFINED;
31 | mStopMode = TIME_UNDEFINED;
32 | mTZ[0] = '\0';
33 | mWeekdays = -1; // All set
34 | mTZ_Offset = 0;
35 |
36 | BlynkParam::iterator it = param.begin();
37 | if (it >= param.end())
38 | return;
39 |
40 | if (0 == strcmp(it.asStr(), "sr")) {
41 | mStartMode = TIME_SUNRISE;
42 | } else if (0 == strcmp(it.asStr(), "ss")) {
43 | mStartMode = TIME_SUNSET;
44 | } else if (!it.isEmpty()) {
45 | mStart = BlynkTime(it.asLong());
46 | if (mStart.isValid()) {
47 | mStartMode = TIME_SPECIFIED;
48 | }
49 | }
50 |
51 | if (++it >= param.end())
52 | return;
53 |
54 | if (0 == strcmp(it.asStr(), "sr")) {
55 | mStopMode = TIME_SUNRISE;
56 | } else if (0 == strcmp(it.asStr(), "ss")) {
57 | mStopMode = TIME_SUNSET;
58 | } else if (!it.isEmpty()) {
59 | mStop = BlynkTime(it.asLong());
60 | if (mStop.isValid()) {
61 | mStopMode = TIME_SPECIFIED;
62 | }
63 | }
64 |
65 | if (++it >= param.end())
66 | return;
67 |
68 | strncpy(mTZ, it.asStr(), sizeof(mTZ));
69 |
70 | if (++it >= param.end())
71 | return;
72 |
73 | if (!it.isEmpty()) {
74 | mWeekdays = 0;
75 | const char* p = it.asStr();
76 |
77 | while (int c = *p++) {
78 | if (c >= '1' && c <= '7') {
79 | BlynkBitSet(mWeekdays, c - '1');
80 | }
81 | }
82 | }
83 |
84 | if (++it >= param.end())
85 | return;
86 |
87 | mTZ_Offset = it.asLong();
88 | }
89 |
90 | BlynkTime& getStart() { return mStart; }
91 | BlynkTime& getStop() { return mStop; }
92 |
93 | TimeMode getStartMode() const { return mStartMode; }
94 | TimeMode getStopMode() const { return mStopMode; }
95 |
96 | bool hasStartTime() const { return mStartMode == TIME_SPECIFIED; }
97 | bool isStartSunrise() const { return mStartMode == TIME_SUNRISE; }
98 | bool isStartSunset() const { return mStartMode == TIME_SUNSET; }
99 | int getStartHour() const { return mStart.hour(); }
100 | int getStartMinute() const { return mStart.minute(); }
101 | int getStartSecond() const { return mStart.second(); }
102 |
103 | bool hasStopTime() const { return mStopMode == TIME_SPECIFIED; }
104 | bool isStopSunrise() const { return mStopMode == TIME_SUNRISE; }
105 | bool isStopSunset() const { return mStopMode == TIME_SUNSET; }
106 | int getStopHour() const { return mStop.hour(); }
107 | int getStopMinute() const { return mStop.minute(); }
108 | int getStopSecond() const { return mStop.second(); }
109 |
110 | const char* getTZ() const { return mTZ; }
111 | int32_t getTZ_Offset() const { return mTZ_Offset; }
112 |
113 | bool isWeekdaySelected(int day) const {
114 | return BlynkBitRead(mWeekdays, (day - 1) % 7);
115 | }
116 |
117 | private:
118 | BlynkTime mStart;
119 | BlynkTime mStop;
120 | char mTZ[32];
121 | int32_t mTZ_Offset;
122 |
123 | TimeMode mStopMode;
124 | TimeMode mStartMode;
125 |
126 | uint8_t mWeekdays;
127 | };
128 |
129 | #endif
130 |
--------------------------------------------------------------------------------
/src/blynk.cpp:
--------------------------------------------------------------------------------
1 | // We don't use this cpp file...
2 |
--------------------------------------------------------------------------------
/src/blynk.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file Blynk.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Nov 2016
7 | * @brief
8 | *
9 | */
10 |
11 | #include "BlynkSimpleParticle.h"
12 |
13 |
--------------------------------------------------------------------------------
/src/utility/BlynkDateTime.h:
--------------------------------------------------------------------------------
1 |
2 | #warning "Please include Blynk/BlynkDateTime.h, instead of utility/BlynkDateTime.h"
3 | #include
4 |
--------------------------------------------------------------------------------
/src/utility/BlynkDebug.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkDebug.cpp
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief Debug utilities for Arduino
8 | */
9 | #include
10 |
11 | #if defined(ARDUINO) && defined(__AVR__) && defined(BLYNK_USE_AVR_WDT)
12 |
13 | #include
14 | #include
15 |
16 | BLYNK_CONSTRUCTOR
17 | static void BlynkSystemInit()
18 | {
19 | MCUSR = 0;
20 | wdt_disable();
21 | }
22 |
23 | void BlynkReset()
24 | {
25 | wdt_enable(WDTO_15MS);
26 | delay(50);
27 | void(*resetFunc)(void) = 0;
28 | resetFunc();
29 | for(;;) {} // To make compiler happy
30 | }
31 |
32 | size_t BlynkFreeRam()
33 | {
34 | extern int __heap_start, *__brkval;
35 | int v;
36 | return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
37 | }
38 |
39 | #define _BLYNK_USE_DEFAULT_MILLIS
40 | #define _BLYNK_USE_DEFAULT_DELAY
41 |
42 | #elif defined(ARDUINO) && defined(__AVR__)
43 |
44 | #include
45 |
46 | void BlynkReset()
47 | {
48 | void(*resetFunc)(void) = 0;
49 | resetFunc();
50 | for(;;) {}
51 | }
52 |
53 | size_t BlynkFreeRam()
54 | {
55 | extern int __heap_start, *__brkval;
56 | int v;
57 | return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
58 | }
59 |
60 | #define _BLYNK_USE_DEFAULT_MILLIS
61 | #define _BLYNK_USE_DEFAULT_DELAY
62 |
63 | #elif defined(ARDUINO) && (defined(ESP8266) || defined(ESP32))
64 |
65 | #include
66 |
67 | size_t BlynkFreeRam()
68 | {
69 | return ESP.getFreeHeap();
70 | }
71 |
72 | void BlynkReset()
73 | {
74 | ESP.restart();
75 | for(;;) {}
76 | }
77 |
78 | #define _BLYNK_USE_DEFAULT_MILLIS
79 | #define _BLYNK_USE_DEFAULT_DELAY
80 |
81 | #elif defined(ARDUINO_ARCH_RP2040) && !defined(__MBED__)
82 |
83 | #include
84 |
85 | void BlynkReset()
86 | {
87 | rp2040.reboot();
88 | for(;;) {}
89 | }
90 |
91 | #define _BLYNK_USE_DEFAULT_FREE_RAM
92 | #define _BLYNK_USE_DEFAULT_MILLIS
93 | #define _BLYNK_USE_DEFAULT_DELAY
94 |
95 | #elif defined(ARDUINO_ARCH_SAMD) || \
96 | defined(ARDUINO_ARCH_SAM) || \
97 | defined(ARDUINO_ARCH_NRF5)
98 |
99 | #include
100 |
101 | extern "C" char *sbrk(int i);
102 |
103 | size_t BlynkFreeRam()
104 | {
105 | char stack_dummy = 0;
106 | return &stack_dummy - sbrk(0);
107 | }
108 |
109 | void BlynkReset()
110 | {
111 | NVIC_SystemReset();
112 | for(;;) {}
113 | }
114 |
115 | #define _BLYNK_USE_DEFAULT_MILLIS
116 | #define _BLYNK_USE_DEFAULT_DELAY
117 |
118 | #elif defined (ARDUINO_ARCH_ARC32)
119 |
120 | millis_time_t BlynkMillis()
121 | {
122 | // TODO: Remove workaround for Intel Curie
123 | // https://forum.arduino.cc/index.php?topic=391836.0
124 | noInterrupts();
125 | uint64_t t = millis();
126 | interrupts();
127 | return t;
128 | }
129 |
130 | #define _BLYNK_USE_DEFAULT_FREE_RAM
131 | #define _BLYNK_USE_DEFAULT_RESET
132 | #define _BLYNK_USE_DEFAULT_DELAY
133 |
134 | #elif defined(ARDUINO) && (defined(__STM32F1__) || defined(__STM32F3__))
135 |
136 | #include
137 | #include
138 |
139 | void BlynkReset()
140 | {
141 | nvic_sys_reset();
142 | for(;;) {}
143 | }
144 |
145 | #define _BLYNK_USE_DEFAULT_FREE_RAM
146 | #define _BLYNK_USE_DEFAULT_MILLIS
147 | #define _BLYNK_USE_DEFAULT_DELAY
148 |
149 | #elif defined (PARTICLE) || defined(SPARK)
150 |
151 | #include "application.h"
152 |
153 | void BlynkReset()
154 | {
155 | System.reset();
156 | for(;;) {} // To make compiler happy
157 | }
158 |
159 | #define _BLYNK_USE_DEFAULT_FREE_RAM
160 | #define _BLYNK_USE_DEFAULT_MILLIS
161 | #define _BLYNK_USE_DEFAULT_DELAY
162 |
163 | #elif defined(__MBED__) && !defined(ARDUINO)
164 |
165 | #include "mbed.h"
166 |
167 | static Timer blynk_millis_timer;
168 | static Ticker blynk_waker;
169 |
170 | static
171 | void blynk_wake() {
172 | //pc.puts("(...)");
173 | }
174 |
175 | BLYNK_CONSTRUCTOR
176 | static void BlynkSystemInit()
177 | {
178 | blynk_waker.attach(&blynk_wake, 2.0);
179 | blynk_millis_timer.start();
180 | }
181 |
182 | void BlynkDelay(millis_time_t ms)
183 | {
184 | wait_ms(ms);
185 | }
186 |
187 | millis_time_t BlynkMillis()
188 | {
189 | return blynk_millis_timer.read_ms();
190 | }
191 |
192 | #define _BLYNK_USE_DEFAULT_FREE_RAM
193 | #define _BLYNK_USE_DEFAULT_RESET
194 |
195 | #elif defined(LINUX) && defined(RASPBERRY)
196 |
197 | #include
198 | #include
199 |
200 | BLYNK_CONSTRUCTOR
201 | static void BlynkSystemInit()
202 | {
203 | wiringPiSetupGpio();
204 | }
205 |
206 | void BlynkReset()
207 | {
208 | exit(1);
209 | for(;;) {} // To make compiler happy
210 | }
211 |
212 | #define _BLYNK_USE_DEFAULT_FREE_RAM
213 | #define _BLYNK_USE_DEFAULT_MILLIS
214 | #define _BLYNK_USE_DEFAULT_DELAY
215 |
216 | #elif defined(LINUX)
217 |
218 | #define _POSIX_C_SOURCE 200809L
219 | #include
220 | #include
221 | #include
222 |
223 | static millis_time_t blynk_startup_time = 0;
224 |
225 | BLYNK_CONSTRUCTOR
226 | static void BlynkSystemInit()
227 | {
228 | blynk_startup_time = BlynkMillis();
229 | }
230 |
231 | void BlynkReset()
232 | {
233 | exit(1);
234 | for(;;) {} // To make compiler happy
235 | }
236 |
237 | void BlynkDelay(millis_time_t ms)
238 | {
239 | usleep(ms * 1000);
240 | }
241 |
242 | millis_time_t BlynkMillis()
243 | {
244 | struct timespec ts;
245 | clock_gettime(CLOCK_MONOTONIC, &ts );
246 | return ( ts.tv_sec * 1000 + ts.tv_nsec / 1000000L ) - blynk_startup_time;
247 | }
248 |
249 | #define _BLYNK_USE_DEFAULT_FREE_RAM
250 |
251 | #elif defined(TI_CC3220)
252 |
253 | #include
254 | #include
255 | #include
256 | #include
257 |
258 | #include
259 |
260 | #include
261 | #include
262 | #include
263 |
264 | void BlynkReset()
265 | {
266 | sl_Stop(200);
267 | for(;;) {
268 | PRCMHibernateCycleTrigger();
269 | }
270 | }
271 |
272 | void BlynkDelay(millis_time_t ms)
273 | {
274 | usleep(ms * 1000);
275 | }
276 |
277 | millis_time_t BlynkMillis()
278 | {
279 | return Clock_getTicks();
280 | }
281 |
282 | #define _BLYNK_USE_DEFAULT_FREE_RAM
283 |
284 | #else
285 |
286 | #if defined(BLYNK_DEBUG_ALL)
287 | #warning "Need to implement board-specific utilities"
288 | #endif
289 |
290 | #define _BLYNK_USE_DEFAULT_FREE_RAM
291 | #define _BLYNK_USE_DEFAULT_RESET
292 | #define _BLYNK_USE_DEFAULT_MILLIS
293 | #define _BLYNK_USE_DEFAULT_DELAY
294 |
295 | #endif
296 |
297 | #ifdef _BLYNK_USE_DEFAULT_DELAY
298 | void BlynkDelay(millis_time_t ms)
299 | {
300 | return delay(ms);
301 | }
302 | #endif
303 |
304 | #ifdef _BLYNK_USE_DEFAULT_MILLIS
305 | millis_time_t BlynkMillis()
306 | {
307 | return millis();
308 | }
309 | #endif
310 |
311 | #ifdef _BLYNK_USE_DEFAULT_FREE_RAM
312 | size_t BlynkFreeRam()
313 | {
314 | return 0;
315 | }
316 | #endif
317 |
318 | #ifdef _BLYNK_USE_DEFAULT_RESET
319 | void BlynkReset()
320 | {
321 | for(;;) {} // To make compiler happy
322 | }
323 | #endif
324 |
325 | #ifdef _BLYNK_USE_DEFAULT_RESET
326 | bool BlynkResetImplemented() { return false; }
327 | #else
328 | bool BlynkResetImplemented() { return true; }
329 | #endif
330 |
331 | void BlynkFatal()
332 | {
333 | BlynkDelay(10000L);
334 | BlynkReset();
335 | }
336 |
337 |
--------------------------------------------------------------------------------
/src/utility/BlynkFifo.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkFifo.h
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Feb 2015
7 | * @brief FIFO implementation
8 | *
9 | */
10 |
11 | #ifndef BlynkFifo_h
12 | #define BlynkFifo_h
13 |
14 | #include
15 |
16 | template
17 | class BlynkFifo
18 | {
19 | public:
20 | BlynkFifo()
21 | {
22 | clear();
23 | }
24 |
25 | void clear()
26 | {
27 | _r = 0;
28 | _w = 0;
29 | }
30 |
31 | ~BlynkFifo(void)
32 | {}
33 |
34 | // writing thread/context API
35 | //-------------------------------------------------------------
36 |
37 | bool writeable(void)
38 | {
39 | return free() > 0;
40 | }
41 |
42 | int free(void)
43 | {
44 | int s = _r - _w;
45 | if (s <= 0)
46 | s += N;
47 | return s - 1;
48 | }
49 |
50 | T put(const T& c)
51 | {
52 | int i = _w;
53 | int j = i;
54 | i = _inc(i);
55 | while (i == _r) // = !writeable()
56 | /* nothing / just wait */;
57 | _b[j] = c;
58 | _w = i;
59 | return c;
60 | }
61 |
62 | int put(const T* p, int n, bool blocking = false)
63 | {
64 | int c = n;
65 | while (c)
66 | {
67 | int f;
68 | while ((f = free()) == 0) // wait for space
69 | {
70 | if (!blocking) return n - c; // no more space and not blocking
71 | /* nothing / just wait */;
72 | }
73 | // check free space
74 | if (c < f) f = c;
75 | int w = _w;
76 | int m = N - w;
77 | // check wrap
78 | if (f > m) f = m;
79 | memcpy(&_b[w], p, f);
80 | _w = _inc(w, f);
81 | c -= f;
82 | p += f;
83 | }
84 | return n - c;
85 | }
86 |
87 | // reading thread/context API
88 | // --------------------------------------------------------
89 |
90 | bool readable(void)
91 | {
92 | return (_r != _w);
93 | }
94 |
95 | size_t size(void)
96 | {
97 | int s = _w - _r;
98 | if (s < 0)
99 | s += N;
100 | return s;
101 | }
102 |
103 | T get(void)
104 | {
105 | int r = _r;
106 | while (r == _w) // = !readable()
107 | /* nothing / just wait */;
108 | T t = _b[r];
109 | _r = _inc(r);
110 | return t;
111 | }
112 |
113 | T peek(void)
114 | {
115 | int r = _r;
116 | while (r == _w);
117 | return _b[r];
118 | }
119 |
120 | int get(T* p, int n, bool blocking = false)
121 | {
122 | int c = n;
123 | while (c)
124 | {
125 | int f;
126 | for (;;) // wait for data
127 | {
128 | f = size();
129 | if (f) break; // free space
130 | if (!blocking) return n - c; // no space and not blocking
131 | /* nothing / just wait */;
132 | }
133 | // check available data
134 | if (c < f) f = c;
135 | int r = _r;
136 | int m = N - r;
137 | // check wrap
138 | if (f > m) f = m;
139 | memcpy(p, &_b[r], f);
140 | _r = _inc(r, f);
141 | c -= f;
142 | p += f;
143 | }
144 | return n - c;
145 | }
146 |
147 | private:
148 | int _inc(int i, int n = 1)
149 | {
150 | return (i + n) % N;
151 | }
152 |
153 | T _b[N];
154 | volatile int _w;
155 | volatile int _r;
156 | };
157 |
158 | #endif
159 |
--------------------------------------------------------------------------------
/src/utility/BlynkHandlers.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * @file BlynkHandlers.cpp
3 | * @author Volodymyr Shymanskyy
4 | * @license This project is released under the MIT License (MIT)
5 | * @copyright Copyright (c) 2015 Volodymyr Shymanskyy
6 | * @date Jan 2015
7 | * @brief Virtual pin utilities
8 | */
9 |
10 | #include
11 | #include
12 | #include
13 |
14 | void BlynkNoOpCbk()
15 | {}
16 |
17 | void BlynkWidgetRead(BlynkReq BLYNK_UNUSED &request)
18 | {
19 | BLYNK_LOG2(BLYNK_F("No handler for reading from pin "), request.pin);
20 | }
21 |
22 | void BlynkWidgetWrite(BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED ¶m)
23 | {
24 | BLYNK_LOG2(BLYNK_F("No handler for writing to pin "), request.pin);
25 | }
26 |
27 | #define BLYNK_ON_READ_IMPL(pin) void BlynkWidgetRead ## pin (BlynkReq BLYNK_UNUSED &req) \
28 | __attribute__((weak, alias("BlynkWidgetRead")))
29 |
30 | #define BLYNK_ON_WRITE_IMPL(pin) void BlynkWidgetWrite ## pin (BlynkReq BLYNK_UNUSED &req, const BlynkParam BLYNK_UNUSED ¶m) \
31 | __attribute__((weak, alias("BlynkWidgetWrite")))
32 |
33 | BLYNK_CONNECTED() __attribute__((weak, alias("BlynkNoOpCbk")));
34 | BLYNK_DISCONNECTED() __attribute__((weak, alias("BlynkNoOpCbk")));
35 |
36 | // Internal Virtual Pins
37 | BLYNK_ON_WRITE_IMPL(InternalPinACON);
38 | BLYNK_ON_WRITE_IMPL(InternalPinADIS);
39 | BLYNK_ON_WRITE_IMPL(InternalPinRTC);
40 | BLYNK_ON_WRITE_IMPL(InternalPinUTC);
41 | BLYNK_ON_WRITE_IMPL(InternalPinOTA);
42 | BLYNK_ON_WRITE_IMPL(InternalPinMETA);
43 | BLYNK_ON_WRITE_IMPL(InternalPinVFS);
44 | BLYNK_ON_WRITE_IMPL(InternalPinDBG);
45 |
46 | // Regular Virtual Pins
47 | BLYNK_ON_READ_IMPL(Default);
48 | BLYNK_ON_WRITE_IMPL(Default);
49 |
50 | BLYNK_ON_READ_IMPL(0 );
51 | BLYNK_ON_READ_IMPL(1 );
52 | BLYNK_ON_READ_IMPL(2 );
53 | BLYNK_ON_READ_IMPL(3 );
54 | BLYNK_ON_READ_IMPL(4 );
55 | BLYNK_ON_READ_IMPL(5 );
56 | BLYNK_ON_READ_IMPL(6 );
57 | BLYNK_ON_READ_IMPL(7 );
58 | BLYNK_ON_READ_IMPL(8 );
59 | BLYNK_ON_READ_IMPL(9 );
60 | BLYNK_ON_READ_IMPL(10);
61 | BLYNK_ON_READ_IMPL(11);
62 | BLYNK_ON_READ_IMPL(12);
63 | BLYNK_ON_READ_IMPL(13);
64 | BLYNK_ON_READ_IMPL(14);
65 | BLYNK_ON_READ_IMPL(15);
66 | BLYNK_ON_READ_IMPL(16);
67 | BLYNK_ON_READ_IMPL(17);
68 | BLYNK_ON_READ_IMPL(18);
69 | BLYNK_ON_READ_IMPL(19);
70 | BLYNK_ON_READ_IMPL(20);
71 | BLYNK_ON_READ_IMPL(21);
72 | BLYNK_ON_READ_IMPL(22);
73 | BLYNK_ON_READ_IMPL(23);
74 | BLYNK_ON_READ_IMPL(24);
75 | BLYNK_ON_READ_IMPL(25);
76 | BLYNK_ON_READ_IMPL(26);
77 | BLYNK_ON_READ_IMPL(27);
78 | BLYNK_ON_READ_IMPL(28);
79 | BLYNK_ON_READ_IMPL(29);
80 | BLYNK_ON_READ_IMPL(30);
81 | BLYNK_ON_READ_IMPL(31);
82 | #ifdef BLYNK_USE_128_VPINS
83 | BLYNK_ON_READ_IMPL(32);
84 | BLYNK_ON_READ_IMPL(33);
85 | BLYNK_ON_READ_IMPL(34);
86 | BLYNK_ON_READ_IMPL(35);
87 | BLYNK_ON_READ_IMPL(36);
88 | BLYNK_ON_READ_IMPL(37);
89 | BLYNK_ON_READ_IMPL(38);
90 | BLYNK_ON_READ_IMPL(39);
91 | BLYNK_ON_READ_IMPL(40);
92 | BLYNK_ON_READ_IMPL(41);
93 | BLYNK_ON_READ_IMPL(42);
94 | BLYNK_ON_READ_IMPL(43);
95 | BLYNK_ON_READ_IMPL(44);
96 | BLYNK_ON_READ_IMPL(45);
97 | BLYNK_ON_READ_IMPL(46);
98 | BLYNK_ON_READ_IMPL(47);
99 | BLYNK_ON_READ_IMPL(48);
100 | BLYNK_ON_READ_IMPL(49);
101 | BLYNK_ON_READ_IMPL(50);
102 | BLYNK_ON_READ_IMPL(51);
103 | BLYNK_ON_READ_IMPL(52);
104 | BLYNK_ON_READ_IMPL(53);
105 | BLYNK_ON_READ_IMPL(54);
106 | BLYNK_ON_READ_IMPL(55);
107 | BLYNK_ON_READ_IMPL(56);
108 | BLYNK_ON_READ_IMPL(57);
109 | BLYNK_ON_READ_IMPL(58);
110 | BLYNK_ON_READ_IMPL(59);
111 | BLYNK_ON_READ_IMPL(60);
112 | BLYNK_ON_READ_IMPL(61);
113 | BLYNK_ON_READ_IMPL(62);
114 | BLYNK_ON_READ_IMPL(63);
115 | BLYNK_ON_READ_IMPL(64);
116 | BLYNK_ON_READ_IMPL(65);
117 | BLYNK_ON_READ_IMPL(66);
118 | BLYNK_ON_READ_IMPL(67);
119 | BLYNK_ON_READ_IMPL(68);
120 | BLYNK_ON_READ_IMPL(69);
121 | BLYNK_ON_READ_IMPL(70);
122 | BLYNK_ON_READ_IMPL(71);
123 | BLYNK_ON_READ_IMPL(72);
124 | BLYNK_ON_READ_IMPL(73);
125 | BLYNK_ON_READ_IMPL(74);
126 | BLYNK_ON_READ_IMPL(75);
127 | BLYNK_ON_READ_IMPL(76);
128 | BLYNK_ON_READ_IMPL(77);
129 | BLYNK_ON_READ_IMPL(78);
130 | BLYNK_ON_READ_IMPL(79);
131 | BLYNK_ON_READ_IMPL(80);
132 | BLYNK_ON_READ_IMPL(81);
133 | BLYNK_ON_READ_IMPL(82);
134 | BLYNK_ON_READ_IMPL(83);
135 | BLYNK_ON_READ_IMPL(84);
136 | BLYNK_ON_READ_IMPL(85);
137 | BLYNK_ON_READ_IMPL(86);
138 | BLYNK_ON_READ_IMPL(87);
139 | BLYNK_ON_READ_IMPL(88);
140 | BLYNK_ON_READ_IMPL(89);
141 | BLYNK_ON_READ_IMPL(90);
142 | BLYNK_ON_READ_IMPL(91);
143 | BLYNK_ON_READ_IMPL(92);
144 | BLYNK_ON_READ_IMPL(93);
145 | BLYNK_ON_READ_IMPL(94);
146 | BLYNK_ON_READ_IMPL(95);
147 | BLYNK_ON_READ_IMPL(96);
148 | BLYNK_ON_READ_IMPL(97);
149 | BLYNK_ON_READ_IMPL(98);
150 | BLYNK_ON_READ_IMPL(99);
151 | BLYNK_ON_READ_IMPL(100);
152 | BLYNK_ON_READ_IMPL(101);
153 | BLYNK_ON_READ_IMPL(102);
154 | BLYNK_ON_READ_IMPL(103);
155 | BLYNK_ON_READ_IMPL(104);
156 | BLYNK_ON_READ_IMPL(105);
157 | BLYNK_ON_READ_IMPL(106);
158 | BLYNK_ON_READ_IMPL(107);
159 | BLYNK_ON_READ_IMPL(108);
160 | BLYNK_ON_READ_IMPL(109);
161 | BLYNK_ON_READ_IMPL(110);
162 | BLYNK_ON_READ_IMPL(111);
163 | BLYNK_ON_READ_IMPL(112);
164 | BLYNK_ON_READ_IMPL(113);
165 | BLYNK_ON_READ_IMPL(114);
166 | BLYNK_ON_READ_IMPL(115);
167 | BLYNK_ON_READ_IMPL(116);
168 | BLYNK_ON_READ_IMPL(117);
169 | BLYNK_ON_READ_IMPL(118);
170 | BLYNK_ON_READ_IMPL(119);
171 | BLYNK_ON_READ_IMPL(120);
172 | BLYNK_ON_READ_IMPL(121);
173 | BLYNK_ON_READ_IMPL(122);
174 | BLYNK_ON_READ_IMPL(123);
175 | BLYNK_ON_READ_IMPL(124);
176 | BLYNK_ON_READ_IMPL(125);
177 | BLYNK_ON_READ_IMPL(126);
178 | BLYNK_ON_READ_IMPL(127);
179 | #endif
180 |
181 | BLYNK_ON_WRITE_IMPL(0 );
182 | BLYNK_ON_WRITE_IMPL(1 );
183 | BLYNK_ON_WRITE_IMPL(2 );
184 | BLYNK_ON_WRITE_IMPL(3 );
185 | BLYNK_ON_WRITE_IMPL(4 );
186 | BLYNK_ON_WRITE_IMPL(5 );
187 | BLYNK_ON_WRITE_IMPL(6 );
188 | BLYNK_ON_WRITE_IMPL(7 );
189 | BLYNK_ON_WRITE_IMPL(8 );
190 | BLYNK_ON_WRITE_IMPL(9 );
191 | BLYNK_ON_WRITE_IMPL(10);
192 | BLYNK_ON_WRITE_IMPL(11);
193 | BLYNK_ON_WRITE_IMPL(12);
194 | BLYNK_ON_WRITE_IMPL(13);
195 | BLYNK_ON_WRITE_IMPL(14);
196 | BLYNK_ON_WRITE_IMPL(15);
197 | BLYNK_ON_WRITE_IMPL(16);
198 | BLYNK_ON_WRITE_IMPL(17);
199 | BLYNK_ON_WRITE_IMPL(18);
200 | BLYNK_ON_WRITE_IMPL(19);
201 | BLYNK_ON_WRITE_IMPL(20);
202 | BLYNK_ON_WRITE_IMPL(21);
203 | BLYNK_ON_WRITE_IMPL(22);
204 | BLYNK_ON_WRITE_IMPL(23);
205 | BLYNK_ON_WRITE_IMPL(24);
206 | BLYNK_ON_WRITE_IMPL(25);
207 | BLYNK_ON_WRITE_IMPL(26);
208 | BLYNK_ON_WRITE_IMPL(27);
209 | BLYNK_ON_WRITE_IMPL(28);
210 | BLYNK_ON_WRITE_IMPL(29);
211 | BLYNK_ON_WRITE_IMPL(30);
212 | BLYNK_ON_WRITE_IMPL(31);
213 | #ifdef BLYNK_USE_128_VPINS
214 | BLYNK_ON_WRITE_IMPL(32);
215 | BLYNK_ON_WRITE_IMPL(33);
216 | BLYNK_ON_WRITE_IMPL(34);
217 | BLYNK_ON_WRITE_IMPL(35);
218 | BLYNK_ON_WRITE_IMPL(36);
219 | BLYNK_ON_WRITE_IMPL(37);
220 | BLYNK_ON_WRITE_IMPL(38);
221 | BLYNK_ON_WRITE_IMPL(39);
222 | BLYNK_ON_WRITE_IMPL(40);
223 | BLYNK_ON_WRITE_IMPL(41);
224 | BLYNK_ON_WRITE_IMPL(42);
225 | BLYNK_ON_WRITE_IMPL(43);
226 | BLYNK_ON_WRITE_IMPL(44);
227 | BLYNK_ON_WRITE_IMPL(45);
228 | BLYNK_ON_WRITE_IMPL(46);
229 | BLYNK_ON_WRITE_IMPL(47);
230 | BLYNK_ON_WRITE_IMPL(48);
231 | BLYNK_ON_WRITE_IMPL(49);
232 | BLYNK_ON_WRITE_IMPL(50);
233 | BLYNK_ON_WRITE_IMPL(51);
234 | BLYNK_ON_WRITE_IMPL(52);
235 | BLYNK_ON_WRITE_IMPL(53);
236 | BLYNK_ON_WRITE_IMPL(54);
237 | BLYNK_ON_WRITE_IMPL(55);
238 | BLYNK_ON_WRITE_IMPL(56);
239 | BLYNK_ON_WRITE_IMPL(57);
240 | BLYNK_ON_WRITE_IMPL(58);
241 | BLYNK_ON_WRITE_IMPL(59);
242 | BLYNK_ON_WRITE_IMPL(60);
243 | BLYNK_ON_WRITE_IMPL(61);
244 | BLYNK_ON_WRITE_IMPL(62);
245 | BLYNK_ON_WRITE_IMPL(63);
246 | BLYNK_ON_WRITE_IMPL(64);
247 | BLYNK_ON_WRITE_IMPL(65);
248 | BLYNK_ON_WRITE_IMPL(66);
249 | BLYNK_ON_WRITE_IMPL(67);
250 | BLYNK_ON_WRITE_IMPL(68);
251 | BLYNK_ON_WRITE_IMPL(69);
252 | BLYNK_ON_WRITE_IMPL(70);
253 | BLYNK_ON_WRITE_IMPL(71);
254 | BLYNK_ON_WRITE_IMPL(72);
255 | BLYNK_ON_WRITE_IMPL(73);
256 | BLYNK_ON_WRITE_IMPL(74);
257 | BLYNK_ON_WRITE_IMPL(75);
258 | BLYNK_ON_WRITE_IMPL(76);
259 | BLYNK_ON_WRITE_IMPL(77);
260 | BLYNK_ON_WRITE_IMPL(78);
261 | BLYNK_ON_WRITE_IMPL(79);
262 | BLYNK_ON_WRITE_IMPL(80);
263 | BLYNK_ON_WRITE_IMPL(81);
264 | BLYNK_ON_WRITE_IMPL(82);
265 | BLYNK_ON_WRITE_IMPL(83);
266 | BLYNK_ON_WRITE_IMPL(84);
267 | BLYNK_ON_WRITE_IMPL(85);
268 | BLYNK_ON_WRITE_IMPL(86);
269 | BLYNK_ON_WRITE_IMPL(87);
270 | BLYNK_ON_WRITE_IMPL(88);
271 | BLYNK_ON_WRITE_IMPL(89);
272 | BLYNK_ON_WRITE_IMPL(90);
273 | BLYNK_ON_WRITE_IMPL(91);
274 | BLYNK_ON_WRITE_IMPL(92);
275 | BLYNK_ON_WRITE_IMPL(93);
276 | BLYNK_ON_WRITE_IMPL(94);
277 | BLYNK_ON_WRITE_IMPL(95);
278 | BLYNK_ON_WRITE_IMPL(96);
279 | BLYNK_ON_WRITE_IMPL(97);
280 | BLYNK_ON_WRITE_IMPL(98);
281 | BLYNK_ON_WRITE_IMPL(99);
282 | BLYNK_ON_WRITE_IMPL(100);
283 | BLYNK_ON_WRITE_IMPL(101);
284 | BLYNK_ON_WRITE_IMPL(102);
285 | BLYNK_ON_WRITE_IMPL(103);
286 | BLYNK_ON_WRITE_IMPL(104);
287 | BLYNK_ON_WRITE_IMPL(105);
288 | BLYNK_ON_WRITE_IMPL(106);
289 | BLYNK_ON_WRITE_IMPL(107);
290 | BLYNK_ON_WRITE_IMPL(108);
291 | BLYNK_ON_WRITE_IMPL(109);
292 | BLYNK_ON_WRITE_IMPL(110);
293 | BLYNK_ON_WRITE_IMPL(111);
294 | BLYNK_ON_WRITE_IMPL(112);
295 | BLYNK_ON_WRITE_IMPL(113);
296 | BLYNK_ON_WRITE_IMPL(114);
297 | BLYNK_ON_WRITE_IMPL(115);
298 | BLYNK_ON_WRITE_IMPL(116);
299 | BLYNK_ON_WRITE_IMPL(117);
300 | BLYNK_ON_WRITE_IMPL(118);
301 | BLYNK_ON_WRITE_IMPL(119);
302 | BLYNK_ON_WRITE_IMPL(120);
303 | BLYNK_ON_WRITE_IMPL(121);
304 | BLYNK_ON_WRITE_IMPL(122);
305 | BLYNK_ON_WRITE_IMPL(123);
306 | BLYNK_ON_WRITE_IMPL(124);
307 | BLYNK_ON_WRITE_IMPL(125);
308 | BLYNK_ON_WRITE_IMPL(126);
309 | BLYNK_ON_WRITE_IMPL(127);
310 | #endif
311 |
312 | static const WidgetReadHandler BlynkReadHandlerVector[] BLYNK_PROGMEM = {
313 | BlynkWidgetRead0, BlynkWidgetRead1, BlynkWidgetRead2, BlynkWidgetRead3,
314 | BlynkWidgetRead4, BlynkWidgetRead5, BlynkWidgetRead6, BlynkWidgetRead7,
315 | BlynkWidgetRead8, BlynkWidgetRead9, BlynkWidgetRead10, BlynkWidgetRead11,
316 | BlynkWidgetRead12, BlynkWidgetRead13, BlynkWidgetRead14, BlynkWidgetRead15,
317 | BlynkWidgetRead16, BlynkWidgetRead17, BlynkWidgetRead18, BlynkWidgetRead19,
318 | BlynkWidgetRead20, BlynkWidgetRead21, BlynkWidgetRead22, BlynkWidgetRead23,
319 | BlynkWidgetRead24, BlynkWidgetRead25, BlynkWidgetRead26, BlynkWidgetRead27,
320 | BlynkWidgetRead28, BlynkWidgetRead29, BlynkWidgetRead30, BlynkWidgetRead31,
321 | #ifdef BLYNK_USE_128_VPINS
322 | BlynkWidgetRead32, BlynkWidgetRead33, BlynkWidgetRead34, BlynkWidgetRead35,
323 | BlynkWidgetRead36, BlynkWidgetRead37, BlynkWidgetRead38, BlynkWidgetRead39,
324 | BlynkWidgetRead40, BlynkWidgetRead41, BlynkWidgetRead42, BlynkWidgetRead43,
325 | BlynkWidgetRead44, BlynkWidgetRead45, BlynkWidgetRead46, BlynkWidgetRead47,
326 | BlynkWidgetRead48, BlynkWidgetRead49, BlynkWidgetRead50, BlynkWidgetRead51,
327 | BlynkWidgetRead52, BlynkWidgetRead53, BlynkWidgetRead54, BlynkWidgetRead55,
328 | BlynkWidgetRead56, BlynkWidgetRead57, BlynkWidgetRead58, BlynkWidgetRead59,
329 | BlynkWidgetRead60, BlynkWidgetRead61, BlynkWidgetRead62, BlynkWidgetRead63,
330 | BlynkWidgetRead64, BlynkWidgetRead65, BlynkWidgetRead66, BlynkWidgetRead67,
331 | BlynkWidgetRead68, BlynkWidgetRead69, BlynkWidgetRead70, BlynkWidgetRead71,
332 | BlynkWidgetRead72, BlynkWidgetRead73, BlynkWidgetRead74, BlynkWidgetRead75,
333 | BlynkWidgetRead76, BlynkWidgetRead77, BlynkWidgetRead78, BlynkWidgetRead79,
334 | BlynkWidgetRead80, BlynkWidgetRead81, BlynkWidgetRead82, BlynkWidgetRead83,
335 | BlynkWidgetRead84, BlynkWidgetRead85, BlynkWidgetRead86, BlynkWidgetRead87,
336 | BlynkWidgetRead88, BlynkWidgetRead89, BlynkWidgetRead90, BlynkWidgetRead91,
337 | BlynkWidgetRead92, BlynkWidgetRead93, BlynkWidgetRead94, BlynkWidgetRead95,
338 | BlynkWidgetRead96, BlynkWidgetRead97, BlynkWidgetRead98, BlynkWidgetRead99,
339 | BlynkWidgetRead100, BlynkWidgetRead101, BlynkWidgetRead102, BlynkWidgetRead103,
340 | BlynkWidgetRead104, BlynkWidgetRead105, BlynkWidgetRead106, BlynkWidgetRead107,
341 | BlynkWidgetRead108, BlynkWidgetRead109, BlynkWidgetRead110, BlynkWidgetRead111,
342 | BlynkWidgetRead112, BlynkWidgetRead113, BlynkWidgetRead114, BlynkWidgetRead115,
343 | BlynkWidgetRead116, BlynkWidgetRead117, BlynkWidgetRead118, BlynkWidgetRead119,
344 | BlynkWidgetRead120, BlynkWidgetRead121, BlynkWidgetRead122, BlynkWidgetRead123,
345 | BlynkWidgetRead124, BlynkWidgetRead125, BlynkWidgetRead126, BlynkWidgetRead127,
346 | #endif
347 | };
348 |
349 | static const WidgetWriteHandler BlynkWriteHandlerVector[] BLYNK_PROGMEM = {
350 | BlynkWidgetWrite0, BlynkWidgetWrite1, BlynkWidgetWrite2, BlynkWidgetWrite3,
351 | BlynkWidgetWrite4, BlynkWidgetWrite5, BlynkWidgetWrite6, BlynkWidgetWrite7,
352 | BlynkWidgetWrite8, BlynkWidgetWrite9, BlynkWidgetWrite10, BlynkWidgetWrite11,
353 | BlynkWidgetWrite12, BlynkWidgetWrite13, BlynkWidgetWrite14, BlynkWidgetWrite15,
354 | BlynkWidgetWrite16, BlynkWidgetWrite17, BlynkWidgetWrite18, BlynkWidgetWrite19,
355 | BlynkWidgetWrite20, BlynkWidgetWrite21, BlynkWidgetWrite22, BlynkWidgetWrite23,
356 | BlynkWidgetWrite24, BlynkWidgetWrite25, BlynkWidgetWrite26, BlynkWidgetWrite27,
357 | BlynkWidgetWrite28, BlynkWidgetWrite29, BlynkWidgetWrite30, BlynkWidgetWrite31,
358 | #ifdef BLYNK_USE_128_VPINS
359 | BlynkWidgetWrite32, BlynkWidgetWrite33, BlynkWidgetWrite34, BlynkWidgetWrite35,
360 | BlynkWidgetWrite36, BlynkWidgetWrite37, BlynkWidgetWrite38, BlynkWidgetWrite39,
361 | BlynkWidgetWrite40, BlynkWidgetWrite41, BlynkWidgetWrite42, BlynkWidgetWrite43,
362 | BlynkWidgetWrite44, BlynkWidgetWrite45, BlynkWidgetWrite46, BlynkWidgetWrite47,
363 | BlynkWidgetWrite48, BlynkWidgetWrite49, BlynkWidgetWrite50, BlynkWidgetWrite51,
364 | BlynkWidgetWrite52, BlynkWidgetWrite53, BlynkWidgetWrite54, BlynkWidgetWrite55,
365 | BlynkWidgetWrite56, BlynkWidgetWrite57, BlynkWidgetWrite58, BlynkWidgetWrite59,
366 | BlynkWidgetWrite60, BlynkWidgetWrite61, BlynkWidgetWrite62, BlynkWidgetWrite63,
367 | BlynkWidgetWrite64, BlynkWidgetWrite65, BlynkWidgetWrite66, BlynkWidgetWrite67,
368 | BlynkWidgetWrite68, BlynkWidgetWrite69, BlynkWidgetWrite70, BlynkWidgetWrite71,
369 | BlynkWidgetWrite72, BlynkWidgetWrite73, BlynkWidgetWrite74, BlynkWidgetWrite75,
370 | BlynkWidgetWrite76, BlynkWidgetWrite77, BlynkWidgetWrite78, BlynkWidgetWrite79,
371 | BlynkWidgetWrite80, BlynkWidgetWrite81, BlynkWidgetWrite82, BlynkWidgetWrite83,
372 | BlynkWidgetWrite84, BlynkWidgetWrite85, BlynkWidgetWrite86, BlynkWidgetWrite87,
373 | BlynkWidgetWrite88, BlynkWidgetWrite89, BlynkWidgetWrite90, BlynkWidgetWrite91,
374 | BlynkWidgetWrite92, BlynkWidgetWrite93, BlynkWidgetWrite94, BlynkWidgetWrite95,
375 | BlynkWidgetWrite96, BlynkWidgetWrite97, BlynkWidgetWrite98, BlynkWidgetWrite99,
376 | BlynkWidgetWrite100, BlynkWidgetWrite101, BlynkWidgetWrite102, BlynkWidgetWrite103,
377 | BlynkWidgetWrite104, BlynkWidgetWrite105, BlynkWidgetWrite106, BlynkWidgetWrite107,
378 | BlynkWidgetWrite108, BlynkWidgetWrite109, BlynkWidgetWrite110, BlynkWidgetWrite111,
379 | BlynkWidgetWrite112, BlynkWidgetWrite113, BlynkWidgetWrite114, BlynkWidgetWrite115,
380 | BlynkWidgetWrite116, BlynkWidgetWrite117, BlynkWidgetWrite118, BlynkWidgetWrite119,
381 | BlynkWidgetWrite120, BlynkWidgetWrite121, BlynkWidgetWrite122, BlynkWidgetWrite123,
382 | BlynkWidgetWrite124, BlynkWidgetWrite125, BlynkWidgetWrite126, BlynkWidgetWrite127,
383 | #endif
384 | };
385 |
386 | WidgetReadHandler GetReadHandler(uint8_t pin)
387 | {
388 | if (pin >= BLYNK_COUNT_OF(BlynkReadHandlerVector))
389 | return NULL;
390 | #ifdef BLYNK_HAS_PROGMEM
391 | return (WidgetReadHandler)pgm_read_word(&BlynkReadHandlerVector[pin]);
392 | #else
393 | return BlynkReadHandlerVector[pin];
394 | #endif
395 | }
396 |
397 | WidgetWriteHandler GetWriteHandler(uint8_t pin)
398 | {
399 | if (pin >= BLYNK_COUNT_OF(BlynkWriteHandlerVector))
400 | return NULL;
401 | #ifdef BLYNK_HAS_PROGMEM
402 | return (WidgetWriteHandler)pgm_read_word(&BlynkWriteHandlerVector[pin]);
403 | #else
404 | return BlynkWriteHandlerVector[pin];
405 | #endif
406 | }
407 |
--------------------------------------------------------------------------------
/src/utility/BlynkHelpers.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | #if !defined(BLYNK_NO_FLOAT) && defined(BLYNK_USE_INTERNAL_DTOSTRF)
7 |
8 | #include
9 | #include
10 |
11 | char* dtostrf_internal(double number, signed char BLYNK_UNUSED width, unsigned char prec, char *s) {
12 | if(isnan(number)) {
13 | strcpy(s, "nan");
14 | return s;
15 | }
16 | if(isinf(number)) {
17 | strcpy(s, "inf");
18 | return s;
19 | }
20 |
21 | if(number > 4294967040.0 || number < -4294967040.0) {
22 | strcpy(s, "ovf");
23 | return s;
24 | }
25 | char* out = s;
26 | // Handle negative numbers
27 | if(number < 0.0) {
28 | *out = '-';
29 | ++out;
30 | number = -number;
31 | }
32 |
33 | // Round correctly so that print(1.999, 2) prints as "2.00"
34 | double rounding = 0.5;
35 | for(uint8_t i = 0; i < prec; ++i) {
36 | rounding /= 10.0;
37 | }
38 |
39 | number += rounding;
40 |
41 | // Extract the integer part of the number and print it
42 | unsigned long int_part = (unsigned long) number;
43 | double remainder = number - (double) int_part;
44 | out += sprintf(out, "%lu", int_part);
45 |
46 | // Print the decimal point, but only if there are digits beyond
47 | if(prec > 0) {
48 | *out++ = '.';
49 | }
50 |
51 | while(prec-- > 0) {
52 | remainder *= 10.0;
53 | if((int)remainder == 0) {
54 | *out++ = '0';
55 | }
56 | }
57 | if((int)remainder != 0) {
58 | sprintf(out, "%d", (int)remainder);
59 | } else {
60 | *out++ = '\0';
61 | }
62 |
63 | return s;
64 | }
65 |
66 | #endif
67 |
68 | #if !defined(BLYNK_NO_LONGLONG) && defined(BLYNK_USE_INTERNAL_ATOLL)
69 |
70 | long long atoll_internal(const char *instr)
71 | {
72 | long long retval = 0;
73 | for (; *instr; instr++) {
74 | retval = 10*retval + (*instr - '0');
75 | }
76 | return retval;
77 | }
78 |
79 | #endif
80 |
81 | #if !defined(BLYNK_NO_LONGLONG)
82 |
83 | char* lltoa_internal(long long val, char* buf, unsigned buf_len, int base)
84 | {
85 | int i = buf_len-2;
86 | int sign = (val < 0);
87 | buf[buf_len-1] = '\0';
88 |
89 | if (val == 0) {
90 | buf[i] = '0';
91 | return &buf[i];
92 | }
93 |
94 | unsigned long long absval = sign ? -val : val;
95 |
96 | for (; absval && i ; --i, absval /= base) {
97 | buf[i] = "0123456789abcdef"[absval % base];
98 | }
99 |
100 | if (sign) { buf[i--] = '-'; }
101 |
102 | return &buf[i+1];
103 | }
104 |
105 | char* ulltoa_internal(unsigned long long val, char* buf, unsigned buf_len, int base)
106 | {
107 | int i = buf_len-2;
108 | buf[buf_len-1] = '\0';
109 |
110 | if (val == 0) {
111 | buf[i] = '0';
112 | return &buf[i];
113 | }
114 |
115 | for (; val && i ; --i, val /= base) {
116 | buf[i] = "0123456789abcdef"[val % base];
117 | }
118 |
119 | return &buf[i+1];
120 | }
121 |
122 | #endif
123 |
124 |
--------------------------------------------------------------------------------
/src/utility/BlynkStreamMulti.h:
--------------------------------------------------------------------------------
1 | #ifndef BlynkStreamMulti_h
2 | #define BlynkStreamMulti_h
3 |
4 | #ifndef BLYNK_MULTI_STREAM_MAX_QTY
5 | #define BLYNK_MULTI_STREAM_MAX_QTY 6
6 | #endif
7 |
8 | class MultiStream
9 | : public Stream
10 | {
11 | public:
12 | MultiStream() {}
13 | virtual ~MultiStream() {}
14 |
15 | bool addStream(Stream* stream) {
16 | if (stream && _streamsQty < BLYNK_MULTI_STREAM_MAX_QTY) {
17 | _streams[_streamsQty++] = stream;
18 | return true;
19 | }
20 | return false;
21 | }
22 |
23 | bool addStream(Stream& stream) {
24 | return addStream(&stream);
25 | }
26 |
27 | /*
28 | * Writing
29 | */
30 |
31 | virtual size_t write(uint8_t ch) {
32 | for (int i=0; i<_streamsQty; i++) {
33 | _streams[i]->write(ch);
34 | }
35 | return 1;
36 | }
37 |
38 | virtual void flush() {
39 | for (int i=0; i<_streamsQty; i++) {
40 | return _streams[i]->flush();
41 | }
42 | }
43 |
44 | /*
45 | * Reading
46 | */
47 |
48 | virtual int available() {
49 | for (int i=0; i<_streamsQty; i++) {
50 | int avail = _streams[i]->available();
51 | if (avail > 0) { return avail; }
52 | }
53 | return 0;
54 | }
55 |
56 | virtual int read() {
57 | for (int i=0; i<_streamsQty; i++) {
58 | if (_streams[i]->available()) {
59 | return _streams[i]->read();
60 | }
61 | }
62 | return -1;
63 | }
64 |
65 | virtual int peek() {
66 | for (int i=0; i<_streamsQty; i++) {
67 | if (_streams[i]->available()) {
68 | return _streams[i]->peek();
69 | }
70 | }
71 | return -1;
72 | }
73 |
74 | private:
75 | Stream* _streams[BLYNK_MULTI_STREAM_MAX_QTY];
76 | int _streamsQty = 0;
77 | };
78 |
79 | #endif
80 |
--------------------------------------------------------------------------------
/src/utility/BlynkStreamNull.h:
--------------------------------------------------------------------------------
1 | #ifndef BlynkStreamNull_h
2 | #define BlynkStreamNull_h
3 |
4 | class NullStream
5 | : public Stream
6 | {
7 | public:
8 |
9 | /*
10 | * Writing
11 | */
12 |
13 | virtual size_t write(uint8_t) override {
14 | return 1;
15 | }
16 |
17 | virtual size_t write(const uint8_t* buffer, size_t size) override {
18 | (void)buffer;
19 | (void)size;
20 | return size;
21 | }
22 |
23 | virtual int availableForWrite() {
24 | return 4096;
25 | }
26 |
27 | virtual void flush() {}
28 |
29 | /*
30 | * Reading
31 | */
32 |
33 | virtual int available() override {
34 | return 0;
35 | }
36 |
37 | virtual int read() override {
38 | return -1;
39 | }
40 |
41 | virtual int peek() override {
42 | return -1;
43 | }
44 |
45 | virtual size_t readBytes(char* buffer, size_t len) {
46 | (void)buffer;
47 | (void)len;
48 | return 0;
49 | }
50 |
51 | virtual int read(uint8_t* buffer, size_t len) {
52 | (void)buffer;
53 | (void)len;
54 | return 0;
55 | }
56 | };
57 |
58 | #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_NULLSTREAM)
59 | static NullStream NullStream;
60 | #endif
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/src/utility/BlynkTimeUtils.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | #define YEAR_0 1900
7 | #define YEAR_EPOCH 1970
8 | #define SECS_IN_DAY (24L * 60L * 60L)
9 | #define IS_LEAP_YEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
10 | #define YEAR_DAYS(year) (IS_LEAP_YEAR(year) ? 366 : 365)
11 |
12 | #define TIME_MAX 2147483647L
13 |
14 | static const int month_tab[2][12] = {
15 | { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
16 | { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
17 | };
18 |
19 | struct blynk_tm* blynk_gmtime_r(const blynk_time_t* t, struct blynk_tm *tm)
20 | {
21 | blynk_time_t time = *t;
22 | unsigned long dayclock, dayno;
23 | int year = YEAR_EPOCH;
24 |
25 | dayclock = (unsigned long) time % SECS_IN_DAY;
26 | dayno = (unsigned long) time / SECS_IN_DAY;
27 |
28 | tm->tm_sec = dayclock % 60;
29 | tm->tm_min = (dayclock % 3600) / 60;
30 | tm->tm_hour = dayclock / 3600;
31 | tm->tm_wday = (dayno + 4) % 7;
32 | while (dayno >= (unsigned long) YEAR_DAYS(year)) {
33 | dayno -= YEAR_DAYS(year);
34 | year++;
35 | }
36 | tm->tm_year = year - YEAR_0;
37 | tm->tm_yday = dayno;
38 | tm->tm_mon = 0;
39 | while (dayno >= (unsigned long) month_tab[IS_LEAP_YEAR(year)][tm->tm_mon]) {
40 | dayno -= month_tab[IS_LEAP_YEAR(year)][tm->tm_mon];
41 | tm->tm_mon++;
42 | }
43 | tm->tm_mday = dayno + 1;
44 | return tm;
45 | }
46 |
47 | blynk_time_t blynk_mk_gmtime(struct blynk_tm *tm)
48 | {
49 | long day, year;
50 | int tm_year;
51 | int yday, month;
52 | long seconds;
53 | int overflow;
54 |
55 | tm->tm_min += tm->tm_sec / 60;
56 | tm->tm_sec %= 60;
57 | if (tm->tm_sec < 0) {
58 | tm->tm_sec += 60;
59 | tm->tm_min--;
60 | }
61 | tm->tm_hour += tm->tm_min / 60;
62 | tm->tm_min = tm->tm_min % 60;
63 | if (tm->tm_min < 0) {
64 | tm->tm_min += 60;
65 | tm->tm_hour--;
66 | }
67 | day = tm->tm_hour / 24;
68 | tm->tm_hour = tm->tm_hour % 24;
69 | if (tm->tm_hour < 0) {
70 | tm->tm_hour += 24;
71 | day--;
72 | }
73 | tm->tm_year += tm->tm_mon / 12;
74 | tm->tm_mon %= 12;
75 | if (tm->tm_mon < 0) {
76 | tm->tm_mon += 12;
77 | tm->tm_year--;
78 | }
79 | day += (tm->tm_mday - 1);
80 | while (day < 0) {
81 | if (--tm->tm_mon < 0) {
82 | tm->tm_year--;
83 | tm->tm_mon = 11;
84 | }
85 | day += month_tab[IS_LEAP_YEAR(YEAR_0 + tm->tm_year)][tm->tm_mon];
86 | }
87 | while (day >= month_tab[IS_LEAP_YEAR(YEAR_0 + tm->tm_year)][tm->tm_mon]) {
88 | day -= month_tab[IS_LEAP_YEAR(YEAR_0 + tm->tm_year)][tm->tm_mon];
89 | if (++(tm->tm_mon) == 12) {
90 | tm->tm_mon = 0;
91 | tm->tm_year++;
92 | }
93 | }
94 | tm->tm_mday = day + 1;
95 | year = YEAR_EPOCH;
96 | if (tm->tm_year < year - YEAR_0)
97 | return (blynk_time_t) -1;
98 | seconds = 0;
99 | day = 0;
100 | overflow = 0;
101 |
102 | tm_year = tm->tm_year + YEAR_0;
103 |
104 | if (TIME_MAX / 365 < tm_year - year)
105 | overflow++;
106 | day = (tm_year - year) * 365;
107 | if (TIME_MAX - day < (tm_year - year) / 4 + 1)
108 | overflow++;
109 | day += (tm_year - year) / 4 + ((tm_year % 4) && tm_year % 4 < year % 4);
110 | day -= (tm_year - year) / 100
111 | + ((tm_year % 100) && tm_year % 100 < year % 100);
112 | day += (tm_year - year) / 400
113 | + ((tm_year % 400) && tm_year % 400 < year % 400);
114 |
115 | yday = month = 0;
116 | while (month < tm->tm_mon) {
117 | yday += month_tab[IS_LEAP_YEAR(tm_year)][month];
118 | month++;
119 | }
120 | yday += (tm->tm_mday - 1);
121 | if (day + yday < 0)
122 | overflow++;
123 | day += yday;
124 |
125 | tm->tm_yday = yday;
126 | tm->tm_wday = (day + 4) % 7;
127 |
128 | seconds = ((tm->tm_hour * 60L) + tm->tm_min) * 60L + tm->tm_sec;
129 |
130 | if ((TIME_MAX - seconds) / SECS_IN_DAY < day)
131 | overflow++;
132 | seconds += day * SECS_IN_DAY;
133 |
134 | if (overflow)
135 | return (blynk_time_t) -1;
136 |
137 | if ((blynk_time_t) seconds != seconds)
138 | return (blynk_time_t) -1;
139 | return (blynk_time_t) seconds;
140 | }
141 |
142 | int blynk_compute_sun(int8_t month, int8_t day, double latitude, double longitude, bool rise)
143 | {
144 | float y, decl, eqt, ha, lon, lat;
145 | uint8_t a;
146 | int minutes;
147 |
148 | month -= 1;
149 | day -= 1;
150 | lat = latitude/57.295779513082322;
151 | lon = -longitude/57.295779513082322;
152 |
153 | //approximate hour;
154 | a = (rise) ? 18 : 6;
155 |
156 | // approximate day of year
157 | y = month * 30.4375 + day + a/24.0; // 0... 365
158 |
159 | // compute fractional year
160 | y *= 1.718771839885e-02; // 0... 1
161 |
162 | // compute equation of time... .43068174
163 | eqt = 229.18 * (0.000075+0.001868*cos(y) -0.032077*sin(y) -0.014615*cos(y*2) -0.040849*sin(y* 2) );
164 |
165 | // compute solar declination... -0.398272
166 | decl = 0.006918-0.399912*cos(y)+0.070257*sin(y)-0.006758*cos(y*2)+0.000907*sin(y*2)-0.002697*cos(y*3)+0.00148*sin(y*3);
167 |
168 | //compute hour angle
169 | ha = ( cos(1.585340737228125) / (cos(lat)*cos(decl)) -tan(lat) * tan(decl) );
170 |
171 | if (fabs(ha) > 1.0) { // we're in the (ant)arctic and there is no rise(or set) today!
172 | return -1;
173 | }
174 |
175 | ha = acos(ha);
176 | if(!rise) ha = -ha;
177 |
178 | // compute minutes from midnight
179 | minutes = 720+4*(lon-ha)*57.295779513082322-eqt;
180 |
181 | return minutes;
182 | }
183 |
184 |
--------------------------------------------------------------------------------
/src/utility/BlynkTimer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * SimpleTimer.cpp
3 | *
4 | * SimpleTimer - A timer library for Arduino.
5 | * Author: mromani@ottotecnica.com
6 | * Copyright (c) 2010 OTTOTECNICA Italy
7 | *
8 | * Callback function parameters added & compiler warnings
9 | * removed by Bill Knight 20March2017
10 | *
11 | * This library is free software; you can redistribute it
12 | * and/or modify it under the terms of the GNU Lesser
13 | * General Public License as published by the Free Software
14 | * Foundation; either version 2.1 of the License, or (at
15 | * your option) any later version.
16 | *
17 | * This library is distributed in the hope that it will
18 | * be useful, but WITHOUT ANY WARRANTY; without even the
19 | * implied warranty of MERCHANTABILITY or FITNESS FOR A
20 | * PARTICULAR PURPOSE. See the GNU Lesser General Public
21 | * License for more details.
22 | *
23 | * You should have received a copy of the GNU Lesser
24 | * General Public License along with this library; if not,
25 | * write to the Free Software Foundation, Inc.,
26 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 | */
28 |
29 |
30 | #include "Blynk/BlynkTimer.h"
31 | #include
32 |
33 | // Select time function:
34 | //static inline unsigned long elapsed() { return micros(); }
35 | static inline unsigned long elapsed() { return BlynkMillis(); }
36 |
37 |
38 | SimpleTimer::SimpleTimer()
39 | : numTimers (-1)
40 | {
41 | }
42 |
43 | void SimpleTimer::init() {
44 | unsigned long current_millis = elapsed();
45 |
46 | for (int i = 0; i < MAX_TIMERS; i++) {
47 | timer[i] = timer_t();
48 | timer[i].prev_millis = current_millis;
49 | }
50 |
51 | numTimers = 0;
52 | }
53 |
54 |
55 | void SimpleTimer::run() {
56 | int i;
57 | unsigned long current_millis;
58 |
59 | // get current time
60 | current_millis = elapsed();
61 |
62 | for (i = 0; i < MAX_TIMERS; i++) {
63 |
64 | timer[i].toBeCalled = DEFCALL_DONTRUN;
65 |
66 | // jump over empty slots
67 | if (isValidTimer(i)) {
68 |
69 | // is it time to process this timer ?
70 | // see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592
71 |
72 | if ((current_millis - timer[i].prev_millis) >= timer[i].delay) {
73 |
74 | if (timer[i].delay) {
75 | unsigned long skipTimes = (current_millis - timer[i].prev_millis) / timer[i].delay;
76 | // update time
77 | timer[i].prev_millis += timer[i].delay * skipTimes;
78 | } else {
79 | timer[i].prev_millis = current_millis;
80 | }
81 |
82 | // check if the timer callback has to be executed
83 | if (timer[i].enabled) {
84 |
85 | // "run forever" timers must always be executed
86 | if (timer[i].maxNumRuns == RUN_FOREVER) {
87 | timer[i].toBeCalled = DEFCALL_RUNONLY;
88 | }
89 | // other timers get executed the specified number of times
90 | else if (timer[i].numRuns < timer[i].maxNumRuns) {
91 | timer[i].toBeCalled = DEFCALL_RUNONLY;
92 | timer[i].numRuns++;
93 |
94 | // after the last run, delete the timer
95 | if (timer[i].numRuns >= timer[i].maxNumRuns) {
96 | timer[i].toBeCalled = DEFCALL_RUNANDDEL;
97 | }
98 | }
99 | }
100 | }
101 | }
102 | }
103 |
104 | for (i = 0; i < MAX_TIMERS; i++) {
105 | if (timer[i].toBeCalled == DEFCALL_DONTRUN)
106 | continue;
107 |
108 | if (timer[i].hasParam)
109 | timer[i].callback_p(timer[i].param);
110 | else
111 | timer[i].callback();
112 |
113 | if (timer[i].toBeCalled == DEFCALL_RUNANDDEL)
114 | deleteTimer(i);
115 | }
116 | }
117 |
118 |
119 | // find the first available slot
120 | // return -1 if none found
121 | int SimpleTimer::findFirstFreeSlot() {
122 | // all slots are used
123 | if (numTimers >= MAX_TIMERS) {
124 | return -1;
125 | }
126 |
127 | // return the first slot with no callback (i.e. free)
128 | for (int i = 0; i < MAX_TIMERS; i++) {
129 | if (!isValidTimer(i)) {
130 | return i;
131 | }
132 | }
133 |
134 | // no free slots found
135 | return -1;
136 | }
137 |
138 |
139 | int SimpleTimer::setupTimer(unsigned long d, const timer_callback& f, unsigned n) {
140 | int freeTimer;
141 |
142 | if (numTimers < 0) {
143 | init();
144 | }
145 |
146 | freeTimer = findFirstFreeSlot();
147 | if (freeTimer < 0) {
148 | return -1;
149 | }
150 |
151 | if (f == NULL) {
152 | return -1;
153 | }
154 |
155 | timer[freeTimer].delay = d;
156 | timer[freeTimer].callback = f;
157 | timer[freeTimer].hasParam = false;
158 | timer[freeTimer].maxNumRuns = n;
159 | timer[freeTimer].enabled = true;
160 | timer[freeTimer].prev_millis = elapsed();
161 |
162 | numTimers++;
163 |
164 | return freeTimer;
165 | }
166 |
167 | int SimpleTimer::setupTimer(unsigned long d, timer_callback_p f, void* p, unsigned n) {
168 | int freeTimer;
169 |
170 | if (numTimers < 0) {
171 | init();
172 | }
173 |
174 | freeTimer = findFirstFreeSlot();
175 | if (freeTimer < 0) {
176 | return -1;
177 | }
178 |
179 | if (f == NULL) {
180 | return -1;
181 | }
182 |
183 | timer[freeTimer].delay = d;
184 | timer[freeTimer].callback_p = f;
185 | timer[freeTimer].param = p;
186 | timer[freeTimer].hasParam = true;
187 | timer[freeTimer].maxNumRuns = n;
188 | timer[freeTimer].enabled = true;
189 | timer[freeTimer].prev_millis = elapsed();
190 |
191 | numTimers++;
192 |
193 | return freeTimer;
194 | }
195 |
196 | bool SimpleTimer::changeInterval(unsigned numTimer, unsigned long d) {
197 | if (numTimer >= MAX_TIMERS) {
198 | return false;
199 | }
200 |
201 | // Updates interval of existing specified timer
202 | if (isValidTimer(numTimer)) {
203 | timer[numTimer].delay = d;
204 | timer[numTimer].prev_millis = elapsed();
205 | return true;
206 | }
207 | // false return for non-used numTimer, no callback
208 | return false;
209 | }
210 |
211 | void SimpleTimer::deleteTimer(unsigned timerId) {
212 | if (timerId >= MAX_TIMERS) {
213 | return;
214 | }
215 |
216 | // nothing to delete if no timers are in use
217 | if (numTimers == 0) {
218 | return;
219 | }
220 |
221 | // don't decrease the number of timers if the
222 | // specified slot is already empty
223 | if (isValidTimer(timerId)) {
224 | timer[timerId] = timer_t();
225 | timer[timerId].prev_millis = elapsed();
226 |
227 | // update number of timers
228 | numTimers--;
229 | }
230 | }
231 |
232 |
233 | // function contributed by code@rowansimms.com
234 | void SimpleTimer::restartTimer(unsigned numTimer) {
235 | if (numTimer >= MAX_TIMERS) {
236 | return;
237 | }
238 |
239 | timer[numTimer].prev_millis = elapsed();
240 | }
241 |
242 | void SimpleTimer::executeNow(unsigned numTimer) {
243 | if (numTimer >= MAX_TIMERS) {
244 | return;
245 | }
246 |
247 | timer[numTimer].prev_millis = elapsed() - timer[numTimer].delay;
248 | }
249 |
250 | bool SimpleTimer::isEnabled(unsigned numTimer) {
251 | if (numTimer >= MAX_TIMERS) {
252 | return false;
253 | }
254 |
255 | return timer[numTimer].enabled;
256 | }
257 |
258 |
259 | void SimpleTimer::enable(unsigned numTimer) {
260 | if (numTimer >= MAX_TIMERS) {
261 | return;
262 | }
263 |
264 | timer[numTimer].enabled = true;
265 | }
266 |
267 |
268 | void SimpleTimer::disable(unsigned numTimer) {
269 | if (numTimer >= MAX_TIMERS) {
270 | return;
271 | }
272 |
273 | timer[numTimer].enabled = false;
274 | }
275 |
276 | void SimpleTimer::enableAll() {
277 | // Enable all timers with a callback assigned (used)
278 | for (int i = 0; i < MAX_TIMERS; i++) {
279 | if (isValidTimer(i) && timer[i].numRuns == RUN_FOREVER) {
280 | timer[i].enabled = true;
281 | }
282 | }
283 | }
284 |
285 | void SimpleTimer::disableAll() {
286 | // Disable all timers with a callback assigned (used)
287 | for (int i = 0; i < MAX_TIMERS; i++) {
288 | if (isValidTimer(i) && timer[i].numRuns == RUN_FOREVER) {
289 | timer[i].enabled = false;
290 | }
291 | }
292 | }
293 |
294 | void SimpleTimer::toggle(unsigned numTimer) {
295 | if (numTimer >= MAX_TIMERS) {
296 | return;
297 | }
298 |
299 | timer[numTimer].enabled = !timer[numTimer].enabled;
300 | }
301 |
302 |
303 | unsigned SimpleTimer::getNumTimers() {
304 | return numTimers;
305 | }
306 |
--------------------------------------------------------------------------------
/src/utility/BlynkUtility.h:
--------------------------------------------------------------------------------
1 |
2 | #warning "Please include Blynk/BlynkUtility.h, instead of utility/BlynkUtility.h"
3 | #include
4 |
--------------------------------------------------------------------------------
/verification.txt:
--------------------------------------------------------------------------------
1 |
2 | === VERIFICATION HOWTO ===
3 |
4 | 1. Install the Blynk App on your Android/iOS smartphone
5 | 2. Login to Bynk App. If you don't have an account, please create one (specify a correct email)
6 | 3. Create a new project (you should get an email with Auth Token)
7 | 4. Follow this guide: http://docs.blynk.cc/#hardware-set-ups-particle
8 |
--------------------------------------------------------------------------------