commit 0e85c04ca5c95b3e8b22e3920fab26a878dc5038 Author: moxitech Date: Wed Oct 23 04:51:07 2024 +0700 Skelet diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..f48affc --- /dev/null +++ b/Readme.md @@ -0,0 +1,11 @@ +##### GO - ZABBIX - WIREN + + +Программа подключается к удаленному хосту zabbix и инициализирует wirenboard-датчики +ПОсле начинает отправлять данные на сервер. + +Configurator - загрузчик конфигурации, etc.. +Zabbix - драйвер соединения zabbix +Dumper - модуль для промежуточного логгирования|сохранения локально +Dashboard - локальный ui с ручками для изменения конфигураций +Sensors-API - api для считывания показаний сенсоров/датчиков diff --git a/app/main.go b/app/main.go new file mode 100644 index 0000000..98422b7 --- /dev/null +++ b/app/main.go @@ -0,0 +1,19 @@ +package main + +// загрузить настройку +// инициализировать подключение к zabbix +// инициализировать датчики +// запустить локальную веб-ручку для настройки +// Записывать в local-db | local-file результаты измерений и асинхронно отправлять в zabbix + +func main() { + // conn, err := zabbix.NewZabbixSNMP("", "Admin", "zabbix") + // if err != nil { + // fmt.Println("[MAIN] :: Ошибка подключения к zabbix") + // } + // val, err := conn.ExampleMethod() + // if err != nil { + // panic(err) + // } + // fmt.Println("OK", val) +} diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..0118c97 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,40 @@ +# TEST +version: '3.7' + +services: + zabbix-server: + image: zabbix/zabbix-server-mysql:alpine-6.0-latest + environment: + - DB_SERVER_HOST=zabbix-mysql + - MYSQL_USER=root + - MYSQL_PASSWORD=zabbix_pwd + - MYSQL_DATABASE=zabbix + depends_on: + - zabbix-mysql + ports: + - "10051:10051" + + zabbix-web: + image: zabbix/zabbix-web-nginx-mysql:alpine-6.0-latest + environment: + - DB_SERVER_HOST=zabbix-mysql + - MYSQL_USER=root + - MYSQL_PASSWORD=zabbix_pwd + - MYSQL_DATABASE=zabbix + - ZBX_SERVER_HOST=zabbix-server + depends_on: + - zabbix-server + ports: + - "8080:8080" + + zabbix-mysql: + image: mysql:8.0 + environment: + - MYSQL_ROOT_PASSWORD=zabbix_pwd + - MYSQL_DATABASE=zabbix + volumes: + - zabbix-mysql-data:/var/lib/mysql + +volumes: + zabbix-mysql-data: + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0f57c05 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module git.moxitech.ru/moxitech/msu_wz_universal + +go 1.22.7 + +require ( + github.com/cavaliercoder/go-zabbix v0.0.0-20230131181515-93725c39d639 // indirect + github.com/gosnmp/gosnmp v1.38.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ef8abbb --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/cavaliercoder/go-zabbix v0.0.0-20230131181515-93725c39d639 h1:eDTc0yCGN1XoC8M1Nb21GbncV0LCuP4DGroC38YBX1o= +github.com/cavaliercoder/go-zabbix v0.0.0-20230131181515-93725c39d639/go.mod h1:o9iZ0ep18zjkTdG1yoCmBZSMAWo2qUXVMxqmEl+6GLo= +github.com/gosnmp/gosnmp v1.38.0 h1:I5ZOMR8kb0DXAFg/88ACurnuwGwYkXWq3eLpJPHMEYc= +github.com/gosnmp/gosnmp v1.38.0/go.mod h1:FE+PEZvKrFz9afP9ii1W3cprXuVZ17ypCcyyfYuu5LY= diff --git a/internal/configurator/conf.go b/internal/configurator/conf.go new file mode 100644 index 0000000..0d1ed1b --- /dev/null +++ b/internal/configurator/conf.go @@ -0,0 +1,12 @@ +package configurator + +type Config struct { +} + +func NewStandartConfig() *Config { + return &Config{} +} + +func ReadConfig() *Config { + return &Config{} +} diff --git a/internal/dashboard/dashboard.go b/internal/dashboard/dashboard.go new file mode 100644 index 0000000..cfdd5f8 --- /dev/null +++ b/internal/dashboard/dashboard.go @@ -0,0 +1 @@ +package dashboard diff --git a/internal/dashboard/template/template.html b/internal/dashboard/template/template.html new file mode 100644 index 0000000..e69de29 diff --git a/internal/dumper/dumper.go b/internal/dumper/dumper.go new file mode 100644 index 0000000..270fc6a --- /dev/null +++ b/internal/dumper/dumper.go @@ -0,0 +1 @@ +package dumper diff --git a/internal/models.go b/internal/models.go new file mode 100644 index 0000000..d8eb7c0 --- /dev/null +++ b/internal/models.go @@ -0,0 +1,14 @@ +package internal + +// Sensor - структура для передачи данных с датчика +type Sensor struct { + Id int `json:"id"` + Temperature float64 `json:"tc"` + Humindity float64 `json:"hm"` + Ts int64 `json:"ts"` +} + +// SensorBlock - структура для передачи данных нескольких датчиков +type SensorBlock struct { + Sensors []Sensor `json:"sensors"` +} diff --git a/internal/zabbix/driver.go b/internal/zabbix/driver.go new file mode 100644 index 0000000..b027a3d --- /dev/null +++ b/internal/zabbix/driver.go @@ -0,0 +1,158 @@ +package zabbix + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "time" + + "github.com/gosnmp/gosnmp" +) + +type ZabbixSNMP struct { + Target string + Port uint16 + Community string + Version gosnmp.SnmpVersion +} + +type Sensor struct { + ID string `json:"id"` + TC float64 `json:"tc"` + PA float64 `json:"pa"` + TS int64 `json:"ts"` +} + +// NewZabbixSNMP creates a new instance of ZabbixSNMP with default SNMP parameters +func NewZabbixSNMP(target string, community string, version gosnmp.SnmpVersion) *ZabbixSNMP { + return &ZabbixSNMP{ + Target: target, + Port: 161, + Community: community, + Version: version, + } +} + +// Get retrieves a value from the SNMP target for the specified OID +func (z *ZabbixSNMP) Get(oid string) (interface{}, error) { + snmp := &gosnmp.GoSNMP{ + Target: z.Target, + Port: z.Port, + Community: z.Community, + Version: z.Version, + Timeout: time.Duration(2) * time.Second, + Retries: 1, + } + + err := snmp.Connect() + if err != nil { + return nil, fmt.Errorf("failed to connect: %v", err) + } + defer snmp.Conn.Close() + + response, err := snmp.Get([]string{oid}) + if err != nil { + return nil, fmt.Errorf("failed to get oid: %v", err) + } + + if len(response.Variables) < 1 { + return nil, fmt.Errorf("no result found for oid: %s", oid) + } + + return formatSNMPValue(response.Variables[0]), nil +} + +// formatSNMPValue formats the SNMP value based on its type +func formatSNMPValue(pdu gosnmp.SnmpPDU) interface{} { + switch pdu.Type { + case gosnmp.OctetString: + return string(pdu.Value.([]byte)) + default: + return pdu.Value + } +} + +// Walk retrieves all values under the provided OID prefix +func (z *ZabbixSNMP) Walk(oid string) (map[string]interface{}, error) { + snmp := &gosnmp.GoSNMP{ + Target: z.Target, + Port: z.Port, + Community: z.Community, + Version: z.Version, + Timeout: time.Duration(2) * time.Second, + Retries: 1, + } + + err := snmp.Connect() + if err != nil { + return nil, fmt.Errorf("failed to connect: %v", err) + } + defer snmp.Conn.Close() + + results := make(map[string]interface{}) + err = snmp.Walk(oid, func(pdu gosnmp.SnmpPDU) error { + results[pdu.Name] = formatSNMPValue(pdu) + return nil + }) + if err != nil { + return nil, fmt.Errorf("failed to walk oid: %v", err) + } + + return results, nil +} + +// SendSensorData sends sensor data to a remote Zabbix server +func SendSensorData(url string, sensor Sensor) error { + data, err := json.Marshal(sensor) + if err != nil { + return fmt.Errorf("failed to marshal sensor data: %v", err) + } + + resp, err := http.Post(url, "application/json", bytes.NewBuffer(data)) + if err != nil { + return fmt.Errorf("failed to send data to Zabbix: %v", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("received non-OK response from Zabbix: %d", resp.StatusCode) + } + + return nil +} + +// Example usage +func Example() { + snmpClient := NewZabbixSNMP("192.168.1.1", "public", gosnmp.Version2c) + + // Get a specific OID value + value, err := snmpClient.Get("1.3.6.1.2.1.1.1.0") + if err != nil { + fmt.Printf("Error: %v\n", err) + return + } + fmt.Printf("Value: %v\n", value) + + // Walk a subtree of OIDs + values, err := snmpClient.Walk("1.3.6.1.2.1.1") + if err != nil { + fmt.Printf("Error: %v\n", err) + return + } + for k, v := range values { + fmt.Printf("%s: %v\n", k, v) + } + + // Send sensor data to Zabbix server + sensor := Sensor{ + ID: "sensor123", + TC: 23.5, + PA: 101.3, + TS: time.Now().Unix(), + } + err = SendSensorData("http://zabbix-server/api/sensordata", sensor) + if err != nil { + fmt.Printf("Error sending sensor data: %v\n", err) + } +}