Files
statusServer/statusClient.go
2025-08-24 08:12:25 +02:00

152 lines
4.0 KiB
Go

package statusServer
import (
"encoding/json"
"fmt"
"gitea.tecamino.com/paadi/statusServer/models"
pubSubModels "gitea.tecamino.com/paadi/pubSub/models"
logging "gitea.tecamino.com/paadi/tecamino-logger/logging"
)
// StatusServerClient wraps a websocket client connection to the StatusServer.
// - `id` is the client identifier (service name)
// - `client` is the underlying websocket client
// - `subs` is a map of topic → callback function, used when subscribed messages are received
type StatusClient struct {
id string
client *models.Client
subs map[string]func(data any)
}
// NewCStatuslient connects to a StatusServer websocket endpoint and sets up callbacks.
// serviceName: unique ID/name for this client
// ip, port: target server address
// debug: enable debug logging
func NewStatusClient(serviceName, ip string, port uint, debug bool) (*StatusClient, error) {
config := models.Config{Log: logging.Config{Debug: debug}}
config.Default()
// create logger for this client
logger, err := logging.NewLogger("statusServer.log", &config.Log)
if err != nil {
return nil, err
}
logger.Debug("NewClient", fmt.Sprintf("initialize new client id:%s to %s:%d", serviceName, ip, port))
// build client wrapper
sc := StatusClient{
id: serviceName,
subs: map[string]func(data any){}, // no subscriptions yet
}
// connect underlying websocket client
sc.client, err = models.NewClient(ip, serviceName, port, logger)
if err != nil {
return nil, err
}
// --- EVENT HANDLERS ---
// connection opened
sc.client.OnOpen = func() {
logger.Info("Client", fmt.Sprintf("id:%s connected to %s:%d", serviceName, ip, port))
}
// message received from server
sc.client.OnMessage = func(data []byte) {
var p pubSubModels.Data
err := json.Unmarshal(data, &p)
if err != nil {
logger.Error("OnMessage", err.Error())
return
}
// if we have a subscription callback for this topic, call it
if f, ok := sc.subs[p.Topic]; ok {
f(p.Data)
}
}
// warning received
sc.client.OnWarning = func(warn string) {
logger.Warning("Client", warn)
}
// error received
sc.client.OnError = func(err error) {
logger.Error("Client", err.Error())
}
// connection closed
sc.client.OnClose = func(code int, reason string) {
logger.Info("Client", fmt.Sprintf("id:%s closed connection to %s:%d", serviceName, ip, port))
}
return &sc, err
}
// Subscribe sends a "subscribe" action for a topic to the server and registers
// a local callback to handle messages for that topic.
func (sc *StatusClient) Subscribe(topic string, cb func(any)) error {
var data pubSubModels.Data
data.Action = "subscribe"
data.Topic = topic
// send subscribe request to server
b, err := json.Marshal(data)
if err != nil {
return err
}
sc.client.SendData(b)
// register callback for topic
sc.subs[topic] = cb
return nil
}
// Publish sends a "publish" action with a payload to the server.
// The server will then deliver this message to all subscribers of the topic.
func (sc *StatusClient) Publish(topic string, data any) error {
var payload pubSubModels.Data
payload.Action = "publish"
payload.Topic = topic
payload.Data = data
b, err := json.Marshal(payload)
if err != nil {
return err
}
sc.client.SendData(b)
return nil
}
// --- Sending helpers (proxy to server messaging system) ---
// SendInfo sends an "info" message to the server.
func (sc *StatusClient) SendInfo(data any) error {
return sc.client.SendInfo(data)
}
// SendInfo sends an "status" message to the server.
func (sc *StatusClient) SendStatus(data any) error {
return sc.client.SendStatus(data)
}
// SendDebug sends a "debug" message to the server.
func (sc *StatusClient) SendDebug(data any) error {
return sc.client.SendDebug(data)
}
// SendWarning sends a "warning" message to the server.
func (sc *StatusClient) SendWarning(data any) error {
return sc.client.SendWarning(data)
}
// SendError sends an "error" message to the server.
func (sc *StatusClient) SendError(data any) error {
return sc.client.SendError(data)
}