Merge pull request #116 from jwetzell/feat/dynamic-json-schema

generate json-schema dynamically in Go
This commit is contained in:
Joel Wetzell
2026-03-23 12:15:45 -05:00
committed by GitHub
77 changed files with 1319 additions and 1659 deletions

99
api.go
View File

@@ -2,22 +2,18 @@ package showbridge
import ( import (
"context" "context"
"embed"
_ "embed" _ "embed"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/fs"
"net/http" "net/http"
"time" "time"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/jwetzell/showbridge-go/internal/module" "github.com/jwetzell/showbridge-go/internal/module"
"github.com/jwetzell/showbridge-go/internal/processor"
"github.com/jwetzell/showbridge-go/internal/route" "github.com/jwetzell/showbridge-go/internal/route"
) )
//go:embed schema
var schema embed.FS
func (r *Router) startAPIServer(config config.ApiConfig) { func (r *Router) startAPIServer(config config.ApiConfig) {
if !config.Enabled { if !config.Enabled {
r.logger.Warn("API not enabled") r.logger.Warn("API not enabled")
@@ -27,8 +23,11 @@ func (r *Router) startAPIServer(config config.ApiConfig) {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/ws", r.handleWebsocket) mux.HandleFunc("/ws", r.handleWebsocket)
mux.HandleFunc("/health", r.handleHealthHTTP) mux.HandleFunc("/health", r.handleHealthHTTP)
mux.Handle("/schema/{schema}", HandleFS(schema))
mux.HandleFunc("/api/v1/config", r.handleConfigHTTP) mux.HandleFunc("/api/v1/config", r.handleConfigHTTP)
mux.HandleFunc("/schema/config.schema.json", handleConfigSchema)
mux.HandleFunc("/schema/routes.schema.json", handleRoutesSchema)
mux.HandleFunc("/schema/modules.schema.json", handleModulesSchema)
mux.HandleFunc("/schema/processors.schema.json", handleProcessorsSchema)
r.apiServerMu.Lock() r.apiServerMu.Lock()
defer r.apiServerMu.Unlock() defer r.apiServerMu.Unlock()
@@ -131,14 +130,92 @@ func (r *Router) handleConfigHTTP(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusMethodNotAllowed) w.WriteHeader(http.StatusMethodNotAllowed)
} }
} }
func HandleFS(fs fs.FS) http.HandlerFunc { func handleConfigSchema(w http.ResponseWriter, req *http.Request) {
handler := http.FileServerFS(fs) switch req.Method {
return func(w http.ResponseWriter, req *http.Request) { case http.MethodGet:
schemaJSON, err := json.Marshal(config.ConfigSchema)
if err != nil {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
handler.ServeHTTP(w, req) w.Write(schemaJSON)
case http.MethodOptions:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
w.WriteHeader(http.StatusOK)
default:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
func handleRoutesSchema(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
schemaJSON, err := json.Marshal(config.RoutesConfigSchema)
if err != nil {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json")
w.Write(schemaJSON)
case http.MethodOptions:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
w.WriteHeader(http.StatusOK)
default:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
func handleModulesSchema(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
schemaJSON, err := json.Marshal(module.GetModulesSchema())
if err != nil {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json")
w.Write(schemaJSON)
case http.MethodOptions:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
w.WriteHeader(http.StatusOK)
default:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
func handleProcessorsSchema(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
schemaJSON, err := json.Marshal(processor.GetProcessorsSchema())
if err != nil {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json")
w.Write(schemaJSON)
case http.MethodOptions:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
w.WriteHeader(http.StatusOK)
default:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusMethodNotAllowed)
} }
} }

1
go.mod
View File

@@ -8,6 +8,7 @@ require (
github.com/emiago/sipgo v1.2.1 github.com/emiago/sipgo v1.2.1
github.com/expr-lang/expr v1.17.8 github.com/expr-lang/expr v1.17.8
github.com/extism/go-sdk v1.7.1 github.com/extism/go-sdk v1.7.1
github.com/google/jsonschema-go v0.4.2
github.com/gorilla/websocket v1.5.3 github.com/gorilla/websocket v1.5.3
github.com/jwetzell/artnet-go v0.2.1 github.com/jwetzell/artnet-go v0.2.1
github.com/jwetzell/free-d-go v0.1.0 github.com/jwetzell/free-d-go v0.1.0

2
go.sum
View File

@@ -51,6 +51,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8=
github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=

28
internal/config/api.go Normal file
View File

@@ -0,0 +1,28 @@
package config
import (
"encoding/json"
"github.com/google/jsonschema-go/jsonschema"
)
type ApiConfig struct {
Enabled bool `json:"enabled"`
Port int `json:"port"`
}
var ApiConfigSchema = jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"enabled": {
Type: "boolean",
Description: "Whether the API server is enabled",
Default: json.RawMessage(`false`),
},
"port": {
Type: "integer",
Description: "Port for the API server to listen on",
},
},
Required: []string{"port"},
}

View File

@@ -1,27 +1,28 @@
package config package config
import (
"github.com/google/jsonschema-go/jsonschema"
)
type Config struct { type Config struct {
Api ApiConfig `json:"api"` Api ApiConfig `json:"api"`
Modules []ModuleConfig `json:"modules"` Modules []ModuleConfig `json:"modules"`
Routes []RouteConfig `json:"routes"` Routes []RouteConfig `json:"routes"`
} }
type ApiConfig struct { var ConfigSchema = jsonschema.Schema{
Enabled bool `json:"enabled"` Schema: "https://json-schema.org/draft/2020-12/schema",
Port int `json:"port"` ID: "https://showbridge.io/config.schema.json",
} Title: "Config",
type ModuleConfig struct { Description: "showbridge configuration",
Id string `json:"id"` Type: "object",
Type string `json:"type"` Properties: map[string]*jsonschema.Schema{
Params Params `json:"params,omitempty"` "api": &ApiConfigSchema,
} "modules": {
Ref: "https://showbridge.io/modules.schema.json",
type RouteConfig struct { },
Input string `json:"input"` "routes": {
Processors []ProcessorConfig `json:"processors"` Ref: "https://showbridge.io/routes.schema.json",
} },
},
type ProcessorConfig struct {
Type string `json:"type"`
Params Params `json:"params,omitempty"`
} }

View File

@@ -0,0 +1,7 @@
package config
type ModuleConfig struct {
Id string `json:"id"`
Type string `json:"type"`
Params Params `json:"params,omitempty"`
}

View File

@@ -0,0 +1,6 @@
package config
type ProcessorConfig struct {
Type string `json:"type"`
Params Params `json:"params,omitempty"`
}

29
internal/config/route.go Normal file
View File

@@ -0,0 +1,29 @@
package config
import "github.com/google/jsonschema-go/jsonschema"
type RouteConfig struct {
Input string `json:"input"`
Processors []ProcessorConfig `json:"processors"`
}
var RoutesConfigSchema = jsonschema.Schema{
Schema: "https://json-schema.org/draft/2020-12/schema",
ID: "https://showbridge.io/routes.schema.json",
Title: "Routes",
Description: "route configurations",
Type: "array",
Items: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"input": {
Type: "string",
MinLength: jsonschema.Ptr(1),
},
"processors": {
Ref: "https://showbridge.io/processors.schema.json",
},
},
Required: []string{"input"},
},
}

View File

@@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
@@ -25,6 +26,17 @@ type DbSqlite struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "db.sqlite", Type: "db.sqlite",
Title: "SQLite Database",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"dsn": {
Type: "string",
MinLength: jsonschema.Ptr(1),
},
},
Required: []string{"dsn"},
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params

View File

@@ -9,6 +9,7 @@ import (
"net" "net"
"net/http" "net/http"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/jwetzell/showbridge-go/internal/processor" "github.com/jwetzell/showbridge-go/internal/processor"
@@ -56,6 +57,20 @@ func (hsrw *HTTPServerResponseWriter) Write(data []byte) (int, error) {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "http.server", Type: "http.server",
Title: "HTTP Server",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"port": {
Title: "Port",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1024),
Maximum: jsonschema.Ptr[float64](65535),
},
},
Required: []string{"port"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params
portNum, err := params.GetInt("port") portNum, err := params.GetInt("port")

View File

@@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"gitlab.com/gomidi/midi/v2" "gitlab.com/gomidi/midi/v2"
@@ -27,6 +28,18 @@ type MIDIInput struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "midi.input", Type: "midi.input",
Title: "MIDI Input",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"port": {
Title: "Port",
Type: "string",
},
},
Required: []string{"port"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params
portString, err := params.GetString("port") portString, err := params.GetString("port")

View File

@@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"gitlab.com/gomidi/midi/v2" "gitlab.com/gomidi/midi/v2"
@@ -27,6 +28,18 @@ type MIDIOutput struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "midi.output", Type: "midi.output",
Title: "MIDI Output",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"port": {
Title: "Port",
Type: "string",
},
},
Required: []string{"port"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params

View File

@@ -5,6 +5,7 @@ import (
"log/slog" "log/slog"
"sync" "sync"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -17,6 +18,9 @@ type ModuleError struct {
type ModuleRegistration struct { type ModuleRegistration struct {
Type string `json:"type"` Type string `json:"type"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
ParamsSchema *jsonschema.Schema `json:"paramsSchema,omitempty"`
New func(config.ModuleConfig) (common.Module, error) New func(config.ModuleConfig) (common.Module, error)
} }
@@ -46,3 +50,49 @@ var (
func CreateLogger(config config.ModuleConfig) *slog.Logger { func CreateLogger(config config.ModuleConfig) *slog.Logger {
return slog.Default().With("component", "module", "id", config.Id, "type", config.Type) return slog.Default().With("component", "module", "id", config.Id, "type", config.Type)
} }
func GetModulesSchema() *jsonschema.Schema {
moduleRegistryMu.RLock()
defer moduleRegistryMu.RUnlock()
schema := &jsonschema.Schema{
Schema: "https://json-schema.org/draft/2020-12/schema",
ID: "https://showbridge.io/modules.schema.json",
Title: "Modules",
Description: "module configurations",
Type: "array",
}
moduleDefinitionSchemas := []*jsonschema.Schema{}
for _, mod := range ModuleRegistry {
moduleSchema := &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"id": {
Type: "string",
MinLength: jsonschema.Ptr(1),
},
"type": {
Const: jsonschema.Ptr[any](mod.Type),
},
},
Required: []string{"id", "type"},
AdditionalProperties: nil,
}
if mod.Title != "" {
moduleSchema.Title = mod.Title
}
if mod.Description != "" {
moduleSchema.Description = mod.Description
}
if mod.ParamsSchema != nil {
moduleSchema.Properties["params"] = mod.ParamsSchema
moduleSchema.Required = append(moduleSchema.Required, "params")
}
moduleDefinitionSchemas = append(moduleDefinitionSchemas, moduleSchema)
}
schema.Items = &jsonschema.Schema{
OneOf: moduleDefinitionSchemas,
}
return schema
}

View File

@@ -7,6 +7,7 @@ import (
"log/slog" "log/slog"
mqtt "github.com/eclipse/paho.mqtt.golang" mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -26,6 +27,26 @@ type MQTTClient struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "mqtt.client", Type: "mqtt.client",
Title: "MQTT Client",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"broker": {
Title: "Broker URL",
Type: "string",
},
"topic": {
Title: "Topic",
Type: "string",
},
"clientId": {
Title: "Client ID",
Type: "string",
},
},
Required: []string{"broker", "topic", "clientId"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params
brokerString, err := params.GetString("broker") brokerString, err := params.GetString("broker")

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"log/slog" "log/slog"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/jwetzell/showbridge-go/internal/processor" "github.com/jwetzell/showbridge-go/internal/processor"
@@ -25,6 +26,22 @@ type NATSClient struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "nats.client", Type: "nats.client",
Title: "NATS Client",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"url": {
Title: "NATS Server URL",
Type: "string",
},
"subject": {
Title: "Subject",
Type: "string",
},
},
Required: []string{"url", "subject"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params
urlString, err := params.GetString("url") urlString, err := params.GetString("url")

View File

@@ -2,12 +2,14 @@ package module
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"net" "net"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/nats-io/nats-server/v2/server" "github.com/nats-io/nats-server/v2/server"
@@ -27,6 +29,27 @@ type NATSServer struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "nats.server", Type: "nats.server",
Title: "NATS Server",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"ip": {
Title: "IP",
Type: "string",
Default: json.RawMessage(`"0.0.0.0"`),
},
"port": {
Title: "Port",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1024),
Maximum: jsonschema.Ptr[float64](65535),
Default: json.RawMessage(`4222`),
},
},
Required: []string{},
AdditionalProperties: nil,
},
New: func(moduleConfig config.ModuleConfig) (common.Module, error) { New: func(moduleConfig config.ModuleConfig) (common.Module, error) {
params := moduleConfig.Params params := moduleConfig.Params
portNum, err := params.GetInt("port") portNum, err := params.GetInt("port")

View File

@@ -25,6 +25,7 @@ type PSNClient struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "psn.client", Type: "psn.client",
Title: "PosiStageNet Client",
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
return &PSNClient{config: config, decoder: psn.NewDecoder(), logger: CreateLogger(config)}, nil return &PSNClient{config: config, decoder: psn.NewDecoder(), logger: CreateLogger(config)}, nil

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
@@ -25,6 +26,22 @@ type RedisClient struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "redis.client", Type: "redis.client",
Title: "Redis Client",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"host": {
Type: "string",
},
"port": {
Type: "integer",
Minimum: jsonschema.Ptr[float64](1),
Maximum: jsonschema.Ptr[float64](65535),
},
},
Required: []string{"host", "port"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params
hostString, err := params.GetString("host") hostString, err := params.GetString("host")

View File

@@ -9,6 +9,7 @@ import (
"log/slog" "log/slog"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/jwetzell/showbridge-go/internal/framer" "github.com/jwetzell/showbridge-go/internal/framer"
@@ -30,6 +31,22 @@ type SerialClient struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "serial.client", Type: "serial.client",
Title: "Serial Client",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"port": {
Title: "Port",
Type: "string",
},
"baudRate": {
Title: "Baud Rate",
Type: "integer",
},
},
Required: []string{"port", "baudRate"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params
portString, err := params.GetString("port") portString, err := params.GetString("port")

View File

@@ -2,6 +2,7 @@ package module
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@@ -14,6 +15,7 @@ import (
"github.com/emiago/diago/media" "github.com/emiago/diago/media"
"github.com/emiago/sipgo" "github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip" "github.com/emiago/sipgo/sip"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/jwetzell/showbridge-go/internal/processor" "github.com/jwetzell/showbridge-go/internal/processor"
@@ -46,6 +48,37 @@ type sipCallContextKey string
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "sip.call.server", Type: "sip.call.server",
Title: "SIP Call Server",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"ip": {
Title: "IP",
Type: "string",
Default: json.RawMessage(`"0.0.0.0"`),
},
"port": {
Title: "Port",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1024),
Maximum: jsonschema.Ptr[float64](65535),
Default: json.RawMessage(`5060`),
},
"transport": {
Title: "Transport",
Type: "string",
Enum: []any{"udp", "tcp", "ws", "udp4", "tcp4"},
Default: json.RawMessage(`"udp"`),
},
"userAgent": {
Title: "User Agent",
Type: "string",
Default: json.RawMessage(`"showbridge"`),
},
},
Required: []string{},
AdditionalProperties: nil,
},
New: func(moduleConfig config.ModuleConfig) (common.Module, error) { New: func(moduleConfig config.ModuleConfig) (common.Module, error) {
params := moduleConfig.Params params := moduleConfig.Params
portNum, err := params.GetInt("port") portNum, err := params.GetInt("port")

View File

@@ -2,6 +2,7 @@ package module
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@@ -15,6 +16,7 @@ import (
"github.com/emiago/diago/media" "github.com/emiago/diago/media"
"github.com/emiago/sipgo" "github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip" "github.com/emiago/sipgo/sip"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/jwetzell/showbridge-go/internal/processor" "github.com/jwetzell/showbridge-go/internal/processor"
@@ -46,6 +48,43 @@ type SIPDTMFCall struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "sip.dtmf.server", Type: "sip.dtmf.server",
Title: "SIP DTMF Server",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"ip": {
Title: "IP",
Type: "string",
Default: json.RawMessage(`"0.0.0.0"`),
},
"port": {
Title: "Port",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1024),
Maximum: jsonschema.Ptr[float64](65535),
Default: json.RawMessage(`5060`),
},
"transport": {
Title: "Transport",
Type: "string",
Enum: []any{"udp", "tcp", "ws", "udp4", "tcp4"},
Default: json.RawMessage(`"udp"`),
},
"userAgent": {
Title: "User Agent",
Type: "string",
Default: json.RawMessage(`"showbridge"`),
},
"separator": {
Title: "DTMF Separator",
Type: "string",
MinLength: jsonschema.Ptr(1),
MaxLength: jsonschema.Ptr(1),
},
},
Required: []string{"separator"},
AdditionalProperties: nil,
},
New: func(moduleConfig config.ModuleConfig) (common.Module, error) { New: func(moduleConfig config.ModuleConfig) (common.Module, error) {
params := moduleConfig.Params params := moduleConfig.Params

View File

@@ -8,6 +8,7 @@ import (
"net" "net"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/jwetzell/showbridge-go/internal/framer" "github.com/jwetzell/showbridge-go/internal/framer"
@@ -27,6 +28,29 @@ type TCPClient struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "net.tcp.client", Type: "net.tcp.client",
Title: "TCP Client",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"host": {
Title: "Host",
Type: "string",
},
"port": {
Title: "Port",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1),
Maximum: jsonschema.Ptr[float64](65535),
},
"framing": {
Title: "Framing Method",
Type: "string",
Enum: []any{"LF", "CR", "CRLF", "SLIP", "RAW"},
},
},
Required: []string{"host", "port", "framing"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params
hostString, err := params.GetString("host") hostString, err := params.GetString("host")

View File

@@ -2,6 +2,7 @@ package module
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
@@ -11,6 +12,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"github.com/jwetzell/showbridge-go/internal/framer" "github.com/jwetzell/showbridge-go/internal/framer"
@@ -33,6 +35,30 @@ type TCPServer struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "net.tcp.server", Type: "net.tcp.server",
Title: "TCP Server",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"ip": {
Title: "IP",
Type: "string",
Default: json.RawMessage(`"0.0.0.0"`),
},
"port": {
Title: "Port",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1024),
Maximum: jsonschema.Ptr[float64](65535),
},
"framing": {
Title: "Framing Method",
Type: "string",
Enum: []any{"LF", "CR", "CRLF", "SLIP", "RAW"},
},
},
Required: []string{"port", "framing"},
AdditionalProperties: nil,
},
New: func(moduleConfig config.ModuleConfig) (common.Module, error) { New: func(moduleConfig config.ModuleConfig) (common.Module, error) {
params := moduleConfig.Params params := moduleConfig.Params
portNum, err := params.GetInt("port") portNum, err := params.GetInt("port")

View File

@@ -7,6 +7,7 @@ import (
"log/slog" "log/slog"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -24,6 +25,19 @@ type TimeInterval struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "time.interval", Type: "time.interval",
Title: "Interval",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"duration": {
Title: "Duration",
Type: "integer",
Description: "Interval duration in milliseconds",
},
},
Required: []string{"duration"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params

View File

@@ -7,6 +7,7 @@ import (
"log/slog" "log/slog"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -24,6 +25,19 @@ type TimeTimer struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "time.timer", Type: "time.timer",
Title: "Timer",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"duration": {
Title: "Duration",
Type: "integer",
Description: "Interval duration in milliseconds",
},
},
Required: []string{"duration"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params

View File

@@ -7,6 +7,7 @@ import (
"log/slog" "log/slog"
"net" "net"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -25,6 +26,24 @@ type UDPClient struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "net.udp.client", Type: "net.udp.client",
Title: "UDP Client",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"host": {
Title: "Host",
Type: "string",
},
"port": {
Title: "Port",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1),
Maximum: jsonschema.Ptr[float64](65535),
},
},
Required: []string{"host", "port"},
AdditionalProperties: nil,
},
New: func(config config.ModuleConfig) (common.Module, error) { New: func(config config.ModuleConfig) (common.Module, error) {
params := config.Params params := config.Params
hostString, err := params.GetString("host") hostString, err := params.GetString("host")

View File

@@ -8,6 +8,7 @@ import (
"net" "net"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -25,6 +26,24 @@ type UDPMulticast struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "net.udp.multicast", Type: "net.udp.multicast",
Title: "UDP Multicast",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"ip": {
Title: "IP",
Type: "string",
},
"port": {
Title: "Port",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1024),
Maximum: jsonschema.Ptr[float64](65535),
},
},
Required: []string{"ip", "port"},
AdditionalProperties: nil,
},
New: func(moduleConfig config.ModuleConfig) (common.Module, error) { New: func(moduleConfig config.ModuleConfig) (common.Module, error) {
params := moduleConfig.Params params := moduleConfig.Params
ipString, err := params.GetString("ip") ipString, err := params.GetString("ip")

View File

@@ -8,6 +8,7 @@ import (
"net" "net"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -25,6 +26,24 @@ type UDPServer struct {
func init() { func init() {
RegisterModule(ModuleRegistration{ RegisterModule(ModuleRegistration{
Type: "net.udp.server", Type: "net.udp.server",
Title: "UDP Server",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"ip": {
Title: "IP",
Type: "string",
},
"port": {
Title: "Port",
Type: "integer",
Minimum: jsonschema.Ptr[float64](1024),
Maximum: jsonschema.Ptr[float64](65535),
},
},
Required: []string{"ip", "port"},
AdditionalProperties: nil,
},
New: func(moduleConfig config.ModuleConfig) (common.Module, error) { New: func(moduleConfig config.ModuleConfig) (common.Module, error) {
params := moduleConfig.Params params := moduleConfig.Params
portNum, err := params.GetInt("port") portNum, err := params.GetInt("port")

View File

@@ -41,6 +41,7 @@ func (apd *ArtNetPacketDecode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "artnet.packet.decode", Type: "artnet.packet.decode",
Title: "Decode ArtNet Packet",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &ArtNetPacketDecode{config: config}, nil return &ArtNetPacketDecode{config: config}, nil
}, },

View File

@@ -40,6 +40,7 @@ func (ape *ArtNetPacketEncode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "artnet.packet.encode", Type: "artnet.packet.encode",
Title: "Encode ArtNet Packet",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &ArtNetPacketEncode{config: config}, nil return &ArtNetPacketEncode{config: config}, nil
}, },

View File

@@ -105,6 +105,7 @@ func (dq *DbQuery) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "db.query", Type: "db.query",
Title: "Query Database",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -29,6 +29,7 @@ func (dl *DebugLog) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "debug.log", Type: "debug.log",
Title: "Debug Log",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &DebugLog{config: config, logger: slog.Default().With("component", "processor", "type", config.Type)}, nil return &DebugLog{config: config, logger: slog.Default().With("component", "processor", "type", config.Type)}, nil
}, },

View File

@@ -32,6 +32,7 @@ func (fc *FilterChange) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "filter.change", Type: "filter.change",
Title: "Filter On Change",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &FilterChange{config: config}, nil return &FilterChange{config: config}, nil
}, },

View File

@@ -6,6 +6,7 @@ import (
"github.com/expr-lang/expr" "github.com/expr-lang/expr"
"github.com/expr-lang/expr/vm" "github.com/expr-lang/expr/vm"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -48,6 +49,18 @@ func (fe *FilterExpr) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "filter.expr", Type: "filter.expr",
Title: "Filter by Expr expression",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"expression": {
Title: "Expression",
Type: "string",
},
},
Required: []string{"expression"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -40,6 +41,18 @@ func (fr *FilterRegex) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "filter.regex", Type: "filter.regex",
Title: "Filter by Regex",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"pattern": {
Title: "Pattern",
Type: "string",
},
},
Required: []string{"pattern"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -2,10 +2,12 @@ package processor
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"strconv" "strconv"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -40,6 +42,19 @@ func (fp *FloatParse) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "float.parse", Type: "float.parse",
Title: "Parse Float",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"bitSize": {
Title: "Bit Size",
Type: "integer",
Enum: []any{32, 64},
Default: json.RawMessage("64"),
},
},
AdditionalProperties: nil,
},
New: func(moduleConfig config.ProcessorConfig) (Processor, error) { New: func(moduleConfig config.ProcessorConfig) (Processor, error) {
params := moduleConfig.Params params := moduleConfig.Params

View File

@@ -2,10 +2,12 @@ package processor
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"math/rand/v2" "math/rand/v2"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -39,6 +41,28 @@ func (fr *FloatRandom) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "float.random", Type: "float.random",
Title: "Random Float",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"bitSize": {
Title: "Bit Size",
Type: "integer",
Enum: []any{32, 64},
Default: json.RawMessage("32"),
},
"min": {
Title: "Minimum",
Type: "number",
},
"max": {
Title: "Maximum",
Type: "number",
},
},
Required: []string{"min", "max"},
AdditionalProperties: nil,
},
New: func(processorConfig config.ProcessorConfig) (Processor, error) { New: func(processorConfig config.ProcessorConfig) (Processor, error) {
params := processorConfig.Params params := processorConfig.Params

View File

@@ -7,6 +7,7 @@ import (
"strconv" "strconv"
"text/template" "text/template"
"github.com/google/jsonschema-go/jsonschema"
freeD "github.com/jwetzell/free-d-go" freeD "github.com/jwetzell/free-d-go"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
@@ -206,6 +207,60 @@ func (fc *FreeDCreate) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "freed.create", Type: "freed.create",
Title: "Create FreeD",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"id": {
Title: "Camera ID",
Type: "string",
},
"pan": {
Title: "Pan",
Type: "string",
},
"tilt": {
Title: "Tilt",
Type: "string",
},
"roll": {
Title: "Roll",
Type: "string",
},
"posX": {
Title: "Position X",
Type: "string",
},
"posY": {
Title: "Position Y",
Type: "string",
},
"posZ": {
Title: "Position Z",
Type: "string",
},
"zoom": {
Title: "Zoom",
Type: "string",
},
"focus": {
Title: "Focus",
Type: "string",
},
},
Required: []string{
"id",
"pan",
"tilt",
"roll",
"posX",
"posY",
"posZ",
"zoom",
"focus",
},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
// TODO(jwetzell): make some params optional // TODO(jwetzell): make some params optional

View File

@@ -38,6 +38,7 @@ func (fd *FreeDDecode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "freed.decode", Type: "freed.decode",
Title: "Decode FreeD",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &FreeDDecode{config: config}, nil return &FreeDDecode{config: config}, nil
}, },

View File

@@ -35,6 +35,7 @@ func (fe *FreeDEncode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "freed.encode", Type: "freed.encode",
Title: "Encode FreeD",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &FreeDEncode{config: config}, nil return &FreeDEncode{config: config}, nil
}, },

View File

@@ -9,6 +9,7 @@ import (
"text/template" "text/template"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -71,6 +72,23 @@ func (hrd *HTTPRequestDo) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "http.request.do", Type: "http.request.do",
Title: "Do HTTP Request",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"method": {
Title: "HTTP Method",
Type: "string",
Enum: []any{"GET", "POST"},
},
"url": {
Title: "URL",
Type: "string",
},
},
Required: []string{"method", "url"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"text/template" "text/template"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -45,6 +46,22 @@ func (hrc *HTTPResponseCreate) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "http.response.create", Type: "http.response.create",
Title: "Create HTTP Response",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"status": {
Title: "Status Code",
Type: "integer",
},
"body": {
Title: "Body",
Type: "string",
},
},
Required: []string{"status", "body"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -2,10 +2,12 @@ package processor
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"strconv" "strconv"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -41,6 +43,25 @@ func (ip *IntParse) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "int.parse", Type: "int.parse",
Title: "Parse Int",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"base": {
Title: "Base",
Type: "integer",
Enum: []any{0, 2, 8, 10, 16},
Default: json.RawMessage("10"),
},
"bitSize": {
Title: "Bit Size",
Type: "integer",
Enum: []any{0, 8, 16, 32, 64},
Default: json.RawMessage("64"),
},
},
AdditionalProperties: nil,
},
New: func(moduleConfig config.ProcessorConfig) (Processor, error) { New: func(moduleConfig config.ProcessorConfig) (Processor, error) {
params := moduleConfig.Params params := moduleConfig.Params

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"math/rand/v2" "math/rand/v2"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -29,6 +30,22 @@ func (ir *IntRandom) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "int.random", Type: "int.random",
Title: "Random Int",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"min": {
Title: "Minimum",
Type: "integer",
},
"max": {
Title: "Maximum",
Type: "integer",
},
},
Required: []string{"min", "max"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -37,6 +38,30 @@ func (ir *IntScale) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "int.scale", Type: "int.scale",
Title: "Scale Int",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"inMin": {
Title: "Input Minimum",
Type: "integer",
},
"inMax": {
Title: "Input Maximum",
Type: "integer",
},
"outMin": {
Title: "Output Minimum",
Type: "integer",
},
"outMax": {
Title: "Output Maximum",
Type: "integer",
},
},
Required: []string{"inMin", "inMax", "outMin", "outMax"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -47,6 +47,7 @@ func (jd *JsonDecode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "json.decode", Type: "json.decode",
Title: "Decode JSON",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &JsonDecode{config: config}, nil return &JsonDecode{config: config}, nil
}, },

View File

@@ -39,6 +39,7 @@ func (je *JsonEncode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "json.encode", Type: "json.encode",
Title: "Encode JSON",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &JsonEncode{config: config}, nil return &JsonEncode{config: config}, nil
}, },

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -52,6 +53,22 @@ func (kvg *KVGet) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "kv.get", Type: "kv.get",
Title: "Get Key",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"module": {
Title: "Module ID",
Type: "string",
},
"key": {
Title: "Key",
Type: "string",
},
},
Required: []string{"module", "key"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -8,6 +8,7 @@ import (
"html/template" "html/template"
"log/slog" "log/slog"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -63,6 +64,26 @@ func (kvs *KVSet) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "kv.set", Type: "kv.set",
Title: "Set Key",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"module": {
Title: "Module ID",
Type: "string",
},
"key": {
Title: "Key",
Type: "string",
},
"value": {
Title: "Value",
Type: "string",
},
},
Required: []string{"module", "key", "value"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -9,6 +9,7 @@ import (
"strconv" "strconv"
"text/template" "text/template"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"gitlab.com/gomidi/midi/v2" "gitlab.com/gomidi/midi/v2"
@@ -315,6 +316,104 @@ func newMidiProgramChangeCreate(config config.ProcessorConfig) (Processor, error
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "midi.message.create", Type: "midi.message.create",
Title: "Create MIDI Message",
ParamsSchema: &jsonschema.Schema{
Type: "object",
OneOf: []*jsonschema.Schema{
{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"type": {
Title: "MIDI Message Type",
Type: "string",
Enum: []any{"NoteOn", "noteon", "note_on"},
},
"channel": {
Title: "Channel",
Type: "string",
},
"note": {
Title: "Note",
Type: "string",
},
"velocity": {
Title: "Velocity",
Type: "string",
},
},
Required: []string{"type", "channel", "note", "velocity"},
AdditionalProperties: nil,
},
{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"type": {
Title: "MIDI Message Type",
Type: "string",
Enum: []any{"NoteOff", "noteoff", "note_off"},
},
"channel": {
Title: "Channel",
Type: "string",
},
"note": {
Title: "Note",
Type: "string",
},
"velocity": {
Title: "Velocity",
Type: "string",
},
},
Required: []string{"type", "channel", "note", "velocity"},
AdditionalProperties: nil,
},
{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"type": {
Title: "MIDI Message Type",
Type: "string",
Enum: []any{"ControlChange", "controlchange", "control_change"},
},
"channel": {
Title: "Channel",
Type: "string",
},
"control": {
Title: "Control",
Type: "string",
},
"value": {
Title: "Value",
Type: "string",
},
},
Required: []string{"type", "channel", "control", "value"},
AdditionalProperties: nil,
},
{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"type": {
Title: "MIDI Message Type",
Type: "string",
Enum: []any{"ProgramChange", "programchange", "program_change"},
},
"channel": {
Title: "Channel",
Type: "string",
},
"program": {
Title: "Program",
Type: "string",
},
},
Required: []string{"type", "channel", "program"},
AdditionalProperties: nil,
},
},
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -37,6 +37,7 @@ func (mmd *MIDIMessageDecode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "midi.message.decode", Type: "midi.message.decode",
Title: "Decode MIDI Message",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &MIDIMessageDecode{config: config}, nil return &MIDIMessageDecode{config: config}, nil
}, },

View File

@@ -35,6 +35,7 @@ func (mme *MIDIMessageEncode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "midi.message.encode", Type: "midi.message.encode",
Title: "Encode MIDI Message",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &MIDIMessageEncode{config: config}, nil return &MIDIMessageEncode{config: config}, nil
}, },

View File

@@ -93,6 +93,7 @@ func (mmu *MIDIMessageUnpack) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "midi.message.unpack", Type: "midi.message.unpack",
Title: "Unpack MIDI Message",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &MIDIMessageUnpack{config: config}, nil return &MIDIMessageUnpack{config: config}, nil
}, },

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -81,6 +82,30 @@ func (mmc *MQTTMessageCreate) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "mqtt.message.create", Type: "mqtt.message.create",
Title: "Create MQTT Message",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"topic": {
Title: "Topic",
Type: "string",
},
"qos": {
Title: "QoS",
Type: "number",
},
"retained": {
Title: "Retained",
Type: "boolean",
},
"payload": {
Title: "Payload",
Type: "string",
},
},
Required: []string{"topic", "qos", "retained", "payload"},
AdditionalProperties: nil,
},
New: func(processorConfig config.ProcessorConfig) (Processor, error) { New: func(processorConfig config.ProcessorConfig) (Processor, error) {
params := processorConfig.Params params := processorConfig.Params
topicString, err := params.GetString("topic") topicString, err := params.GetString("topic")

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"text/template" "text/template"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -60,6 +61,22 @@ func (nmc *NATSMessageCreate) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "nats.message.create", Type: "nats.message.create",
Title: "Create NATS Message",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"subject": {
Title: "Subject",
Type: "string",
},
"payload": {
Title: "Payload",
Type: "string",
},
},
Required: []string{"subject", "payload"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params
subjectString, err := params.GetString("subject") subjectString, err := params.GetString("subject")

View File

@@ -9,6 +9,7 @@ import (
"strconv" "strconv"
"text/template" "text/template"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/osc-go" "github.com/jwetzell/osc-go"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
@@ -87,6 +88,29 @@ func (omc *OSCMessageCreate) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "osc.message.create", Type: "osc.message.create",
Title: "Create OSC Message",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"address": {
Title: "Address",
Type: "string",
},
"args": {
Title: "Arguments",
Type: "array",
Items: &jsonschema.Schema{
Type: "string",
},
},
"types": {
Title: "Argument Types",
Type: "string",
},
},
Required: []string{"address"},
AdditionalProperties: nil,
},
New: func(processorConfig config.ProcessorConfig) (Processor, error) { New: func(processorConfig config.ProcessorConfig) (Processor, error) {
params := processorConfig.Params params := processorConfig.Params
addressString, err := params.GetString("address") addressString, err := params.GetString("address")

View File

@@ -49,6 +49,7 @@ func (omd *OSCMessageDecode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "osc.message.decode", Type: "osc.message.decode",
Title: "Decode OSC Message",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &OSCMessageDecode{config: config}, nil return &OSCMessageDecode{config: config}, nil
}, },

View File

@@ -33,6 +33,7 @@ func (ome *OSCMessageEncode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "osc.message.encode", Type: "osc.message.encode",
Title: "Encode OSC Message",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &OSCMessageEncode{config: config}, nil return &OSCMessageEncode{config: config}, nil
}, },

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"sync" "sync"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -16,6 +17,9 @@ type Processor interface {
type ProcessorRegistration struct { type ProcessorRegistration struct {
Type string `json:"type"` Type string `json:"type"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
ParamsSchema *jsonschema.Schema `json:"paramsSchema,omitempty"`
New func(config.ProcessorConfig) (Processor, error) New func(config.ProcessorConfig) (Processor, error)
} }
@@ -41,3 +45,45 @@ var (
processorRegistryMu sync.RWMutex processorRegistryMu sync.RWMutex
ProcessorRegistry = make(map[string]ProcessorRegistration) ProcessorRegistry = make(map[string]ProcessorRegistration)
) )
func GetProcessorsSchema() *jsonschema.Schema {
processorRegistryMu.RLock()
defer processorRegistryMu.RUnlock()
schema := &jsonschema.Schema{
Schema: "https://json-schema.org/draft/2020-12/schema",
ID: "https://showbridge.io/processors.schema.json",
Title: "Processors",
Description: "processor configurations",
Type: "array",
}
processorDefinitionSchemas := []*jsonschema.Schema{}
for _, proc := range ProcessorRegistry {
processorSchema := &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"type": {
Const: jsonschema.Ptr[any](proc.Type),
},
},
Required: []string{"type"},
AdditionalProperties: nil,
}
if proc.Title != "" {
processorSchema.Title = proc.Title
}
if proc.Description != "" {
processorSchema.Description = proc.Description
}
if proc.ParamsSchema != nil {
processorSchema.Properties["params"] = proc.ParamsSchema
processorSchema.Required = append(processorSchema.Required, "params")
}
processorDefinitionSchemas = append(processorDefinitionSchemas, processorSchema)
}
schema.Items = &jsonschema.Schema{
OneOf: processorDefinitionSchemas,
}
return schema
}

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -45,6 +46,19 @@ func (ro *RouterInput) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "router.input", Type: "router.input",
Title: "Router Input",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"source": {
Title: "Source",
Type: "string",
Description: "source to report as to the router",
},
},
Required: []string{"source"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -41,6 +42,19 @@ func (ro *RouterOutput) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "router.output", Type: "router.output",
Title: "Router Output",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"module": {
Title: "Module ID",
Type: "string",
Description: "ID of module to send output to",
},
},
Required: []string{"module"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -6,6 +6,7 @@ import (
"github.com/expr-lang/expr" "github.com/expr-lang/expr"
"github.com/expr-lang/expr/vm" "github.com/expr-lang/expr/vm"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -37,6 +38,18 @@ func (se *ScriptExpr) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "script.expr", Type: "script.expr",
Title: "Evaluate Expr Expression",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"expression": {
Title: "Expression",
Type: "string",
},
},
Required: []string{"expression"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
"modernc.org/quickjs" "modernc.org/quickjs"
@@ -21,9 +22,9 @@ func (sj *ScriptJS) Process(ctx context.Context, wrappedPayload common.WrappedPa
//NOTE(jwetzell): some weird conversion going on with these types //NOTE(jwetzell): some weird conversion going on with these types
_, isUint8Slice := common.GetAnyAs[[]uint8](wrappedPayload.Payload) _, isUint8Slice := common.GetAnyAs[[]uint8](wrappedPayload.Payload)
_, isbyteSlice := common.GetAnyAs[[]byte](wrappedPayload.Payload) _, isByteSlice := common.GetAnyAs[[]byte](wrappedPayload.Payload)
if isUint8Slice || isbyteSlice { if isUint8Slice || isByteSlice {
intSlice, ok := common.GetAnyAsIntSlice(wrappedPayload.Payload) intSlice, ok := common.GetAnyAsIntSlice(wrappedPayload.Payload)
if ok { if ok {
@@ -94,6 +95,18 @@ func (sj *ScriptJS) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "script.js", Type: "script.js",
Title: "Run JavaScript",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"program": {
Title: "Program",
Type: "string",
},
},
Required: []string{"program"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -2,10 +2,12 @@ package processor
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
extism "github.com/extism/go-sdk" extism "github.com/extism/go-sdk"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -51,6 +53,28 @@ func (sw *ScriptWASM) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "script.wasm", Type: "script.wasm",
Title: "Run WASM Plugin",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"path": {
Title: "Path",
Type: "string",
},
"function": {
Title: "Function",
Type: "string",
Default: json.RawMessage(`"process"`),
},
"enableWasi": {
Title: "Enable WASI",
Type: "boolean",
Default: json.RawMessage("false"),
},
},
Required: []string{"path"},
AdditionalProperties: nil,
},
New: func(processorConfig config.ProcessorConfig) (Processor, error) { New: func(processorConfig config.ProcessorConfig) (Processor, error) {
params := processorConfig.Params params := processorConfig.Params

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"text/template" "text/template"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -52,6 +53,25 @@ func (srac *SipResponseAudioCreate) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "sip.response.audio.create", Type: "sip.response.audio.create",
Title: "Create SIP Audio Response",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"preWait": {
Title: "Pre Wait (ms)",
Type: "integer",
},
"postWait": {
Title: "Post Wait (ms)",
Type: "integer",
},
"audioFile": {
Type: "string",
},
},
Required: []string{"preWait", "postWait", "audioFile"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -8,6 +8,7 @@ import (
"regexp" "regexp"
"text/template" "text/template"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -60,6 +61,25 @@ func (srdc *SipResponseDTMFCreate) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "sip.response.dtmf.create", Type: "sip.response.dtmf.create",
Title: "Create SIP DTMF Response",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"preWait": {
Title: "Pre Wait (ms)",
Type: "integer",
},
"postWait": {
Title: "Post Wait (ms)",
Type: "integer",
},
"digits": {
Type: "string",
},
},
Required: []string{"preWait", "postWait", "digits"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"text/template" "text/template"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -38,6 +39,18 @@ func (sc *StringCreate) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "string.create", Type: "string.create",
Title: "Create String",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"template": {
Title: "Template",
Type: "string",
},
},
Required: []string{"template"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params
templateString, err := params.GetString("template") templateString, err := params.GetString("template")

View File

@@ -34,6 +34,7 @@ func (sd *StringDecode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "string.decode", Type: "string.decode",
Title: "Decode String",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &StringDecode{config: config}, nil return &StringDecode{config: config}, nil
}, },

View File

@@ -33,6 +33,7 @@ func (se *StringEncode) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "string.encode", Type: "string.encode",
Title: "Encode String",
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
return &StringEncode{config: config}, nil return &StringEncode{config: config}, nil
}, },

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -36,6 +37,18 @@ func (ss *StringSplit) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "string.split", Type: "string.split",
Title: "Split String",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"separator": {
Title: "Separator",
Type: "string",
},
},
Required: []string{"separator"},
AdditionalProperties: nil,
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -45,6 +46,17 @@ func (sf *StructFieldGet) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "struct.field.get", Type: "struct.field.get",
Title: "Get Struct Field",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"name": {
Title: "Field Name",
Type: "string",
},
},
Required: []string{"name"},
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params
nameString, err := params.GetString("name") nameString, err := params.GetString("name")

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -64,6 +65,17 @@ func (sm *StructMethodGet) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "struct.method.get", Type: "struct.method.get",
Title: "Get Struct Method",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"name": {
Title: "Method Name",
Type: "string",
},
},
Required: []string{"name"},
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params
nameString, err := params.GetString("name") nameString, err := params.GetString("name")

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/google/jsonschema-go/jsonschema"
"github.com/jwetzell/showbridge-go/internal/common" "github.com/jwetzell/showbridge-go/internal/common"
"github.com/jwetzell/showbridge-go/internal/config" "github.com/jwetzell/showbridge-go/internal/config"
) )
@@ -26,6 +27,18 @@ func (ts *TimeSleep) Type() string {
func init() { func init() {
RegisterProcessor(ProcessorRegistration{ RegisterProcessor(ProcessorRegistration{
Type: "time.sleep", Type: "time.sleep",
Title: "Sleep",
ParamsSchema: &jsonschema.Schema{
Type: "object",
Properties: map[string]*jsonschema.Schema{
"duration": {
Title: "Duration",
Type: "integer",
Description: "Duration to sleep in milliseconds",
},
},
Required: []string{"duration"},
},
New: func(config config.ProcessorConfig) (Processor, error) { New: func(config config.ProcessorConfig) (Processor, error) {
params := config.Params params := config.Params

View File

@@ -1,29 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://showbridge.io/config.schema.json",
"title": "Config",
"description": "showbridge configuration",
"type": "object",
"properties": {
"api": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether the API server is enabled"
},
"port": {
"type": "integer",
"description": "Port for the API server to listen on"
}
},
"required": ["port"]
},
"modules": {
"$ref": "https://showbridge.io/modules.schema.json"
},
"routes": {
"$ref": "https://showbridge.io/routes.schema.json"
}
}
}

View File

@@ -1,586 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://showbridge.io/modules.schema.json",
"title": "Modules",
"description": "module configurations",
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"title": "HTTP Server",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "http.server"
},
"params": {
"type": "object",
"properties": {
"port": {
"title": "Port",
"type": "integer",
"minimum": 1024,
"maximum": 65535
}
},
"required": ["port"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Interval",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "time.interval"
},
"params": {
"type": "object",
"properties": {
"duration": {
"title": "Duration",
"type": "integer",
"description": "Interval duration in milliseconds"
}
},
"required": ["duration"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Timer",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "time.timer"
},
"params": {
"type": "object",
"properties": {
"duration": {
"title": "Duration",
"type": "integer",
"description": "Timer duration in milliseconds"
}
},
"required": ["duration"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "MIDI Input",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "midi.input"
},
"params": {
"type": "object",
"properties": {
"port": {
"title": "Port",
"type": "string"
}
},
"required": ["port"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "MIDI Output",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "midi.output"
},
"params": {
"type": "object",
"properties": {
"port": {
"title": "Port",
"type": "string"
}
},
"required": ["port"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "MQTT Client",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "mqtt.client"
},
"params": {
"type": "object",
"properties": {
"broker": {
"title": "Broker URL",
"type": "string"
},
"topic": {
"title": "Topic",
"type": "string"
},
"clientId": {
"title": "Client ID",
"type": "string"
}
},
"required": ["broker", "topic", "clientId"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "NATS Client",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "nats.client"
},
"params": {
"type": "object",
"properties": {
"url": {
"title": "NATS Server URL",
"type": "string"
},
"subject": {
"title": "Subject",
"type": "string"
}
},
"required": ["url", "subject"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "NATS Server",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "nats.server"
},
"params": {
"type": "object",
"properties": {
"ip": {
"title": "IP",
"type": "string",
"default": "0.0.0.0"
},
"port": {
"title": "Port",
"type": "integer",
"minimum": 1024,
"maximum": 65535,
"default": 4222
}
},
"required": [],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "PSN Client",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "psn.client"
}
},
"required": ["id", "type"],
"additionalProperties": false
},
{
"type": "object",
"title": "RedisClientModule",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "redis.client"
},
"params": {
"type": "object",
"properties": {
"host": {
"type": "string"
},
"port": {
"type": "integer",
"minimum": 1,
"maximum": 65535
}
},
"required": ["host", "port"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Serial Client",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "serial.client"
},
"params": {
"type": "object",
"properties": {
"port": {
"title": "Port",
"type": "string"
},
"baudRate": {
"title": "Baud Rate",
"type": "integer"
}
},
"required": ["port", "baudRate"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "SIP Call Server",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "sip.call.server"
},
"params": {
"type": "object",
"properties": {
"ip": {
"title": "IP",
"type": "string",
"default": "0.0.0.0"
},
"port": {
"title": "Port",
"type": "integer",
"minimum": 1024,
"maximum": 65535,
"default": 5060
},
"transport": {
"title": "Transport",
"type": "string",
"enum": ["udp", "tcp", "ws", "udp4", "tcp4"],
"default": "udp"
},
"userAgent": {
"title": "User Agent",
"type": "string",
"default": "showbridge"
}
},
"required": [],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "SIP DTMF Server",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "sip.dtmf.server"
},
"params": {
"type": "object",
"properties": {
"ip": {
"title": "IP",
"type": "string",
"default": "0.0.0.0"
},
"port": {
"title": "Port",
"type": "integer",
"minimum": 1024,
"maximum": 65535,
"default": 5060
},
"transport": {
"title": "Transport",
"type": "string",
"enum": ["udp", "tcp", "ws", "udp4", "tcp4"],
"default": "udp"
},
"userAgent": {
"title": "User Agent",
"type": "string",
"default": "showbridge"
},
"separator": {
"title": "DTMF Separator",
"type": "string",
"minLength": 1,
"maxLength": 1
}
},
"required": ["separator"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "TCP Client",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "net.tcp.client"
},
"params": {
"type": "object",
"properties": {
"host": {
"title": "Host",
"type": "string"
},
"port": {
"title": "Port",
"type": "integer",
"minimum": 1,
"maximum": 65535
},
"framing": {
"title": "Framing Method",
"type": "string",
"enum": ["LF", "CR", "CRLF", "SLIP", "RAW"]
}
},
"required": ["host", "port", "framing"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "TCP Server",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "net.tcp.server"
},
"params": {
"type": "object",
"properties": {
"ip": {
"title": "IP",
"type": "string",
"default": "0.0.0.0"
},
"port": {
"title": "Port",
"type": "integer",
"minimum": 1024,
"maximum": 65535
},
"framing": {
"title": "Framing Method",
"type": "string",
"enum": ["LF", "CR", "CRLF", "SLIP", "RAW"]
}
},
"required": ["port", "framing"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "UDP Client",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "net.udp.client"
},
"params": {
"type": "object",
"properties": {
"host": {
"title": "Host",
"type": "string"
},
"port": {
"title": "Port",
"type": "integer",
"minimum": 1,
"maximum": 65535
}
},
"required": ["host", "port"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "UDP Multicast",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "net.udp.multicast"
},
"params": {
"type": "object",
"properties": {
"ip": {
"title": "IP",
"type": "string"
},
"port": {
"title": "Port",
"type": "integer",
"minimum": 1024,
"maximum": 65535
}
},
"required": ["ip", "port"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "UDP Server",
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"type": {
"const": "net.udp.server"
},
"params": {
"type": "object",
"properties": {
"ip": {
"title": "IP",
"type": "string",
"default": "0.0.0.0"
},
"port": {
"title": "Port",
"type": "integer",
"minimum": 1024,
"maximum": 65535
}
},
"required": ["port"],
"additionalProperties": false
}
},
"required": ["id", "type", "params"],
"additionalProperties": false
}
]
}
}

View File

@@ -1,926 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://showbridge.io/processors.schema.json",
"title": "Processors",
"description": "processor configurations",
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"title": "Decode ArtNet Packet",
"properties": {
"type": {
"type": "string",
"const": "artnet.packet.decode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Encode ArtNet Packet",
"properties": {
"type": {
"type": "string",
"const": "artnet.packet.encode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Debug Log",
"properties": {
"type": {
"type": "string",
"const": "debug.log"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Filter by Expr expression",
"properties": {
"type": {
"type": "string",
"const": "filter.expr"
},
"params": {
"type": "object",
"properties": {
"expression": {
"title": "Expression",
"type": "string"
}
},
"required": ["expression"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Filter by Regex",
"properties": {
"type": {
"type": "string",
"const": "filter.regex"
},
"params": {
"type": "object",
"properties": {
"pattern": {
"title": "Pattern",
"type": "string"
}
},
"required": ["pattern"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Filter Unique Values",
"properties": {
"type": {
"type": "string",
"const": "filter.unique"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Parse Float",
"properties": {
"type": {
"type": "string",
"const": "float.parse"
},
"params": {
"type": "object",
"properties": {
"bitSize": {
"title": "Bit Size",
"type": "integer",
"enum": [32, 64],
"default": 64
}
},
"additionalProperties": false
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Create FreeD",
"properties": {
"type": {
"type": "string",
"const": "freed.create"
},
"params": {
"type": "object",
"properties": {
"id": {
"title": "Camera ID",
"type": "string"
},
"pan": {
"title": "Pan",
"type": "string"
},
"tilt": {
"title": "Tilt",
"type": "string"
},
"roll": {
"title": "Roll",
"type": "string"
},
"posX": {
"title": "Position X",
"type": "string"
},
"posY": {
"title": "Position Y",
"type": "string"
},
"posZ": {
"title": "Position Z",
"type": "string"
},
"zoom": {
"title": "Zoom",
"type": "string"
},
"focus": {
"title": "Focus",
"type": "string"
}
},
"required": [
"id",
"pan",
"tilt",
"roll",
"posX",
"posY",
"posZ",
"zoom",
"focus"
],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Decode FreeD",
"properties": {
"type": {
"type": "string",
"const": "freed.decode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Encode FreeD",
"properties": {
"type": {
"type": "string",
"const": "freed.encode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Do HTTP Request",
"properties": {
"type": {
"type": "string",
"const": "http.request.do"
},
"params": {
"type": "object",
"properties": {
"method": {
"title": "HTTP Method",
"type": "string",
"enum": ["GET", "POST"]
},
"url": {
"title": "URL",
"type": "string"
}
},
"required": ["method", "url"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Create HTTP Response",
"properties": {
"type": {
"type": "string",
"const": "http.response.create"
},
"params": {
"type": "object",
"properties": {
"status": {
"title": "Status Code",
"type": "integer"
},
"body": {
"title": "Body",
"type": "string"
}
},
"required": ["status", "body"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Parse Int",
"properties": {
"type": {
"type": "string",
"const": "int.parse"
},
"params": {
"type": "object",
"properties": {
"base": {
"title": "Base",
"type": "integer",
"enum": [0, 2, 8, 10, 16],
"default": 10
},
"bitSize": {
"title": "Bit Size",
"type": "integer",
"enum": [0, 8, 16, 32, 64],
"default": 64
}
},
"additionalProperties": false
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Random Int",
"properties": {
"type": {
"type": "string",
"const": "int.random"
},
"params": {
"type": "object",
"properties": {
"min": {
"title": "Minimum",
"type": "integer"
},
"max": {
"title": "Maximum",
"type": "integer"
}
},
"required": ["min", "max"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Scale Int",
"properties": {
"type": {
"type": "string",
"const": "int.scale"
},
"params": {
"type": "object",
"properties": {
"inMin": {
"title": "Input Minimum",
"type": "integer"
},
"inMax": {
"title": "Input Maximum",
"type": "integer"
},
"outMin": {
"title": "Output Minimum",
"type": "integer"
},
"outMax": {
"title": "Output Maximum",
"type": "integer"
}
},
"required": ["inMin", "inMax", "outMin", "outMax"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Decode JSON",
"properties": {
"type": {
"type": "string",
"const": "json.decode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Encode JSON",
"properties": {
"type": {
"type": "string",
"const": "json.encode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Create MIDI Message",
"properties": {
"type": {
"type": "string",
"const": "midi.message.create"
},
"params": {
"type": "object",
"oneOf": [
{
"type": "object",
"properties": {
"type": {
"title": "MIDI Message Type",
"type": "string",
"enum": ["NoteOn", "noteon", "note_on"]
},
"channel": {
"title": "Channel",
"type": "string"
},
"note": {
"title": "Note",
"type": "string"
},
"velocity": {
"title": "Velocity",
"type": "string"
}
},
"required": ["type", "channel", "note", "velocity"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"type": {
"title": "MIDI Message Type",
"type": "string",
"enum": ["NoteOff", "noteoff", "note_off"]
},
"channel": {
"title": "Channel",
"type": "string"
},
"note": {
"title": "Note",
"type": "string"
},
"velocity": {
"title": "Velocity",
"type": "string"
}
},
"required": ["type", "channel", "note", "velocity"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"type": {
"title": "MIDI Message Type",
"type": "string",
"enum": ["ControlChange", "controlchange", "control_change"]
},
"channel": {
"title": "Channel",
"type": "string"
},
"control": {
"title": "Control",
"type": "string"
},
"value": {
"title": "Value",
"type": "string"
}
},
"required": ["type", "channel", "control", "value"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"type": {
"title": "MIDI Message Type",
"type": "string",
"enum": ["ProgramChange", "programchange", "program_change"]
},
"channel": {
"title": "Channel",
"type": "string"
},
"program": {
"title": "Program",
"type": "string"
}
},
"required": ["type", "channel", "program"],
"additionalProperties": false
}
]
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Decode MIDI Message",
"properties": {
"type": {
"type": "string",
"const": "midi.message.decode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Encode MIDI Message",
"properties": {
"type": {
"type": "string",
"const": "midi.message.encode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Unpack MIDI Message",
"properties": {
"type": {
"type": "string",
"const": "midi.message.unpack"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Create MQTT Message",
"properties": {
"type": {
"type": "string",
"const": "mqtt.message.create"
},
"params": {
"type": "object",
"properties": {
"topic": {
"title": "Topic",
"type": "string"
},
"qos": {
"title": "QoS",
"type": "number"
},
"retained": {
"title": "Retained",
"type": "boolean"
},
"payload": {
"title": "Payload",
"type": "string"
}
},
"required": ["topic", "qos", "retained", "payload"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Encode MQTT Message",
"properties": {
"type": {
"type": "string",
"const": "mqtt.message.encode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Create NATS Message",
"properties": {
"type": {
"type": "string",
"const": "nats.message.create"
},
"params": {
"type": "object",
"properties": {
"subject": {
"title": "Subject",
"type": "string"
},
"payload": {
"title": "Payload",
"type": "string"
}
},
"required": ["subject", "payload"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Create OSC Message",
"properties": {
"type": {
"type": "string",
"const": "osc.message.create"
},
"params": {
"type": "object",
"properties": {
"address": {
"title": "Address",
"type": "string"
},
"args": {
"title": "Arguments",
"type": "array",
"items": {
"type": "string"
}
},
"types": {
"title": "Argument Types",
"type": "string"
}
},
"required": ["address"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Decode OSC Message",
"properties": {
"type": {
"type": "string",
"const": "osc.message.decode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Encode OSC Message",
"properties": {
"type": {
"type": "string",
"const": "osc.message.encode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Router Input",
"properties": {
"type": {
"type": "string",
"const": "router.input"
},
"params": {
"type": "object",
"properties": {
"source": {
"title": "Source",
"type": "string",
"description": "source to report as to the router"
}
},
"required": ["source"]
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Router Output",
"properties": {
"type": {
"type": "string",
"const": "router.output"
},
"params": {
"type": "object",
"properties": {
"module": {
"title": "Module ID",
"type": "string",
"description": "ID of module to send output to"
}
},
"required": ["module"]
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Evaluate Expr expression",
"properties": {
"type": {
"type": "string",
"const": "script.expr"
},
"params": {
"type": "object",
"properties": {
"expression": {
"title": "Expression",
"type": "string"
}
},
"required": ["expression"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Run JavaScript",
"properties": {
"type": {
"type": "string",
"const": "script.js"
},
"params": {
"type": "object",
"properties": {
"program": {
"title": "Program",
"type": "string"
}
},
"required": ["program"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Run WASM Plugin",
"properties": {
"type": {
"type": "string",
"const": "script.wasm"
},
"params": {
"type": "object",
"properties": {
"path": {
"title": "Path",
"type": "string"
},
"function": {
"title": "Function",
"type": "string",
"default": "process"
},
"enableWasi": {
"title": "Enable WASI",
"type": "boolean",
"default": false
}
},
"required": ["path"],
"additionalProperties": false
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Create String",
"properties": {
"type": {
"type": "string",
"const": "string.create"
},
"params": {
"type": "object",
"properties": {
"template": {
"title": "Template",
"type": "string"
}
},
"required": ["template"]
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Decode String",
"properties": {
"type": {
"type": "string",
"const": "string.decode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Encode String",
"properties": {
"type": {
"type": "string",
"const": "string.encode"
}
},
"required": ["type"],
"additionalProperties": false
},
{
"type": "object",
"title": "Split String",
"properties": {
"type": {
"type": "string",
"const": "string.split"
},
"params": {
"type": "object",
"properties": {
"separator": {
"title": "Separator",
"type": "string"
}
},
"required": ["separator"]
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Get Struct Field",
"properties": {
"type": {
"type": "string",
"const": "struct.field.get"
},
"params": {
"type": "object",
"properties": {
"name": {
"title": "Field Name",
"type": "string"
}
},
"required": ["name"]
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Get Struct Method",
"properties": {
"type": {
"type": "string",
"const": "struct.method.get"
},
"params": {
"type": "object",
"properties": {
"name": {
"title": "Method Name",
"type": "string"
}
},
"required": ["name"]
}
},
"required": ["type", "params"],
"additionalProperties": false
},
{
"type": "object",
"title": "Sleep",
"properties": {
"type": {
"type": "string",
"const": "time.sleep"
},
"params": {
"type": "object",
"properties": {
"duration": {
"title": "Duration",
"type": "integer",
"description": "Duration to sleep in milliseconds"
}
},
"required": ["duration"]
}
},
"required": ["type", "params"],
"additionalProperties": false
}
]
}
}

View File

@@ -1,20 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://showbridge.io/routes.schema.json",
"title": "Routes",
"description": "route configurations",
"type": "array",
"items": {
"type": "object",
"properties": {
"input": {
"type": "string",
"minLength": 1
},
"processors": {
"$ref": "https://showbridge.io/processors.schema.json"
}
},
"required": ["input"]
}
}