Skip to content

Instantly share code, notes, and snippets.

@seanedwards
Last active October 20, 2021 03:06
Show Gist options
  • Select an option

  • Save seanedwards/5136554508bea240cc460d3fc8763bdb to your computer and use it in GitHub Desktop.

Select an option

Save seanedwards/5136554508bea240cc460d3fc8763bdb to your computer and use it in GitHub Desktop.
UART Barcode Scanner Component for ESPHome
#include <esphome.h>
#include <sstream>
class BarcodeReader : public Component, public UARTDevice, public CustomAPIDevice {
public:
BarcodeReader(UARTComponent *port) : UARTDevice(port) {}
std::stringstream buffer;
unsigned long millisendstr=0;
void setup() override {
millisendstr=millis();
}
void loop() override {
if (serialScanerEvent()) {
std::string buf = buffer.str();
// 0x02 indicates a return code from something we wrote to the scanner.
// We skip those ones.
if (buf[0] != 0x02) {
fire_homeassistant_event("esphome.barcode", {{"barcode", buffer.str()}});
ESP_LOGD("barcode", "barcode: %s", buffer.str().c_str());
} else {
ESP_LOGD("barcode", "Command returned success.");
}
buffer.str("");
}
}
bool serialScanerEvent() {
//
if (available()>0) {
// get the new byte:
buffer.put((char)read());
// add it to the inputString:
millisendstr=millis();
}
return millis()-millisendstr>200 && buffer.tellp() > 0;
}
static std::vector<uint8_t> set_scanning(bool scanning) {
return write(0x0002, {(uint8_t)scanning});
}
static std::vector<uint8_t> write(uint16_t address, const std::vector<uint8_t>& data) {
uint8_t* address_bytes = (uint8_t*)&address;
ESP_LOGD("barcode", "Writing: 0x%02X%02X (%d bytes)", address_bytes[1], address_bytes[0], data.size());
std::vector<uint8_t> ret;
// Head1
ret.push_back(0x7E);
ret.push_back(0x00);
// Types
ret.push_back(0x08);
// Lens
ret.push_back((uint8_t)data.size());
// Address
ret.push_back(address_bytes[1]);
ret.push_back(address_bytes[0]);
// Data
ret.insert(ret.end(), data.begin(), data.end());
// CRC
uint16_t crc = (uint16_t)crc_cal_by_bit(ret.data()+2, ret.size()-2);
uint8_t* crc_bytes = (uint8_t*)&crc;
ret.push_back(crc_bytes[1]);
ret.push_back(crc_bytes[0]);
return ret;
}
static unsigned int crc_cal_by_bit (unsigned char * ptr, unsigned char len)
{
unsigned int crc = 0;
while (len-- != 0) {
for (unsigned char i = 0x80; i != 0; i /= 2) {
crc *= 2;
if ((crc & 0x10000) != 0)//After the previous CRC is multiplied by 2, if the first bit is 1, divide by 0x11021
crc ^= 0x11021;
if ((*ptr & i) != 0)//If the bit is 1, then CRC = CRC of the previous bit + bit/CRC_CCITT
crc ^= 0x1021;
}
ptr++;
}
return crc;
}
};
<<: !include include/root.yaml
esphome:
name: scanner-001
platform: esp32
board: nodemcu-32s
includes:
- components/barcode.h
on_boot:
priority: -200
then:
# Bit 7:
# 0: No LED, 1: LED on successful decode
# Bit 6:
# 0: Silence, 1: Beeps
# Bit 5-4:
# 00: No target, 01: Standard, 10/11: Keep
# Bit 3-2:
# 00: No lighting, 01: Standard, 10/11: Keep
# Bit 1-0:
# 00: Manual mode
# 01: Command mode
# 10: Continuous mode
# 11: Sensing mode
- uart.write: !lambda # 87654321
return BarcodeReader::write(0x0000, {0B01010111});
# Save settings to flash
- uart.write: [0x7E, 0x00, 0x09, 0x01, 0x00, 0x00, 0xDE, 0xC8]
logger:
level: VERY_VERBOSE
uart:
id: uart_bus
tx_pin: GPIO25
rx_pin: GPIO26
baud_rate: 9600
parity: ODD
custom_component:
- id: reader
lambda: |-
auto scanner = new BarcodeReader(id(uart_bus));
return {scanner};
binary_sensor:
- platform: gpio
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: True
name: "EN button"
on_press:
- logger.log: 'Hello World'
- script.execute: scan
#- uart.write: !lambda
# return BarcodeReader::write(0x0000, {0B01010101});
#- uart.write: [0x7E, 0x00, 0x09, 0x01, 0x00, 0x00, 0xDE, 0xC8]
internal: true
script:
- id: scan
mode: single
then:
- uart.write: !lambda
return BarcodeReader::set_scanning(true);
- delay: 5s
- uart.write: !lambda
return BarcodeReader::set_scanning(false);
status_led:
pin: GPIO16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment