import sdtcloudpubsub
import time
import uuid
from pymodbus.client import ModbusSerialClient as ModbusClient
import os, json
from collections import Counter

sdtcloud = sdtcloudpubsub.sdtcloudpubsub()
sdtcloud.setClient(f"device-app-{uuid.uuid1()}") # parameter is client ID(string)

def get_point_temperature(serial_obj):
    global t_col
    # CWT-TM-320s
    res_dict = {}
    points = []
    ch_list = [f'ch_{num}' for num in range(1, 13)]
    
    with open('config.json', 'r') as f:
        info = json.load(f)
    
    t_col = []
    for key, value in info['temperature_point'].items():
        if value[0] == 'y':
            t_col.append(value[1])
            points.append(ch_list.index(key) + 1)
            res_dict[value[1]] = 999.99
    
    try:
        res = serial_obj.read_holding_registers(address=32, count=32, slave=2)
        
        for i, j in zip(res_dict.keys(), points):
            res_dict[i] = res.registers[j - 1] * 0.1
    except Exception as e:
        print(f'error: {e}')
        pass
        
    return res_dict

def get_keyence_devices(serial_obj):
    global g_zero_point, k_col
    # CWT-MB307D
    res_dict = {
		"oilInFlowRate": 999.99,
		"oilInTemperature": 999.99,
		"oilOutFlowRate": 999.99,
		"oilOutTemperature": 999.99,

		"waterInFlowRate": 999.99,
		"waterInTemperature": 999.99,
		"waterOutFlowRate": 999.99,
		"waterOutTemperature": 999.99
    }
    
    points = [1, 2, 3, 4, 5, 6, 7, 8]
    
    try:
        res = serial_obj.read_holding_registers(address=50, count=8, slave=5)
        
        for i, j in enumerate(k_col):
            if i % 2 == 0:
                res_dict[j] = ((res.registers[i] - g_zero_point[i // 2]) / 16000) * 300
            else:
                res_dict[j] = ((res.registers[i] - 4000) / 16000) * 100
    except Exception as e:
        pass
        
    return res_dict

def init_zero_detection(serial_obj, config_dict):
    global g_zero_point, k_col
    
    if config_dict['set_zero_temperature'] == 'y':
        try:
            res = serial_obj.read_holding_registers(address=50, count=8, slave=5)

            for i, j in enumerate(k_col):
                if not i % 2:
                    config_dict['ref_zero_point'][j] = res.registers[i]
            
            config_dict['set_zero_temperature'] = 'n'
            
            with open('./config.json', 'w') as f:
                json.dump(config_dict, f, indent=4)
        except:
            return False
    
    for idx, val in enumerate(k_col):
        if not idx % 2:
            g_zero_point[idx // 2] = config_dict['ref_zero_point'][val]
    
    return True

def init_data_dict():
    global k_col, t_col
    # col = ["topLeftTemperature", "topRightTemperature", "bottomLeftTemperature", "bottomRightTemperature",
    #         "oilInFlowRate", "oilInTemperature", "oilOutFlowRate", "oilOutTemperature",
    #         "waterInFlowRate", "waterInTemperature", "waterOutFlowRate", "waterOutTemperature"]
    col = k_col + t_col
    
    return {key: 0.0 for key in col}

def runAction():
    sum_data = init_data_dict()
    # sum_data = {}
    cnt, cnt_limit = 0, 0
    
    while True:
        with open('./config.json', 'r') as config:
            config_data = json.load(config)

        interval = int(config_data['get_data_interval'])
        
        if interval <= 5:
            cnt_limit = 1
        elif interval <= 1800:
            cnt_limit = 10
        else:
            cnt_limit = 100
            
        init_zero_detection(client1, config_data)
        
        start = int(time.time() * 1000)
        pub_data = {
            **get_point_temperature(client1), **get_keyence_devices(client1)
        }
                
        for key, value in pub_data.items():
            try:
                sum_data[key] += value
            except:
                sum_data[key] = value
        
        end = int(time.time() * 1000)
        diff = end - start
        sleep_time = int(interval / cnt_limit) - (diff * 0.001)
        cnt += 1
        if cnt == cnt_limit:
            snd_data = {key: value / cnt_limit for key, value in sum_data.items()}
            sdtcloud.pubMessage(snd_data)
            cnt = 0
            sum_data = init_data_dict()
            
        time.sleep(sleep_time)

if __name__ == "__main__":
    password = 'Sdt2513!@'
    os.system(f'echo "{password}" | sudo chmod 777 /dev/ttyS0')
    port_name = '/dev/ttyS0'
    client1 = ModbusClient(port=port_name, baudrate=19200, parity='N', stopbits=1, bytesize=8, timeout=0.25)
    
    client1.connect()
    
    g_zero_point = [0] * 4
    k_col = ["oilInFlowRate","oilInTemperature","oilOutFlowRate","oilOutTemperature",
            "waterInFlowRate","waterInTemperature","waterOutFlowRate","waterOutTemperature"]
    t_col = []

    runAction()