add: sensors

This commit is contained in:
Charles Hathaway
2023-10-01 22:02:30 -07:00
parent a07a993bab
commit ac4e32697c
13 changed files with 1247 additions and 191 deletions
+31
View File
@@ -14,6 +14,7 @@ import (
"connectrpc.com/connect" "connectrpc.com/connect"
pb "github.com/chathaway-codes/home-sensors/v2/gen" pb "github.com/chathaway-codes/home-sensors/v2/gen"
servicepb "github.com/chathaway-codes/home-sensors/v2/gen/genconnect" servicepb "github.com/chathaway-codes/home-sensors/v2/gen/genconnect"
"github.com/chathaway-codes/home-sensors/v2/internal/sensors"
"github.com/chathaway-codes/home-sensors/v2/internal/video" "github.com/chathaway-codes/home-sensors/v2/internal/video"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v3"
"github.com/pion/webrtc/v3/pkg/media" "github.com/pion/webrtc/v3/pkg/media"
@@ -37,6 +38,11 @@ func main() {
if err != nil { if err != nil {
log.Fatal().Err(err).Msg("failed to get default video") log.Fatal().Err(err).Msg("failed to get default video")
} }
sensors, err := sensors.Default.Get()
if err != nil {
log.Fatal().Err(err).Msg("failed to get default sensor")
}
client := servicepb.NewSignalerServiceClient(http.DefaultClient, "http://192.168.0.65:8080/") client := servicepb.NewSignalerServiceClient(http.DefaultClient, "http://192.168.0.65:8080/")
authToken, err := client.CreateAuthToken(ctx, connect.NewRequest(&pb.CreateAuthTokenRequest{ authToken, err := client.CreateAuthToken(ctx, connect.NewRequest(&pb.CreateAuthTokenRequest{
Home: "home1234", Home: "home1234",
@@ -54,6 +60,14 @@ func main() {
go vid.Run() go vid.Run()
defer vid.Done() defer vid.Done()
go sensors.Run()
defer sensors.Done()
sensorCh, sensorDone := sensors.Join()
defer sensorDone()
go handleSensor(ctx, client, token, sensorCh)
// Create a new RTCPeerConnection // Create a new RTCPeerConnection
log.Info().Msg("waiting for connections") log.Info().Msg("waiting for connections")
@@ -67,6 +81,23 @@ func main() {
} }
} }
func handleSensor(ctx context.Context, client servicepb.SignalerServiceClient, token string, ch <-chan *pb.Sample) {
for {
var sample *pb.Sample
select {
case sample = <-ch:
// proceed
case <-ctx.Done():
return
}
if _, err := client.CreateSample(ctx, withAuth(token, &pb.CreateSampleRequest{
Sample: sample,
})); err != nil {
log.Error().Err(err).Msg("failed to create sample")
}
}
}
func handleSession(ctx context.Context, client servicepb.SignalerServiceClient, token string, session *connect.Response[pb.Session], vid *video.Video) { func handleSession(ctx context.Context, client servicepb.SignalerServiceClient, token string, session *connect.Response[pb.Session], vid *video.Video) {
var err error var err error
log.Debug().Msg("new session") log.Debug().Msg("new session")
@@ -51,6 +51,12 @@ const (
// SignalerServicePopIceMessageProcedure is the fully-qualified name of the SignalerService's // SignalerServicePopIceMessageProcedure is the fully-qualified name of the SignalerService's
// PopIceMessage RPC. // PopIceMessage RPC.
SignalerServicePopIceMessageProcedure = "/signaler.SignalerService/PopIceMessage" SignalerServicePopIceMessageProcedure = "/signaler.SignalerService/PopIceMessage"
// SignalerServiceCreateSampleProcedure is the fully-qualified name of the SignalerService's
// CreateSample RPC.
SignalerServiceCreateSampleProcedure = "/signaler.SignalerService/CreateSample"
// SignalerServiceListSamplesProcedure is the fully-qualified name of the SignalerService's
// ListSamples RPC.
SignalerServiceListSamplesProcedure = "/signaler.SignalerService/ListSamples"
) )
// SignalerServiceClient is a client for the signaler.SignalerService service. // SignalerServiceClient is a client for the signaler.SignalerService service.
@@ -72,6 +78,12 @@ type SignalerServiceClient interface {
// //
// If there are no messages, this blocks until one becomes available. // If there are no messages, this blocks until one becomes available.
PopIceMessage(context.Context, *connect.Request[gen.PopIceMessageRequest]) (*connect.Response[gen.IceMessage], error) PopIceMessage(context.Context, *connect.Request[gen.PopIceMessageRequest]) (*connect.Response[gen.IceMessage], error)
// CreateSample creates a sample for the given camera.
// If called without an auth token indicating a camera, an error
// is returned.
// TODO: this should be moved to a seperate service
CreateSample(context.Context, *connect.Request[gen.CreateSampleRequest]) (*connect.Response[gen.Sample], error)
ListSamples(context.Context, *connect.Request[gen.ListSamplesRequest]) (*connect.Response[gen.ListSamplesResponse], error)
} }
// NewSignalerServiceClient constructs a client for the signaler.SignalerService service. By // NewSignalerServiceClient constructs a client for the signaler.SignalerService service. By
@@ -114,6 +126,16 @@ func NewSignalerServiceClient(httpClient connect.HTTPClient, baseURL string, opt
baseURL+SignalerServicePopIceMessageProcedure, baseURL+SignalerServicePopIceMessageProcedure,
opts..., opts...,
), ),
createSample: connect.NewClient[gen.CreateSampleRequest, gen.Sample](
httpClient,
baseURL+SignalerServiceCreateSampleProcedure,
opts...,
),
listSamples: connect.NewClient[gen.ListSamplesRequest, gen.ListSamplesResponse](
httpClient,
baseURL+SignalerServiceListSamplesProcedure,
opts...,
),
} }
} }
@@ -125,6 +147,8 @@ type signalerServiceClient struct {
popSession *connect.Client[gen.PopSessionRequest, gen.Session] popSession *connect.Client[gen.PopSessionRequest, gen.Session]
createIceMessage *connect.Client[gen.CreateIceMessageRequest, gen.IceMessage] createIceMessage *connect.Client[gen.CreateIceMessageRequest, gen.IceMessage]
popIceMessage *connect.Client[gen.PopIceMessageRequest, gen.IceMessage] popIceMessage *connect.Client[gen.PopIceMessageRequest, gen.IceMessage]
createSample *connect.Client[gen.CreateSampleRequest, gen.Sample]
listSamples *connect.Client[gen.ListSamplesRequest, gen.ListSamplesResponse]
} }
// CreateAuthToken calls signaler.SignalerService.CreateAuthToken. // CreateAuthToken calls signaler.SignalerService.CreateAuthToken.
@@ -157,6 +181,16 @@ func (c *signalerServiceClient) PopIceMessage(ctx context.Context, req *connect.
return c.popIceMessage.CallUnary(ctx, req) return c.popIceMessage.CallUnary(ctx, req)
} }
// CreateSample calls signaler.SignalerService.CreateSample.
func (c *signalerServiceClient) CreateSample(ctx context.Context, req *connect.Request[gen.CreateSampleRequest]) (*connect.Response[gen.Sample], error) {
return c.createSample.CallUnary(ctx, req)
}
// ListSamples calls signaler.SignalerService.ListSamples.
func (c *signalerServiceClient) ListSamples(ctx context.Context, req *connect.Request[gen.ListSamplesRequest]) (*connect.Response[gen.ListSamplesResponse], error) {
return c.listSamples.CallUnary(ctx, req)
}
// SignalerServiceHandler is an implementation of the signaler.SignalerService service. // SignalerServiceHandler is an implementation of the signaler.SignalerService service.
type SignalerServiceHandler interface { type SignalerServiceHandler interface {
CreateAuthToken(context.Context, *connect.Request[gen.CreateAuthTokenRequest]) (*connect.Response[gen.AuthToken], error) CreateAuthToken(context.Context, *connect.Request[gen.CreateAuthTokenRequest]) (*connect.Response[gen.AuthToken], error)
@@ -176,6 +210,12 @@ type SignalerServiceHandler interface {
// //
// If there are no messages, this blocks until one becomes available. // If there are no messages, this blocks until one becomes available.
PopIceMessage(context.Context, *connect.Request[gen.PopIceMessageRequest]) (*connect.Response[gen.IceMessage], error) PopIceMessage(context.Context, *connect.Request[gen.PopIceMessageRequest]) (*connect.Response[gen.IceMessage], error)
// CreateSample creates a sample for the given camera.
// If called without an auth token indicating a camera, an error
// is returned.
// TODO: this should be moved to a seperate service
CreateSample(context.Context, *connect.Request[gen.CreateSampleRequest]) (*connect.Response[gen.Sample], error)
ListSamples(context.Context, *connect.Request[gen.ListSamplesRequest]) (*connect.Response[gen.ListSamplesResponse], error)
} }
// NewSignalerServiceHandler builds an HTTP handler from the service implementation. It returns the // NewSignalerServiceHandler builds an HTTP handler from the service implementation. It returns the
@@ -214,6 +254,16 @@ func NewSignalerServiceHandler(svc SignalerServiceHandler, opts ...connect.Handl
svc.PopIceMessage, svc.PopIceMessage,
opts..., opts...,
) )
signalerServiceCreateSampleHandler := connect.NewUnaryHandler(
SignalerServiceCreateSampleProcedure,
svc.CreateSample,
opts...,
)
signalerServiceListSamplesHandler := connect.NewUnaryHandler(
SignalerServiceListSamplesProcedure,
svc.ListSamples,
opts...,
)
return "/signaler.SignalerService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return "/signaler.SignalerService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path { switch r.URL.Path {
case SignalerServiceCreateAuthTokenProcedure: case SignalerServiceCreateAuthTokenProcedure:
@@ -228,6 +278,10 @@ func NewSignalerServiceHandler(svc SignalerServiceHandler, opts ...connect.Handl
signalerServiceCreateIceMessageHandler.ServeHTTP(w, r) signalerServiceCreateIceMessageHandler.ServeHTTP(w, r)
case SignalerServicePopIceMessageProcedure: case SignalerServicePopIceMessageProcedure:
signalerServicePopIceMessageHandler.ServeHTTP(w, r) signalerServicePopIceMessageHandler.ServeHTTP(w, r)
case SignalerServiceCreateSampleProcedure:
signalerServiceCreateSampleHandler.ServeHTTP(w, r)
case SignalerServiceListSamplesProcedure:
signalerServiceListSamplesHandler.ServeHTTP(w, r)
default: default:
http.NotFound(w, r) http.NotFound(w, r)
} }
@@ -260,3 +314,11 @@ func (UnimplementedSignalerServiceHandler) CreateIceMessage(context.Context, *co
func (UnimplementedSignalerServiceHandler) PopIceMessage(context.Context, *connect.Request[gen.PopIceMessageRequest]) (*connect.Response[gen.IceMessage], error) { func (UnimplementedSignalerServiceHandler) PopIceMessage(context.Context, *connect.Request[gen.PopIceMessageRequest]) (*connect.Response[gen.IceMessage], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("signaler.SignalerService.PopIceMessage is not implemented")) return nil, connect.NewError(connect.CodeUnimplemented, errors.New("signaler.SignalerService.PopIceMessage is not implemented"))
} }
func (UnimplementedSignalerServiceHandler) CreateSample(context.Context, *connect.Request[gen.CreateSampleRequest]) (*connect.Response[gen.Sample], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("signaler.SignalerService.CreateSample is not implemented"))
}
func (UnimplementedSignalerServiceHandler) ListSamples(context.Context, *connect.Request[gen.ListSamplesRequest]) (*connect.Response[gen.ListSamplesResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("signaler.SignalerService.ListSamples is not implemented"))
}
+531 -189
View File
File diff suppressed because it is too large Load Diff
+144
View File
@@ -0,0 +1,144 @@
package sensors
import (
"bufio"
"context"
"os/exec"
"strconv"
"strings"
"sync"
"time"
pb "github.com/chathaway-codes/home-sensors/v2/gen"
"github.com/chathaway-codes/home-sensors/v2/internal/pipespy"
"github.com/chathaway-codes/home-sensors/v2/internal/watcher/config"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
)
var Default = &Mod{}
type Sensors struct {
mu sync.Mutex
ctx context.Context
readCmd *exec.Cmd
cancelFunc func()
ticker time.Ticker
listeners map[string]chan<- *pb.Sample
}
func New(cfg *config.Config) (*Sensors, error) {
ctx, cancelFunc := context.WithCancel(context.Background())
readCmd := exec.CommandContext(ctx, cfg.SensorCmd.Binary, cfg.SensorCmd.Arguments...)
ticker := time.NewTicker(time.Duration(cfg.SensorRateMS) * time.Millisecond)
return &Sensors{
ctx: ctx,
cancelFunc: cancelFunc,
readCmd: readCmd,
ticker: *ticker,
// it would be better if sensors.Run handled sending to the server; to do that,
// it needs a connection and the auth token. I don't have a clean way of getting that
// right now.
listeners: make(map[string]chan<- *pb.Sample),
}, nil
}
func (v *Sensors) Run() {
pipe := pipespy.New()
snoop := pipe.Add(pipespy.NewCmd(v.readCmd)).Snoop()
defer snoop.Close()
cleanUp := pipe.Start()
defer func() {
errs := cleanUp()
for _, err := range errs {
log.Err(err).Send()
}
}()
scanner := bufio.NewScanner(snoop)
for scanner.Scan() {
line := scanner.Text()
parts := strings.Split(line, " ")
if len(parts) != 3 {
log.Error().Str("line", line).Msg("malformed line; expected 3 floats: humidity pressure temperature_c")
}
humidity, err := strconv.ParseFloat(parts[0], 64)
if err != nil {
log.Error().Err(err).Str("val", parts[0]).Msg("failed to parse humidity")
}
pressure, err := strconv.ParseFloat(parts[1], 64)
if err != nil {
log.Error().Err(err).Str("val", parts[1]).Msg("failed to parse pressure")
}
temperatureC, err := strconv.ParseFloat(parts[2], 64)
if err != nil {
log.Error().Err(err).Str("val", parts[2]).Msg("failed to parse temperature_c")
}
select {
case <-v.ticker.C:
func() {
v.mu.Lock()
defer v.mu.Unlock()
samples := []*pb.Sample{
{
Type: pb.Sample_HUMIDITY,
Reading: humidity,
},
{
Type: pb.Sample_PRESSURE,
Reading: pressure,
},
{
Type: pb.Sample_TEMPERATURE_C,
Reading: temperatureC,
},
}
for _, listener := range v.listeners {
for _, sample := range samples {
listener <- sample
}
}
}()
default:
// do nothing
}
}
}
// Join will connect to a running stream.
func (v *Sensors) Join() (<-chan *pb.Sample, func()) {
v.mu.Lock()
defer v.mu.Unlock()
myID := uuid.New().String()
ch := make(chan *pb.Sample)
v.listeners[myID] = ch
return ch, func() {
v.mu.Lock()
defer v.mu.Unlock()
delete(v.listeners, myID)
}
}
// Done stops the processing.
func (v *Sensors) Done() {
v.cancelFunc()
}
type Mod struct{}
func (m *Mod) Get() (*Sensors, error) {
cfg, err := config.Default.Get()
if err != nil {
return nil, err
}
return New(cfg)
}
+2
View File
@@ -19,6 +19,8 @@ type Cmd struct {
type Config struct { type Config struct {
H264Cmd *Cmd `yaml:"h264"` H264Cmd *Cmd `yaml:"h264"`
IVFCmd *Cmd `yaml:"ivf"` IVFCmd *Cmd `yaml:"ivf"`
SensorCmd *Cmd `yaml:"sensor"`
SensorRateMS int64 `yaml:"sensor_rate_ms"`
} }
func New(source []byte) (*Config, error) { func New(source []byte) (*Config, error) {
+65
View File
@@ -37,6 +37,9 @@ type Server struct {
sessionsByCamera map[string]chan *session sessionsByCamera map[string]chan *session
sessionsById map[string]*session sessionsById map[string]*session
// Most recent sample
samplesByCamera map[string]map[pb.Sample_Type]*pb.Sample
} }
func New() *Server { func New() *Server {
@@ -44,6 +47,7 @@ func New() *Server {
camerasByHome: make(map[string]map[string]*camera), camerasByHome: make(map[string]map[string]*camera),
sessionsByCamera: make(map[string]chan *session), sessionsByCamera: make(map[string]chan *session),
sessionsById: make(map[string]*session), sessionsById: make(map[string]*session),
samplesByCamera: make(map[string]map[pb.Sample_Type]*pb.Sample),
} }
go s.cleanup() go s.cleanup()
return s return s
@@ -160,9 +164,11 @@ func (s *Server) PopSession(ctx context.Context, request *connect.Request[pb.Pop
s.mu.Lock() s.mu.Lock()
if _, ok := s.camerasByHome[authToken.Home]; !ok { if _, ok := s.camerasByHome[authToken.Home]; !ok {
s.mu.Unlock()
return nil, status.Errorf(codes.NotFound, "home %q not found", authToken.Home) return nil, status.Errorf(codes.NotFound, "home %q not found", authToken.Home)
} }
if _, ok := s.camerasByHome[authToken.Home][authToken.Uid]; !ok { if _, ok := s.camerasByHome[authToken.Home][authToken.Uid]; !ok {
s.mu.Unlock()
return nil, status.Errorf(codes.Unauthenticated, "you are not a camera") return nil, status.Errorf(codes.Unauthenticated, "you are not a camera")
} }
@@ -238,6 +244,65 @@ func (s *Server) PopIceMessage(ctx context.Context, request *connect.Request[pb.
return connect.NewResponse(msg), nil return connect.NewResponse(msg), nil
} }
func (s *Server) CreateSample(ctx context.Context, request *connect.Request[pb.CreateSampleRequest]) (*connect.Response[pb.Sample], error) {
authToken, err := getAuthToken(request)
if err != nil {
return nil, err
}
s.mu.Lock()
defer s.mu.Unlock()
if _, ok := s.camerasByHome[authToken.Home]; !ok {
return nil, status.Errorf(codes.NotFound, "home %q not found", authToken.Home)
}
cam, ok := s.camerasByHome[authToken.Home][authToken.Uid]
if !ok {
return nil, status.Errorf(codes.Unauthenticated, "you are not a camera")
}
if _, ok := s.samplesByCamera[authToken.Uid]; !ok {
s.samplesByCamera[authToken.Uid] = make(map[pb.Sample_Type]*pb.Sample)
}
sample := request.Msg.GetSample()
s.samplesByCamera[authToken.Uid][sample.Type] = &pb.Sample{
Type: sample.Type,
Reading: sample.Reading,
CameraId: &pb.Camera_Identifier{
Id: cam.id,
},
}
return connect.NewResponse(s.samplesByCamera[authToken.Uid][sample.Type]), nil
}
func (s *Server) ListSamples(ctx context.Context, request *connect.Request[pb.ListSamplesRequest]) (*connect.Response[pb.ListSamplesResponse], error) {
authToken, err := getAuthToken(request)
if err != nil {
return nil, err
}
s.mu.Lock()
defer s.mu.Unlock()
if _, ok := s.camerasByHome[authToken.Home]; !ok {
return nil, status.Errorf(codes.NotFound, "home %q not found", authToken.Home)
}
var samples []*pb.Sample
for camera := range s.camerasByHome[authToken.Home] {
if sample, ok := s.samplesByCamera[camera]; ok {
for _, sample := range sample {
samples = append(samples, sample)
}
}
}
return connect.NewResponse(&pb.ListSamplesResponse{
Samples: samples,
}), nil
}
func (s *Server) cleanup() { func (s *Server) cleanup() {
ticker := time.NewTicker(time.Minute * 5) ticker := time.NewTicker(time.Minute * 5)
for t := range ticker.C { for t := range ticker.C {
+31
View File
@@ -23,6 +23,12 @@ service SignalerService {
// If there are no messages, this blocks until one becomes available. // If there are no messages, this blocks until one becomes available.
rpc PopIceMessage(PopIceMessageRequest) returns (IceMessage); rpc PopIceMessage(PopIceMessageRequest) returns (IceMessage);
// CreateSample creates a sample for the given camera.
// If called without an auth token indicating a camera, an error
// is returned.
// TODO: this should be moved to a seperate service
rpc CreateSample(CreateSampleRequest) returns (Sample);
rpc ListSamples(ListSamplesRequest) returns (ListSamplesResponse);
} }
message CreateAuthTokenRequest{ message CreateAuthTokenRequest{
@@ -85,6 +91,17 @@ message PopIceMessageRequest {
Session.Identifier session_identifier = 1; Session.Identifier session_identifier = 1;
} }
message CreateSampleRequest{
Sample sample = 1;
}
message ListSamplesRequest {
}
message ListSamplesResponse {
repeated Sample samples = 1;
}
message Camera { message Camera {
message Identifier { message Identifier {
string id = 1; string id = 1;
@@ -127,3 +144,17 @@ message Session {
message AuthToken { message AuthToken {
string token = 1; string token = 1;
} }
message Sample{
enum Type {
UNSPECIFIED = 0;
TEMPERATURE_C = 1;
HUMIDITY = 2;
PRESSURE = 3;
}
Type type = 1;
double reading = 2;
// Read-only; will be ignored in CreateSample.
Camera.Identifier camera_id = 3;
}
+32
View File
@@ -0,0 +1,32 @@
h264:
binary: "/usr/bin/libcamera-vid"
arguments:
- "-n"
- "-t"
- "0"
- "--codec"
- "h264"
- "--mode"
- "1640:1232"
- "--denoise"
- "off"
- "--inline"
- "-o"
- "-"
ivf:
binary: "/usr/bin/ffmpeg"
arguments:
- "-i"
- "-"
- "-g"
- "30"
- "-b:v"
- "2M"
- "-f"
- "ivf"
- "-"
sensor:
binary: "/usr/bin/python3"
arguments:
- "/home/charles/temperature.py"
sensor_rate_ms: 10000
+6
View File
@@ -14,3 +14,9 @@ ivf:
- "-f" - "-f"
- "ivf" - "ivf"
- "-" - "-"
sensor:
binary: "/usr/bin/yes"
arguments:
- "44.33889713096721 1015.1977693083448 23.60542243081727"
sensor_rate_ms: 10000
+212
View File
@@ -14,6 +14,10 @@ import 'dart:core' as $core;
import 'package:fixnum/fixnum.dart' as $fixnum; import 'package:fixnum/fixnum.dart' as $fixnum;
import 'package:protobuf/protobuf.dart' as $pb; import 'package:protobuf/protobuf.dart' as $pb;
import 'signaler_service.pbenum.dart';
export 'signaler_service.pbenum.dart';
class CreateAuthTokenRequest_Camera extends $pb.GeneratedMessage { class CreateAuthTokenRequest_Camera extends $pb.GeneratedMessage {
factory CreateAuthTokenRequest_Camera({ factory CreateAuthTokenRequest_Camera({
$core.String? id, $core.String? id,
@@ -658,6 +662,134 @@ class PopIceMessageRequest extends $pb.GeneratedMessage {
Session_Identifier ensureSessionIdentifier() => $_ensure(0); Session_Identifier ensureSessionIdentifier() => $_ensure(0);
} }
class CreateSampleRequest extends $pb.GeneratedMessage {
factory CreateSampleRequest({
Sample? sample,
}) {
final $result = create();
if (sample != null) {
$result.sample = sample;
}
return $result;
}
CreateSampleRequest._() : super();
factory CreateSampleRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory CreateSampleRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CreateSampleRequest', package: const $pb.PackageName(_omitMessageNames ? '' : 'signaler'), createEmptyInstance: create)
..aOM<Sample>(1, _omitFieldNames ? '' : 'sample', subBuilder: Sample.create)
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
CreateSampleRequest clone() => CreateSampleRequest()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
CreateSampleRequest copyWith(void Function(CreateSampleRequest) updates) => super.copyWith((message) => updates(message as CreateSampleRequest)) as CreateSampleRequest;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static CreateSampleRequest create() => CreateSampleRequest._();
CreateSampleRequest createEmptyInstance() => create();
static $pb.PbList<CreateSampleRequest> createRepeated() => $pb.PbList<CreateSampleRequest>();
@$core.pragma('dart2js:noInline')
static CreateSampleRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CreateSampleRequest>(create);
static CreateSampleRequest? _defaultInstance;
@$pb.TagNumber(1)
Sample get sample => $_getN(0);
@$pb.TagNumber(1)
set sample(Sample v) { setField(1, v); }
@$pb.TagNumber(1)
$core.bool hasSample() => $_has(0);
@$pb.TagNumber(1)
void clearSample() => clearField(1);
@$pb.TagNumber(1)
Sample ensureSample() => $_ensure(0);
}
class ListSamplesRequest extends $pb.GeneratedMessage {
factory ListSamplesRequest() => create();
ListSamplesRequest._() : super();
factory ListSamplesRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory ListSamplesRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ListSamplesRequest', package: const $pb.PackageName(_omitMessageNames ? '' : 'signaler'), createEmptyInstance: create)
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
ListSamplesRequest clone() => ListSamplesRequest()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
ListSamplesRequest copyWith(void Function(ListSamplesRequest) updates) => super.copyWith((message) => updates(message as ListSamplesRequest)) as ListSamplesRequest;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ListSamplesRequest create() => ListSamplesRequest._();
ListSamplesRequest createEmptyInstance() => create();
static $pb.PbList<ListSamplesRequest> createRepeated() => $pb.PbList<ListSamplesRequest>();
@$core.pragma('dart2js:noInline')
static ListSamplesRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ListSamplesRequest>(create);
static ListSamplesRequest? _defaultInstance;
}
class ListSamplesResponse extends $pb.GeneratedMessage {
factory ListSamplesResponse({
$core.Iterable<Sample>? samples,
}) {
final $result = create();
if (samples != null) {
$result.samples.addAll(samples);
}
return $result;
}
ListSamplesResponse._() : super();
factory ListSamplesResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory ListSamplesResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ListSamplesResponse', package: const $pb.PackageName(_omitMessageNames ? '' : 'signaler'), createEmptyInstance: create)
..pc<Sample>(1, _omitFieldNames ? '' : 'samples', $pb.PbFieldType.PM, subBuilder: Sample.create)
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
ListSamplesResponse clone() => ListSamplesResponse()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
ListSamplesResponse copyWith(void Function(ListSamplesResponse) updates) => super.copyWith((message) => updates(message as ListSamplesResponse)) as ListSamplesResponse;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ListSamplesResponse create() => ListSamplesResponse._();
ListSamplesResponse createEmptyInstance() => create();
static $pb.PbList<ListSamplesResponse> createRepeated() => $pb.PbList<ListSamplesResponse>();
@$core.pragma('dart2js:noInline')
static ListSamplesResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ListSamplesResponse>(create);
static ListSamplesResponse? _defaultInstance;
@$pb.TagNumber(1)
$core.List<Sample> get samples => $_getList(0);
}
class Camera_Identifier extends $pb.GeneratedMessage { class Camera_Identifier extends $pb.GeneratedMessage {
factory Camera_Identifier({ factory Camera_Identifier({
$core.String? id, $core.String? id,
@@ -1219,6 +1351,86 @@ class AuthToken extends $pb.GeneratedMessage {
void clearToken() => clearField(1); void clearToken() => clearField(1);
} }
class Sample extends $pb.GeneratedMessage {
factory Sample({
Sample_Type? type,
$core.double? reading,
Camera_Identifier? cameraId,
}) {
final $result = create();
if (type != null) {
$result.type = type;
}
if (reading != null) {
$result.reading = reading;
}
if (cameraId != null) {
$result.cameraId = cameraId;
}
return $result;
}
Sample._() : super();
factory Sample.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory Sample.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Sample', package: const $pb.PackageName(_omitMessageNames ? '' : 'signaler'), createEmptyInstance: create)
..e<Sample_Type>(1, _omitFieldNames ? '' : 'type', $pb.PbFieldType.OE, defaultOrMaker: Sample_Type.UNSPECIFIED, valueOf: Sample_Type.valueOf, enumValues: Sample_Type.values)
..a<$core.double>(2, _omitFieldNames ? '' : 'reading', $pb.PbFieldType.OD)
..aOM<Camera_Identifier>(3, _omitFieldNames ? '' : 'cameraId', subBuilder: Camera_Identifier.create)
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
Sample clone() => Sample()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
Sample copyWith(void Function(Sample) updates) => super.copyWith((message) => updates(message as Sample)) as Sample;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Sample create() => Sample._();
Sample createEmptyInstance() => create();
static $pb.PbList<Sample> createRepeated() => $pb.PbList<Sample>();
@$core.pragma('dart2js:noInline')
static Sample getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Sample>(create);
static Sample? _defaultInstance;
@$pb.TagNumber(1)
Sample_Type get type => $_getN(0);
@$pb.TagNumber(1)
set type(Sample_Type v) { setField(1, v); }
@$pb.TagNumber(1)
$core.bool hasType() => $_has(0);
@$pb.TagNumber(1)
void clearType() => clearField(1);
@$pb.TagNumber(2)
$core.double get reading => $_getN(1);
@$pb.TagNumber(2)
set reading($core.double v) { $_setDouble(1, v); }
@$pb.TagNumber(2)
$core.bool hasReading() => $_has(1);
@$pb.TagNumber(2)
void clearReading() => clearField(2);
@$pb.TagNumber(3)
Camera_Identifier get cameraId => $_getN(2);
@$pb.TagNumber(3)
set cameraId(Camera_Identifier v) { setField(3, v); }
@$pb.TagNumber(3)
$core.bool hasCameraId() => $_has(2);
@$pb.TagNumber(3)
void clearCameraId() => clearField(3);
@$pb.TagNumber(3)
Camera_Identifier ensureCameraId() => $_ensure(2);
}
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
+25
View File
@@ -9,3 +9,28 @@
// ignore_for_file: non_constant_identifier_names, prefer_final_fields // ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import // ignore_for_file: unnecessary_import, unnecessary_this, unused_import
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class Sample_Type extends $pb.ProtobufEnum {
static const Sample_Type UNSPECIFIED = Sample_Type._(0, _omitEnumNames ? '' : 'UNSPECIFIED');
static const Sample_Type TEMPERATURE_C = Sample_Type._(1, _omitEnumNames ? '' : 'TEMPERATURE_C');
static const Sample_Type HUMIDITY = Sample_Type._(2, _omitEnumNames ? '' : 'HUMIDITY');
static const Sample_Type PRESSURE = Sample_Type._(3, _omitEnumNames ? '' : 'PRESSURE');
static const $core.List<Sample_Type> values = <Sample_Type> [
UNSPECIFIED,
TEMPERATURE_C,
HUMIDITY,
PRESSURE,
];
static final $core.Map<$core.int, Sample_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static Sample_Type? valueOf($core.int value) => _byValue[value];
const Sample_Type._($core.int v, $core.String n) : super(v, n);
}
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');
+40
View File
@@ -45,6 +45,14 @@ class SignalerServiceClient extends $grpc.Client {
'/signaler.SignalerService/PopIceMessage', '/signaler.SignalerService/PopIceMessage',
($0.PopIceMessageRequest value) => value.writeToBuffer(), ($0.PopIceMessageRequest value) => value.writeToBuffer(),
($core.List<$core.int> value) => $0.IceMessage.fromBuffer(value)); ($core.List<$core.int> value) => $0.IceMessage.fromBuffer(value));
static final _$createSample = $grpc.ClientMethod<$0.CreateSampleRequest, $0.Sample>(
'/signaler.SignalerService/CreateSample',
($0.CreateSampleRequest value) => value.writeToBuffer(),
($core.List<$core.int> value) => $0.Sample.fromBuffer(value));
static final _$listSamples = $grpc.ClientMethod<$0.ListSamplesRequest, $0.ListSamplesResponse>(
'/signaler.SignalerService/ListSamples',
($0.ListSamplesRequest value) => value.writeToBuffer(),
($core.List<$core.int> value) => $0.ListSamplesResponse.fromBuffer(value));
SignalerServiceClient($grpc.ClientChannel channel, SignalerServiceClient($grpc.ClientChannel channel,
{$grpc.CallOptions? options, {$grpc.CallOptions? options,
@@ -75,6 +83,14 @@ class SignalerServiceClient extends $grpc.Client {
$grpc.ResponseFuture<$0.IceMessage> popIceMessage($0.PopIceMessageRequest request, {$grpc.CallOptions? options}) { $grpc.ResponseFuture<$0.IceMessage> popIceMessage($0.PopIceMessageRequest request, {$grpc.CallOptions? options}) {
return $createUnaryCall(_$popIceMessage, request, options: options); return $createUnaryCall(_$popIceMessage, request, options: options);
} }
$grpc.ResponseFuture<$0.Sample> createSample($0.CreateSampleRequest request, {$grpc.CallOptions? options}) {
return $createUnaryCall(_$createSample, request, options: options);
}
$grpc.ResponseFuture<$0.ListSamplesResponse> listSamples($0.ListSamplesRequest request, {$grpc.CallOptions? options}) {
return $createUnaryCall(_$listSamples, request, options: options);
}
} }
@$pb.GrpcServiceName('signaler.SignalerService') @$pb.GrpcServiceName('signaler.SignalerService')
@@ -124,6 +140,20 @@ abstract class SignalerServiceBase extends $grpc.Service {
false, false,
($core.List<$core.int> value) => $0.PopIceMessageRequest.fromBuffer(value), ($core.List<$core.int> value) => $0.PopIceMessageRequest.fromBuffer(value),
($0.IceMessage value) => value.writeToBuffer())); ($0.IceMessage value) => value.writeToBuffer()));
$addMethod($grpc.ServiceMethod<$0.CreateSampleRequest, $0.Sample>(
'CreateSample',
createSample_Pre,
false,
false,
($core.List<$core.int> value) => $0.CreateSampleRequest.fromBuffer(value),
($0.Sample value) => value.writeToBuffer()));
$addMethod($grpc.ServiceMethod<$0.ListSamplesRequest, $0.ListSamplesResponse>(
'ListSamples',
listSamples_Pre,
false,
false,
($core.List<$core.int> value) => $0.ListSamplesRequest.fromBuffer(value),
($0.ListSamplesResponse value) => value.writeToBuffer()));
} }
$async.Future<$0.AuthToken> createAuthToken_Pre($grpc.ServiceCall call, $async.Future<$0.CreateAuthTokenRequest> request) async { $async.Future<$0.AuthToken> createAuthToken_Pre($grpc.ServiceCall call, $async.Future<$0.CreateAuthTokenRequest> request) async {
@@ -150,10 +180,20 @@ abstract class SignalerServiceBase extends $grpc.Service {
return popIceMessage(call, await request); return popIceMessage(call, await request);
} }
$async.Future<$0.Sample> createSample_Pre($grpc.ServiceCall call, $async.Future<$0.CreateSampleRequest> request) async {
return createSample(call, await request);
}
$async.Future<$0.ListSamplesResponse> listSamples_Pre($grpc.ServiceCall call, $async.Future<$0.ListSamplesRequest> request) async {
return listSamples(call, await request);
}
$async.Future<$0.AuthToken> createAuthToken($grpc.ServiceCall call, $0.CreateAuthTokenRequest request); $async.Future<$0.AuthToken> createAuthToken($grpc.ServiceCall call, $0.CreateAuthTokenRequest request);
$async.Future<$0.ListCamerasResponse> listCameras($grpc.ServiceCall call, $0.ListCamerasRequest request); $async.Future<$0.ListCamerasResponse> listCameras($grpc.ServiceCall call, $0.ListCamerasRequest request);
$async.Future<$0.Session> createSession($grpc.ServiceCall call, $0.CreateSessionRequest request); $async.Future<$0.Session> createSession($grpc.ServiceCall call, $0.CreateSessionRequest request);
$async.Future<$0.Session> popSession($grpc.ServiceCall call, $0.PopSessionRequest request); $async.Future<$0.Session> popSession($grpc.ServiceCall call, $0.PopSessionRequest request);
$async.Future<$0.IceMessage> createIceMessage($grpc.ServiceCall call, $0.CreateIceMessageRequest request); $async.Future<$0.IceMessage> createIceMessage($grpc.ServiceCall call, $0.CreateIceMessageRequest request);
$async.Future<$0.IceMessage> popIceMessage($grpc.ServiceCall call, $0.PopIceMessageRequest request); $async.Future<$0.IceMessage> popIceMessage($grpc.ServiceCall call, $0.PopIceMessageRequest request);
$async.Future<$0.Sample> createSample($grpc.ServiceCall call, $0.CreateSampleRequest request);
$async.Future<$0.ListSamplesResponse> listSamples($grpc.ServiceCall call, $0.ListSamplesRequest request);
} }
+64
View File
@@ -160,6 +160,41 @@ final $typed_data.Uint8List popIceMessageRequestDescriptor = $convert.base64Deco
'ChRQb3BJY2VNZXNzYWdlUmVxdWVzdBJLChJzZXNzaW9uX2lkZW50aWZpZXIYASABKAsyHC5zaW' 'ChRQb3BJY2VNZXNzYWdlUmVxdWVzdBJLChJzZXNzaW9uX2lkZW50aWZpZXIYASABKAsyHC5zaW'
'duYWxlci5TZXNzaW9uLklkZW50aWZpZXJSEXNlc3Npb25JZGVudGlmaWVy'); 'duYWxlci5TZXNzaW9uLklkZW50aWZpZXJSEXNlc3Npb25JZGVudGlmaWVy');
@$core.Deprecated('Use createSampleRequestDescriptor instead')
const CreateSampleRequest$json = {
'1': 'CreateSampleRequest',
'2': [
{'1': 'sample', '3': 1, '4': 1, '5': 11, '6': '.signaler.Sample', '10': 'sample'},
],
};
/// Descriptor for `CreateSampleRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List createSampleRequestDescriptor = $convert.base64Decode(
'ChNDcmVhdGVTYW1wbGVSZXF1ZXN0EigKBnNhbXBsZRgBIAEoCzIQLnNpZ25hbGVyLlNhbXBsZV'
'IGc2FtcGxl');
@$core.Deprecated('Use listSamplesRequestDescriptor instead')
const ListSamplesRequest$json = {
'1': 'ListSamplesRequest',
};
/// Descriptor for `ListSamplesRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List listSamplesRequestDescriptor = $convert.base64Decode(
'ChJMaXN0U2FtcGxlc1JlcXVlc3Q=');
@$core.Deprecated('Use listSamplesResponseDescriptor instead')
const ListSamplesResponse$json = {
'1': 'ListSamplesResponse',
'2': [
{'1': 'samples', '3': 1, '4': 3, '5': 11, '6': '.signaler.Sample', '10': 'samples'},
],
};
/// Descriptor for `ListSamplesResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List listSamplesResponseDescriptor = $convert.base64Decode(
'ChNMaXN0U2FtcGxlc1Jlc3BvbnNlEioKB3NhbXBsZXMYASADKAsyEC5zaWduYWxlci5TYW1wbG'
'VSB3NhbXBsZXM=');
@$core.Deprecated('Use cameraDescriptor instead') @$core.Deprecated('Use cameraDescriptor instead')
const Camera$json = { const Camera$json = {
'1': 'Camera', '1': 'Camera',
@@ -284,3 +319,32 @@ const AuthToken$json = {
final $typed_data.Uint8List authTokenDescriptor = $convert.base64Decode( final $typed_data.Uint8List authTokenDescriptor = $convert.base64Decode(
'CglBdXRoVG9rZW4SFAoFdG9rZW4YASABKAlSBXRva2Vu'); 'CglBdXRoVG9rZW4SFAoFdG9rZW4YASABKAlSBXRva2Vu');
@$core.Deprecated('Use sampleDescriptor instead')
const Sample$json = {
'1': 'Sample',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.signaler.Sample.Type', '10': 'type'},
{'1': 'reading', '3': 2, '4': 1, '5': 1, '10': 'reading'},
{'1': 'camera_id', '3': 3, '4': 1, '5': 11, '6': '.signaler.Camera.Identifier', '10': 'cameraId'},
],
'4': [Sample_Type$json],
};
@$core.Deprecated('Use sampleDescriptor instead')
const Sample_Type$json = {
'1': 'Type',
'2': [
{'1': 'UNSPECIFIED', '2': 0},
{'1': 'TEMPERATURE_C', '2': 1},
{'1': 'HUMIDITY', '2': 2},
{'1': 'PRESSURE', '2': 3},
],
};
/// Descriptor for `Sample`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List sampleDescriptor = $convert.base64Decode(
'CgZTYW1wbGUSKQoEdHlwZRgBIAEoDjIVLnNpZ25hbGVyLlNhbXBsZS5UeXBlUgR0eXBlEhgKB3'
'JlYWRpbmcYAiABKAFSB3JlYWRpbmcSOAoJY2FtZXJhX2lkGAMgASgLMhsuc2lnbmFsZXIuQ2Ft'
'ZXJhLklkZW50aWZpZXJSCGNhbWVyYUlkIkYKBFR5cGUSDwoLVU5TUEVDSUZJRUQQABIRCg1URU'
'1QRVJBVFVSRV9DEAESDAoISFVNSURJVFkQAhIMCghQUkVTU1VSRRAD');