feat: 调整IOT社区版目录

This commit is contained in:
willem
2025-09-03 14:21:09 +08:00
parent f2d4e9484c
commit 367f11e076
30 changed files with 845 additions and 138 deletions

71
command/cmd.go Normal file
View File

@@ -0,0 +1,71 @@
package command
import (
"context"
"fmt"
"os"
"os/signal"
"sagooiot/internal/sse"
"syscall"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gcmd"
)
func runMain(ctx context.Context, s *ghttp.Server) error {
var signalChannel = make(chan os.Signal, 1)
enablePProf := g.Cfg().MustGet(context.Background(), "system.enablePProf").Bool()
if enablePProf {
pprofPort := g.Cfg().MustGet(context.Background(), "system.pprofPort").String()
if pprofPort == "" {
pprofPort = "58089"
}
RunSystemAnalysis(signalChannel, pprofPort) // 运行系统分析
}
deferFuncListIotCore, err := InitSystemDeferFunc(ctx)
defer func() {
for _, f := range deferFuncListIotCore {
if f == nil {
continue
}
if deferErr := f(ctx); deferErr != nil {
fmt.Printf("defer func error: %s\n", deferErr.Error())
}
}
}()
err = InitSystem(ctx, InitFuncNoDeferListForIotCore)
if err != nil {
fmt.Printf("defer func error: %s\n", err.Error())
}
err = InitSystem(ctx, InitFuncNoDeferListWebAdmin)
if err != nil {
fmt.Printf("defer func error: %s\n", err.Error())
}
sse.Init() // 启动SSE推送
RunServer(ctx, signalChannel, s)
signal.Notify(signalChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
fmt.Println("收到关闭服务信号:", <-signalChannel)
time.Sleep(time.Second * 3)
fmt.Println("成功关闭服务器")
return nil
}
// NewMainCommand creates a new gcmd.Command with a custom server getter function
func NewMainCommand(s *ghttp.Server) gcmd.Command {
return gcmd.Command{
Name: "main",
Usage: "main [options]",
Brief: "start sagoo-iot server",
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
return runMain(ctx, s)
},
}
}

View File

@@ -1,4 +1,4 @@
package cmd
package command
import (
"github.com/gogf/gf/v2/net/ghttp"

View File

@@ -1,11 +1,7 @@
package cmd
package command
import (
"context"
"github.com/gogf/gf/contrib/trace/jaeger/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gmode"
"sagooiot/internal/consts"
"sagooiot/internal/logic/analysis"
"sagooiot/pkg/cache"
@@ -13,6 +9,11 @@ import (
"sagooiot/pkg/statistics"
"sagooiot/pkg/utility/helper"
"sagooiot/utility/validate"
"github.com/gogf/gf/contrib/trace/jaeger/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gmode"
)
func AllSystemInit(ctx context.Context) {

View File

@@ -1,8 +1,9 @@
package cmd
package command
import (
"context"
"fmt"
_ "sagooiot/internal/logic"
"sagooiot/internal/service"
"sagooiot/network"
"sagooiot/network/core/logic/model"

View File

@@ -1,4 +1,4 @@
package cmd
package command
import (
"context"

View File

@@ -1,4 +1,4 @@
package cmd
package command
import (
"context"

View File

@@ -1,4 +1,4 @@
package cmd
package command
import (
"context"

View File

@@ -2,9 +2,10 @@ package router
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
analysisController "sagooiot/internal/controller/analysis"
"sagooiot/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// Analysis 分析统计相关的接口

View File

@@ -2,14 +2,14 @@ package router
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
oauthController "sagooiot/internal/controller/oauth"
"github.com/gogf/gf/v2/net/ghttp"
)
// Analysis 分析统计相关的接口
func OAuth(ctx context.Context, group *ghttp.RouterGroup) {
group.Group("/oauth", func(group *ghttp.RouterGroup) {
//group.Middleware(service.Middleware().Auth)
group.Bind(
oauthController.OProvider, // 第三方授权配置提供
oauthController.OUser, // 第三方授权用户登录

View File

@@ -2,10 +2,11 @@ package router
import (
"context"
"github.com/gogf/gf/v2/net/ghttp"
commonController "sagooiot/internal/controller/common"
systemController "sagooiot/internal/controller/system"
"sagooiot/internal/service"
"github.com/gogf/gf/v2/net/ghttp"
)
// System 系统默认功能的路由,不含业务属性的
@@ -49,10 +50,8 @@ func System(ctx context.Context, group *ghttp.RouterGroup) {
systemController.SysOperLog, //操作日志管理
systemController.SysLoginLog, //访问日志管理
systemController.SysJob, //定时任务管理
systemController.SysJobLog, //定时任务日志
systemController.SysJob, //定时任务管理
systemController.SysJobLog, //定时任务日志
systemController.SysUserOnline, //在线用户
systemController.SysNotifications, //消息中心

View File

@@ -1,21 +1,30 @@
package cmd
package command
import (
"context"
"expvar"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/util/gmode"
"os"
"sagooiot/internal/cmd/router"
"os/signal"
"runtime/debug"
router2 "sagooiot/command/router"
"sagooiot/internal/service"
"sagooiot/internal/sse"
"sagooiot/module"
"sagooiot/pkg/utility"
"syscall"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/util/gmode"
)
func RunServer(ctx context.Context, stopSignal chan os.Signal) {
type SagooIoTApp struct {
Server *ghttp.Server
ApiRouterGroup *ghttp.RouterGroup
}
func GetServer(ctx context.Context) SagooIoTApp {
var s = g.Server()
// 自定义丰富文档
enhanceOpenAPIDoc(s)
@@ -59,7 +68,7 @@ func RunServer(ctx context.Context, stopSignal chan os.Signal) {
group.GET("/logInfo", sse.LogInfoEvent)
})
s.Group("/api/v1", func(group *ghttp.RouterGroup) {
apiV1 := s.Group("/api/v1", func(group *ghttp.RouterGroup) {
group.Middleware(
service.Middleware().Ctx,
service.Middleware().ResponseHandler,
@@ -67,11 +76,11 @@ func RunServer(ctx context.Context, stopSignal chan os.Signal) {
service.Middleware().I18n,
)
service.SysToken().GfToken().Middleware(group)
router.System(ctx, group) //系统默认功能的路由
router.Iot(ctx, group) //Iot功能的路由
router.Analysis(ctx, group) //分析统计功能的路由
module.Router(ctx, group) //加载模块的路由
router.OAuth(ctx, group) //第三方授权登录
router2.System(ctx, group) //系统默认功能的路由
router2.Iot(ctx, group) //Iot功能的路由
router2.Analysis(ctx, group) //分析统计功能的路由
router2.OAuth(ctx, group) //oauth2
module.Router(ctx, group) //加载模块的路由
})
@@ -85,12 +94,27 @@ func RunServer(ctx context.Context, stopSignal chan os.Signal) {
s.EnablePProf() //打开pprof性能分析工具不需要的时候可以注掉
}
return SagooIoTApp{
s,
apiV1,
}
}
func RunServer(ctx context.Context, stopSignal chan os.Signal, s *ghttp.Server) {
go func() {
defer func() {
if err := recover(); err != nil {
fmt.Println("panic 产生,错误:", err)
g.Log().Debugf(ctx, "RunServer: panic 产生,错误:%s", err)
}
}()
//捕获panic意处出错进行出错信息记录
loggerPath := g.Cfg().MustGet(context.Background(), "logger.path").String()
err := debug.SetCrashOutput(utility.InitFatalLog(loggerPath), debug.CrashOptions{})
if err != nil {
g.Log().Error(ctx, err)
}
// https
https := g.Cfg().MustGet(ctx, "server.https").Bool()
if https {
@@ -99,11 +123,36 @@ func RunServer(ctx context.Context, stopSignal chan os.Signal) {
s.EnableHTTPS(certFile, keyFile)
}
go s.Run()
select {
case <-ctx.Done():
}
s.Run()
stopSignal <- syscall.SIGQUIT
}()
// 在程序退出信号处理中添加协程清理
// 监听系统信号
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() {
sig := <-sigChan
g.Log().Infof(ctx, "接收到信号 %v开始优雅关闭...", sig)
// 优雅关闭各个组件,防止协程泄漏
shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// 4. 关闭HTTP服务器
if s != nil {
g.Log().Info(shutdownCtx, "关闭HTTP服务器...")
if err := s.Shutdown(); err != nil {
g.Log().Errorf(shutdownCtx, "HTTP服务器关闭失败: %v", err)
}
}
// 5. 给协程一些时间完成清理
time.Sleep(2 * time.Second)
g.Log().Info(shutdownCtx, "优雅关闭完成")
os.Exit(0)
}()
return
}

25
go.mod
View File

@@ -1,6 +1,8 @@
module sagooiot
go 1.21
go 1.23.0
toolchain go1.24.4
require (
github.com/Knetic/govaluate v3.0.0+incompatible
@@ -10,13 +12,15 @@ require (
github.com/gogf/gf/contrib/nosql/redis/v2 v2.6.2
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.6.2
github.com/gogf/gf/v2 v2.6.2
github.com/golang-jwt/jwt/v5 v5.0.0
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/golang-module/carbon/v2 v2.2.8
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75
github.com/gorilla/sessions v1.4.0
github.com/gorilla/websocket v1.5.1
github.com/hashicorp/go-plugin v1.6.0
github.com/hibiken/asynq v0.24.1
github.com/hpcloud/tail v1.0.0
github.com/markbates/goth v1.82.0
github.com/minio/minio-go/v7 v7.0.66
github.com/mojocn/base64Captcha v1.3.6
github.com/mssola/useragent v1.0.0
@@ -24,12 +28,14 @@ require (
github.com/redis/go-redis/v9 v9.3.1
github.com/robertkrimen/otto v0.3.0
github.com/shirou/gopsutil/v3 v3.23.11
github.com/stretchr/testify v1.9.0
github.com/taosdata/driver-go/v3 v3.5.1
github.com/tealeg/xlsx v1.0.5
github.com/tencentyun/cos-go-sdk-v5 v0.7.45
github.com/xinjiayu/sse v1.0.1
github.com/xuri/excelize/v2 v2.8.0
go.opentelemetry.io/otel v1.18.0
golang.org/x/oauth2 v0.27.0
)
require (
@@ -37,6 +43,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/color v1.15.0 // indirect
@@ -49,6 +56,7 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
github.com/hashicorp/go-hclog v0.14.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
@@ -70,6 +78,7 @@ require (
github.com/mozillazg/go-httpheader v0.2.1 // indirect
github.com/oklog/run v1.0.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.3 // indirect
@@ -88,18 +97,16 @@ require (
go.opentelemetry.io/otel/metric v1.18.0 // indirect
go.opentelemetry.io/otel/sdk v1.18.0 // indirect
go.opentelemetry.io/otel/trace v1.18.0 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/crypto v0.35.0 // indirect
golang.org/x/image v0.13.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.16.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529 // indirect
google.golang.org/grpc v1.56.1 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/fsnotify.v1 v1.4.7 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect

48
go.sum
View File

@@ -53,8 +53,8 @@ github.com/gogf/gf/contrib/trace/jaeger/v2 v2.6.2 h1:MChoSivlMZS1Cw6is6u+kBmjdV3
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.6.2/go.mod h1:yI+aJpR6kU1ATLaRaCzI1o7fY/HNDDCfR5RS3mPNr0s=
github.com/gogf/gf/v2 v2.6.2 h1:TvI1UEH2RDbgFVlJJjkc/6ct6+5zjbOS5MiJ2ESG8qg=
github.com/gogf/gf/v2 v2.6.2/go.mod h1:x2XONYcI4hRQ/4gMNbWHmZrNzSEIg20s2NULbzom5k0=
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-module/carbon/v2 v2.2.8 h1:a1VxHHKAR7fc1ho7sYXhS1s5S4x7+oqAf2EY5p8C46A=
github.com/golang-module/carbon/v2 v2.2.8/go.mod h1:XDALX7KgqmHk95xyLeaqX9/LJGbfLATyruTziq68SZ8=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
@@ -71,6 +71,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -78,6 +80,10 @@ github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY=
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
@@ -103,7 +109,6 @@ github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -115,6 +120,8 @@ github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0g
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/markbates/goth v1.82.0 h1:8j/c34AjBSTNzO7zTsOyP5IYCQCMBTRBHAbBt/PI0bQ=
github.com/markbates/goth v1.82.0/go.mod h1:/DRlcq0pyqkKToyZjsL2KgiA1zbF1HIjE7u2uC79rUk=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@@ -176,8 +183,8 @@ github.com/robertkrimen/otto v0.3.0 h1:5RI+8860NSxvXywDY9ddF5HcPw0puRsd8EgbXV0oq
github.com/robertkrimen/otto v0.3.0/go.mod h1:uW9yN1CYflmUQYvAMS0m+ZiNo3dMzRUDQJX0jWbzgxw=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ=
@@ -193,15 +200,17 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/taosdata/driver-go/v3 v3.5.1 h1:ln8gLJ6HR6gHU6dodmOa9utUjPUpAcdIplh6arFO26Q=
github.com/taosdata/driver-go/v3 v3.5.1/go.mod h1:H2vo/At+rOPY1aMzUV9P49SVX7NlXb3LAbKw+MCLrmU=
github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
@@ -242,8 +251,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg=
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
@@ -260,14 +269,16 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -287,8 +298,9 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -301,8 +313,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
@@ -312,8 +324,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -1,67 +0,0 @@
package cmd
import (
"context"
"fmt"
"os"
"os/signal"
"sagooiot/internal/sse"
"syscall"
"time"
"sagooiot/internal/logic/tdengine"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
)
var (
Main = gcmd.Command{
Name: "main",
Usage: "main",
Brief: "start sagoo-iot server",
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
var signalChannel = make(chan os.Signal, 1)
enablePProf := g.Cfg().MustGet(context.Background(), "system.enablePProf").Bool()
if enablePProf {
pprofPort := g.Cfg().MustGet(context.Background(), "system.pprofPort").String()
if pprofPort == "" {
pprofPort = "58089"
}
RunSystemAnalysis(signalChannel, pprofPort) // 运行系统分析
}
deferFuncListIotCore, err := InitSystemDeferFunc(ctx)
defer func() {
for _, f := range deferFuncListIotCore {
if f == nil {
continue
}
if deferErr := f(ctx); deferErr != nil {
fmt.Printf("defer func error: %s\n", deferErr.Error())
}
}
}()
err = InitSystem(ctx, InitFuncNoDeferListForIotCore)
if err != nil {
fmt.Printf("defer func error: %s\n", err.Error())
}
err = InitSystem(ctx, InitFuncNoDeferListWebAdmin)
if err != nil {
fmt.Printf("defer func error: %s\n", err.Error())
}
sse.Init() // 启动SSE推送
RunServer(ctx, signalChannel)
signal.Notify(signalChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
fmt.Println("收到关闭服务信号:", <-signalChannel)
time.Sleep(time.Second * 3)
tdengine.Close()
fmt.Println("成功关闭服务器")
return
},
}
)

20
main.go
View File

@@ -1,17 +1,19 @@
package main
import (
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
_ "github.com/taosdata/driver-go/v3/taosRestful"
_ "github.com/taosdata/driver-go/v3/taosWS"
"sagooiot/command"
_ "sagooiot/internal/logic"
_ "sagooiot/internal/packed"
_ "sagooiot/network/core/logic/model"
"github.com/gogf/gf/v2/os/gctx"
"sagooiot/internal/cmd"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
_ "github.com/taosdata/driver-go/v3/taosRestful"
_ "github.com/taosdata/driver-go/v3/taosWS"
"sagooiot/pkg/utility/version"
"github.com/gogf/gf/v2/os/gctx"
)
var (
@@ -23,6 +25,8 @@ var (
func main() {
version.ShowLogo(BuildVersion, BuildTime, CommitID)
ctx := gctx.GetInitCtx()
cmd.AllSystemInit(ctx)
cmd.Main.Run(ctx)
command.AllSystemInit(ctx)
app := command.GetServer(ctx)
cmd := command.NewMainCommand(app.Server)
cmd.Run(ctx)
}

12
pkg/proxy/alarm_log.go Normal file
View File

@@ -0,0 +1,12 @@
package proxy
import (
"context"
"sagooiot/internal/dao"
proxyModel "sagooiot/pkg/proxy/model"
)
func GetAlarmLogByDeviceKey(ctx context.Context, deviceKeys []string) (out []*proxyModel.AlarmLog, err error) {
err = dao.AlarmLog.Ctx(ctx).WhereIn(dao.AlarmLog.Columns().DeviceKey, deviceKeys).Scan(&out)
return
}

44
pkg/proxy/analysis.go Normal file
View File

@@ -0,0 +1,44 @@
package proxy
import (
"context"
"sagooiot/internal/service"
proxyModel "sagooiot/pkg/proxy/model"
"github.com/gogf/gf/v2/util/gconv"
)
// GetProductCount 获取产品数量统计
func GetProductCount(ctx context.Context) (out proxyModel.ProductCount, err error) {
res, err := service.AnalysisProduct().GetProductCount(ctx)
if err != nil {
return
}
err = gconv.Scan(res, &out)
return
}
// GetDeviceOnlineOfflineCount 获取设备在线离线统计
func GetDeviceOnlineOfflineCount(ctx context.Context) (out proxyModel.DeviceOnlineOfflineCount, err error) {
res, err := service.AnalysisDevice().GetDeviceOnlineOfflineCount(ctx)
if err != nil {
return
}
err = gconv.Scan(res, &out)
return
}
// GetDeviceDataTotalCount 获取设备消息总数统计,dataType :day,month,year
func GetDeviceDataTotalCount(ctx context.Context, dataType string) (number int64, err error) {
return service.AnalysisDevice().GetDeviceDataTotalCount(ctx, dataType)
}
// GetAlarmLevelCount 告警级别统计
func GetAlarmLevelCount(ctx context.Context, dataType, date string) (out []proxyModel.CountData, err error) {
res, err := service.AnalysisAlarm().GetAlarmLevelCount(ctx, dataType, date)
if err != nil {
return
}
err = gconv.Scan(res, &out)
return
}

20
pkg/proxy/config_data.go Normal file
View File

@@ -0,0 +1,20 @@
package proxy
import (
"context"
"sagooiot/internal/service"
"github.com/gogf/gf/v2/util/gconv"
)
// GetConfigMapByKeys 通过key数组获取参数从缓存获取
func GetConfigMapByKeys(ctx context.Context, keys []string) (out map[string]string, err error) {
configInfos, err := service.ConfigData().GetConfigByKeys(ctx, keys)
if err != nil {
return nil, err
}
if err = gconv.Scan(configInfos, &out); err != nil {
return
}
return
}

99
pkg/proxy/dev_device.go Normal file
View File

@@ -0,0 +1,99 @@
package proxy
import (
"context"
"sagooiot/internal/model"
"sagooiot/internal/service"
proxyModel "sagooiot/pkg/proxy/model"
"github.com/gogf/gf/v2/util/gconv"
)
// GetDeviceDetail 获取设备详情
func GetDeviceDetail(ctx context.Context, key string) (out *proxyModel.DeviceOutput, err error) {
detail, err := service.DevDevice().Detail(ctx, key)
if err != nil {
return
}
if detail != nil {
if err = gconv.Scan(detail, &out); err != nil {
return
}
}
return
}
// RunStatus 运行状态
func RunStatus(ctx context.Context, deviceKey string) (out *proxyModel.DeviceRunStatusOutput, err error) {
deviceRunStatusOutput, err := service.DevDevice().RunStatus(ctx, deviceKey)
if err != nil {
return
}
if deviceRunStatusOutput != nil {
if err = gconv.Scan(deviceRunStatusOutput, &out); err != nil {
return
}
}
return
}
func AllProperty(ctx context.Context, key string) (list []proxyModel.TSLProperty, err error) {
propertyOut, err := service.DevTSLProperty().AllProperty(ctx, key)
if err != nil {
return
}
if propertyOut != nil {
if err = gconv.Scan(propertyOut, &list); err != nil {
return
}
}
return
}
// Get 设备详情
func Get(ctx context.Context, deviceKey string) (out *proxyModel.DeviceOutput, err error) {
detail, err := service.DevDevice().Get(ctx, deviceKey)
if err != nil {
return
}
if detail != nil {
if err = gconv.Scan(detail, &out); err != nil {
return
}
}
return
}
func ListForPage(ctx context.Context, input *proxyModel.ListDeviceForPageInput) (total, page int, out []*proxyModel.DeviceOutput, err error) {
var in *model.ListDeviceForPageInput
if err = gconv.Scan(input, &in); err != nil {
return
}
list, err := service.DevDevice().ListForPage(ctx, in)
if err != nil {
return
}
if list != nil {
total, page = list.Total, list.CurrentPage
if err = gconv.Scan(list.Device, &out); err != nil {
return
}
}
return
}
// GetPropertyList 设备属性详情列表
func GetPropertyList(ctx context.Context, input *proxyModel.DeviceGetPropertyListInput) (out *proxyModel.DeviceGetPropertyListOutput, err error) {
var in *model.DeviceGetPropertyListInput
if err = gconv.Scan(input, &in); err != nil {
return
}
data, err := service.DevDevice().GetPropertyList(ctx, in)
if err != nil {
return
}
if data != nil {
err = gconv.Scan(data, &out)
}
return
}

View File

@@ -0,0 +1,21 @@
package model
import "github.com/gogf/gf/v2/os/gtime"
type AlarmLog struct {
Id int64 `json:"id" description:""`
DeptId int `json:"deptId" description:"部门ID"`
Type uint `json:"type" description:"告警类型1=规则告警2=设备自主告警"`
RuleId uint64 `json:"ruleId" description:"规则id"`
RuleName string `json:"ruleName" description:"规则名称"`
Level uint `json:"level" description:"告警级别"`
Data string `json:"data" description:"触发告警的数据"`
Expression string `json:"expression" description:"触发告警的表达式"`
ProductKey string `json:"productKey" description:"产品标识"`
DeviceKey string `json:"deviceKey" description:"设备标识"`
Status int `json:"status" description:"告警状态0=未处理1=已处理"`
CreatedAt *gtime.Time `json:"createdAt" description:"告警时间"`
UpdatedBy uint `json:"updatedBy" description:"告警处理人员"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"处理时间"`
Content string `json:"content" description:"处理意见"`
}

View File

@@ -0,0 +1,23 @@
package model
// ProductCount 产品数量统计
type ProductCount struct {
Total int `json:"total"` // 产品总数
Disable int `json:"disable"` // 禁用产品数
Enable int `json:"enable"` // 启用产品数
Added int `json:"added"` // 新增产品数
}
// DeviceOnlineOfflineCount 设备在线离线状态统计
type DeviceOnlineOfflineCount struct {
Total int `json:"total"` // 设备总数
Online int `json:"online"` // 在线设备数
Offline int `json:"offline"` // 离线设备数
Disable int `json:"disable"` // 禁用设备数
}
// CountData 统计数据
type CountData struct {
Title string
Value int64
}

View File

@@ -0,0 +1,24 @@
package model
import "github.com/gogf/gf/v2/os/gtime"
type ConfigureDiagramOut struct {
Id int `json:"id" description:""`
Code string `json:"code" description:""`
DeptId int `json:"deptId" description:"部门ID"`
FolderId int `json:"folderId" description:"文件夹ID"`
Name string `json:"name" description:"名字"`
Types int `json:"types" description:"类型"`
Images string `json:"images" description:"图片"`
PointIds []map[string]string `json:"pointIds" description:""`
JsonData string `json:"jsonData" description:""`
Remark string `json:"remark" description:""`
Status int `json:"status" description:"状态 0 停用 1启用"`
IsDeleted int `json:"isDeleted" description:"是否删除 0未删除 1已删除"`
CreatedBy uint `json:"createdBy" description:"创建人"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedBy int `json:"updatedBy" description:"修改人"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"`
DeletedBy int `json:"deletedBy" description:"删除人"`
DeletedAt *gtime.Time `json:"deletedAt" description:"删除时间"`
}

View File

@@ -0,0 +1,69 @@
package model
import "github.com/gogf/gf/v2/os/gtime"
type SyncProduct struct {
TenantCode string `json:"tenantCode" description:"租户code"`
Id uint `json:"id" description:""`
DeptId int `json:"deptId" description:"部门ID"`
Key string `json:"key" description:"产品标识"`
Name string `json:"name" description:"产品名称"`
CategoryId uint `json:"categoryId" description:"所属品类"`
MessageProtocol string `json:"messageProtocol" description:"消息协议"`
TransportProtocol string `json:"transportProtocol" description:"传输协议: MQTT,COAP,UDP"`
ProtocolId uint `json:"protocolId" description:"协议id"`
DeviceType string `json:"deviceType" description:"设备类型: 网关,设备,子设备"`
Desc string `json:"desc" description:"描述"`
Icon string `json:"icon" description:"图片地址"`
Metadata string `json:"metadata" description:"物模型"`
MetadataTable int `json:"metadataTable" description:"是否生成物模型表0=否1=是"`
Policy string `json:"policy" description:"采集策略"`
Status int `json:"status" description:"发布状态0=未发布1=已发布"`
AuthType int `json:"authType" description:"认证方式1=Basic2=AccessToken3=证书)"`
AuthUser string `json:"authUser" description:"认证用户"`
AuthPasswd string `json:"authPasswd" description:"认证密码"`
AccessToken string `json:"accessToken" description:"AccessToken"`
CertificateId int `json:"certificateId" description:"证书ID"`
ScriptInfo string `json:"scriptInfo" description:"脚本信息"`
CreatedBy uint `json:"createdBy" description:"创建者"`
UpdatedBy uint `json:"updatedBy" description:"更新者"`
DeletedBy uint `json:"deletedBy" description:"删除者"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"`
DeletedAt *gtime.Time `json:"deletedAt" description:"删除时间"`
}
type SyncDevice struct {
TenantCode string `json:"tenantCode" description:"租户code"`
Id uint `json:"id" description:""`
DeptId int `json:"deptId" description:"部门ID"`
Key string `json:"key" description:"设备标识"`
Name string `json:"name" description:"设备名称"`
ProductId uint `json:"productId" description:"所属产品"`
Desc string `json:"desc" description:"描述"`
MetadataTable int `json:"metadataTable" description:"是否生成物模型子表0=否1=是"`
Status int `json:"status" description:"状态0=未启用,1=离线,2=在线"`
OnlineTimeout int `json:"onlineTimeout" description:"设备在线超时设置,单位:秒"`
RegistryTime *gtime.Time `json:"registryTime" description:"激活时间"`
LastOnlineTime *gtime.Time `json:"lastOnlineTime" description:"最后上线时间"`
Version string `json:"version" description:"固件版本号"`
TunnelId int `json:"tunnelId" description:"tunnelId"`
Lng string `json:"lng" description:"经度"`
Lat string `json:"lat" description:"纬度"`
Address string `json:"address" description:"详细地址"`
AuthType int `json:"authType" description:"认证方式1=Basic2=AccessToken3=证书)"`
AuthUser string `json:"authUser" description:"认证用户"`
AuthPasswd string `json:"authPasswd" description:"认证密码"`
AccessToken string `json:"accessToken" description:"AccessToken"`
CertificateId int `json:"certificateId" description:"证书ID"`
ExtensionInfo string `json:"extensionInfo" description:"设备扩展信息"`
CreatedBy uint `json:"createdBy" description:"创建者"`
UpdatedBy uint `json:"updatedBy" description:"更新者"`
DeletedBy uint `json:"deletedBy" description:"删除者"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"`
DeletedAt *gtime.Time `json:"deletedAt" description:"删除时间"`
ProductKey string `json:"productKey" description:"产品key"`
Tags []*DevDeviceTag `json:"tags" orm:"with:device_id=id" dc:"设备标签"`
}

View File

@@ -0,0 +1,95 @@
package model
import (
"sagooiot/internal/model"
"sagooiot/internal/model/entity"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/os/gtime"
)
type DevDeviceTag struct {
Id uint `json:"id" dc:"标签ID"`
DeviceId uint `json:"deviceId" dc:"设备ID"`
Key string `json:"key" dc:"标签标识"`
Name string `json:"name" dc:"标签名称"`
Value string `json:"value" dc:"标签值"`
}
// 物模型
type TSL struct {
Key string `json:"key" dc:"产品标识"`
Name string `json:"name" dc:"产品名称"`
Properties []model.TSLProperty `json:"properties" dc:"属性"`
Functions []model.TSLFunction `json:"functions" dc:"功能"`
Events []model.TSLEvent `json:"events" dc:"事件"`
Tags []model.TSLTag `json:"tags" dc:"标签"`
}
// 参数值(类型、类型参数)
type TSLValueType struct {
Type string `json:"type" ` // 类型
model.TSLParam // 参数
}
type DeviceRes struct {
*entity.DevDevice
DeptName string `json:"deptName" dc:"部门名称"`
ProductName string `json:"productName" dc:"产品名称"`
TSL *model.TSL `json:"tsl" dc:"物模型"`
Product *entity.DevProduct `json:"product" orm:"with:key=product_key" dc:"产品信息"`
Tags []*model.DevDeviceTag `json:"tags" orm:"with:device_id=id" dc:"设备标签"`
}
type DeviceOutput struct {
*entity.DevDevice
DeptName string `json:"deptName" dc:"部门名称"`
ProductName string `json:"productName" dc:"产品名称"`
TSL *model.TSL `json:"tsl" dc:"物模型"`
Product *entity.DevProduct `json:"product" orm:"with:key=product_key" dc:"产品信息"`
Tags []*model.DevDeviceTag `json:"tags" orm:"with:device_id=id" dc:"设备标签"`
}
// 设备运行状态
type DeviceRunStatusOutput struct {
Status int `json:"status" dc:"状态0=未启用,1=离线,2=在线"`
LastOnlineTime *gtime.Time `json:"lastOnlineTime" dc:"最后上线时间"`
Properties []model.DevicePropertiy `json:"properties" dc:"属性列表"`
}
// 属性
type TSLProperty struct {
Key string `json:"key" dc:"属性标识" v:"required|regex:^[A-Za-z_]+[\\w]*$#请输入属性标识|标识由字母、数字和下划线组成,且不能以数字开头"`
Name string `json:"name" dc:"属性名称" v:"required#请输入属性名称"`
AccessMode int `json:"accessMode" dc:"属性访问类型:0=读写,1=只读" v:"required#请选择是否只读"`
ValueType TSLValueType `json:"valueType" dc:"属性值"`
Desc string `json:"desc" dc:"描述"`
}
type ListDeviceForPageInput struct {
Key string `json:"key" dc:"设备标识"`
Name string `json:"name" dc:"设备名称"`
ProductKey string `json:"productKey" dc:"所属产品"`
TunnelId int `json:"tunnelId" description:"tunnelId"`
Status string `p:"status"` //设备状态
Keys []string `json:"keys" dc:"设备标识"`
DeviceTypes []string `json:"deviceTypes" dc:"设备类型"`
DeptIds []int `json:"deptIds" dc:"组织ID"`
model.PaginationInput
}
type DeviceGetPropertyListInput struct {
DeviceKey string `json:"device_key" dc:"设备ID" v:"required#设备key不能为空"`
PropertyKey string `json:"propertyKey" dc:"属性标识" v:"required#属性标识不能为空"`
model.PaginationInput
}
type DeviceGetPropertyListOutput struct {
List []*DevicePropertiyOut `json:"list" dc:"属性列表"`
model.PaginationOutput
}
type DevicePropertiyOut struct {
Ts *gtime.Time `json:"ts" dc:"时间"`
Value *gvar.Var `json:"value" dc:"属性值"`
}

18
pkg/proxy/model/scene.go Normal file
View File

@@ -0,0 +1,18 @@
package model
type SceneOutput struct {
Id string `json:"id" description:"场景ID"`
Code string `json:"code" description:"场景编码"`
DeptId int `json:"deptId" description:"部门ID"`
Name string `json:"name" description:"场景名称"`
Description string `json:"description" description:"场景描述"`
SceneType string `json:"sceneType" description:"场景类型"`
Status string `json:"status" description:"状态0=未启用1=已启用"`
StartTime string `json:"startTime" description:"开始时间"`
CreateBy string `json:"createBy" description:"创建者"`
CreatedAt string `json:"createdAt" description:"创建时间"`
UpdateBy string `json:"updateBy" description:"更新者"`
UpdatedAt string `json:"updatedAt" description:"更新时间"`
DeletedBy string `json:"deletedBy" description:"删除者"`
DeletedAt string `json:"deletedAt" description:"删除时间"`
}

View File

@@ -0,0 +1,46 @@
package model
import "github.com/gogf/gf/v2/os/gtime"
type SysDeptOut struct {
DeptId int64 `json:"deptId" description:"部门id"`
OrganizationId int `json:"organizationId" description:"组织ID"`
ParentId int64 `json:"parentId" description:"父部门id"`
Ancestors string `json:"ancestors" description:"祖级列表"`
DeptName string `json:"deptName" description:"部门名称"`
OrderNum int `json:"orderNum" description:"显示顺序"`
Leader string `json:"leader" description:"负责人"`
Phone string `json:"phone" description:"联系电话"`
Email string `json:"email" description:"邮箱"`
Status uint `json:"status" description:"部门状态0停用 1正常"`
IsDeleted int `json:"isDeleted" description:"是否删除 0未删除 1已删除"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
CreatedBy uint `json:"createdBy" description:"创建人"`
UpdatedBy int `json:"updatedBy" description:"修改人"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`
DeletedBy int `json:"deletedBy" description:"删除人"`
DeletedAt *gtime.Time `json:"deletedAt" description:"删除时间"`
}
type AddDeptInput struct {
OrganizationId int `json:"organizationId" description:"组织ID"`
ParentId int64 `json:"parentId" description:"父部门id"`
DeptName string `json:"deptName" description:"部门名称"`
OrderNum int `json:"orderNum" description:"显示顺序"`
Leader string `json:"leader" description:"负责人"`
Phone string `json:"phone" description:"联系电话"`
Email string `json:"email" description:"邮箱"`
Status uint `json:"status" description:"部门状态0停用 1正常"`
}
type EditDeptInput struct {
DeptId int64 `json:"deptId"`
ParentId int64 `json:"parentId"`
OrganizationId int `json:"organizationId"`
DeptName string `json:"deptName"`
OrderNum int `json:"orderNum"`
Status uint `json:"status"`
Leader string `json:"leader"`
Phone string `json:"phone"`
Email string `json:"email"`
}

View File

@@ -0,0 +1,35 @@
package model
import "github.com/gogf/gf/v2/os/gtime"
type UserInfoOut struct {
Id uint64 `json:"id" description:""`
UserName string `json:"userName" description:"用户名"`
UserTypes string `json:"userTypes" description:"系统 system 企业 company"`
Mobile string `json:"mobile" description:"中国手机不带国家代码,国际手机号格式为:国家代码-手机号"`
UserNickname string `json:"userNickname" description:"用户昵称"`
Birthday *gtime.Time `json:"birthday" description:"生日"`
UserEmail string `json:"userEmail" description:"用户登录邮箱"`
Sex int `json:"sex" description:"性别;0:保密,1:男,2:女"`
Avatar string `json:"avatar" description:"用户头像"`
DeptId uint64 `json:"deptId" description:"部门id"`
Remark string `json:"remark" description:"备注"`
IsAdmin int `json:"isAdmin" description:"是否后台管理员 1 是 0 否"`
Address string `json:"address" description:"联系地址"`
Describe string `json:"describe" description:"描述信息"`
LastLoginIp string `json:"lastLoginIp" description:"最后登录ip"`
LastLoginTime *gtime.Time `json:"lastLoginTime" description:"最后登录时间"`
Status uint `json:"status" description:"用户状态;0:禁用,1:正常,2:未验证"`
CreatedBy uint `json:"createdBy" description:"创建者"`
IsDeleted int `json:"isDeleted" orm:"is_deleted" description:"是否删除 0未删除 1已删除"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建日期"`
UpdatedBy uint `json:"updatedBy" description:"更新者"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"修改日期"`
RoleIds []int `json:"roleIds" description:"角色ID数组" v:"required#角色不能为空"`
PostIds []int `json:"postIds" description:"岗位ID数组" v:"required#岗位不能为空"`
}
type LoginUserOut struct {
UserNickname string `orm:"user_nickname" json:"userNickname"` // 用户昵称
Avatar string `orm:"avatar" json:"avatar"` //头像
}

97
pkg/proxy/system.go Normal file
View File

@@ -0,0 +1,97 @@
package proxy
import (
"context"
"database/sql"
"sagooiot/internal/model"
"sagooiot/internal/service"
proxyModel "sagooiot/pkg/proxy/model"
"github.com/gogf/gf/v2/util/gconv"
)
// GetUserInfo 获取当前登录用户信息
func GetUserInfo(ctx context.Context) (userInfo *model.ContextUser, err error) {
userInfo = service.Context().GetLoginUser(ctx)
return
}
func GetUserAll(ctx context.Context) (data []*proxyModel.UserInfoOut, err error) {
//获取所有用户列表
sysUserInfo, err := service.SysUser().GetAll(ctx)
if err != nil {
return
}
if len(sysUserInfo) > 0 {
err = gconv.Scan(sysUserInfo, &data)
}
return
}
// GetDeptInfoById 根据部门id获取部门信息
func GetDeptInfoById(ctx context.Context, deptId int64) (out *proxyModel.SysDeptOut, err error) {
//获取部门名称
deptOut, _ := service.SysDept().Detail(ctx, deptId)
if deptOut != nil {
if err = gconv.Scan(deptOut, &out); err != nil {
return
}
}
return
}
func GetDeptAll(ctx context.Context) (out []*proxyModel.SysDeptOut, err error) {
//获取部门名称
deptOut, _ := service.SysDept().GetAll(ctx)
if deptOut != nil {
if err = gconv.Scan(deptOut, &out); err != nil {
return
}
}
return
}
// GetDeptInfosByParentId 根据父ID获取子部门信息
func GetDeptInfosByParentId(ctx context.Context, parentId int) (data []*proxyModel.SysDeptOut, err error) {
all, err := service.SysDept().GetFromCache(ctx)
if err != nil {
return
}
if len(all) == 0 {
return
}
out := service.SysDept().FindSonByParentId(all, int64(parentId))
if len(out) > 0 {
err = gconv.Scan(out, &data)
}
return
}
// GetUserInfoById 根据用户id获取用户信息
func GetUserInfoById(ctx context.Context, userId uint) (out *proxyModel.UserInfoOut, err error) {
userOut, _ := service.SysUser().GetUserById(ctx, userId)
if userOut != nil {
if err = gconv.Scan(userOut, &out); err != nil {
return
}
}
return
}
// GetFromCache 获取部门信息并更新缓存
func GetFromCache(ctx context.Context) (list []*proxyModel.SysDeptOut, err error) {
all, err := service.SysDept().GetFromCache(ctx)
if err != nil {
return
}
if len(all) > 0 {
err = gconv.Scan(all, &list)
}
return
}
// GetSequences 获取主键ID
func GetSequences(ctx context.Context, result sql.Result, tableName string, primaryKey string) (lastInsertId int64, err error) {
lastInsertId, err = service.Sequences().GetSequences(ctx, result, tableName, primaryKey)
return
}

26
pkg/utility/fatallog.go Normal file
View File

@@ -0,0 +1,26 @@
package utility
import (
"log"
"os"
"path/filepath"
)
func InitFatalLog(loggerPath string) *os.File {
loggerPath = loggerPath + "-error.log"
// 确保目录存在
dir := filepath.Dir(loggerPath)
if err := os.MkdirAll(dir, 0755); err != nil {
log.Fatalf("创建目录失败: %v", err)
return nil
}
// 打开(如果不存在则创建)日志文件
file, err := os.OpenFile(loggerPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("打开文件失败: %v", err)
return nil
}
return file
}