Skip to content

Commit

Permalink
fix: fix target load panic (hootrhino#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
lion-brave authored Jun 16, 2023
1 parent cde2341 commit 7da19e2
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 116 deletions.
13 changes: 10 additions & 3 deletions device/generic_modbus_device.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ type _GMODHostConfig struct {

type _GMODConfig struct {
CommonConfig _GMODCommonConfig `json:"commonConfig" validate:"required"`
RtuConfig common.CommonUartConfig `json:"rtuConfig" validate:"required"`
TcpConfig _GMODHostConfig `json:"tcpConfig" validate:"required"`
RtuConfig common.CommonUartConfig `json:"rtuConfig"`
TcpConfig _GMODHostConfig `json:"tcpConfig"`
Registers []common.RegisterRW `json:"registers" validate:"required" title:"寄存器配置"`
}
type generic_modbus_device struct {
Expand All @@ -80,7 +80,14 @@ func NewGenericModbusDevice(e typex.RuleX) typex.XDevice {
mdev.mainConfig = _GMODConfig{
CommonConfig: _GMODCommonConfig{},
TcpConfig: _GMODHostConfig{Host: "127.0.0.1", Port: 502},
RtuConfig: common.CommonUartConfig{},
RtuConfig: common.CommonUartConfig{
Timeout: 3000,
Uart: "/tty/s1",
BaudRate: 9600,
DataBits: 8,
Parity: "N",
StopBits: 1,
},
}
mdev.Busy = false
mdev.status = typex.DEV_DOWN
Expand Down
2 changes: 1 addition & 1 deletion engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ func (e *RuleEngine) RemoveOutEnd(uuid string) {
e.OutEnds.Delete(uuid)
outEnd = nil
}
glogger.GLogger.Infof("InEnd [%v] has been deleted", uuid)
glogger.GLogger.Infof("OutEnd [%v] has been deleted", uuid)
}
}

Expand Down
20 changes: 10 additions & 10 deletions engine/load_device.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (e *RuleEngine) RemoveDevice(uuid string) {
*
*/
func (e *RuleEngine) LoadUserDevice(abstractDevice typex.XDevice, deviceInfo *typex.Device) error {
return startDevices(abstractDevice, deviceInfo, e)
return loadDevices(abstractDevice, deviceInfo, e)
}

// 加载内置设备
Expand All @@ -72,7 +72,7 @@ func (e *RuleEngine) LoadBuiltinDevice(deviceInfo *typex.Device) error {
*/
func (e *RuleEngine) LoadDevice(deviceInfo *typex.Device) error {
if config := e.DeviceTypeManager.Find(deviceInfo.Type); config != nil {
return startDevices(config.Device, deviceInfo, e)
return loadDevices(config.Device, deviceInfo, e)
}
return fmt.Errorf("unsupported Device type:%s", deviceInfo.Type)

Expand All @@ -83,7 +83,7 @@ func (e *RuleEngine) LoadDevice(deviceInfo *typex.Device) error {
* 启动一个和RULEX直连的外部设备
*
*/
func startDevices(abstractDevice typex.XDevice, deviceInfo *typex.Device, e *RuleEngine) error {
func loadDevices(abstractDevice typex.XDevice, deviceInfo *typex.Device, e *RuleEngine) error {
// Bind
deviceInfo.Device = abstractDevice
e.SaveDevice(deviceInfo)
Expand All @@ -100,15 +100,15 @@ func startDevices(abstractDevice typex.XDevice, deviceInfo *typex.Device, e *Rul
}

// start
if err := startDevice(abstractDevice, e); err != nil {
glogger.GLogger.Error(err)
e.RemoveDevice(deviceInfo.UUID)
return err
}
// if err := startDevice(abstractDevice, e); err != nil {
// glogger.GLogger.Error(err)
// e.RemoveDevice(deviceInfo.UUID)
// return err
// }
startDevice(abstractDevice, e)
go func(ctx context.Context) {
for {
ticker := time.NewTicker(time.Duration(time.Second * 5))
<-ticker.C
select {
case <-ctx.Done():
{
Expand All @@ -119,7 +119,7 @@ func startDevices(abstractDevice typex.XDevice, deviceInfo *typex.Device, e *Rul
{
}
}

<-ticker.C
if abstractDevice.Details() == nil {
return
}
Expand Down
71 changes: 33 additions & 38 deletions engine/load_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
*
*/
func (e *RuleEngine) LoadUserOutEnd(target typex.XTarget, out *typex.OutEnd) error {
return startTarget(target, out, e)
return loadTarget(target, out, e)
}

/*
Expand All @@ -29,7 +29,7 @@ func (e *RuleEngine) LoadBuiltinOutEnd(out *typex.OutEnd) error {
}
func (e *RuleEngine) LoadOutEnd(out *typex.OutEnd) error {
if config := e.TargetTypeManager.Find(out.Type); config != nil {
return startTarget(config.Target, out, e)
return loadTarget(config.Target, out, e)
}
return errors.New("unsupported target type:" + out.Type.String())
}
Expand All @@ -39,12 +39,10 @@ func (e *RuleEngine) LoadOutEnd(out *typex.OutEnd) error {
// Target life cycle:
//
// Register -> Start -> running/restart cycle
func startTarget(target typex.XTarget, out *typex.OutEnd, e typex.RuleX) error {
//
// 先注册, 如果出问题了直接删除就行
//
func loadTarget(target typex.XTarget, out *typex.OutEnd, e typex.RuleX) error {
// Set sources to inend
out.Target = target
e.SaveOutEnd(out)

// Load config
config := e.GetOutEnd(out.UUID).Config
if config == nil {
Expand All @@ -57,44 +55,33 @@ func startTarget(target typex.XTarget, out *typex.OutEnd, e typex.RuleX) error {
e.RemoveInEnd(out.UUID)
return err
}
// 然后启动资源
ctx, cancelCTX := typex.NewCCTX()
if err := target.Start(typex.CCTX{Ctx: ctx, CancelCTX: cancelCTX}); err != nil {
glogger.GLogger.Error(err)
e.RemoveOutEnd(out.UUID)
return err
}
// Set sources to inend
out.Target = target
// start
// if err := startTarget(target, e); err != nil {
// glogger.GLogger.Error(err)
// e.RemoveOutEnd(out.UUID)
// return err
// }
//
tryIfRestartTarget(target, e, out.UUID)
startTarget(target, e)
go func(ctx context.Context) {
ticker := time.NewTicker(time.Duration(time.Second * 5))

// 5 seconds
//
TICKER:
<-ticker.C
select {
case <-ctx.Done():
{
ticker.Stop()
return
}
default:
{
goto CHECK
for {
select {
case <-ctx.Done():
{
ticker.Stop()
return
}
default:
{
}
}
}
CHECK:
{
<-ticker.C
if target.Details() == nil {
return
}
tryIfRestartTarget(target, e, out.UUID)
goto TICKER
}

}(typex.GCTX)
glogger.GLogger.Infof("Target [%v, %v] load successfully", out.Name, out.UUID)
return nil
Expand All @@ -111,9 +98,17 @@ func tryIfRestartTarget(target typex.XTarget, e typex.RuleX, id string) {
target.Stop()
runtime.Gosched()
runtime.GC()
ctx, cancelCTX := typex.NewCCTX()
target.Start(typex.CCTX{Ctx: ctx, CancelCTX: cancelCTX})
startTarget(target, e)
} else {
target.Details().State = typex.SOURCE_UP
}
}

func startTarget(target typex.XTarget, e typex.RuleX) error {
ctx, cancelCTX := typex.NewCCTX()
if err := target.Start(typex.CCTX{Ctx: ctx, CancelCTX: cancelCTX}); err != nil {
glogger.GLogger.Error("abstractDevice start error:", err)
return err
}
return nil
}
8 changes: 8 additions & 0 deletions plugin/http_server/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ type MOutEnd struct {
Description string
Config string
}
func (md MOutEnd) GetConfig() map[string]interface{} {
result := make(map[string]interface{})
err := json.Unmarshal([]byte(md.Config), &result)
if err != nil {
return map[string]interface{}{}
}
return result
}

type MUser struct {
RulexModel
Expand Down
91 changes: 54 additions & 37 deletions plugin/http_server/outend_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,72 @@ import (
"gopkg.in/square/go-jose.v2/json"
)

func OutEndDetail(c *gin.Context, hs *HttpApiServer, e typex.RuleX) {
func OutEnds(c *gin.Context, hs *HttpApiServer, e typex.RuleX) {
uuid, _ := c.GetQuery("uuid")
Model, err := hs.GetMOutEndWithUUID(uuid)
if uuid == "" {
outends := []typex.OutEnd{}
for _, mOut := range hs.AllMOutEnd() {
outEnd := e.GetOutEnd(mOut.UUID)
if outEnd == nil {
tOut := typex.OutEnd{}
tOut.UUID = mOut.UUID
tOut.Name = mOut.Name
tOut.Type = typex.TargetType(mOut.Type)
tOut.Description = mOut.Description
tOut.Config = mOut.GetConfig()
tOut.State = typex.SOURCE_STOP
outends = append(outends, tOut)
}
if outEnd != nil {
outends = append(outends, *outEnd)
}
}
c.JSON(HTTP_OK, OkWithData(outends))
return
}
mOut, err := hs.GetMOutEndWithUUID(uuid)
if err != nil {
c.JSON(HTTP_OK, Error400(err))
return
}
var OutEnd *typex.OutEnd
if OutEnd = e.GetOutEnd(Model.UUID); OutEnd == nil {
tmpOut := typex.OutEnd{
UUID: Model.UUID,
State: typex.SOURCE_STOP,
Type: typex.TargetType(Model.Type),
Name: Model.Name,
Description: Model.Description,
}
c.JSON(HTTP_OK, OkWithData(tmpOut))
outEnd := e.GetOutEnd(mOut.UUID)
if outEnd == nil {
// 如果内存里面没有就给安排一个死设备
tOut := typex.OutEnd{}
tOut.UUID = mOut.UUID
tOut.Name = mOut.Name
tOut.Type = typex.TargetType(mOut.Type)
tOut.Description = mOut.Description
tOut.Config = mOut.GetConfig()
tOut.State = typex.SOURCE_STOP
c.JSON(HTTP_OK, OkWithData(tOut))
return
}
c.JSON(HTTP_OK, OkWithData(OutEnd))
c.JSON(HTTP_OK, OkWithData(outEnd))
}

// Get all outends
func OutEnds(c *gin.Context, hs *HttpApiServer, e typex.RuleX) {
func OutEndDetail(c *gin.Context, hs *HttpApiServer, e typex.RuleX) {
uuid, _ := c.GetQuery("uuid")
if uuid == "" {
outends := []*typex.OutEnd{}
for _, v := range hs.AllMOutEnd() {
var outEnd *typex.OutEnd
if outEnd = e.GetOutEnd(v.UUID); outEnd == nil {
outEnd.State = typex.SOURCE_STOP
}
if outEnd != nil {
outends = append(outends, outEnd)
}
}
c.JSON(HTTP_OK, OkWithData(outends))
} else {
Model, err := hs.GetMOutEndWithUUID(uuid)
if err != nil {
c.JSON(HTTP_OK, Error400(err))
return
}
var outend *typex.OutEnd
if outend = e.GetOutEnd(Model.UUID); outend == nil {
outend.State = typex.SOURCE_STOP
}
c.JSON(HTTP_OK, OkWithData(outend))
mOut, err := hs.GetMOutEndWithUUID(uuid)
if err != nil {
c.JSON(HTTP_OK, Error400(err))
return
}
outEnd := e.GetOutEnd(mOut.UUID)
if outEnd == nil {
// 如果内存里面没有就给安排一个死设备
tOutEnd := new(typex.OutEnd)
tOutEnd.UUID = mOut.UUID
tOutEnd.Name = mOut.Name
tOutEnd.Type = typex.TargetType(mOut.Type)
tOutEnd.Description = mOut.Description
tOutEnd.Config = mOut.GetConfig()
tOutEnd.State = typex.SOURCE_STOP
c.JSON(HTTP_OK, OkWithData(tOutEnd))
return
}
c.JSON(HTTP_OK, OkWithData(outEnd))
}

// Delete outEnd by UUID
Expand Down
Loading

0 comments on commit 7da19e2

Please sign in to comment.