加入 pjlink 控制
This commit is contained in:
141
pkg/pjlink/pjlink.go
Normal file
141
pkg/pjlink/pjlink.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package pjlink
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/md5"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrAuthFailed = errors.New("授权验证失败")
|
||||
ErrCommandError = errors.New("命令执行异常")
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Host string
|
||||
Port string
|
||||
Password string
|
||||
ID string
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
func NewClient(host, port, password, id string) *Client {
|
||||
return &Client{
|
||||
Host: host,
|
||||
Port: port,
|
||||
Password: password,
|
||||
ID: id,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Connect() error {
|
||||
address := net.JoinHostPort(c.Host, c.Port)
|
||||
conn, err := net.DialTimeout("tcp", address, 5*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.conn = conn
|
||||
|
||||
// Read challenge
|
||||
reader := bufio.NewReader(c.conn)
|
||||
response, err := reader.ReadString('\r')
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle authentication
|
||||
if strings.HasPrefix(response, "PJLINK 1") {
|
||||
if c.Password == "" {
|
||||
c.Close()
|
||||
return ErrAuthFailed
|
||||
}
|
||||
|
||||
challenge := strings.TrimSpace(strings.Split(response, " ")[2])
|
||||
authString := fmt.Sprintf("%s%s", challenge, c.Password)
|
||||
hashed := md5.Sum([]byte(authString))
|
||||
authHash := fmt.Sprintf("%x", hashed)
|
||||
|
||||
_, err = fmt.Fprintf(c.conn, "%s\r", authHash)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
authResponse, err := reader.ReadString('\r')
|
||||
if err != nil || !strings.Contains(authResponse, "OK") {
|
||||
c.Close()
|
||||
return ErrAuthFailed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) sendCommand(command string) (string, error) {
|
||||
if c.conn == nil {
|
||||
return "", errors.New("not connected")
|
||||
}
|
||||
|
||||
fullCommand := fmt.Sprintf("%%%s%s\r", c.ID, command)
|
||||
_, err := c.conn.Write([]byte(fullCommand))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(c.conn)
|
||||
response, err := reader.ReadString('\r')
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Remove prefix and parse response
|
||||
parts := strings.SplitN(response, "=", 2)
|
||||
if len(parts) < 2 {
|
||||
return "", ErrCommandError
|
||||
}
|
||||
|
||||
result := strings.TrimSpace(parts[1])
|
||||
if result == "ERR1" {
|
||||
return "", ErrAuthFailed
|
||||
} else if result == "ERR2" {
|
||||
return "", ErrCommandError
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Client) PowerOn() error {
|
||||
response, err := c.sendCommand("POWR 1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if response != "OK" {
|
||||
return fmt.Errorf("unexpected response: %s", response)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) PowerOff() error {
|
||||
response, err := c.sendCommand("POWR 0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if response != "OK" {
|
||||
return fmt.Errorf("unexpected response: %s", response)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Close() {
|
||||
if c.conn != nil {
|
||||
c.conn.Close()
|
||||
c.conn = nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user