Загрузка данных


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)
}