#-*-coding:utf-8-*-
# pip install paho-mqtt
# 导入 paho-mqtt 的 Client：
import paho.mqtt.client as mqtt
import time
unacked_sub = [] #未获得服务器响应的订阅消息 id 列表

# 0：DO 继电器输出接口
# 1：DI 开关量输入接口
# 2：AI 模拟量输入接口
# 3：VO 语音输出接口
# 4：PC电脑开关机接口
ExecType = 3
# 用于响应服务器端 CONNACK 的 callback，如果连接正常建立，rc 值为 0
def on_connect(client, userdata, flags, rc):
    if(rc==0):
        print("Connection Successful!Code:"+str(rc))
    else:
        print("Connection Failure!Code:"+str(rc))


# 用于响应服务器端 PUBLISH 消息的 callback，打印消息主题和内容
def on_message(client, userdata, msg):
    print("Received message, topic:" + msg.topic + "payload:" + str(msg.payload))

# 在连接断开时的 callback，打印 result code
def on_disconnect(client, userdata, rc):
    print("Disconnection returned result:"+ str(rc))

# 在订阅获得服务器响应后，从为响应列表中删除该消息 id
def on_subscribe(client, userdata, mid, granted_qos):
    unacked_sub.remove(mid)


# 构造一个 Client 实例
client = mqtt.Client()
client.on_connect = on_connect
client.on_disconnect= on_disconnect
client.on_message = on_message
client.on_subscribe = on_subscribe

# 连接 broker
# connect() 函数是阻塞的，在连接成功或失败后返回。如果想使用异步非阻塞方式，可以使用 connect_async() 函数。
client.connect("192.168.10.173", 1883, 60)

client.loop_start()

# 订阅单个主题
result, mid = client.subscribe("/user/update", 0)
unacked_sub.append(mid)
# 订阅多个主题
# result, mid = client.subscribe([("temperature", 0), ("humidity", 0)])
# unacked_sub.append(mid)

while len(unacked_sub) != 0:
    time.sleep(1)

if(ExecType == 0):
    print(u"DO 继电器输出接口测试：")

    # 控制 DO 继电器输出接口 OUT1 吸合
    msg = "AT+STACH1=1\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 时间单位改成秒 0：秒 1：100毫秒
    msg = "AT+DLYUNIT=0\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 控制 DO 继电器输出接口 OUT1 点动开，开启后延时5秒后关闭
    msg = "AT+STACH1=3,5,100000,1000000\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 控制 DO 继电器输出接口 OUT1~OUT4 间隔 1 秒轮流吸合
    msg = "AT+DODLY=1,1,4,1,1\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 继电器 OUT1 每天早上 8 点定时吸合
    msg = "AT+AUTOCONT=2,TASK1,[CYC:1],[T:3,0|1|2|3|4|5|6,08:00:00],[DO:0,1,1,100000,100000,1000000],[N:1,0]\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # IN1/DI1 联动控制继电器 OUT1 点动输出 5 秒
    msg = "AT+LINKAGE1=3,5,100000,1,1000000\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 上电默认状态设置为吸合
    msg = "AT+DODEFSTA=1\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 使能状态主动上传
    msg = "AT+KPUPLOAD=1\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 使能掉电保存
    msg = "AT+KPKEEP=1\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束
elif(ExecType == 1):
    print(u'DI开关量输入接口测试：')

    # 读取DI开关量输入接口IN1/DI1的状态指令：
    msg = "AT+OCCH1=?\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 被动上传  AT+OCMOD=0\r\n
    # 定时上传	AT+OCMOD=1,300   1：上传模式  300：上传间隔 单位：10ms
    # 触发上传(所有通道)	AT+OCMOD=2,0
    # 触发上传(单个通道)	AT+OCMOD=3,0
    # 设置DI上传模式：每3秒设置上传一次DI状态：
    msg = "AT+OCMOD=1,300\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

elif(ExecType == 2):
    print(u"AI模拟量输入接口测试：")
    # 设置AI1接口的信号类型是电压型
    msg ="AT+AIMODE1=0\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 读取AI1接口实时采样值
    msg ="AT+AIVALUE1=?\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 0：被动上传  使用AT+AIVALUE1=?\r\n指令读取AI1接口实时采样值
    # 1：定时上传	AT+AIUPLOAD1=1,30\r\n   30：上传间隔 单位：100ms
    # 2：触发上传	AT+AIUPLOAD1=2,0,30,0,2000,0,0\r\n  设置 AI1 接口采样值高于 2000 并持续 3 秒触发上传
    # 3：定时+触发上传 AT+AIUPLOAD1=2,30,30,0,2000,0,0\r\n  设置 AI1 接口 3秒上传一次 或 采样值高于 2000 并持续 3 秒触发上传
    # 设置3秒上传1次AI1接口采样值
    msg ="AT+AIUPLOAD1=1,30\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束
elif(ExecType == 3):
    print(u"VO语音输出接口测试：")
    # 控制VO1接口播放文字“泥人科技”
    msg =u"AT+TTS1=1,0,8\r\n泥人科技"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg.encode('gbk'))
    time.sleep(1) #等待消息处理结束

    # 控制VO1接口播放语音文件1
    msg ="AT+AUDIO1=1,10\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 定时播放 VO1接口每天早上8点播放语音文件1
    msg ="AT+AUTOCONT=2,TASK1,[CYC:1],[T:3,0|1|2|3|4|5|6,08:00:00],[VO:0,1,1,10,1,0],[N:1,0]\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # IN1/DI1联动播放语音文件1
    msg ="AT+AUTOCONT=2,TASK1,[CYC:1],[DI:3,1,1],[VO:0,1,1,10,1,0],[N:1,0]\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 文本播放拓展（发音人、声调、语速、语调）
    # VO1 接口使用 
    # 发音人：[m3] 3 晓玲(女声) 51 尹小坚(男声) 52 易小强(男声) 53 田蓓蓓(女声) 54 唐老鸭(效果器) 55 小燕子(女童声)
    # 声调：[i0] 0 - 不识别汉语拼音 1 - 识别汉语拼音 
    # 注意： 欢迎[i0]shi3泥人科技  读作：欢迎shi3用泥人科技   欢迎[i1]shi3用泥人科技  读作：欢迎使用泥人科技
    # 1）拼音格式为：1 至 6 位字母 + 1 位数字   
    # 2）声调用 1 位数字表示 ：1 阴平、2 阳平、3 上声、4 去声、5 轻声 
    # 语速：1-10档 [s5]
    # 语调：1-10档 [t5]
    # 音量：1-10档 [v5]
    # VO1接口使用发音人：晓玲,声调：5,语速：5,语调：5,音量：5播放文本
    msg =u"AT+TTS1=1,0,1,1,39\r\n[m3][s5][t5][v5]欢迎[i0]shi3用泥人科技"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg.encode('gbk'))
    time.sleep(1) #等待消息处理结束
elif(ExecType == 4):
    print(u'电脑开关机功能测试')
    # 发送电脑开机指令
    msg ="AT+PCSSSTA=1\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 每天早上8点开机
    msg ="AT+AUTOCONT=2,TaskName1,[T:3,0|1|2|3|4|5|6,08:00:00],[PC:0,1],[N:1,0]\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 0：被动上传  使用AT+PCSSSTA=?\r\n指令读取开关机状态
    # 1：定时上传	AT+PCSSUPLOAD=1,30\r\n   30：上传间隔 单位：100ms
    # 2：触发上传	AT+PCSSUPLOAD=2\r\n  
    # 3：定时+触发上传 AT+PCSSUPLOAD=3,30\r\n 
    # 设置3秒上传1次电脑开关机状态
    msg ="AT+PCSSUPLOAD=1,30\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 上电自动开机功能启用
    msg ="AT+PCSSAUTO=1\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束

    # 上电禁用机箱按键，即按键失效
    msg ="AT+PCSSEXTKEY=1\r\n"
    print("SendCmd:" + msg.replace("\r\n","\\r\\n"))
    client.publish("/user/get", payload = msg)
    time.sleep(1) #等待消息处理结束
print(u'测试完成！')
print(u'更多控制指令的详细解释请查阅《网络控制器AT指令手册V2.9.PDF》')
print(u'本Demo仅用于开发参考，不能直接用于商业项目实施！')

client.loop_stop()
client.disconnect()