package main
import (
"crypto/aes"
"crypto/md5"
"encoding/binary"
"encoding/hex"
"flag"
"fmt"
"hash/crc32"
"net"
"time"
)
func encryptAES(data []byte, key []byte) []byte {
block, _ := aes.NewCipher(key)
padding := block.BlockSize() - len(data)%block.BlockSize()
padtext := append(data, make([]byte, padding)...)
for i := len(data); i < len(padtext); i++ {
padtext[i] = byte(padding)
}
encrypted := make([]byte, len(padtext))
for bs, be := 0, block.BlockSize(); bs < len(padtext); bs, be = bs+block.BlockSize(), be+block.BlockSize() {
block.Encrypt(encrypted[bs:be], padtext[bs:be])
}
return encrypted
}
func main() {
ip := flag.String("ip", "", "IP-адрес лампы")
id := flag.String("id", "", "ID устройства")
key := flag.String("key", "", "Local Key")
action := flag.String("cmd", "off", "on или off")
flag.Parse()
if *ip == "" || *id == "" || *key == "" {
fmt.Println("Использование: ./tuya_lite -ip=192.168.1.X -id=... -key=... -cmd=off")
return
}
var state bool
if *action == "on" { state = true }
// Формируем payload для Tuya v3.3
timestamp := time.Now().Unix()
dps := fmt.Sprintf(`{"dps":{"1":%t},"t":%d}`, state, timestamp)
// Хэшируем ключ для создания вектора шифрования протокола 3.3
hasher := md5.New()
hasher.Write([]byte(*key))
md5Key := hasher.Sum(nil)
encData := encryptAES([]byte(dps), md5Key)
// Собираем бинарный контейнер Tuya (Header, Command Type, Length, Data, CRC)
payload := append([]byte("3.3"), make([]byte, 12)...) // Заголовок версии
payload = append(payload, encData...)
packet := make([]byte, 0)
packet = append(packet, []byte{0x00, 0x00, 0x55, 0xAA}...) // Prefix
packet = append(packet, []byte{0x00, 0x00, 0x00, 0x00}...) // Sequence
packet = append(packet, []byte{0x00, 0x00, 0x00, 0x07}...) // Command 7 (CONTROL)
lengthBuf := make([]byte, 4)
binary.BigEndian.PutUint32(lengthBuf, uint32(len(payload)+8))
packet = append(packet, lengthBuf...)
packet = append(packet, payload...)
crc := crc32.ChecksumIEEE(packet)
crcBuf := make([]byte, 4)
binary.BigEndian.PutUint32(crcBuf, crc)
packet = append(packet, crcBuf...)
packet = append(packet, []byte{0x00, 0x00, 0xAA, 0x55}...) // Suffix
// Отправляем пакет по TCP напрямую в лампу
conn, err := net.DialTimeout("tcp", *ip+":6668", 2*time.Second)
if err != nil {
fmt.Println("Ошибка подключения к лампе:", err)
return
}
defer conn.Close()
_, err = conn.Write(packet)
if err != nil {
fmt.Println("Ошибка отправки:", err)
return
}
fmt.Printf("Команда %s успешно отправлена напрямую на %s!\n", *action, *ip)
}