├── README.md
├── examples
├── AnalogJSON
│ └── AnalogJSON.ino
├── Blink
│ └── Blink.ino
├── BlinkSendCommand
│ └── BlinkSendCommand.ino
├── SlaveRespondTele
│ └── ClientRespondTele.ino
└── SlaveSendCommand
│ └── SlaveSendCommand.ino
├── keywords.txt
├── library.json
├── library.properties
└── src
├── TasmotaClient.cpp
└── TasmotaClient.h
/README.md:
--------------------------------------------------------------------------------
1 | # TasmotaClient
2 |
3 | This library adds support for the TasmotaClient driver integrated into Tasmota from https://github.com/arendst/Tasmota
4 |
5 | Read the TasmotaClient wiki article on the Tasmota wiki from https://tasmota.github.io/docs/#/TasmotaSlave to see how to enable support for this library inside Tasmota.
6 |
7 | Edit:(docs are not up to date and dokuments the old TasmotaSlave comands) (2020-11-21)
8 | # Change Log
9 |
10 | ### 2019-11-29 - v0.0.2 (Pre-release)
11 |
12 | - Add support for sending commands to Tasmota using ExecuteCommand(char *cmnd)
13 |
--------------------------------------------------------------------------------
/examples/AnalogJSON/AnalogJSON.ino:
--------------------------------------------------------------------------------
1 | /*
2 | AnalogJSON.ino - Example on how to send a JSON back to a Tasmota device
3 | which requested it on teleperiod.
4 |
5 | Copyright (C) 2019 Andre Thomas
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | #include
22 | #include
23 |
24 | TasmotaClient client(&Serial);
25 |
26 | /*******************************************************************\
27 | * user_FUNC_JSON creates the JSON which will be sent back to the
28 | * Tasmota device upon receiving a request to do so
29 | \*******************************************************************/
30 |
31 | void user_FUNC_JSON(void)
32 | {
33 | uint8_t a = 0;
34 | char myjson[100];
35 | sprintf(myjson,"{\"A0\": %u, \"A1\": %u, \"A2\": %u, \"A3\": %u, \"A4\": %u, \"A5\": %u, \"A6\": %u, \"A7\": %u}", analogRead(A0), analogRead(A1), analogRead(A2), analogRead(A3), analogRead(A4), analogRead(A5), analogRead(A6), analogRead(A7));
36 | client.sendJSON(myjson);
37 | }
38 |
39 | /*******************************************************************\
40 | * Normal setup() function for Arduino to configure the serial port
41 | * speed (which should match what was configured in Tasmota, and
42 | * attach the function which will be called when the Tasmota device
43 | * reuqests a new JSON (usually on Teleperiod on Tasmota device)
44 | \*******************************************************************/
45 |
46 | void setup() {
47 | // Configure the serial port speed
48 | Serial.begin(57600);
49 | // Attach the callback function which will provide the JSON to Tasmota
50 | client.attach_FUNC_JSON(user_FUNC_JSON);
51 | }
52 |
53 | void loop() {
54 | // Call the client loop function every so often to process incoming requests
55 | client.loop();
56 | }
57 |
--------------------------------------------------------------------------------
/examples/Blink/Blink.ino:
--------------------------------------------------------------------------------
1 | /*
2 | Blink.ino - Example for TasmotaClient receiving the FUNC_EVERY_SECOND
3 | callback and respond by toggling the LED as configured.
4 |
5 | Copyright (C) 2019 Andre Thomas
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 | */
20 |
21 | #include
22 | #include
23 |
24 | TasmotaClient client(&Serial);
25 |
26 | bool ledstate = false;
27 |
28 | /*******************************************************************\
29 | * Function which will be called when Tasmota sends a
30 | * FUNC_EVERY_SECOND command
31 | \*******************************************************************/
32 |
33 | void user_FUNC_EVERY_SECOND(void)
34 | {
35 | if (ledstate) {
36 | ledstate = false;
37 | digitalWrite(LED_BUILTIN, LOW);
38 | } else {
39 | ledstate = true;
40 | digitalWrite(LED_BUILTIN, HIGH);
41 | }
42 | }
43 |
44 | /*******************************************************************\
45 | * Normal setup() function for Arduino to configure the serial port
46 | * speed (which should match what was configured in Tasmota) and
47 | * attach any callback functions associated with specific requests
48 | * or commands that are sent by Tasmota.
49 | \*******************************************************************/
50 |
51 | void setup() {
52 | // Configure serial port
53 | Serial.begin(57600);
54 | // We're going to use the builtin LED so lets configure the pin as OUTPUT
55 | pinMode(LED_BUILTIN, OUTPUT);
56 | // Attach the callback function which will be called when Tasmota requests it
57 | client.attach_FUNC_EVERY_SECOND(user_FUNC_EVERY_SECOND);
58 | }
59 |
60 | void loop() {
61 | // Call the client loop function every so often to process incoming requests
62 | client.loop();
63 | }
64 |
--------------------------------------------------------------------------------
/examples/BlinkSendCommand/BlinkSendCommand.ino:
--------------------------------------------------------------------------------
1 | /*
2 | BlinkRelay.ino - Example for TasmotaClient receiving the FUNC_EVERY_SECOND
3 | callback and respond by toggling the LED as configured.
4 | This example also extends sending commands back to the
5 | Tasmota device by which could be any command normally
6 | executed from the console but in this particular example
7 | we just use a simple publish command.
8 |
9 | Copyright (C) 2019 Andre Thomas
10 |
11 | This program is free software: you can redistribute it and/or modify
12 | it under the terms of the GNU General Public License as published by
13 | the Free Software Foundation, either version 3 of the License, or
14 | (at your option) any later version.
15 |
16 | This program is distributed in the hope that it will be useful,
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | GNU General Public License for more details.
20 |
21 | You should have received a copy of the GNU General Public License
22 | along with this program. If not, see .
23 | */
24 |
25 | #include
26 | #include
27 |
28 | TasmotaClient client(&Serial);
29 |
30 | bool ledstate = false;
31 |
32 | /*******************************************************************\
33 | * Function which will be called when Tasmota sends a
34 | * FUNC_EVERY_SECOND command
35 | \*******************************************************************/
36 |
37 | void user_FUNC_EVERY_SECOND(void)
38 | {
39 | if (ledstate) {
40 | ledstate = false;
41 | digitalWrite(LED_BUILTIN, LOW);
42 | } else {
43 | ledstate = true;
44 | digitalWrite(LED_BUILTIN, HIGH);
45 | }
46 | if (ledstate) {
47 | client.ExecuteCommand((char*)"publish tele/mytopic/power on");
48 | } else {
49 | client.ExecuteCommand((char*)"publish tele/mytopic/power off");
50 | }
51 | }
52 |
53 | /*******************************************************************\
54 | * Normal setup() function for Arduino to configure the serial port
55 | * speed (which should match what was configured in Tasmota) and
56 | * attach any callback functions associated with specific requests
57 | * or commands that are sent by Tasmota.
58 | \*******************************************************************/
59 |
60 | void setup() {
61 | // Configure serial port
62 | Serial.begin(57600);
63 | // We're going to use the builtin LED so lets configure the pin as OUTPUT
64 | pinMode(LED_BUILTIN, OUTPUT);
65 | // Attach the callback function which will be called when Tasmota requests it
66 | client.attach_FUNC_EVERY_SECOND(user_FUNC_EVERY_SECOND);
67 | }
68 |
69 | void loop() {
70 | // Call the client loop function every so often to process incoming requests
71 | client.loop();
72 | }
73 |
--------------------------------------------------------------------------------
/examples/SlaveRespondTele/ClientRespondTele.ino:
--------------------------------------------------------------------------------
1 | /*
2 | ClientRespondTele.ino - Example for TasmotaClient to respond to ClientSend ON and
3 | ClientSend OFF commands via console or telemetry.
4 | In this example the ON and OFF is case sensitive so needs
5 | to be sent in capital letters from the Tasmota device.
6 | Upon receiving ON/OFF the client will turn the LED on/off
7 | respectively and respond with a telemetry message sent
8 | back to Tasmota that will be published for telemetry
9 | and rules processing on the Tasmota device.
10 |
11 | Copyright (C) 2019 Andre Thomas
12 |
13 | This program is free software: you can redistribute it and/or modify
14 | it under the terms of the GNU General Public License as published by
15 | the Free Software Foundation, either version 3 of the License, or
16 | (at your option) any later version.
17 |
18 | This program is distributed in the hope that it will be useful,
19 | but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | GNU General Public License for more details.
22 |
23 | You should have received a copy of the GNU General Public License
24 | along with this program. If not, see .
25 | */
26 |
27 | #include
28 | #include
29 |
30 | TasmotaClient client(&Serial);
31 |
32 | /*******************************************************************\
33 | * Normal setup() function for Arduino to configure the serial port
34 | * speed (which should match what was configured in Tasmota) and
35 | * attach any callback functions associated with specific requests
36 | * or commands that are sent by Tasmota.
37 | \*******************************************************************/
38 |
39 | void setup() {
40 | // Configure the LED pin as OUTPUT
41 | pinMode(LED_BUILTIN, OUTPUT);
42 | // Configure the serial port for the correct baud rate
43 | Serial.begin(57600);
44 | // Attach the callback function which will be called when Tasmota requests it
45 | client.attach_FUNC_COMMAND_SEND(user_FUNC_RECEIVE);
46 | }
47 |
48 | /*******************************************************************\
49 | * Function which will be called when Tasmota sends a
50 | * ClientSend command
51 | \*******************************************************************/
52 |
53 | void user_FUNC_RECEIVE(char *data)
54 | {
55 | if (!strcmp(data, "ON")) { // ClientSend ON
56 | digitalWrite(LED_BUILTIN, HIGH);
57 | char response[20];
58 | sprintf(response,"{\"LED\":\"ON\"}");
59 | client.SendTele(response);
60 | }
61 | if (!strcmp(data, "OFF")) { // ClientSend OFF
62 | digitalWrite(LED_BUILTIN, LOW);
63 | char response[20];
64 | sprintf(response,"{\"LED\":\"OFF\"}");
65 | client.SendTele(response);
66 | }
67 | }
68 |
69 | void loop() {
70 | client.loop(); // Call the client loop function every so often to process incoming requests
71 | }
72 |
--------------------------------------------------------------------------------
/examples/SlaveSendCommand/SlaveSendCommand.ino:
--------------------------------------------------------------------------------
1 | /*
2 | SlaveSendCommand.ino - Example for TasmotaSlave to respond to SlaveSend ON and
3 | SlaveSend OFF commands via console or telemetry.
4 | In this example the ON and OFF is case sensitive so needs
5 | to be sent in capital letters from the Tasmota device.
6 | Upon receiving ON/OFF the slave will turn the LED on/off
7 | respectively.
8 |
9 | A second function callback is also attached which will
10 | respond with a JSON message on Tasmota Teleperiod when
11 | requested from the Tasmota device.
12 |
13 | Copyright (C) 2019 Andre Thomas
14 | This program is free software: you can redistribute it and/or modify
15 | it under the terms of the GNU General Public License as published by
16 | the Free Software Foundation, either version 3 of the License, or
17 | (at your option) any later version.
18 | This program is distributed in the hope that it will be useful,
19 | but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | GNU General Public License for more details.
22 | You should have received a copy of the GNU General Public License
23 | along with this program. If not, see .
24 | */
25 |
26 | #include
27 | #include
28 |
29 | TasmotaSlave slave(&Serial);
30 |
31 | /*******************************************************************\
32 | * Normal setup() function for Arduino to configure the serial port
33 | * speed (which should match what was configured in Tasmota) and
34 | * attach any callback functions associated with specific requests
35 | * or commands that are sent by Tasmota.
36 | \*******************************************************************/
37 |
38 | void setup() {
39 | // Configure the LED pin as OUTPUT
40 | pinMode(LED_BUILTIN, OUTPUT);
41 | // Configure the serial port baud rate
42 | Serial.begin(57600);
43 | // Attach the function which will respond to the JSON request from Tasmota
44 | slave.attach_FUNC_JSON(user_FUNC_JSON);
45 | // Attach the function which will be called when the Tasmota device sends data using SlaveSend command
46 | slave.attach_FUNC_COMMAND_SEND(user_FUNC_RECEIVE);
47 | }
48 |
49 | /*******************************************************************\
50 | * Function which will be called when this slave device receives a
51 | * SlaveSend command from the Tasmota device.
52 | \*******************************************************************/
53 |
54 | void user_FUNC_RECEIVE(char *data)
55 | {
56 | if (!strcmp(data, "ON")) { // SlaveSend ON
57 | digitalWrite(LED_BUILTIN, HIGH);
58 | }
59 | if (!strcmp(data, "OFF")) { // SlaveSend OFF
60 | digitalWrite(LED_BUILTIN, LOW);
61 | }
62 | }
63 |
64 | /*******************************************************************\
65 | * user_FUNC_JSON creates the JSON which will be sent back to the
66 | * Tasmota device upon receiving a request to do so
67 | \*******************************************************************/
68 |
69 | void user_FUNC_JSON(void)
70 | {
71 | uint8_t a = 0;
72 | char myjson[100];
73 | sprintf(myjson,"{\"A0\": %u, \"A1\": %u, \"A2\": %u, \"A3\": %u, \"A4\": %u, \"A5\": %u, \"A6\": %u, \"A7\": %u}", analogRead(A0), analogRead(A1), analogRead(A2), analogRead(A3), analogRead(A4), analogRead(A5), analogRead(A6), analogRead(A7));
74 | slave.sendJSON(myjson);
75 | }
76 |
77 | void loop() {
78 | // Call the slave loop every so often to process any incoming requests
79 | slave.loop();
80 | }
81 |
--------------------------------------------------------------------------------
/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map for TasmotaClient
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 |
9 | TasmotaClient KEYWORD1
10 |
11 | #######################################
12 | # Methods and Functions (KEYWORD2)
13 | #######################################
14 |
15 | receive_buffer KEYWORD2
16 | sendFeatures KEYWORD2
17 | sendJSON KEYWORD2
18 | attach_FUNC_JSON KEYWORD2
19 | attach_FUNC_EVERY_SECOND KEYWORD2
20 | attach_FUNC_EVERY_100_MSECOND KEYWORD2
21 | attach_FUNC_COMMAND_SEND KEYWORD2
22 | SendCommand KEYWORD2
23 | SendTele KEYWORD2
24 | waitforbytes KEYWORD2
25 | ProcessSend KEYWORD2
26 | ProcessCommand KEYWORD2
27 | ExecuteCommand KEYWORD2
28 | loop KEYWORD2
29 |
30 | #######################################
31 | # Constants (LITERAL1)
32 | #######################################
33 |
34 |
--------------------------------------------------------------------------------
/library.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "TasmotaClient",
3 | "version": "0.0.2",
4 | "keywords": [
5 | "serial", "io", "TasmotaClient"
6 | ],
7 | "description": "TasmotaClient Driver Library",
8 | "repository":
9 | {
10 | "type": "git",
11 | "url": "https://github.com/andrethomas/TasmotaSlave"
12 | },
13 | "frameworks": "arduino"
14 | }
15 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=TasmotaSlave
2 | version=0.0.2
3 | author=Andre Thomas
4 | maintainer=Andre Thomas
5 | sentence=TasmotaSlave Driver Library for Arduino
6 | paragraph=
7 | category=Signal Input/Output
8 | url=
9 | architectures=avr,esp8266,esp32,samd,sam,stm32,STM32F1,megaavr,teensy,samd_beta,atmelavr,arm,stm32f4,atmelsam,STM32F4,megaAVR,esp
10 |
--------------------------------------------------------------------------------
/src/TasmotaClient.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | TasmotaClient.cpp - Library for microcontrollers enclientd by Tasmota
3 |
4 | Copyright (C) 2019 Andre Thomas
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 |
23 | /*************************************************\
24 | * TasmotaClient shared structures
25 | \*************************************************/
26 |
27 | typedef union {
28 | uint32_t data;
29 | struct {
30 | uint32_t func_json_append : 1; // Supports FUNC_JSON_APPEND callback
31 | uint32_t func_every_second : 1; // Supports FUNC_EVERY_SECOND callback (No JSON)
32 | uint32_t func_every_100_msecond : 1; // Supports FUNC_EVERY_100_MSECOND callback (No JSON)
33 | uint32_t func_client_send : 1; // Supports FUNC_COMMAND
34 | uint32_t spare4 : 1;
35 | uint32_t spare5 : 1;
36 | uint32_t spare6 : 1;
37 | uint32_t spare7 : 1;
38 | uint32_t spare8 : 1;
39 | uint32_t spare9 : 1;
40 | uint32_t spare10 : 1;
41 | uint32_t spare11 : 1;
42 | uint32_t spare12 : 1;
43 | uint32_t spare13 : 1;
44 | uint32_t spare14 : 1;
45 | uint32_t spare15 : 1;
46 | uint32_t spare16 : 1;
47 | uint32_t spare17 : 1;
48 | uint32_t spare18 : 1;
49 | uint32_t spare19 : 1;
50 | uint32_t spare20 : 1;
51 | uint32_t spare21 : 1;
52 | uint32_t spare22 : 1;
53 | uint32_t spare23 : 1;
54 | uint32_t spare24 : 1;
55 | uint32_t spare25 : 1;
56 | uint32_t spare26 : 1;
57 | uint32_t spare27 : 1;
58 | uint32_t spare28 : 1;
59 | uint32_t spare29 : 1;
60 | uint32_t spare30 : 1;
61 | uint32_t spare31 : 1;
62 | };
63 | } FeatureCfg;
64 |
65 | /**************************************************\
66 | * Settings structure - MUST remain 4 byte aligned
67 | \**************************************************/
68 |
69 | struct FEATURES {
70 | uint32_t features_version;
71 | FeatureCfg features;
72 | } Settings;
73 |
74 | /********************************************************************************\
75 | * Command structure for sending/receiving commands - MUST remain 4 byte aligned
76 | \********************************************************************************/
77 |
78 | struct COMMAND {
79 | uint8_t command;
80 | uint8_t parameter;
81 | uint8_t unused2;
82 | uint8_t unused3;
83 | } Command;
84 |
85 | TasmotaClient::TasmotaClient(HardwareSerial *device)
86 | {
87 | serial = device;
88 | Settings.features_version = TASMOTA_CLIENT_LIB_VERSION;
89 | Settings.features.func_json_append = 0;
90 | Settings.features.func_every_second = 0;
91 | Settings.features.func_every_100_msecond = 0;
92 | Settings.features.func_client_send = 0;
93 | Settings.features.spare4 = 0;
94 | Settings.features.spare5 = 0;
95 | Settings.features.spare6 = 0;
96 | Settings.features.spare7 = 0;
97 | Settings.features.spare8 = 0;
98 | Settings.features.spare9 = 0;
99 | Settings.features.spare10 = 0;
100 | Settings.features.spare11 = 0;
101 | Settings.features.spare12 = 0;
102 | Settings.features.spare13 = 0;
103 | Settings.features.spare14 = 0;
104 | Settings.features.spare15 = 0;
105 | Settings.features.spare16 = 0;
106 | Settings.features.spare17 = 0;
107 | Settings.features.spare18 = 0;
108 | Settings.features.spare19 = 0;
109 | Settings.features.spare20 = 0;
110 | Settings.features.spare21 = 0;
111 | Settings.features.spare22 = 0;
112 | Settings.features.spare23 = 0;
113 | Settings.features.spare24 = 0;
114 | Settings.features.spare25 = 0;
115 | Settings.features.spare26 = 0;
116 | Settings.features.spare27 = 0;
117 | Settings.features.spare28 = 0;
118 | Settings.features.spare29 = 0;
119 | Settings.features.spare30 = 0;
120 | Settings.features.spare31 = 0;
121 | }
122 |
123 | void TasmotaClient::sendFeatures(void)
124 | {
125 | char buffer[sizeof(Settings)];
126 | memcpy(&buffer, &Settings, sizeof(Settings));
127 | serial->write(char(PARAM_DATA_START));
128 | for (uint8_t ca = 0; ca < sizeof(buffer); ca++) {
129 | serial->write(char(buffer[ca]));
130 | }
131 | serial->write(char(PARAM_DATA_END));
132 | }
133 |
134 | void TasmotaClient::sendJSON(char *json)
135 | {
136 | serial->write(char(PARAM_DATA_START));
137 | for (uint8_t ca = 0; ca < strlen(json); ca++) {
138 | serial->write(json[ca]);
139 | }
140 | serial->write(char(PARAM_DATA_END));
141 | }
142 |
143 | void TasmotaClient::attach_FUNC_JSON(callbackFunc func)
144 | {
145 | Settings.features.func_json_append = 1;
146 | FUNC_JSON = func;
147 | }
148 |
149 | void TasmotaClient::attach_FUNC_EVERY_SECOND(callbackFunc func)
150 | {
151 | Settings.features.func_every_second = 1;
152 | FUNC_EVERY_SECOND = func;
153 | }
154 |
155 | void TasmotaClient::attach_FUNC_EVERY_100_MSECOND(callbackFunc func)
156 | {
157 | Settings.features.func_every_100_msecond = 1;
158 | FUNC_EVERY_100_MSECOND = func;
159 | }
160 |
161 | void TasmotaClient::attach_FUNC_COMMAND_SEND(callbackFunc1 func)
162 | {
163 | Settings.features.func_client_send = 1;
164 | FUNC_SEND = func;
165 | }
166 |
167 | uint8_t TasmotaClient::waitforbytes(uint16_t num, uint16_t timeout)
168 | {
169 | uint16_t timer = 0;
170 | while (timer < timeout) {
171 | if (serial->available() > (int)(num-1)) {
172 | return 1;
173 | }
174 | delay(1);
175 | timer++;
176 | }
177 | return 0;
178 | }
179 |
180 | void TasmotaClient::ProcessSend(uint8_t sz)
181 | {
182 | if (waitforbytes(sz+2,50)) {
183 | serial->read(); // read leading character
184 | for (uint8_t idx = 0; idx < sz; idx++) {
185 | receive_buffer[idx] = serial->read();
186 | }
187 | serial->read(); // read trailing byte
188 | receive_buffer[sz] = '\0';
189 | FUNC_SEND(receive_buffer);
190 | }
191 | }
192 |
193 | void TasmotaClient::ProcessCommand(void)
194 | {
195 | if (waitforbytes(sizeof(Command)+1, 100)) {
196 | char buffer[sizeof(Command)];
197 | for (uint8_t idx = 0; idx < sizeof(Command); idx++) {
198 | buffer[idx] = serial->read();
199 | }
200 | serial->read(); // Remove end of command character
201 | memcpy(&Command, &buffer, sizeof(Command));
202 | switch (Command.command) {
203 | case CMND_FEATURES:
204 | sendFeatures();
205 | break;
206 | case CMND_FUNC_JSON:
207 | FUNC_JSON();
208 | break;
209 | case CMND_FUNC_EVERY_SECOND:
210 | FUNC_EVERY_SECOND();
211 | break;
212 | case CMND_FUNC_EVERY_100_MSECOND:
213 | FUNC_EVERY_100_MSECOND();
214 | break;
215 | case CMND_CLIENT_SEND:
216 | ProcessSend(Command.parameter);
217 | break;
218 | default:
219 | break;
220 | }
221 | }
222 | }
223 |
224 | void TasmotaClient::SendCommand(uint8_t cmnd, uint8_t param)
225 | {
226 | Command.command = cmnd;
227 | Command.parameter = param;
228 | Command.unused2 = 0;
229 | Command.unused3 = 0;
230 | uint8_t tmp[sizeof(Command)];
231 | memcpy(&tmp, &Command, sizeof(Command));
232 | serial->write(char(CMND_START));
233 | for (uint8_t idx = 0; idx < sizeof(Command); idx++) {
234 | serial->write(tmp[idx]);
235 | }
236 | serial->write(char(CMND_END));
237 | }
238 |
239 | void TasmotaClient::SendTele(char *data)
240 | {
241 | SendCommand(CMND_PUBLISH_TELE, strlen(data));
242 | serial->write(char(PARAM_DATA_START));
243 | for (uint8_t idx = 0; idx < strlen(data); idx++) {
244 | serial->write(data[idx]);
245 | }
246 | serial->write(char(PARAM_DATA_END));
247 | }
248 |
249 | void TasmotaClient::ExecuteCommand(char *cmnd)
250 | {
251 | SendCommand(CMND_EXECUTE_CMND, strlen(cmnd));
252 | serial->write(char(PARAM_DATA_START));
253 | for (uint8_t idx = 0; idx < strlen(cmnd); idx++) {
254 | serial->write(cmnd[idx]);
255 | }
256 | serial->write(char(PARAM_DATA_END));
257 | }
258 |
259 | void TasmotaClient::loop(void)
260 | {
261 | if (serial->available()) {
262 | uint8_t cmnd = serial->read();
263 | switch (cmnd) {
264 | case CMND_START:
265 | ProcessCommand();
266 | break;
267 | default:
268 | break;
269 | }
270 | }
271 | }
272 |
--------------------------------------------------------------------------------
/src/TasmotaClient.h:
--------------------------------------------------------------------------------
1 | /*
2 | TasmotaClient.h - Library for microcontrollers enslaved by Tasmota
3 |
4 | Copyright (C) 2019 Andre Thomas
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #ifndef __TASMOTACLIENT_H__
21 | #define __TASMOTACLIENT_H__
22 |
23 | #include
24 |
25 | /*************************************************\
26 | * TasmotaClient Configuration Defaults
27 | \*************************************************/
28 |
29 | #define TASMOTA_CLIENT_LIB_VERSION 20191129
30 |
31 | /*************************************************\
32 | * TasmotaClient Command definitions
33 | \*************************************************/
34 |
35 | #define CMND_START 0xFC
36 | #define CMND_END 0xFD
37 |
38 | #define CMND_FEATURES 0x01
39 | #define CMND_FUNC_JSON 0x02
40 | #define CMND_FUNC_EVERY_SECOND 0x03
41 | #define CMND_FUNC_EVERY_100_MSECOND 0x04
42 | #define CMND_CLIENT_SEND 0x05
43 | #define CMND_PUBLISH_TELE 0x06
44 | #define CMND_EXECUTE_CMND 0x07
45 |
46 | /*************************************************\
47 | * TasmotaClient Parameter defintions
48 | \*************************************************/
49 |
50 | #define PARAM_DATA_START 0xFE
51 | #define PARAM_DATA_END 0xFF
52 |
53 | /*************************************************\
54 | * Prototypes for passing functions as parameters
55 | \*************************************************/
56 |
57 | typedef void (*callbackFunc) (void);
58 | typedef void (*callbackFunc1) (char*);
59 |
60 | /*************************************************\
61 | * TasmotaClient Class
62 | \*************************************************/
63 |
64 | class TasmotaClient {
65 | public:
66 | char receive_buffer[100];
67 | // Constructor
68 | TasmotaClient(HardwareSerial *device = nullptr);
69 | // Sends configured features back to Tasmota so it knows which callbacks are supported
70 | void sendFeatures(void);
71 | // Send JSON back to Tasmota device
72 | void sendJSON(char *json);
73 | // Configure a callback for FUNC_JSON
74 | void attach_FUNC_JSON(callbackFunc func = nullptr);
75 | // Configure a callback for FUNC_EVERY_SECOND
76 | void attach_FUNC_EVERY_SECOND(callbackFunc func = nullptr);
77 | // Configure a callback for FUNC_EVERY_100_MSECOND
78 | void attach_FUNC_EVERY_100_MSECOND(callbackFunc func = nullptr);
79 | // Configure a callback for FUNC_COMMAND_SEND (ClientSend on Tasmota device)
80 | void attach_FUNC_COMMAND_SEND(callbackFunc1 func = nullptr);
81 | // Send command to Tasmota device using the prescribed protocol
82 | void SendCommand(uint8_t cmnd, uint8_t param);
83 | // Send telemetry data back to the Tasmota device
84 | void SendTele(char *data);
85 | // Used internally (should probably be moved to private:)
86 | uint8_t waitforbytes(uint16_t num, uint16_t timeout);
87 | // Used internally to process incoming ClientSend command
88 | void ProcessSend(uint8_t sz);
89 | // Used internally to decode and process incoming commands from the Tasmota device
90 | void ProcessCommand(void);
91 | // Main client loop which needs to be serviced occasionally to process incoming requests
92 | void ExecuteCommand(char *cmnd);
93 | void loop(void);
94 | private:
95 | HardwareSerial *serial;
96 | callbackFunc FUNC_JSON;
97 | callbackFunc FUNC_EVERY_SECOND;
98 | callbackFunc FUNC_EVERY_100_MSECOND;
99 | callbackFunc1 FUNC_SEND;
100 | };
101 |
102 | #endif // __TASMOTACLIENT_H__
103 |
--------------------------------------------------------------------------------