# AI模式
# 导入ku
from sklearn.preprocessing import LabelEncoder, OrdinalEncoder
# 导入高斯朴素贝叶斯算法相关函数
from sklearn.naive_bayes import GaussianNB
# 导入划分数据集的库
from sklearn.model_selection import train_test_split
# 导入预测模型准确率的库
from sklearn import metrics 
# 导入保存训练模型的库
import joblib
from pinpong.board import Board,Pin,DHT11,NeoPixel
from pinpong.extension.unihiker import * # 导入pinpong.extension.unihiker包中所有模块

import os 

import time
import datetime 

import pandas as pd
import numpy as np
from unihiker import GUI
gui=GUI()  # 实例化GUI类


# 定义原始文件
model_file = 'templates/model.pkl'
csv_file1 = 'templates/AN_original.csv'
csv_file2 = 'templates/AI_dealed.csv'



# 定义全局变量
global nowtime,data_temp,data_humidity,data_light,data_water,state_light
data_temp = 23      # 温度数据
data_humidity = 45  # 湿度数据
data_light = 1023   # 光线数据
data_water = "否"   # 水分数据，表示是否漏水
state_light = "关闭"  # 灯光状态变量,eg:关闭/明亮/暖黄/




# 初始化主控板
Board('UNIHIKER').begin() 
# 创建DHT11实例
dht11 = DHT11(Pin(Pin.P4))
# 创建灯环实例
np23 = NeoPixel(Pin(Pin.P16), 16) # 引脚23，灯数为16
np23.clear() # 清空显示
# 创建模拟环境光实例
light22 =  Pin(Pin.P1, Pin.ANALOG) # 初始化22引脚为模拟输入模式
# 创建雨滴实例
water24 = Pin(Pin.P2, Pin.IN) # 初始化24引脚为数字输入模式



'''定义功能函数--显示不同颜色的灯光'''
def lamp_bright(): # 明亮--白光
    lamp_number = 0
    for index in range(16):
        np23[lamp_number] = (255,255,255)
        lamp_number = (lamp_number + 1)
def lamp_warm():  # 暖黄--黄光亮
    lamp_number = 0
    for index in range(16):
        np23[lamp_number] = (255,255,0)
        # np23[lamp_number] = (255,198,107)
        lamp_number = (lamp_number + 1)
def lamp_close():  # 关闭--黑
    lamp_number = 0
    for index in range(16):
        np23[lamp_number] = (0,0,0)
        lamp_number = (lamp_number + 1) 



'''定义按钮回调函数--数据处理'''
def deal_data():
    global flag_deal 
    flag_deal = 1
'''定义按钮回调函数--训练模型''' 
def train_model():
    global flag_train
    flag_train = 1

# 定义初始处理标志
flag_deal = 0
# 定义初始训练标志
flag_train = 0


# 定义功能函数--数据处理      
def process():
    '''先进行数据清洗（删除空值）'''
    df = pd.read_csv(csv_file1,encoding = 'gb2312')
    df = df.replace(r'^\s*$', np.nan, regex=True)
    df = pd.DataFrame(df)
    df=df.dropna()
    df=df.dropna(axis=0)
    df=df.dropna().reset_index(drop=True) # Reset index after drop
    df.to_csv(csv_file2, index=False)
    '''读取清洗后的文件进行数据处理（删除多余列，编码灯光状态为012）'''
    HAR_df = pd.read_csv(csv_file2,usecols=[2,3,4,5,7])
    
    # 处理灯光状态
    state_light2 = HAR_df.iloc[:][['灯光状态']].values
    ordinalencoder2 = LabelEncoder()
    state_light2 = ordinalencoder2.fit_transform(state_light2.ravel())
    HAR_df['灯光状态'] = state_light2
    # 保存csv文件
    HAR_df.to_csv(csv_file2, index=False)


# 定义功能函数--训练模型
def train(file_train,file_model,data_y):
    # 导入预处理后的数据集
    HAR_df = pd.read_csv(file_train)
    '''训练模型'''
    # 选择温度、湿度、光照作为预测条件
    feature_cols =["时段","温度", "湿度", "光照"]
    # 选择灯光状态作为预测结果
    X = HAR_df[feature_cols].values # X为数据特征
    y = HAR_df[data_y] #y为数据标签
    # 划分训练集、测试集
    X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.3, random_state=1)
    # 新建一个高斯朴素贝叶斯分类器
    gnb = GaussianNB()
    # 开始训练
    gnb.fit(X_train, y_train)
    # 用测试集计算准确率
    y_pred = gnb.predict(X_test) # 预测测试集结果
    accuracy = metrics.accuracy_score(y_test, y_pred)
    print("训练完成,Accuracy:",accuracy) # 通过对比，计算准确率 
    # 保存模型
    joblib.dump(gnb,file_model)   



# 定义实时预测线程
def predict_start1():
    # 导入贝叶斯模型
    GNB_model = joblib.load(model_file) 
    while True:
        global period,data_temp,data_humidity,data_light,state_light
        if period == '0h-1h':
            period = 0
        elif period == '1h-2h':
            period = 1
        elif period == '2h-3h':
            period = 2
        elif period == '3h-4h':
            period = 3
        elif period == '4h-5h':
            period = 4
        elif period == '5h-6h':
            period = 5
        elif period == '6h-7h':
            period = 6
        elif period == '7h-8h':
            period = 7
        elif period == '8h-9h':
            period = 8
        elif period == '9h-10h':
            period = 9
        elif period == '10h-11h':
            period = 10
        elif period == '11h-12h':
            period = 11
        elif period == '12h-13h':
            period = 12
        elif period == '13h-14h':
            period = 13
        elif period == '14h-15h':
            period = 14
        elif period == '15h-16h':
            period = 15
        elif period == '16h-17h':
            period = 16
        elif period == '17h-18h':
            period = 17
        elif period == '18h-19h':
            period = 18
        elif period == '19h-20h':
            period = 19
        elif period == '20h-21h':
            period = 20
        elif period == '21h-22h':
            period = 21
        elif period == '22h-23h':
            period = 22
        elif period == '23h-24h':
            period = 23

        # 使用贝叶斯模型进行预测，特征为（时段 温度 湿度 光照 是否下雨）
        res = GNB_model.predict([[period,data_temp,data_humidity,data_light]])[0]
        print("灯光状态预测结果为：",res) 
        global state_light
        if res == 0:
            state_light = "关闭"
            text_state_light.config(text = state_light)
            lamp_close()
        elif res == 1:
            state_light = "明亮"
            text_state_light.config(text = state_light)
            lamp_bright()
        elif res == 2:
            state_light = "暖黄"
            text_state_light.config(text = state_light)
            lamp_warm()
        time.sleep(1)


# 定义停止预测功能
def predict_stop():
    global state_light
    gui.stop_thread(thread_predict1) 
    state_light = "关闭"
    text_state_light.config(text = state_light)
    lamp_close() # 关灯



# 定义按钮回调函数--实时预测线程的开启关闭
count_button_predict = 0
def predict():
    text_content1.config(text='')
    text_content2.config(text='')
    text_content3.config(text='')
    global count_button_predict,thread_predict1
    if count_button_predict == 0:
        thread_predict1 = gui.start_thread(predict_start1)
        text_result.config(text = 'AI应用已启动...')
        count_button_predict = 1
    elif count_button_predict == 1:
        predict_stop()
        text_result.config(text = 'AI应用已关闭...')
        count_button_predict = 0



'''Unihiker'''
# 显示标题title
title = gui.draw_text(text="智能家居AI模式",x=41,y=5,font_size=16, color="#0000FF")
# 显示温度数据temp
gui.draw_round_rect(x=20,y=40,w=95,h=45,r=5,width=1,color="#0000FF")  # 绘制圆角矩形
gui.draw_image(image="image/温度.png",x=37,y=42,w=20)  # 显示温度icon
gui.draw_text(text="温度",x=60,y=40,font_size=13, color="#FF6600")  # 显示文字“温度”
text_temp = gui.draw_digit(text=data_temp,x=43,y=66,font_size=15, color="#000000")  # 显示温度数据
gui.draw_text(text="℃",x=77,y=62,font_size=12, color="#000000")  # 显示文字“℃”
# 显示湿度数据humidity
gui.draw_round_rect(x=125,y=40,w=95,h=45,r=5,width=1,color="#0000FF")
gui.draw_image(image="image/湿度.png",x=142,y=42,w=20)
gui.draw_text(text="湿度",x=165,y=40,font_size=13, color="#FF6600")
text_humidity = gui.draw_digit(text=data_humidity,x=148,y=66,font_size=15, color="#000000")
gui.draw_text(text="％",x=182,y=62,font_size=12, color="#000000")
# 显示光照数据light
gui.draw_round_rect(x=20,y=95,w=95,h=45,r=5,width=1,color="#0000FF") 
gui.draw_image(image="image/光照.png",x=37,y=97,w=20)  
gui.draw_text(text="光照",x=60,y=95,font_size=13, color="#FF6600")  
text_light = gui.draw_digit(text=data_light,x=43,y=120,font_size=15, color="#000000") 
# 显示是否漏水数据water
gui.draw_round_rect(x=125,y=95,w=95,h=45,r=5,width=1,color="#0000FF")  
gui.draw_image(image="image/漏水.png",x=142,y=97,w=20)  
gui.draw_text(text="漏水",x=165,y=95,font_size=13, color="#FF6600")  
text_water = gui.draw_text(text=data_water,x=162,y=115,font_size=12, color="#000000") 
# 显示灯光状态state_light
gui.draw_round_rect(x=20,y=150,w=200,h=40,r=5,width=1,color="#0000FF") 
gui.draw_image(image="image/灯光.png",x=74,y=152,w=20)  
gui.draw_text(text="灯光状态",x=94,y=150,font_size=12, color="#FF6600")  
text_state_light = gui.draw_digit(text=state_light,x=102,y=172,font_size=11, color="#000000") 
# # 显示风扇状态state_fan
# gui.draw_round_rect(x=125,y=150,w=95,h=40,r=5,width=1,color="#0000FF")  
# gui.draw_image(image="image/风扇.png",x=130,y=152,w=20)  
# gui.draw_text(text="风扇状态",x=148,y=150,font_size=12, color="#FF6600")  
# text_state_fan = gui.draw_digit(text=state_fan,x=157,y=172,font_size=11, color="#000000") 
# 显示AI模式
rect = gui.draw_round_rect(x=20,y=198,w=200,h=100,r=5,width=1,color="#0000FF")  # x=20
button_deal = gui.add_button(x=30, y=203, w=57, h=30, text="处理", onclick=deal_data) # x=30
button_train = gui.add_button(x=92, y=203, w=57, h=30, text="训练", onclick=train_model)# x=92
button_pretict = gui.add_button(x=153, y=203, w=57, h=30, text="应用", onclick=predict)# x=153
text_content1 = gui.draw_digit(text='',x=30,y=238,font_size=11, color="#000000") # 正在导入第  (x=30)
text_content2 = gui.draw_digit(text='',x=110,y=238,font_size=11, color="#000000") 
text_content3 = gui.draw_digit(text='',x=140,y=238,font_size=11, color="#000000") # 行数据......
text_result = gui.draw_digit(text='',x=70,y=268,font_size=11, color="#000000") 



'''传感器检测线程'''
count_button_a = 0 # 记录按键a按压次数
def sensor_main():
    while True:
        try:
            global nowtime,period,data_temp,data_humidity,data_light,data_water,state_light
            nowtime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            nowtime2 = datetime.datetime.now()
            if nowtime2.hour < 1 and nowtime2.hour >=0:
                period = '0h-1h'
            elif nowtime2.hour < 2 and nowtime2.hour >=1:
                period = '1h-2h'
            elif nowtime2.hour < 3 and nowtime2.hour >=2:
                period = '2h-3h'
            elif nowtime2.hour < 4 and nowtime2.hour >=3:
                period = '3h-4h'
            elif nowtime2.hour < 5 and nowtime2.hour >=4:
                period = '4h-5h'
            elif nowtime2.hour < 6 and nowtime2.hour >=5:
                period = '5h-6h'
            elif nowtime2.hour < 7 and nowtime2.hour >=6:
                period = '6h-7h'
            elif nowtime2.hour < 8 and nowtime2.hour >=7:
                period = '7h-8h'
            elif nowtime2.hour < 9 and nowtime2.hour >=8:
                period = '8h-9h'
            elif nowtime2.hour < 10 and nowtime2.hour >=9:
                period = '9h-10h'
            elif nowtime2.hour < 11 and nowtime2.hour >=10:
                period = '10h-11h'
            elif nowtime2.hour < 12 and nowtime2.hour >=11:
                period = '11h-12h'
            elif nowtime2.hour < 13 and nowtime2.hour >=12:
                period = '12h-13h'
            elif nowtime2.hour < 14 and nowtime2.hour >=13:
                period = '13h-14h'
            elif nowtime2.hour < 15 and nowtime2.hour >=14:
                period = '14h-15h'
            elif nowtime2.hour < 16 and nowtime2.hour >=15:
                period = '15h-16h'
            elif nowtime2.hour < 17 and nowtime2.hour >=16:
                period = '16h-17h'
            elif nowtime2.hour < 18 and nowtime2.hour >=17:
                period = '17h-18h'
            elif nowtime2.hour < 19 and nowtime2.hour >=18:
                period = '18h-19h'
            elif nowtime2.hour < 20 and nowtime2.hour >=19:
                period = '19h-20h'
            elif nowtime2.hour < 21 and nowtime2.hour >=20:
                period = '20h-21h'
            elif nowtime2.hour < 22 and nowtime2.hour >=21:
                period = '21h-22h'
            elif nowtime2.hour < 23 and nowtime2.hour >=22:
                period = '22h-23h'
            elif nowtime2.hour < 24 and nowtime2.hour >=23:
                period = '23h-24h'
            data_temp = int(dht11.temp_c()) # 读取摄氏温度
            data_humidity = int(dht11.humidity()) # 读取湿度
            data_light = light22.read_analog() # 读取环境光
            data_water = water24.read_digital()  #读取引脚电平
            if data_water == 0:
                data_water = "否"
                text_water.config(text = "否")
            else:
                data_water = "是"
                text_water.config(text = "是")
        except:
            data_temp = None
            data_humidity = None
            data_light = None
            data_water = None 
        print(data_temp,data_humidity,data_light,data_water,state_light)
        print("-----------")
        text_temp.config(text = data_temp)
        text_humidity.config(text = data_humidity)
        text_light.config(text = data_light)
        time.sleep(1)


thread_sensor = gui.start_thread(sensor_main)  # 启动线程--传感器检测


# 主程序启动
while True:
    '''检查数据处理按钮是否按压'''
    if flag_deal == 1:
        text_content1.config(x=30,text='正在导入第')
        text_content3.config(text='行数据...')
        text_result.config(text = '')
        for i in range(241):
            text_content2.config(text = i)
            time.sleep(0.02)
        process()    # 执行数据处理
        print('数据处理完成!')
        text_result.config(text = '数据处理完成!')
        flag_deal = 0
    '''检查训练模型按钮是否按压'''
    if flag_train == 1:
        text_content1.config(x=75,text='正在训练模型...')
        text_content2.config(text='')
        text_content3.config(text='')
        text_result.config(text = '')
        for i in range(20):
            time.sleep(0.1)    
        train(csv_file2,model_file,'灯光状态') # 执行训练
        text_content1.config(text='')
        print('模型训练完成!')
        text_result.config(text = '模型训练完成!')
        flag_train = 0

    time.sleep(1)