Skip to content

Commit b3a96b5

Browse files
author
Thouen
committed
feat: enhance Modbus point view with tooltip and format inference
- Updated ModbusSlavePointView.vue to include a tooltip for point types, displaying device protocol and storage type. - Added logic to infer format from point data, ensuring consistent display in the UI. - Adjusted column definitions in the table to accommodate new tooltip functionality. style: improve form controls and help drawer styles - Introduced new styles for field hints and warnings in form-controls.css to enhance user experience. - Modified help-drawer.css for better layout and readability, including adjustments to spacing and element sizes. fix: ensure safe ID handling in device routes - Added isPathSafeId utility function to check for safe ID usage in URL paths, preventing routing issues. - Updated DeviceList.vue to utilize this function when deleting devices, ensuring proper handling of IDs with unsafe characters. refactor: enhance point list with additional hints and warnings - Updated PointList.vue to provide clearer labels and hints for data format and parsing type selections. - Implemented warnings for mismatched parsing types and data types to guide user configuration. test: add unit tests for ID sanitization and ensure device ID functionality - Created tests for EnsureDeviceID, EnsurePointID, and EnsureChannelID to validate ID sanitization logic. - Added comprehensive tests for sanitizeID function to ensure correct behavior across various input cases.
1 parent d537228 commit b3a96b5

41 files changed

Lines changed: 1887 additions & 282 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cmd/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,11 @@ func main() {
358358

359359
zap.L().Info("Shutting down...")
360360

361+
// 有序关闭:HTTP → EdgeCompute → Channels → Pipeline,
362+
// 之后再由 defer 依次关闭 Northbound、Shadow、Store。
361363
srv.StopBackgroundTasks()
364+
srv.Shutdown()
365+
ecm.Stop()
362366
cm.Shutdown()
367+
pipeline.Stop()
363368
}

internal/ai_agent/manager.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ai_agent
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"sync"
67
"time"
@@ -113,10 +114,11 @@ func (a *Agent) Create(req aitypes.CreateRequest) (*aitypes.TaskRecord, error) {
113114

114115
a.mu.Lock()
115116
a.tasks[id] = rec
117+
result := cloneTask(rec)
116118
a.mu.Unlock()
117119

118120
go a.runPipeline(id, req, estTokens)
119-
return cloneTask(rec), nil
121+
return result, nil
120122
}
121123

122124
func (a *Agent) AttachFile(taskID, filename string) error {
@@ -222,6 +224,17 @@ func (a *Agent) runPipeline(id string, req aitypes.CreateRequest, tokens int) {
222224
}
223225

224226
func cloneTask(t *aitypes.TaskRecord) *aitypes.TaskRecord {
227+
if t == nil {
228+
return nil
229+
}
230+
data, err := json.Marshal(t)
231+
if err == nil {
232+
var cp aitypes.TaskRecord
233+
if json.Unmarshal(data, &cp) == nil {
234+
return &cp
235+
}
236+
}
237+
225238
cp := *t
226239
if t.Stages != nil {
227240
cp.Stages = append([]aitypes.StageProgress(nil), t.Stages...)

internal/core/channel_manager.go

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -650,8 +650,12 @@ func (cm *ChannelManager) tryConnectChannel(channelID string) {
650650
// StartChannel 启动一个采集通道
651651
func (cm *ChannelManager) StartChannel(channelID string) error {
652652
cm.mu.RLock()
653-
ch, ok := cm.channels[channelID]
653+
chPtr, ok := cm.channels[channelID]
654654
d, okDrv := cm.drivers[channelID]
655+
var ch model.Channel
656+
if ok && chPtr != nil {
657+
ch = chPtr.DeepCopy()
658+
}
655659
cm.mu.RUnlock()
656660

657661
if !ok || !okDrv {
@@ -688,7 +692,7 @@ func (cm *ChannelManager) StartChannel(channelID string) error {
688692
continue
689693
}
690694

691-
if err := cm.registerDeviceToScanEngine(ch, dev); err != nil {
695+
if err := cm.registerDeviceToScanEngine(&ch, dev); err != nil {
692696
zap.L().Error("Failed to register device to ScanEngine", zap.String("device", dev.Name), zap.Error(err))
693697
}
694698
}
@@ -702,8 +706,12 @@ func (cm *ChannelManager) StartChannel(channelID string) error {
702706
// StopChannel 停止一个采集通道
703707
func (cm *ChannelManager) StopChannel(channelID string) error {
704708
cm.mu.RLock()
705-
ch, ok := cm.channels[channelID]
709+
chPtr, ok := cm.channels[channelID]
706710
d, okDrv := cm.drivers[channelID]
711+
var ch model.Channel
712+
if ok && chPtr != nil {
713+
ch = chPtr.DeepCopy()
714+
}
707715
cm.mu.RUnlock()
708716

709717
if !ok || !okDrv {
@@ -727,7 +735,7 @@ func (cm *ChannelManager) GetChannels() []model.Channel {
727735
defer cm.mu.RUnlock()
728736
channels := make([]model.Channel, 0, len(cm.channels))
729737
for _, ch := range cm.channels {
730-
c := *ch
738+
c := ch.DeepCopy()
731739
if node := cm.stateManager.GetNode(c.ID); node != nil {
732740
c.NodeRuntime = &model.NodeRuntime{
733741
FailCount: node.Runtime.FailCount,
@@ -938,6 +946,15 @@ func (cm *ChannelManager) GetDevicePoints(channelID, deviceID string) ([]model.P
938946
Quality: "Uncertain",
939947
Value: nil,
940948
ReadWrite: point.ReadWrite,
949+
Format: point.Format,
950+
WordOrder: point.WordOrder,
951+
Scale: point.Scale,
952+
Offset: point.Offset,
953+
ReadFormula: point.ReadFormula,
954+
WriteFormula: point.WriteFormula,
955+
Group: point.Group,
956+
ScanClass: point.ScanClass,
957+
ReportMode: point.ReportMode,
941958
})
942959
}
943960
return points, nil
@@ -982,6 +999,15 @@ func (cm *ChannelManager) getDevicePointsFromShadow(dev *model.Device, slaveID u
982999
Quality: "Bad",
9831000
Value: nil,
9841001
ReadWrite: point.ReadWrite,
1002+
Format: point.Format,
1003+
WordOrder: point.WordOrder,
1004+
Scale: point.Scale,
1005+
Offset: point.Offset,
1006+
ReadFormula: point.ReadFormula,
1007+
WriteFormula: point.WriteFormula,
1008+
Group: point.Group,
1009+
ScanClass: point.ScanClass,
1010+
ReportMode: point.ReportMode,
9851011
}
9861012
if sp, exists := shadow.Points[point.ID]; exists {
9871013
pd.Value = sp.Value
@@ -1507,7 +1533,11 @@ func (cm *ChannelManager) ScanChannel(ctx context.Context, channelID string, par
15071533
}
15081534
cm.mu.RLock()
15091535
d, okDrv := cm.drivers[channelID]
1510-
ch, okCh := cm.channels[channelID]
1536+
chPtr, okCh := cm.channels[channelID]
1537+
var ch model.Channel
1538+
if okCh && chPtr != nil {
1539+
ch = chPtr.DeepCopy()
1540+
}
15111541
cm.mu.RUnlock()
15121542

15131543
if !okDrv {
@@ -1591,7 +1621,7 @@ func (cm *ChannelManager) ScanChannel(ctx context.Context, channelID string, par
15911621
zap.Stack("stack"))
15921622
}
15931623
}()
1594-
cm.autoUpdateBACnetAddresses(ch, result)
1624+
cm.autoUpdateBACnetAddresses(&ch, result)
15951625
}()
15961626
}
15971627

@@ -1755,7 +1785,11 @@ func (cm *ChannelManager) ScanDevice(ctx context.Context, channelID, deviceID st
17551785
}
17561786
cm.mu.RLock()
17571787
d, okDrv := cm.drivers[channelID]
1758-
ch, okCh := cm.channels[channelID]
1788+
chPtr, okCh := cm.channels[channelID]
1789+
var ch model.Channel
1790+
if okCh && chPtr != nil {
1791+
ch = chPtr.DeepCopy()
1792+
}
17591793
cm.mu.RUnlock()
17601794

17611795
if !okDrv || !okCh {
@@ -2543,7 +2577,7 @@ func (cm *ChannelManager) saveChannels() error {
25432577
// Copy channel data under caller's lock
25442578
channels := make([]model.Channel, 0, len(cm.channels))
25452579
for _, c := range cm.channels {
2546-
channels = append(channels, *c)
2580+
channels = append(channels, c.DeepCopy())
25472581
}
25482582

25492583
// Save asynchronously to avoid holding cm.mu during disk I/O.

0 commit comments

Comments
 (0)