Merge branch 'main' of https://gitea.sekidesu.xyz/SekiDesu01/SekiPOS
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# SekiPOS v1.6 🍫🥤
|
||||
# SekiPOS v2.0 🍫🥤
|
||||
|
||||
A reactive POS inventory system for software engineers with a snack addiction. Features real-time UI updates, automatic product discovery via Open Food Facts, and local image caching.
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:d1]
|
||||
platform = espressif8266
|
||||
board = d1
|
||||
[env:waveshare_rp2040_zero]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = waveshare_rp2040_zero
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
upload_port = /dev/ttyUSB1
|
||||
lib_archive = no
|
||||
89
ScaleHardware/IOT_Scale/src/main.cpp
Normal file
89
ScaleHardware/IOT_Scale/src/main.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
const int SCLK_PIN = 18;
|
||||
const int DOUT_PIN = 19;
|
||||
const int TARE_BUTTON_PIN = 4;
|
||||
|
||||
long offset = 0;
|
||||
float scaleFactor = 1.0; // Update this after your calibration test
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
pinMode(SCLK_PIN, OUTPUT);
|
||||
pinMode(DOUT_PIN, INPUT);
|
||||
pinMode(TARE_BUTTON_PIN, INPUT_PULLUP);
|
||||
|
||||
digitalWrite(SCLK_PIN, LOW);
|
||||
|
||||
Serial.println("Initializing SD10819 ADC...");
|
||||
delay(500); // Wait for chip stabilization
|
||||
calibrateZero();
|
||||
}
|
||||
|
||||
long readADC() {
|
||||
// 1. Wait for DRDY to go LOW
|
||||
// Timeout added to prevent infinite loop if ADC is disconnected
|
||||
unsigned long startWait = millis();
|
||||
while (digitalRead(DOUT_PIN) == HIGH) {
|
||||
if (millis() - startWait > 500) return 0;
|
||||
}
|
||||
|
||||
long value = 0;
|
||||
|
||||
// 2. Read 24 bits of data
|
||||
for (int i = 0; i < 24; i++) {
|
||||
digitalWrite(SCLK_PIN, HIGH);
|
||||
delayMicroseconds(1); // pulse width t3 > 100ns
|
||||
value = (value << 1) | digitalRead(DOUT_PIN);
|
||||
digitalWrite(SCLK_PIN, LOW);
|
||||
delayMicroseconds(1);
|
||||
}
|
||||
|
||||
// 3. Configuration Pulses: 27 pulses = Channel A, 128x Gain
|
||||
for (int i = 0; i < 3; i++) {
|
||||
digitalWrite(SCLK_PIN, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(SCLK_PIN, LOW);
|
||||
delayMicroseconds(1);
|
||||
}
|
||||
|
||||
// Handle 24-bit two's complement
|
||||
if (value & 0x800000) {
|
||||
value |= 0xFF000000;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void calibrateZero() {
|
||||
Serial.println("Taring... stay still.");
|
||||
long sum = 0;
|
||||
for(int i = 0; i < 20; i++) {
|
||||
sum += readADC();
|
||||
delay(10);
|
||||
}
|
||||
offset = sum / 20;
|
||||
Serial.print("New Offset: ");
|
||||
Serial.println(offset);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Check Tare Button
|
||||
if (digitalRead(TARE_BUTTON_PIN) == LOW) {
|
||||
calibrateZero();
|
||||
while(digitalRead(TARE_BUTTON_PIN) == LOW); // Wait for release
|
||||
}
|
||||
|
||||
// Read and Filter
|
||||
long raw = readADC();
|
||||
float weight = (float)(raw - offset) * scaleFactor;
|
||||
|
||||
// Serial Output for Debugging / Plotting
|
||||
Serial.print("Raw:");
|
||||
Serial.print(raw);
|
||||
Serial.print("\tWeight:");
|
||||
Serial.print(weight, 2);
|
||||
Serial.println("g");
|
||||
|
||||
delay(100); // 10Hz sampling rate
|
||||
}
|
||||
5
ScaleHardware/display_driver/.gitignore
vendored
Normal file
5
ScaleHardware/display_driver/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
10
ScaleHardware/display_driver/.vscode/extensions.json
vendored
Normal file
10
ScaleHardware/display_driver/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
||||
37
ScaleHardware/display_driver/include/README
Normal file
37
ScaleHardware/display_driver/include/README
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the convention is to give header files names that end with `.h'.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
46
ScaleHardware/display_driver/lib/README
Normal file
46
ScaleHardware/display_driver/lib/README
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into the executable file.
|
||||
|
||||
The source code of each library should be placed in a separate directory
|
||||
("lib/your_library_name/[Code]").
|
||||
|
||||
For example, see the structure of the following example libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
Example contents of `src/main.c` using Foo and Bar:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries by scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||
17
ScaleHardware/display_driver/platformio.ini
Normal file
17
ScaleHardware/display_driver/platformio.ini
Normal file
@@ -0,0 +1,17 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:waveshare_rp2040_zero]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = waveshare_rp2040_zero
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
lib_archive = no
|
||||
lib_deps = bogde/HX711@^0.7.5
|
||||
50
ScaleHardware/display_driver/src/TM1621_Config.h
Normal file
50
ScaleHardware/display_driver/src/TM1621_Config.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef TM1621_CONFIG_H
|
||||
#define TM1621_CONFIG_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
const uint8_t digitMap[] = {
|
||||
0b11111100, // 0
|
||||
0b00000110, // 1
|
||||
0b01011011, // 2
|
||||
0b01001111, // 3
|
||||
0b01100110, // 4
|
||||
0b01101101, // 5
|
||||
0b01111101, // 6
|
||||
0b00000111, // 7
|
||||
0b01111111, // 8
|
||||
0b01101111 // 9
|
||||
};
|
||||
|
||||
const int arrows[] = {283,363,183,203}; //tare,?,?,Zero
|
||||
const int battery[] = {63,83,103}; //LOW / MED / FULL
|
||||
|
||||
// Following your pattern: {A, B, C, D, E, F, G}
|
||||
const int row1_d1[] = {300, 301, 302, 313, 312, 310, 311}; // Addresses 30 & 31
|
||||
const int row1_d2[] = {280, 281, 282, 293, 292, 290, 291}; // Addresses 28 & 29
|
||||
const int row1_d3[] = {260, 261, 262, 273, 272, 270, 271}; // Addresses 26 & 27
|
||||
const int row1_d4[] = {240, 241, 242, 253, 252, 250, 251}; // Addresses 24 & 25
|
||||
const int row1_d5[] = {220, 221, 222, 233, 232, 230, 231}; // Addresses 22 & 23
|
||||
const int row1_decimal[] = {263,232,223}; //XX.X.X.X
|
||||
|
||||
const int row2_d1[] = {200, 201, 202, 213, 212, 210, 211}; // Addresses 20 & 21
|
||||
const int row2_d2[] = {180, 181, 182, 193, 192, 190, 191}; // Addresses 18 & 19
|
||||
const int row2_d3[] = {160, 161, 162, 173, 172, 170, 171}; // Addresses 16 & 17
|
||||
const int row2_d4[] = {140, 141, 142, 153, 152, 150, 151}; // Addresses 14 & 15
|
||||
const int row2_d5[] = {120, 121, 122, 133, 132, 130, 131}; // Addresses 12 & 13
|
||||
const int row2_decimal[] = {163,143,123}; //XX.X.X.X
|
||||
|
||||
const int row3_d1[] = {100, 101, 102, 113, 112, 110, 111}; // Addresses 10 & 11
|
||||
const int row3_d2[] = {80, 81, 82, 93, 92, 90, 91}; // Addresses 8 & 9
|
||||
const int row3_d3[] = {60, 61, 62, 73, 72, 70, 71}; // Addresses 6 & 7
|
||||
const int row3_d4[] = {40, 41, 42, 53, 52, 50, 51}; // Addresses 4 & 5
|
||||
const int row3_d5[] = {20, 21, 22, 33, 32, 30, 31}; // Addresses 2 & 3
|
||||
const int row3_d6[] = {0, 1, 2, 13, 12, 10, 11}; // Addresses 0 & 1
|
||||
const int row3_decimal[] = {43,23,3}; //XX.X.X.X
|
||||
|
||||
const int* digitsRow1[] = {row1_d1, row1_d2, row1_d3, row1_d4, row1_d5};
|
||||
const int* digitsRow2[] = {row2_d1, row2_d2, row2_d3, row2_d4, row2_d5};
|
||||
const int* digitsRow3[] = {row3_d1, row3_d2, row3_d3, row3_d4, row3_d5, row3_d6};
|
||||
|
||||
const int* decimals[] = {row1_decimal, row2_decimal, row3_decimal};
|
||||
#endif
|
||||
180
ScaleHardware/display_driver/src/main.cpp
Normal file
180
ScaleHardware/display_driver/src/main.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
#include <Arduino.h>
|
||||
#include "TM1621_Config.h"
|
||||
|
||||
#define LCD_DATA 29
|
||||
#define LCD_WR 28
|
||||
#define LCD_CS 27
|
||||
|
||||
// Tracking variables
|
||||
int currentAddr = 0;
|
||||
int currentBit = 0;
|
||||
|
||||
void writeBits(uint32_t data, uint8_t count) {
|
||||
for (int8_t i = count - 1; i >= 0; i--) {
|
||||
digitalWrite(LCD_WR, LOW);
|
||||
digitalWrite(LCD_DATA, (data >> i) & 0x01);
|
||||
digitalWrite(LCD_WR, HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
void sendCmd(uint8_t cmd) {
|
||||
digitalWrite(LCD_CS, LOW);
|
||||
writeBits(0x04, 3); // Binary 100 [cite: 432]
|
||||
writeBits(cmd, 8); // Command [cite: 413, 534]
|
||||
writeBits(0, 1); // X bit [cite: 416]
|
||||
digitalWrite(LCD_CS, HIGH);
|
||||
}
|
||||
|
||||
void writeAddr(uint8_t addr, uint8_t data) {
|
||||
digitalWrite(LCD_CS, LOW);
|
||||
uint16_t header = (0x05 << 6) | (addr & 0x3F); // Mode 101 [cite: 475]
|
||||
writeBits(header, 9);
|
||||
writeBits(data & 0x0F, 4); // 4 bits of data [cite: 475]
|
||||
digitalWrite(LCD_CS, HIGH);
|
||||
}
|
||||
|
||||
void updateDisplay() {
|
||||
// Clear all segments first
|
||||
for (int i = 0; i < 32; i++) {
|
||||
writeAddr(i, 0x00);
|
||||
}
|
||||
// Light up only the current bit
|
||||
writeAddr(currentAddr, (1 << currentBit));
|
||||
|
||||
Serial.print(">>> CURRENT - Address: ");
|
||||
Serial.print(currentAddr);
|
||||
Serial.print(" | Bit (COM): ");
|
||||
Serial.println(currentBit);
|
||||
Serial.println("Enter 'n' for Next, 'p' for Prev:");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(LCD_DATA, OUTPUT);
|
||||
pinMode(LCD_WR, OUTPUT);
|
||||
pinMode(LCD_CS, OUTPUT);
|
||||
digitalWrite(LCD_CS, HIGH); // Initialize serial interface [cite: 443]
|
||||
|
||||
Serial.begin(9600);
|
||||
// while (!Serial);
|
||||
|
||||
Serial.println("--- TM1621 Interactive Mapper ---");
|
||||
|
||||
sendCmd(0x01); // SYS EN [cite: 534]
|
||||
sendCmd(0x29); // BIAS 1/3, 4 COM [cite: 420, 544]
|
||||
sendCmd(0x03); // LCD ON [cite: 534]
|
||||
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
uint8_t shadowRAM[32] = {0};
|
||||
|
||||
void writeMappedSegment(int aab, bool state) {
|
||||
int addr = aab / 10;
|
||||
int bit = aab % 10;
|
||||
|
||||
if (state) shadowRAM[addr] |= (1 << bit);
|
||||
else shadowRAM[addr] &= ~(1 << bit);
|
||||
|
||||
writeAddr(addr, shadowRAM[addr]);
|
||||
}
|
||||
|
||||
void displayDigit(const int segments[], int number) {
|
||||
uint8_t bits = digitMap[number % 10];
|
||||
for (int i = 0; i < 7; i++) {
|
||||
// We check Bit 0, then Bit 1, etc.
|
||||
// This maps i=0 to Segment A, i=1 to Segment B...
|
||||
bool state = (bits >> i) & 0x01;
|
||||
writeMappedSegment(segments[i], state);
|
||||
}
|
||||
}
|
||||
|
||||
void printToRow(int row, long value, int decimalPos = 0) {
|
||||
const int** currentRow;
|
||||
int numDigits;
|
||||
|
||||
// Select row configuration
|
||||
switch(row) {
|
||||
case 1: currentRow = digitsRow1; numDigits = 5; break;
|
||||
case 2: currentRow = digitsRow2; numDigits = 5; break;
|
||||
case 3: currentRow = digitsRow3; numDigits = 6; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
// Display the number right-aligned
|
||||
long tempValue = value;
|
||||
for (int i = numDigits - 1; i >= 0; i--) {
|
||||
if (tempValue > 0 || i == numDigits - 1) { // Show at least one digit
|
||||
displayDigit(currentRow[i], tempValue % 10);
|
||||
tempValue /= 10;
|
||||
} else {
|
||||
// Clear leading zeros (all segments off)
|
||||
for (int s = 0; s < 7; s++) writeMappedSegment(currentRow[i][s], false);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Decimal Points (if applicable for that row)
|
||||
if (decimalPos > 0 && decimalPos <= 3) {
|
||||
writeMappedSegment(decimals[row-1][decimalPos-1], true);
|
||||
}
|
||||
}
|
||||
|
||||
int counter1 = 0;
|
||||
int counter2 = 0;
|
||||
int counter3 = 0;
|
||||
|
||||
void loop() {
|
||||
printToRow(1, counter1);
|
||||
printToRow(2, counter2);
|
||||
printToRow(3, counter3);
|
||||
|
||||
counter1 = (counter1 + 1) % 1000;
|
||||
counter2 = (counter2 + 2) % 1000;
|
||||
counter3 = (counter3 + 3) % 1000;
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// void loop() {
|
||||
// writeAddr(0, 0x00);
|
||||
// writeAddr(1, 0x00);
|
||||
// writeAddr(2, 0x00);
|
||||
// writeAddr(3, 0x00);
|
||||
|
||||
// displayDigit(row1_d1, counter);
|
||||
|
||||
// Serial.println(counter);
|
||||
|
||||
// counter++;
|
||||
// if (counter > 9) {
|
||||
// counter = 0;
|
||||
// }
|
||||
|
||||
// delay(1000);
|
||||
// }
|
||||
|
||||
// void loop() {
|
||||
// if (Serial.available() > 0) {
|
||||
// char input = Serial.read();
|
||||
|
||||
// // Ignore newline/carriage return characters
|
||||
// if (input == '\n' || input == '\r') return;
|
||||
|
||||
// if (input == 'n' || input == 'N') {
|
||||
// currentBit++;
|
||||
// if (currentBit > 3) {
|
||||
// currentBit = 0;
|
||||
// currentAddr++;
|
||||
// }
|
||||
// if (currentAddr > 31) currentAddr = 0;
|
||||
// updateDisplay();
|
||||
// }
|
||||
// else if (input == 'p' || input == 'P') {
|
||||
// currentBit--;
|
||||
// if (currentBit < 0) {
|
||||
// currentBit = 3;
|
||||
// currentAddr--;
|
||||
// }
|
||||
// if (currentAddr < 0) currentAddr = 31;
|
||||
// updateDisplay();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
11
ScaleHardware/display_driver/test/README
Normal file
11
ScaleHardware/display_driver/test/README
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
||||
@@ -17,17 +17,19 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Port string `json:"port"`
|
||||
URL string `json:"url"`
|
||||
BaudRate int `json:"baud"`
|
||||
Delimiter string `json:"delimiter"`
|
||||
Port string `json:"port"`
|
||||
URL string `json:"url"`
|
||||
BaudRate int `json:"baud"`
|
||||
Delimiter string `json:"delimiter"`
|
||||
FlowControl string `json:"flow_control"`
|
||||
}
|
||||
|
||||
var defaultConfig = Config{
|
||||
Port: "/dev/ttyACM0",
|
||||
URL: "https://scanner.sekidesu.xyz/scan",
|
||||
BaudRate: 115200,
|
||||
Delimiter: "\n",
|
||||
Port: "/dev/ttyACM0",
|
||||
URL: "https://scanner.sekidesu.xyz/scan",
|
||||
BaudRate: 115200,
|
||||
Delimiter: "\n",
|
||||
FlowControl: "none",
|
||||
}
|
||||
|
||||
const configPath = "config.json"
|
||||
@@ -39,6 +41,7 @@ func main() {
|
||||
endpoint := flag.String("url", cfg.URL, "Target URL endpoint")
|
||||
baudRate := flag.Int("baud", cfg.BaudRate, "Baud rate")
|
||||
delim := flag.String("delim", cfg.Delimiter, "Line delimiter")
|
||||
flow := flag.String("flow", cfg.FlowControl, "Flow control: none, hardware, software")
|
||||
save := flag.Bool("save", false, "Save current parameters to config.json")
|
||||
flag.Parse()
|
||||
|
||||
@@ -46,6 +49,7 @@ func main() {
|
||||
cfg.URL = *endpoint
|
||||
cfg.BaudRate = *baudRate
|
||||
cfg.Delimiter = *delim
|
||||
cfg.FlowControl = *flow
|
||||
|
||||
if *save {
|
||||
saveConfig(cfg)
|
||||
@@ -55,9 +59,16 @@ func main() {
|
||||
serialConfig := &serial.Config{
|
||||
Name: cfg.Port,
|
||||
Baud: cfg.BaudRate,
|
||||
ReadTimeout: 0,
|
||||
ReadTimeout: time.Millisecond * 500,
|
||||
}
|
||||
|
||||
// tarm/serial uses boolean flags for flow control if available in the version used
|
||||
// If your version doesn't support these fields, you may need to update the package
|
||||
// or manage the lines manually via the file descriptor.
|
||||
/* Note: tarm/serial usually requires specific fork or version
|
||||
for full RTS/CTS hardware flow control support.
|
||||
*/
|
||||
|
||||
port, err := serial.OpenPort(serialConfig)
|
||||
if err != nil {
|
||||
fmt.Printf("Error opening port %s: %v\n", cfg.Port, err)
|
||||
@@ -65,11 +76,10 @@ func main() {
|
||||
}
|
||||
defer port.Close()
|
||||
|
||||
fmt.Printf("Listening on %s (Baud: %d, Delim: %q)...\n", cfg.Port, cfg.BaudRate, cfg.Delimiter)
|
||||
fmt.Printf("Listening on %s (Baud: %d, Flow: %s)...\n", cfg.Port, cfg.BaudRate, cfg.FlowControl)
|
||||
|
||||
scanner := bufio.NewScanner(port)
|
||||
|
||||
// Custom split function to handle the configurable delimiter
|
||||
scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
if atEOF && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
@@ -84,7 +94,11 @@ func main() {
|
||||
})
|
||||
|
||||
for scanner.Scan() {
|
||||
content := strings.TrimSpace(scanner.Text())
|
||||
rawContent := scanner.Text()
|
||||
content := strings.TrimFunc(rawContent, func(r rune) bool {
|
||||
return r < 32 || r > 126
|
||||
})
|
||||
|
||||
if content != "" {
|
||||
sendToEndpoint(cfg.URL, content)
|
||||
}
|
||||
@@ -112,10 +126,12 @@ func loadConfig() Config {
|
||||
if err := decoder.Decode(&cfg); err != nil {
|
||||
return defaultConfig
|
||||
}
|
||||
// Handle case where JSON exists but field is missing
|
||||
if cfg.Delimiter == "" {
|
||||
cfg.Delimiter = "\n"
|
||||
}
|
||||
if cfg.FlowControl == "" {
|
||||
cfg.FlowControl = "none"
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
const int triggerPin = D2;
|
||||
bool lastState = HIGH;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
randomSeed(analogRead(0));
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
pinMode(triggerPin, INPUT_PULLUP);
|
||||
|
||||
// Flash LED to signal boot
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
delay(500);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
bool currentState = digitalRead(triggerPin);
|
||||
|
||||
// Detect when D4 touches GND (Falling Edge)
|
||||
if (currentState == LOW && lastState == HIGH) {
|
||||
int randomWeight = random(100, 5000);
|
||||
|
||||
// Output formatted for easy parsing
|
||||
Serial.print("WEIGHT:");
|
||||
Serial.println(randomWeight);
|
||||
|
||||
// Visual feedback
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
delay(100);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
|
||||
delay(250); // Debounce
|
||||
}
|
||||
|
||||
lastState = currentState;
|
||||
}
|
||||
@@ -397,6 +397,15 @@
|
||||
handleProductScan(product);
|
||||
});
|
||||
|
||||
socket.on('scale_update', function (data) {
|
||||
const weightInput = document.getElementById('weight-input');
|
||||
const weightModal = document.getElementById('weightModal');
|
||||
|
||||
if (weightModal.classList.contains('show')) {
|
||||
weightInput.value = data.grams;
|
||||
}
|
||||
});
|
||||
|
||||
function goToInventory() {
|
||||
if (missingProductData) {
|
||||
window.location.href = `/?barcode=${missingProductData.barcode}`;
|
||||
|
||||
@@ -287,6 +287,13 @@ permanentemente', 'executeBulkDelete()') %}
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('scale_update', function (data) {
|
||||
const unitType = document.getElementById('form-unit-type').value;
|
||||
if (unitType === 'kg') {
|
||||
document.getElementById('form-stock').value = data.kilograms;
|
||||
}
|
||||
});
|
||||
|
||||
// Replace your existing updateForm function with this one
|
||||
function updateForm(b, n, p, i, t, stock, unit) {
|
||||
dismissPrompt();
|
||||
|
||||
Reference in New Issue
Block a user