device_daily_running_record.go
5.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
package domain
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-manufacture/pkg/infrastructure/utils"
"time"
)
const DefaultTimeWindow = 1
// 设备每日运行记录(汇总)
type DeviceDailyRunningRecord struct {
// 设备每日运行记录ID
DeviceDailyRunningRecordId int `json:"deviceDailyRunningRecordId"`
// 企业id
CompanyId int `json:"companyId"`
// 组织ID
OrgId int `json:"orgId"`
// 工作位置
WorkStation *WorkStation `json:"workStation"`
// 设备Id
DeviceId int `json:"deviceId"`
// 设备编号
DeviceCode string `json:"deviceCode"`
// 生产日期
ProductDate time.Time `json:"productDate"`
// 设备运行记录信息
DeviceRunningRecordInfo *DeviceRunningRecordInfo `json:"deviceRunningRecordInfo"`
// 创建时间
CreatedAt time.Time `json:"createdAt"`
// 更新时间
UpdatedAt time.Time `json:"updatedAt"`
// 删除时间
DeletedAt time.Time `json:"deletedAt"`
}
type DeviceDailyRunningRecordRepository interface {
Save(deviceDailyRunningRecord *DeviceDailyRunningRecord) (*DeviceDailyRunningRecord, error)
Remove(deviceDailyRunningRecord *DeviceDailyRunningRecord) (*DeviceDailyRunningRecord, error)
FindOne(queryOptions map[string]interface{}) (*DeviceDailyRunningRecord, error)
Find(queryOptions map[string]interface{}) (int64, []*DeviceDailyRunningRecord, error)
}
func (deviceDailyRunningRecord *DeviceDailyRunningRecord) Identify() interface{} {
if deviceDailyRunningRecord.DeviceDailyRunningRecordId == 0 {
return nil
}
return deviceDailyRunningRecord.DeviceDailyRunningRecordId
}
func (deviceDailyRunningRecord *DeviceDailyRunningRecord) Update(data map[string]interface{}) error {
return nil
}
// 设备运行记录信息
type DeviceRunningRecordInfo struct {
// 当前状态
// bit0: 运行、停止
// bit1: 正常、故障
CurrentStatus int `json:"currentStatus"`
// 设备OEE = tu * pu * qu
OEE float64 `json:"oee"`
// 时间利用率 TimeUtilization 运行时间 / (当前时间-当日零时)
TimeUtilization float64 `json:"tu"`
// 性能利用率 PerformanceUtilization
// 1. 当前设备实际产出数量/理论数量(理论数量=60*60*12/标准工时)
// 2. 没有数量100%
PerformanceUtilization float64 `json:"pu"`
// 合格率 QualificationUtilization
// 1.按工段的合格率
// 2.默认100%
QualificationUtilization float64 `json:"qu"`
// 运行时长 单位:h
UpTime float64 `json:"upTime"`
// 生成数量
Count int `json:"count"`
// 设备温度 单位:摄氏度
Temp float64 `json:"temp"`
// 时间点
//TimeLine []string `json:"timeLine"`
// 时间点对应的设备状态 按小时 1
TimeLineDeviceStatus map[string]*HourDeviceStatus `json:"timeLineDeviceStatus"`
// 批次数据
// 生产计划ID
ProductPlanId int `json:"productPlanId,omitempty"`
}
func NewDeviceRunningRecordInfo() *DeviceRunningRecordInfo {
return &DeviceRunningRecordInfo{
TimeLineDeviceStatus: make(map[string]*HourDeviceStatus),
}
}
func (d *DeviceRunningRecordInfo) AddDeviceRunningData(t time.Time, data *DeviceRunningData) {
d.CurrentStatus = data.StartupStatus | (1 << data.ComStatus)
d.ResetUpTime()
d.Count += data.Count
//d.Temp = data.FrontTemp
d.Temp = data.Temp1
d.AddTimeLineDeviceStatus(t, data)
//d.OEE
d.TimeUtilization = d.UpTime * 100 / (time.Now().Sub(utils.GetZeroTime(time.Now())).Hours())
//d.PerformanceUtilization
//d.QualificationUtilization
}
// 添加新的设备状态
func (d *DeviceRunningRecordInfo) AddTimeLineDeviceStatus(t time.Time, data *DeviceRunningData) {
if t.IsZero() {
return
}
key := fmt.Sprintf("%v", t.Hour())
var v *HourDeviceStatus
var ok bool
if v, ok = d.TimeLineDeviceStatus[key]; !ok {
v = NewHourDeviceStatus()
d.TimeLineDeviceStatus[key] = v
}
v.UpdateUp(t, data.StartupStatus)
v.UpdateCom(t, data.ComStatus)
}
// 重置运行时长
func (d *DeviceRunningRecordInfo) ResetUpTime() float64 {
var upTime float64
for _, v := range d.TimeLineDeviceStatus {
t := v.CountTime(v.Up)
upTime += t.Hours()
}
d.UpTime = upTime
return upTime
}
// 重置设备运行OEE
func (d *DeviceRunningRecordInfo) ResetOEE(pu, qu float64) float64 {
d.PerformanceUtilization = pu
d.QualificationUtilization = qu
d.OEE = (d.TimeUtilization + d.PerformanceUtilization + d.QualificationUtilization) / 3
return d.OEE
}
// 单个小时内的设备状态
type HourDeviceStatus struct {
// 时间窗口 1-60 代表时间段范围
// 例如: w=1 则标识下面的状态按1分钟记录一次状态
// up 启动 bit0-bit59的位用来存启动状态 1:启动 0:关闭
// com通讯 bit0-bit59的位用来存通讯状态 1:正常 0:故障
// 如果 w=5 表示按5分钟记录一次状态 使用到 bit0-bit11
Window int `json:"w"`
// 启动
// bit0:1 代表
Up int `json:"up"`
// 通讯
Com int `json:"com"`
}
// 更新启动状态
func (d *HourDeviceStatus) UpdateUp(t time.Time, up int) {
m := t.Minute()
bit := 1 << (m / d.Window)
if up&1 == 0 {
return
}
if d.Up&bit > 0 {
return
}
d.Up |= bit
return
}
// 更新通讯状态
func (d *HourDeviceStatus) UpdateCom(t time.Time, c int) {
m := t.Minute()
bit := 1 << (m / d.Window)
if c&1 == 0 {
return
}
if d.Com&bit > 0 {
return
}
d.Com |= bit
return
}
// 计算状态持续的时间
func (d *HourDeviceStatus) CountTime(v int) time.Duration {
l := 60 / d.Window
count := 0
index := 1
for i := 0; i < l; i++ {
if index&v > 0 {
count++
}
index <<= 1
}
return time.Duration(d.Window*count) * time.Minute / time.Hour
}
func NewHourDeviceStatus() *HourDeviceStatus {
return &HourDeviceStatus{
Window: DefaultTimeWindow,
Up: 0,
Com: 0,
}
}