本帖最后由 vany5921 于 2020-6-8 11:53 编辑
这个项目旨在创建一个小工具,读取我想添加到我的购物清单中的产品条码
这个小工具是用M5StickC+一个带串行端口条形码阅读器+一个带3D打印机的盒子来集成它们的。我是利用了Bring!与树莓派的HomeAssistant进行通讯,条码通过MQTT发送到MQTT服务器,通过HomeAssistant中运行的python脚本进行接收,此程序在excel工作表中查找条形码,您可以在其中找到所有产品的列表。一旦产品被识别,它就被送到了Bring!应用程序通过一个非官方的API和MQTT返回产品名并显示在条形码阅读器屏幕上。
Vcc <------> 3V3,GND <------> GND,TX <------> G36,Trigger <-------> G26 这个盒子是用Tinkercad设计的,是测试版。目前它不是理想的盒子,但测试它就足够了。底座包含一个带有磁铁的连接器,因此您可以快速连接和断开充电器。 M5StickC程序: 按下A按钮后,扫码器的捕获触发引脚激活,并等待通过串行端口接收数据的最长时间为10秒。当通过串行端口接收到信息时,条形码被发送到MQTT服务器,如果从MQTT服务器接收到产品名,它将显示在屏幕上。连接充电器时,检查输入电压,显示器将关闭,以免损坏显示器。 [mw_shl_code=arduino,true]//
// Lector codigo barras para M5Stack Stick-C
//
// Mayo-2020
//
// daekka LNX
#include <M5StickC.h>
#include <WiFi.h>
#include <ubSubClient.h>
//WiFi credentials
char* ssid = "xxxxxx";
char* password = "xxxxxx";
const char* mqtt_server = "192.168.1.200";
const char* mqttUser = "xxxxxx";
const char* mqttPassword = "xxxxxx";
WiFiClient espClient;
PubSubClient client(espClient);
// LED
#define ledPin 10
// Pin trigger lector
#define triggerPin 26
bool usb_power = false;
unsigned long previus_millis_captura = millis();
const int timeThreshold_captura = 10000;
String codigo_leido="";
// the setup routine runs once when M5StickC starts up
void setup() {
// initialize the M5StickC object
M5.begin();
// Trigger del lector
pinMode (triggerPin, OUTPUT);
digitalWrite (triggerPin, HIGH);
// LED
pinMode (ledPin, OUTPUT);
digitalWrite (ledPin, HIGH); // turn off the LED
// Puerto serie
Serial2.begin(9600,SERIAL_8N1,36,0);
// Activa el wifi y MQTT
activa_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
// Ajusto el brillo
//M5.Lcd.setBrightness(80);
// Rota la pantalla
M5.Lcd.setRotation(3);
M5.Axp.ScreenBreath(10);
// Lcd display
M5.Lcd.fillScreen(WHITE);
delay(500);
M5.Lcd.fillScreen(RED);
delay(500);
M5.Lcd.fillScreen(GREEN);
delay(500);
M5.Lcd.fillScreen(BLUE);
delay(500);
M5.Lcd.fillScreen(BLACK);
delay(500);
if (M5.Axp.GetVBusVoltage() > 4) {
usb_power = false;
}
else {
usb_power = true;
}
}
void activa_wifi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void callback(char* topic, byte* message, unsigned int length) {
String messageTemp;
if (String(topic) == "lector_codigo_barras/in") {
for (int i = 0; i < length; i++) {
messageTemp += (char)message;
}
for (int i = 0; i < 10; i++) {
messageTemp += " ";
}
display_producto (messageTemp);
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
// Attempt to connect
if (client.connect("M5stickC-Codigo_barras")) {
// Subscribe
client.subscribe("lector_codigo_barras/in");
} else {
delay(1000);
}
}
}
void display_titulo (String titulo) {
M5.Lcd.setTextColor(WHITE,BLACK);
M5.Lcd.drawString(titulo + " ", 11, 8, 1);
}
void display_producto (String producto){
M5.Lcd.setTextColor(GREEN,BLACK);
M5.Lcd.drawString(producto + " ", 10, 30, 4);
}
void display_codigo_barras (String codigo) {
M5.Lcd.setTextColor(RED,BLACK);
M5.Lcd.drawString(codigo + " ", 10, 60, 2);
}
void enciende_pantalla (){
M5.Lcd.writecommand(ST7735_DISPON);
M5.Axp.ScreenBreath(10);
M5.Lcd.fillScreen(BLACK);
display_titulo ("LECTOR CODIGO BARRAS");
display_producto ("roducto.....");
display_codigo_barras ("Esperando.....");
}
void apaga_pantalla (){
M5.Lcd.writecommand(ST7735_DISPOFF);
M5.Axp.ScreenBreath(0);
}
void comprobacion_usb_conectado() {
// Apaga la pantalla
if ((M5.Axp.GetVBusVoltage() > 4) && (usb_power == false) ){
usb_power = true;
apaga_pantalla();
}
if ((M5.Axp.GetVBusVoltage() <= 4) && (usb_power == true) ){
usb_power = false;
enciende_pantalla();
}
}
void captura_codigo () {
digitalWrite (ledPin, LOW); // turn on the LED
digitalWrite (triggerPin, LOW); // Activa lector
previus_millis_captura = millis();
while (Serial2.available() == 0 && (millis()-previus_millis_captura<timeThreshold_captura)) {
delay (10);
}
if (millis()-previus_millis_captura<timeThreshold_captura) {
M5.Lcd.fillScreen(GREEN);
delay (100);
codigo_leido = Serial2.readString();
M5.Lcd.fillScreen(BLACK);
M5.Axp.ScreenBreath(10);
display_titulo ("LECTOR CODIGO BARRAS");
int str_len = codigo_leido.length()-1;
char char_array[str_len];
codigo_leido.toCharArray(char_array, str_len);
client.publish("lector_codigo_barras/out", char_array);
display_codigo_barras (codigo_leido);
}
else {
display_codigo_barras ("TIME OUT.....");
}
digitalWrite (triggerPin, HIGH); // Apaga lector
digitalWrite (ledPin, HIGH); // turn on the LED
}
// the loop routine runs over and over again forever
void loop(){
if (!client.connected()) {
reconnect();
}
client.loop();
// Comprueba si esta el USB cargador conectado y apaga o enciende la pantalla
comprobacion_usb_conectado();
// Actualiza estado botones
M5.update();
if (M5.BtnA.wasPressed()) {
captura_codigo();
}
}[/mw_shl_code]
HomeAssistant设置要实现的集成:
- MQTT传感器:从扫码器接收条形码
- Shell命令:执行Python代码
- Automation:在MQTT传感器接收到数据后启动Python代码。
[mw_shl_code=python,true]############################################################
#
# Home Assistant - Lector codigo de barras
#
############################################################
sensor:
- platform: mqtt
name: lector_codigo_barras
state_topic: "lector_codigo_barras/out"
expire_after: 2
shell_command:
insert_producto_lector_codigo_barras: '/usr/bin/python /home/homeassistant/.homeassistant/python/bring/insert_producto_lector_codigo_barras.py "{{ producto }}"'
automation:
- alias: recibido_codigo_barras
initial_state: true
trigger:
- platform: state
entity_id: sensor.lector_codigo_barras
action:
- service: shell_command.insert_producto_lector_codigo_barras
data_template:
producto: '{{ states.sensor.lector_codigo_barras.state }}'[/mw_shl_code]
python脚本
python代码要实现的工作
- 搜索接收到的条码(系统参数[1] )在存储产品的excel表中
- 通过MQTT发送产品的名称
- 将产品添加到Bring!使用非官方BringApi库的应用程序
[mw_shl_code=python,true]#!/usr/bin/env python
# coding: utf8
# Find barcodes from excel sheet
# daekka LNX
import requests
import json
import sys
import os
import xlrd
from collections import OrderedDict
import bringapi
import time
# Open the workbook and select the worksheet (first=0)
path_excel_productos = '/home/homeassistant/.homeassistant/python/bring'
file_name_excel_productos = 'barcode_productos.xlsx'
wb = xlrd.open_workbook(os.path.join(path_excel_productos, file_name_excel_productos))
sh = wb.sheet_by_index(0)
#Iterate through each row in worksheet and fetch values into dict
for rownum in range(1, sh.nrows):
row_values = sh.row_values(rownum)
if row_values[3] == sys.argv[1]:
producto = OrderedDict()
producto['id_aleman'] = row_values[0]
producto['id_traduccion'] = row_values[1]
#producto['id_categoria'] = row_values[2]
#producto['id_codigo'] = row_values[3]
#MQTT
os.system ('mosquitto_pub -h 192.168.1.200 -m "' + producto['id_traduccion'] +'" -t lector_codigo_barras/in')
#BRING!
bring = bringapi.BringApi("user","password",True)
bring.purchase_item(producto['id_aleman'],"")
#Finaliza buble
break
[/mw_shl_code]
excel工作表有4列:
应用程序中产品的原始名称。这是要在API BRING中使用的名称,这样就不会创建新产品。如果你用的名字不在BRING!中将创建产品,您必须修改应用程序中的类别和图标。
翻译成我的想显示的名称。这是我在M5Stick屏幕中显示的名称。
产品所属的类别(未使用)
在扫描条形码时当同一产品有多个品牌时,必须用同一行复制数据。
|