refact
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
# Добавляем файл генерации рецептов
|
||||
src_files(
|
||||
saeco_series_6000.cpp
|
||||
recipe.cpp
|
||||
crc.cpp
|
||||
)
|
||||
Binary file not shown.
@@ -0,0 +1,43 @@
|
||||
#include "saeco_series_6000.h"
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace saeco_series_6000 {
|
||||
|
||||
uint32_t SaecoSeries6000::calc_crc(const std::vector<uint8_t>& data, size_t start, size_t end) {
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
const uint32_t POLY = 0x04C11DB7;
|
||||
if (start >= end) return 0;
|
||||
// start
|
||||
uint8_t val = data[start];
|
||||
((uint8_t*)(&crc))[3] ^= BitReverse[val];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
if (crc & 0x80000000) {
|
||||
crc = (crc << 1) ^ POLY;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
// остальные байты
|
||||
for (size_t i = start + 1; i < end; i++) {
|
||||
uint8_t v = data[i];
|
||||
((uint8_t*)(&crc))[3] ^= BitReverse[v];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
if (crc & 0x80000000) {
|
||||
crc = (crc << 1) ^ POLY;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t t32 = 0;
|
||||
((uint8_t*)(&t32))[0] = BitReverse[((uint8_t*)(&crc))[3]];
|
||||
((uint8_t*)(&t32))[1] = BitReverse[((uint8_t*)(&crc))[2]];
|
||||
((uint8_t*)(&t32))[2] = BitReverse[((uint8_t*)(&crc))[1]];
|
||||
((uint8_t*)(&t32))[3] = BitReverse[((uint8_t*)(&crc))[0]];
|
||||
crc = t32 ^ 0xFFFFFFFF;
|
||||
return crc;
|
||||
}
|
||||
|
||||
} // namespace saeco_series_6000
|
||||
} // namespace esphome
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "saeco_series_6000.h"
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace saeco_series_6000 {
|
||||
|
||||
std::vector<uint8_t> SaecoSeries6000::build_coffee_recipe(uint8_t type, uint8_t bean, uint8_t cups, uint16_t vol, uint16_t milk) {
|
||||
static const uint8_t CoffeePattern[7][4] = {
|
||||
{0,1,1,2}, // Espresso
|
||||
{1,2,3,2}, // Americano
|
||||
{2,2,1,2}, // Cappuccino
|
||||
{3,2,2,2}, // Latte
|
||||
{4,0,0,1}, // Coffee with milk
|
||||
{5,1,0,1}, // Milk foam
|
||||
{6,0,0,1} // Hot water
|
||||
};
|
||||
uint8_t rec[10] = {0};
|
||||
if (type >= 7) type = 0;
|
||||
rec[0] = CoffeePattern[type][0];
|
||||
if (rec[0] == 5 || rec[0] == 4) {
|
||||
rec[1] = 3; // всегда молотый для молока и milk foam
|
||||
} else {
|
||||
rec[1] = bean;
|
||||
}
|
||||
if (cups > CoffeePattern[type][3]) {
|
||||
rec[2] = CoffeePattern[type][3];
|
||||
} else {
|
||||
rec[2] = cups;
|
||||
}
|
||||
rec[3] = CoffeePattern[type][1];
|
||||
rec[4] = CoffeePattern[type][2];
|
||||
if (rec[0] == 1) { // Americano
|
||||
rec[6] = 40;
|
||||
rec[7] = 0;
|
||||
rec[8] = (uint8_t)vol;
|
||||
rec[9] = vol / 0x100;
|
||||
rec[5] = 0;
|
||||
} else {
|
||||
rec[6] = (uint8_t)vol;
|
||||
rec[7] = vol / 0x100;
|
||||
if (rec[0] == 0 || rec[0] == 1 || rec[0] == 4 || rec[0] == 5) {
|
||||
if (rec[0] == 5) {
|
||||
rec[5] = 2;
|
||||
} else {
|
||||
rec[5] = 0;
|
||||
}
|
||||
rec[8] = 0;
|
||||
rec[9] = 0;
|
||||
} else {
|
||||
rec[5] = 2;
|
||||
rec[8] = (uint8_t)milk;
|
||||
rec[9] = milk / 0x100;
|
||||
}
|
||||
}
|
||||
return std::vector<uint8_t>(rec, rec + 10);
|
||||
}
|
||||
|
||||
} // namespace saeco_series_6000
|
||||
} // namespace esphome
|
||||
@@ -24,6 +24,7 @@ void SaecoSeries6000::loop() {
|
||||
uart_display_->write_byte(byte); // Mirror byte immediately
|
||||
process_mainboard_byte(byte); // Process the "sniffed" byte
|
||||
}
|
||||
|
||||
// Контроль активности UART (выключение через 15 сек)
|
||||
static uint32_t last_check = 0;
|
||||
uint32_t now = millis();
|
||||
@@ -232,41 +233,6 @@ const uint8_t SaecoSeries6000::BitReverse[256] = {
|
||||
0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
|
||||
};
|
||||
|
||||
uint32_t SaecoSeries6000::calc_crc(const std::vector<uint8_t>& data, size_t start, size_t end) {
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
const uint32_t POLY = 0x04C11DB7;
|
||||
if (start >= end) return 0;
|
||||
// start
|
||||
uint8_t val = data[start];
|
||||
((uint8_t*)(&crc))[3] ^= BitReverse[val];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
if (crc & 0x80000000) {
|
||||
crc = (crc << 1) ^ POLY;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
// остальные байты
|
||||
for (size_t i = start + 1; i < end; i++) {
|
||||
uint8_t v = data[i];
|
||||
((uint8_t*)(&crc))[3] ^= BitReverse[v];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
if (crc & 0x80000000) {
|
||||
crc = (crc << 1) ^ POLY;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t t32 = 0;
|
||||
((uint8_t*)(&t32))[0] = BitReverse[((uint8_t*)(&crc))[3]];
|
||||
((uint8_t*)(&t32))[1] = BitReverse[((uint8_t*)(&crc))[2]];
|
||||
((uint8_t*)(&t32))[2] = BitReverse[((uint8_t*)(&crc))[1]];
|
||||
((uint8_t*)(&t32))[3] = BitReverse[((uint8_t*)(&crc))[0]];
|
||||
crc = t32 ^ 0xFFFFFFFF;
|
||||
return crc;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> SaecoSeries6000::parse_hex_string_to_bytes(const std::string& hex_string) {
|
||||
std::vector<uint8_t> pkt;
|
||||
size_t pos = 0;
|
||||
@@ -339,5 +305,26 @@ void SaecoSeries6000::send_packets_to_mainboard(const std::vector<std::vector<ui
|
||||
|
||||
// Реализация SendPacketsAction полностью в header (saeco_series_6000.h)
|
||||
|
||||
void SaecoSeries6000::coffee_build(uint8_t type, uint8_t bean, uint8_t cups, uint16_t vol, uint16_t milk) {
|
||||
// Формируем пакет для отправки (AA AA AA 90 ... CRC CRC CRC CRC 55)
|
||||
std::vector<uint8_t> pkt = {0xAA, 0xAA, 0xAA, 0x90};
|
||||
std::vector<uint8_t> rec = build_coffee_recipe(type, bean, cups, vol, milk);
|
||||
pkt.insert(pkt.end(), rec.begin(), rec.end());
|
||||
// Добавляем 4 байта CRC (заполним позже) и 0x55
|
||||
pkt.resize(pkt.size() + 4 + 1, 0);
|
||||
pkt[pkt.size() - 1] = 0x55;
|
||||
// Пересчёт CRC
|
||||
size_t preamble = 3;
|
||||
size_t crc_start = preamble;
|
||||
size_t crc_end = pkt.size() - 5;
|
||||
uint32_t crc = calc_crc(pkt, crc_start, crc_end);
|
||||
pkt[pkt.size()-2] = (crc >> 24) & 0xFF;
|
||||
pkt[pkt.size()-3] = (crc >> 16) & 0xFF;
|
||||
pkt[pkt.size()-4] = (crc >> 8) & 0xFF;
|
||||
pkt[pkt.size()-5] = crc & 0xFF;
|
||||
// Отправляем пакет
|
||||
send_packets_to_mainboard(std::vector<std::vector<uint8_t>>{pkt});
|
||||
}
|
||||
|
||||
} // namespace saeco_series_6000
|
||||
} // namespace esphome
|
||||
@@ -26,6 +26,28 @@ class SaecoSeries6000 : public Component {
|
||||
void send_packets_to_mainboard(const std::vector<std::string>& hex_packets, uint32_t delay_ms = 10);
|
||||
void send_packets_to_mainboard(const std::string& hex_packet, uint32_t delay_ms = 10);
|
||||
|
||||
// Типы напитков
|
||||
enum CoffeeType {
|
||||
ESPRESSO = 0,
|
||||
AMERICANO = 1,
|
||||
CAPPUCCINO = 2,
|
||||
LATTE = 3,
|
||||
COFFEE_WITH_MILK = 4,
|
||||
MILK_FOAM = 5,
|
||||
HOT_WATER = 6
|
||||
};
|
||||
// Крепость/помол
|
||||
enum CoffeeStrength {
|
||||
MILD = 0,
|
||||
NORMAL = 1,
|
||||
STRONG = 2,
|
||||
GROUND = 3
|
||||
};
|
||||
// Построение и отправка пакета приготовления кофе
|
||||
void coffee_build(uint8_t type, uint8_t bean, uint8_t cups, uint16_t vol, uint16_t milk);
|
||||
// Генерация рецепта (только формирование данных)
|
||||
static std::vector<uint8_t> build_coffee_recipe(uint8_t type, uint8_t bean, uint8_t cups, uint16_t vol, uint16_t milk);
|
||||
|
||||
protected:
|
||||
uart::UARTComponent *uart_display_;
|
||||
uart::UARTComponent *uart_mainboard_;
|
||||
@@ -57,7 +79,8 @@ class SaecoSeries6000 : public Component {
|
||||
void parse_b5_packet(const uint8_t* buffer, uint16_t size);
|
||||
void pub_status(uint8_t status);
|
||||
static const uint8_t BitReverse[256];
|
||||
uint32_t calc_crc(const std::vector<uint8_t>& data, size_t start, size_t end);
|
||||
// CRC-32 для пакетов кофемашины
|
||||
static uint32_t calc_crc(const std::vector<uint8_t>& data, size_t start, size_t end);
|
||||
std::vector<uint8_t> parse_hex_string_to_bytes(const std::string& hex_string);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user