diff --git a/.golangci.yaml b/.golangci.yaml index 2955e35..f7af91c 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -3,18 +3,16 @@ linters: disable: - exportloopref # Deprecated - execinquery # Deprecated + - exhaustruct # Very noisy, hard to disable when want zero values + - forcetypeassert # If its wrong, we want to know + - nlreturn # Not desired - gci - gocritic - - gofumpt - - forbidigo - - godot - godox - gomnd - - ireturn - - exhaustruct + - gochecknoglobals + - gosec - mnd - - forcetypeassert - - nlreturn - nonamedreturns - paralleltest - predeclared @@ -23,17 +21,19 @@ linters: - varnamelen - wrapcheck - wsl - - err113 - - stylecheck - - gochecknoglobals - depguard - cyclop - - whitespace - revive - - goimports - - gosec - - protogetter - funlen - unparam - exhaustive - inamedparam + +linters-settings: + ireturn: + allow: + - tea.Model + - error + - stdlib + - empty + - generic diff --git a/cmd/monitor/common.go b/cmd/monitor/common.go index e76b406..a9e6808 100644 --- a/cmd/monitor/common.go +++ b/cmd/monitor/common.go @@ -2,12 +2,18 @@ package main import ( "errors" + "fmt" "github.com/DownerCase/ecal-go/ecal/monitoring" "github.com/charmbracelet/bubbles/table" tea "github.com/charmbracelet/bubbletea" ) +var ( + errNoTopic = errors.New("no topic") + errEmptyTable = errors.New("table empty") +) + func NewTable(columns []table.Column) table.Model { return table.New( table.WithHeight(8), @@ -46,12 +52,12 @@ func getTopicMonitoring(topicType topicType) []monitoring.TopicMon { return nil } -func getTopicFromId(topicType topicType, id string) (monitoring.TopicMon, error) { - topic_list := getTopicMonitoring(topicType) - for _, topic := range topic_list { - if topic.Topic_id == id { +func getTopicFromID(topicType topicType, id string) (monitoring.TopicMon, error) { + topicList := getTopicMonitoring(topicType) + for _, topic := range topicList { + if topic.TopicID == id { return topic, nil } } - return monitoring.TopicMon{}, errors.New("Unable to find topic") + return monitoring.TopicMon{}, fmt.Errorf("[getTopicFromId]: %w", errNoTopic) } diff --git a/cmd/monitor/config_page.go b/cmd/monitor/config_page.go index 0efa91a..a81e500 100644 --- a/cmd/monitor/config_page.go +++ b/cmd/monitor/config_page.go @@ -6,26 +6,26 @@ import ( tea "github.com/charmbracelet/bubbletea" ) -type model_config struct { +type modelConfig struct { viewport viewport.Model } -func NewConfigModel() *model_config { +func NewConfigModel() *modelConfig { viewport := viewport.New(85, 10) viewport.SetContent(ecal.GetConfig()) viewport.Style = baseStyle - return &model_config{ + return &modelConfig{ viewport: viewport, } } -func (m *model_config) Refresh() {} +func (m *modelConfig) Refresh() {} -func (m *model_config) Update(msg tea.Msg) (cmd tea.Cmd) { +func (m *modelConfig) Update(msg tea.Msg) (cmd tea.Cmd) { m.viewport, cmd = m.viewport.Update(msg) return cmd } -func (m *model_config) View() string { +func (m *modelConfig) View() string { return m.viewport.View() } diff --git a/cmd/monitor/hosts_list.go b/cmd/monitor/hosts_list.go index 9423bfc..00a04f1 100644 --- a/cmd/monitor/hosts_list.go +++ b/cmd/monitor/hosts_list.go @@ -8,11 +8,11 @@ import ( tea "github.com/charmbracelet/bubbletea" ) -type model_hosts struct { +type modelHosts struct { table table.Model } -func NewHostsModel() *model_hosts { +func NewHostsModel() *modelHosts { columns := []table.Column{ {Title: "Host", Width: 28}, {Title: "Processes", Width: 9}, @@ -22,21 +22,21 @@ func NewHostsModel() *model_hosts { {Title: "Clients", Width: 7}, } - return &model_hosts{ + return &modelHosts{ table: NewTable(columns), } } -func (m *model_hosts) Update(msg tea.Msg) tea.Cmd { +func (m *modelHosts) Update(msg tea.Msg) tea.Cmd { m.updateTable(nil) return nil } -func (m *model_hosts) View() string { +func (m *modelHosts) View() string { return baseStyle.Render(m.table.View()) + "\n" + m.table.HelpView() } -func (m *model_hosts) Refresh() { +func (m *modelHosts) Refresh() { m.updateTable(nil) } @@ -48,7 +48,7 @@ type hostInfo struct { Processes int } -func (m *model_hosts) updateTable(msg tea.Msg) { +func (m *modelHosts) updateTable(msg tea.Msg) { mon := monitoring.GetMonitoring(monitoring.MonitorAll) hosts := make(map[string]hostInfo) @@ -73,9 +73,9 @@ func (m *model_hosts) updateTable(msg tea.Msg) { hosts[server.HostName] = host } for _, proc := range mon.Processes { - host := hosts[proc.Host_name] + host := hosts[proc.HostName] host.Processes += 1 - hosts[proc.Host_name] = host + hosts[proc.HostName] = host } m.table.SetRows(hostsToRows(hosts)) diff --git a/cmd/monitor/log_list.go b/cmd/monitor/log_list.go index 268749e..364277c 100644 --- a/cmd/monitor/log_list.go +++ b/cmd/monitor/log_list.go @@ -13,8 +13,8 @@ import ( type LoggingPage int const ( - subpage_logging_main LoggingPage = iota - subpage_logging_detailed + subpageLoggingMain LoggingPage = iota + subpageLoggingDetailed ) type logsKeyMap struct { @@ -22,11 +22,11 @@ type logsKeyMap struct { Clear key.Binding } -type model_logs struct { - table_logs table.Model - subpage LoggingPage - help help.Model - keymap logsKeyMap +type modelLogs struct { + table table.Model + subpage LoggingPage + help help.Model + keymap logsKeyMap // model_detailed } @@ -48,7 +48,7 @@ func (km logsKeyMap) FullHelp() [][]key.Binding { return append([][]key.Binding{{km.Clear}}, km.KeyMap.FullHelp()...) } -func NewLogsModel() *model_logs { +func NewLogsModel() *modelLogs { columns := []table.Column{ {Title: "Time", Width: 10}, {Title: "Level", Width: 6}, @@ -56,70 +56,70 @@ func NewLogsModel() *model_logs { {Title: "Message", Width: 46}, } - return &model_logs{ - table_logs: NewTable(columns), - subpage: subpage_logging_main, - help: help.New(), - keymap: newLogsKeyMap(), + return &modelLogs{ + table: NewTable(columns), + subpage: subpageLoggingMain, + help: help.New(), + keymap: newLogsKeyMap(), } } -func (m *model_logs) Update(msg tea.Msg) tea.Cmd { +func (m *modelLogs) Update(msg tea.Msg) tea.Cmd { var cmd tea.Cmd switch m.subpage { - case subpage_logging_main: + case subpageLoggingMain: switch msg := msg.(type) { case tea.KeyMsg: switch { case key.Matches(msg, m.keymap.Clear): - m.table_logs.SetRows([]table.Row{}) + m.table.SetRows([]table.Row{}) m.updateTable(nil) default: m.updateTable(msg) } } - case subpage_logging_detailed: + case subpageLoggingDetailed: // cmd = m.model_detailed.Update(msg) } return cmd } -func (m *model_logs) View() string { +func (m *modelLogs) View() string { switch m.subpage { - case subpage_logging_main: - return baseStyle.Render(m.table_logs.View()) + "\n" + m.help.View(m.keymap) - case subpage_logging_detailed: + case subpageLoggingMain: + return baseStyle.Render(m.table.View()) + "\n" + m.help.View(m.keymap) + case subpageLoggingDetailed: // return m.model_detailed.View() } return "Invalid page" } -func (m *model_logs) Refresh() { +func (m *modelLogs) Refresh() { switch m.subpage { - case subpage_logging_detailed: + case subpageLoggingDetailed: // m.model_detailed.Refresh() default: m.updateTable(nil) } } -func (m *model_logs) updateTable(msg tea.Msg) { +func (m *modelLogs) updateTable(msg tea.Msg) { rows := []table.Row{} logs := logging.GetLogging().Messages for _, log := range logs { rows = append(rows, logToRow(log)) } - m.table_logs.SetRows(append(m.table_logs.Rows(), rows...)) - m.table_logs, _ = m.table_logs.Update(msg) + m.table.SetRows(append(m.table.Rows(), rows...)) + m.table, _ = m.table.Update(msg) } func logToRow(log logging.LogMessage) table.Row { return []string{ time.UnixMicro(log.Time).Format(time.TimeOnly), log.Level.String(), - log.Unit_name, + log.UnitName, log.Content, } } diff --git a/cmd/monitor/main.go b/cmd/monitor/main.go index b4ccc4c..9bb0e7e 100644 --- a/cmd/monitor/main.go +++ b/cmd/monitor/main.go @@ -9,7 +9,7 @@ func main() { ecal.Initialize( ecal.NewConfig(ecal.WithLoggingReceive(true)), "Go Monitor", - ecal.C_Subscriber|ecal.C_Monitoring|ecal.C_Logging|ecal.C_Service, + ecal.CSubscriber|ecal.CMonitoring|ecal.CLogging|ecal.CService, ) defer ecal.Finalize() // Shutdown eCAL at the end of the program logging.SetConsoleFilter(logging.LevelAll) diff --git a/cmd/monitor/page_processes.go b/cmd/monitor/page_processes.go index c52f5e3..e76913e 100644 --- a/cmd/monitor/page_processes.go +++ b/cmd/monitor/page_processes.go @@ -7,66 +7,66 @@ import ( type ProcessesPage int const ( - subpage_proc_main ProcessesPage = iota - subpage_proc_detailed + subpageProcMain ProcessesPage = iota + subpageProcDetailed ) -type model_processes struct { +type modelProcesses struct { subpage ProcessesPage pages map[ProcessesPage]PageModel NavKeys NavKeyMap } -func NewProcessesModel() *model_processes { - return (&model_processes{ - subpage: subpage_proc_main, +func NewProcessesModel() *modelProcesses { + return (&modelProcesses{ + subpage: subpageProcMain, pages: map[ProcessesPage]PageModel{ - subpage_proc_main: NewProcessesMainModel(), - subpage_proc_detailed: NewDetailedProcessModel(), + subpageProcMain: NewProcessesMainModel(), + subpageProcDetailed: NewDetailedProcessModel(), }, NavKeys: make(NavKeyMap), }).Init() } -func (m *model_processes) Init() *model_processes { +func (m *modelProcesses) Init() *modelProcesses { m.NavKeys["esc"] = func() tea.Cmd { m.navUp(); return nil } m.NavKeys["enter"] = func() tea.Cmd { m.navDown(); return nil } return m } -func (m *model_processes) Update(msg tea.Msg) tea.Cmd { +func (m *modelProcesses) Update(msg tea.Msg) tea.Cmd { if cmd, navigated := m.NavKeys.HandleMsg(msg); navigated { return cmd } return m.pages[m.subpage].Update(msg) } -func (m *model_processes) View() string { +func (m *modelProcesses) View() string { return m.pages[m.subpage].View() } -func (m *model_processes) Refresh() { +func (m *modelProcesses) Refresh() { m.pages[m.subpage].Refresh() } -func (m *model_processes) navDown() { +func (m *modelProcesses) navDown() { switch m.subpage { - case subpage_proc_main: - main := m.pages[subpage_proc_main].(*model_processes_main) + case subpageProcMain: + main := m.pages[subpageProcMain].(*modelProcessesMain) pid, err := main.getSelectedPid() if err != nil { return // Can't transition } - detailed := m.pages[subpage_proc_detailed].(*model_process_detailed) + detailed := m.pages[subpageProcDetailed].(*modelProcessDetailed) detailed.Pid = pid - m.subpage = subpage_proc_detailed + m.subpage = subpageProcDetailed detailed.Refresh() } } -func (m *model_processes) navUp() { +func (m *modelProcesses) navUp() { switch m.subpage { - case subpage_proc_detailed: - m.subpage = subpage_proc_main + case subpageProcDetailed: + m.subpage = subpageProcMain } } diff --git a/cmd/monitor/page_processes_detailed.go b/cmd/monitor/page_processes_detailed.go index 8a331b5..9351e54 100644 --- a/cmd/monitor/page_processes_detailed.go +++ b/cmd/monitor/page_processes_detailed.go @@ -10,45 +10,45 @@ import ( tea "github.com/charmbracelet/bubbletea" ) -type model_process_detailed struct { - table_detailed table.Model - Pid int32 +type modelProcessDetailed struct { + table table.Model + Pid int32 } -func NewDetailedProcessModel() *model_process_detailed { +func NewDetailedProcessModel() *modelProcessDetailed { cols := []table.Column{ {Title: "", Width: 10}, {Title: "", Width: 67}, } - return &model_process_detailed{ - table_detailed: NewTable(cols), - Pid: 0, + return &modelProcessDetailed{ + table: NewTable(cols), + Pid: 0, } } -func (m *model_process_detailed) Init() tea.Cmd { +func (m *modelProcessDetailed) Init() tea.Cmd { return nil } -func (m *model_process_detailed) Update(msg tea.Msg) tea.Cmd { +func (m *modelProcessDetailed) Update(msg tea.Msg) tea.Cmd { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: - m.table_detailed, cmd = m.table_detailed.Update(msg) + m.table, cmd = m.table.Update(msg) } return cmd } -func (m *model_process_detailed) View() string { - return baseStyle.Render(m.table_detailed.View()) + "\n" + m.table_detailed.HelpView() +func (m *modelProcessDetailed) View() string { + return baseStyle.Render(m.table.View()) + "\n" + m.table.HelpView() } -func (m *model_process_detailed) Refresh() { +func (m *modelProcessDetailed) Refresh() { m.updateDetailedTable(nil) } -func (m *model_process_detailed) updateDetailedTable(msg tea.Msg) { +func (m *modelProcessDetailed) updateDetailedTable(msg tea.Msg) { mon := monitoring.GetMonitoring(monitoring.MonitorProcess) var p monitoring.ProcessMon @@ -58,18 +58,18 @@ func (m *model_process_detailed) updateDetailedTable(msg tea.Msg) { break } } - m.table_detailed.Columns()[0].Title = strconv.FormatInt(int64(p.Pid), 10) - m.table_detailed.Columns()[1].Title = p.Process_name - health := fmt.Sprintf("%s %v", p.State_severity.String(), p.State_severity_level) + m.table.Columns()[0].Title = strconv.FormatInt(int64(p.Pid), 10) + m.table.Columns()[1].Title = p.ProcessName + health := fmt.Sprintf("%s %v", p.StateSeverity.String(), p.StateSeverityLevel) rows := []table.Row{ - {"Unit", p.Unit_name}, - {health, p.State_info}, - {"Parameters", p.Process_parameters}, - {"Host", fmt.Sprintf("%s (Group: %s)", p.Host_name, p.Host_group)}, - {"Components", p.Components_initialized}, - {"Runtime", p.Runtime_version}, - {"Tick", strconv.FormatInt(int64(p.Registration_clock), 10)}, + {"Unit", p.UnitName}, + {health, p.StateInfo}, + {"Parameters", p.ProcessParameters}, + {"Host", fmt.Sprintf("%s (Group: %s)", p.HostName, p.HostGroup)}, + {"Components", p.ComponentsInitialized}, + {"Runtime", p.RuntimeVersion}, + {"Tick", strconv.FormatInt(int64(p.RegistrationClock), 10)}, } - m.table_detailed.SetRows(rows) - m.table_detailed, _ = m.table_detailed.Update(msg) + m.table.SetRows(rows) + m.table, _ = m.table.Update(msg) } diff --git a/cmd/monitor/page_processes_main.go b/cmd/monitor/page_processes_main.go index f548f30..10c60b4 100644 --- a/cmd/monitor/page_processes_main.go +++ b/cmd/monitor/page_processes_main.go @@ -1,7 +1,6 @@ package main import ( - "errors" "path/filepath" "strconv" @@ -10,11 +9,11 @@ import ( tea "github.com/charmbracelet/bubbletea" ) -type model_processes_main struct { - table_processes table.Model +type modelProcessesMain struct { + table table.Model } -func NewProcessesMainModel() *model_processes_main { +func NewProcessesMainModel() *modelProcessesMain { columns := []table.Column{ {Title: "PID", Width: 7}, {Title: "Name", Width: 33}, @@ -23,49 +22,49 @@ func NewProcessesMainModel() *model_processes_main { {Title: "Tick", Width: 4}, } - return &model_processes_main{ - table_processes: NewTable(columns), + return &modelProcessesMain{ + table: NewTable(columns), } } -func (m *model_processes_main) Update(msg tea.Msg) tea.Cmd { +func (m *modelProcessesMain) Update(msg tea.Msg) tea.Cmd { return m.updateTable(msg) } -func (m *model_processes_main) View() string { - return baseStyle.Render(m.table_processes.View()) + "\n" + m.table_processes.HelpView() +func (m *modelProcessesMain) View() string { + return baseStyle.Render(m.table.View()) + "\n" + m.table.HelpView() } -func (m *model_processes_main) Refresh() { +func (m *modelProcessesMain) Refresh() { m.updateTable(nil) } -func (m *model_processes_main) getSelectedPid() (int32, error) { - row := m.table_processes.SelectedRow() +func (m *modelProcessesMain) getSelectedPid() (int32, error) { + row := m.table.SelectedRow() if row == nil { - return 0, errors.New("No processes") + return 0, errEmptyTable } pid, err := strconv.ParseInt(row[0], 10, 64) return int32(pid), err } -func (m *model_processes_main) updateTable(msg tea.Msg) (cmd tea.Cmd) { +func (m *modelProcessesMain) updateTable(msg tea.Msg) (cmd tea.Cmd) { rows := []table.Row{} mon := monitoring.GetMonitoring(monitoring.MonitorProcess) for _, proc := range mon.Processes { rows = append(rows, procToRow(proc)) } - m.table_processes.SetRows(rows) - m.table_processes, cmd = m.table_processes.Update(msg) + m.table.SetRows(rows) + m.table, cmd = m.table.Update(msg) return } func procToRow(proc monitoring.ProcessMon) table.Row { return []string{ strconv.FormatInt(int64(proc.Pid), 10), - filepath.Base(proc.Process_name), - proc.State_severity.String(), - proc.State_info, - strconv.FormatInt(int64(proc.Registration_clock), 10), + filepath.Base(proc.ProcessName), + proc.StateSeverity.String(), + proc.StateInfo, + strconv.FormatInt(int64(proc.RegistrationClock), 10), } } diff --git a/cmd/monitor/page_services.go b/cmd/monitor/page_services.go index 53d1be8..ca808d6 100644 --- a/cmd/monitor/page_services.go +++ b/cmd/monitor/page_services.go @@ -7,68 +7,67 @@ import ( type ServicesPage int const ( - subpage_services_main ServicesPage = iota - subpage_services_detailed + subpageServicesMain ServicesPage = iota + subpageServicesDetailed ) -type model_services struct { +type modelServices struct { subpage ServicesPage pages map[ServicesPage]PageModel NavKeys NavKeyMap } -func NewServicesModel() *model_services { - return (&model_services{ - subpage: subpage_services_main, +func NewServicesModel() *modelServices { + return (&modelServices{ + subpage: subpageServicesMain, pages: map[ServicesPage]PageModel{ - subpage_services_main: NewServicesMainModel(), - subpage_services_detailed: NewDetailedServiceModel(), + subpageServicesMain: NewServicesMainModel(), + subpageServicesDetailed: NewDetailedServiceModel(), }, NavKeys: make(NavKeyMap), }).Init() } -func (m *model_services) Refresh() { +func (m *modelServices) Refresh() { m.pages[m.subpage].Refresh() } -func (m *model_services) Init() *model_services { +func (m *modelServices) Init() *modelServices { m.NavKeys["esc"] = func() tea.Cmd { m.navUp(); return nil } m.NavKeys["enter"] = func() tea.Cmd { m.navDown(); return nil } return m } -func (m *model_services) Update(msg tea.Msg) tea.Cmd { +func (m *modelServices) Update(msg tea.Msg) tea.Cmd { if cmd, navigated := m.NavKeys.HandleMsg(msg); navigated { return cmd } return m.pages[m.subpage].Update(msg) } -func (m *model_services) View() string { +func (m *modelServices) View() string { return m.pages[m.subpage].View() } -func (m *model_services) navDown() { +func (m *modelServices) navDown() { switch m.subpage { - case subpage_services_main: - main := m.pages[subpage_services_main].(*model_services_main) - id, isServer, err := main.GetSelectedId() + case subpageServicesMain: + main := m.pages[subpageServicesMain].(*modelServicesMain) + id, isServer, err := main.GetSelectedID() if err != nil { return // Can't transition } - detailed := m.pages[subpage_services_detailed].(*model_service_detailed) + detailed := m.pages[subpageServicesDetailed].(*modelServiceDetailed) detailed.IsServer = isServer - detailed.Id = id + detailed.ID = id detailed.Refresh() - m.subpage = subpage_services_detailed - + m.subpage = subpageServicesDetailed } } -func (m *model_services) navUp() { +func (m *modelServices) navUp() { switch m.subpage { - case subpage_services_detailed: - m.subpage = subpage_services_main + case subpageServicesDetailed: + m.subpage = subpageServicesMain } } diff --git a/cmd/monitor/page_services_detailed.go b/cmd/monitor/page_services_detailed.go index f7734f1..5e886bd 100644 --- a/cmd/monitor/page_services_detailed.go +++ b/cmd/monitor/page_services_detailed.go @@ -10,46 +10,46 @@ import ( tea "github.com/charmbracelet/bubbletea" ) -type model_service_detailed struct { - table_detailed table.Model - Id string - IsServer bool +type modelServiceDetailed struct { + table table.Model + ID string + IsServer bool } -func NewDetailedServiceModel() *model_service_detailed { +func NewDetailedServiceModel() *modelServiceDetailed { cols := []table.Column{ {Title: "", Width: 10}, {Title: "", Width: 67}, } - return &model_service_detailed{ - table_detailed: NewTable(cols), - Id: "", + return &modelServiceDetailed{ + table: NewTable(cols), + ID: "", } } -func (m *model_service_detailed) Update(msg tea.Msg) tea.Cmd { +func (m *modelServiceDetailed) Update(msg tea.Msg) tea.Cmd { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: - m.table_detailed, cmd = m.table_detailed.Update(msg) + m.table, cmd = m.table.Update(msg) } return cmd } -func (m *model_service_detailed) View() string { - return baseStyle.Render(m.table_detailed.View()) + "\n" + m.table_detailed.HelpView() +func (m *modelServiceDetailed) View() string { + return baseStyle.Render(m.table.View()) + "\n" + m.table.HelpView() } -func (m *model_service_detailed) Refresh() { +func (m *modelServiceDetailed) Refresh() { m.updateDetailedTable(nil) } -func (m *model_service_detailed) updateDetailedTable(msg tea.Msg) { +func (m *modelServiceDetailed) updateDetailedTable(msg tea.Msg) { if m.IsServer { mon := monitoring.GetMonitoring(monitoring.MonitorServer) for _, s := range mon.Servers { - if s.Id == m.Id { + if s.ID == m.ID { m.updateTableServer(&s) break } @@ -57,31 +57,31 @@ func (m *model_service_detailed) updateDetailedTable(msg tea.Msg) { } else { mon := monitoring.GetMonitoring(monitoring.MonitorClient) for _, c := range mon.Clients { - if c.Id == m.Id { + if c.ID == m.ID { m.updateTableClient(&c) break } } } - m.table_detailed, _ = m.table_detailed.Update(msg) + m.table, _ = m.table.Update(msg) } -func (m *model_service_detailed) updateTableClient(c *monitoring.ClientMon) { - m.table_detailed.Columns()[0].Title = "Client" - m.table_detailed.Columns()[1].Title = c.Process +func (m *modelServiceDetailed) updateTableClient(c *monitoring.ClientMon) { + m.table.Columns()[0].Title = "Client" + m.table.Columns()[1].Title = c.Process baseRows := m.getBaseRows(c.ServiceBase) - m.table_detailed.SetRows(append(baseRows, getMethodRows(c.ServiceBase)...)) + m.table.SetRows(append(baseRows, getMethodRows(c.ServiceBase)...)) } -func (m *model_service_detailed) updateTableServer(s *monitoring.ServerMon) { - m.table_detailed.Columns()[0].Title = "Server" - m.table_detailed.Columns()[1].Title = s.Process +func (m *modelServiceDetailed) updateTableServer(s *monitoring.ServerMon) { + m.table.Columns()[0].Title = "Server" + m.table.Columns()[1].Title = s.Process baseRows := m.getBaseRows(s.ServiceBase) baseRows = append(baseRows, table.Row{"TCP Port", fmt.Sprintf("V0: %v, V1: %v", s.PortV0, s.PortV1)}) - m.table_detailed.SetRows(append(baseRows, getMethodRows(s.ServiceBase)...)) + m.table.SetRows(append(baseRows, getMethodRows(s.ServiceBase)...)) } -func (m *model_service_detailed) getBaseRows(b monitoring.ServiceBase) []table.Row { +func (m *modelServiceDetailed) getBaseRows(b monitoring.ServiceBase) []table.Row { return []table.Row{ {"Unit", fmt.Sprintf("%s (Protocol V%v)", b.Unit, b.ProtocolVersion)}, {"Pid", fmt.Sprintf("%v (%s)", b.Pid, b.HostName)}, diff --git a/cmd/monitor/page_services_main.go b/cmd/monitor/page_services_main.go index a1df56f..c3c24af 100644 --- a/cmd/monitor/page_services_main.go +++ b/cmd/monitor/page_services_main.go @@ -1,7 +1,6 @@ package main import ( - "errors" "strconv" "github.com/DownerCase/ecal-go/ecal/monitoring" @@ -9,11 +8,11 @@ import ( tea "github.com/charmbracelet/bubbletea" ) -type model_services_main struct { - table_services table.Model +type modelServicesMain struct { + table table.Model } -func NewServicesMainModel() *model_services_main { +func NewServicesMainModel() *modelServicesMain { cols := []table.Column{ {Title: "ID", Width: 0}, // Hidden unique ID {Title: "T", Width: 1}, // Type (Client/Server) @@ -22,32 +21,32 @@ func NewServicesMainModel() *model_services_main { {Title: "Tick", Width: 4}, } - return &model_services_main{ - table_services: NewTable(cols), + return &modelServicesMain{ + table: NewTable(cols), } } -func (m *model_services_main) Refresh() { +func (m *modelServicesMain) Refresh() { m.updateTable(nil) } -func (m *model_services_main) Update(msg tea.Msg) tea.Cmd { +func (m *modelServicesMain) Update(msg tea.Msg) tea.Cmd { return m.updateTable(msg) } -func (m *model_services_main) View() string { - return baseStyle.Render(m.table_services.View()) + "\n" + m.table_services.HelpView() +func (m *modelServicesMain) View() string { + return baseStyle.Render(m.table.View()) + "\n" + m.table.HelpView() } -func (m *model_services_main) GetSelectedId() (string, bool, error) { - row := m.table_services.SelectedRow() +func (m *modelServicesMain) GetSelectedID() (string, bool, error) { + row := m.table.SelectedRow() if row == nil { - return "", false, errors.New("No processes") + return "", false, errEmptyTable } return row[0], row[1] == "S", nil } -func (m *model_services_main) updateTable(msg tea.Msg) (cmd tea.Cmd) { +func (m *modelServicesMain) updateTable(msg tea.Msg) (cmd tea.Cmd) { rows := []table.Row{} mon := monitoring.GetMonitoring(monitoring.MonitorClient | monitoring.MonitorServer) for _, client := range mon.Clients { @@ -56,8 +55,8 @@ func (m *model_services_main) updateTable(msg tea.Msg) (cmd tea.Cmd) { for _, server := range mon.Servers { rows = append(rows, serverToRow(server)) } - m.table_services.SetRows(rows) - m.table_services, cmd = m.table_services.Update(msg) + m.table.SetRows(rows) + m.table, cmd = m.table.Update(msg) return } @@ -71,14 +70,14 @@ func serviceToRow(service monitoring.ServiceBase) table.Row { func clientToRow(client monitoring.ClientMon) table.Row { return append( - []string{client.Id, "C"}, + []string{client.ID, "C"}, serviceToRow(client.ServiceBase)..., ) } func serverToRow(server monitoring.ServerMon) table.Row { return append( - []string{server.Id, "S"}, + []string{server.ID, "S"}, serviceToRow(server.ServiceBase)..., ) } diff --git a/cmd/monitor/page_topics.go b/cmd/monitor/page_topics.go index 1b59b47..54cbfe6 100644 --- a/cmd/monitor/page_topics.go +++ b/cmd/monitor/page_topics.go @@ -7,83 +7,83 @@ import ( type TopicsPage int const ( - subpage_topic_main TopicsPage = iota - subpage_topic_detailed - subpage_topic_messages // TODO: Not implemented + subpageTopicMain TopicsPage = iota + subpageTopicDetailed + subpageTopicMessages // TODO: Not implemented ) -type model_topics struct { +type modelTopics struct { subpage TopicsPage pages map[TopicsPage]PageModel NavKeys NavKeyMap } -func NewTopicsModel() *model_topics { - return (&model_topics{ - subpage: subpage_topic_main, +func NewTopicsModel() *modelTopics { + return (&modelTopics{ + subpage: subpageTopicMain, pages: map[TopicsPage]PageModel{ - subpage_topic_main: NewTopicsMainModel(), - subpage_topic_detailed: NewDetailedModel(), - subpage_topic_messages: NewTopicsMessagesModel(), + subpageTopicMain: NewTopicsMainModel(), + subpageTopicDetailed: NewDetailedModel(), + subpageTopicMessages: NewTopicsMessagesModel(), }, NavKeys: make(NavKeyMap), }).Init() } -func (m *model_topics) navDown() { +func (m *modelTopics) navDown() { switch m.subpage { - case subpage_topic_main: - main_model := m.pages[subpage_topic_main].(*model_topics_main) - topic, topicType, err := main_model.GetSelectedId() + case subpageTopicMain: + mainModel := m.pages[subpageTopicMain].(*modelTopicsMain) + topic, topicType, err := mainModel.GetSelectedID() if err != nil { return // Don't' transition } - detailed := m.pages[subpage_topic_detailed].(*model_topic_detailed) + detailed := m.pages[subpageTopicDetailed].(*modelTopicDetailed) detailed.ShowTopic(topic, topicType) - m.subpage = subpage_topic_detailed + m.subpage = subpageTopicDetailed } } -func (m *model_topics) navUp() { +func (m *modelTopics) navUp() { switch m.subpage { default: - m.subpage = subpage_topic_main + m.subpage = subpageTopicMain } } -func (m *model_topics) navMessages() tea.Cmd { - if m.subpage != subpage_topic_main { +func (m *modelTopics) navMessages() tea.Cmd { + if m.subpage != subpageTopicMain { return nil } - main_model := m.pages[subpage_topic_main].(*model_topics_main) - topic, topicType, err := main_model.GetSelectedId() + mainModel := m.pages[subpageTopicMain].(*modelTopicsMain) + topic, topicType, err := mainModel.GetSelectedID() if err != nil { return nil // Don't' transition } - messages_model := m.pages[subpage_topic_messages].(*model_topic_messages) - messages_model.ShowTopic(topic, topicType) - m.subpage = subpage_topic_messages - return messages_model.Init() + messagesModel := m.pages[subpageTopicMessages].(*modelTopicMessages) + messagesModel.ShowTopic(topic, topicType) + m.subpage = subpageTopicMessages + return messagesModel.Init() } -func (m *model_topics) Refresh() { +func (m *modelTopics) Refresh() { m.pages[m.subpage].Refresh() } -func (m *model_topics) Init() *model_topics { +func (m *modelTopics) Init() *modelTopics { m.NavKeys["esc"] = func() tea.Cmd { m.navUp(); return nil } m.NavKeys["enter"] = func() tea.Cmd { m.navDown(); return nil } m.NavKeys["m"] = func() tea.Cmd { return m.navMessages() } return m } -func (m *model_topics) Update(msg tea.Msg) tea.Cmd { +func (m *modelTopics) Update(msg tea.Msg) tea.Cmd { if cmd, navigated := m.NavKeys.HandleMsg(msg); navigated { return cmd } return m.pages[m.subpage].Update(msg) } -func (m *model_topics) View() string { +func (m *modelTopics) View() string { return m.pages[m.subpage].View() } diff --git a/cmd/monitor/page_topics_detailed.go b/cmd/monitor/page_topics_detailed.go index 60f955b..ffc8004 100644 --- a/cmd/monitor/page_topics_detailed.go +++ b/cmd/monitor/page_topics_detailed.go @@ -8,69 +8,69 @@ import ( tea "github.com/charmbracelet/bubbletea" ) -type model_topic_detailed struct { - table_detailed table.Model - detailed_topic_id string - topicType topicType +type modelTopicDetailed struct { + table table.Model + id string `exhaustruct:"optional"` + topicType topicType `exhaustruct:"optional"` } -func NewDetailedModel() *model_topic_detailed { - +func NewDetailedModel() *modelTopicDetailed { cols := []table.Column{ {Title: "", Width: 14}, {Title: "", Width: 67}, } - return &model_topic_detailed{ - table_detailed: NewTable(cols), - detailed_topic_id: "", + return &modelTopicDetailed{ + table: NewTable(cols), } } -func (m *model_topic_detailed) ShowTopic(topic_id string, topicType topicType) { - m.detailed_topic_id = topic_id +func (m *modelTopicDetailed) ShowTopic(topicID string, topicType topicType) { + m.id = topicID m.topicType = topicType m.updateDetailedTable(nil) } -func (m *model_topic_detailed) Init() tea.Cmd { +func (m *modelTopicDetailed) Init() tea.Cmd { return nil } -func (m *model_topic_detailed) Update(msg tea.Msg) tea.Cmd { +func (m *modelTopicDetailed) Update(msg tea.Msg) tea.Cmd { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: - m.table_detailed, cmd = m.table_detailed.Update(msg) + m.table, cmd = m.table.Update(msg) } return cmd } -func (m *model_topic_detailed) View() string { - return baseStyle.Render(m.table_detailed.View()) + "\n" + m.table_detailed.HelpView() +func (m *modelTopicDetailed) View() string { + return baseStyle.Render(m.table.View()) + "\n" + m.table.HelpView() } -func (m *model_topic_detailed) Refresh() { +func (m *modelTopicDetailed) Refresh() { m.updateDetailedTable(nil) } -func (m *model_topic_detailed) updateDetailedTable(msg tea.Msg) { - t, _ := getTopicFromId(m.topicType, m.detailed_topic_id) - m.table_detailed.Columns()[0].Title = t.Direction - m.table_detailed.Columns()[1].Title = t.Topic_name +func (m *modelTopicDetailed) updateDetailedTable(msg tea.Msg) { + t, _ := getTopicFromID(m.topicType, m.id) + m.table.Columns()[0].Title = t.Direction + m.table.Columns()[1].Title = t.TopicName rows := []table.Row{ {"Datatype", fmt.Sprintf("(%s) %s", t.Datatype.Encoding, t.Datatype.Name)}, - {"Unit", t.Unit_name}, - {"Messages", - fmt.Sprintf("%v (%v dropped)", t.Data_clock, t.Message_drops), + {"Unit", t.UnitName}, + { + "Messages", + fmt.Sprintf("%v (%v dropped)", t.DataClock, t.MessageDrops), }, - {"Frequency", strconv.FormatFloat(float64(t.Data_freq)/1000, 'f', -1, 32)}, - {"Message Size", strconv.FormatInt(int64(t.Topic_size), 10)}, - {"Connections", - fmt.Sprintf("%v local, %v external", t.Connections_local, t.Connections_external), + {"Frequency", strconv.FormatFloat(float64(t.DataFreq)/1000, 'f', -1, 32)}, + {"Message Size", strconv.FormatInt(int64(t.TopicSize), 10)}, + { + "Connections", + fmt.Sprintf("%v local, %v external", t.ConnectionsLocal, t.ConnectionsExternal), }, - {"Tick", strconv.FormatInt(int64(t.Registration_clock), 10)}, + {"Tick", strconv.FormatInt(int64(t.RegistrationClock), 10)}, } - m.table_detailed.SetRows(rows) - m.table_detailed, _ = m.table_detailed.Update(msg) + m.table.SetRows(rows) + m.table, _ = m.table.Update(msg) } diff --git a/cmd/monitor/page_topics_main.go b/cmd/monitor/page_topics_main.go index d442369..7def180 100644 --- a/cmd/monitor/page_topics_main.go +++ b/cmd/monitor/page_topics_main.go @@ -1,7 +1,6 @@ package main import ( - "errors" "strconv" "strings" @@ -64,15 +63,15 @@ func (km topicsKeyMap) FullHelp() [][]key.Binding { return append([][]key.Binding{{km.FilterAll, km.FilterPub, km.FilterSub}}, km.KeyMap.FullHelp()...) } -type model_topics_main struct { - table_topics table.Model - keymap topicsKeyMap - help help.Model - filter entityFilter +type modelTopicsMain struct { + table table.Model + keymap topicsKeyMap + help help.Model + filter entityFilter } -func NewTopicsMainModel() *model_topics_main { - topics_columns := []table.Column{ +func NewTopicsMainModel() *modelTopicsMain { + cols := []table.Column{ {Title: "ID", Width: 0}, // Zero width ID column to use as identifier {Title: "D", Width: 1}, {Title: "Topic", Width: 20}, @@ -83,18 +82,18 @@ func NewTopicsMainModel() *model_topics_main { {Title: "Tick", Width: 4}, } - return &model_topics_main{ - table_topics: NewTable(topics_columns), - keymap: newTopicsKeyMap(), - help: help.New(), + return &modelTopicsMain{ + table: NewTable(cols), + keymap: newTopicsKeyMap(), + help: help.New(), } } -func (m *model_topics_main) Refresh() { +func (m *modelTopicsMain) Refresh() { m.updateTopicsTable(nil) } -func (m *model_topics_main) Update(msg tea.Msg) tea.Cmd { +func (m *modelTopicsMain) Update(msg tea.Msg) tea.Cmd { switch msg := msg.(type) { case tea.KeyMsg: switch { @@ -118,14 +117,14 @@ func (m *model_topics_main) Update(msg tea.Msg) tea.Cmd { return nil } -func (m *model_topics_main) View() string { - return baseStyle.Render(m.table_topics.View()) + "\n" + m.help.View(m.keymap) +func (m *modelTopicsMain) View() string { + return baseStyle.Render(m.table.View()) + "\n" + m.help.View(m.keymap) } -func (m *model_topics_main) GetSelectedId() (string, topicType, error) { - row := m.table_topics.SelectedRow() +func (m *modelTopicsMain) GetSelectedID() (string, topicType, error) { + row := m.table.SelectedRow() if row == nil { - return "", 0, errors.New("No active topics") + return "", 0, errEmptyTable } var topicType topicType switch row[1] { @@ -137,7 +136,7 @@ func (m *model_topics_main) GetSelectedId() (string, topicType, error) { return row[0], topicType, nil } -func (m *model_topics_main) updateTopicsTable(msg tea.Msg) { +func (m *modelTopicsMain) updateTopicsTable(msg tea.Msg) { rows := []table.Row{} entities := monitoring.MonitorNone switch m.filter { @@ -155,19 +154,19 @@ func (m *model_topics_main) updateTopicsTable(msg tea.Msg) { for _, topic := range mon.Subscribers { rows = append(rows, topicToRow(topic)) } - m.table_topics.SetRows(rows) - m.table_topics, _ = m.table_topics.Update(msg) + m.table.SetRows(rows) + m.table, _ = m.table.Update(msg) } func topicToRow(topic monitoring.TopicMon) table.Row { return []string{ - topic.Topic_id, + topic.TopicID, strings.ToUpper(topic.Direction[0:1]), - topic.Topic_name, + topic.TopicName, topic.Datatype.Name, - strconv.FormatInt(topic.Data_clock, 10), - strconv.FormatInt(int64(topic.Topic_size), 10), - strconv.FormatFloat(float64(topic.Data_freq)/1000, 'f', -1, 32), - strconv.FormatInt(int64(topic.Registration_clock), 10), + strconv.FormatInt(topic.DataClock, 10), + strconv.FormatInt(int64(topic.TopicSize), 10), + strconv.FormatFloat(float64(topic.DataFreq)/1000, 'f', -1, 32), + strconv.FormatInt(int64(topic.RegistrationClock), 10), } } diff --git a/cmd/monitor/page_topics_messages.go b/cmd/monitor/page_topics_messages.go index 478dd20..221e6c5 100644 --- a/cmd/monitor/page_topics_messages.go +++ b/cmd/monitor/page_topics_messages.go @@ -14,11 +14,11 @@ import ( "github.com/muesli/reflow/wrap" ) -type model_topic_messages struct { +type modelTopicMessages struct { viewport viewport.Model mon monitoring.TopicMon topicType topicType - topicId string + topicID string subscriber *subscriber.Subscriber msg []byte deserializer func([]byte) string @@ -28,20 +28,20 @@ type msgMsg struct { msg []byte } -func NewTopicsMessagesModel() *model_topic_messages { +func NewTopicsMessagesModel() *modelTopicMessages { viewport := viewport.New(85, 10) subscriber, _ := subscriber.New() - return &model_topic_messages{ + return &modelTopicMessages{ viewport: viewport, subscriber: subscriber, } } -func (m *model_topic_messages) Init() tea.Cmd { +func (m *modelTopicMessages) Init() tea.Cmd { return m.receiveTicks() } -func (m *model_topic_messages) Update(msg tea.Msg) tea.Cmd { +func (m *modelTopicMessages) Update(msg tea.Msg) tea.Cmd { var cmd tea.Cmd switch msg := msg.(type) { case msgMsg: @@ -53,14 +53,14 @@ func (m *model_topic_messages) Update(msg tea.Msg) tea.Cmd { return cmd } -func (m *model_topic_messages) View() string { +func (m *modelTopicMessages) View() string { s := strings.Builder{} - s.WriteString(highlight.Render(m.mon.Topic_name)) + s.WriteString(highlight.Render(m.mon.TopicName)) s.WriteString( fmt.Sprintf(" Messages: %v (%vHz)", - m.mon.Data_clock, + m.mon.DataClock, // TODO: Conversion that can stringify to KHz, MHz, etc. - strconv.FormatFloat(float64(m.mon.Data_freq)/1000.0, 'e', 3, 64)), + strconv.FormatFloat(float64(m.mon.DataFreq)/1000.0, 'e', 3, 64)), ) s.WriteRune('\n') // Manually wrap the string with museli/reflow to inject newlines @@ -70,32 +70,32 @@ func (m *model_topic_messages) View() string { return baseStyle.Render(s.String()) } -func (m *model_topic_messages) Refresh() { - m.mon, _ = getTopicFromId(m.topicType, m.topicId) +func (m *modelTopicMessages) Refresh() { + m.mon, _ = getTopicFromID(m.topicType, m.topicID) } -func (m *model_topic_messages) ShowTopic(topicId string, topicType topicType) { - if m.topicId != topicId { +func (m *modelTopicMessages) ShowTopic(topicID string, topicType topicType) { + if m.topicID != topicID { m.topicType = topicType - m.topicId = topicId - m.mon, _ = getTopicFromId(m.topicType, m.topicId) + m.topicID = topicID + m.mon, _ = getTopicFromID(m.topicType, m.topicID) m.createSubscriber() } m.Refresh() } -func (m *model_topic_messages) createSubscriber() { +func (m *modelTopicMessages) createSubscriber() { // (re)create subscriber with new topic type m.subscriber.Delete() subscriber, err := subscriber.New() if err != nil { subscriber.Delete() - fmt.Println("Failed to allocate new subscriber") + panic(fmt.Errorf("[Topic Messages]: %w", err)) } - err = subscriber.Create(m.mon.Topic_name, m.mon.Datatype) + err = subscriber.Create(m.mon.TopicName, m.mon.Datatype) if err != nil { subscriber.Delete() - fmt.Println("Failed to create subscriber!") + panic(fmt.Errorf("[Topic Messages]: %w", err)) } switch { case m.mon.Datatype.Name == "std::string" && m.mon.Datatype.Encoding == "base": @@ -107,7 +107,7 @@ func (m *model_topic_messages) createSubscriber() { m.subscriber = subscriber } -func (m *model_topic_messages) receiveTicks() tea.Cmd { +func (m *modelTopicMessages) receiveTicks() tea.Cmd { return func() tea.Msg { switch msg := (<-m.subscriber.Messages).(type) { case []byte: @@ -117,7 +117,7 @@ func (m *model_topic_messages) receiveTicks() tea.Cmd { } } -// Message deserializers +// Message deserializers. func deserializeBasicString(msg []byte) string { return string(msg) } diff --git a/cmd/monitor/tea.go b/cmd/monitor/tea.go index d7f9150..8f01ab8 100644 --- a/cmd/monitor/tea.go +++ b/cmd/monitor/tea.go @@ -1,8 +1,7 @@ package main import ( - "fmt" - "os" + "log" "strings" "time" @@ -18,13 +17,13 @@ type PageModel interface { type Page int const ( - page_topics Page = iota - page_services - page_hosts - page_processes - page_logs - page_system - page_about + pageTopics Page = iota + pageServices + pageHosts + pageProcesses + pageLogs + pageSystem + pageAbout ) type model struct { @@ -34,15 +33,15 @@ type model struct { func newModel() *model { pagesMap := make(map[Page]PageModel) - pagesMap[page_topics] = NewTopicsModel() - pagesMap[page_services] = NewServicesModel() - pagesMap[page_hosts] = NewHostsModel() - pagesMap[page_processes] = NewProcessesModel() - pagesMap[page_logs] = NewLogsModel() - pagesMap[page_system] = NewConfigModel() - pagesMap[page_about] = &PlaceholderModel{"About Placeholder"} + pagesMap[pageTopics] = NewTopicsModel() + pagesMap[pageServices] = NewServicesModel() + pagesMap[pageHosts] = NewHostsModel() + pagesMap[pageProcesses] = NewProcessesModel() + pagesMap[pageLogs] = NewLogsModel() + pagesMap[pageSystem] = NewConfigModel() + pagesMap[pageAbout] = &PlaceholderModel{"About Placeholder"} return &model{ - page: page_topics, + page: pageTopics, pages: pagesMap, } } @@ -83,19 +82,19 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "q", "ctrl+c": return m, tea.Quit case "1": - m.transitionTo(page_topics) + m.transitionTo(pageTopics) case "2": - m.transitionTo(page_services) + m.transitionTo(pageServices) case "3": - m.transitionTo(page_hosts) + m.transitionTo(pageHosts) case "4": - m.transitionTo(page_processes) + m.transitionTo(pageProcesses) case "5": - m.transitionTo(page_logs) + m.transitionTo(pageLogs) case "6": - m.transitionTo(page_system) + m.transitionTo(pageSystem) case "7": - m.transitionTo(page_about) + m.transitionTo(pageAbout) default: cmd = m.updatePage(msg) } @@ -130,7 +129,6 @@ func (m *model) View() string { func doCli() { p := tea.NewProgram(newModel()) if _, err := p.Run(); err != nil { - fmt.Println("Error running program:", err) - os.Exit(1) + log.Fatal("Error running program:", err) } } diff --git a/ecal/callback.go b/ecal/callback.go index 7149bed..ed8404d 100644 --- a/ecal/callback.go +++ b/ecal/callback.go @@ -2,6 +2,7 @@ package ecal //#include import "C" + import ( "runtime/cgo" ) diff --git a/ecal/core.go b/ecal/core.go index d4459de..5e1bee1 100644 --- a/ecal/core.go +++ b/ecal/core.go @@ -4,6 +4,7 @@ package ecal // #include "core.h" // #include import "C" + import ( "runtime/cgo" "unsafe" @@ -11,15 +12,15 @@ import ( const ( // eCAL Components - C_None uint = 0x000 - C_Publisher uint = 0x001 - C_Subscriber uint = 0x002 - C_Service uint = 0x004 - C_Monitoring uint = 0x008 - C_Logging uint = 0x010 - C_TimeSync uint = 0x020 - C_Default uint = C_Publisher | C_Subscriber | C_Service | C_Logging | C_TimeSync - C_All uint = C_Publisher | C_Subscriber | C_Service | C_Monitoring | C_Logging | C_TimeSync + CNone uint = 0x000 + CPublisher uint = 0x001 + CSubscriber uint = 0x002 + CService uint = 0x004 + CMonitoring uint = 0x008 + CLogging uint = 0x010 + CTimeSync uint = 0x020 + CDefault uint = CPublisher | CSubscriber | CService | CLogging | CTimeSync + CAll uint = CPublisher | CSubscriber | CService | CMonitoring | CLogging | CTimeSync ) type ConfigLogging struct { @@ -58,15 +59,15 @@ func GetVersion() C.struct_version { return C.GetVersion() } -func Initialize(config Config, unit_name string, components uint) int { +func Initialize(config Config, unitName string, components uint) int { cconfig := C.struct_CConfig{ logging: C.struct_CConfigLogging{ receive_enabled: C.bool(config.Logging.ReceiveEnabled), }, } - unit_c := C.CString(unit_name) - defer C.free(unsafe.Pointer(unit_c)) - return int(C.Initialize(&cconfig, unit_c, C.uint(components))) + unitNameC := C.CString(unitName) + defer C.free(unsafe.Pointer(unitNameC)) + return int(C.Initialize(&cconfig, unitNameC, C.uint(components))) } func Finalize() int { @@ -81,11 +82,12 @@ func IsComponentInitialized(component uint) bool { return bool(C.IsComponentInitialized(C.uint(component))) } -func SetUnitName(unit_name string) bool { - unit_c := C.CString(unit_name) - defer C.free(unsafe.Pointer(unit_c)) - return bool(C.SetUnitName(unit_c)) +func SetUnitName(unitName string) bool { + unitNameC := C.CString(unitName) + defer C.free(unsafe.Pointer(unitNameC)) + return bool(C.SetUnitName(unitNameC)) } + func Ok() bool { return bool(C.Ok()) } diff --git a/ecal/core_test.go b/ecal/core_test.go index ac3505b..fe68479 100644 --- a/ecal/core_test.go +++ b/ecal/core_test.go @@ -26,12 +26,11 @@ func TestGetVersion(t *testing.T) { } func TestInitializeFinalize(t *testing.T) { - if IsInitialized() { t.Error("eCAL pre-initialized...") } - initResult := Initialize(NewConfig(), "go_test", C_Default) + initResult := Initialize(NewConfig(), "go_test", CDefault) if initResult == 1 { t.Fatal("eCAL already initialized") } else if initResult != 0 { @@ -39,7 +38,7 @@ func TestInitializeFinalize(t *testing.T) { } // Test double initialization - secondInit := Initialize(NewConfig(), "go_test2", C_Publisher) + secondInit := Initialize(NewConfig(), "go_test2", CPublisher) if secondInit != 1 { t.Errorf("Second initialize returned %v", secondInit) } @@ -47,8 +46,8 @@ func TestInitializeFinalize(t *testing.T) { if !IsInitialized() { t.Error("IsInitialized return false, expected true") } - if !IsComponentInitialized(C_Publisher) { - t.Error("Expected publisher component to be initialised") + if !IsComponentInitialized(CPublisher) { + t.Error("Expected publisheCPublisher to be initialised") } if !SetUnitName("go_test_set_name") { diff --git a/ecal/logging/callback.go b/ecal/logging/callback.go index d7a860e..f794cd4 100644 --- a/ecal/logging/callback.go +++ b/ecal/logging/callback.go @@ -3,6 +3,7 @@ package logging //#include "logging.h" //#include "types.h" import "C" + import ( "runtime/cgo" "unsafe" @@ -12,13 +13,13 @@ func copyToLogMessages(cmsgs []C.struct_CLogMessage) []LogMessage { msgs := make([]LogMessage, len(cmsgs)) for idx, msg := range cmsgs { msgs[idx] = LogMessage{ - Time: int64(msg.time), - Host: C.GoString(msg.host_name), - Process: C.GoString(msg.process_name), - Unit_name: C.GoString(msg.unit_name), - Content: C.GoString(msg.content), - Pid: int32(msg.pid), - Level: Level(msg.level), + Time: int64(msg.time), + Host: C.GoString(msg.host_name), + Process: C.GoString(msg.process_name), + UnitName: C.GoString(msg.unit_name), + Content: C.GoString(msg.content), + Pid: int32(msg.pid), + Level: Level(msg.level), } } return msgs @@ -28,9 +29,9 @@ func copyToLogMessages(cmsgs []C.struct_CLogMessage) []LogMessage { func goCopyLogging(handle C.uintptr_t, clogging *C.struct_CLogging) { l := cgo.Handle(handle).Value().(*Logging) - num_messages := clogging.num_messages - if num_messages > 0 { - ms := (*[1 << 30]C.struct_CLogMessage)(unsafe.Pointer(clogging.messages))[:num_messages:num_messages] + numMessages := clogging.num_messages + if numMessages > 0 { + ms := (*[1 << 30]C.struct_CLogMessage)(unsafe.Pointer(clogging.messages))[:numMessages:numMessages] l.Messages = copyToLogMessages(ms) } } diff --git a/ecal/logging/logging.go b/ecal/logging/logging.go index 98f1ecd..5a7a912 100644 --- a/ecal/logging/logging.go +++ b/ecal/logging/logging.go @@ -7,6 +7,7 @@ package logging // Log(level, _GoStringPtr(msg), _GoStringLen(msg)); // } import "C" + import ( "fmt" "runtime/cgo" @@ -16,13 +17,13 @@ import ( type Level uint8 type LogMessage struct { - Time int64 - Host string - Process string - Unit_name string - Content string - Pid int32 - Level Level + Time int64 + Host string + Process string + UnitName string + Content string + Pid int32 + Level Level } const ( @@ -122,7 +123,7 @@ func SetConsoleFilter(levels Level) { C.SetConsoleFilter(C.eCAL_Logging_Filter(levels)) } -func SetUdpFilter(levels Level) { +func SetUDPFilter(levels Level) { C.SetUDPFilter(C.eCAL_Logging_Filter(levels)) } diff --git a/ecal/monitoring/callback.go b/ecal/monitoring/callback.go index d6b9f30..56174f3 100644 --- a/ecal/monitoring/callback.go +++ b/ecal/monitoring/callback.go @@ -2,6 +2,7 @@ package monitoring //#include "monitoring.h" import "C" + import ( "runtime/cgo" "unsafe" @@ -13,22 +14,22 @@ func copyToTopicMons(ctopics []C.struct_CTopicMon) []TopicMon { topics := make([]TopicMon, len(ctopics)) for idx, pub := range ctopics { topics[idx] = TopicMon{ - Topic_id: C.GoString(pub.topic_id), - Registration_clock: int32(pub.registration_clock), - Topic_name: C.GoString(pub.topic_name), - Data_clock: int64(pub.data_clock), - Data_freq: int32(pub.data_freq), - Topic_size: int32(pub.topic_size), - Unit_name: C.GoString(pub.unit_name), - Direction: C.GoString(pub.direction), + TopicID: C.GoString(pub.topic_id), + RegistrationClock: int32(pub.registration_clock), + TopicName: C.GoString(pub.topic_name), + DataClock: int64(pub.data_clock), + DataFreq: int32(pub.data_freq), + TopicSize: int32(pub.topic_size), + UnitName: C.GoString(pub.unit_name), + Direction: C.GoString(pub.direction), Datatype: types.DataType{ Name: C.GoString(pub.datatype.name), Encoding: C.GoString(pub.datatype.encoding), }, - Connections_local: int32(pub.connections_local), - Connections_external: int32(pub.connections_external), - Message_drops: int32(pub.message_drops), - HostName: C.GoString(pub.host_name), + ConnectionsLocal: int32(pub.connections_local), + ConnectionsExternal: int32(pub.connections_external), + MessageDrops: int32(pub.message_drops), + HostName: C.GoString(pub.host_name), } } return topics @@ -38,17 +39,17 @@ func copyToProcessMons(cprocs []C.struct_CProcessMon) []ProcessMon { procs := make([]ProcessMon, len(cprocs)) for idx, proc := range cprocs { procs[idx] = ProcessMon{ - Registration_clock: int32(proc.registration_clock), - Host_name: C.GoString(proc.host_name), - Pid: int32(proc.pid), - Process_name: C.GoString(proc.process_name), - Unit_name: C.GoString(proc.unit_name), - Process_parameters: C.GoString(proc.process_parameters), // Command line args - State_severity: ProcessSeverity(proc.state_severity), - State_severity_level: int32(proc.state_severity_level), - State_info: C.GoString(proc.state_info), - Components_initialized: C.GoString(proc.components), - Runtime_version: C.GoString(proc.runtime), // eCAL Version in use + RegistrationClock: int32(proc.registration_clock), + HostName: C.GoString(proc.host_name), + Pid: int32(proc.pid), + ProcessName: C.GoString(proc.process_name), + UnitName: C.GoString(proc.unit_name), + ProcessParameters: C.GoString(proc.process_parameters), // Command line args + StateSeverity: ProcessSeverity(proc.state_severity), + StateSeverityLevel: int32(proc.state_severity_level), + StateInfo: C.GoString(proc.state_info), + ComponentsInitialized: C.GoString(proc.components), + RuntimeVersion: C.GoString(proc.runtime), // eCAL Version in use } } return procs @@ -76,7 +77,7 @@ func copyToMethodMons(cmethods []C.struct_CMethodMon) []MethodMon { func copyToServiceBase(cbase C.struct_CServiceCommon) ServiceBase { return ServiceBase{ Name: C.GoString(cbase.name), - Id: C.GoString(cbase.id), + ID: C.GoString(cbase.id), RegistrationClock: int32(cbase.registration_clock), HostName: C.GoString(cbase.host_name), Process: C.GoString(cbase.process_name), diff --git a/ecal/monitoring/monitoring.go b/ecal/monitoring/monitoring.go index 9df2d61..3d8d089 100644 --- a/ecal/monitoring/monitoring.go +++ b/ecal/monitoring/monitoring.go @@ -5,6 +5,7 @@ package monitoring //#include "monitoring.h" //#cgo CPPFLAGS: -I${SRCDIR}/../types import "C" + import ( "runtime/cgo" "strconv" @@ -53,41 +54,41 @@ func (p ProcessSeverity) String() string { } type TopicMon struct { - Registration_clock int32 // registration heart beat - HostName string + RegistrationClock int32 // registration heart beat + HostName string // host_group string // pid int32 // process_name string - Unit_name string - Topic_id string - Topic_name string - Direction string - Datatype types.DataType + UnitName string + TopicID string + TopicName string + Direction string + Datatype types.DataType // TODO: transport layer - Topic_size int32 // Size of messages (bytes) - Connections_local int32 - Connections_external int32 - Message_drops int32 + TopicSize int32 // Size of messages (bytes) + ConnectionsLocal int32 + ConnectionsExternal int32 + MessageDrops int32 // data_id int64 - Data_clock int64 - Data_freq int32 // mHz + DataClock int64 + DataFreq int32 // mHz // attributes } type ProcessMon struct { - Registration_clock int32 // registration heart beat - Host_name string - Host_group string - Pid int32 - Process_name string - Unit_name string - Process_parameters string // Command line args - State_severity ProcessSeverity - State_severity_level int32 - State_info string + RegistrationClock int32 // registration heart beat + HostName string + HostGroup string + Pid int32 + ProcessName string + UnitName string + ProcessParameters string // Command line args + StateSeverity ProcessSeverity + StateSeverityLevel int32 + StateInfo string // TODO: Time sync? - Components_initialized string - Runtime_version string // eCAL Version in use + ComponentsInitialized string + RuntimeVersion string // eCAL Version in use } type methodType struct { @@ -104,7 +105,7 @@ type MethodMon struct { type ServiceBase struct { Name string - Id string + ID string Methods []MethodMon RegistrationClock int32 // registration heart beat HostName string diff --git a/ecal/monitoring/monitoring_test.go b/ecal/monitoring/monitoring_test.go index 281cf6e..88b6140 100644 --- a/ecal/monitoring/monitoring_test.go +++ b/ecal/monitoring/monitoring_test.go @@ -9,20 +9,20 @@ import ( "github.com/DownerCase/ecal-go/ecal/registration" "github.com/DownerCase/ecal-go/internal/ecaltest" "github.com/DownerCase/ecal-go/internal/ecaltest/regtest" - "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_publisher" - "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_subscriber" + testutilpublisher "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_publisher" + testutilsubscriber "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_subscriber" ) -func expectTopicPresent(t *testing.T, ts []TopicMon, topic_name string) { +func expectTopicPresent(t *testing.T, ts []TopicMon, topicName string) { if len(ts) == 0 { t.Error("Monitoring returned no topics") } for _, topic := range ts { - if topic.Topic_name == topic_name { + if topic.TopicName == topicName { return } } - t.Error("Monitoring does not contain expected topic", topic_name, "\nReceived", ts) + t.Error("Monitoring does not contain expected topic", topicName, "\nReceived", ts) } func TestPublisherMonitoring(t *testing.T) { @@ -33,7 +33,7 @@ func TestPublisherMonitoring(t *testing.T) { channel := make(chan regtest.Callback) registration.AddPublisherEventCallback(regtest.EventCallback(topic, channel)) - pub := testutil_publisher.NewGenericPublisher(t, topic) + pub := testutilpublisher.NewGenericPublisher(t, topic) defer pub.Delete() mon := GetMonitoring(MonitorHost) @@ -56,8 +56,8 @@ func expectPid(t *testing.T, pid int, procs []ProcessMon) { } for _, proc := range procs { if pid == int(proc.Pid) { - if proc.Host_name != hostname { - t.Error("Expected hostname", hostname, "got", proc.Host_name) + if proc.HostName != hostname { + t.Error("Expected hostname", hostname, "got", proc.HostName) } return } @@ -73,7 +73,7 @@ func TestSubscriberMonitoring(t *testing.T) { channel := make(chan regtest.Callback) registration.AddSubscriberEventCallback(regtest.EventCallback(topic, channel)) - sub := testutil_subscriber.NewGenericSubscriber(t, topic) + sub := testutilsubscriber.NewGenericSubscriber(t, topic) defer sub.Delete() mon := GetMonitoring(MonitorHost) diff --git a/ecal/protobuf/publisher/protobuf_publisher.go b/ecal/protobuf/publisher/protobuf_publisher.go index 6dc9466..9aa00e6 100644 --- a/ecal/protobuf/publisher/protobuf_publisher.go +++ b/ecal/protobuf/publisher/protobuf_publisher.go @@ -7,7 +7,7 @@ import ( "google.golang.org/protobuf/proto" ) -// Type must be a pointer and implement the proto.Message interface +// Type must be a pointer and implement the proto.Message interface. type Msg[T any] interface { *T proto.Message diff --git a/ecal/protobuf/publisher/protobuf_publisher_test.go b/ecal/protobuf/publisher/protobuf_publisher_test.go index c8f883a..958e6f3 100644 --- a/ecal/protobuf/publisher/protobuf_publisher_test.go +++ b/ecal/protobuf/publisher/protobuf_publisher_test.go @@ -3,19 +3,20 @@ package publisher_test import ( "testing" - "github.com/DownerCase/ecal-go/internal/ecaltest/protobuf/testutil_publisher" + testutilpublisher "github.com/DownerCase/ecal-go/internal/ecaltest/protobuf/testutil_publisher" "github.com/DownerCase/ecal-go/protos" ) func TestProtobufPublisher(t *testing.T) { - pub := testutil_publisher.NewProtobufPublisher[protos.Person](t, "testing_protobuf_publisher") + pub := testutilpublisher.NewProtobufPublisher[protos.Person](t, "testing_protobuf_publisher") defer pub.Delete() if pub.Messages == nil { t.Error("Message channel nil") } - person := &protos.Person{Id: 0, Name: "John", Email: "john@doe.net", + person := &protos.Person{ + Id: 0, Name: "John", Email: "john@doe.net", Dog: &protos.Dog{Name: "Pluto"}, House: &protos.House{Rooms: 5}, } diff --git a/ecal/protobuf/subscriber/protobuf_subscriber.go b/ecal/protobuf/subscriber/protobuf_subscriber.go index fea6e9a..09e5b57 100644 --- a/ecal/protobuf/subscriber/protobuf_subscriber.go +++ b/ecal/protobuf/subscriber/protobuf_subscriber.go @@ -2,7 +2,6 @@ package subscriber import "C" import ( - "errors" "fmt" "reflect" "time" @@ -39,7 +38,7 @@ func (p *Subscriber[U, T]) Receive(timeout time.Duration) (U, error) { select { case msg = <-p.Messages: case <-time.After(timeout): - return u, errors.New("Receive timed out") + return u, fmt.Errorf("[Receive[%v]()]: %w", reflect.TypeFor[U](), subscriber.ErrRcvTimeout) } switch msg := msg.(type) { case U: @@ -47,17 +46,16 @@ func (p *Subscriber[U, T]) Receive(timeout time.Duration) (U, error) { case error: return u, msg default: - err := fmt.Sprint("Unexpected message type recevied", reflect.TypeOf(msg)) - return u, errors.New(err) + return u, fmt.Errorf("%w: %v", subscriber.ErrRcvBadType, reflect.TypeOf(msg)) } } func deserialize[U any, T Msg[U]](data unsafe.Pointer, len int) any { // WARNING: Creates a Go slice backed by C data and deserializes into a Go // value which gets put into the channel - bytes_unsafe := unsafe.Slice((*byte)(data), len) + bytesUnsafe := unsafe.Slice((*byte)(data), len) var msg U - err := proto.Unmarshal(bytes_unsafe, T(&msg)) + err := proto.Unmarshal(bytesUnsafe, T(&msg)) if err != nil { return err } diff --git a/ecal/protobuf/subscriber/protobuf_subscriber_test.go b/ecal/protobuf/subscriber/protobuf_subscriber_test.go index 4b34784..4c81283 100644 --- a/ecal/protobuf/subscriber/protobuf_subscriber_test.go +++ b/ecal/protobuf/subscriber/protobuf_subscriber_test.go @@ -7,7 +7,7 @@ import ( "github.com/DownerCase/ecal-go/ecal" "github.com/DownerCase/ecal-go/ecal/protobuf/publisher" "github.com/DownerCase/ecal-go/internal/ecaltest" - "github.com/DownerCase/ecal-go/internal/ecaltest/protobuf/testutil_publisher" + testutilpublisher "github.com/DownerCase/ecal-go/internal/ecaltest/protobuf/testutil_publisher" "github.com/DownerCase/ecal-go/protos" ) @@ -26,7 +26,7 @@ func TestSubscriber(t *testing.T) { ecaltest.InitEcal(t) defer ecal.Finalize() // Shutdown eCAL at the end of the program - pub := testutil_publisher.NewProtobufPublisher[protos.Person](t, "testing_protobuf_subscriber") + pub := testutilpublisher.NewProtobufPublisher[protos.Person](t, "testing_protobuf_subscriber") defer pub.Delete() sub := newSubscriber[protos.Person](t, "testing_protobuf_subscriber") @@ -35,7 +35,6 @@ func TestSubscriber(t *testing.T) { go sendMessages(pub) for range 10 { msg, err := sub.Receive(2 * time.Second) - if err != nil { t.Error(err) } @@ -66,7 +65,8 @@ func TestSubscriberTimeout(t *testing.T) { } func sendMessages(p *publisher.Publisher[*protos.Person]) { - person := &protos.Person{Id: 0, Name: "John", Email: "john@doe.net", + person := &protos.Person{ + Id: 0, Name: "John", Email: "john@doe.net", Dog: &protos.Dog{Name: "Pluto"}, House: &protos.House{Rooms: 5}, } diff --git a/ecal/publisher/publisher.go b/ecal/publisher/publisher.go index ad37be0..0396102 100644 --- a/ecal/publisher/publisher.go +++ b/ecal/publisher/publisher.go @@ -10,6 +10,7 @@ package publisher // const char* const descriptor, size_t descriptor_len //); import "C" + import ( "errors" "runtime/cgo" @@ -18,6 +19,11 @@ import ( "github.com/DownerCase/ecal-go/ecal/types" ) +var ( + errFailedAlloc = errors.New("failed to allocate publisher") + errFailedCreate = errors.New("failed to create publisher") +) + type DataType = types.DataType type Publisher struct { @@ -35,7 +41,7 @@ func New() (*Publisher, error) { pub.handle = handle if !C.NewPublisher(C.uintptr_t(pub.handle)) { handle.Delete() - return nil, errors.New("Failed to allocate new publisher") + return nil, errFailedAlloc } return &pub, nil } @@ -54,19 +60,19 @@ func (p *Publisher) Delete() { } func (p *Publisher) Create(topic string, datatype DataType) error { - var descriptor_ptr *C.char = nil + var descriptorPtr *C.char = nil if len(datatype.Descriptor) > 0 { - descriptor_ptr = (*C.char)(unsafe.Pointer(&datatype.Descriptor[0])) + descriptorPtr = (*C.char)(unsafe.Pointer(&datatype.Descriptor[0])) } if !C.GoPublisherCreate( C.uintptr_t(p.handle), topic, datatype.Name, datatype.Encoding, - descriptor_ptr, + descriptorPtr, C.size_t(len(datatype.Descriptor)), ) { - return errors.New("Failed to Create publisher") + return errFailedCreate } go p.sendMessages() return nil diff --git a/ecal/publisher/publisher_test.go b/ecal/publisher/publisher_test.go index d6751ed..8d5b9cf 100644 --- a/ecal/publisher/publisher_test.go +++ b/ecal/publisher/publisher_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/DownerCase/ecal-go/ecal/publisher" - "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_publisher" + testutilpublisher "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_publisher" ) func TestNewPublishers(t *testing.T) { @@ -18,10 +18,9 @@ func TestNewPublishers(t *testing.T) { } func TestPublisher(t *testing.T) { - pub := testutil_publisher.NewGenericPublisher(t, "testing") + pub := testutilpublisher.NewGenericPublisher(t, "testing") defer pub.Delete() if pub.Messages == nil { t.Error("Message channel nil") } - } diff --git a/ecal/registration/registration.go b/ecal/registration/registration.go index 1e6f3e5..7dcc915 100644 --- a/ecal/registration/registration.go +++ b/ecal/registration/registration.go @@ -5,7 +5,9 @@ package registration //#include "types.h" // #cgo CPPFLAGS: -I${SRCDIR}/../types import "C" + import ( + "log" "runtime/cgo" "github.com/DownerCase/ecal-go/ecal/types" @@ -14,18 +16,20 @@ import ( type Event uint8 const ( - ENTITY_NEW Event = 0 - ENTITY_DELETED Event = 1 + EntityNew Event = 0 + EntityDeleted Event = 1 ) type QualityFlags uint8 -type EntityId = types.EntityId -type TopicId = types.TopicId +type ( + EntityID = types.EntityID + TopicID = types.TopicID +) type CallbackToken struct { - ecal_token uint - go_handle cgo.Handle + ecalToken uint + goHandle cgo.Handle } type QualityTopicInfo struct { @@ -33,50 +37,53 @@ type QualityTopicInfo struct { QualityFlags QualityFlags } -func AddPublisherEventCallback(callback func(TopicId, Event)) CallbackToken { +func AddPublisherEventCallback(callback func(TopicID, Event)) CallbackToken { handle := cgo.NewHandle(callback) - ecal_token := C.AddPublisherEventCallback(C.uintptr_t(handle)) + ecalToken := C.AddPublisherEventCallback(C.uintptr_t(handle)) token := CallbackToken{ - ecal_token: uint(ecal_token), - go_handle: handle, + ecalToken: uint(ecalToken), + goHandle: handle, } return token } func RemPublisherCallback(token CallbackToken) { - C.RemPublisherEventCallback(C.uintptr_t(token.ecal_token)) - token.go_handle.Delete() + C.RemPublisherEventCallback(C.uintptr_t(token.ecalToken)) + token.goHandle.Delete() } -func AddSubscriberEventCallback(callback func(TopicId, Event)) CallbackToken { +func AddSubscriberEventCallback(callback func(TopicID, Event)) CallbackToken { handle := cgo.NewHandle(callback) - ecal_token := C.AddSubscriberEventCallback(C.uintptr_t(handle)) + ecalToken := C.AddSubscriberEventCallback(C.uintptr_t(handle)) token := CallbackToken{ - ecal_token: uint(ecal_token), - go_handle: handle, + ecalToken: uint(ecalToken), + goHandle: handle, } return token } func RemSubscriberCallback(token CallbackToken) { - C.RemSubscriberEventCallback(C.uintptr_t(token.ecal_token)) - token.go_handle.Delete() + C.RemSubscriberEventCallback(C.uintptr_t(token.ecalToken)) + token.goHandle.Delete() } -func toTopicId(id *C.struct_CTopicId) TopicId { - return TopicId{ - Topic_id: EntityId{ - Entity_id: C.GoString(id.topic_id.entity_id), - Process_id: int32(id.topic_id.process_id), - Host_name: C.GoString(id.topic_id.host_name), +func toTopicID(id *C.struct_CTopicId) TopicID { + return TopicID{ + TopicID: EntityID{ + EntityID: C.GoString(id.topic_id.entity_id), + ProcessID: int32(id.topic_id.process_id), + HostName: C.GoString(id.topic_id.host_name), }, - Topic_name: C.GoString(id.topic_name), + TopicName: C.GoString(id.topic_name), } } //export goTopicEventCallback func goTopicEventCallback(handle C.uintptr_t, id C.struct_CTopicId, event C.uint8_t) { h := cgo.Handle(handle) - f := h.Value().(func(TopicId, Event)) - f(toTopicId(&id), Event(event)) + f, ok := h.Value().(func(TopicID, Event)) + if !ok { + log.Panic("Invalid handle passed to registration callback") + } + f(toTopicID(&id), Event(event)) } diff --git a/ecal/registration/registration_test.go b/ecal/registration/registration_test.go index 3ff10b1..1af96fc 100644 --- a/ecal/registration/registration_test.go +++ b/ecal/registration/registration_test.go @@ -7,8 +7,8 @@ import ( "github.com/DownerCase/ecal-go/ecal/registration" "github.com/DownerCase/ecal-go/internal/ecaltest" "github.com/DownerCase/ecal-go/internal/ecaltest/regtest" - "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_publisher" - "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_subscriber" + testutilpublisher "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_publisher" + testutilsubscriber "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_subscriber" ) func TestPublisherCallback(t *testing.T) { @@ -20,7 +20,7 @@ func TestPublisherCallback(t *testing.T) { registration.AddPublisherEventCallback(regtest.EventCallback(topic, channel)) - pub := testutil_publisher.NewGenericPublisher(t, topic) + pub := testutilpublisher.NewGenericPublisher(t, topic) defer pub.Delete() regtest.ExpectNew(t, topic, channel) @@ -39,7 +39,7 @@ func TestSubscriberCallback(t *testing.T) { registration.AddSubscriberEventCallback(regtest.EventCallback(topic, channel)) - sub := testutil_subscriber.NewGenericSubscriber(t, topic) + sub := testutilsubscriber.NewGenericSubscriber(t, topic) defer sub.Delete() regtest.ExpectNew(t, topic, channel) diff --git a/ecal/string/publisher/string_publisher.go b/ecal/string/publisher/string_publisher.go index 8110b6d..90c1dd3 100644 --- a/ecal/string/publisher/string_publisher.go +++ b/ecal/string/publisher/string_publisher.go @@ -15,13 +15,13 @@ func New() (*Publisher, error) { return &Publisher{*pub}, err } -// Send a message formatted with fmt.Print +// Send a message formatted with fmt.Print. func (p *Publisher) Send(msg ...any) error { p.Messages <- []byte(fmt.Sprint(msg...)) return nil } -// Send a message formatted with fmt.Printf +// Send a message formatted with fmt.Printf. func (p *Publisher) Sendf(format string, a ...any) error { p.Messages <- []byte(fmt.Sprintf(format, a...)) return nil diff --git a/ecal/string/publisher/string_publisher_test.go b/ecal/string/publisher/string_publisher_test.go index 546f584..1f43184 100644 --- a/ecal/string/publisher/string_publisher_test.go +++ b/ecal/string/publisher/string_publisher_test.go @@ -3,7 +3,7 @@ package publisher_test import ( "testing" - "github.com/DownerCase/ecal-go/internal/ecaltest/string/testutil_publisher" + testutilpublisher "github.com/DownerCase/ecal-go/internal/ecaltest/string/testutil_publisher" ) func TestStringPublisher(t *testing.T) { diff --git a/ecal/string/subscriber/string_subscriber.go b/ecal/string/subscriber/string_subscriber.go index e1ca755..0a15751 100644 --- a/ecal/string/subscriber/string_subscriber.go +++ b/ecal/string/subscriber/string_subscriber.go @@ -2,7 +2,7 @@ package subscriber import "C" import ( - "errors" + "fmt" "time" "unsafe" @@ -24,7 +24,7 @@ func (p *Subscriber) Receive(timeout time.Duration) (string, error) { case msg := <-p.Messages: return msg.(string), nil case <-time.After(timeout): - return "", errors.New("Receive timed out") + return "", fmt.Errorf("[Receive]: %w", subscriber.ErrRcvTimeout) } } diff --git a/ecal/string/subscriber/string_subscriber_test.go b/ecal/string/subscriber/string_subscriber_test.go index dcb8917..0d9f8a9 100644 --- a/ecal/string/subscriber/string_subscriber_test.go +++ b/ecal/string/subscriber/string_subscriber_test.go @@ -8,10 +8,10 @@ import ( "github.com/DownerCase/ecal-go/ecal" "github.com/DownerCase/ecal-go/ecal/string/publisher" "github.com/DownerCase/ecal-go/internal/ecaltest" - "github.com/DownerCase/ecal-go/internal/ecaltest/string/testutil_publisher" + testutilpublisher "github.com/DownerCase/ecal-go/internal/ecaltest/string/testutil_publisher" ) -var TEST_MESSAGE = "Test string" +const TestMessage = "Test string" func newSubscriber(t *testing.T, topic string) *Subscriber { sub, err := New() @@ -24,7 +24,7 @@ func newSubscriber(t *testing.T, topic string) *Subscriber { return sub } -// Export for testing +// Export for testing. var NewSubscriber = newSubscriber func TestSubscriber(t *testing.T) { @@ -43,11 +43,11 @@ func TestSubscriber(t *testing.T) { if err != nil { t.Error(err) } - if len(msg) != len(TEST_MESSAGE) { - t.Error("Expected message of length", len(TEST_MESSAGE), "Received:", len(msg)) + if len(msg) != len(TestMessage) { + t.Error("Expected message of length", len(TestMessage), "Received:", len(msg)) } - if !reflect.DeepEqual(msg, TEST_MESSAGE) { - t.Error(msg, "!=", TEST_MESSAGE) + if !reflect.DeepEqual(msg, TestMessage) { + t.Error(msg, "!=", TestMessage) } } } @@ -65,7 +65,7 @@ func TestSubscriberTimeout(t *testing.T) { func sendMessages(p *publisher.Publisher) { for !p.IsStopped() { - p.Messages <- []byte(TEST_MESSAGE) + p.Messages <- []byte(TestMessage) time.Sleep(10 * time.Millisecond) } } diff --git a/ecal/subscriber/subscriber.go b/ecal/subscriber/subscriber.go index 32f877d..7dd243e 100644 --- a/ecal/subscriber/subscriber.go +++ b/ecal/subscriber/subscriber.go @@ -10,8 +10,10 @@ package subscriber // const char* const descriptor, size_t descriptor_len // ); import "C" + import ( "errors" + "fmt" "runtime/cgo" "time" "unsafe" @@ -19,6 +21,13 @@ import ( "github.com/DownerCase/ecal-go/ecal/types" ) +var ( + ErrFailedAlloc = errors.New("failed to allocate subscriber") + ErrFailedCreate = errors.New("failed to create subscriber") + ErrRcvTimeout = errors.New("timed out") + ErrRcvBadType = errors.New("receive could not handle type") +) + type Subscriber struct { Messages chan any handle cgo.Handle @@ -38,7 +47,7 @@ func New() (*Subscriber, error) { sub.handle = handle if !C.NewSubscriber(C.uintptr_t(sub.handle)) { handle.Delete() - return nil, errors.New("Failed to allocate new subscriber") + return nil, ErrFailedAlloc } return sub, nil } @@ -57,19 +66,19 @@ func (p *Subscriber) Delete() { } func (p *Subscriber) Create(topic string, datatype DataType) error { - var descriptor_ptr *C.char = nil + var descriptorPtr *C.char = nil if len(datatype.Descriptor) > 0 { - descriptor_ptr = (*C.char)(unsafe.Pointer(&datatype.Descriptor[0])) + descriptorPtr = (*C.char)(unsafe.Pointer(&datatype.Descriptor[0])) } if !C.GoSubscriberCreate( C.uintptr_t(p.handle), topic, datatype.Name, datatype.Encoding, - descriptor_ptr, + descriptorPtr, C.size_t(len(datatype.Descriptor)), ) { - return errors.New("Failed to Create publisher") + return ErrFailedCreate } return nil } @@ -80,7 +89,7 @@ func (p *Subscriber) Receive(timeout time.Duration) ([]byte, error) { case msg := <-p.Messages: return msg.([]byte), nil case <-time.After(timeout): - return nil, errors.New("Receive timed out") + return nil, fmt.Errorf("[Receive]: %w", ErrRcvTimeout) } } diff --git a/ecal/subscriber/subscriber_test.go b/ecal/subscriber/subscriber_test.go index d925f9d..4791fbd 100644 --- a/ecal/subscriber/subscriber_test.go +++ b/ecal/subscriber/subscriber_test.go @@ -8,20 +8,20 @@ import ( "github.com/DownerCase/ecal-go/ecal" "github.com/DownerCase/ecal-go/ecal/publisher" "github.com/DownerCase/ecal-go/internal/ecaltest" - "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_publisher" - "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_subscriber" + testutilpublisher "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_publisher" + testutilsubscriber "github.com/DownerCase/ecal-go/internal/ecaltest/testutil_subscriber" ) -var TEST_MESSAGE = []byte{4, 15, 80} +var TestMessage = []byte{4, 15, 80} func TestSubscriber(t *testing.T) { ecaltest.InitEcal(t) defer ecal.Finalize() // Shutdown eCAL at the end of the program - pub := testutil_publisher.NewGenericPublisher(t, "testing_subscriber") + pub := testutilpublisher.NewGenericPublisher(t, "testing_subscriber") defer pub.Delete() - sub := testutil_subscriber.NewGenericSubscriber(t, "testing_subscriber") + sub := testutilsubscriber.NewGenericSubscriber(t, "testing_subscriber") defer sub.Delete() go sendMessages(pub) @@ -35,11 +35,11 @@ func TestSubscriber(t *testing.T) { if msg == nil { t.Error("Nil message received:") } - if len(msg) != len(TEST_MESSAGE) { - t.Error("Expected message of length", len(TEST_MESSAGE), "Received:", len(msg)) + if len(msg) != len(TestMessage) { + t.Error("Expected message of length", len(TestMessage), "Received:", len(msg)) } - if !reflect.DeepEqual(msg, TEST_MESSAGE) { - t.Error(msg, "!=", TEST_MESSAGE) + if !reflect.DeepEqual(msg, TestMessage) { + t.Error(msg, "!=", TestMessage) } } } @@ -47,7 +47,7 @@ func TestSubscriber(t *testing.T) { func TestSubscriberTimeout(t *testing.T) { ecaltest.InitEcal(t) defer ecal.Finalize() // Shutdown eCAL at the end of the program - sub := testutil_subscriber.NewGenericSubscriber(t, "testing_subscriber_timeout") + sub := testutilsubscriber.NewGenericSubscriber(t, "testing_subscriber_timeout") defer sub.Delete() msg, err := sub.Receive(50 * time.Millisecond) if err == nil { @@ -57,7 +57,7 @@ func TestSubscriberTimeout(t *testing.T) { func sendMessages(p *publisher.Publisher) { for !p.IsStopped() { - p.Messages <- TEST_MESSAGE + p.Messages <- TestMessage time.Sleep(10 * time.Millisecond) } } diff --git a/ecal/types/types.go b/ecal/types/types.go index f44adc2..ad335c4 100644 --- a/ecal/types/types.go +++ b/ecal/types/types.go @@ -2,15 +2,15 @@ package types import "C" -type EntityId struct { - Entity_id string - Process_id int32 - Host_name string +type EntityID struct { + EntityID string + ProcessID int32 + HostName string } -type TopicId struct { - Topic_id EntityId - Topic_name string +type TopicID struct { + TopicID EntityID + TopicName string } type DataType struct { diff --git a/internal/ecaltest/init.go b/internal/ecaltest/init.go index c116365..bd5cc3a 100644 --- a/internal/ecaltest/init.go +++ b/internal/ecaltest/init.go @@ -10,7 +10,7 @@ func InitEcal(t *testing.T, opts ...ecal.ConfigOption) { initResult := ecal.Initialize( ecal.NewConfig(opts...), "Go eCAL!", - ecal.C_Publisher|ecal.C_Subscriber|ecal.C_Logging|ecal.C_Monitoring, + ecal.CPublisher|ecal.CSubscriber|ecal.CLogging|ecal.CMonitoring, ) if initResult != 0 { t.Fatal("Failed to initialize", initResult) diff --git a/internal/ecaltest/protobuf/testutil_publisher/testutil_protobuf_publisher.go b/internal/ecaltest/protobuf/testutil_publisher/testutil_protobuf_publisher.go index 0f0c0d3..3402add 100644 --- a/internal/ecaltest/protobuf/testutil_publisher/testutil_protobuf_publisher.go +++ b/internal/ecaltest/protobuf/testutil_publisher/testutil_protobuf_publisher.go @@ -1,4 +1,4 @@ -package testutil_publisher +package testutilpublisher import ( "testing" @@ -8,7 +8,6 @@ import ( func NewProtobufPublisher[U any, T publisher.Msg[U]](t *testing.T, topic string) *publisher.Publisher[T] { pub, err := publisher.New[U, T]() - if err != nil { t.Error(err) } diff --git a/internal/ecaltest/regtest/test_registration.go b/internal/ecaltest/regtest/test_registration.go index c322965..a9b993e 100644 --- a/internal/ecaltest/regtest/test_registration.go +++ b/internal/ecaltest/regtest/test_registration.go @@ -9,12 +9,12 @@ import ( type Callback struct { Event registration.Event - Id registration.TopicId + ID registration.TopicID } -func EventCallback(topic string, channel chan Callback) func(registration.TopicId, registration.Event) { - return func(id registration.TopicId, event registration.Event) { - if id.Topic_name == topic { +func EventCallback(topic string, channel chan Callback) func(registration.TopicID, registration.Event) { + return func(id registration.TopicID, event registration.Event) { + if id.TopicName == topic { channel <- Callback{event, id} } } @@ -28,9 +28,9 @@ func expectEvent(event registration.Event, t *testing.T, topic string, channel c t.Error("Registration timeout") return } - if response.Id.Topic_name != topic { + if response.ID.TopicName != topic { // Should be pre-filtered by callback - t.Error("Unexpected event for topic", response.Id.Topic_name) + t.Error("Unexpected event for topic", response.ID.TopicName) } else if response.Event != event { t.Error("Expected event", event, "actual", response.Event) } else { @@ -39,9 +39,9 @@ func expectEvent(event registration.Event, t *testing.T, topic string, channel c } func ExpectNew(t *testing.T, topic string, channel chan Callback) { - expectEvent(registration.ENTITY_NEW, t, topic, channel) + expectEvent(registration.EntityNew, t, topic, channel) } func ExpectDeleted(t *testing.T, topic string, channel chan Callback) { - expectEvent(registration.ENTITY_DELETED, t, topic, channel) + expectEvent(registration.EntityDeleted, t, topic, channel) } diff --git a/internal/ecaltest/string/testutil_publisher/testutil_string_publisher.go b/internal/ecaltest/string/testutil_publisher/testutil_string_publisher.go index e7946b8..abe6dac 100644 --- a/internal/ecaltest/string/testutil_publisher/testutil_string_publisher.go +++ b/internal/ecaltest/string/testutil_publisher/testutil_string_publisher.go @@ -8,7 +8,6 @@ import ( func NewStringPublisher(t *testing.T, topic string) *publisher.Publisher { pub, err := publisher.New() - if err != nil { t.Error(err) } diff --git a/internal/ecaltest/testutil_publisher/testutil_publisher.go b/internal/ecaltest/testutil_publisher/testutil_publisher.go index 102b119..c1dceec 100644 --- a/internal/ecaltest/testutil_publisher/testutil_publisher.go +++ b/internal/ecaltest/testutil_publisher/testutil_publisher.go @@ -1,4 +1,4 @@ -package testutil_publisher +package testutilpublisher import ( "testing" diff --git a/internal/ecaltest/testutil_subscriber/testutil_subscriber.go b/internal/ecaltest/testutil_subscriber/testutil_subscriber.go index dd4e7ac..56c31bc 100644 --- a/internal/ecaltest/testutil_subscriber/testutil_subscriber.go +++ b/internal/ecaltest/testutil_subscriber/testutil_subscriber.go @@ -1,4 +1,4 @@ -package testutil_subscriber +package testutilsubscriber import ( "testing" diff --git a/internal/protobuf/protobuf.go b/internal/protobuf/protobuf.go index 8377c81..c3b4b4d 100644 --- a/internal/protobuf/protobuf.go +++ b/internal/protobuf/protobuf.go @@ -1,7 +1,7 @@ package protobuf import ( - "fmt" + "log" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protodesc" @@ -10,7 +10,7 @@ import ( ) func hasFile(fset *descriptorpb.FileDescriptorSet, fname string) bool { - for _, file := range fset.File { + for _, file := range fset.GetFile() { if file.GetName() == fname { return true } @@ -65,7 +65,7 @@ func GetProtoMessageDescription(msg proto.Message) []byte { getFileDescriptor(desc, &pset) bytes, err := proto.Marshal(&pset) if err != nil { - fmt.Println(err) + log.Println("WARN: GetProtoMessageDescription failed to marshal file descriptor set", err) return nil } return bytes diff --git a/main.go b/main.go index 2bebaa5..3013135 100644 --- a/main.go +++ b/main.go @@ -15,15 +15,15 @@ import ( func main() { // eCAL version as string and semantic version components - fmt.Println(ecal.GetVersionString()) - fmt.Println(ecal.GetVersion()) + fmt.Println(ecal.GetVersionString()) //nolint:forbidigo + fmt.Println(ecal.GetVersion()) //nolint:forbidigo // Initialize eCAL with default config, the unit name "Go eCAL", // and the Publisher, Subscriber and Logging components enabled initResult := ecal.Initialize( ecal.NewConfig(), "Go eCAL!", - ecal.C_Publisher|ecal.C_Subscriber|ecal.C_Logging, + ecal.CPublisher|ecal.CSubscriber|ecal.CLogging, ) // Enable all logging levels in the console @@ -51,7 +51,8 @@ func main() { } defer pub.Delete() // Don't forget to delete the publisher when done! - person := &protos.Person{Id: 0, Name: "John", Email: "john@doe.net", + person := &protos.Person{ + Id: 0, Name: "John", Email: "john@doe.net", Dog: &protos.Dog{Name: "Pluto"}, House: &protos.House{Rooms: 5}, } @@ -60,8 +61,8 @@ func main() { panic("Failed to Create protobuf publisher") } - string_pub, _ := string_publisher.New() - if string_pub.Create("string topic") != nil { + stringPublisher, _ := string_publisher.New() + if stringPublisher.Create("string topic") != nil { panic("Failed to Create string publisher") } @@ -88,7 +89,7 @@ func main() { logging.Error(err) } - if err = string_pub.Send("Message ", idx); err != nil { + if err = stringPublisher.Send("Message ", idx); err != nil { logging.Error(err) } @@ -101,13 +102,13 @@ func receiveMessages(s *subscriber.Subscriber) { for { msg, err := s.Receive(2 * time.Second) if err == nil { - fmt.Println("Received:", msg) + fmt.Println("Received:", msg) //nolint:forbidigo } else { - fmt.Println(err) + fmt.Println(err) //nolint:forbidigo } } } -func registrationLogger(id registration.TopicId, event registration.Event) { - fmt.Println("Received registration sample:", id) +func registrationLogger(id registration.TopicID, event registration.Event) { + fmt.Println("Received registration sample:", id) //nolint:forbidigo }