【修改IBP实体、电路逻辑】

This commit is contained in:
weizhihong 2023-12-06 16:43:29 +08:00
parent 4861c8c248
commit bf9d0ab624
8 changed files with 182 additions and 306 deletions

View File

@ -77,47 +77,20 @@ type SpkElectronic struct {
// SPK继电器元器件组件
var SpkElectronicType = ecs.NewComponentType[SpkElectronic]()
// SPK采集电路吸起、落下接通状态
type SpkCollectState struct {
SPKSX1J_XQ bool
SPKSX3J_XQ bool
SPKSS2J_XQ bool
SPKSS4J_XQ bool
SPKSXPLA_XQ bool
SPKSSPLA_XQ bool
// EMP 电路设备
type EmpDeviceElectronic struct {
EMP_BTNS []*ecs.Entry // 紧急关闭按钮
EMPFA_BTN *ecs.Entry // 复原按钮
EMPD *ecs.Entry // 指示灯
EMPJ *ecs.Entry // 继电器
}
var SpkCollectStateType = ecs.NewComponentType[SpkCollectState]()
// EMP 电路
type EmpElectronic struct {
// 控制区
EMP1_BTN *ecs.Entry
EMP3_BTN *ecs.Entry
EMP5_BTN *ecs.Entry
EMPX_BTN *ecs.Entry
XEMPFA_BTN *ecs.Entry
EMP2_BTN *ecs.Entry
EMP4_BTN *ecs.Entry
EMP6_BTN *ecs.Entry
EMPS_BTN *ecs.Entry
SEMPFA_BTN *ecs.Entry
// 表示区
XEMPJ *ecs.Entry // 继电器
XEMPD *ecs.Entry
SEMPJ *ecs.Entry // 继电器
SEMPD *ecs.Entry
SDA *ecs.Entry // 按钮
QBA *ecs.Entry // 非自复位按钮
Alarm *ecs.Entry // 蜂鸣器
EMPJMap map[string]*EmpDeviceElectronic
SDA *ecs.Entry // 按钮
QBA *ecs.Entry // 非自复位按钮
Alarm *ecs.Entry // 蜂鸣器
}
var EmpElectronicType = ecs.NewComponentType[EmpElectronic]()
// EMP 采集电路吸起、落下接通状态
type EmpCollectState struct {
XEMPJ_XQ bool
SEMPJ_XQ bool
}
var EmpCollectStateType = ecs.NewComponentType[EmpCollectState]()

View File

@ -1,6 +1,9 @@
package entity
import (
"fmt"
"log/slog"
"strings"
"unsafe"
"joylink.club/ecs"
@ -75,135 +78,132 @@ func NewIBPKeyEntity(w ecs.World, uid string, entityMap map[string]*ecs.Entry) *
}
// 构建人员防护实体
func LoadSPKEntity(w ecs.World, entry *ecs.Entry, spkData *repository.IBPRefMap, worldData *component.WorldData) error {
func LoadSPKEntity(w ecs.World, entry *ecs.Entry, datas []repository.IGroupedElectronicComponent, worldData *component.WorldData) error {
if len(datas) == 0 {
return nil
}
entityMap := worldData.EntityMap
spk := &component.SpkElectronic{}
// 按钮组
for _, btn := range spkData.Buttons() {
e := NewButtonEntity(w, btn, entityMap)
switch btn.Code() {
for _, c := range datas {
switch c.Code() {
// 按钮组
case "SPKSXPLA":
spk.SPKSXPLA_BTN = e
spk.SPKSXPLA_BTN = NewButtonEntity(w, c.(*repository.Button), entityMap)
case "SPKSSPLA":
spk.SPKSSPLA_BTN = e
spk.SPKSSPLA_BTN = NewButtonEntity(w, c.(*repository.Button), entityMap)
case "SDA":
spk.SDA = e
}
}
// 钥匙组
for _, key := range spkData.Keys() {
e := NewIBPKeyEntity(w, key.Id(), entityMap)
switch key.Code() {
spk.SDA = NewButtonEntity(w, c.(*repository.Button), entityMap)
// 钥匙组、继电器
case "SPKSX1J":
spk.SPKSX1J_KEY = e
r, ok := c.(*repository.Relay)
if ok {
spk.SPKSX1J = NewRelayEntity(w, r, entityMap)
} else {
spk.SPKSX1J_KEY = NewIBPKeyEntity(w, c.Id(), entityMap)
}
case "SPKSX3J":
spk.SPKSX3J_KEY = e
r, ok := c.(*repository.Relay)
if ok {
spk.SPKSX3J = NewRelayEntity(w, r, entityMap)
} else {
spk.SPKSX3J_KEY = NewIBPKeyEntity(w, c.Id(), entityMap)
}
case "SPKSS2J":
spk.SPKSS2J_KEY = e
r, ok := c.(*repository.Relay)
if ok {
spk.SPKSS2J = NewRelayEntity(w, r, entityMap)
} else {
spk.SPKSS2J_KEY = NewIBPKeyEntity(w, c.Id(), entityMap)
}
case "SPKSS4J":
spk.SPKSS4J_KEY = e
}
}
// 继电器组
for _, relay := range spkData.Relays() {
e := NewRelayEntity(w, relay, entityMap)
switch relay.Code() {
case "SPKSX1J":
spk.SPKSX1J = e
case "SPKSX3J":
spk.SPKSX3J = e
case "SPKSS2J":
spk.SPKSS2J = e
case "SPKSS4J":
spk.SPKSS4J = e
r, ok := c.(*repository.Relay)
if ok {
spk.SPKSS4J = NewRelayEntity(w, r, entityMap)
} else {
spk.SPKSS4J_KEY = NewIBPKeyEntity(w, c.Id(), entityMap)
}
case "SPKSXPLAJ":
spk.SPKSXPLAJ = e
spk.SPKSXPLAJ = NewRelayEntity(w, c.(*repository.Relay), entityMap)
case "SPKSSPLAJ":
spk.SPKSSPLAJ = e
}
}
// 灯组
for _, light := range spkData.Lights() {
e := NewIBPLightEntity(w, light.Id(), entityMap)
switch light.Code() {
spk.SPKSSPLAJ = NewRelayEntity(w, c.(*repository.Relay), entityMap)
// 灯组
case "SPKSX1D":
spk.SPKSX1D = e
spk.SPKSX1D = NewIBPLightEntity(w, c.Id(), entityMap)
case "SPKSX3D":
spk.SPKSX3D = e
spk.SPKSX3D = NewIBPLightEntity(w, c.Id(), entityMap)
case "SPKSS2D":
spk.SPKSS2D = e
spk.SPKSS2D = NewIBPLightEntity(w, c.Id(), entityMap)
case "SPKSS4D":
spk.SPKSS4D = e
spk.SPKSS4D = NewIBPLightEntity(w, c.Id(), entityMap)
}
}
// 绑定组件
entry.AddComponent(component.SpkElectronicType, unsafe.Pointer(spk))
entry.AddComponent(component.SpkCollectStateType, unsafe.Pointer(&component.SpkCollectState{}))
return nil
}
// 构建紧急关闭实体
func LoadEMPEntity(w ecs.World, entry *ecs.Entry, spkData *repository.IBPRefMap, worldData *component.WorldData) error {
func LoadEMPEntity(w ecs.World, entry *ecs.Entry, datas []*repository.ElectronicComponentGroup, worldData *component.WorldData) error {
if len(datas) == 0 {
return nil
}
entityMap := worldData.EntityMap
emp := &component.EmpElectronic{}
// 按钮组
for _, btn := range spkData.Buttons() {
e := NewButtonEntity(w, btn, entityMap)
switch btn.Code() {
case "EMP1":
emp.EMP1_BTN = e
case "EMP3":
emp.EMP3_BTN = e
case "EMP5":
emp.EMP5_BTN = e
case "EMP2":
emp.EMP2_BTN = e
case "EMP4":
emp.EMP4_BTN = e
case "EMP6":
emp.EMP6_BTN = e
case "EMP-X":
emp.EMPX_BTN = e
case "EMP-S":
emp.EMPS_BTN = e
case "XEMPFA":
emp.XEMPFA_BTN = e
case "SEMPFA":
emp.SEMPFA_BTN = e
case "QBA":
emp.QBA = e
case "SDA":
emp.SDA = e
emp := &component.EmpElectronic{EMPJMap: make(map[string]*component.EmpDeviceElectronic)}
for _, g := range datas {
if g.Code() == "EMP" { // 独立设备
for _, c := range g.Components() {
switch c.Code() {
case "QBA":
emp.QBA = NewButtonEntity(w, c.(*repository.Button), entityMap)
case "SDA":
emp.SDA = NewButtonEntity(w, c.(*repository.Button), entityMap)
case "蜂鸣器":
emp.Alarm = NewAlarmEntity(w, c.(*repository.Alarm), entityMap)
default:
r, ok := c.(*repository.Relay)
if ok { // 如果是继电器
d := emp.EMPJMap[r.Code()]
if d == nil {
d = &component.EmpDeviceElectronic{}
}
d.EMPJ = NewRelayEntity(w, r, entityMap)
emp.EMPJMap[r.Code()] = d
} else {
slog.Warn("车站未实现设备[id:%s]逻辑", c.Id())
}
}
}
} else { // 组合设备
d := emp.EMPJMap[g.Code()]
if d == nil {
d = &component.EmpDeviceElectronic{}
}
for _, c := range g.Components() {
b, ok := c.(*repository.Button)
if strings.HasSuffix(c.Code(), "EMPD") {
d.EMPD = NewIBPLightEntity(w, c.Id(), entityMap)
} else if ok && strings.HasSuffix(c.Code(), "EMPFA") {
d.EMPFA_BTN = NewButtonEntity(w, b, entityMap)
} else if ok && strings.HasPrefix(c.Code(), "EMP") {
d.EMP_BTNS = append(d.EMP_BTNS, NewButtonEntity(w, b, entityMap))
} else {
slog.Warn("车站未实现设备[id:%s]逻辑", c.Id())
}
}
emp.EMPJMap[g.Code()] = d
}
}
// 继电器组
for _, relay := range spkData.Relays() {
e := NewRelayEntity(w, relay, entityMap)
switch relay.Code() {
case "XEMPJ":
emp.XEMPJ = e
case "SEMPJ":
emp.SEMPJ = e
}
if emp.Alarm == nil || emp.QBA == nil || emp.SDA == nil {
return fmt.Errorf("车站EMP组合初始化出错,请检查IBP地图组合数据")
}
// 灯组
for _, light := range spkData.Lights() {
e := NewIBPLightEntity(w, light.Id(), entityMap)
switch light.Code() {
case "XEMPD":
emp.XEMPD = e
case "SEMPD":
emp.SEMPD = e
}
}
// 蜂鸣器
for _, alarm := range spkData.Alarms() {
switch alarm.Code() {
case "蜂鸣器":
emp.Alarm = NewAlarmEntity(w, alarm, entityMap)
for code, e := range emp.EMPJMap {
if e.EMPFA_BTN == nil || e.EMPD == nil || len(e.EMP_BTNS) == 0 {
return fmt.Errorf("车站组合[%s]还原按钮未关联,请检查IBP地图组合数据", code)
} else if e.EMPJ == nil {
return fmt.Errorf("车站组合[%s]还原按钮未关联,请检查继电器地图组合数据", code)
}
}
entry.AddComponent(component.EmpElectronicType, unsafe.Pointer(emp))
entry.AddComponent(component.EmpCollectStateType, unsafe.Pointer(&component.EmpCollectState{}))
return nil
}

View File

@ -22,13 +22,14 @@ func LoadStations(w ecs.World) error {
if err != nil {
return err
}
entry := NewStationEntity(w, station.Id(), data)
if station.GetIbpSpk() != nil { // 人员防护
LoadSPKEntity(w, entry, station.GetIbpSpk(), data)
err = LoadSPKEntity(w, entry, station.SpksComponents(), data) // 人员防护
if err != nil {
return err
}
if station.GetIbpEmp() != nil { // 紧急停车
LoadEMPEntity(w, entry, station.GetIbpEmp(), data)
err = LoadEMPEntity(w, entry, station.EmpGroups(), data) // 紧急停车
if err != nil {
return err
}
}
return nil

View File

@ -1,91 +0,0 @@
package repository
type IBP struct {
Spk *IBPRefMap
Emp *IBPRefMap
}
func NewIBP() *IBP {
return &IBP{
Spk: newIBPRefMap(),
Emp: newIBPRefMap(),
}
}
type IBPRefMap struct {
buttonMap map[string]*Button
relayMap map[string]*Relay
alarmMap map[string]*Alarm
lightMap map[string]*Light
keyMap map[string]*Key
}
func newIBPRefMap() *IBPRefMap {
return &IBPRefMap{
buttonMap: make(map[string]*Button),
relayMap: make(map[string]*Relay),
alarmMap: make(map[string]*Alarm),
lightMap: make(map[string]*Light),
keyMap: make(map[string]*Key),
}
}
func (ibp *IBPRefMap) AddButton(btn *Button) {
ibp.buttonMap[btn.Id()] = btn
}
func (ibp *IBPRefMap) AddRelay(relay *Relay) {
ibp.relayMap[relay.Id()] = relay
}
func (ibp *IBPRefMap) AddLight(light *Light) {
ibp.lightMap[light.Id()] = light
}
func (ibp *IBPRefMap) AddAlarm(fmq *Alarm) {
ibp.alarmMap[fmq.Id()] = fmq
}
func (ibp *IBPRefMap) AddKey(key *Key) {
ibp.keyMap[key.Id()] = key
}
func (ibp *IBPRefMap) Buttons() []*Button {
var buttons []*Button
for _, b := range ibp.buttonMap {
buttons = append(buttons, b)
}
return buttons
}
func (ibp *IBPRefMap) Relays() []*Relay {
var relays []*Relay
for _, b := range ibp.relayMap {
relays = append(relays, b)
}
return relays
}
func (ibp *IBPRefMap) Alarms() []*Alarm {
var alarms []*Alarm
for _, b := range ibp.alarmMap {
alarms = append(alarms, b)
}
return alarms
}
func (ibp *IBPRefMap) Lights() []*Light {
var lights []*Light
for _, b := range ibp.lightMap {
lights = append(lights, b)
}
return lights
}
func (ibp *IBPRefMap) Keys() []*Key {
var keys []*Key
for _, b := range ibp.keyMap {
keys = append(keys, b)
}
return keys
}

View File

@ -6,6 +6,7 @@ import (
"log/slog"
"math"
"strconv"
"strings"
"joylink.club/rtsssimulation/repository/model/proto"
"joylink.club/rtsssimulation/util/number"
@ -913,17 +914,18 @@ func buildStationRelationShip(source *proto.Repository, repo *Repository) error
if !ok {
return fmt.Errorf("缺失车站[%s]", protoData.Id)
}
if len(protoData.ElectronicGroup) > 0 {
for _, ref := range protoData.ElectronicGroup {
switch ref.Code {
case "EMP":
bindIbpDevice(repo, ref.Components, station.GetIbpEmp())
case "SPKS":
bindIbpDevice(repo, ref.Components, station.GetIbpSpk())
default:
slog.Warn("未知的车站组合", "组合code", ref.Code)
}
for _, group := range protoData.ElectronicGroup {
if group.Code == "SPKS" {
station.spksComponents = buildRelComponent(repo, group.Components)
} else if group.Code == "EMP" || strings.HasSuffix(group.Code, "EMPJ") {
station.empGroups = append(station.empGroups, &ElectronicComponentGroup{
code: group.Code,
components: buildRelComponent(repo, group.Components),
})
} else {
slog.Warn("未知的车站组合code", group.Code)
}
}
if len(protoData.Deccs) > 0 { // 暂时让逻辑运行起来,后需重构
station.deviceEcc = protoData.Deccs
@ -932,22 +934,23 @@ func buildStationRelationShip(source *proto.Repository, repo *Repository) error
return nil
}
// 将设备绑入IBP
func bindIbpDevice(repo *Repository, comps []*proto.ElectronicComponent, refMap *IBPRefMap) {
func buildRelComponent(repo *Repository, comps []*proto.ElectronicComponent) []IGroupedElectronicComponent {
var components []IGroupedElectronicComponent
for _, data := range comps {
switch data.DeviceType {
case proto.DeviceType_DeviceType_Alarm:
refMap.AddAlarm(repo.alarmMap[data.Id])
components = append(components, repo.alarmMap[data.Id])
case proto.DeviceType_DeviceType_Button:
refMap.AddButton(repo.buttonMap[data.Id])
components = append(components, repo.buttonMap[data.Id])
case proto.DeviceType_DeviceType_Relay:
refMap.AddRelay(repo.relayMap[data.Id])
components = append(components, repo.relayMap[data.Id])
case proto.DeviceType_DeviceType_Light:
refMap.AddLight(repo.lightMap[data.Id])
components = append(components, repo.lightMap[data.Id])
case proto.DeviceType_DeviceType_Key:
refMap.AddKey(repo.keyMap[data.Id])
components = append(components, repo.keyMap[data.Id])
default:
slog.Warn("IBP未绑定【%s】类型设备", data.DeviceType.String())
}
}
return components
}

View File

@ -1,20 +1,21 @@
package repository
import "joylink.club/rtsssimulation/repository/model/proto"
import (
"joylink.club/rtsssimulation/repository/model/proto"
)
type Station struct {
Identity
code string
ibp *IBP
componentGroups []*ElectronicComponentGroup
deviceEcc []*proto.DeviceEcc
code string
empGroups []*ElectronicComponentGroup
spksComponents []IGroupedElectronicComponent
deviceEcc []*proto.DeviceEcc
}
func NewStation(id, code string) *Station {
return &Station{
Identity: identity{id, proto.DeviceType_DeviceType_Station},
code: code,
ibp: NewIBP(),
}
}
@ -22,16 +23,23 @@ func (s *Station) GetCode() string {
return s.code
}
func (s *Station) GetIbpEmp() *IBPRefMap {
return s.ibp.Emp
func (s *Station) EmpGroups() []*ElectronicComponentGroup {
return s.empGroups
}
func (s *Station) GetIbpSpk() *IBPRefMap {
return s.ibp.Spk
func (s *Station) SpksComponents() []IGroupedElectronicComponent {
return s.spksComponents
}
func (s *Station) ComponentGroups() []*ElectronicComponentGroup {
return s.componentGroups
func (s *Station) SpksButtons() []*Button {
var buttons []*Button
for _, c := range s.spksComponents {
b, ok := c.(*Button)
if ok {
buttons = append(buttons, b)
}
}
return buttons
}
func (s *Station) DeviceEcc() []*proto.DeviceEcc {

View File

@ -14,10 +14,7 @@ type IBPSys struct {
// ibp盘系统
func NewIBPSys() *IBPSys {
return &IBPSys{
query: ecs.NewQuery(filter.Contains(
component.SpkElectronicType, component.SpkCollectStateType,
component.EmpElectronicType, component.EmpCollectStateType,
)),
query: ecs.NewQuery(filter.Contains(component.SpkElectronicType, component.EmpElectronicType)),
}
}
@ -27,11 +24,9 @@ func (ibp *IBPSys) Update(w ecs.World) {
spkState := component.SpkElectronicType.Get(entry)
ibp.spkControl(entry, spkState)
ibp.spksState(entry, spkState)
ibp.spkCollect(entry, spkState)
empState := component.EmpElectronicType.Get(entry)
ibp.empControl(entry, empState)
ibp.empState(entry, empState)
ibp.empCollect(entry, empState)
})
}
@ -76,55 +71,41 @@ func (ibp *IBPSys) spksState(entry *ecs.Entry, spkState *component.SpkElectronic
setLightTdVal(spkState.SPKSS4D, sda || !getRelayXqVal(spkState.SPKSS4J))
}
// 人员防护继电器采集电路状态逻辑
func (ibp *IBPSys) spkCollect(entry *ecs.Entry, spkState *component.SpkElectronic) {
collectState := component.SpkCollectStateType.Get(entry)
collectState.SPKSX1J_XQ = getRelayXqVal(spkState.SPKSX1J)
collectState.SPKSX3J_XQ = getRelayXqVal(spkState.SPKSX3J)
collectState.SPKSS2J_XQ = getRelayXqVal(spkState.SPKSS2J)
collectState.SPKSS4J_XQ = getRelayXqVal(spkState.SPKSS4J)
collectState.SPKSXPLA_XQ = getRelayXqVal(spkState.SPKSXPLAJ)
collectState.SPKSSPLA_XQ = getRelayXqVal(spkState.SPKSSPLAJ)
}
// 紧急关闭控制电路
func (ibp *IBPSys) empControl(entry *ecs.Entry, s *component.EmpElectronic) {
xempfab := getIbpBtnVal(s.XEMPFA_BTN)
xempj := component.RelayDriveType.Get(s.XEMPJ)
// xempfab接通或者按钮组接通并且xempj继电器吸起状态
xempj.Td = xempfab || (getRelayXqVal(s.XEMPJ) &&
(!getIbpBtnVal(s.EMP1_BTN)) && (!getIbpBtnVal(s.EMP3_BTN)) &&
(!getIbpBtnVal(s.EMP5_BTN)) && (!getIbpBtnVal(s.EMPX_BTN)))
sempfab := getIbpBtnVal(s.SEMPFA_BTN)
sempj := component.RelayDriveType.Get(s.SEMPJ)
// sempfab接通或者按钮组接通并且sempj继电器吸起状态
sempj.Td = sempfab || (getRelayXqVal(s.SEMPJ) &&
(!getIbpBtnVal(s.EMP2_BTN)) && (!getIbpBtnVal(s.EMP4_BTN)) &&
(!getIbpBtnVal(s.EMP6_BTN)) && (!getIbpBtnVal(s.EMPS_BTN)))
for _, e := range s.EMPJMap {
empfab := getIbpBtnVal(e.EMPFA_BTN)
empj := component.RelayDriveType.Get(e.EMPJ)
// empfab接通或者按钮组接通并且empj继电器吸起状态
empBtnStatus := true
for _, b := range e.EMP_BTNS {
if !empBtnStatus {
break
}
empBtnStatus = !getIbpBtnVal(b)
}
empj.Td = empfab || (getRelayXqVal(e.EMPJ) && empBtnStatus)
}
}
// 紧急关闭表示电路
func (ibp *IBPSys) empState(entry *ecs.Entry, s *component.EmpElectronic) {
sda := getIbpBtnVal(s.SDA)
xempj := getRelayXqVal(s.XEMPJ)
setLightTdVal(s.XEMPD, sda || !xempj)
sempj := getRelayXqVal(s.SEMPJ)
setLightTdVal(s.SEMPD, sda || !sempj)
xq, lx := true, false
for _, e := range s.EMPJMap {
empj := getRelayXqVal(e.EMPJ)
setLightTdVal(e.EMPD, sda || !empj)
xq = xq && empj
lx = lx || !empj
}
qba := getIbpBtnVal(s.QBA)
if qba {
setAlarmTdVal(s.Alarm, xempj && sempj)
setAlarmTdVal(s.Alarm, xq)
} else {
setAlarmTdVal(s.Alarm, (!xempj) || (!sempj))
setAlarmTdVal(s.Alarm, lx)
}
}
// 紧急关闭继电器采集电路状态逻辑
func (ibp *IBPSys) empCollect(entry *ecs.Entry, s *component.EmpElectronic) {
collectState := component.EmpCollectStateType.Get(entry)
collectState.XEMPJ_XQ = getRelayXqVal(s.XEMPJ)
collectState.SEMPJ_XQ = getRelayXqVal(s.SEMPJ)
}
// 获取按钮状态
func getIbpBtnVal(entry *ecs.Entry) bool {
btn := component.BitStateType.Get(entry)

View File

@ -1,11 +1,12 @@
package circuit_sys
import (
"strings"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"strings"
)
type PsdSys struct {
@ -205,7 +206,7 @@ func (p *PsdSys) exciteMPLJ(world ecs.World, circuit *component.PsdCircuit, uid
} else {
return
}
for _, button := range station.GetIbpSpk().Buttons() {
for _, button := range station.SpksButtons() {
if button.Code() != buttonCode {
return
}