|
|
package adl400TtyApi
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
|
|
|
|
"github.com/towgo/towgo/towgo"
|
|
|
"math"
|
|
|
"tgk-touch/internal/global"
|
|
|
"tgk-touch/internal/library/ADL400"
|
|
|
"tgk-touch/internal/module/basicInfo/deviceManagement"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
func readPhaseData(rpc towgo.JsonRpcConnection) {
|
|
|
var p struct {
|
|
|
CommUid string `json:"comm_uid"`
|
|
|
}
|
|
|
rpc.ReadParams(&p)
|
|
|
|
|
|
addr := getMeterAddr(p.CommUid)
|
|
|
rtuCommUid := p.CommUid
|
|
|
var mp deviceManagement.MeterPower
|
|
|
totalEnergy, aEnergy, bEnergy, cEnergy, err := mc.ReadEnergy(rtuCommUid, addr)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
mp.TotalActiveEnergy = math.Round(totalEnergy*100) / 100
|
|
|
mp.AEnergy = math.Round(aEnergy*100) / 100
|
|
|
mp.BEnergy = math.Round(bEnergy*100) / 100
|
|
|
mp.CEnergy = math.Round(cEnergy*100) / 100
|
|
|
|
|
|
_, aVoltage, bVoltage, cVoltage, err := mc.ReadVoltage(rtuCommUid, addr)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
mp.AVoltage = math.Round(aVoltage*100) / 100
|
|
|
mp.BVoltage = math.Round(bVoltage*100) / 100
|
|
|
mp.CVoltage = math.Round(cVoltage*100) / 100
|
|
|
|
|
|
_, aElectricCurrent, bElectricCurrent, cElectricCurrent, err := mc.ReadElectricCurrent(rtuCommUid, addr)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
mp.AElectricCurrent = math.Round(aElectricCurrent*100) / 100
|
|
|
mp.BElectricCurrent = math.Round(bElectricCurrent*100) / 100
|
|
|
mp.CElectricCurrent = math.Round(cElectricCurrent*100) / 100
|
|
|
|
|
|
totalPower, aPower, bPower, cPower, err := mc.ReadPower(rtuCommUid, addr)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
mp.TotalActivePower = math.Round(totalPower*100) / 100
|
|
|
mp.APower = math.Round(aPower*100) / 100
|
|
|
mp.BPower = math.Round(bPower*100) / 100
|
|
|
mp.CPower = math.Round(cPower*100) / 100
|
|
|
tf, af, bf, cf, err := mc.ReadPowerFactor(rtuCommUid, addr)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
mp.TotalPowerFactor = math.Round(tf*1000) / 1000
|
|
|
mp.APowerFactor = math.Round(af*100) / 100
|
|
|
mp.BPowerFactor = math.Round(bf*100) / 100
|
|
|
mp.CPowerFactor = math.Round(cf*100) / 100
|
|
|
if mp.TotalPowerFactor >= 1 {
|
|
|
mp.TotalPowerFactor = 0.999
|
|
|
}
|
|
|
rpc.WriteResult(mp)
|
|
|
}
|
|
|
|
|
|
func getMsgAddress(rpc towgo.JsonRpcConnection) {
|
|
|
var p struct {
|
|
|
CommUid string `json:"comm_uid"`
|
|
|
}
|
|
|
rpc.ReadParams(&p)
|
|
|
addr, err := mc.ReadMsgAddr(p.CommUid, getMeterAddr(p.CommUid))
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
rpc.WriteResult(fmt.Sprintf("0x%X", addr))
|
|
|
}
|
|
|
|
|
|
// 获取日冻结时间
|
|
|
func getDailyFreezingTime(rpc towgo.JsonRpcConnection) {
|
|
|
var p struct {
|
|
|
CommUid string `json:"comm_uid"`
|
|
|
}
|
|
|
rpc.ReadParams(&p)
|
|
|
|
|
|
time, err := mc.ReadDailyFreezingTime(p.CommUid, getMeterAddr(p.CommUid))
|
|
|
if err != nil {
|
|
|
panic(gerror.Wrap(err, "getDailyFreezingTime"))
|
|
|
}
|
|
|
|
|
|
rpc.WriteResult(time)
|
|
|
|
|
|
}
|
|
|
func geDeviceTime(rpc towgo.JsonRpcConnection) {
|
|
|
var p struct {
|
|
|
CommUid string `json:"comm_uid"`
|
|
|
}
|
|
|
rpc.ReadParams(&p)
|
|
|
|
|
|
time, err := mc.ReadTime(p.CommUid, getMeterAddr(p.CommUid))
|
|
|
if err != nil {
|
|
|
panic(gerror.Wrap(err, "geTime"))
|
|
|
}
|
|
|
rpc.WriteResult(time.Format("2006-01-02 15:04:05"))
|
|
|
|
|
|
}
|
|
|
|
|
|
func getReadMonthlyFreezingTime(rpc towgo.JsonRpcConnection) {
|
|
|
var p struct {
|
|
|
CommUid string `json:"comm_uid"`
|
|
|
}
|
|
|
rpc.ReadParams(&p)
|
|
|
|
|
|
day, hour, err := mc.ReadMonthlyFreezingTime(p.CommUid, getMeterAddr(p.CommUid))
|
|
|
if err != nil {
|
|
|
panic(gerror.Wrap(err, "getReadMonthlyFreezingTime"))
|
|
|
}
|
|
|
r := map[string]interface{}{}
|
|
|
r["day"] = day
|
|
|
r["hour"] = hour
|
|
|
rpc.WriteResult(r)
|
|
|
}
|
|
|
func getFreezeTheData(rpc towgo.JsonRpcConnection) {
|
|
|
var p struct {
|
|
|
CommUid string `json:"comm_uid"`
|
|
|
}
|
|
|
rpc.ReadParams(&p)
|
|
|
|
|
|
/*read, err := ADL400.H6000.Read(p.CommUid, getMeterAddr(p.CommUid))
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
block, err := ParseHistoricalEnergyBlock(read)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}*/
|
|
|
dayData := []*HistoricalEnergyBlock{}
|
|
|
monthData := []*HistoricalEnergyBlock{}
|
|
|
for i := 1; i <= 90; i++ {
|
|
|
time.Sleep(10 * time.Second)
|
|
|
|
|
|
address, err := ADL400.GetDailyBlockAddress(i)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
g.Log().Debugf("GetDailyBlockAddress:% X", address)
|
|
|
read, err := address.Read(p.CommUid, getMeterAddr(p.CommUid))
|
|
|
if err != nil {
|
|
|
g.Log().Error(err)
|
|
|
continue
|
|
|
}
|
|
|
block, err := ParseHistoricalEnergyBlock(read)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
dayData = append(dayData, block)
|
|
|
}
|
|
|
for i := 1; i <= 48; i++ {
|
|
|
time.Sleep(10 * time.Second)
|
|
|
address, err := ADL400.GetMonthlyBlockAddress(i)
|
|
|
if err != nil {
|
|
|
g.Log().Error(err)
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
g.Log().Debugf("GetMonthlyBlockAddress:% X", address)
|
|
|
read, err := address.Read(p.CommUid, getMeterAddr(p.CommUid))
|
|
|
if err != nil {
|
|
|
g.Log().Error(err)
|
|
|
continue
|
|
|
}
|
|
|
block, err := ParseHistoricalEnergyBlock(read)
|
|
|
if err != nil {
|
|
|
panic(err)
|
|
|
}
|
|
|
monthData = append(monthData, block)
|
|
|
}
|
|
|
r := map[string]interface{}{}
|
|
|
r["day"] = dayData
|
|
|
r["month"] = monthData
|
|
|
rpc.WriteResult(r)
|
|
|
}
|
|
|
|
|
|
// HistoricalEnergyBlock 包含块读取的历史电能数据
|
|
|
type HistoricalEnergyBlock struct {
|
|
|
FreezeTime time.Time // 冻结时间
|
|
|
TotalActiveEnergy float64 // 总有功电能 (kWh)
|
|
|
PeakActiveEnergy float64 // 有功尖电能 (kWh)
|
|
|
FlatActiveEnergy float64 // 有功峰电能 (kWh)
|
|
|
OffPeakActiveEnergy float64 // 有功平电能 (kWh)
|
|
|
ValleyActiveEnergy float64 // 有功谷电能 (kWh)
|
|
|
TotalReactiveEnergy float64 // 总无功电能 (kvarh)
|
|
|
PeakReactiveEnergy float64 // 无功尖电能 (kvarh)
|
|
|
FlatReactiveEnergy float64 // 无功峰电能 (kvarh)
|
|
|
OffPeakReactiveEnergy float64 // 无功平电能 (kvarh)
|
|
|
ValleyReactiveEnergy float64 // 无功谷电能 (kvarh)
|
|
|
PhaseAActiveEnergy float64 // A相正向有功电能 (kWh)
|
|
|
PhaseBActiveEnergy float64 // B相正向有功电能 (kWh)
|
|
|
PhaseCActiveEnergy float64 // C相正向有功电能 (kWh)
|
|
|
MaxActiveDemand float64 // 有功最大需量 (kW)
|
|
|
MaxActiveDemandTime time.Time // 有功最大需量发生时间
|
|
|
MaxReactiveDemand float64 // 无功最大需量 (kvar)
|
|
|
MaxReactiveDemandTime time.Time // 无功最大需量发生时间
|
|
|
}
|
|
|
|
|
|
// parseUint16Time 解析寄存器中的时间格式
|
|
|
func parseUint16Time(register uint16) (byte, byte) {
|
|
|
// 寄存器格式:高字节 = 第一部分,低字节 = 第二部分
|
|
|
return byte(register >> 8), byte(register & 0xFF)
|
|
|
}
|
|
|
|
|
|
// parseEnergy 解析电能值 (32位数据:2个寄存器)
|
|
|
func parseEnergy(registers []uint16, offset int) float64 {
|
|
|
value := uint32(registers[offset])<<16 | uint32(registers[offset+1])
|
|
|
// 假设精度为0.01 kWh/kvarh (根据实际情况调整)
|
|
|
return float64(value) * 0.01
|
|
|
}
|
|
|
|
|
|
// parseDemand 解析需量值 (16位数据)
|
|
|
func parseDemand(register uint16) float64 {
|
|
|
// 假设精度为0.01 kW/kvar (根据实际情况调整)
|
|
|
return float64(register) * 0.01
|
|
|
}
|
|
|
|
|
|
// parseDateTime 解析日期时间 (年、月、日、时、分)
|
|
|
func parseDateTime(year, month, day, hour, minute uint16) time.Time {
|
|
|
// 处理特殊年份格式 (假设2000年基准)
|
|
|
if year < 100 {
|
|
|
year += 2000
|
|
|
}
|
|
|
|
|
|
// 注意:冻结日期可能不是当前日期
|
|
|
return time.Date(
|
|
|
int(year),
|
|
|
time.Month(month),
|
|
|
int(day),
|
|
|
int(hour),
|
|
|
int(minute),
|
|
|
0, 0, time.Local,
|
|
|
)
|
|
|
}
|
|
|
|
|
|
// ParseHistoricalEnergyBlock 解析 H6000 块读取的数据
|
|
|
func ParseHistoricalEnergyBlock(registers []uint16) (*HistoricalEnergyBlock, error) {
|
|
|
// 验证数据长度应为 34个寄存器 * 2字节/寄存器 = 68字节
|
|
|
if len(registers) != 34 {
|
|
|
return nil, fmt.Errorf("invalid data length: expected 68 bytes, got %d", len(registers))
|
|
|
}
|
|
|
|
|
|
// 将字节数据转换为 uint16 寄存器数组
|
|
|
/* registers := make([]uint16, 34)
|
|
|
err := binary.Read(bytes.NewReader(data), binary.BigEndian, ®isters)
|
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("binary read error: %v", err)
|
|
|
}*/
|
|
|
|
|
|
block := &HistoricalEnergyBlock{}
|
|
|
|
|
|
// 解析冻结时间
|
|
|
freezeYear, freezeMonth := parseUint16Time(registers[0]) // 6000H: 年-月
|
|
|
freezeDay, freezeHour := parseUint16Time(registers[1]) // 6001H: 日-时
|
|
|
block.FreezeTime = parseDateTime(
|
|
|
uint16(freezeYear), uint16(freezeMonth),
|
|
|
uint16(freezeDay), uint16(freezeHour), 0,
|
|
|
)
|
|
|
|
|
|
// 解析电能数据 (32位值, 各2个寄存器)
|
|
|
block.TotalActiveEnergy = parseEnergy(registers, 2) // 6002H-6003H
|
|
|
block.PeakActiveEnergy = parseEnergy(registers, 4) // 6004H-6005H
|
|
|
block.FlatActiveEnergy = parseEnergy(registers, 6) // 6006H-6007H (峰)
|
|
|
block.OffPeakActiveEnergy = parseEnergy(registers, 8) // 6008H-6009H (平)
|
|
|
block.ValleyActiveEnergy = parseEnergy(registers, 10) // 600AH-600BH (谷)
|
|
|
|
|
|
block.TotalReactiveEnergy = parseEnergy(registers, 12) // 600CH-600DH
|
|
|
block.PeakReactiveEnergy = parseEnergy(registers, 14) // 600EH-600FH
|
|
|
block.FlatReactiveEnergy = parseEnergy(registers, 16) // 6010H-6011H (峰)
|
|
|
block.OffPeakReactiveEnergy = parseEnergy(registers, 18) // 6012H-6013H (平)
|
|
|
block.ValleyReactiveEnergy = parseEnergy(registers, 20) // 6014H-6015H (谷)
|
|
|
|
|
|
block.PhaseAActiveEnergy = parseEnergy(registers, 22) // 6016H-6017H
|
|
|
block.PhaseBActiveEnergy = parseEnergy(registers, 24) // 6018H-6019H
|
|
|
block.PhaseCActiveEnergy = parseEnergy(registers, 26) // 601AH-601BH
|
|
|
|
|
|
// 解析有功最大需量及时间
|
|
|
block.MaxActiveDemand = parseDemand(registers[28]) // 601CH (有功最大需量)
|
|
|
|
|
|
minute, hour := parseUint16Time(registers[29]) // 601DH: 分-时
|
|
|
day, month := parseUint16Time(registers[30]) // 601EH: 日-月
|
|
|
block.MaxActiveDemandTime = parseDateTime(
|
|
|
uint16(block.FreezeTime.Year()), uint16(month),
|
|
|
uint16(day), uint16(hour), uint16(minute),
|
|
|
)
|
|
|
|
|
|
// 解析无功最大需量及时间
|
|
|
block.MaxReactiveDemand = parseDemand(registers[31]) // 601FH (无功最大需量)
|
|
|
|
|
|
minute, hour = parseUint16Time(registers[32]) // 6020H: 分-时
|
|
|
day, month = parseUint16Time(registers[33]) // 6021H: 日-月
|
|
|
block.MaxReactiveDemandTime = parseDateTime(
|
|
|
uint16(block.FreezeTime.Year()), uint16(month),
|
|
|
uint16(day), uint16(hour), uint16(minute),
|
|
|
)
|
|
|
|
|
|
return block, nil
|
|
|
}
|