mirror of
https://github.com/esphome/esphome.git
synced 2024-11-28 09:44:12 +01:00
Trial this
This commit is contained in:
parent
2e11b5fe5e
commit
63246ee815
5 changed files with 133 additions and 1364 deletions
|
@ -1,20 +1,112 @@
|
|||
#pragma once
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/text_sensor/text_sensor.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "lora_e220.h"
|
||||
#include "ebyte_lora_e220.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace ebyte_lora_e220 {
|
||||
|
||||
static const char *const TAG = "ebyte_lora_e220";
|
||||
void EbyteLoraE220::setup() {
|
||||
if (this->pin_aux != nullptr) {
|
||||
this->pin_aux->pin_mode(gpio::FLAG_INPUT);
|
||||
ESP_LOGD(TAG, "Init AUX pin!");
|
||||
}
|
||||
if (this->pin_m0 != nullptr) {
|
||||
this->pin_m0->pin_mode(gpio::FLAG_OUTPUT);
|
||||
ESP_LOGD(TAG, "Init M0 pin!");
|
||||
this->pin_m0->digital_write(true);
|
||||
}
|
||||
if (this->pin_m1 != nullptr) {
|
||||
this->pin_m1->pin_mode(gpio::FLAG_OUTPUT);
|
||||
ESP_LOGD(TAG, "Init M1 pin!");
|
||||
this->pin_m1->digital_write(true);
|
||||
}
|
||||
|
||||
bool status = setMode(MODE_0_NORMAL);
|
||||
ESP_LOGD(TAG, "setup success %s", status);
|
||||
}
|
||||
bool EbyteLoraE220::setMode(MODE_TYPE mode) {
|
||||
// data sheet claims module needs some extra time after mode setting (2ms)
|
||||
// most of my projects uses 10 ms, but 40ms is safer
|
||||
|
||||
delay(40);
|
||||
|
||||
if (this->pin_m0 == nullptr && this->pin_m1 == nullptr) {
|
||||
ESP_LOGD(TAG, "The M0 and M1 pins is not set, this mean that you are connect directly the pins as you need!");
|
||||
} else {
|
||||
switch (mode) {
|
||||
case MODE_0_NORMAL:
|
||||
// Mode 0 | normal operation
|
||||
this->pin_m0->digital_write(false);
|
||||
this->pin_m1->digital_write(false);
|
||||
ESP_LOGD(TAG, "MODE NORMAL!");
|
||||
break;
|
||||
case MODE_1_WOR_TRANSMITTER:
|
||||
this->pin_m0->digital_write(true);
|
||||
this->pin_m1->digital_write(false);
|
||||
ESP_LOGD(TAG, "MODE WOR!");
|
||||
break;
|
||||
case MODE_2_WOR_RECEIVER:
|
||||
// case MODE_2_PROGRAM:
|
||||
this->pin_m0->digital_write(false);
|
||||
this->pin_m1->digital_write(true);
|
||||
ESP_LOGD(TAG, "MODE RECEIVING!");
|
||||
break;
|
||||
case MODE_3_CONFIGURATION:
|
||||
// Mode 3 | Setting operation
|
||||
this->pin_m0->digital_write(true);
|
||||
this->pin_m1->digital_write(true);
|
||||
ESP_LOGD(TAG, "MODE SLEEP CONFIG!");
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// data sheet says 2ms later control is returned, let's give just a bit more time
|
||||
// these modules can take time to activate pins
|
||||
delay(40);
|
||||
|
||||
// wait until aux pin goes back low
|
||||
bool result = this->waitCompleteResponse(1000);
|
||||
|
||||
if (result) {
|
||||
this->mode = mode;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "No success");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool EbyteLoraE220::waitCompleteResponse(unsigned long timeout, unsigned int waitNoAux) {
|
||||
unsigned long t = millis();
|
||||
|
||||
// make darn sure millis() is not about to reach max data type limit and start over
|
||||
if (((unsigned long) (t + timeout)) == 0) {
|
||||
t = 0;
|
||||
}
|
||||
|
||||
// if AUX pin was supplied and look for HIGH state
|
||||
// note you can omit using AUX if no pins are available, but you will have to use delay() to let module finish
|
||||
if (this->pin_aux != nullptr) {
|
||||
while (this->pin_aux->digital_read() == false) {
|
||||
if ((millis() - t) > timeout) {
|
||||
ESP_LOGD(TAG, "Timeout error!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "AUX HIGH!");
|
||||
} else {
|
||||
// if you can't use aux pin, use 4K7 pullup with Arduino
|
||||
// you may need to adjust this value if transmissions fail
|
||||
delay(waitNoAux);
|
||||
ESP_LOGD(TAG, "Wait no AUX pin!");
|
||||
}
|
||||
|
||||
// per data sheet control after aux goes high is 2ms so delay for at least that long)
|
||||
delay(20);
|
||||
ESP_LOGD(TAG, "Complete!");
|
||||
return true;
|
||||
}
|
||||
void EbyteLoraE220::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Ebyte Lora E220");
|
||||
LOG_PIN(" Aux pin: ", this->pin_aux);
|
||||
|
@ -24,18 +116,17 @@ void EbyteLoraE220::dump_config() {
|
|||
void EbyteLoraE220::update() {
|
||||
// This will be called by App.loop()
|
||||
|
||||
if (e220ttl.available() > 1) {
|
||||
// read the String message
|
||||
lora_e220::ResponseContainer rc = e220ttl.receiveMessageRSSI();
|
||||
// Is something goes wrong print error
|
||||
if (rc.status.code != 1) {
|
||||
this->status_text_sensor->publish_state(rc.status.getResponseDescription());
|
||||
} else {
|
||||
// Print the data received
|
||||
this->status_text_sensor->publish_state(rc.status.getResponseDescription());
|
||||
this->message_text_sensor->publish_state(rc.data);
|
||||
this->rssi_sensor->publish_state(rc.rssi);
|
||||
if (this->available() > 1) {
|
||||
std::string buffer;
|
||||
uint8_t data;
|
||||
while (this->available() > 0) {
|
||||
if (this->read_byte(&data)) {
|
||||
buffer += (char) data;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "%s", buffer);
|
||||
this->message_text_sensor->publish_state(buffer.substr(0, buffer.length() - 1));
|
||||
this->rssi_sensor->publish_state(atoi(buffer.substr(buffer.length() - 1, 1).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,25 +7,44 @@
|
|||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "lora_e220.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace ebyte_lora_e220 {
|
||||
|
||||
static const char *const TAG = "ebyte_lora_e220";
|
||||
|
||||
// the mode the receiver is in
|
||||
enum MODE_TYPE {
|
||||
MODE_0_NORMAL = 0,
|
||||
MODE_0_TRANSMISSION = 0,
|
||||
MODE_1_WOR_TRANSMITTER = 1,
|
||||
MODE_1_WOR = 1,
|
||||
MODE_2_WOR_RECEIVER = 2,
|
||||
MODE_2_POWER_SAVING = 2,
|
||||
MODE_3_CONFIGURATION = 3,
|
||||
MODE_3_PROGRAM = 3,
|
||||
MODE_3_SLEEP = 3,
|
||||
MODE_INIT = 0xFF
|
||||
};
|
||||
class EbyteLoraE220 : public PollingComponent, public uart::UARTDevice {
|
||||
public:
|
||||
lora_e220::LoRa_E220 e220ttl = lora_e220::LoRa_E220(this, pin_aux, pin_m0, pin_m1); // SERIAL AUX M0 M1
|
||||
void set_message_sensor(text_sensor::TextSensor *s) { message_text_sensor = s; }
|
||||
void set_status_sensor(text_sensor::TextSensor *s) { status_text_sensor = s; }
|
||||
void set_rssi_sensor(sensor::Sensor *s) { rssi_sensor = s; }
|
||||
void set_pin_aux(GPIOPin *s) { pin_aux = s; }
|
||||
void set_pin_m0(GPIOPin *s) { pin_m0 = s; }
|
||||
void set_pin_m1(GPIOPin *s) { pin_m1 = s; }
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
MODE_TYPE mode = MODE_0_NORMAL;
|
||||
// set WOR mode
|
||||
bool setMode(MODE_TYPE type);
|
||||
// checks the aux port to see if it is done setting
|
||||
bool waitCompleteResponse(unsigned long timeout = 1000, unsigned int waitNoAux = 100);
|
||||
|
||||
protected:
|
||||
std::vector<uint8_t> buffer_;
|
||||
text_sensor::TextSensor *message_text_sensor;
|
||||
|
|
|
@ -1,710 +0,0 @@
|
|||
#include "lora_e220.h"
|
||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||
namespace esphome {
|
||||
namespace lora_e220 {
|
||||
LoRa_E220::LoRa_E220(esphome::uart::UARTDevice *serial, GPIOPin *auxPin, GPIOPin *m0Pin,
|
||||
GPIOPin *m1Pin) { //, uint32_t serialConfig
|
||||
this->serial = serial;
|
||||
this->auxPin = auxPin;
|
||||
|
||||
this->m0Pin = m0Pin;
|
||||
this->m1Pin = m1Pin;
|
||||
}
|
||||
bool LoRa_E220::begin() {
|
||||
if (this->auxPin != nullptr) {
|
||||
this->m0Pin->pin_mode(gpio::FLAG_INPUT);
|
||||
ESP_LOGD(TAG, "Init AUX pin!");
|
||||
}
|
||||
if (this->m0Pin != nullptr) {
|
||||
this->m0Pin->pin_mode(gpio::FLAG_OUTPUT);
|
||||
ESP_LOGD(TAG, "Init M0 pin!");
|
||||
this->m0Pin->digital_write(true);
|
||||
}
|
||||
if (this->m1Pin != nullptr) {
|
||||
this->m0Pin->pin_mode(gpio::FLAG_OUTPUT);
|
||||
ESP_LOGD(TAG, "Init M1 pin!");
|
||||
this->m1Pin->digital_write(true);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Begin ex");
|
||||
|
||||
state_naming::Status status = setMode(MODE_0_NORMAL);
|
||||
return status == state_naming::E220_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Utility method to wait until module is doen tranmitting
|
||||
a timeout is provided to avoid an infinite loop
|
||||
|
||||
*/
|
||||
|
||||
state_naming::Status LoRa_E220::waitCompleteResponse(unsigned long timeout, unsigned int waitNoAux) {
|
||||
state_naming::Status result = state_naming::E220_SUCCESS;
|
||||
|
||||
unsigned long t = millis();
|
||||
|
||||
// make darn sure millis() is not about to reach max data type limit and start over
|
||||
if (((unsigned long) (t + timeout)) == 0) {
|
||||
t = 0;
|
||||
}
|
||||
|
||||
// if AUX pin was supplied and look for HIGH state
|
||||
// note you can omit using AUX if no pins are available, but you will have to use delay() to let module finish
|
||||
if (this->auxPin != -1) {
|
||||
while (this->auxPin->digital_read() == false) {
|
||||
if ((millis() - t) > timeout) {
|
||||
result = state_naming::ERR_E220_TIMEOUT;
|
||||
ESP_LOGD(TAG, "Timeout error!");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "AUX HIGH!");
|
||||
} else {
|
||||
// if you can't use aux pin, use 4K7 pullup with Arduino
|
||||
// you may need to adjust this value if transmissions fail
|
||||
this->managedDelay(waitNoAux);
|
||||
ESP_LOGD(TAG, "Wait no AUX pin!");
|
||||
}
|
||||
|
||||
// per data sheet control after aux goes high is 2ms so delay for at least that long)
|
||||
this->managedDelay(20);
|
||||
ESP_LOGD(TAG, "Complete!");
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
delay() in a library is not a good idea as it can stop interrupts
|
||||
just poll internal time until timeout is reached
|
||||
|
||||
*/
|
||||
|
||||
void LoRa_E220::managedDelay(unsigned long timeout) {
|
||||
unsigned long t = millis();
|
||||
|
||||
// make darn sure millis() is not about to reach max data type limit and start over
|
||||
if (((unsigned long) (t + timeout)) == 0) {
|
||||
t = 0;
|
||||
}
|
||||
|
||||
while ((millis() - t) < timeout) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Method to indicate availability
|
||||
|
||||
*/
|
||||
|
||||
int LoRa_E220::available() { return this->serial->available(); }
|
||||
|
||||
void LoRa_E220::flush() { this->serial->flush(); }
|
||||
|
||||
void LoRa_E220::cleanUARTBuffer() {
|
||||
while (this->serial->available()) {
|
||||
this->serial->read();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Method to send a chunk of data provided data is in a struct--my personal favorite as you
|
||||
need not parse or worry about sprintf() inability to handle floats
|
||||
|
||||
TTP: put your structure definition into a .h file and include in both the sender and reciever
|
||||
sketches
|
||||
|
||||
NOTE: of your sender and receiver MCU's are different (Teensy and Arduino) caution on the data
|
||||
types each handle ints floats differently
|
||||
|
||||
*/
|
||||
|
||||
state_naming::Status LoRa_E220::sendStruct(void *structureManaged, uint16_t size_) {
|
||||
if (size_ > MAX_SIZE_TX_PACKET + 2) {
|
||||
return state_naming::ERR_E220_PACKET_TOO_BIG;
|
||||
}
|
||||
|
||||
Status result = state_naming::E220_SUCCESS;
|
||||
|
||||
uint8_t len = this->serial->write((uint8_t *) structureManaged, size_);
|
||||
if (len != size_) {
|
||||
ESP_LOGD(TAG, "Send... len:")
|
||||
ESP_LOGD(TAG, "%d", len);
|
||||
ESP_LOGD(TAG, " size:")
|
||||
ESP_LOGD(TAG, "%d", size_);
|
||||
if (len == 0) {
|
||||
result = state_naming::ERR_E220_NO_RESPONSE_FROM_DEVICE;
|
||||
} else {
|
||||
result = state_naming::ERR_E220_DATA_SIZE_NOT_MATCH;
|
||||
}
|
||||
}
|
||||
if (result != state_naming::E220_SUCCESS)
|
||||
return result;
|
||||
|
||||
result = this->waitCompleteResponse(5000, 5000);
|
||||
if (result != state_naming::E220_SUCCESS)
|
||||
return result;
|
||||
ESP_LOGD(TAG, "Clear buffer...")
|
||||
this->cleanUARTBuffer();
|
||||
|
||||
ESP_LOGD(TAG, "ok!")
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Method to get a chunk of data provided data is in a struct--my personal favorite as you
|
||||
need not parse or worry about sprintf() inability to handle floats
|
||||
|
||||
TTP: put your structure definition into a .h file and include in both the sender and reciever
|
||||
sketches
|
||||
|
||||
NOTE: of your sender and receiver MCU's are different (Teensy and Arduino) caution on the data
|
||||
types each handle ints floats differently
|
||||
|
||||
*/
|
||||
|
||||
state_naming::Status LoRa_E220::receiveStruct(void *structureManaged, uint16_t size_) {
|
||||
Status result = state_naming::E220_SUCCESS;
|
||||
|
||||
uint8_t len = this->serialDef.stream->readBytes((uint8_t *) structureManaged, size_);
|
||||
|
||||
ESP_LOGD(TAG, "Available buffer: ");
|
||||
ESP_LOGD(TAG, "%d", len);
|
||||
ESP_LOGD(TAG, " structure size: ");
|
||||
ESP_LOGD(TAG, "%d", size_);
|
||||
|
||||
if (len != size_) {
|
||||
if (len == 0) {
|
||||
result = state_naming::ERR_E220_NO_RESPONSE_FROM_DEVICE;
|
||||
} else {
|
||||
result = state_naming::ERR_E220_DATA_SIZE_NOT_MATCH;
|
||||
}
|
||||
}
|
||||
if (result != state_naming::E220_SUCCESS)
|
||||
return result;
|
||||
|
||||
result = this->waitCompleteResponse(1000);
|
||||
if (result != state_naming::E220_SUCCESS)
|
||||
return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
method to set the mode (program, normal, etc.)
|
||||
|
||||
*/
|
||||
|
||||
state_naming::Status LoRa_E220::setMode(MODE_TYPE mode) {
|
||||
// data sheet claims module needs some extra time after mode setting (2ms)
|
||||
// most of my projects uses 10 ms, but 40ms is safer
|
||||
|
||||
this->managedDelay(40);
|
||||
|
||||
if (this->m0Pin == -1 && this->m1Pin == -1) {
|
||||
ESP_LOGD(TAG, "The M0 and M1 pins is not set, this mean that you are connect directly the pins as you need!")
|
||||
} else {
|
||||
switch (mode) {
|
||||
case MODE_0_NORMAL:
|
||||
// Mode 0 | normal operation
|
||||
this->m0Pin->digital_write(false);
|
||||
this->m1Pin->digital_write(false);
|
||||
ESP_LOGD(TAG, "MODE NORMAL!");
|
||||
break;
|
||||
case MODE_1_WOR_TRANSMITTER:
|
||||
this->m0Pin->digital_write(true);
|
||||
this->m1Pin->digital_write(false);
|
||||
ESP_LOGD(TAG, "MODE WOR!");
|
||||
break;
|
||||
case MODE_2_WOR_RECEIVER:
|
||||
// case MODE_2_PROGRAM:
|
||||
this->m0Pin->digital_write(false);
|
||||
this->m1Pin->digital_write(true);
|
||||
ESP_LOGD(TAG, "MODE RECEIVING!");
|
||||
break;
|
||||
case MODE_3_CONFIGURATION:
|
||||
// Mode 3 | Setting operation
|
||||
this->m0Pin->digital_write(true);
|
||||
this->m1Pin->digital_write(true);
|
||||
ESP_LOGD(TAG, "MODE SLEEP CONFIG!");
|
||||
break;
|
||||
|
||||
default:
|
||||
return state_naming::ERR_E220_INVALID_PARAM;
|
||||
}
|
||||
}
|
||||
// data sheet says 2ms later control is returned, let's give just a bit more time
|
||||
// these modules can take time to activate pins
|
||||
this->managedDelay(40);
|
||||
|
||||
// wait until aux pin goes back low
|
||||
state_naming::Status res = this->waitCompleteResponse(1000);
|
||||
|
||||
if (res == state_naming::E220_SUCCESS) {
|
||||
this->mode = mode;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
MODE_TYPE LoRa_E220::getMode() { return this->mode; }
|
||||
|
||||
bool LoRa_E220::writeProgramCommand(PROGRAM_COMMAND cmd, REGISTER_ADDRESS addr, PACKET_LENGHT pl) {
|
||||
uint8_t CMD[3] = {cmd, addr, pl};
|
||||
uint8_t size = this->serial->write_array(CMD, 3);
|
||||
|
||||
ESP_LOGD(TAG, "%d", size);
|
||||
|
||||
this->managedDelay(50); // need ti check
|
||||
|
||||
return size != 2;
|
||||
}
|
||||
|
||||
ResponseStructContainer LoRa_E220::getConfiguration() {
|
||||
ResponseStructContainer rc;
|
||||
|
||||
rc.status.code = checkUARTConfiguration(MODE_3_PROGRAM);
|
||||
if (rc.status.code != state_naming::E220_SUCCESS)
|
||||
return rc;
|
||||
|
||||
MODE_TYPE prevMode = this->mode;
|
||||
|
||||
rc.status.code = this->setMode(MODE_3_PROGRAM);
|
||||
if (rc.status.code != state_naming::E220_SUCCESS)
|
||||
return rc;
|
||||
|
||||
this->writeProgramCommand(READ_CONFIGURATION, REG_ADDRESS_CFG, PL_CONFIGURATION);
|
||||
|
||||
rc.data = malloc(sizeof(Configuration));
|
||||
rc.status.code = this->receiveStruct((uint8_t *) rc.data, sizeof(Configuration));
|
||||
|
||||
#ifdef LoRa_E220_DEBUG
|
||||
this->printParameters((Configuration *) rc.data);
|
||||
#endif
|
||||
|
||||
if (rc.status.code != state_naming::E220_SUCCESS) {
|
||||
this->setMode(prevMode);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc.status.code = this->setMode(prevMode);
|
||||
if (rc.status.code != state_naming::E220_SUCCESS)
|
||||
return rc;
|
||||
|
||||
if (WRONG_FORMAT == ((Configuration *) rc.data)->COMMAND) {
|
||||
rc.status.code = state_naming::ERR_E220_WRONG_FORMAT;
|
||||
}
|
||||
if (RETURNED_COMMAND != ((Configuration *) rc.data)->COMMAND ||
|
||||
REG_ADDRESS_CFG != ((Configuration *) rc.data)->STARTING_ADDRESS ||
|
||||
PL_CONFIGURATION != ((Configuration *) rc.data)->LENGHT) {
|
||||
rc.status.code = state_naming::ERR_E220_HEAD_NOT_RECOGNIZED;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
state_naming::RESPONSE_STATUS LoRa_E220::checkUARTConfiguration(MODE_TYPE mode) {
|
||||
if (mode == MODE_3_PROGRAM) {
|
||||
return state_naming::ERR_E220_WRONG_UART_CONFIG;
|
||||
}
|
||||
return state_naming::E220_SUCCESS;
|
||||
}
|
||||
|
||||
ResponseStatus LoRa_E220::setConfiguration(Configuration configuration, PROGRAM_COMMAND saveType) {
|
||||
ResponseStatus rc;
|
||||
|
||||
rc.code = checkUARTConfiguration(MODE_3_PROGRAM);
|
||||
if (rc.code != state_naming::E220_SUCCESS)
|
||||
return rc;
|
||||
|
||||
MODE_TYPE prevMode = this->mode;
|
||||
|
||||
rc.code = this->setMode(MODE_3_PROGRAM);
|
||||
if (rc.code != state_naming::E220_SUCCESS)
|
||||
return rc;
|
||||
|
||||
// this->writeProgramCommand(saveType, REG_ADDRESS_CFG);
|
||||
|
||||
// configuration.HEAD = saveType;
|
||||
configuration.COMMAND = saveType;
|
||||
configuration.STARTING_ADDRESS = REG_ADDRESS_CFG;
|
||||
configuration.LENGHT = PL_CONFIGURATION;
|
||||
|
||||
rc.code = this->sendStruct((uint8_t *) &configuration, sizeof(Configuration));
|
||||
if (rc.code != state_naming::E220_SUCCESS) {
|
||||
this->setMode(prevMode);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc.code = this->receiveStruct((uint8_t *) &configuration, sizeof(Configuration));
|
||||
|
||||
#ifdef LoRa_E220_DEBUG
|
||||
this->printParameters((Configuration *) &configuration);
|
||||
#endif
|
||||
|
||||
rc.code = this->setMode(prevMode);
|
||||
if (rc.code != state_naming::E220_SUCCESS)
|
||||
return rc;
|
||||
|
||||
if (WRONG_FORMAT == ((Configuration *) &configuration)->COMMAND) {
|
||||
rc.code = state_naming::ERR_E220_WRONG_FORMAT;
|
||||
}
|
||||
if (RETURNED_COMMAND != ((Configuration *) &configuration)->COMMAND ||
|
||||
REG_ADDRESS_CFG != ((Configuration *) &configuration)->STARTING_ADDRESS ||
|
||||
PL_CONFIGURATION != ((Configuration *) &configuration)->LENGHT) {
|
||||
rc.code = state_naming::ERR_E220_HEAD_NOT_RECOGNIZED;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
ResponseStructContainer LoRa_E220::getModuleInformation() {
|
||||
ResponseStructContainer rc;
|
||||
|
||||
rc.status.code = checkUARTConfiguration(MODE_3_PROGRAM);
|
||||
if (rc.status.code != state_naming::E220_SUCCESS)
|
||||
return rc;
|
||||
|
||||
MODE_TYPE prevMode = this->mode;
|
||||
|
||||
rc.status.code = this->setMode(MODE_3_PROGRAM);
|
||||
if (rc.status.code != state_naming::E220_SUCCESS)
|
||||
return rc;
|
||||
|
||||
this->writeProgramCommand(READ_CONFIGURATION, REG_ADDRESS_PID, PL_PID);
|
||||
|
||||
rc.data = malloc(sizeof(ModuleInformation));
|
||||
|
||||
rc.status.code = this->receiveStruct((uint8_t *) rc.data, sizeof(ModuleInformation));
|
||||
if (rc.status.code != state_naming::E220_SUCCESS) {
|
||||
this->setMode(prevMode);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc.status.code = this->setMode(prevMode);
|
||||
if (rc.status.code != state_naming::E220_SUCCESS)
|
||||
return rc;
|
||||
|
||||
// this->printParameters(*configuration);
|
||||
|
||||
if (WRONG_FORMAT == ((ModuleInformation *) rc.data)->COMMAND) {
|
||||
rc.status.code = state_naming::ERR_E220_WRONG_FORMAT;
|
||||
}
|
||||
if (RETURNED_COMMAND != ((ModuleInformation *) rc.data)->COMMAND ||
|
||||
REG_ADDRESS_PID != ((ModuleInformation *) rc.data)->STARTING_ADDRESS ||
|
||||
PL_PID != ((ModuleInformation *) rc.data)->LENGHT) {
|
||||
rc.status.code = state_naming::ERR_E220_HEAD_NOT_RECOGNIZED;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "----------------------------------------");
|
||||
ESP_LOGD(TAG, "HEAD: ");
|
||||
ESP_LOGD(TAG, "%d", ((ModuleInformation *) rc.data)->COMMAND);
|
||||
ESP_LOGD(TAG, " ");
|
||||
ESP_LOGD(TAG, "%d", ((ModuleInformation *) rc.data)->STARTING_ADDRESS);
|
||||
ESP_LOGD(TAG, " ");
|
||||
ESP_LOGD(TAG, "%s", format_hex_pretty(((ModuleInformation *) rc.data)->LENGHT).c_str());
|
||||
|
||||
ESP_LOGD(TAG, "Model no.: ");
|
||||
ESP_LOGD(TAG, "%s", format_hex_pretty(((ModuleInformation *) rc.data)->model).c_str());
|
||||
ESP_LOGD(TAG, "Version : ");
|
||||
ESP_LOGD(TAG, "%s", format_hex_pretty(((ModuleInformation *) rc.data)->version).c_str());
|
||||
ESP_LOGD(TAG, "Features : ");
|
||||
ESP_LOGD(TAG, "%s", format_hex_pretty(((ModuleInformation *) rc.data)->features).c_str());
|
||||
ESP_LOGD(TAG, "Status : ");
|
||||
ESP_LOGD(TAG, rc.status.getResponseDescription());
|
||||
ESP_LOGD(TAG, "----------------------------------------");
|
||||
return rc;
|
||||
}
|
||||
|
||||
ResponseStatus LoRa_E220::resetModule() {
|
||||
ESP_LOGD(TAG, "No information to reset module!");
|
||||
ResponseStatus status;
|
||||
status.code = state_naming::ERR_E220_NOT_IMPLEMENT;
|
||||
return status;
|
||||
}
|
||||
|
||||
state_naming::ResponseContainer LoRa_E220::receiveMessage() { return LoRa_E220::receiveMessageComplete(false); }
|
||||
state_naming::ResponseContainer LoRa_E220::receiveMessageRSSI() { return LoRa_E220::receiveMessageComplete(true); }
|
||||
|
||||
state_naming::ResponseContainer LoRa_E220::receiveMessageComplete(bool rssiEnabled) {
|
||||
ResponseContainer rc;
|
||||
rc.status.code = state_naming::E220_SUCCESS;
|
||||
std::string buffer;
|
||||
uint8_t data;
|
||||
while (this->available() > 0) {
|
||||
if (this->read_byte(&data)) {
|
||||
buffer += (char) data;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, buffer);
|
||||
|
||||
if (rssiEnabled) {
|
||||
rc.rssi = buffer.charAt(tmpData.length() - 1);
|
||||
rc.data = buffer.substd::string(0, tmpData.length() - 1);
|
||||
} else {
|
||||
rc.data = tmpData;
|
||||
}
|
||||
this->cleanUARTBuffer();
|
||||
if (rc.status.code != state_naming::E220_SUCCESS) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
// rc.data = message; // malloc(sizeof (moduleInformation));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
state_naming::ResponseContainer LoRa_E220::receiveInitialMessage(uint8_t size) {
|
||||
ResponseContainer rc;
|
||||
rc.status.code = state_naming::E220_SUCCESS;
|
||||
char buff[size];
|
||||
uint8_t len = this->serialDef.stream->readBytes(buff, size);
|
||||
if (len != size) {
|
||||
if (len == 0) {
|
||||
rc.status.code = state_naming::ERR_E220_NO_RESPONSE_FROM_DEVICE;
|
||||
} else {
|
||||
rc.status.code = state_naming::ERR_E220_DATA_SIZE_NOT_MATCH;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc.data = buff; // malloc(sizeof (moduleInformation));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
state_naming::ResponseStructContainer LoRa_E220::receiveMessage(const uint8_t size) {
|
||||
return LoRa_E220::receiveMessageComplete(size, false);
|
||||
}
|
||||
state_naming::ResponseStructContainer LoRa_E220::receiveMessageRSSI(const uint8_t size) {
|
||||
return LoRa_E220::receiveMessageComplete(size, true);
|
||||
}
|
||||
|
||||
state_naming::ResponseStructContainer LoRa_E220::receiveMessageComplete(const uint8_t size, bool rssiEnabled) {
|
||||
ResponseStructContainer rc;
|
||||
|
||||
rc.data = malloc(size);
|
||||
rc.status.code = this->receiveStruct((uint8_t *) rc.data, size);
|
||||
if (rc.status.code != state_naming::E220_SUCCESS) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (rssiEnabled) {
|
||||
char rssi[1];
|
||||
this->serial->read_bytes(rssi, 1);
|
||||
rc.rssi = rssi[0];
|
||||
}
|
||||
this->cleanUARTBuffer();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
ResponseStatus LoRa_E220::sendMessage(const void *message, const uint8_t size) {
|
||||
ResponseStatus status;
|
||||
status.code = this->sendStruct((uint8_t *) message, size);
|
||||
if (status.code != state_naming::E220_SUCCESS)
|
||||
return status;
|
||||
|
||||
return status;
|
||||
}
|
||||
ResponseStatus LoRa_E220::sendMessage(const std::string message) {
|
||||
ESP_LOGD(TAG, "Send message: ");
|
||||
ESP_LOGD(TAG, message);
|
||||
uint8_t size = message.length(); // sizeof(message.c_str())+1;
|
||||
ESP_LOGD(TAG, " size: ");
|
||||
ESP_LOGD(TAG, "%d", size);
|
||||
char messageFixed[size];
|
||||
memcpy(messageFixed, message.c_str(), size);
|
||||
ESP_LOGD(TAG, " memcpy ");
|
||||
|
||||
ResponseStatus status;
|
||||
status.code = this->sendStruct((uint8_t *) &messageFixed, size);
|
||||
if (status.code != state_naming::E220_SUCCESS)
|
||||
return status;
|
||||
|
||||
// free(messageFixed);
|
||||
return status;
|
||||
}
|
||||
|
||||
ResponseStatus LoRa_E220::sendFixedMessage(uint8_t ADDH, uint8_t ADDL, uint8_t CHAN, const std::string message) {
|
||||
uint8_t size = message.length();
|
||||
char messageFixed[size];
|
||||
memcpy(messageFixed, message.c_str(), size);
|
||||
return this->sendFixedMessage(ADDH, ADDL, CHAN, (uint8_t *) messageFixed, size);
|
||||
}
|
||||
ResponseStatus LoRa_E220::sendBroadcastFixedMessage(uint8_t CHAN, const std::string message) {
|
||||
return this->sendFixedMessage(state_naming::BROADCAST_ADDRESS, state_naming::BROADCAST_ADDRESS, CHAN, message);
|
||||
}
|
||||
|
||||
typedef struct fixedStransmission {
|
||||
uint8_t ADDH = 0;
|
||||
uint8_t ADDL = 0;
|
||||
uint8_t CHAN = 0;
|
||||
unsigned char message[];
|
||||
} FixedStransmission;
|
||||
|
||||
FixedStransmission *init_stack(int m) {
|
||||
FixedStransmission *st = (FixedStransmission *) malloc(sizeof(FixedStransmission) + m * sizeof(int));
|
||||
return st;
|
||||
}
|
||||
|
||||
ResponseStatus LoRa_E220::sendFixedMessage(uint8_t ADDH, uint8_t ADDL, uint8_t CHAN, const void *message,
|
||||
const uint8_t size) {
|
||||
ESP_LOGD(TAG, ADDH);
|
||||
FixedStransmission *fixedStransmission = init_stack(size);
|
||||
fixedStransmission->ADDH = ADDH;
|
||||
fixedStransmission->ADDL = ADDL;
|
||||
fixedStransmission->CHAN = CHAN;
|
||||
memcpy(fixedStransmission->message, (unsigned char *) message, size);
|
||||
ResponseStatus status;
|
||||
status.code = this->sendStruct((uint8_t *) fixedStransmission, size + 3);
|
||||
free(fixedStransmission);
|
||||
if (status.code != state_naming::E220_SUCCESS)
|
||||
return status;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
ConfigurationMessage *init_stack_conf(int m) {
|
||||
ConfigurationMessage *st = (ConfigurationMessage *) malloc(sizeof(ConfigurationMessage) + m * sizeof(int));
|
||||
return st;
|
||||
}
|
||||
|
||||
ResponseStatus LoRa_E220::sendConfigurationMessage(uint8_t ADDH, uint8_t ADDL, uint8_t CHAN,
|
||||
Configuration *configuration, PROGRAM_COMMAND programCommand) {
|
||||
ResponseStatus rc;
|
||||
|
||||
configuration->COMMAND = programCommand;
|
||||
configuration->STARTING_ADDRESS = REG_ADDRESS_CFG;
|
||||
configuration->LENGHT = PL_CONFIGURATION;
|
||||
|
||||
ConfigurationMessage *fixedStransmission = init_stack_conf(sizeof(Configuration));
|
||||
|
||||
memcpy(fixedStransmission->message, (unsigned char *) configuration, sizeof(Configuration));
|
||||
|
||||
fixedStransmission->specialCommand1 = SPECIAL_WIFI_CONF_COMMAND;
|
||||
fixedStransmission->specialCommand2 = SPECIAL_WIFI_CONF_COMMAND;
|
||||
|
||||
ESP_LOGD(TAG, "%d", sizeof(Configuration) + 2);
|
||||
|
||||
rc = sendFixedMessage(ADDH, ADDL, CHAN, fixedStransmission, sizeof(Configuration) + 2);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ResponseStatus LoRa_E220::sendBroadcastFixedMessage(uint8_t CHAN, const void *message, const uint8_t size) {
|
||||
return this->sendFixedMessage(0xFF, 0xFF, CHAN, message, size);
|
||||
}
|
||||
|
||||
#define KeeLoq_NLF 0x3A5C742E
|
||||
|
||||
unsigned long LoRa_E220::encrypt(unsigned long data) {
|
||||
unsigned long x = data;
|
||||
unsigned long r;
|
||||
int keyBitNo, index;
|
||||
unsigned long keyBitVal, bitVal;
|
||||
|
||||
for (r = 0; r < 528; r++) {
|
||||
keyBitNo = r & 63;
|
||||
if (keyBitNo < 32)
|
||||
keyBitVal = bitRead(this->halfKeyloqKey, keyBitNo); // key low
|
||||
else
|
||||
keyBitVal = bitRead(this->halfKeyloqKey, keyBitNo - 32); // key hight
|
||||
index = 1 * bitRead(x, 1) + 2 * bitRead(x, 9) + 4 * bitRead(x, 20) + 8 * bitRead(x, 26) + 16 * bitRead(x, 31);
|
||||
bitVal = bitRead(x, 0) ^ bitRead(x, 16) ^ bitRead(KeeLoq_NLF, index) ^ keyBitVal;
|
||||
x = (x >> 1) ^ bitVal << 31;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
unsigned long LoRa_E220::decrypt(unsigned long data) {
|
||||
unsigned long x = data;
|
||||
unsigned long r;
|
||||
int keyBitNo, index;
|
||||
unsigned long keyBitVal, bitVal;
|
||||
|
||||
for (r = 0; r < 528; r++) {
|
||||
keyBitNo = (15 - r) & 63;
|
||||
if (keyBitNo < 32)
|
||||
keyBitVal = bitRead(this->halfKeyloqKey, keyBitNo); // key low
|
||||
else
|
||||
keyBitVal = bitRead(this->halfKeyloqKey, keyBitNo - 32); // key hight
|
||||
index = 1 * bitRead(x, 0) + 2 * bitRead(x, 8) + 4 * bitRead(x, 19) + 8 * bitRead(x, 25) + 16 * bitRead(x, 30);
|
||||
bitVal = bitRead(x, 31) ^ bitRead(x, 15) ^ bitRead(KeeLoq_NLF, index) ^ keyBitVal;
|
||||
x = (x << 1) ^ bitVal;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
#ifdef LoRa_E220_DEBUG
|
||||
void LoRa_E220::printParameters(struct Configuration *configuration) {
|
||||
ESP_LOGD(TAG, "----------------------------------------");
|
||||
|
||||
ESP_LOGD(TAG, "HEAD : ");
|
||||
ESP_LOGD(TAG, "%s", format_hex_pretty(configuration->COMMAND).c_str());
|
||||
ESP_LOGD(TAG, " ");
|
||||
ESP_LOGD(TAG, format_hex_pretty(configuration->STARTING_ADDRESS).c_str());
|
||||
ESP_LOGD(TAG, " ");
|
||||
ESP_LOGD(TAG, format_hex_pretty(configuration->LENGHT).c_str());
|
||||
ESP_LOGD(TAG, " ");
|
||||
ESP_LOGD(TAG, "AddH : ");
|
||||
ESP_LOGD(TAG, format_hex_pretty(configuration->ADDH).c_str();
|
||||
ESP_LOGD(TAG, "AddL : ");
|
||||
ESP_LOGD(TAG, format_hex_pretty(configuration->ADDL).c_str());
|
||||
ESP_LOGD(TAG, " ");
|
||||
ESP_LOGD(TAG, "Chan : ");
|
||||
ESP_LOGD(TAG, "%d", configuration->CHAN);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->getChannelDescription());
|
||||
ESP_LOGD(TAG, " ");
|
||||
ESP_LOGD(TAG, "SpeedParityBit : ");
|
||||
ESP_LOGD(TAG, "%d", configuration->SPED.uartParity);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->SPED.getUARTParityDescription());
|
||||
ESP_LOGD(TAG, "SpeedUARTDatte : ");
|
||||
ESP_LOGD(TAG,"%d", configuration->SPED.uartBaudRate);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->SPED.getUARTBaudRateDescription());
|
||||
ESP_LOGD(TAG, "SpeedAirDataRate : ");
|
||||
ESP_LOGD(TAG,"%d", configuration->SPED.airDataRate);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->SPED.getAirDataRateDescription());
|
||||
ESP_LOGD(TAG, " ");
|
||||
ESP_LOGD(TAG, "OptionSubPacketSett: ");
|
||||
ESP_LOGD(TAG,"%d", configuration->OPTION.subPacketSetting);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->OPTION.getSubPacketSetting());
|
||||
ESP_LOGD(TAG, "OptionTranPower : ");
|
||||
ESP_LOGD(TAG, configuration->OPTION.transmissionPower);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->OPTION.getTransmissionPowerDescription());
|
||||
ESP_LOGD(TAG, "OptionRSSIAmbientNo: ");
|
||||
ESP_LOGD(TAG,"%d", configuration->OPTION.RSSIAmbientNoise);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->OPTION.getRSSIAmbientNoiseEnable());
|
||||
ESP_LOGD(TAG, " ");
|
||||
ESP_LOGD(TAG, "TransModeWORPeriod : ");
|
||||
ESP_LOGD(TAG,"%d", configuration->TRANSMISSION_MODE.WORPeriod);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->TRANSMISSION_MODE.getWORPeriodByParamsDescription());
|
||||
ESP_LOGD(TAG, "TransModeEnableLBT : ");
|
||||
ESP_LOGD(TAG,"%d", configuration->TRANSMISSION_MODE.enableLBT);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->TRANSMISSION_MODE.getLBTEnableByteDescription());
|
||||
ESP_LOGD(TAG, "TransModeEnableRSSI: ");
|
||||
ESP_LOGD(TAG, "%d", configuration->TRANSMISSION_MODE.enableRSSI);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->TRANSMISSION_MODE.getRSSIEnableByteDescription());
|
||||
ESP_LOGD(TAG, "TransModeFixedTrans: ");
|
||||
ESP_LOGD(TAG, "%d", configuration->TRANSMISSION_MODE.fixedTransmission);
|
||||
ESP_LOGD(TAG, " -> ");
|
||||
ESP_LOGD(TAG, configuration->TRANSMISSION_MODE.getFixedTransmissionDescription());
|
||||
|
||||
ESP_LOGD(TAG, "----------------------------------------");
|
||||
}
|
||||
#endif
|
||||
} // namespace lora_e220
|
||||
} // namespace esphome
|
|
@ -1,213 +0,0 @@
|
|||
#pragma once
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "state_naming.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
namespace esphome {
|
||||
namespace lora_e220 {
|
||||
|
||||
#define MAX_SIZE_TX_PACKET 200
|
||||
|
||||
static const char *const TAG = "ebyte_lora_e220";
|
||||
enum MODE_TYPE {
|
||||
MODE_0_NORMAL = 0,
|
||||
MODE_0_TRANSMISSION = 0,
|
||||
MODE_1_WOR_TRANSMITTER = 1,
|
||||
MODE_1_WOR = 1,
|
||||
MODE_2_WOR_RECEIVER = 2,
|
||||
MODE_2_POWER_SAVING = 2,
|
||||
MODE_3_CONFIGURATION = 3,
|
||||
MODE_3_PROGRAM = 3,
|
||||
MODE_3_SLEEP = 3,
|
||||
MODE_INIT = 0xFF
|
||||
};
|
||||
|
||||
enum PROGRAM_COMMAND {
|
||||
WRITE_CFG_PWR_DWN_SAVE = 0xC0,
|
||||
READ_CONFIGURATION = 0xC1,
|
||||
WRITE_CFG_PWR_DWN_LOSE = 0xC2,
|
||||
WRONG_FORMAT = 0xFF,
|
||||
RETURNED_COMMAND = 0xC1,
|
||||
SPECIAL_WIFI_CONF_COMMAND = 0xCF
|
||||
};
|
||||
|
||||
enum REGISTER_ADDRESS {
|
||||
REG_ADDRESS_CFG = 0x00,
|
||||
REG_ADDRESS_SPED = 0x02,
|
||||
REG_ADDRESS_TRANS_MODE = 0x03,
|
||||
REG_ADDRESS_CHANNEL = 0x04,
|
||||
REG_ADDRESS_OPTION = 0x05,
|
||||
REG_ADDRESS_CRYPT = 0x06,
|
||||
REG_ADDRESS_PID = 0x08
|
||||
};
|
||||
|
||||
enum PACKET_LENGHT {
|
||||
PL_CONFIGURATION = 0x08,
|
||||
|
||||
PL_SPED = 0x01,
|
||||
PL_OPTION = 0x01,
|
||||
PL_TRANSMISSION_MODE = 0x01,
|
||||
PL_CHANNEL = 0x01,
|
||||
PL_CRYPT = 0x02,
|
||||
PL_PID = 0x03
|
||||
};
|
||||
|
||||
struct Speed {
|
||||
uint8_t airDataRate : 3; // bit 0-2
|
||||
std::string getAirDataRateDescription() { return state_naming::getAirDataRateDescriptionByParams(this->airDataRate); }
|
||||
|
||||
uint8_t uartParity : 2; // bit 3-4
|
||||
std::string getUARTParityDescription() { return state_naming::getUARTParityDescriptionByParams(this->uartParity); }
|
||||
|
||||
uint8_t uartBaudRate : 3; // bit 5-7
|
||||
std::string getUARTBaudRateDescription() {
|
||||
return state_naming::getUARTBaudRateDescriptionByParams(this->uartBaudRate);
|
||||
}
|
||||
};
|
||||
|
||||
struct TransmissionMode {
|
||||
uint8_t WORPeriod : 3; // bit 2,1,0
|
||||
std::string getWORPeriodByParamsDescription() { return state_naming::getWORPeriodByParams(this->WORPeriod); }
|
||||
uint8_t reserved2 : 1; // bit 3
|
||||
uint8_t enableLBT : 1; // bit 4
|
||||
std::string getLBTEnableByteDescription() { return state_naming::getLBTEnableByteByParams(this->enableLBT); }
|
||||
uint8_t reserved : 1; // bit 5
|
||||
|
||||
uint8_t fixedTransmission : 1; // bit 6
|
||||
std::string getFixedTransmissionDescription() {
|
||||
return state_naming::getFixedTransmissionDescriptionByParams(this->fixedTransmission);
|
||||
}
|
||||
|
||||
uint8_t enableRSSI : 1; // bit 7
|
||||
std::string getRSSIEnableByteDescription() { return state_naming::getRSSIEnableByteByParams(this->enableRSSI); }
|
||||
};
|
||||
|
||||
struct Option {
|
||||
uint8_t transmissionPower : 2; // bit 0-1
|
||||
std::string getTransmissionPowerDescription() {
|
||||
return state_naming::getTransmissionPowerDescriptionByParams(this->transmissionPower);
|
||||
}
|
||||
uint8_t reserved : 3; // bit 2-4
|
||||
|
||||
uint8_t RSSIAmbientNoise : 1; // bit 5
|
||||
std::string getRSSIAmbientNoiseEnable() {
|
||||
return state_naming::getRSSIAmbientNoiseEnableByParams(this->RSSIAmbientNoise);
|
||||
}
|
||||
|
||||
uint8_t subPacketSetting : 2; // bit 6-7
|
||||
std::string getSubPacketSetting() { return state_naming::getSubPacketSettingByParams(this->subPacketSetting); }
|
||||
};
|
||||
|
||||
struct Crypt {
|
||||
uint8_t CRYPT_H = 0;
|
||||
uint8_t CRYPT_L = 0;
|
||||
};
|
||||
|
||||
struct Configuration {
|
||||
uint8_t COMMAND = 0;
|
||||
uint8_t STARTING_ADDRESS = 0;
|
||||
uint8_t LENGHT = 0;
|
||||
|
||||
uint8_t ADDH = 0;
|
||||
uint8_t ADDL = 0;
|
||||
|
||||
struct Speed SPED;
|
||||
struct Option OPTION;
|
||||
|
||||
uint8_t CHAN = 0;
|
||||
std::string getChannelDescription() { return std::string(this->CHAN + OPERATING_FREQUENCY + "MHz"); }
|
||||
|
||||
struct TransmissionMode TRANSMISSION_MODE;
|
||||
|
||||
struct Crypt CRYPT;
|
||||
};
|
||||
|
||||
struct ModuleInformation {
|
||||
uint8_t COMMAND = 0;
|
||||
uint8_t STARTING_ADDRESS = 0;
|
||||
uint8_t LENGHT = 0;
|
||||
|
||||
uint8_t model = 0;
|
||||
uint8_t version = 0;
|
||||
uint8_t features = 0;
|
||||
};
|
||||
|
||||
struct ResponseStatus {
|
||||
uint8_t code;
|
||||
std::string getResponseDescription() { return state_naming::getResponseDescriptionByParams(this->code); }
|
||||
};
|
||||
|
||||
struct ResponseStructContainer {
|
||||
void *data;
|
||||
uint8_t rssi;
|
||||
ResponseStatus status;
|
||||
void close() { free(this->data); }
|
||||
};
|
||||
struct ResponseContainer {
|
||||
std::string data;
|
||||
uint8_t rssi;
|
||||
ResponseStatus status;
|
||||
};
|
||||
|
||||
struct ConfigurationMessage {
|
||||
uint8_t specialCommand1 = 0xCF;
|
||||
uint8_t specialCommand2 = 0xCF;
|
||||
|
||||
unsigned char message[];
|
||||
};
|
||||
|
||||
class LoRa_E220 {
|
||||
public:
|
||||
LoRa_E220(uart::UARTDevice *device, GPIOPin *auxPin, GPIOPin *m0Pin, GPIOPin *m1Pin);
|
||||
bool begin();
|
||||
state_naming::Status setMode(MODE_TYPE mode);
|
||||
MODE_TYPE getMode();
|
||||
ResponseStructContainer getConfiguration();
|
||||
ResponseStatus setConfiguration(Configuration configuration, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);
|
||||
ResponseStructContainer getModuleInformation();
|
||||
ResponseStatus resetModule();
|
||||
ResponseStatus sendMessage(const void *message, const uint8_t size);
|
||||
ResponseContainer receiveMessageUntil(char delimiter = '\0');
|
||||
ResponseStructContainer receiveMessage(const uint8_t size);
|
||||
ResponseStructContainer receiveMessageRSSI(const uint8_t size);
|
||||
ResponseStructContainer receiveMessageComplete(const uint8_t size, bool enableRSSI);
|
||||
ResponseContainer receiveMessageComplete(bool enableRSSI);
|
||||
ResponseStatus sendMessage(const std::string message);
|
||||
ResponseContainer receiveMessage();
|
||||
ResponseContainer receiveMessageRSSI();
|
||||
ResponseStatus sendFixedMessage(uint8_t ADDH, uint8_t ADDL, uint8_t CHAN, const std::string message);
|
||||
ResponseStatus sendFixedMessage(uint8_t ADDH, uint8_t ADDL, uint8_t CHAN, const void *message, const uint8_t size);
|
||||
ResponseStatus sendBroadcastFixedMessage(uint8_t CHAN, const void *message, const uint8_t size);
|
||||
ResponseStatus sendBroadcastFixedMessage(uint8_t CHAN, const std::string message);
|
||||
ResponseContainer receiveInitialMessage(const uint8_t size);
|
||||
ResponseStatus sendConfigurationMessage(uint8_t ADDH, uint8_t ADDL, uint8_t CHAN, Configuration *configuration,
|
||||
PROGRAM_COMMAND programCommand = WRITE_CFG_PWR_DWN_SAVE);
|
||||
int available();
|
||||
|
||||
private:
|
||||
uart::UARTDevice *serial;
|
||||
GPIOPin *auxPin;
|
||||
GPIOPin *m0Pin;
|
||||
GPIOPin *m1Pin;
|
||||
|
||||
unsigned long halfKeyloqKey = 0x06660708;
|
||||
unsigned long encrypt(unsigned long data);
|
||||
unsigned long decrypt(unsigned long data);
|
||||
|
||||
MODE_TYPE mode = MODE_0_NORMAL;
|
||||
|
||||
void managedDelay(unsigned long timeout);
|
||||
state_naming::Status waitCompleteResponse(unsigned long timeout = 1000, unsigned int waitNoAux = 100);
|
||||
void flush();
|
||||
void cleanUARTBuffer();
|
||||
|
||||
state_naming::Status sendStruct(void *structureManaged, uint16_t size_);
|
||||
state_naming::Status receiveStruct(void *structureManaged, uint16_t size_);
|
||||
bool writeProgramCommand(PROGRAM_COMMAND cmd, REGISTER_ADDRESS addr, PACKET_LENGHT pl);
|
||||
|
||||
state_naming::RESPONSE_STATUS checkUARTConfiguration(MODE_TYPE mode);
|
||||
};
|
||||
} // namespace lora_e220
|
||||
} // namespace esphome
|
|
@ -1,418 +0,0 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
namespace esphome {
|
||||
namespace state_naming {
|
||||
|
||||
#ifdef FREQUENCY_433
|
||||
#define OPERATING_FREQUENCY 410
|
||||
#elif defined(FREQUENCY_400)
|
||||
#define OPERATING_FREQUENCY 410
|
||||
#elif defined(FREQUENCY_230)
|
||||
#define OPERATING_FREQUENCY 220
|
||||
#elif defined(FREQUENCY_868)
|
||||
#define OPERATING_FREQUENCY 850
|
||||
#elif defined(FREQUENCY_900)
|
||||
#define OPERATING_FREQUENCY 850
|
||||
#elif defined(FREQUENCY_915)
|
||||
#define OPERATING_FREQUENCY 900
|
||||
#else
|
||||
#define OPERATING_FREQUENCY 410
|
||||
#endif
|
||||
|
||||
#define BROADCAST_ADDRESS 255
|
||||
|
||||
typedef enum RESPONSE_STATUS {
|
||||
#ifndef ARDUINO_ARCH_STM32
|
||||
SUCCESS = 1,
|
||||
#endif
|
||||
E220_SUCCESS = 1,
|
||||
ERR_E220_UNKNOWN, /* something shouldn't happened */
|
||||
ERR_E220_NOT_SUPPORT,
|
||||
ERR_E220_NOT_IMPLEMENT,
|
||||
ERR_E220_NOT_INITIAL,
|
||||
ERR_E220_INVALID_PARAM,
|
||||
ERR_E220_DATA_SIZE_NOT_MATCH,
|
||||
ERR_E220_BUF_TOO_SMALL,
|
||||
ERR_E220_TIMEOUT,
|
||||
ERR_E220_HARDWARE,
|
||||
ERR_E220_HEAD_NOT_RECOGNIZED,
|
||||
ERR_E220_NO_RESPONSE_FROM_DEVICE,
|
||||
ERR_E220_WRONG_UART_CONFIG,
|
||||
ERR_E220_WRONG_FORMAT,
|
||||
ERR_E220_PACKET_TOO_BIG
|
||||
} Status;
|
||||
|
||||
static std::string getResponseDescriptionByParams(uint8_t status) {
|
||||
switch (status) {
|
||||
case E220_SUCCESS:
|
||||
return "Success";
|
||||
break;
|
||||
case ERR_E220_UNKNOWN:
|
||||
return "Unknown";
|
||||
break;
|
||||
case ERR_E220_NOT_SUPPORT:
|
||||
return "Not support!";
|
||||
break;
|
||||
case ERR_E220_NOT_IMPLEMENT:
|
||||
return "Not implement";
|
||||
break;
|
||||
case ERR_E220_NOT_INITIAL:
|
||||
return "Not initial!";
|
||||
break;
|
||||
case ERR_E220_INVALID_PARAM:
|
||||
return "Invalid param!";
|
||||
break;
|
||||
case ERR_E220_DATA_SIZE_NOT_MATCH:
|
||||
return "Data size not match!";
|
||||
break;
|
||||
case ERR_E220_BUF_TOO_SMALL:
|
||||
return "Buff too small!";
|
||||
break;
|
||||
case ERR_E220_TIMEOUT:
|
||||
return "Timeout!!";
|
||||
break;
|
||||
case ERR_E220_HARDWARE:
|
||||
return "Hardware error!";
|
||||
break;
|
||||
case ERR_E220_HEAD_NOT_RECOGNIZED:
|
||||
return "Save mode returned not recognized!";
|
||||
break;
|
||||
case ERR_E220_NO_RESPONSE_FROM_DEVICE:
|
||||
return "No response from device! (Check wiring)";
|
||||
break;
|
||||
case ERR_E220_WRONG_UART_CONFIG:
|
||||
return "Wrong UART configuration! (BPS must be 9600 for configuration)";
|
||||
break;
|
||||
case ERR_E220_PACKET_TOO_BIG:
|
||||
return "The device support only 200byte of data transmission!";
|
||||
break;
|
||||
default:
|
||||
return "Invalid status!";
|
||||
}
|
||||
}
|
||||
|
||||
enum E220_UART_PARITY { MODE_00_8N1 = 0b00, MODE_01_8O1 = 0b01, MODE_10_8E1 = 0b10, MODE_11_8N1 = 0b11 };
|
||||
|
||||
static std::string getUARTParityDescriptionByParams(uint8_t uartParity) {
|
||||
switch (uartParity) {
|
||||
case MODE_00_8N1:
|
||||
return "8N1 (Default)";
|
||||
break;
|
||||
case MODE_01_8O1:
|
||||
return "8O1";
|
||||
break;
|
||||
case MODE_10_8E1:
|
||||
return "8E1";
|
||||
break;
|
||||
case MODE_11_8N1:
|
||||
return "8N1 (equal to 00";
|
||||
break;
|
||||
default:
|
||||
return "Invalid UART Parity!";
|
||||
}
|
||||
}
|
||||
|
||||
enum UART_BPS_TYPE {
|
||||
UART_BPS_1200 = 0b000,
|
||||
UART_BPS_2400 = 0b001,
|
||||
UART_BPS_4800 = 0b010,
|
||||
UART_BPS_9600 = 0b011,
|
||||
UART_BPS_19200 = 0b100,
|
||||
UART_BPS_38400 = 0b101,
|
||||
UART_BPS_57600 = 0b110,
|
||||
UART_BPS_115200 = 0b111
|
||||
};
|
||||
|
||||
enum UART_BPS_RATE {
|
||||
UART_BPS_RATE_1200 = 1200,
|
||||
UART_BPS_RATE_2400 = 2400,
|
||||
UART_BPS_RATE_4800 = 4800,
|
||||
UART_BPS_RATE_9600 = 9600,
|
||||
UART_BPS_RATE_19200 = 19200,
|
||||
UART_BPS_RATE_38400 = 38400,
|
||||
UART_BPS_RATE_57600 = 57600,
|
||||
UART_BPS_RATE_115200 = 115200
|
||||
};
|
||||
|
||||
static std::string getUARTBaudRateDescriptionByParams(uint8_t uartBaudRate) {
|
||||
switch (uartBaudRate) {
|
||||
case UART_BPS_1200:
|
||||
return "1200bps";
|
||||
break;
|
||||
case UART_BPS_2400:
|
||||
return "2400bps";
|
||||
break;
|
||||
case UART_BPS_4800:
|
||||
return "4800bps";
|
||||
break;
|
||||
case UART_BPS_9600:
|
||||
return "9600bps (default)";
|
||||
break;
|
||||
case UART_BPS_19200:
|
||||
return "19200bps";
|
||||
break;
|
||||
case UART_BPS_38400:
|
||||
return "38400bps";
|
||||
break;
|
||||
case UART_BPS_57600:
|
||||
return "57600bps";
|
||||
break;
|
||||
case UART_BPS_115200:
|
||||
return "115200bps";
|
||||
break;
|
||||
default:
|
||||
return "Invalid UART Baud Rate!";
|
||||
}
|
||||
}
|
||||
|
||||
enum AIR_DATA_RATE {
|
||||
AIR_DATA_RATE_000_24 = 0b000,
|
||||
AIR_DATA_RATE_001_24 = 0b001,
|
||||
AIR_DATA_RATE_010_24 = 0b010,
|
||||
AIR_DATA_RATE_011_48 = 0b011,
|
||||
AIR_DATA_RATE_100_96 = 0b100,
|
||||
AIR_DATA_RATE_101_192 = 0b101,
|
||||
AIR_DATA_RATE_110_384 = 0b110,
|
||||
AIR_DATA_RATE_111_625 = 0b111
|
||||
};
|
||||
|
||||
static std::string getAirDataRateDescriptionByParams(uint8_t airDataRate) {
|
||||
switch (airDataRate) {
|
||||
case AIR_DATA_RATE_000_24:
|
||||
return "2.4kbps";
|
||||
break;
|
||||
case AIR_DATA_RATE_001_24:
|
||||
return "2.4kbps";
|
||||
break;
|
||||
case AIR_DATA_RATE_010_24:
|
||||
return "2.4kbps (default)";
|
||||
break;
|
||||
case AIR_DATA_RATE_011_48:
|
||||
return "4.8kbps";
|
||||
break;
|
||||
case AIR_DATA_RATE_100_96:
|
||||
return "9.6kbps";
|
||||
break;
|
||||
case AIR_DATA_RATE_101_192:
|
||||
return "19.2kbps";
|
||||
break;
|
||||
case AIR_DATA_RATE_110_384:
|
||||
return "38.4kbps";
|
||||
break;
|
||||
case AIR_DATA_RATE_111_625:
|
||||
return "62.5kbps";
|
||||
break;
|
||||
default:
|
||||
return "Invalid Air Data Rate!";
|
||||
}
|
||||
}
|
||||
|
||||
enum SUB_PACKET_SETTING {
|
||||
SPS_200_00 = 0b00,
|
||||
SPS_128_01 = 0b01,
|
||||
SPS_064_10 = 0b10,
|
||||
SPS_032_11 = 0b11
|
||||
|
||||
};
|
||||
static std::string getSubPacketSettingByParams(uint8_t subPacketSetting) {
|
||||
switch (subPacketSetting) {
|
||||
case SPS_200_00:
|
||||
return "200bytes (default)";
|
||||
break;
|
||||
case SPS_128_01:
|
||||
return "128bytes";
|
||||
break;
|
||||
case SPS_064_10:
|
||||
return "64bytes";
|
||||
break;
|
||||
case SPS_032_11:
|
||||
return "32bytes";
|
||||
break;
|
||||
default:
|
||||
return "Invalid Sub Packet Setting!";
|
||||
}
|
||||
}
|
||||
|
||||
enum RSSI_AMBIENT_NOISE_ENABLE { RSSI_AMBIENT_NOISE_ENABLED = 0b1, RSSI_AMBIENT_NOISE_DISABLED = 0b0 };
|
||||
static std::string getRSSIAmbientNoiseEnableByParams(uint8_t rssiAmbientNoiseEnabled) {
|
||||
switch (rssiAmbientNoiseEnabled) {
|
||||
case RSSI_AMBIENT_NOISE_ENABLED:
|
||||
return "Enabled";
|
||||
break;
|
||||
case RSSI_AMBIENT_NOISE_DISABLED:
|
||||
return "Disabled (default)";
|
||||
break;
|
||||
default:
|
||||
return "Invalid RSSI Ambient Noise enabled!";
|
||||
}
|
||||
}
|
||||
|
||||
enum WOR_PERIOD {
|
||||
WOR_500_000 = 0b000,
|
||||
WOR_1000_001 = 0b001,
|
||||
WOR_1500_010 = 0b010,
|
||||
WOR_2000_011 = 0b011,
|
||||
WOR_2500_100 = 0b100,
|
||||
WOR_3000_101 = 0b101,
|
||||
WOR_3500_110 = 0b110,
|
||||
WOR_4000_111 = 0b111
|
||||
|
||||
};
|
||||
static std::string getWORPeriodByParams(uint8_t WORPeriod) {
|
||||
switch (WORPeriod) {
|
||||
case WOR_500_000:
|
||||
return "500ms";
|
||||
break;
|
||||
case WOR_1000_001:
|
||||
return "1000ms";
|
||||
break;
|
||||
case WOR_1500_010:
|
||||
return "1500ms";
|
||||
break;
|
||||
case WOR_2000_011:
|
||||
return "2000ms (default)";
|
||||
break;
|
||||
case WOR_2500_100:
|
||||
return "2500ms";
|
||||
break;
|
||||
case WOR_3000_101:
|
||||
return "3000ms";
|
||||
break;
|
||||
case WOR_3500_110:
|
||||
return "3500ms";
|
||||
break;
|
||||
case WOR_4000_111:
|
||||
return "4000ms";
|
||||
break;
|
||||
default:
|
||||
return "Invalid WOR period!";
|
||||
}
|
||||
}
|
||||
enum LBT_ENABLE_BYTE { LBT_ENABLED = 0b1, LBT_DISABLED = 0b0 };
|
||||
static std::string getLBTEnableByteByParams(uint8_t LBTEnableByte) {
|
||||
switch (LBTEnableByte) {
|
||||
case LBT_ENABLED:
|
||||
return "Enabled";
|
||||
break;
|
||||
case LBT_DISABLED:
|
||||
return "Disabled (default)";
|
||||
break;
|
||||
default:
|
||||
return "Invalid LBT enable byte!";
|
||||
}
|
||||
}
|
||||
|
||||
enum RSSI_ENABLE_BYTE { RSSI_ENABLED = 0b1, RSSI_DISABLED = 0b0 };
|
||||
static std::string getRSSIEnableByteByParams(uint8_t RSSIEnableByte) {
|
||||
switch (RSSIEnableByte) {
|
||||
case RSSI_ENABLED:
|
||||
return "Enabled";
|
||||
break;
|
||||
case RSSI_DISABLED:
|
||||
return "Disabled (default)";
|
||||
break;
|
||||
default:
|
||||
return "Invalid RSSI enable byte!";
|
||||
}
|
||||
}
|
||||
|
||||
enum FIDEX_TRANSMISSION { FT_TRANSPARENT_TRANSMISSION = 0b0, FT_FIXED_TRANSMISSION = 0b1 };
|
||||
|
||||
static std::string getFixedTransmissionDescriptionByParams(uint8_t fixedTransmission) {
|
||||
switch (fixedTransmission) {
|
||||
case FT_TRANSPARENT_TRANSMISSION:
|
||||
return "Transparent transmission (default)";
|
||||
break;
|
||||
case FT_FIXED_TRANSMISSION:
|
||||
return "Fixed transmission (first three bytes can be used as high/low address and channel)";
|
||||
break;
|
||||
default:
|
||||
return "Invalid fixed transmission param!";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef E220_22
|
||||
enum TRANSMISSION_POWER {
|
||||
POWER_22 = 0b00,
|
||||
POWER_17 = 0b01,
|
||||
POWER_13 = 0b10,
|
||||
POWER_10 = 0b11
|
||||
|
||||
};
|
||||
|
||||
static std::string getTransmissionPowerDescriptionByParams(uint8_t transmissionPower) {
|
||||
switch (transmissionPower) {
|
||||
case POWER_22:
|
||||
return "22dBm (Default)";
|
||||
break;
|
||||
case POWER_17:
|
||||
return "17dBm";
|
||||
break;
|
||||
case POWER_13:
|
||||
return "13dBm";
|
||||
break;
|
||||
case POWER_10:
|
||||
return "10dBm";
|
||||
break;
|
||||
default:
|
||||
return "Invalid transmission power param";
|
||||
}
|
||||
}
|
||||
#elif defined(E220_30)
|
||||
enum TRANSMISSION_POWER {
|
||||
POWER_30 = 0b00,
|
||||
POWER_27 = 0b01,
|
||||
POWER_24 = 0b10,
|
||||
POWER_21 = 0b11
|
||||
|
||||
};
|
||||
|
||||
static std::string getTransmissionPowerDescriptionByParams(uint8_t transmissionPower) {
|
||||
switch (transmissionPower) {
|
||||
case POWER_30:
|
||||
return "30dBm (Default)";
|
||||
break;
|
||||
case POWER_27:
|
||||
return "27dBm";
|
||||
break;
|
||||
case POWER_24:
|
||||
return "24dBm";
|
||||
break;
|
||||
case POWER_21:
|
||||
return "21dBm";
|
||||
break;
|
||||
default:
|
||||
return "Invalid transmission power param";
|
||||
}
|
||||
}
|
||||
#else
|
||||
enum TRANSMISSION_POWER {
|
||||
POWER_22 = 0b00,
|
||||
POWER_17 = 0b01,
|
||||
POWER_13 = 0b10,
|
||||
POWER_10 = 0b11
|
||||
|
||||
};
|
||||
|
||||
static std::string getTransmissionPowerDescriptionByParams(uint8_t transmissionPower) {
|
||||
switch (transmissionPower) {
|
||||
case POWER_22:
|
||||
return "22dBm (Default)";
|
||||
break;
|
||||
case POWER_17:
|
||||
return "17dBm";
|
||||
break;
|
||||
case POWER_13:
|
||||
return "13dBm";
|
||||
break;
|
||||
case POWER_10:
|
||||
return "10dBm";
|
||||
break;
|
||||
default:
|
||||
return "Invalid transmission power param";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace state_naming
|
||||
} // namespace esphome
|
Loading…
Reference in a new issue