Skip to content

Commit c0269d1

Browse files
committed
generic interface
1 parent e136819 commit c0269d1

File tree

7 files changed

+241
-4
lines changed

7 files changed

+241
-4
lines changed

.github/workflows/build_arduino_ide.yml

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ jobs:
4646
- name: esp32:esp32
4747
source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
4848
sketch-paths: |
49+
- examples/generic-interface
4950
- examples/simple-read-VS1
5051
- examples/simple-read-VS2
5152
- examples/simple-write-VS1

.github/workflows/build_platformio.yml

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jobs:
3535
strategy:
3636
matrix:
3737
example: [
38+
examples/generic-interface/generic-interface.ino
3839
examples/simple-read-VS1/simple-read-VS1.ino,
3940
examples/simple-read-VS2/simple-read-VS2.ino,
4041
examples/simple-write-VS1/simple-write-VS1.ino,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#include <Arduino.h>
2+
3+
#include <VitoWiFi.h>
4+
5+
/*
6+
This example is to show how you could build your own
7+
interface and serves as a compilation test
8+
*/
9+
10+
// Dummy class that has all the methods for VitoWiFi to work
11+
// but doesn't do anything in this case.
12+
// Use as skeleton for your own implementation
13+
class DummyInterface {
14+
public:
15+
bool begin() {
16+
// prepare the interface
17+
// optolink comm at 4800 baud, 8 bits, even parity and 2 stop bits
18+
// called at VitoWiFi::begin()
19+
return true;
20+
}
21+
void end() {
22+
// stop the interface
23+
// called at VitoWiFi::end()
24+
}
25+
std::size_t write(const uint8_t* data, uint8_t length) {
26+
// tries to write `data` with length `length` to the interface
27+
// returns the actually written data
28+
return 0;
29+
}
30+
uint8_t read() {
31+
// read one byte from the interface
32+
// availability of data is checked first
33+
return 0;
34+
}
35+
size_t available() {
36+
// check if data is available
37+
return 0;
38+
}
39+
};
40+
41+
// optolink on Dummy Interface, logging output on UART1 (connected to USB)
42+
DummyInterface dummyInterface;
43+
#define SERIAL1 dummyInterface
44+
#define SERIAL2 Serial
45+
#define SERIALBAUDRATE 115200
46+
47+
VitoWiFi::VitoWiFi<VitoWiFi::VS2> vitoWiFi(&SERIAL1);
48+
bool readValues = false;
49+
uint8_t datapointIndex = 0;
50+
51+
VitoWiFi::Datapoint datapoints[] = {
52+
VitoWiFi::Datapoint("outsidetemp", 0x5525, 2, VitoWiFi::div10),
53+
VitoWiFi::Datapoint("boilertemp", 0x0810, 2, VitoWiFi::div10),
54+
VitoWiFi::Datapoint("pump", 0x2906, 1, VitoWiFi::noconv)
55+
};
56+
57+
void onResponse(const VitoWiFi::PacketVS2& response, const VitoWiFi::Datapoint& request) {
58+
// raw data can be accessed through the 'response' argument
59+
SERIAL2.print("Raw data received:");
60+
const uint8_t* data = response.data();
61+
for (uint8_t i = 0; i < response.dataLength(); ++i) {
62+
SERIAL2.printf(" %02x", data[i]);
63+
}
64+
SERIAL2.print("\n");
65+
66+
// the raw data can be decoded using the datapoint. Be sure to use the correct type
67+
SERIAL2.printf("%s: ", request.name());
68+
if (request.converter() == VitoWiFi::div10) {
69+
float value = request.decode(response);
70+
SERIAL2.printf("%.1f\n", value);
71+
} else if (request.converter() == VitoWiFi::noconv) {
72+
bool value = request.decode(response);
73+
// alternatively, we can just cast response.data()[0] to bool
74+
SERIAL2.printf("%s\n", value ? "ON" : "OFF");
75+
}
76+
}
77+
78+
void onError(VitoWiFi::OptolinkResult error, const VitoWiFi::Datapoint& request) {
79+
SERIAL2.printf("Datapoint \"%s\" error: ", request.name());
80+
if (error == VitoWiFi::OptolinkResult::TIMEOUT) {
81+
SERIAL2.print("timeout\n");
82+
} else if (error == VitoWiFi::OptolinkResult::LENGTH) {
83+
SERIAL2.print("length\n");
84+
} else if (error == VitoWiFi::OptolinkResult::NACK) {
85+
SERIAL2.print("nack\n");
86+
} else if (error == VitoWiFi::OptolinkResult::CRC) {
87+
SERIAL2.print("crc\n");
88+
} else if (error == VitoWiFi::OptolinkResult::ERROR) {
89+
SERIAL2.print("error\n");
90+
}
91+
}
92+
93+
void setup() {
94+
delay(1000);
95+
SERIAL2.begin(SERIALBAUDRATE);
96+
SERIAL2.print("Setting up vitoWiFi\n");
97+
98+
vitoWiFi.onResponse(onResponse);
99+
vitoWiFi.onError(onError);
100+
vitoWiFi.begin();
101+
102+
SERIAL2.print("Setup finished\n");
103+
}
104+
105+
void loop() {
106+
static uint32_t lastMillis = 0;
107+
if (millis() - lastMillis > 60000UL) { // read all values every 60 seconds
108+
lastMillis = millis();
109+
readValues = true;
110+
datapointIndex = 0;
111+
}
112+
113+
if (readValues) {
114+
if (vitoWiFi.read(datapoints[datapointIndex])) {
115+
++datapointIndex;
116+
}
117+
if (datapointIndex == 3) {
118+
readValues = false;
119+
}
120+
}
121+
122+
vitoWiFi.loop();
123+
}

src/GWG/GWG.h

+27-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@ the LICENSE file.
2222
#endif
2323
#elif defined(__linux__)
2424
#include "../Interface/LinuxSerialInterface.h"
25-
#else
26-
#error "platform not supported"
2725
#endif
26+
#include "../Interface/GenericInterface.h"
2827

2928
namespace VitoWiFi {
3029

@@ -41,6 +40,32 @@ class GWG {
4140
#else
4241
explicit GWG(const char* interface);
4342
#endif
43+
template<class C>
44+
GWG(C* interface)
45+
: _state(State::UNDEFINED)
46+
, _currentMillis(vw_millis())
47+
, _lastMillis(_currentMillis)
48+
, _requestTime(0)
49+
, _bytesTransferred(0)
50+
, _interface(nullptr)
51+
, _currentDatapoint(Datapoint(nullptr, 0x0000, 0, VitoWiFi::noconv))
52+
, _currentRequest()
53+
, _responseBuffer(nullptr)
54+
, _allocatedLength(0)
55+
, _onResponseCallback(nullptr)
56+
, _onErrorCallback(nullptr) {
57+
assert(interface != nullptr);
58+
_interface = new(std::nothrow) VitoWiFiInternals::GenericInterface(interface);
59+
if (!_interface) {
60+
vw_log_e("Could not create serial interface");
61+
vw_abort();
62+
}
63+
_responseBuffer = reinterpret_cast<uint8_t*>(malloc(START_PAYLOAD_LENGTH));
64+
if (!_responseBuffer) {
65+
vw_log_e("Could not create response buffer");
66+
vw_abort();
67+
}
68+
}
4469
~GWG();
4570
GWG(const GWG&) = delete;
4671
GWG & operator=(const GWG&) = delete;

src/Interface/GenericInterface.h

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
Copyright (c) 2023 Bert Melis. All rights reserved.
3+
4+
This work is licensed under the terms of the MIT license.
5+
For a copy, see <https://opensource.org/licenses/MIT> or
6+
the LICENSE file.
7+
*/
8+
9+
#pragma once
10+
11+
#include "SerialInterface.h"
12+
13+
namespace VitoWiFiInternals {
14+
15+
template <class C>
16+
class GenericInterface : public SerialInterface {
17+
public:
18+
explicit GenericInterface(C* interface)
19+
: _interface() {
20+
// empty
21+
}
22+
bool begin() override {
23+
return _interface->begin();
24+
}
25+
void end() override {
26+
_interface->end();
27+
}
28+
std::size_t write(const uint8_t* data, uint8_t length) override {
29+
return _interface->write(data, length);
30+
}
31+
uint8_t read() override {
32+
return _interface->read();
33+
}
34+
size_t available() override {
35+
return _interface->available();
36+
}
37+
38+
private:
39+
C* _interface;
40+
};
41+
42+
} // end namespace VitoWiFiInternals

src/VS1/VS1.h

+26
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,32 @@ class VS1 {
4141
#else
4242
explicit VS1(const char* interface);
4343
#endif
44+
template<class C>
45+
VS1(C* interface)
46+
: _state(State::UNDEFINED)
47+
, _currentMillis(vw_millis())
48+
, _lastMillis(_currentMillis)
49+
, _requestTime(0)
50+
, _bytesTransferred(0)
51+
, _interface(nullptr)
52+
, _currentDatapoint(Datapoint(nullptr, 0x0000, 0, VitoWiFi::noconv))
53+
, _currentRequest()
54+
, _responseBuffer(nullptr)
55+
, _allocatedLength(0)
56+
, _onResponseCallback(nullptr)
57+
, _onErrorCallback(nullptr) {
58+
assert(interface != nullptr);
59+
_interface = new(std::nothrow) VitoWiFiInternals::GenericInterface<C>(interface);
60+
if (!_interface) {
61+
vw_log_e("Could not create serial interface");
62+
vw_abort();
63+
}
64+
_responseBuffer = reinterpret_cast<uint8_t*>(malloc(START_PAYLOAD_LENGTH));
65+
if (!_responseBuffer) {
66+
vw_log_e("Could not create response buffer");
67+
vw_abort();
68+
}
69+
}
4470
~VS1();
4571
VS1(const VS1&) = delete;
4672
VS1 & operator=(const VS1&) = delete;

src/VS2/VS2.h

+21-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@ the LICENSE file.
2222
#endif
2323
#elif defined(__linux__)
2424
#include "../Interface/LinuxSerialInterface.h"
25-
#else
26-
#error "platform not supported"
2725
#endif
26+
#include "../Interface/GenericInterface.h"
2827

2928
namespace VitoWiFi {
3029

@@ -41,6 +40,26 @@ class VS2 {
4140
#else
4241
explicit VS2(const char* interface);
4342
#endif
43+
template<class C>
44+
VS2(C* interface)
45+
: _state(State::UNDEFINED)
46+
, _currentMillis(vw_millis())
47+
, _lastMillis(_currentMillis)
48+
, _requestTime(0)
49+
, _bytesSent(0)
50+
, _interface(nullptr)
51+
, _parser()
52+
, _currentDatapoint(Datapoint(nullptr, 0, 0, noconv))
53+
, _currentPacket()
54+
, _onResponseCallback(nullptr)
55+
, _onErrorCallback(nullptr) {
56+
assert(interface != nullptr);
57+
_interface = new(std::nothrow) VitoWiFiInternals::GenericInterface<C>(interface);
58+
if (!_interface) {
59+
vw_log_e("Could not create serial interface");
60+
vw_abort();
61+
}
62+
}
4463
~VS2();
4564
VS2(const VS2&) = delete;
4665
VS2 & operator=(const VS2&) = delete;

0 commit comments

Comments
 (0)