微雪4.2寸WiFi电子墨水屏GO版示例
这块板子自带了充电电池、WiFi蓝牙模块、充电模块。
package main
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"net"
"strconv"
"github.com/Comdex/imgo"
)
var (
g_width = 400
g_hight = 300
g_frame_len = 1024 //每次传输数据长度不应超过1100Byte,否则将会导致数据丢失.???
g_sector_size = 4096 //扇区大小
)
func check_res(res []byte) (cr []byte, err error) {
if res[0] != '$' {
return cr, errors.New("接收头错误")
}
i := bytes.LastIndexByte(res, '#')
if i == -1 {
return cr, errors.New("接收尾错误")
}
return res[1:i], err
}
func send_cmd(conn net.Conn, cmd []byte, hr bool) (res []byte, err error) {
var check byte
for _, b := range cmd {
check ^= b
}
buf := new(bytes.Buffer)
binary.Write(buf, binary.BigEndian, ';')
binary.Write(buf, binary.BigEndian, cmd)
binary.Write(buf, binary.BigEndian, '/')
binary.Write(buf, binary.BigEndian, check)
conn.Write(buf.Bytes())
rdata := make([]byte, 64)
rl, _ := conn.Read(rdata)
rd, err := check_res(rdata[:rl])
if err != nil {
return res, err
}
if len(rd) != 1 || rd[0] != check {
return res, errors.New("发送数据错误")
}
if hr == false {
return
}
rl, _ = conn.Read(rdata)
return check_res(rdata[:rl])
}
func send_data(conn net.Conn, data []byte) error {
var check byte
for _, b := range data {
check ^= b
}
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.BigEndian, uint8(0x57))
binary.Write(buf, binary.BigEndian, data)
binary.Write(buf, binary.BigEndian, check)
conn.Write(buf.Bytes())
rdata := make([]byte, 64)
rl, _ := conn.Read(rdata)
rd, err := check_res(rdata[:rl])
if err != nil {
return nil
}
if len(rd) != 1 || rd[0] != check {
return errors.New("发送数据错误")
}
return nil
}
func flush_buffer(conn net.Conn, img []byte) {
res, err := send_cmd(conn, []byte("F"), false)
fmt.Println("刷写数据", string(res), err)
for i := 0; i < len(img)/g_frame_len; i++ {
addr := i * g_frame_len
num := addr % g_sector_size / g_frame_len //扇区的第几块? num因版本升级而失去作用,可为恒定值???
data := new(bytes.Buffer)
binary.Write(data, binary.BigEndian, uint32(addr))
binary.Write(data, binary.BigEndian, uint32(g_frame_len))
binary.Write(data, binary.BigEndian, uint8(num))
binary.Write(data, binary.BigEndian, img[addr:addr+g_frame_len])
send_data(conn, data.Bytes())
}
if len(img)%g_frame_len != 0 {
addr := len(img) / g_frame_len * g_frame_len
num := addr % g_sector_size / g_frame_len //扇区的第几块? num因版本升级而失去作用,可为恒定值???
data := new(bytes.Buffer)
binary.Write(data, binary.BigEndian, uint32(addr))
binary.Write(data, binary.BigEndian, uint32(len(img)-addr))
binary.Write(data, binary.BigEndian, uint8(num))
binary.Write(data, binary.BigEndian, img[addr:])
send_data(conn, data.Bytes())
}
data := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} //当addr和len均为0时,退出刷新模式。并自动刷新屏幕。???
send_data(conn, data)
res, err = send_cmd(conn, []byte("D"), false)
fmt.Println("显示数据", string(res), err)
}
func img_to_400_300_bin(p string) (bw []byte, err error) {
img43, err := imgo.ResizeForMatrix(p, g_width, g_hight) //调整大小
if err != nil {
return
}
//imgo.SaveAsJPEG("clo.jpg", img43, 100)
imgb := imgo.Binaryzation(img43, 127) //黑白化
//imgo.SaveAsJPEG("bin.jpg", imgb, 100)
bw = make([]byte, g_width/8*g_hight) //生成画布 一比特一像素
for i := 0; i < len(imgb); i++ { //高
for j := 0; j < len(imgb[0]); j++ { //宽
var r uint8
if imgb[i][j][0] == 0 { //rgba
r = 0
} else {
r = 1
}
pos := i*len(imgb[0]) + j
bw[pos/8] |= r << (8 - (pos % 8) - 1) //按位填充数据
}
}
return
}
func doServerStuff(conn net.Conn) {
defer conn.Close()
res, err := send_cmd(conn, []byte("G"), true)
fmt.Println("主机名", string(res), err)
res, err = send_cmd(conn, []byte("C"), true)
fmt.Println("是否有锁", string(res), err)
res, err = send_cmd(conn, []byte("N123456"), true)
fmt.Println("解锁结果", string(res), err)
res, err = send_cmd(conn, []byte("b"), true)
b, _ := strconv.Atoi(string(res))
fmt.Println("电池电压", b*3, err)
bw, _ := img_to_400_300_bin(`C:\123.jpg`)
flush_buffer(conn, bw)
for {
res, err = send_cmd(conn, []byte("b"), true)
b, _ := strconv.Atoi(string(res))
fmt.Println("电池电压", b*3, err)
}
}
func main() {
fmt.Println("开启服务")
listener, err := net.Listen("tcp", ":6868")
if err != nil {
fmt.Println("监听失败", err)
return
}
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("接收新客户失败", err)
return
}
fmt.Println("接收到新客户", conn.RemoteAddr())
go doServerStuff(conn)
}
}
自己翻译成go语言版,非常粗糙能跑通版。
官方文档地址 https://www.waveshare.net/wiki/4.2inch_e-Paper_Cloud_Module