Skip to content

Commit beb4e8f

Browse files
committed
Merge branch 'hi-develop' into hi
* hi-develop: feat:定时统计在线离线时间 fix:webpwd接口添加签名,set_hotdnsq执行判断 fix: transaction lock fix: update column fix: 发送给路由器的分流为空数组时,删除路由中心的分流数据 fix: 发送给路由器的分流为空数组时,删除路由中心的分流数据 optimize: 路由器的web终端显示水印 fix:移动网络下网关无dns,默认使用8.8.8.8 fix:移动网络下网关无dns,默认使用8.8.8.8
2 parents 68dc7d9 + 188df30 commit beb4e8f

File tree

12 files changed

+548
-48
lines changed

12 files changed

+548
-48
lines changed

cmd/cmd/all.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"github.com/spf13/cobra"
6+
"log"
7+
"os"
8+
"rttys/cmd/model"
9+
"rttys/hi"
10+
"runtime"
11+
"time"
12+
)
13+
14+
func init() {
15+
rootCmd.AddCommand(allCmd)
16+
}
17+
18+
var allCmd = &cobra.Command{
19+
Use: "all",
20+
Short: "Summary statistic status by all time",
21+
Long: "Summary statistic status by all time",
22+
PreRun: func(cmd *cobra.Command, args []string) {
23+
rttysDB = os.Getenv("RTTYS_DB")
24+
if rttysDB == "" {
25+
log.Fatal("env RTTYS_DB is required")
26+
}
27+
var err error
28+
db, err = hi.InstanceDB(rttysDB)
29+
if err != nil {
30+
log.Fatal("init db occurred error")
31+
}
32+
},
33+
Run: func(cmd *cobra.Command, args []string) {
34+
defer func() {
35+
var mem runtime.MemStats
36+
runtime.ReadMemStats(&mem)
37+
fmt.Printf("本次运行总共分配内存:%d\n", mem.Alloc)
38+
}()
39+
handle()
40+
},
41+
}
42+
43+
func handle() {
44+
var msgs []model.Message
45+
var devIDs []string
46+
db.Table("hi_messages").Where("action in ?", []string{Off, On}).Order("created_at asc").Find(&msgs)
47+
for _, msg := range msgs {
48+
if !hi.InArray(msg.Devid, devIDs) {
49+
devIDs = append(devIDs, msg.Devid)
50+
}
51+
}
52+
53+
// 清空所有
54+
db.Exec("TRUNCATE TABLE hi_statistics_status")
55+
56+
for _, devID := range devIDs {
57+
// 初始化map
58+
allRecords = make(map[string]model.StatisticsStatus, 1)
59+
var deviceMsgs []model.Message
60+
for _, msg := range msgs {
61+
if msg.Devid == devID {
62+
deviceMsgs = append(deviceMsgs, msg)
63+
}
64+
}
65+
// hack: 最后添加一条不一样的状态,方便计算
66+
lastMsg := deviceMsgs[len(deviceMsgs)-1]
67+
tmpAction := Off
68+
if lastMsg.Action == Off {
69+
tmpAction = On
70+
}
71+
deviceMsgs = append(deviceMsgs, model.Message{
72+
ID: 0,
73+
Devid: devID,
74+
Action: tmpAction,
75+
CreatedAt: uint32(time.Now().Unix()),
76+
})
77+
78+
handleMessages(devID, deviceMsgs)
79+
80+
var statistic []model.StatisticsStatus
81+
for _, item := range allRecords {
82+
statistic = append(statistic, item)
83+
}
84+
// 批量插入
85+
db.Table("hi_statistics_status").Create(&statistic)
86+
}
87+
}
88+
89+
func handleMessages(devId string, messages []model.Message) {
90+
// 连续相同动作,保留第一条
91+
var handledMessages []model.Message
92+
var lastMessage model.Message
93+
for i, message := range messages {
94+
if i == 0 {
95+
lastMessage = message
96+
handledMessages = append(handledMessages, message)
97+
continue
98+
}
99+
if message.Action != lastMessage.Action {
100+
handledMessages = append(handledMessages, message)
101+
}
102+
lastMessage = message
103+
}
104+
105+
for i, message := range handledMessages {
106+
if i == 0 {
107+
lastMessage = message
108+
continue
109+
}
110+
111+
lastMsgEndSec := time.Unix(int64(lastMessage.CreatedAt), 0).Format(layoutDate) + " 23:59:59"
112+
lastMsgDayEnd, err := time.ParseInLocation(layoutDatetime, lastMsgEndSec, loc)
113+
if err != nil {
114+
panic(err)
115+
}
116+
lastMsgDate := time.Unix(int64(lastMessage.CreatedAt), 0).Format(layoutDate)
117+
msgDate := time.Unix(int64(message.CreatedAt), 0).Format(layoutDate)
118+
if lastMsgDate != msgDate { // 不是同一天,分多段
119+
updateMap(devId, lastMsgDate, lastMessage.Action, uint32(lastMsgDayEnd.Unix())+1, lastMessage.CreatedAt)
120+
// 跨度大于 ( 1 天 + 上个记录日期剩余秒数 )
121+
if message.CreatedAt > (uint32(lastMsgDayEnd.Unix()) + DaySeconds) {
122+
days := (message.CreatedAt - lastMessage.CreatedAt) / DaySeconds
123+
for i2 := 0; i2 < int(days); i2++ {
124+
tmpDate := time.Unix(int64(lastMessage.CreatedAt)+int64(DaySeconds*(i2+1)), 0).Format(layoutDate)
125+
if tmpDate != msgDate {
126+
updateMap(devId, tmpDate, lastMessage.Action, DaySeconds, 0)
127+
}
128+
}
129+
}
130+
recordStartSec := msgDate + " 00:00:00"
131+
recordDayStart, err := time.ParseInLocation(layoutDatetime, recordStartSec, loc)
132+
if err != nil {
133+
panic(err)
134+
}
135+
updateMap(devId, msgDate, lastMessage.Action, message.CreatedAt, uint32(recordDayStart.Unix()))
136+
} else { // 同一天
137+
updateMap(devId, msgDate, lastMessage.Action, message.CreatedAt, lastMessage.CreatedAt)
138+
}
139+
lastMessage = message
140+
}
141+
}

cmd/cmd/common.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package cmd
2+
3+
import (
4+
"gorm.io/gorm"
5+
"rttys/cmd/model"
6+
"time"
7+
)
8+
9+
const Off = "disconnected"
10+
const On = "connected"
11+
const DaySeconds = 86400
12+
13+
var (
14+
rttysDB string
15+
db *gorm.DB
16+
layoutDate = "2006-01-02"
17+
layoutDatetime = "2006-01-02 15:04:05"
18+
allRecords map[string]model.StatisticsStatus
19+
loc, _ = time.LoadLocation("Local")
20+
)
21+
22+
func updateMap(devID string, date string, status string, end uint32, start uint32) {
23+
key := devID + ":" + date
24+
var (
25+
online uint32
26+
offline uint32
27+
)
28+
if status == Off {
29+
offline = end - start
30+
} else {
31+
online = end - start
32+
}
33+
34+
if v, ok := allRecords[key]; ok {
35+
v.Offline += offline
36+
v.Online += online
37+
v.LastAction = status
38+
allRecords[key] = v
39+
} else {
40+
allRecords[key] = model.StatisticsStatus{
41+
Devid: devID,
42+
Date: date,
43+
Online: online,
44+
Offline: offline,
45+
LastAction: status,
46+
}
47+
}
48+
}

cmd/cmd/root.go

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"github.com/spf13/cobra"
6+
"log"
7+
"os"
8+
"rttys/cmd/model"
9+
"rttys/hi"
10+
"time"
11+
)
12+
13+
var specifiedDay string
14+
15+
var rootCmd = &cobra.Command{
16+
Use: "statistic-status",
17+
Short: "Summary statistic status by day",
18+
Long: "Summary statistic status by day",
19+
PreRun: func(cmd *cobra.Command, args []string) {
20+
rttysDB = os.Getenv("RTTYS_DB")
21+
if rttysDB == "" {
22+
log.Fatal("env RTTYS_DB is required")
23+
}
24+
var err error
25+
db, err = hi.InstanceDB(rttysDB)
26+
if err != nil {
27+
log.Fatal("init db occurred error")
28+
}
29+
30+
if specifiedDay != "" {
31+
_, err := time.ParseInLocation(layoutDate, specifiedDay, loc)
32+
if err != nil {
33+
log.Fatal("specified day error")
34+
}
35+
}
36+
},
37+
Run: func(cmd *cobra.Command, args []string) {
38+
39+
var theDay string
40+
if specifiedDay != "" {
41+
theDay = specifiedDay
42+
} else {
43+
theDay = time.Now().Add(-DaySeconds * time.Second).Format(layoutDate)
44+
}
45+
theDayStartStr := theDay + " 00:00:00"
46+
theDayStartTime, err := time.ParseInLocation(layoutDatetime, theDayStartStr, loc)
47+
if err != nil {
48+
log.Fatal("parse time error:" + err.Error())
49+
}
50+
theDayStart := theDayStartTime.Unix()
51+
nextDayStart := theDayStart + DaySeconds
52+
dayBeforeTheDay := time.Unix(theDayStart, 0).Add(-DaySeconds).Format(layoutDate)
53+
54+
var (
55+
ss []model.StatisticsStatus
56+
msgs []model.Message
57+
yesterdayMsgs []model.Message
58+
)
59+
allRecords = make(map[string]model.StatisticsStatus, 1)
60+
// 前一天的数据
61+
db.Table("hi_statistics_status").Where("date = ?", dayBeforeTheDay).Find(&ss)
62+
// 当天的数据
63+
db.Table("hi_messages").Where("action in ?", []string{Off, On}).
64+
Where("created_at between ? and ?", theDayStart, theDayStart+DaySeconds).
65+
Order("created_at asc").Find(&yesterdayMsgs)
66+
67+
for _, s := range ss {
68+
msgs = append(msgs, model.Message{
69+
ID: 0,
70+
Devid: s.Devid,
71+
Action: s.LastAction,
72+
CreatedAt: uint32(theDayStart),
73+
})
74+
}
75+
for _, yesterdayMsg := range yesterdayMsgs {
76+
msgs = append(msgs, yesterdayMsg)
77+
}
78+
var devIDs []string
79+
for _, msg := range msgs {
80+
if !hi.InArray(msg.Devid, devIDs) {
81+
devIDs = append(devIDs, msg.Devid)
82+
}
83+
}
84+
// 按设备分组
85+
for _, devID := range devIDs {
86+
var deviceMsgs []model.Message
87+
for _, msg := range msgs {
88+
if msg.Devid == devID {
89+
deviceMsgs = append(deviceMsgs, msg)
90+
}
91+
}
92+
// hack: 最后添加一条不一样的状态,方便计算
93+
endMsg := deviceMsgs[len(deviceMsgs)-1]
94+
tmpAction := Off
95+
if endMsg.Action == Off {
96+
tmpAction = On
97+
}
98+
deviceMsgs = append(deviceMsgs, model.Message{
99+
ID: 0,
100+
Devid: devID,
101+
Action: tmpAction,
102+
CreatedAt: uint32(nextDayStart),
103+
})
104+
105+
handleMessagesByDay(devID, theDay, deviceMsgs)
106+
}
107+
108+
db.Table("hi_statistics_status").Where("date = ?", theDay).Delete(&model.StatisticsStatus{})
109+
var statistic []model.StatisticsStatus
110+
for _, item := range allRecords {
111+
statistic = append(statistic, item)
112+
}
113+
// 批量插入
114+
db.Table("hi_statistics_status").Create(&statistic)
115+
},
116+
}
117+
118+
func handleMessagesByDay(devID string, msgDate string, msgs []model.Message) {
119+
// 连续相同动作,保留第一条
120+
var handledMessages []model.Message
121+
var lastMessage model.Message
122+
for i, msg := range msgs {
123+
if i == 0 {
124+
lastMessage = msg
125+
handledMessages = append(handledMessages, msg)
126+
continue
127+
}
128+
if msg.Action != lastMessage.Action {
129+
handledMessages = append(handledMessages, msg)
130+
}
131+
lastMessage = msg
132+
}
133+
134+
for i, message := range handledMessages {
135+
if i == 0 {
136+
lastMessage = message
137+
continue
138+
}
139+
updateMap(devID, msgDate, lastMessage.Action, message.CreatedAt, lastMessage.CreatedAt)
140+
lastMessage = message
141+
}
142+
}
143+
144+
func Execute() {
145+
rootCmd.CompletionOptions.DisableDefaultCmd = true
146+
rootCmd.Flags().StringVar(&specifiedDay, "day", "", "specified day, eg: 2020-02-02")
147+
if err := rootCmd.Execute(); err != nil {
148+
fmt.Println(err)
149+
os.Exit(1)
150+
}
151+
}

cmd/main.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package main
2+
3+
import "rttys/cmd/cmd"
4+
5+
func main() {
6+
cmd.Execute()
7+
}

cmd/model/tables.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package model
2+
3+
type Message struct {
4+
ID uint32 `gorm:"id"`
5+
Devid string `gorm:"devid"`
6+
Action string `gorm:"action"`
7+
CreatedAt uint32 `gorm:"created_at"`
8+
}
9+
10+
type StatisticsStatus struct {
11+
ID uint32 `gorm:"id"`
12+
Devid string `gorm:"devid"`
13+
Date string `gorm:"date"`
14+
LastAction string `gorm:"last_action"`
15+
Offline uint32 `gorm:"offline"`
16+
Online uint32 `gorm:"online"`
17+
}

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
github.com/go-playground/universal-translator v0.18.0 // indirect
2525
github.com/google/go-cmp v0.5.9 // indirect
2626
github.com/google/uuid v1.3.0 // indirect
27+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
2728
github.com/jinzhu/inflection v1.0.0 // indirect
2829
github.com/jinzhu/now v1.1.5 // indirect
2930
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
@@ -33,6 +34,8 @@ require (
3334
github.com/onsi/gomega v1.24.2 // indirect
3435
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
3536
github.com/russross/blackfriday/v2 v2.1.0 // indirect
37+
github.com/spf13/cobra v1.7.0 // indirect
38+
github.com/spf13/pflag v1.0.5 // indirect
3639
github.com/ugorji/go/codec v1.2.6 // indirect
3740
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
3841
golang.org/x/sys v0.3.0 // indirect
@@ -51,7 +54,7 @@ require (
5154
)
5255

5356
require (
54-
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
57+
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
5558
github.com/go-playground/validator/v10 v10.9.0 // indirect
5659
github.com/golang/protobuf v1.5.2 // indirect
5760
github.com/mattn/go-isatty v0.0.14 // indirect

0 commit comments

Comments
 (0)