/
managerweb.go
167 lines (137 loc) · 6.75 KB
/
managerweb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package main
import (
"github.com/labstack/echo"
mid "github.com/labstack/echo/middleware"
"net/http"
"fmt"
"strconv"
"encoding/json"
"golang.org/x/net/websocket"
)
// ManagerWeb основная стркутура объекта Менеджер веб-интерфейса
type ManagerWeb struct {
e *echo.Echo
Sign chan Action // канал по которому передается команда добавления/удаления вебсокета (нового подключения веб-клиента)
Listch []chan Alarm // массив активных веб-клиентов
// TODO структура менеджера веб-интерфейса
}
// Action структура действий с массивом активных вебсокетов
type Action struct {
Command string // команда
Channel chan Alarm // канал, который слушает активный вебсокет. При получении сигнала обновляет информацию на веб-интерфейсе
}
// Alarm сигнал, который вызывает обновление информации в списке ботов и отправки ее по вебсокету
type Alarm struct {
}
func newManagerWeb() (*ManagerWeb, error) {
mw := &ManagerWeb{}
return mw, nil
}
//Start метод запускает веб-интерфейс
func (mw *ManagerWeb) Start() error {
go func() {
if mw.e == nil {
mw.e = echo.New()
}
mw.e.Use(mid.Logger()) // выводить лог
//mw.e.Use(mid.Recover()) // игнорировать ошибки при работе сервера
mw.e.Get("/", hello) // будущая основная страница
//api
mw.e.Get("/api/bots", listBot) // вывести json-список текущих ботов
mw.e.Post("/api/bots", createBot) // создать нового бота
mw.e.Patch("/api/bot/:id/:action", sendActionToBot) // отправить основные команды боту (старт, стоп...)
mw.e.Delete("/api/bot/:id", deleteBot) // удалить бота
//websocket
mw.e.WebSocket("/bots/ws", mw.websockDataBots) // вебсокет для динамического обновления информация по списку ботов
// служебные вызовы на время разработки
mw.e.Get("/api/bots/upd", mw.updateInfBots) // иницировать обновление информации в списке ботов
// TODO инициализация настроек сервера (ip с которых можно принимать запросы, порт и т.д.)
mw.e.Run(":8080")
}()
return nil
}
// manager фоновая горутина, отслеживает актуальный список подключившихся веб-клиентов
func (mw *ManagerWeb) manager(ch <-chan Action) {
for {
act := <-ch // получить команду
switch act.Command {
case "add": // добавить в масиив канал, который слушает новый вебсокет
mw.Listch = append(mw.Listch, act.Channel)
case "del": // удалить из массива канал
for i:= 0; i < len(mw.Listch); i++ {
if mw.Listch[i] == act.Channel {
mw.Listch = append(mw.Listch[:i], mw.Listch[i+1:]...)
break
}
}
}
fmt.Println(mw.Listch)
}
}
// websockDataBots метод отправляет по вебсокету к веб-клиенту обновленную информацию по ботам при получении сигнала из канала
func (mw *ManagerWeb) websockDataBots(c *echo.Context) error {
act := Action{} // структура действий с массивом активных вебсокетов (добавить, удалить...)
ws := c.Socket() // открытый вебсокет
ch := make(chan Alarm) // канал, по сигналу которого будет отправляться обновленная информация по боту на веб-клиенту через вебсокет
act.Command = "add" // добавить информацию по новому каналу и вебсокету
act.Channel = ch
mw.Sign <- act // в массив активных вебсокетов
defer func() {
actdef := Action{}
actdef.Command = "del" // при закрытии вебсокета
actdef.Channel = ch
mw.Sign <- actdef // удалить из массива вебсокет и канал
}()
type List struct { // структура с данными, которые необходимо отправить на веб-клиент по вебсокету
ID int `json:"id"` // идентификатор бота
Name string `json:"name"` // имя бота
}
ind := 0
for {
var st List // создать структуру с данными бота
st.ID = ind
st.Name = "name-" + strconv.Itoa(ind)
msg, _ := json.Marshal(st) // сконвертировать структуру для отправки по вебсокету
err := websocket.Message.Send(ws, string(msg)) // отправить данные веб-клиенту по вебсокету
if err != nil {
return err
}
<-ch // ждать следующего сигнала для обновления информации
ind++
}
//return nil
}
// updateInfBots посылает сигнал всем обработчикам вебсокетов (websockDataBots) о том, что нужно обновить информацию на веб-клиентах
func (mw *ManagerWeb) updateInfBots(c *echo.Context) error {
// перебрать массив каналов активных вебсокетов
for i:=0; i<len(mw.Listch);i++ {
ch := mw.Listch[i]
ch <- Alarm{} // каждому отправить сигнал, что необходимо обновить информацию на веб-клиенте
}
fmt.Println(mw.Listch)
return c.String(http.StatusOK, "ok\n")
}
//Stop метод останавливает веб-интерфейс
func (mw *ManagerWeb) Stop() error {
// TODO остановка веб-интерфейса
return nil
}
//Restart метод останавливает и запускает (перезапускает) веб-интерфейс
func (mw *ManagerWeb) Restart() error {
var err error
// остановить веб-интерфейс
err = mw.Stop()
if err != nil {
return err
}
// запустить веб-интерфейс
err = mw.Start()
if err != nil {
return err
}
return nil
}
func hello(c *echo.Context) error {
// TODO когда-нибудь будет выводить основную страницу
return c.String(http.StatusOK, "ok\n")
}