# -*- coding: utf-8 -*-
"""
version 1.0
2025/11/24 zebra scanner scale MP7001
com1: weight 9600 7 even
com3: barcode 9600 8N1

todo:  
  to exe win
  linux
  to get status?
  setup guide
  improve
  check config file
done
  work in windows

no
  lb kg oz
@author: KL
"""
import serial
import time
import re
import os
from datetime import datetime
from pynput.keyboard import Key, Controller
keyboard = Controller()

print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+' Program starting .........')

time.sleep(2)

def restart():
    import sys
    print(" program restarting in 2 sec ... ")
    time.sleep(2)
    os.execv(sys.executable, ['python'] + sys.argv)

def getBarcode(ser2):
    time.sleep(.1)
    x=str(ser2.readline().decode())
    #print('barcode raw data readline')
    print(x)
    if len(x)>0:
        typeStr(x)
    time.sleep(0.3)
    #time.sleep(2)


def getWeight(ser,preweight=0):
    ser.write(str.encode("W"))  #to get weight
    #print(('Command sent ...'))
    time.sleep(.1)
    x=ser.readline()
    print('raw data readline:'+str(x))

    #b'\x02?d\r'
    #b'\x02000.57\r'
    #b'\x02001.84\r'
    #b'\x02014.99\r'
    x=x[1:-1].decode(errors="ignore")
    try:
        weight=str(float(x));
        #print('after process:')
        #print(weight)
    except Exception as e:
        print(str("  error : "+str(e)))
        print('invalid or 0')
        return preweight

    print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+" WEIGHT: "+weight)
    if(weight!=preweight):
        typeStr(weight)
        preweight=weight

    print(" ")
    print("return weight " + preweight)
    return preweight


def typeStr(result):
    #print("to delete first "  )
    for i in range(20):
        keyboard.press(Key.backspace)
        keyboard.release(Key.backspace)
    print("to type: " + result)
    keyboard.type(result)            
    time.sleep(.3)

    
preweight=0
while True:
    try:
        #flog = open('log.txt', 'a')
        #flog.write(str((datetime.now())) +' Program started .........\n')

        # Default settings
        scale_port = 'COM1'
        scanner_port = 'COM3'
        unit = 'lb'

        # Load config if exists
        file_path = 'config.txt'
        if os.path.exists(file_path):
            with open(file_path, 'r') as fconfig:
                for line in fconfig:
                    if '=' in line:
                        key, value = line.strip().split('=', 1)
                        key = key.strip().lower()
                        value = value.strip()
                        if key == 'scale_port':
                            scale_port = value
                        elif key == 'scanner_port':
                            scanner_port = value
                        elif key == 'unit':
                            unit = value.lower()
            print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+" Config loaded from file.")
        else:
            print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+" Config file not found, using defaults.")

        print(f"  scale_port={scale_port}, scanner_port={scanner_port}, unit={unit}")

        count=0
        weight=0
        #for scale
        comFail=True
        while(comFail):
            try:
                ser = serial.Serial(
                  port=scale_port,\
                  baudrate=9600,\
                  parity=serial.PARITY_EVEN,\
                  stopbits=serial.STOPBITS_ONE,\
                  bytesize=serial.SEVENBITS,\
                  timeout=0)
                print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+' Open port for SCALE: '+ scale_port+' Successful\n')
                comFail=False
                
            except Exception as e:
                #could be permission denied, still connected, how to check?
                print("****************************")
                print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+ " open COM for SCALE "+scale_port+" error occured: "+str(e))
                print(" will try again in 10 seconds **************************** ")
                time.sleep(3)
                #flog.write(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+ " error occured: "+str(e)+'\n')
                #flog.write('Open port: '+ activePort+ ' FAILED. \n')
                comFail=True
                pattern= "could not open port"
                if(re.search(pattern,str(e))):
                    print(pattern)
                    restart()
                time.sleep(10)

        #for scanner
        comFail=True
        while(comFail):
            try:
                ser2 = serial.Serial(
                  port=scanner_port,\
                  baudrate=9600,\
                  parity=serial.PARITY_NONE,\
                  stopbits=serial.STOPBITS_ONE,\
                  bytesize=serial.EIGHTBITS,\
                  timeout=0)
                print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+' Open port for SCANNER: '+ scanner_port+' Successful\n')
                comFail=False
                
            except Exception as e:
                #could be permission denied, still connected, how to check?
                print("****************************")
                print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+ " open COM for SCANNER "+scanner_port+" error occured: "+str(e))
                print(" will try again in 10 seconds **************************** ")
                time.sleep(3)
                #flog.write(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+ " error occured: "+str(e)+'\n')
                #flog.write('Open port: '+ activePort+ ' FAILED. \n')
                comFail=True
                pattern= "could not open port"
                if(re.search(pattern,str(e))):
                    print(pattern)
                    restart()
                time.sleep(10)

        preweight=0
        while True:
            count=count+1
            preweight=getWeight(ser,preweight)
            getBarcode(ser2)
            time.sleep(0.2)
    except KeyboardInterrupt:
        print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+" User abort. Exiting...")
        if 'ser' in locals():
            ser.close()
        if 'ser2' in locals():
            ser2.close()
        print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+" Ports closed.")
        break
    except Exception as e:
        print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+"  error 3: "+str(e))
        if 'ser' in locals():
            ser.close()
        if 'ser2' in locals():
            ser2.close()
        time.sleep(3)
