# smart home
from pinpong.extension.unihiker import * # 导入pinpong.extension.unihiker包中所有模块
from pinpong.board import Board,Pin,DHT11,NeoPixel,Tone
import cv2
import time
import datetime 
import requests  # 导入requests库
from unihiker import GUI
import socket
import numpy
import sys 


gui=GUI()  # 实例化GUI类


# 定义服务器IP,输入服务器IP替换下面的xxx.xxx.xxx.xxx
http_host1 = 'http://xxx.xxx.xxx.xxx:8089/input1'
http_host2 = 'http://xxx.xxx.xxx.xxx:8089/lamp_on'
http_host3 = 'http://xxx.xxx.xxx.xxx:8089/lamp_off'
http_host4 = 'http://xxx.xxx.xxx.xxx:8089/fan_on'
http_host5 = 'http://xxx.xxx.xxx.xxx:8089/fan_off'
http_host6 = 'http://xxx.xxx.xxx.xxx:8089/mode_manual'
http_host7 = 'http://xxx.xxx.xxx.xxx:8089/mode_auto'
http_host8 = 'http://xxx.xxx.xxx.xxx:8089/state_lamp'
http_host9 = 'http://xxx.xxx.xxx.xxx:8089/state_fan'
http_host10 = 'http://xxx.xxx.xxx.xxx:8089/fan_on_2'
http_host11 = 'http://xxx.xxx.xxx.xxx:8089/fan_off_2'



# 定义全局变量
global nowtime,data_temp,data_humidity,data_light,data_water,state_lamp,state_fan,state_carema
data_temp = 30       # 温度数据
data_humidity = 50   # 湿度数据
data_light = 1023    # 光线数据
data_water = "否"    # 水分数据，表示是否漏水
state_lamp = "关闭"  # 灯光状态变量eg:关闭/明亮/暖黄/
state_fan = '关闭'   # 风扇状态变量 eg:关闭/打开
state_carema = 0 # 摄像头状态
is_auto_mode = 0 # 定义一个标志位--自动模式,1为开,0为关



'''初始化硬件'''
# 初始化主控板
Board('UNIHIKER').begin() 
# 创建DHT11实例
dht11 = DHT11(Pin(Pin.P4)) # P4
# 创建模拟环境光实例
light_1 =  Pin(Pin.P1, Pin.ANALOG) # 初始化P1引脚为模拟输入模式
# 创建继电器实例
relay_10 = Pin(Pin.P10, Pin.OUT)  # 初始化P10引脚为数字输出模式
relay_10.write_digital(0) # 控制继电器引脚为高电平，关闭继电器  1灭0亮 亮则启动
# 创建雨滴实例
water_2 = Pin(Pin.P2, Pin.IN) # 初始化P2引脚为数字输入模式
# 创建灯环实例
np_16 = NeoPixel(Pin(Pin.P16), 16) # 引脚16，灯数为16
np_16.clear() # 清空显示
# 创建蜂鸣器实例
tone = Tone(Pin(Pin.P26)) # 将Pin传入Tone中实现模拟输出
tone.freq(200) # 按照设置的频率200播放



'''定义功能函数'''
# 显示不同颜色的灯光
def lamp_bright(): # 明亮--白光
    lamp_number = 0
    for index in range(16):
        np_16[lamp_number] = (255,255,255)
        lamp_number = (lamp_number + 1)
    text_state_lamp.config(text='明亮')
def lamp_warm():  # 暖黄--黄光亮
    lamp_number = 0
    for index in range(16):
        np_16[lamp_number] = (255,255,0)
        lamp_number = (lamp_number + 1)
    text_state_lamp.config(text='暖黄')
def lamp_close():  # 关闭--黑
    lamp_number = 0
    for index in range(16):
        np_16[lamp_number] = (0,0,0)
        lamp_number = (lamp_number + 1) 
    text_state_lamp.config(text='关闭')
# 蜂鸣器发声
def buzzer():
    for i in range(3):
        tone.on()  # 打开蜂鸣器
        time.sleep(0.5) # 延时1.5秒
        tone.off() # 关闭蜂鸣器
        time.sleep(0.5) # 延时1.5秒
# 风扇开关
def fan_on():
    relay_10.write_digital(1) # 控制继电器引脚为高电平，关闭继电器  1灭0亮 
    text_state_fan.config(text='开启')
def fan_off():
    relay_10.write_digital(0) # 控制继电器引脚为高电平，关闭继电器  1灭0亮 
    text_state_fan.config(text='关闭')



'''初始化屏幕'''
# 显示标题title
title = gui.draw_text(text="智能家居",x=78,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_lamp
gui.draw_round_rect(x=20,y=150,w=95,h=40,r=5,width=1,color="#0000FF") 
gui.draw_image(image="image/灯光.png",x=24,y=152,w=20)  
gui.draw_text(text="灯光状态",x=44,y=150,font_size=12, color="#FF6600")  
text_state_lamp = gui.draw_text(text=state_lamp,x=52,y=170,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_text(text=state_fan,x=157,y=170,font_size=11, color="#000000") 
# 显示当前模式
rect = gui.draw_round_rect(x=20,y=198,w=200,h=53,r=5,width=1,color="#0000FF")  # x=20
text_now_mode = gui.draw_text(text="当前模式",x=88,y=197,font_size=12, color="#FF6600") 
text_result = gui.draw_text(text='手动模式',x=90,y=230,font_size=11, color="#000000") 


# 定义自动模式功能
def mode_auto():
    # 漏水则蜂鸣器发声警报
    if data_water == "是":  
        buzzer()

    # 白天关灯，黄昏开明亮灯，夜晚则暖黄灯
    if data_light > 3000: # 白天
        lamp_close()
        '''发送灯光状态'''
        state_lamp_lamp = {"灯光状态":'关闭'}
        response_8 = requests.post(http_host8,state_lamp_lamp,1000) 
    elif data_light > 1200 and data_light <= 3000: # 黄昏
        lamp_bright()
        '''发送灯光状态'''
        state_lamp_lamp = {"灯光状态":'明亮'}
        response_8 = requests.post(http_host8,state_lamp_lamp,1000) 
    else: # 夜晚
        lamp_warm()
        '''发送灯光状态'''
        state_lamp_lamp = {"灯光状态":'暖黄'}
        response_8 = requests.post(http_host8,state_lamp_lamp,1000) 

    # 温度或者湿度过大则打开风扇
    if data_temp > 20 or data_humidity > 80:  
        fan_on() 
        '''发送风扇状态'''
        state_fan_fan = {"风扇状态":'开启'}
        response_9 = requests.post(http_host9,state_fan_fan,1000) 
    else:
        fan_off() 
        '''发送风扇状态'''
        state_fan_fan = {"风扇状态":'关闭'}
        response_9 = requests.post(http_host9,state_fan_fan,1000) 


# 定义传感器检测功能            
def sensor_main():
    while True:
        try:
            global nowtime,period,data_temp,data_humidity,data_light,data_water,state_lamp,state_fan
            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 = light_1.read_analog()  # 读取环境光
            data_water = water_2.read_digital()  # 读取引脚电平
            if data_water == 0:
                data_water = "否"
            else:
                data_water = "是"

        except:
            data_temp = 30
            data_humidity = 50
            data_light = 1023
            data_water = "否"

        # write_to_sql() # 插入数据库
        print(period,data_temp,data_humidity,data_light,data_water)
        print("-----------")
        text_temp.config(text = data_temp)
        text_humidity.config(text = data_humidity)
        text_light.config(text = data_light)
        text_water.config(text = data_water)

        # 发送数据：时间、时段、温度、湿度、光线、是否漏水
        try:
            data_jiaju = {"时间":nowtime,"时段":period,"温度":data_temp,"湿度":data_humidity,"光线":data_light,"漏水":data_water}
            response_1 = requests.post(http_host1,data_jiaju,1000)  
        except:
            print(Exception)

        # 判断是否进入自动模式
        if is_auto_mode == 1 : # 如果要进入自动模式
            mode_auto()  # 调用自动函数
        else:
            pass
        time.sleep(1)
thread_sensor = gui.start_thread(sensor_main)  # 启动线程--传感器检测


'''使用opencv打开摄像头'''
# 建立图像读取对象
print("init camera")
capture = cv2.VideoCapture(0)
# 调节摄像头尺寸
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
# 设置图像缓存区大小
capture.set(cv2.CAP_PROP_BUFFERSIZE, 1)
# 建立sock连接
# address要连接的服务器IP地址和端口号
address = ('xxx.xxx.xxx.xxx', 8088)  # 输入服务器IP替换xxx.xxx.xxx.xxx
try:
    # 建立socket对象
    # socket.AF_INET：服务器之间网络通信 
    # socket.SOCK_STREAM：流式socket , for TCP
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 设置给定套接字选项的值''''''
    #开启连接
    sock.connect(address)
except socket.error as msg:
    print(msg)
    sys.exit(1)


def SendVideo():
    while capture.isOpened():   #摄像头打开执行下面的程序
        cv2.waitKey(10)   # 延迟10毫秒
        # 读取一帧图像，读取成功:ret=1 frame=读取到的一帧图像；读取失败:ret=0
        # global capture
        ret, frame = capture.read()
        frame = cv2.flip(frame,0)
        # 压缩参数，后面cv2.imencode将会用到，对于jpeg来说，15代表图像质量，越高代表图像质量越好为 0-100，默认95
        encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),15]
        # 停止0.1S 防止发送过快服务的处理不过来，如果服务端的处理很多，那么应该加大这个值
        # time.sleep(0.01)
        # cv2.imencode将图片格式转换(编码)成流数据，赋值到内存缓存中;主要用于图像数据格式的压缩，方便网络传输
        # '.jpg'表示将图片按照jpg格式编码。
        result, imgencode = cv2.imencode('.jpg', frame, encode_param)
        # 建立矩阵
        data = numpy.array(imgencode)
        # 将numpy矩阵转换成字符形式，以便在网络中传输
        stringData = data.tostring()
        # 先发送要发送的数据的长度
        # ljust() 方法返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串


        sock.send(str.encode(str(len(stringData)).ljust(16)))
        # 发送数据
        sock.send(stringData)

        # 读取服务器返回值
        receive = sock.recv(1024)
        if len(receive):
            print(str(receive,encoding='utf-8'))
        # # 读取下一帧图片
        # ret, frame = capture.read()
        if cv2.waitKey(10) == 27:
            break
    sock.close()
thread_SendVideo = gui.start_thread(SendVideo)  # 启动线程--传感器检测


while True:
    '''接收远程端控制指令'''
    try:
        # 打开灯光：明亮、暖黄
        response_2=requests.get(url=http_host2)  # 接收服务器控制指令
        if response_2.text == 'bright':  # 如果指令是“bright”
            lamp_bright()
        elif response_2.text == 'warm': # 如果指令是“warm”
            lamp_warm()
        # 关闭灯光
        response_3=requests.get(url=http_host3)  # 接收服务器控制指令
        if response_3.text == 'close': # 如果指令是“close”
            lamp_close()    
        # 打开风扇
        response_4=requests.get(url=http_host4)  # 接收服务器控制指令
        if response_4.text == 'on': # 如果指令是“on”
            fan_on() 
        # 关闭风扇
        response_5=requests.get(url=http_host5)  # 接收服务器控制指令
        if response_5.text == 'off': # 如果指令是“off”
            fan_off() 
            
        # 手动模式
        response_6=requests.get(url=http_host6)  # 接收服务器控制指令
        if response_6.text == 'manual':  # 如果指令是“manual”
            text_result.config(text = '手动模式')
            is_auto_mode = 0
            print("手动模式已开启")
            lamp_close()
            fan_off()
        # 自动模式
        response_7=requests.get(url=http_host7)  # 接收服务器控制指令
        if response_7.text == 'auto': # 如果指令是“auto”
            text_result.config(text = '自动模式')
            is_auto_mode = 1
            print("自动模式已开启")


    except:
        print(Exception)
    time.sleep(1)
