Skip to content

Commit

Permalink
generic interface
Browse files Browse the repository at this point in the history
  • Loading branch information
bertmelis committed Jan 14, 2025
1 parent e136819 commit c0269d1
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 4 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build_arduino_ide.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
- name: esp32:esp32
source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
sketch-paths: |
- examples/generic-interface
- examples/simple-read-VS1
- examples/simple-read-VS2
- examples/simple-write-VS1
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build_platformio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
strategy:
matrix:
example: [
examples/generic-interface/generic-interface.ino
examples/simple-read-VS1/simple-read-VS1.ino,
examples/simple-read-VS2/simple-read-VS2.ino,
examples/simple-write-VS1/simple-write-VS1.ino,
Expand Down
123 changes: 123 additions & 0 deletions examples/generic-interface/generic-interface.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include <Arduino.h>

#include <VitoWiFi.h>

/*
This example is to show how you could build your own
interface and serves as a compilation test
*/

// Dummy class that has all the methods for VitoWiFi to work
// but doesn't do anything in this case.
// Use as skeleton for your own implementation
class DummyInterface {
public:
bool begin() {
// prepare the interface
// optolink comm at 4800 baud, 8 bits, even parity and 2 stop bits
// called at VitoWiFi::begin()
return true;
}
void end() {
// stop the interface
// called at VitoWiFi::end()
}
std::size_t write(const uint8_t* data, uint8_t length) {
// tries to write `data` with length `length` to the interface
// returns the actually written data
return 0;
}
uint8_t read() {
// read one byte from the interface
// availability of data is checked first
return 0;
}
size_t available() {
// check if data is available
return 0;
}
};

// optolink on Dummy Interface, logging output on UART1 (connected to USB)
DummyInterface dummyInterface;
#define SERIAL1 dummyInterface
#define SERIAL2 Serial
#define SERIALBAUDRATE 115200

VitoWiFi::VitoWiFi<VitoWiFi::VS2> vitoWiFi(&SERIAL1);
bool readValues = false;
uint8_t datapointIndex = 0;

VitoWiFi::Datapoint datapoints[] = {
VitoWiFi::Datapoint("outsidetemp", 0x5525, 2, VitoWiFi::div10),
VitoWiFi::Datapoint("boilertemp", 0x0810, 2, VitoWiFi::div10),
VitoWiFi::Datapoint("pump", 0x2906, 1, VitoWiFi::noconv)
};

void onResponse(const VitoWiFi::PacketVS2& response, const VitoWiFi::Datapoint& request) {
// raw data can be accessed through the 'response' argument
SERIAL2.print("Raw data received:");
const uint8_t* data = response.data();
for (uint8_t i = 0; i < response.dataLength(); ++i) {
SERIAL2.printf(" %02x", data[i]);
}
SERIAL2.print("\n");

// the raw data can be decoded using the datapoint. Be sure to use the correct type
SERIAL2.printf("%s: ", request.name());
if (request.converter() == VitoWiFi::div10) {
float value = request.decode(response);
SERIAL2.printf("%.1f\n", value);
} else if (request.converter() == VitoWiFi::noconv) {
bool value = request.decode(response);
// alternatively, we can just cast response.data()[0] to bool
SERIAL2.printf("%s\n", value ? "ON" : "OFF");
}
}

void onError(VitoWiFi::OptolinkResult error, const VitoWiFi::Datapoint& request) {
SERIAL2.printf("Datapoint \"%s\" error: ", request.name());
if (error == VitoWiFi::OptolinkResult::TIMEOUT) {
SERIAL2.print("timeout\n");
} else if (error == VitoWiFi::OptolinkResult::LENGTH) {
SERIAL2.print("length\n");
} else if (error == VitoWiFi::OptolinkResult::NACK) {
SERIAL2.print("nack\n");
} else if (error == VitoWiFi::OptolinkResult::CRC) {
SERIAL2.print("crc\n");
} else if (error == VitoWiFi::OptolinkResult::ERROR) {
SERIAL2.print("error\n");
}
}

void setup() {
delay(1000);
SERIAL2.begin(SERIALBAUDRATE);
SERIAL2.print("Setting up vitoWiFi\n");

vitoWiFi.onResponse(onResponse);
vitoWiFi.onError(onError);
vitoWiFi.begin();

SERIAL2.print("Setup finished\n");
}

void loop() {
static uint32_t lastMillis = 0;
if (millis() - lastMillis > 60000UL) { // read all values every 60 seconds
lastMillis = millis();
readValues = true;
datapointIndex = 0;
}

if (readValues) {
if (vitoWiFi.read(datapoints[datapointIndex])) {
++datapointIndex;
}
if (datapointIndex == 3) {
readValues = false;
}
}

vitoWiFi.loop();
}
29 changes: 27 additions & 2 deletions src/GWG/GWG.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ the LICENSE file.
#endif
#elif defined(__linux__)
#include "../Interface/LinuxSerialInterface.h"
#else
#error "platform not supported"
#endif
#include "../Interface/GenericInterface.h"

namespace VitoWiFi {

Expand All @@ -41,6 +40,32 @@ class GWG {
#else
explicit GWG(const char* interface);
#endif
template<class C>
GWG(C* interface)
: _state(State::UNDEFINED)
, _currentMillis(vw_millis())
, _lastMillis(_currentMillis)
, _requestTime(0)
, _bytesTransferred(0)
, _interface(nullptr)
, _currentDatapoint(Datapoint(nullptr, 0x0000, 0, VitoWiFi::noconv))
, _currentRequest()
, _responseBuffer(nullptr)
, _allocatedLength(0)
, _onResponseCallback(nullptr)
, _onErrorCallback(nullptr) {
assert(interface != nullptr);
_interface = new(std::nothrow) VitoWiFiInternals::GenericInterface(interface);
if (!_interface) {
vw_log_e("Could not create serial interface");
vw_abort();
}
_responseBuffer = reinterpret_cast<uint8_t*>(malloc(START_PAYLOAD_LENGTH));
if (!_responseBuffer) {
vw_log_e("Could not create response buffer");
vw_abort();
}
}
~GWG();
GWG(const GWG&) = delete;
GWG & operator=(const GWG&) = delete;
Expand Down
42 changes: 42 additions & 0 deletions src/Interface/GenericInterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Copyright (c) 2023 Bert Melis. All rights reserved.
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT> or
the LICENSE file.
*/

#pragma once

#include "SerialInterface.h"

namespace VitoWiFiInternals {

template <class C>
class GenericInterface : public SerialInterface {
public:
explicit GenericInterface(C* interface)
: _interface() {
// empty
}
bool begin() override {
return _interface->begin();
}
void end() override {
_interface->end();
}
std::size_t write(const uint8_t* data, uint8_t length) override {
return _interface->write(data, length);
}
uint8_t read() override {
return _interface->read();
}
size_t available() override {
return _interface->available();
}

private:
C* _interface;
};

} // end namespace VitoWiFiInternals
26 changes: 26 additions & 0 deletions src/VS1/VS1.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,32 @@ class VS1 {
#else
explicit VS1(const char* interface);
#endif
template<class C>
VS1(C* interface)
: _state(State::UNDEFINED)
, _currentMillis(vw_millis())
, _lastMillis(_currentMillis)
, _requestTime(0)
, _bytesTransferred(0)
, _interface(nullptr)
, _currentDatapoint(Datapoint(nullptr, 0x0000, 0, VitoWiFi::noconv))
, _currentRequest()
, _responseBuffer(nullptr)
, _allocatedLength(0)
, _onResponseCallback(nullptr)
, _onErrorCallback(nullptr) {
assert(interface != nullptr);
_interface = new(std::nothrow) VitoWiFiInternals::GenericInterface<C>(interface);
if (!_interface) {
vw_log_e("Could not create serial interface");
vw_abort();
}
_responseBuffer = reinterpret_cast<uint8_t*>(malloc(START_PAYLOAD_LENGTH));
if (!_responseBuffer) {
vw_log_e("Could not create response buffer");
vw_abort();
}
}
~VS1();
VS1(const VS1&) = delete;
VS1 & operator=(const VS1&) = delete;
Expand Down
23 changes: 21 additions & 2 deletions src/VS2/VS2.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ the LICENSE file.
#endif
#elif defined(__linux__)
#include "../Interface/LinuxSerialInterface.h"
#else
#error "platform not supported"
#endif
#include "../Interface/GenericInterface.h"

namespace VitoWiFi {

Expand All @@ -41,6 +40,26 @@ class VS2 {
#else
explicit VS2(const char* interface);
#endif
template<class C>
VS2(C* interface)
: _state(State::UNDEFINED)
, _currentMillis(vw_millis())
, _lastMillis(_currentMillis)
, _requestTime(0)
, _bytesSent(0)
, _interface(nullptr)
, _parser()
, _currentDatapoint(Datapoint(nullptr, 0, 0, noconv))
, _currentPacket()
, _onResponseCallback(nullptr)
, _onErrorCallback(nullptr) {
assert(interface != nullptr);
_interface = new(std::nothrow) VitoWiFiInternals::GenericInterface<C>(interface);
if (!_interface) {
vw_log_e("Could not create serial interface");
vw_abort();
}
}
~VS2();
VS2(const VS2&) = delete;
VS2 & operator=(const VS2&) = delete;
Expand Down

0 comments on commit c0269d1

Please sign in to comment.