Pending barcodes (Networked)

Collects barcodes with the reliability of v2.2.0 and syncs them via a local server.

作者
Hamad AlShegifi
日安装量
0
总安装量
1
评分
0 0 0
版本
3.5.1
创建于
2025-10-02
更新于
2025-10-16
大小
19.0 KB
许可证
暂无
适用于

import json
import socket
import threading
import time
from flask import Flask, request, jsonify
from flask_cors import CORS
import os

# --- Configuration ---
BARCODES_FILE = 'barcodes.json'
SERVER_PORT = 5678 # Port for the web server (for Tampermonkey)
BROADCAST_PORT = 5679 # Port for network discovery and sync
BROADCAST_INTERVAL = 20 # Seconds between sync broadcasts

# --- Flask Web Server Setup ---
app = Flask(__name__)
CORS(app) # Allow requests from the Tampermonkey script

# --- Barcode Data Management ---
data_lock = threading.Lock()

def load_barcodes():
"""Safely loads barcodes from the JSON file."""
with data_lock:
if not os.path.exists(BARCODES_FILE):
return []
try:
with open(BARCODES_FILE, 'r') as f:
return json.load(f)
except (json.JSONDecodeError, IOError):
return []

def save_barcodes(barcodes):
"""Safely saves barcodes to the JSON file."""
with data_lock:
# Sort by count to maintain some order
barcodes.sort(key=lambda x: x.get('count', 0))
with open(BARCODES_FILE, 'w') as f:
json.dump(barcodes, f, indent=4)

def merge_barcodes(local_list, received_list):
"""Merges two lists of barcodes, avoiding duplicates based on the 'barcode' value."""
merged_dict = {item['barcode']: item for item in local_list}
changed = False
for item in received_list:
if item['barcode'] not in merged_dict:
merged_dict[item['barcode']] = item
changed = True
else:
if item.get('found', False) and not merged_dict[item['barcode']].get('found', False):
merged_dict[item['barcode']]['found'] = True
changed = True

if not changed:
return local_list # Return original list if no changes

final_list = list(merged_dict.values())
for i, item in enumerate(final_list):
item['count'] = i + 1
return final_list


# --- API Endpoints for Tampermonkey ---

@app.route('/get_barcodes', methods=['GET'])
def get_barcodes():
"""Endpoint for the script to fetch the current list of barcodes."""
return jsonify(load_barcodes())

# *** NEW, SAFER ENDPOINT FOR ADDING BARCODES ***
@app.route('/add_barcode', methods=['POST'])
def add_barcode():
"""Endpoint for the script to send a single new barcode."""
new_entry = request.json
if not new_entry or 'barcode' not in new_entry:
return jsonify({"status": "error", "message": "Invalid data format."}), 400

barcodes = load_barcodes()

# Check for duplicates
if any(b['barcode'] == new_entry['barcode'] for b in barcodes):
return jsonify({"status": "success", "message": "Barcode already exists."}), 200

# Add the new entry and re-assign counts
barcodes.append(new_entry)
for i, item in enumerate(barcodes):
item['count'] = i + 1

save_barcodes(barcodes)
print(f"[{time.ctime()}] Added new barcode: {new_entry['barcode']}")
return jsonify({"status": "success", "message": "Barcode added."}), 201

@app.route('/update_barcodes', methods=['POST'])
def update_barcodes():
"""Endpoint for the script to send a full list of barcodes (e.g., after deleting)."""
new_barcodes = request.json
if isinstance(new_barcodes, list):
save_barcodes(new_barcodes)
return jsonify({"status": "success", "message": "Barcode list updated."}), 200
return jsonify({"status": "error", "message": "Invalid data format."}), 400


# --- Network Syncing Logic (UDP Broadcast) ---

def broadcast_sync():
"""Periodically sends the entire local barcode list to the network."""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
while True:
time.sleep(BROADCAST_INTERVAL)
barcodes = load_barcodes()
if barcodes:
message = json.dumps(barcodes).encode('utf-8')
try:
sock.sendto(message, ('', BROADCAST_PORT))
# print(f"[{time.ctime()}] Sent sync broadcast with {len(barcodes)} items.")
except Exception as e:
print(f"Error sending broadcast: {e}")

def listen_for_sync():
"""Listens for barcode lists from other computers and merges them."""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', BROADCAST_PORT))
print(f"Listening for sync data on UDP port {BROADCAST_PORT}")
my_ip = socket.gethostbyname(socket.gethostname())

while True:
try:
data, addr = sock.recvfrom(65507)
if addr[0] != my_ip:
received_barcodes = json.loads(data.decode('utf-8'))
local_barcodes = load_barcodes()
merged_list = merge_barcodes(local_barcodes, received_barcodes)

if merged_list is not local_barcodes:
save_barcodes(merged_list)
print(f"[{time.ctime()}] Received and merged {len(received_barcodes)} barcodes from {addr[0]}. New total: {len(merged_list)}.")
except Exception as e:
print(f"Error receiving sync data: {e}")


if __name__ == '__main__':
print("--- Barcode Sync Server ---")
if not os.path.exists(BARCODES_FILE):
save_barcodes([])
print(f"Created empty barcodes file at: {os.path.abspath(BARCODES_FILE)}")

listener_thread = threading.Thread(target=listen_for_sync, daemon=True)
listener_thread.start()
broadcaster_thread = threading.Thread(target=broadcast_sync, daemon=True)
broadcaster_thread.start()

print(f"Starting web server for Tampermonkey on http://localhost:{SERVER_PORT}")
app.run(host='0.0.0.0', port=SERVER_PORT)

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址