# -*- coding: utf-8 -*-
"""
version 1.0
2025/09/02  magelland 9800i scanner/scale
todo:  
  to exe win
  linux
  to get status?
  setup guide
  improve
done
  work in windows
  check config file
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)

statusZ={'30':'scaleNotReady','31':'NonStableWeight','32':'OverWeight30','33':'stableZero','34':'stableNonZero','35':'weightSent'};

def scaleStatus(ser):
    ser.write(str.encode("i"))  #status
    print((' getting scale status ...'))
    time.sleep(.1)
    x=ser.readline()
    #print(x)
    l=len(x)
    #print("length: "+str(l))
    x=getBarcode(x).encode('UTF-8')
    #print(x)
    #print("returned length: "+str(len(x)))
    yy=x.hex();
    #print(yy)
    v=yy[4:6]
    w=yy[6:8]
    x=yy[8:10]
    y=yy[10:12]
    z=yy[12:14]
    print(' v:'+str(v) +' w:'+str(w) +' x:'+str(x) +' y:'+str(y) +' z:'+str(z) )
    try:
        print(statusZ[z])
    except Exception as e:
        print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+"  statusVWZ key error: "+str(e))
        #flog.writelines(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+' statusVWZ key error: '+str(e)+'\n')

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

preweight=0

def scaleMonitor(ser,preweight=0):
    ser.write(str.encode("\x53\x31\x34\x0d"))  #to get weight
    print(('Command sent ...'))
    time.sleep(.1)
    x=ser.readline()
    print('raw data readline')
    print(x)

    #dual cable W
    #b'\x02000.00\r'
    #b'\x02?A\x02000.00\r'

    #single cable
    #b'S1440128\r'
    #b'S141\rS08A818574027473\r'
    #b'S08A818574027473\rS1440332\r'
    #b'S08A693493010740\rS1440003\r'
    #b'S08A049578993741\rS1440004\r'
    #b'S08E08066145\rS1440002\r'
    #b'S08E07820401\rS1440004\r'
    #b'S1440004\rS08F4710126456921\r'

    x=getBarcode(x).encode('UTF-8')
    l=len(x)
    print(x)
    print(" x length: "+str(l))
    if( l==0 ):
        print(" x len 0 , return")
        return preweight

    yy=x.hex();
    print(yy)
    print('above hex value')

    decoded = x.decode('utf-8')

    #b'S1440128\r' //single cable
    match = re.search(r'S144(\d{4})\r', decoded)

    if match:
        weight = match.group(1)
    else:
        print("No match found.")
        return 0

    print(" raw Weight: "+ weight)
    weight=str(float(weight)/100)

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

    print(" ")
    print("return preweight " + 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)            

    
def getBarcode(data):
    #b'S141\rS08A818574027473\r'
    #b'S08A818574027473\rS1440332\r'

    #print("to match: "+str(data));
#UPCA, UPCE, EAN13, Code128, O2.

    #Code128
    pattern = r'S08B3(\d{3,13})\r'
    barcodes = re.findall(pattern, data.decode('latin1'))
    if(len(barcodes)==0):
        #UPC-A
        pattern = r'S08A(\d{5,13})\r'
        barcodes = re.findall(pattern, data.decode('latin1'))
    if(len(barcodes)==0):
        #UPC-E
        pattern = r'S08E(\d{7,8})\r'
        barcodes = re.findall(pattern, data.decode('latin1'))
    if(len(barcodes)==0):
        #EAN13
        pattern = r'S08F(\d{13})\r'
        barcodes = re.findall(pattern, data.decode('latin1'))

    for barcode in barcodes:
        barcode = re.sub(r'[a-zA-Z]', '', barcode)
        if len(barcode) == 11 and barcode.startswith('2'):
            barcode = barcode + '5'
        print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+" barcode found:", barcode)
        typeStr(barcode)
        time.sleep(0.3)
        
    remaining_string = re.sub(pattern, '', data.decode('latin1'))
    #print("Remaining string:", remaining_string)
    return remaining_string

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

        file_path = 'config.txt'
        if os.path.exists(file_path):
            fconfig = open('config.txt', 'r')
            activePort=fconfig.readline().strip()
            unit=fconfig.readline().strip().lower()
            if(unit==''):
                unit='lb'
            print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+" config unit: " + unit)
            fconfig.close()
            print("File exists.")
        else:
            activePort='COM1'
            unit='lb'


        count=0
        weight=0
        comFail=True
        while(comFail):
            try: 
                ser = serial.Serial(
                  port=activePort,\
                  baudrate=9600,\
                  parity=serial.PARITY_EVEN,\
                  stopbits=serial.STOPBITS_ONE,\
                  bytesize=serial.SEVENBITS,\
                  timeout=0)
                #flog.write('Open port: '+ activePort+' Successful\n')
                print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+' Open port: '+ activePort+' Successful\n')
                comFail=False
                
            except Exception as e:
                print("****************************")
                print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+ " open COM "+activePort+" 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)

        #scaleStatus(ser)

        preweight=0
        while True:
            count=count+1
            preweight=scaleMonitor(ser,preweight)

            time.sleep(0.3)
        break
    except KeyboardInterrupt:
        print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+" User abort. Exiting...")
        ser.close()
        #flog.close()
        time.sleep(.1)
        exit()
    except Exception as e:
        print(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+"  error 3: "+str(e))
        #flog.writelines(str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))+' statusVWZ key error: '+str(e)+'\n')
        time.sleep(3)
      
ser.close()
#flog.close()
exit()
