Merged branch 'master' into ESP32OTA to acquire ClassyBluetooth changes

Resolved Conflict:
	Arduino/SenderTrial2/SenderTrial2.ino

Defined pin 23 for triggering wifiManager
This commit is contained in:
rljonesau 2018-11-06 13:25:05 +11:00
commit 4a841f530a
19 changed files with 661 additions and 543 deletions

Binary file not shown.

Binary file not shown.

View file

@ -1,6 +1,6 @@
{
"board": "esp32:esp32:esp32",
"port": "COM9",
"port": "192.168.0.101",
"sketch": "SenderTrial2.ino",
"output": "..\\build",
"configuration": "PSRAM=disabled,PartitionScheme=default,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,DebugLevel=none"

View file

@ -11,6 +11,14 @@
"xtree": "cpp",
"algorithm": "cpp",
"initializer_list": "cpp",
"xutility": "cpp"
"xutility": "cpp",
"istream": "cpp",
"memory": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp"
}
}

View file

@ -1,2 +1,31 @@
// Place Holder Config File - User config vars and defines to be moved here
// Jimmy C
//////////////////////////////////////////////////////////////////////////////
// Configure bluetooth options
// ** Recommended to use HC-05 for now **
// If none are enabled, we'll use an abstract class that only reports
// to the debug port what would have been sent
//
#define USE_HC05_BLUETOOTH 1
#define USE_BLE_BLUETOOTH 0
#define USE_CLASSIC_BLUETOOTH 0
///////////////////////////////////////////////////////////////////////////////
// limit rate of Bluetooth delivery from enthusiastic OEM controllers
//
#define OEM_TO_BLUETOOTH_MODERATION_TIME 700
// show when we did not echo data frames to bluetooth
#define REPORT_SUPPRESSED_OEM_DATA_FRAMES 0
///////////////////////////////////////////////////////////////////////////////
// debug reporting options
//
// true: each frame of data is reported on a new lines
// false: controller, then heater response frmaes are reported on a single line (excel CSV worthy!)
//
#define TERMINATE_OEM_LINE false /* when an OEM controller exists */
#define TERMINATE_BTC_LINE false /* when an OEM controller does not exist */

View file

@ -16,34 +16,33 @@ bool res;
void initWifi(int initpin,const char *failedssid, const char *failedpassword)
{
TRIG_PIN = initpin;
pinMode(TRIG_PIN, INPUT);
//reset settings - wipe credentials for testing
//wm.resetSettings();
//reset settings - wipe credentials for testing
//wm.resetSettings();
// Automatically connect using saved credentials,
// if connection fails, it starts an access point with the specified name ( "AutoConnectAP"),
// if empty will auto generate SSID, if password is blank it will be anonymous AP (wm.autoConnect())
// then goes into a blocking loop awaiting configuration and will return success result
wm.setConfigPortalTimeout(20);
wm.setConfigPortalBlocking(true);
// Automatically connect using saved credentials,
// if connection fails, it starts an access point with the specified name ( "AutoConnectAP"),
// if empty will auto generate SSID, if password is blank it will be anonymous AP (wm.autoConnect())
// then goes into a blocking loop awaiting configuration and will return success result
wm.setConfigPortalTimeout(20);
wm.setConfigPortalBlocking(true);
res = wm.autoConnect(); // auto generated AP name from chipid
res = wm.autoConnect(); // auto generated AP name from chipid
if(!res) {
Serial.println("Failed to connect");
Serial.println("Setting up ESP as AP");
WiFi.softAP(failedssid, failedpassword);
}
else {
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
if(!res) {
Serial.println("Failed to connect");
Serial.println("Setting up ESP as AP");
WiFi.softAP(failedssid, failedpassword);
}
else {
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
}
void doWiFiManager(){

View file

@ -1,33 +0,0 @@
#include <Arduino.h>
class CProtocol;
void Bluetooth_Init();
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
void Bluetooth_Check();
void Bluetooth_SendACK();
extern void Command_Interpret(const char* pLine); // decodes received command lines, implemented in main .ino file!
struct sRxLine {
char Line[64];
int Len;
sRxLine() {
clear();
}
bool append(char val) {
if(Len < (sizeof(Line) - 1)) {
Line[Len++] = val;
Line[Len] = 0;
return true;
}
return false;
}
void clear() {
Line[0] = 0;
Len = 0;
}
};

View file

@ -0,0 +1,58 @@
#include <Arduino.h>
#include <string.h>
class CProtocol;
extern void Command_Interpret(const char* pLine); // decodes received command lines, implemented in main .ino file!
struct sRxLine {
char Line[64];
int Len;
sRxLine() {
clear();
}
bool append(char val) {
if(Len < (sizeof(Line) - 1)) {
Line[Len++] = val;
Line[Len] = 0;
return true;
}
return false;
}
void clear() {
Line[0] = 0;
Len = 0;
}
};
class CBluetoothAbstract {
protected:
sRxLine _rxLine;
unsigned long lastTime;
public:
virtual void init() {};
virtual void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true) {
char msg[32];
if(strncmp(pHdr, "[HTR]", 5) == 0) {
unsigned delta = millis() - lastTime;
sprintf(msg, "%+8dms ", delta);
}
else {
lastTime = millis();
sprintf(msg, "%8dms ", lastTime);
}
DebugPort.print(msg);
DebugReportFrame(pHdr, Frame, lineterm ? "\r\n" : " ");
};
virtual void check() {};
virtual void collectRxData(char rxVal) {
if(isControl(rxVal)) { // "End of Line"
Command_Interpret(_rxLine.Line);
_rxLine.clear();
}
else {
_rxLine.append(rxVal); // append new char to our Rx buffer
}
};
};

View file

@ -1,7 +1,8 @@
#include "Bluetooth.h"
#include <Arduino.h>
#include "pins.h"
#include "Protocol.h"
#include "debugport.h"
#include "BluetoothESP32.h"
#ifdef TELNET
#define DebugPort Debug
@ -14,242 +15,85 @@
#ifdef ESP32
#define ESP32_USE_HC05
#ifdef BT_LED
const int LED = 2;
// ESP32
sRxLine RxLine;
#ifdef ESP32_USE_HC05
//static HardwareSerial& Bluetooth(Serial2); // TODO: make proper ESP32 BT client
bool Bluetooth_ATCommand(const char* cmd);
// Search for a HC-05 BlueTooth adapter, trying the more common baud rates first.
// As we cannot power up with the key pin high we are at the mercy of the baud rate
// stored in the module.
// **IMPORTANT**
// We must use a HC-05 module that uses a 3 pin 3.3V regulator (NOT 5 pin).
// On those modules, the EN input drive pin 34 and can be used to switch to AT
// command mode from data mode by raising EN high.
// ** BEWARE**
// The other style modules (with a 5 pin regulator) will disable the HC-05's power
// when the EN pin is low!!!!
//
// Once in command mode we can start interrogating using a simple "AT" command and
// checking for a response.
// If no response, try another baud rate till we do find a response.
// We can then proceed and configure the device's name, and force 9600 data rate
void Bluetooth_Init()
{
const int BTRates[] = {
9600, 38400, 115200, 19200, 57600, 2400, 4800, 1200
};
RxLine.clear();
// attach to the SENSE line from the HC-05 module
// this line goes high when a BT client is connected :-)
pinMode(HC05_Sense, INPUT);
digitalWrite(KeyPin, HIGH); // request HC-05 module to enter command mode
// Open Serial2, explicitly specify pins for pin multiplexer!);
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin);
DebugPort.println("\r\n\r\nAttempting to detect HC-05 Bluetooth module...");
int BTidx = 0;
int maxTries = sizeof(BTRates)/sizeof(int);
for(BTidx = 0; BTidx < maxTries; BTidx++) {
DebugPort.print(" @ ");
DebugPort.print(BTRates[BTidx]);
DebugPort.print(" baud... ");
Serial2.begin(BTRates[BTidx], SERIAL_8N1, Rx2Pin, Tx2Pin); // open serial port at a std.baud rate
delay(10);
Serial2.print("\r\n"); // clear the throat!
delay(100);
Serial2.setTimeout(100);
if(Bluetooth_ATCommand("AT\r\n")) { // probe with a simple "AT"
DebugPort.println(" OK."); // got a response - woo hoo found the module!
break;
}
if(Bluetooth_ATCommand("AT\r\n")) { // sometimes a second try is good...
DebugPort.println(" OK.");
break;
}
// failed, try another baud rate
DebugPort.println("");
Serial2.flush();
Serial2.end();
delay(100);
}
DebugPort.println("");
if(BTidx == maxTries) {
// we could not get anywhere with teh AT commands, but maybe this is the other module
// plough on and assume 9600 baud, but at the mercy of whatever the module name is...
DebugPort.println("FAILED to detect a HC-05 Bluetooth module :-(");
// leave the EN pin high - if other style module keeps it powered!
// assume it is 9600, and just (try to) use it like that...
// we will sense the STATE line to prove a client is hanging off the link...
DebugPort.println("ASSUMING a HC-05 module @ 9600baud (Unknown name)");
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin);
}
else {
// found a HC-05 module at one of its supported baud rates.
// now program it's name and force a 9600 baud data interface.
// this is the defacto standard as shipped!
DebugPort.println("HC-05 found");
do { // so we can break!
DebugPort.print(" Setting Name to \"Diesel Heater\"... ");
if(!Bluetooth_ATCommand("AT+NAME=\"Diesel Heater\"\r\n")) {
DebugPort.println("FAILED");
break;
}
DebugPort.println("OK");
DebugPort.print(" Setting baud rate to 9600N81...");
if(!Bluetooth_ATCommand("AT+UART=9600,1,0\r\n")) {
DebugPort.println("FAILED");
break;
};
DebugPort.println("OK");
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin);
// leave HC-05 command mode, return to data mode
digitalWrite(KeyPin, LOW);
} while (0); // yeah lame, allows break prior though :-)
}
delay(50);
DebugPort.println("");
}
void Bluetooth_Check()
{
// check for data coming back over Bluetooth
if(Serial2.available()) {
char rxVal = Serial2.read();
if(isControl(rxVal)) { // "End of Line"
Command_Interpret(RxLine.Line);
RxLine.clear();
}
else {
RxLine.append(rxVal); // append new char to our Rx buffer
}
}
}
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm)
{
DebugPort.print(millis());
DebugPort.print("ms ");
// DebugReportFrame(pHdr, Frame, lineterm ? "\r\n" : " ");
DebugReportFrame(pHdr, Frame, " ");
if(digitalRead(HC05_Sense)) {
if(Frame.verifyCRC()) {
// send data frame to HC-05
Serial2.print(pHdr);
Serial2.write(Frame.Data, 24);
// toggle LED
digitalWrite(LED, !digitalRead(LED)); // toggle LED
}
else {
DebugPort.print("Bluetooth data not sent, CRC error ");
}
}
else {
DebugPort.print("No Bluetooth client");
// force LED off
digitalWrite(LED, 0);
}
if(lineterm)
DebugPort.println("");
}
// local function, typically to perform Hayes commands with HC-05
bool Bluetooth_ATCommand(const char* cmd)
{
Serial2.print(cmd);
char RxBuffer[16];
memset(RxBuffer, 0, 16);
int read = Serial2.readBytesUntil('\n', RxBuffer, 16); // \n is not included in returned string!
if((read == 3) && (0 == strcmp(RxBuffer, "OK\r")) ) {
return true;
}
return false;
}
#else // ESP32_USE_HC05
#ifndef ESP32_USE_BLE_RLJ
#endif
/////////////////////////////////////////////////////////////////////////////////////////
// CLASSIC BLUETOOTH
// HC-05 BLUETOOTH with ESP32
// |
// V
//
CBluetoothESP32HC05::CBluetoothESP32HC05(int keyPin, int sensePin, int rxPin, int txPin) : CBluetoothHC05(keyPin, sensePin)
{
_rxPin = rxPin;
_txPin = txPin;
}
void
CBluetoothESP32HC05::openSerial(int baudrate)
{
// Open Serial port on the ESP32
// best to explicitly specify pins for the pin multiplexer!
HC05_SerialPort.begin(baudrate, SERIAL_8N1, _rxPin, _txPin);
}
// ^
// |
// HC-05 BLUETOOTH with ESP32
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
// CLASSIC BLUETOOTH on ESP32
// |
// V
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;
void Bluetooth_Init()
void
CBluetoothESP32Classic::init()
{
RxLine.clear();
_rxLine.clear();
#ifdef BT_LED
pinMode(LED, OUTPUT);
#endif
if(!SerialBT.begin("ESPHEATER")) {
DebugPort.println("An error occurred initialising Bluetooth");
}
}
void Bluetooth_Check()
void
CBluetoothESP32Classic::check()
{
if(SerialBT.available()) {
char rxVal = SerialBT.read();
if(isControl(rxVal)) { // "End of Line"
Command_Interpret(RxLine.Line);
RxLine.clear();
}
else {
RxLine.append(rxVal);
}
collectRxData(rxVal);
}
}
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm)
void
CBluetoothESP32Classic::sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm)
{
char fullMsg[32];
DebugPort.print(millis());
DebugReportFrame(pHdr, Frame, lineterm ? "\r\n" : " ");
// report to debug port
CBluetoothAbstract::sendFrame(pHdr, Frame, lineterm);
delay(40);
if(SerialBT.hasClient()) {
if(Frame.verifyCRC()) {
#ifdef BT_LED
digitalWrite(LED, !digitalRead(LED)); // toggle LED
#endif
int len = strlen(pHdr);
if(len < 8) {
strcpy(fullMsg, pHdr);
memcpy(&fullMsg[len], Frame.Data, 24);
SerialBT.write((uint8_t*)fullMsg, 24+len);
}
/* SerialBT.print(pHdr);
delay(1);
SerialBT.write(Frame.Data, 24);*/
delay(10);
}
else {
@ -258,32 +102,24 @@ void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm
}
else {
DebugPort.println("No Bluetooth client");
#ifdef BT_LED
digitalWrite(LED, 0);
#endif
}
}
void Bluetooth_SendACK()
{
/* if(SerialBT.hasClient()) {
SerialBT.print("[ACK]");
}*/
}
// ^
// |
// CLASSIC BLUETOOTH
// CLASSIC BLUETOOTH on ESP32
/////////////////////////////////////////////////////////////////////////////////////////
#else // ESP32_USE_BLE_RLJ
/////////////////////////////////////////////////////////////////////////////////////////
// BLE
// BLE on ESP32
// |
// V
#include <BLEDevice.h>
/*#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
@ -292,28 +128,39 @@ void Bluetooth_SendACK()
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
void BLE_Send(std::string Data);
void BLE_Send(std::string Data);*/
/*
BLEServer *pServer = NULL;
BLECharacteristic* pTxCharacteristic = NULL;
volatile bool deviceConnected = false;
bool oldDeviceConnected = false;
*/
class MyServerCallbacks : public BLEServerCallbacks {
volatile bool& _deviceConnected;
public:
MyServerCallbacks(volatile bool& devConnected) : _deviceConnected(devConnected), BLEServerCallbacks() {};
private:
void onConnect(BLEServer* pServer) {
deviceConnected = true;
_deviceConnected = true;
}
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
_deviceConnected = false;
}
};
class MyCallbacks : public BLECharacteristicCallbacks {
CBluetoothESP32BLE* _pHost;
public:
MyCallbacks(CBluetoothESP32BLE* pHost) : BLECharacteristicCallbacks() {
_pHost = pHost;
};
private:
// this callback is called when the ESP WRITE characteristic has been written to by a client
// We need to *read* the new information!
void onWrite(BLECharacteristic* pCharacteristic) {
@ -322,103 +169,133 @@ class MyCallbacks : public BLECharacteristicCallbacks {
while(rxValue.length() > 0) {
char rxVal = rxValue[0];
if(isControl(rxVal)) { // "End of Line"
Command_Interpret(BluetoothRxLine);
BluetoothRxLine = "";
}
else {
BluetoothRxLine += rxVal; // append new char to our Rx buffer
}
if(_pHost) _pHost->collectRxData(rxVal);
rxValue.erase(0, 1);
}
}
};
void Bluetooth_Init()
CBluetoothESP32BLE::CBluetoothESP32BLE()
{
_pServer = NULL;
_pTxCharacteristic = NULL;
_deviceConnected = false;
_oldDeviceConnected = false;
}
CBluetoothESP32BLE::~CBluetoothESP32BLE()
{
}
void
CBluetoothESP32BLE::init()
{
// create the BLE device
BLEDevice::init("DieselHeater");
// create the BLE server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks);
_pServer = BLEDevice::createServer();
_pServer->setCallbacks(new MyServerCallbacks(_deviceConnected));
// create the BLE service
BLEService *pService = pServer->createService(SERVICE_UUID);
BLEService *pService = _pServer->createService(SERVICE_UUID);
// create a BLE characteristic
pTxCharacteristic = pService->createCharacteristic(
_pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
_pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic* pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks/*()*/);
pRxCharacteristic->setCallbacks(new MyCallbacks(this));
// start the service
pService->start();
// start advertising
pServer->getAdvertising()->start();
_pServer->getAdvertising()->start();
DebugPort.println("Awaiting a client to notify...");
}
void Bluetooth_Report(const char* pHdr, const CProtocol& Frame)
void
CBluetoothESP32BLE::sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm)
{
if(deviceConnected) {
char fullMsg[32];
// report to debug port
CBluetoothAbstract::sendFrame(pHdr, Frame, lineterm);
delay(40);
if(_deviceConnected) {
if(Frame.verifyCRC()) {
// BLE can only squirt 20 bytes per packet.
// build the entire message then divide and conquer
#ifdef BT_LED
digitalWrite(LED, !digitalRead(LED)); // toggle LED
#endif
std::string txData = pHdr;
txData.append((char*)Frame.Data, 24);
BLE_Send(txData);
delay(10);
}
else {
DebugPort.println("Data not sent to Bluetooth, CRC error!");
}
}
else {
DebugPort.println("No Bluetooth client");
#ifdef BT_LED
digitalWrite(LED, 0);
#endif
}
}
void Bluetooth_Check()
void
CBluetoothESP32BLE::check()
{
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
if (!_deviceConnected && _oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
_pServer->startAdvertising(); // restart advertising
DebugPort.println("start advertising");
oldDeviceConnected = deviceConnected;
DebugPort.println("CLIENT DISCONNECTED");
_oldDeviceConnected = _deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
if (_deviceConnected && !_oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
DebugPort.println("CLIENT CONNECTED");
_oldDeviceConnected = _deviceConnected;
}
}
// break down supplied string into 20 byte chunks (or less)
// BLE can only handle 20 bytes per packet!
void BLE_Send(std::string Data)
void
CBluetoothESP32BLE::BLE_Send(std::string Data)
{
while(!Data.empty()) {
std::string substr = Data.substr(0, 20);
int len = substr.length();
pTxCharacteristic->setValue((uint8_t*)Data.data(), len);
pTxCharacteristic->notify();
_pTxCharacteristic->setValue((uint8_t*)Data.data(), len);
_pTxCharacteristic->notify();
Data.erase(0, len);
}
}
// ^
// |
// BLE
// BLE on ESP32
/////////////////////////////////////////////////////////////////////////////////////////
#endif // ESP32_USE_BLE_RLJ
#endif // ESP32_USE_HC05
#endif // __ESP32__

View file

@ -0,0 +1,41 @@
#include "BluetoothHC05.h"
#include "BluetoothSerial.h"
class CBluetoothESP32HC05 : public CBluetoothHC05 {
int _rxPin, _txPin;
public:
CBluetoothESP32HC05(int keyPin, int sensePin, int rxPin, int txPin);
protected:
void openSerial(int baudrate);
};
class CBluetoothESP32Classic : public CBluetoothAbstract {
BluetoothSerial SerialBT;
public:
virtual void init();
virtual void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
virtual void check();
};
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
class CBluetoothESP32BLE : public CBluetoothAbstract {
const char* SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"; // UART service UUID
const char* CHARACTERISTIC_UUID_RX = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
const char* CHARACTERISTIC_UUID_TX = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
BLEServer *_pServer;
BLECharacteristic* _pTxCharacteristic;
volatile bool _deviceConnected;
bool _oldDeviceConnected;
void BLE_Send(std::string Data);
public:
CBluetoothESP32BLE();
virtual ~CBluetoothESP32BLE();
virtual void init();
virtual void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
virtual void check();
};

View file

@ -1,41 +1,35 @@
#include "Bluetooth.h"
#include "pins.h"
#include "Protocol.h"
#include "debugport.h"
#include "BluetoothHC05.h"
// Bluetooth access via HC-05 Module, using a UART
#ifndef ESP32
// NOTE: ESP32 uses an entirely different mechanism, please refer to BluetoothESP32.cpp/.h
#ifdef __arm__
// for Arduino Due
static UARTClass& Bluetooth(Serial2);
#else
// for Mega
static HardwareSerial& Bluetooth(Serial2); // TODO: make proper ESP32 BT client
#endif
bool Bluetooth_ATCommand(const char* cmd);
sRxLine RxLine;
const int BTRates[] = {
9600, 38400, 115200, 19200, 57600, 2400, 4800
};
bool bHC05Available = false;
void Bluetooth_Init()
CBluetoothHC05::CBluetoothHC05(int keyPin, int sensePin)
{
RxLine.clear();
// extra control pins required to fully drive a HC05 module
_keyPin = keyPin; // used to enable AT command mode (ONLY ON SUPPORTED MODULES!!!!)
_sensePin = sensePin; // feedback signal used to sense if a client is connected
}
void
CBluetoothHC05::init()
{
const int BTRates[] = {
9600, 38400, 115200, 19200, 57600, 2400, 4800, 1200
};
_rxLine.clear();
// attach to the SENSE line from the HC-05 module
// this line goes high when a BT client is connected :-)
pinMode(_sensePin, INPUT);
// search for BlueTooth adapter, trying the common baud rates, then less common
// as the device cannot be guaranteed to power up with the key pin high
// we are at the mercy of the baud rate stored in the module.
Bluetooth.begin(9600);
digitalWrite(KeyPin, HIGH);
delay(500);
digitalWrite(_keyPin, HIGH); // request HC-05 module to enter command mode
openSerial(9600); // virtual function, may call derived class method here
DebugPort.println("\r\n\r\nAttempting to detect HC-05 Bluetooth module...");
@ -45,113 +39,136 @@ void Bluetooth_Init()
DebugPort.print(" @ ");
DebugPort.print(BTRates[BTidx]);
DebugPort.print(" baud... ");
Bluetooth.end();
Bluetooth.begin(BTRates[BTidx]); // open serial port at a certain baud rate
Bluetooth.print("\r\n");
Bluetooth.setTimeout(50);
openSerial(BTRates[BTidx]); // open serial port at a std.baud rate
delay(10);
HC05_SerialPort.print("\r\n"); // clear the throat!
delay(100);
HC05_SerialPort.setTimeout(100);
if(Bluetooth_ATCommand("AT\r\n")) {
if(ATCommand("AT\r\n")) { // probe with a simple "AT"
DebugPort.println(" OK."); // got a response - woo hoo found the module!
break;
}
if(ATCommand("AT\r\n")) { // sometimes a second try is good...
DebugPort.println(" OK.");
break;
}
// failed, try another baud rate
DebugPort.println("");
Bluetooth.flush();
HC05_SerialPort.flush();
HC05_SerialPort.end();
delay(100);
}
DebugPort.println("");
if(BTidx == maxTries) {
DebugPort.println("FAILED to detect HC-05 Bluetooth module :-(");
// we could not get anywhere with the AT commands, but maybe this is the other module
// plough on and assume 9600 baud, but at the mercy of whatever the module name is...
DebugPort.println("FAILED to detect a HC-05 Bluetooth module :-(");
// leave the EN pin high - if other style module keeps it powered!
// assume it is 9600, and just (try to) use it like that...
// we will sense the STATE line to prove a client is hanging off the link...
DebugPort.println("ASSUMING a HC-05 module @ 9600baud (Unknown name)");
openSerial(9600);
}
else {
if(BTRates[BTidx] == 115200) {
DebugPort.println("HC-05 found and already set to 115200 baud, skipping Init.");
bHC05Available = true;
// found a HC-05 module at one of its supported baud rates.
// now program it's name and force a 9600 baud data interface.
// this is the defacto standard as shipped!
DebugPort.println("HC-05 found");
DebugPort.print(" Setting Name to \"Diesel Heater\"... ");
if(!ATCommand("AT+NAME=\"Diesel Heater\"\r\n")) {
DebugPort.println("FAILED");
}
else {
do {
DebugPort.println("HC-05 found");
DebugPort.print(" Setting Name to \"DieselHeater\"... ");
if(!Bluetooth_ATCommand("AT+NAME=\"DieselHeater\"\r\n")) {
DebugPort.println("FAILED");
break;
}
DebugPort.println("OK");
DebugPort.print(" Setting baud rate to 115200N81...");
if(!Bluetooth_ATCommand("AT+UART=115200,1,0\r\n")) {
DebugPort.println("FAILED");
break;
};
DebugPort.println("OK");
Bluetooth.end();
Bluetooth.begin(115200);
bHC05Available = true;
} while(0);
DebugPort.println("OK");
}
DebugPort.print(" Setting baud rate to 9600N81...");
if(!ATCommand("AT+UART=9600,1,0\r\n")) {
DebugPort.println("FAILED");
}
else {
DebugPort.println("OK");
}
openSerial(9600);
// leave HC-05 command mode, return to data mode
digitalWrite(_keyPin, LOW);
}
digitalWrite(KeyPin, LOW); // leave HC-05 command mode
delay(500);
if(!bHC05Available)
Bluetooth.end(); // close serial port if no module found
delay(50);
DebugPort.println("");
}
void Bluetooth_Check()
{
void
CBluetoothHC05::check()
{
// check for data coming back over Bluetooth
if(bHC05Available) {
if(Bluetooth.available()) {
char rxVal = Bluetooth.read();
if(isControl(rxVal)) { // "End of Line"
Command_Interpret(RxLine.Line);
RxLine.clear();
}
else {
RxLine.append(rxVal); // append new char to our Rx buffer
}
}
if(HC05_SerialPort.available()) { // serial rx data is available
char rxVal = HC05_SerialPort.read();
collectRxData(rxVal);
}
}
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame)
void
CBluetoothHC05::sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm)
{
if(bHC05Available) {
// report to debug port
CBluetoothAbstract::sendFrame(pHdr, Frame, false);
if(digitalRead(_sensePin)) {
if(Frame.verifyCRC()) {
Bluetooth.print(pHdr);
Bluetooth.write(Frame.Data, 24);
// send data frame to HC-05
HC05_SerialPort.print(pHdr);
HC05_SerialPort.write(Frame.Data, 24);
// toggle LED
#ifdef BT_LED
digitalWrite(LED, !digitalRead(LED)); // toggle LED
#endif
}
else {
DebugPort.print("Bluetooth data not sent, CRC error ");
DebugPort.println(pHdr);
}
}
else {
if(lineterm) { // only report no client if this will be at end of line (long line support)
DebugPort.print("No Bluetooth client");
}
// force LED off
#ifdef BT_LED
digitalWrite(LED, 0);
#endif
}
if(lineterm)
DebugPort.println("");
}
// local function, typically to perform Hayes commands with HC-05
bool Bluetooth_ATCommand(const char* cmd)
void
CBluetoothHC05::openSerial(int baudrate)
{
if(bHC05Available) {
Bluetooth.print(cmd);
char RxBuffer[16];
memset(RxBuffer, 0, 16);
int read = Bluetooth.readBytesUntil('\n', RxBuffer, 16); // \n is not included in returned string!
if((read == 3) && (0 == strcmp(RxBuffer, "OK\r")) ) {
return true;
}
return false;
// standard serial port for Due, Mega (ESP32 uses virtual, derived from this class)
HC05_SerialPort.begin(baudrate);
}
// protected function, to perform Hayes commands with HC-05
bool
CBluetoothHC05::ATCommand(const char* cmd)
{
HC05_SerialPort.print(cmd);
char RxBuffer[16];
memset(RxBuffer, 0, 16);
int read = HC05_SerialPort.readBytesUntil('\n', RxBuffer, 16); // \n is not included in returned string!
if((read == 3) && (0 == strcmp(RxBuffer, "OK\r")) ) {
return true;
}
return false;
}
#endif

View file

@ -0,0 +1,27 @@
#include "BluetoothAbstract.h"
// Define the serial port for access to a HC-05 module.
// This is generally Serial2, but different platforms use
// a different class for the implementation.
#ifdef __arm__
// for Arduino Due
static UARTClass& HC05_SerialPort(Serial2);
#else
// for Mega, ESP32
static HardwareSerial& HC05_SerialPort(Serial2);
#endif
// define a derived class that offers bluetooth messaging over the HC-05
class CBluetoothHC05 : public CBluetoothAbstract {
bool ATCommand(const char* str);
int _sensePin, _keyPin;
public:
CBluetoothHC05(int keyPin, int sensePin);
void init();
void sendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm=true);
void check();
protected:
virtual void openSerial(int baudrate);
};

View file

@ -269,3 +269,15 @@ CProtocol::Init(int FrameMode)
}
}
void
CProtocol::DebugReport(const char* hdr, const char* ftr)
{
DebugPort.print(hdr); // header
for(int i=0; i<24; i++) {
char str[16];
sprintf(str, " %02X", Data[i]); // build 2 dig hex values
DebugPort.print(str); // and print
}
DebugPort.print(ftr); // footer
}

View file

@ -164,6 +164,8 @@ public:
short getTemperature_HeatExchg(); // temperature of heat exchanger
void setTemperature_HeatExchg(short degC); // temperature of heat exchanger
void DebugReport(const char* hdr, const char* ftr);
CProtocol& operator=(const CProtocol& rhs);
};

View file

@ -15,7 +15,7 @@
If Pin 21 is grounded on the Due, this simple stream will be reported over Serial and
no control from the Arduino will be allowed.
This allows sniffing of the blue wire in a normal system.
This allows passive sniffing of the blue wire in a normal system.
The binary data is received from the line.
If it has been > 100ms since the last blue wire activity this indicates a new frame
@ -27,12 +27,12 @@
Capture those bytes and store them in the Heater1 data array.
Once again these bytes are then reported over Serial to the PC in ASCII.
If no activity is sensed in a second, it is assumed no controller is attached and we
If no activity is sensed in a second, it is assumed no OEM controller is attached and we
have full control over the heater.
Either way we can now inject a message onto the blue wire allowing our custom
on/off control.
We must remain synchronous with the OEM controller if it exists otherwise E-07
We must remain synchronous with an OEM controller if it exists otherwise E-07
faults will be caused.
Typical data frame timing on the blue wire is then:
@ -43,19 +43,20 @@
But this does rise if new max/min or voltage settings are sent.
**The heater only ever sends Rx data in response to a data frame from a controller**
A HC-05 Bluetooth module is attached to Serial2:
For Bluetooth connectivity, a HC-05 Bluetooth module is attached to Serial2:
TXD -> Rx2 (pin 17)
RXD -> Tx2 (pin 16)
EN(key) -> pin 15
STATE -> pin 4
This code only works with boards that have more than one hardware serial port like Arduino
Mega, Due, Zero etc.
Mega, Due, Zero, ESP32 etc.
The circuit:
- a Tx Rx multiplexer is required to combine the Arduino's Tx1 And Rx1 pins onto the blue wire.
- a Tx Enable signal from pin 20 controls the multiplexer
- a Tx Enable signal from pin 22 controls the multiplexer, high for Tx, low for Rx
- Serial logging software on Serial0 via USB link
created 23 Sep 2018 by Ray Jones
@ -70,18 +71,35 @@
#include "debugport.h"
#include "SmartError.h"
#include "BTCWifi.h"
#include "BTCConfig.h"
#define HOST_NAME "remotedebug-sample"
#include "BTCota.h"
#define HOST_NAME "BTCHeater"
#define TRIGGER_PIN 0
#define FAILEDSSID "BTCESP32"
#define FAILEDPASSWORD "thereisnospoon"
#define ESP32_USE_BLE_RLJ
#include "Bluetooth.h"
//comment this out to remove TELNET
//#define TELNET
#ifdef TELNET
#define DebugPort Debug
#endif
#ifndef TELNET
#define DebugPort DebugPort
#endif
#ifdef ESP32
#include "BluetoothESP32.h"
#else
#include "BluetoothHC05.h"
#endif
// Setup Serial Port Definitions
#if defined(__arm__)
@ -106,6 +124,9 @@ class CommStates {
m_State = eState;
m_Count = 0;
}
eCS get() {
return m_State;
}
bool is(eCS eState) {
return m_State == eState;
}
@ -114,7 +135,7 @@ class CommStates {
return m_Count == limit;
}
private:
int m_State;
eCS m_State;
int m_Count;
};
@ -151,13 +172,42 @@ public:
CommStates CommState;
CTxManage TxManage(TxEnbPin, BlueWireSerial);
//CProtocol OEMCtrlFrame; // data packet received from heater in response to OEM controller packet
//CProtocol HeaterFrame1; // data packet received from heater in response to OEM controller packet
CModeratedFrame OEMCtrlFrame; // data packet received from heater in response to OEM controller packet
CModeratedFrame HeaterFrame1; // data packet received from heater in response to OEM controller packet
CProtocol HeaterFrame2; // data packet received from heater in response to our packet
CProtocol DefaultBTCParams(CProtocol::CtrlMode); // defines the default parameters, used in case of no OEM controller
CSmartError SmartError;
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Bluetooth instantiation
//
#ifdef ESP32
// Bluetooth options for ESP32
#if USE_HC05_BLUETOOTH == 1
CBluetoothESP32HC05 Bluetooth(HC05_KeyPin, HC05_SensePin, Rx2Pin, Tx2Pin); // Instantiate ESP32 using a HC-05
#elif USE_BLE_BLUETOOTH == 1
CBluetoothESP32BLE Bluetooth; // Instantiate ESP32 BLE server
#elif USE_CLASSIC_BLUETOOTH == 1
CBluetoothESP32Classic Bluetooth; // Instantiate ESP32 Classic Bluetooth server
#else // none selected
CBluetoothAbstract Bluetooth; // default no bluetooth support - empty shell
#endif
#else // !ESP32
// Bluetooth for others
#if USE_HC05_BLUETOOTH == 1
CBluetoothHC05 Bluetooth(HC05_KeyPin, HC05_SensePin); // Instantiate a HC-05
#else // none selected
CBluetoothAbstract Bluetooth; // default no bluetooth support - empty shell
#endif // closing USE_HC05_BLUETOOTH
#endif // closing ESP32
//
// END Bluetooth instantiation
////////////////////////////////////////////////////////////////////////////////////////////////////////
long lastRxTime; // used to observe inter character delays
bool hasOEMController = false;
@ -170,18 +220,17 @@ CHeaterStorage NVStorage; // dummy, for now
#endif
CHeaterStorage* pNVStorage = NULL;
void PrepareTxFrame(const CProtocol& basisFrame, CProtocol& TxFrame, bool isBTCmaster);
void setup()
{
initWifi(TRIGGER_PIN, FAILEDSSID, FAILEDPASSWORD);
void setup() {
// initWifi(TRIGGER_PIN, FAILEDSSID, FAILEDPASSWORD);
initWifi(WiFi_TriggerPin, FAILEDSSID, FAILEDPASSWORD);
initOTA();
pinMode(Tx2Pin, OUTPUT);
digitalWrite(Tx2Pin, HIGH);
pinMode(Rx2Pin, INPUT_PULLUP);
pinMode(ListenOnlyPin, INPUT_PULLUP);
pinMode(KeyPin, OUTPUT);
digitalWrite(KeyPin, LOW);
pinMode(HC05_KeyPin, OUTPUT);
digitalWrite(HC05_KeyPin, LOW);
// initialize serial port to interact with the "blue wire"
// 25000 baud, Tx and Rx channels of Chinese heater comms interface:
@ -214,7 +263,7 @@ void setup()
DefaultBTCParams.setFan_Min(1680);
DefaultBTCParams.setFan_Max(4500);
Bluetooth_Init();
Bluetooth.init();
// create pointer to CHeaterStorage
// via the magic of polymorphism we can use this to access whatever
@ -224,11 +273,12 @@ void setup()
pNVStorage->load();
}
// main functional loop is based about a state machine approach, waiting for data
// to appear upon the blue wire, and marshalling into an appropriate receive buffer
// according to the state.
// main functional loop is based about a state machine approach, waiting for data
// to appear upon the blue wire, and marshalling into an appropriate receive buffers
// according to the state.
void loop()
{
unsigned long timenow = millis();
@ -246,7 +296,7 @@ void loop()
}
}
Bluetooth_Check(); // check for Bluetooth activity
Bluetooth.check(); // check for Bluetooth activity
// calc elapsed time since last rxd byte
// used to detect no OEM controller, or the start of an OEM frame sequence
@ -277,6 +327,7 @@ void loop()
// Blue wire data reception
// Reads data from the "blue wire" Serial port, (to/from heater)
// If an OEM controller exists we will also see it's data frames
// Note that the data is read now, then held for later use in the state machine
//
sRxData BlueWireData;
@ -292,128 +343,156 @@ void loop()
///////////////////////////////////////////////////////////////////////////////////////////
// do our state machine to track the reception and delivery of blue wire data
// we may need to transit to a OEMCtrlRx if we captured a new byte, so stand alone if here!
if( CommState.is(CommStates::Idle)) {
switch(CommState.get()) {
// Detect the possible start of a new frame sequence from an OEM controller
// This will be the first activity for considerable period on the blue wire
// The heater always responds to a controller frame, but otherwise never by itself
if(BlueWireData.available() && (RxTimeElapsed > 100)) {
DebugPort.print("Re-sync'd with OEM Controller. ");
DebugPort.print(RxTimeElapsed);
DebugPort.println("ms Idle time.");
hasOEMController = true;
CommState.set(CommStates::OEMCtrlRx); // we must add this new byte!
}
case CommStates::Idle:
// Detect the possible start of a new frame sequence from an OEM controller
// This will be the first activity for considerable period on the blue wire
// The heater always responds to a controller frame, but otherwise never by itself
if(RxTimeElapsed >= 970) {
// have not seen any receive data for a second.
// OEM controller is probably not connected. 6
// Skip state machine immediately to BTC_Tx, sending our own settings.
hasOEMController = false;
bool isBTCmaster = true;
TxManage.PrepareFrame(DefaultBTCParams, isBTCmaster); // use our parameters, and mix in NV storage values
TxManage.Start(timenow);
CommState.set(CommStates::BTC_Tx);
break;
}
if(RxTimeElapsed >= 970) {
// have not seen any receive data for a second.
// OEM controller is probably not connected. 6
// Skip state machine immediately to BTC_Tx, sending our own settings.
hasOEMController = false;
CommState.set(CommStates::BTC_Tx);
bool isBTCmaster = true;
TxManage.PrepareFrame(DefaultBTCParams, isBTCmaster); // use our parameters, and mix in NV storage values
TxManage.Start(timenow);
}
} // CommState::Idle
if( CommState.is(CommStates::OEMCtrlRx) ) {
// collect OEM controller frame
if(BlueWireData.available()) {
if(CommState.collectData(OEMCtrlFrame, BlueWireData.getValue()) ) {
CommState.set(CommStates::OEMCtrlReport); // collected 24 bytes, move on!
if(BlueWireData.available() && (RxTimeElapsed > 100)) {
#ifdef REPORT_OEM_RESYNC
DebugPort.print("Re-sync'd with OEM Controller. ");
DebugPort.print(RxTimeElapsed);
DebugPort.println("ms Idle time.");
#endif
hasOEMController = true;
CommState.set(CommStates::OEMCtrlRx); // we must add this new byte!
//
// ** IMPORTANT - we must drop through to OEMCtrlRx *NOW* (skip break) **
//
}
}
}
else if( CommState.is(CommStates::OEMCtrlReport) ) {
// filled OEM controller frame, report
// echo received OEM controller frame over Bluetooth, using [OEM] header
if(OEMCtrlFrame.elapsedTime() > 700) {
Bluetooth_SendFrame("[OEM]", OEMCtrlFrame, true);
OEMCtrlFrame.setTime();
}
else {
DebugPort.println("Suppressed delivery of OEM frame");
}
CommState.set(CommStates::HeaterRx1);
}
else if( CommState.is(CommStates::HeaterRx1) ) {
// collect heater frame, always in response to an OEM controller frame
if(BlueWireData.available()) {
if( CommState.collectData(HeaterFrame1, BlueWireData.getValue()) ) {
CommState.set(CommStates::HeaterReport1);
else {
break; // only break if we failed all the Idle tests
}
}
}
else if(CommState.is(CommStates::HeaterReport1) ) {
// received heater frame (after controller message), report
case CommStates::OEMCtrlRx:
// collect OEM controller frame
if(BlueWireData.available()) {
if(CommState.collectData(OEMCtrlFrame, BlueWireData.getValue()) ) {
CommState.set(CommStates::OEMCtrlReport); // collected 24 bytes, move on!
}
}
break;
case CommStates::OEMCtrlReport:
// filled OEM controller frame, report
// echo received OEM controller frame over Bluetooth, using [OEM] header
// note that Rotary Knob and LED OEM controllers can flood the Bluetooth
// handling at the client side, moderate OEM Bluetooth delivery
if(OEMCtrlFrame.elapsedTime() > OEM_TO_BLUETOOTH_MODERATION_TIME) {
Bluetooth.sendFrame("[OEM]", OEMCtrlFrame, TERMINATE_OEM_LINE);
OEMCtrlFrame.setTime();
}
else {
#if REPORT_SUPPRESSED_OEM_DATA_FRAMES != 0
DebugPort.println("Suppressed delivery of OEM frame");
#endif
}
CommState.set(CommStates::HeaterRx1);
break;
case CommStates::HeaterRx1:
// collect heater frame, always in response to an OEM controller frame
if(BlueWireData.available()) {
if( CommState.collectData(HeaterFrame1, BlueWireData.getValue()) ) {
CommState.set(CommStates::HeaterReport1);
}
}
break;
case CommStates::HeaterReport1:
// received heater frame (after controller message), report
// do some monitoring of the heater state variable
// if suspicious transitions, introduce a smart error!
SmartError.monitor(HeaterFrame1);
// do some monitoring of the heater state variable
// if abnormal transitions, introduce a smart error!
SmartError.monitor(HeaterFrame1);
// echo heater reponse data to Bluetooth client
if(HeaterFrame1.elapsedTime() > 700) {
Bluetooth_SendFrame("[HTR]", HeaterFrame1);
HeaterFrame1.setTime();
}
else {
DebugPort.println("Suppressed delivery of OEM heater response frame");
}
if(digitalRead(ListenOnlyPin)) {
bool isBTCmaster = false;
TxManage.PrepareFrame(OEMCtrlFrame, isBTCmaster); // parrot OEM parameters, but block NV modes
TxManage.Start(timenow);
CommState.set(CommStates::BTC_Tx);
}
else {
CommState.set(CommStates::Idle); // "Listen Only" input is held low, don't send out Tx
}
}
// Handle time interval where we send data to the blue wire
else if(CommState.is(CommStates::BTC_Tx)) {
lastRxTime = timenow; // *we* are pumping onto blue wire, track this activity!
if(TxManage.CheckTx(timenow) ) { // monitor progress of our data delivery
CommState.set(CommStates::HeaterRx2); // then await heater repsonse
}
}
else if( CommState.is(CommStates::HeaterRx2) ) {
// collect heater frame, in response to our control frame
if(BlueWireData.available()) {
if( CommState.collectData(HeaterFrame2, BlueWireData.getValue()) ) {
CommState.set(CommStates::HeaterReport2);
// echo heater reponse data to Bluetooth client
// note that Rotary Knob and LED OEM controllers can flood the Bluetooth
// handling at the client side, moderate OEM Bluetooth delivery
if(HeaterFrame1.elapsedTime() > OEM_TO_BLUETOOTH_MODERATION_TIME) {
Bluetooth.sendFrame("[HTR]", HeaterFrame1, true);
HeaterFrame1.setTime();
}
else {
#if REPORT_SUPPRESSED_OEM_DATA_FRAMES != 0
DebugPort.println("Suppressed delivery of OEM heater response frame");
#endif
}
}
}
else if( CommState.is(CommStates::HeaterReport2) ) {
// received heater frame (after our control message), report
if(digitalRead(ListenOnlyPin)) {
bool isBTCmaster = false;
TxManage.PrepareFrame(OEMCtrlFrame, isBTCmaster); // parrot OEM parameters, but block NV modes
TxManage.Start(timenow);
CommState.set(CommStates::BTC_Tx);
}
else {
CommState.set(CommStates::Idle); // "Listen Only" input is held low, don't send out Tx
}
break;
// do some monitoring of the heater state variable
// if suspicious transitions, introduce a smart error!
SmartError.monitor(HeaterFrame2);
case CommStates::BTC_Tx:
// Handle time interval where we send data to the blue wire
lastRxTime = timenow; // *we* are pumping onto blue wire, track this activity!
if(TxManage.CheckTx(timenow) ) { // monitor progress of our data delivery
if(!hasOEMController) {
// only convey this frames to Bluetooth when NOT using an OEM controller!
Bluetooth.sendFrame("[BTC]", TxManage.getFrame(), TERMINATE_BTC_LINE); // BTC => Bluetooth Controller :-)
}
CommState.set(CommStates::HeaterRx2); // then await heater repsonse
}
break;
delay(5);
if(!hasOEMController) {
// only convey these frames to Bluetooth when NOT using an OEM controller!
Bluetooth_SendFrame("[BTC]", TxManage.getFrame(), true); // BTC => Bluetooth Controller :-)
Bluetooth_SendFrame("[HTR]", HeaterFrame2); // pin not grounded, suppress duplicate to BT
}
CommState.set(CommStates::Idle);
case CommStates::HeaterRx2:
// collect heater frame, in response to our control frame
if(BlueWireData.available()) {
if( CommState.collectData(HeaterFrame2, BlueWireData.getValue()) ) {
CommState.set(CommStates::HeaterReport2);
}
}
break;
case CommStates::HeaterReport2:
// received heater frame (after our control message), report
// do some monitoring of the heater state variables
// if abnormal transitions, introduce a smart error!
SmartError.monitor(HeaterFrame2);
delay(5);
if(!hasOEMController) {
// only convey these frames to Bluetooth when NOT using an OEM controller!
// Bluetooth.sendFrame("[BTC]", TxManage.getFrame(), TERMINATE_BTC_LINE); // BTC => Bluetooth Controller :-)
Bluetooth.sendFrame("[HTR]", HeaterFrame2, true); // pin not grounded, suppress duplicate to BT
}
CommState.set(CommStates::Idle);
#ifdef SHOW_HEAP
Serial.print("Free heap ");
Serial.println(ESP.getFreeHeap());
Serial.print("Free heap ");
Serial.println(ESP.getFreeHeap());
#endif
}
break;
} // switch(CommState)
} // loop

View file

@ -1,3 +1,4 @@
#include <Arduino.h>
class CProtocol;

View file

@ -1,8 +1,9 @@
const int TxEnbPin = 22;
const int ListenOnlyPin = 21;
const int KeyPin = 15;
const int Tx1Pin = 18;
const int Rx1Pin = 19;
const int Tx2Pin = 16;
const int Rx2Pin = 17;
const int HC05_Sense = 4;
const int HC05_KeyPin = 15;
const int HC05_SensePin = 4;
const int WiFi_TriggerPin = 23;