255 lines
6.7 KiB
Go
255 lines
6.7 KiB
Go
|
package model
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"log/slog"
|
||
|
)
|
||
|
|
||
|
type DCEvent int
|
||
|
|
||
|
const (
|
||
|
// 驱动数据更新
|
||
|
DCE_Drive_Update DCEvent = 1
|
||
|
// 采集数据更新
|
||
|
DCE_Collect_Update DCEvent = 2
|
||
|
)
|
||
|
|
||
|
// 驱动采集数据
|
||
|
type DC interface {
|
||
|
// 更新驱动数据,位数组
|
||
|
UpdateDriveByBits(start uint32, bits []bool) error
|
||
|
// 更新驱动数据,字节数组
|
||
|
UpdateDriveByBytes(start uint32, values []byte) error
|
||
|
// 更新采集数据,位数组
|
||
|
UpdateCollectByBits(start uint32, bits []bool) error
|
||
|
// 更新采集数据,字节数组
|
||
|
UpdateCollectByBytes(start uint32, values []byte) error
|
||
|
// 获取驱动数据,字节数组
|
||
|
GetDrive() []byte
|
||
|
// 获取指定驱动数据,位
|
||
|
GetDriveBit(start uint32) bool
|
||
|
// 获取指定驱动数据,位数组
|
||
|
GetDriveBits(start uint32, quantity uint32) []bool
|
||
|
// 获取指定驱动数据,字节
|
||
|
GetDriveByte(start uint32) byte
|
||
|
// 获取指定驱动数据,字节数组
|
||
|
GetDriveBytes(start uint32, quantity uint32) []byte
|
||
|
// 获取采集数据,字节数组
|
||
|
GetCollect() []byte
|
||
|
// 获取指定采集数据,位
|
||
|
GetCollectBit(start uint32) bool
|
||
|
// 获取指定采集数据,位数组
|
||
|
GetCollectBits(start uint32, quantity uint32) []bool
|
||
|
// 获取指定采集数据,字节
|
||
|
GetCollectByte(start uint32) byte
|
||
|
// 获取指定采集数据,字节数组
|
||
|
GetCollectBytes(start uint32, quantity uint32) []byte
|
||
|
// 发布事件
|
||
|
Emit(event DCEvent)
|
||
|
// 订阅事件
|
||
|
On(event DCEvent, callback func(dc DC))
|
||
|
// 取消订阅
|
||
|
Off(event DCEvent, callback func(dc DC))
|
||
|
}
|
||
|
|
||
|
type dc struct {
|
||
|
// 驱动数据
|
||
|
drive []byte
|
||
|
driveBits []bool
|
||
|
// 采集数据
|
||
|
collect []byte
|
||
|
collectBits []bool
|
||
|
// 事件
|
||
|
subscribes map[DCEvent][]func(dc DC)
|
||
|
}
|
||
|
|
||
|
// GetCollect implements DC.
|
||
|
func (d *dc) GetCollect() []byte {
|
||
|
return d.collect
|
||
|
}
|
||
|
|
||
|
func (d *dc) GetCollectBit(start uint32) bool {
|
||
|
if start >= uint32(len(d.collectBits)) {
|
||
|
panic(fmt.Errorf("GetCollectBit超出范围"))
|
||
|
}
|
||
|
return d.collectBits[start]
|
||
|
}
|
||
|
|
||
|
func (d *dc) GetCollectBits(start uint32, quantity uint32) []bool {
|
||
|
if start+quantity > uint32(len(d.collectBits)) {
|
||
|
panic(fmt.Errorf("GetCollectBits超出范围"))
|
||
|
}
|
||
|
return d.collectBits[start : start+quantity]
|
||
|
}
|
||
|
|
||
|
func (d *dc) GetCollectByte(start uint32) byte {
|
||
|
if start >= uint32(len(d.collect)) {
|
||
|
panic(fmt.Errorf("GetCollectByte超出范围"))
|
||
|
}
|
||
|
return d.collect[start]
|
||
|
}
|
||
|
|
||
|
func (d *dc) GetCollectBytes(start uint32, quantity uint32) []byte {
|
||
|
if start+quantity > uint32(len(d.collect)) {
|
||
|
panic(fmt.Errorf("GetCollectBytes超出范围"))
|
||
|
}
|
||
|
return d.collect[start : start+quantity]
|
||
|
}
|
||
|
|
||
|
// GetDrive implements DC.
|
||
|
func (d *dc) GetDrive() []byte {
|
||
|
return d.drive
|
||
|
}
|
||
|
|
||
|
func (d *dc) GetDriveBit(start uint32) bool {
|
||
|
if start >= uint32(len(d.driveBits)) {
|
||
|
panic(fmt.Errorf("GetDriveBit超出范围"))
|
||
|
}
|
||
|
return d.driveBits[start]
|
||
|
}
|
||
|
|
||
|
func (d *dc) GetDriveBits(start uint32, quantity uint32) []bool {
|
||
|
if start+quantity > uint32(len(d.driveBits)) {
|
||
|
panic(fmt.Errorf("GetDriveBits超出范围"))
|
||
|
}
|
||
|
return d.driveBits[start : start+quantity]
|
||
|
}
|
||
|
|
||
|
func (d *dc) GetDriveByte(start uint32) byte {
|
||
|
if start >= uint32(len(d.drive)) {
|
||
|
panic(fmt.Errorf("GetDriveByte超出范围"))
|
||
|
}
|
||
|
return d.drive[start]
|
||
|
}
|
||
|
|
||
|
func (d *dc) GetDriveBytes(start uint32, quantity uint32) []byte {
|
||
|
if start+quantity > uint32(len(d.drive)) {
|
||
|
panic(fmt.Errorf("GetDriveBytes超出范围"))
|
||
|
}
|
||
|
return d.drive[start : start+quantity]
|
||
|
}
|
||
|
|
||
|
// UpdateCollectByBits implements DC.
|
||
|
func (d *dc) UpdateCollectByBits(start uint32, bits []bool) error {
|
||
|
total := len(d.collectBits)
|
||
|
if start >= uint32(total) {
|
||
|
return fmt.Errorf("UpdateCollectByBits参数start超出范围")
|
||
|
}
|
||
|
end := start + uint32(len(bits))
|
||
|
if end > uint32(total) {
|
||
|
return fmt.Errorf("UpdateCollectByBits参数start+len(bits)超出范围")
|
||
|
}
|
||
|
for i := start; i < end; i++ {
|
||
|
d.collectBits[i] = bits[i-start]
|
||
|
}
|
||
|
d.collect = encodeBytes(d.collectBits)
|
||
|
slog.Debug("UpdateCollectByBits成功", "collect", fmt.Sprintf("%v", d.collect), "collectBits", d.collectBits)
|
||
|
d.Emit(DCE_Collect_Update)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// UpdateCollectByBytes implements DC.
|
||
|
func (d *dc) UpdateCollectByBytes(start uint32, values []byte) error {
|
||
|
total := len(d.collect)
|
||
|
if start >= uint32(total) {
|
||
|
return fmt.Errorf("UpdateCollectByBytes参数start超出范围")
|
||
|
}
|
||
|
end := start + uint32(len(values))
|
||
|
if end > uint32(total) {
|
||
|
return fmt.Errorf("UpdateCollectByBytes参数start+len(values)超出范围")
|
||
|
}
|
||
|
copy(d.collect[start:end], values)
|
||
|
d.collectBits = decodeBools(d.collect)
|
||
|
slog.Debug("UpdateCollectByBytes成功", "collect", fmt.Sprintf("%v", d.collect), "collectBits", d.collectBits)
|
||
|
d.Emit(DCE_Collect_Update)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// UpdateDriveByBits implements DC.
|
||
|
func (d *dc) UpdateDriveByBits(start uint32, bits []bool) error {
|
||
|
total := len(d.driveBits)
|
||
|
if start >= uint32(total) {
|
||
|
return fmt.Errorf("UpdateDriveByBits参数start超出范围")
|
||
|
}
|
||
|
end := start + uint32(len(bits))
|
||
|
if end > uint32(total) {
|
||
|
return fmt.Errorf("UpdateDriveByBits参数start+len(bits)超出范围")
|
||
|
}
|
||
|
for i := start; i < end; i++ {
|
||
|
d.driveBits[i] = bits[i-start]
|
||
|
}
|
||
|
d.drive = encodeBytes(d.driveBits)
|
||
|
slog.Debug("UpdateDriveByBits成功", "drive", fmt.Sprintf("%v", d.drive), "driveBits", d.driveBits)
|
||
|
d.Emit(DCE_Drive_Update)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// UpdateDriveByBytes implements DC.
|
||
|
func (d *dc) UpdateDriveByBytes(start uint32, values []byte) error {
|
||
|
total := len(d.drive)
|
||
|
if start >= uint32(total) {
|
||
|
return fmt.Errorf("UpdateDriveByBytes参数start超出范围")
|
||
|
}
|
||
|
end := start + uint32(len(values))
|
||
|
if end > uint32(total) {
|
||
|
return fmt.Errorf("UpdateDriveByBytes参数start+len(values)超出范围")
|
||
|
}
|
||
|
copy(d.drive[start:end], values)
|
||
|
d.driveBits = decodeBools(d.drive)
|
||
|
slog.Debug("UpdateDriveByBytes成功", "drive", fmt.Sprintf("%v", d.drive), "driveBits", d.driveBits)
|
||
|
d.Emit(DCE_Drive_Update)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Emit implements DC.
|
||
|
func (d *dc) Emit(event DCEvent) {
|
||
|
listeners := d.subscribes[event]
|
||
|
for _, v := range listeners {
|
||
|
v(d)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// On implements DC.
|
||
|
func (d *dc) On(event DCEvent, callback func(d DC)) {
|
||
|
d.subscribes[event] = append(d.subscribes[event], callback)
|
||
|
}
|
||
|
|
||
|
// Off implements DC.
|
||
|
func (d *dc) Off(event DCEvent, callback func(d DC)) {
|
||
|
panic("unimplemented")
|
||
|
}
|
||
|
|
||
|
func NewDC(d []byte, c []byte) DC {
|
||
|
return &dc{
|
||
|
drive: d,
|
||
|
driveBits: decodeBools(d),
|
||
|
collect: c,
|
||
|
collectBits: decodeBools(c),
|
||
|
subscribes: make(map[DCEvent][]func(d DC)),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func decodeBools(bytes []byte) (out []bool) {
|
||
|
len := len(bytes) * 8
|
||
|
var i int
|
||
|
for i = 0; i < len; i++ {
|
||
|
out = append(out, (((bytes[i/8] >> (i % 8)) & 0x01) == 0x01))
|
||
|
}
|
||
|
return out
|
||
|
}
|
||
|
|
||
|
func encodeBytes(bits []bool) (out []byte) {
|
||
|
len := len(bits)
|
||
|
if len%8 != 0 {
|
||
|
panic("encodeBytes参数bits长度错误")
|
||
|
}
|
||
|
var i int
|
||
|
out = make([]byte, len/8)
|
||
|
for i = 0; i < len; i++ {
|
||
|
if bits[i] {
|
||
|
out[i/8] = out[i/8] | (1 << (i % 8))
|
||
|
}
|
||
|
}
|
||
|
return out
|
||
|
}
|