From 74e8d2e01988b9ebbc59480da1242ca90a3420b9 Mon Sep 17 00:00:00 2001 From: Daniel Ponte Date: Tue, 6 Aug 2024 20:52:59 -0400 Subject: [PATCH] Filter in pb --- pkg/calls/filter.go | 67 +++++++-- pkg/gordio/nexus/client.go | 7 +- pkg/gordio/nexus/commands.go | 6 +- pkg/gordio/nexus/nexus.go | 14 +- pkg/gordio/server/server.go | 10 +- pkg/gordio/sources/http.go | 2 +- pkg/live/listener.go | 13 -- pkg/pb/stillbox.pb.go | 263 ++++++++++++++++++++++++++++++----- pkg/pb/stillbox.proto | 16 ++- 9 files changed, 321 insertions(+), 77 deletions(-) delete mode 100644 pkg/live/listener.go diff --git a/pkg/calls/filter.go b/pkg/calls/filter.go index ac050ef..440b39b 100644 --- a/pkg/calls/filter.go +++ b/pkg/calls/filter.go @@ -4,24 +4,24 @@ import ( "context" "dynatron.me/x/stillbox/pkg/gordio/database" + "dynatron.me/x/stillbox/pkg/pb" ) -type FilterQuery struct { - Query string - Params []interface{} -} - type Talkgroup struct { System uint32 Talkgroup uint32 } +func (c *Call) TalkgroupTuple() Talkgroup { + return Talkgroup{System: uint32(c.System), Talkgroup: uint32(c.Talkgroup)} +} + func (t Talkgroup) Pack() int64 { // P25 system IDs are 12 bits, so we can fit them in a signed 8 byte int (int64, pg INT8) return int64((int64(t.System) << 32) | int64(t.Talkgroup)) } -type Filter struct { +type TalkgroupFilter struct { Talkgroups []Talkgroup `json:"talkgroups,omitempty"` TalkgroupsNot []Talkgroup `json:"talkgroupsNot,omitempty"` TalkgroupTagsAll []string `json:"talkgroupTagsAll,omitempty"` @@ -31,6 +31,36 @@ type Filter struct { talkgroups map[Talkgroup]bool } +func TalkgroupFilterFromPB(p *pb.Filter) *TalkgroupFilter { + tgf := &TalkgroupFilter{ + TalkgroupTagsAll: p.TalkgroupTagsAll, + TalkgroupTagsAny: p.TalkgroupTagsAny, + TalkgroupTagsNot: p.TalkgroupTagsNot, + } + + if l := len(p.Talkgroups); l > 0 { + tgf.Talkgroups = make([]Talkgroup, l) + for i, t := range p.Talkgroups { + tgf.Talkgroups[i] = Talkgroup{ + System: uint32(t.System), + Talkgroup: uint32(t.Talkgroup), + } + } + } + + if l := len(p.TalkgroupsNot); l > 0 { + tgf.TalkgroupsNot = make([]Talkgroup, l) + for i, t := range p.TalkgroupsNot { + tgf.TalkgroupsNot[i] = Talkgroup{ + System: uint32(t.System), + Talkgroup: uint32(t.Talkgroup), + } + } + } + + return tgf +} + func PackedTGs(tg []Talkgroup) []int64 { s := make([]int64, len(tg)) @@ -41,15 +71,15 @@ func PackedTGs(tg []Talkgroup) []int64 { return s } -func (f *Filter) hasTags() bool { +func (f *TalkgroupFilter) hasTags() bool { return len(f.TalkgroupTagsAny) > 0 || len(f.TalkgroupTagsAll) > 0 || len(f.TalkgroupTagsNot) > 0 } -func (f *Filter) GetFinalTalkgroups() map[Talkgroup]bool { +func (f *TalkgroupFilter) GetFinalTalkgroups() map[Talkgroup]bool { return f.talkgroups } -func (f *Filter) compile(ctx context.Context) error { +func (f *TalkgroupFilter) compile(ctx context.Context) error { f.talkgroups = make(map[Talkgroup]bool) for _, tg := range f.Talkgroups { f.talkgroups[tg] = true @@ -59,7 +89,7 @@ func (f *Filter) compile(ctx context.Context) error { db := database.FromCtx(ctx) tagTGs, err := db.GetTalkgroupIDsByTags(ctx, f.TalkgroupTagsAny, f.TalkgroupTagsAll, f.TalkgroupTagsNot) if err != nil { - return nil, err + return err } for _, tg := range tagTGs { @@ -74,7 +104,7 @@ func (f *Filter) compile(ctx context.Context) error { return nil } -func (f *Filter) Test(ctx context.Context, call *Call) bool { +func (f *TalkgroupFilter) Test(ctx context.Context, call *Call) bool { if f == nil { // no filter means all calls return true } @@ -86,5 +116,20 @@ func (f *Filter) Test(ctx context.Context, call *Call) bool { } } + tg := call.TalkgroupTuple() + + tgRes, have := f.talkgroups[tg] + if have { + return tgRes + } + + for _, patch := range call.Patches { + tg.Talkgroup = uint32(patch) + tgRes, have := f.talkgroups[tg] + if have { + return tgRes + } + } + return false } diff --git a/pkg/gordio/nexus/client.go b/pkg/gordio/nexus/client.go index 0237f35..627f719 100644 --- a/pkg/gordio/nexus/client.go +++ b/pkg/gordio/nexus/client.go @@ -26,9 +26,10 @@ type client struct { Connection - filter *calls.Filter - live live.Listener - nexus *Nexus + liveState pb.LiveState + filter *calls.TalkgroupFilter + + nexus *Nexus } type Connection interface { diff --git a/pkg/gordio/nexus/commands.go b/pkg/gordio/nexus/commands.go index 58f81a6..525fe2e 100644 --- a/pkg/gordio/nexus/commands.go +++ b/pkg/gordio/nexus/commands.go @@ -17,9 +17,7 @@ func (c *client) HandleCommand(cmd *pb.Command) { } func (c *client) Live(cmd *pb.Live) { - switch cmd.State { - case pb.LiveState_LS_STOPPED: - case pb.LiveState_LS_LIVE: - case pb.LiveState_LS_PAUSED: + if cmd.State != nil { + c.liveState = *cmd.State } } diff --git a/pkg/gordio/nexus/nexus.go b/pkg/gordio/nexus/nexus.go index 65350be..134ffe2 100644 --- a/pkg/gordio/nexus/nexus.go +++ b/pkg/gordio/nexus/nexus.go @@ -1,6 +1,7 @@ package nexus import ( + "context" "sync" "dynatron.me/x/stillbox/pkg/calls" @@ -34,7 +35,7 @@ func New() *Nexus { return n } -func (n *Nexus) Go(done <-chan struct{}) { +func (n *Nexus) Go(ctx context.Context) { for { select { case call, ok := <-n.callCh: @@ -42,8 +43,8 @@ func (n *Nexus) Go(done <-chan struct{}) { return } - n.broadcastCallToClients(call) - case <-done: + n.broadcastCallToClients(ctx, call) + case <-ctx.Done(): return } } @@ -53,17 +54,18 @@ func (n *Nexus) BroadcastCall(call *calls.Call) { n.callCh <- call } -func (n *Nexus) broadcastCallToClients(call *calls.Call) { +func (n *Nexus) broadcastCallToClients(ctx context.Context, call *calls.Call) { message := &pb.Message{ ToClientMessage: &pb.Message_Call{Call: call.ToPB()}, } n.Lock() defer n.Unlock() - for cl, _ := range n.clients { - if cl.filter != nil && !cl.filter.Test(call) { + for cl := range n.clients { + if !cl.filter.Test(ctx, call) { continue } + if cl.Send(message) { // we already hold the lock, and the channel is closed anyway delete(n.clients, cl) diff --git a/pkg/gordio/server/server.go b/pkg/gordio/server/server.go index e6b394c..0ab41a8 100644 --- a/pkg/gordio/server/server.go +++ b/pkg/gordio/server/server.go @@ -1,6 +1,7 @@ package server import ( + "context" "net/http" "dynatron.me/x/stillbox/pkg/gordio/auth" @@ -54,12 +55,11 @@ func New(cfg *config.Config) (*Server, error) { func (s *Server) Go() error { defer s.db.Close() - done := make(chan struct{}) - defer func() { - close(done) - }() - go s.nex.Go(done) + ctx, cancel := context.WithCancel(database.CtxWithDB(context.Background(), s.db)) + defer cancel() + + go s.nex.Go(ctx) http.ListenAndServe(s.conf.Listen, s.r) return nil diff --git a/pkg/gordio/sources/http.go b/pkg/gordio/sources/http.go index 57f3ee0..c8dfe7d 100644 --- a/pkg/gordio/sources/http.go +++ b/pkg/gordio/sources/http.go @@ -10,8 +10,8 @@ import ( "time" "dynatron.me/x/stillbox/internal/common" - "dynatron.me/x/stillbox/pkg/gordio/auth" "dynatron.me/x/stillbox/pkg/calls" + "dynatron.me/x/stillbox/pkg/gordio/auth" "github.com/go-chi/chi/v5" "github.com/rs/zerolog/log" ) diff --git a/pkg/live/listener.go b/pkg/live/listener.go deleted file mode 100644 index d17242b..0000000 --- a/pkg/live/listener.go +++ /dev/null @@ -1,13 +0,0 @@ -package live - -import ( - "dynatron.me/x/stillbox/pkg/pb" -) - -type Listener struct { - pb.Live -} - -func (l *Listener) IsLive() bool { - return l.State == pb.LiveState_LS_LIVE -} diff --git a/pkg/pb/stillbox.pb.go b/pkg/pb/stillbox.pb.go index b0ca97c..cb51185 100644 --- a/pkg/pb/stillbox.pb.go +++ b/pkg/pb/stillbox.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v5.27.2 +// protoc v5.27.1 // source: stillbox.proto package pb @@ -488,7 +488,8 @@ type Live struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - State LiveState `protobuf:"varint,1,opt,name=state,proto3,enum=stillbox.LiveState" json:"state,omitempty"` + State *LiveState `protobuf:"varint,1,opt,name=state,proto3,enum=stillbox.LiveState,oneof" json:"state,omitempty"` + Filter *Filter `protobuf:"bytes,2,opt,name=filter,proto3,oneof" json:"filter,omitempty"` } func (x *Live) Reset() { @@ -524,12 +525,153 @@ func (*Live) Descriptor() ([]byte, []int) { } func (x *Live) GetState() LiveState { - if x != nil { - return x.State + if x != nil && x.State != nil { + return *x.State } return LiveState_LS_STOPPED } +func (x *Live) GetFilter() *Filter { + if x != nil { + return x.Filter + } + return nil +} + +type Talkgroup struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + System int32 `protobuf:"varint,1,opt,name=system,proto3" json:"system,omitempty"` + Talkgroup int32 `protobuf:"varint,2,opt,name=talkgroup,proto3" json:"talkgroup,omitempty"` +} + +func (x *Talkgroup) Reset() { + *x = Talkgroup{} + if protoimpl.UnsafeEnabled { + mi := &file_stillbox_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Talkgroup) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Talkgroup) ProtoMessage() {} + +func (x *Talkgroup) ProtoReflect() protoreflect.Message { + mi := &file_stillbox_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Talkgroup.ProtoReflect.Descriptor instead. +func (*Talkgroup) Descriptor() ([]byte, []int) { + return file_stillbox_proto_rawDescGZIP(), []int{6} +} + +func (x *Talkgroup) GetSystem() int32 { + if x != nil { + return x.System + } + return 0 +} + +func (x *Talkgroup) GetTalkgroup() int32 { + if x != nil { + return x.Talkgroup + } + return 0 +} + +type Filter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Talkgroups []*Talkgroup `protobuf:"bytes,1,rep,name=talkgroups,proto3" json:"talkgroups,omitempty"` + TalkgroupsNot []*Talkgroup `protobuf:"bytes,2,rep,name=talkgroups_not,json=talkgroupsNot,proto3" json:"talkgroups_not,omitempty"` + TalkgroupTagsAll []string `protobuf:"bytes,3,rep,name=talkgroup_tags_all,json=talkgroupTagsAll,proto3" json:"talkgroup_tags_all,omitempty"` + TalkgroupTagsAny []string `protobuf:"bytes,4,rep,name=talkgroup_tags_any,json=talkgroupTagsAny,proto3" json:"talkgroup_tags_any,omitempty"` + TalkgroupTagsNot []string `protobuf:"bytes,5,rep,name=talkgroup_tags_not,json=talkgroupTagsNot,proto3" json:"talkgroup_tags_not,omitempty"` +} + +func (x *Filter) Reset() { + *x = Filter{} + if protoimpl.UnsafeEnabled { + mi := &file_stillbox_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Filter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Filter) ProtoMessage() {} + +func (x *Filter) ProtoReflect() protoreflect.Message { + mi := &file_stillbox_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Filter.ProtoReflect.Descriptor instead. +func (*Filter) Descriptor() ([]byte, []int) { + return file_stillbox_proto_rawDescGZIP(), []int{7} +} + +func (x *Filter) GetTalkgroups() []*Talkgroup { + if x != nil { + return x.Talkgroups + } + return nil +} + +func (x *Filter) GetTalkgroupsNot() []*Talkgroup { + if x != nil { + return x.TalkgroupsNot + } + return nil +} + +func (x *Filter) GetTalkgroupTagsAll() []string { + if x != nil { + return x.TalkgroupTagsAll + } + return nil +} + +func (x *Filter) GetTalkgroupTagsAny() []string { + if x != nil { + return x.TalkgroupTagsAny + } + return nil +} + +func (x *Filter) GetTalkgroupTagsNot() []string { + if x != nil { + return x.TalkgroupTagsNot + } + return nil +} + type Search struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -539,7 +681,7 @@ type Search struct { func (x *Search) Reset() { *x = Search{} if protoimpl.UnsafeEnabled { - mi := &file_stillbox_proto_msgTypes[6] + mi := &file_stillbox_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -552,7 +694,7 @@ func (x *Search) String() string { func (*Search) ProtoMessage() {} func (x *Search) ProtoReflect() protoreflect.Message { - mi := &file_stillbox_proto_msgTypes[6] + mi := &file_stillbox_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -565,7 +707,7 @@ func (x *Search) ProtoReflect() protoreflect.Message { // Deprecated: Use Search.ProtoReflect.Descriptor instead. func (*Search) Descriptor() ([]byte, []int) { - return file_stillbox_proto_rawDescGZIP(), []int{6} + return file_stillbox_proto_rawDescGZIP(), []int{8} } var File_stillbox_proto protoreflect.FileDescriptor @@ -624,16 +766,41 @@ var file_stillbox_proto_rawDesc = []byte{ 0x63, 0x68, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x43, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x31, 0x0a, - 0x04, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x29, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, + 0x6e, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x7a, 0x0a, + 0x04, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, - 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x22, 0x08, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2a, 0x37, 0x0a, 0x09, 0x4c, 0x69, - 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x53, 0x5f, 0x53, 0x54, - 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x53, 0x5f, 0x4c, 0x49, - 0x56, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x53, 0x5f, 0x50, 0x41, 0x55, 0x53, 0x45, - 0x44, 0x10, 0x02, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, + 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x48, 0x01, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x09, + 0x0a, 0x07, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x09, 0x54, 0x61, 0x6c, + 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1c, + 0x0a, 0x09, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x09, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x83, 0x02, 0x0a, + 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x0a, 0x74, 0x61, 0x6c, 0x6b, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, + 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x52, 0x0a, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x3a, 0x0a, 0x0e, + 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x5f, 0x6e, 0x6f, 0x74, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x78, 0x2e, + 0x54, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0d, 0x74, 0x61, 0x6c, 0x6b, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x4e, 0x6f, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x61, 0x6c, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x61, 0x6c, 0x6c, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, + 0x61, 0x67, 0x73, 0x41, 0x6c, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x61, 0x6e, 0x79, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x10, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, + 0x73, 0x41, 0x6e, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x5f, 0x6e, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x10, 0x74, 0x61, 0x6c, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x4e, + 0x6f, 0x74, 0x22, 0x08, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2a, 0x37, 0x0a, 0x09, + 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x53, 0x5f, + 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x53, 0x5f, + 0x4c, 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x53, 0x5f, 0x50, 0x41, 0x55, + 0x53, 0x45, 0x44, 0x10, 0x02, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -649,7 +816,7 @@ func file_stillbox_proto_rawDescGZIP() []byte { } var file_stillbox_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_stillbox_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_stillbox_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_stillbox_proto_goTypes = []any{ (LiveState)(0), // 0: stillbox.LiveState (*Message)(nil), // 1: stillbox.Message @@ -658,23 +825,28 @@ var file_stillbox_proto_goTypes = []any{ (*Notification)(nil), // 4: stillbox.Notification (*Command)(nil), // 5: stillbox.Command (*Live)(nil), // 6: stillbox.Live - (*Search)(nil), // 7: stillbox.Search - (*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp + (*Talkgroup)(nil), // 7: stillbox.Talkgroup + (*Filter)(nil), // 8: stillbox.Filter + (*Search)(nil), // 9: stillbox.Search + (*timestamppb.Timestamp)(nil), // 10: google.protobuf.Timestamp } var file_stillbox_proto_depIdxs = []int32{ - 2, // 0: stillbox.Message.call:type_name -> stillbox.Call - 4, // 1: stillbox.Message.notification:type_name -> stillbox.Notification - 3, // 2: stillbox.Message.popup:type_name -> stillbox.UserPopup - 8, // 3: stillbox.Call.dateTime:type_name -> google.protobuf.Timestamp - 8, // 4: stillbox.Notification.dateTime:type_name -> google.protobuf.Timestamp - 6, // 5: stillbox.Command.liveCommand:type_name -> stillbox.Live - 7, // 6: stillbox.Command.searchCommand:type_name -> stillbox.Search - 0, // 7: stillbox.Live.state:type_name -> stillbox.LiveState - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 2, // 0: stillbox.Message.call:type_name -> stillbox.Call + 4, // 1: stillbox.Message.notification:type_name -> stillbox.Notification + 3, // 2: stillbox.Message.popup:type_name -> stillbox.UserPopup + 10, // 3: stillbox.Call.dateTime:type_name -> google.protobuf.Timestamp + 10, // 4: stillbox.Notification.dateTime:type_name -> google.protobuf.Timestamp + 6, // 5: stillbox.Command.liveCommand:type_name -> stillbox.Live + 9, // 6: stillbox.Command.searchCommand:type_name -> stillbox.Search + 0, // 7: stillbox.Live.state:type_name -> stillbox.LiveState + 8, // 8: stillbox.Live.filter:type_name -> stillbox.Filter + 7, // 9: stillbox.Filter.talkgroups:type_name -> stillbox.Talkgroup + 7, // 10: stillbox.Filter.talkgroups_not:type_name -> stillbox.Talkgroup + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_stillbox_proto_init() } @@ -756,6 +928,30 @@ func file_stillbox_proto_init() { } } file_stillbox_proto_msgTypes[6].Exporter = func(v any, i int) any { + switch v := v.(*Talkgroup); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_stillbox_proto_msgTypes[7].Exporter = func(v any, i int) any { + switch v := v.(*Filter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_stillbox_proto_msgTypes[8].Exporter = func(v any, i int) any { switch v := v.(*Search); i { case 0: return &v.state @@ -777,13 +973,14 @@ func file_stillbox_proto_init() { (*Command_LiveCommand)(nil), (*Command_SearchCommand)(nil), } + file_stillbox_proto_msgTypes[5].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_stillbox_proto_rawDesc, NumEnums: 1, - NumMessages: 7, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/pb/stillbox.proto b/pkg/pb/stillbox.proto index dfb325e..57c5dc2 100644 --- a/pkg/pb/stillbox.proto +++ b/pkg/pb/stillbox.proto @@ -50,7 +50,21 @@ enum LiveState { } message Live { - LiveState state = 1; + optional LiveState state = 1; + optional Filter filter = 2; +} + +message Talkgroup { + int32 system = 1; + int32 talkgroup = 2; +} + +message Filter { + repeated Talkgroup talkgroups = 1; + repeated Talkgroup talkgroups_not = 2; + repeated string talkgroup_tags_all = 3; + repeated string talkgroup_tags_any = 4; + repeated string talkgroup_tags_not = 5; } message Search {