refactor: migrate lib/grpcentity to lib/grpc/basic and update path references
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
# lib/grpc/basic 실습 설명서
|
||||
|
||||
본 디렉토리는 Go 언어를 활용한 gRPC 서버 및 클라이언트 실습 예제를 포함하고 있습니다.
|
||||
|
||||
## 📖 실습 상세 분석 및 가이드 안내
|
||||
|
||||
학습의 일관성을 위해, 이 실습의 상세 분석 및 개념 명세는 통합 교재의 gRPC 심화 가이드인 **[docs/GRPC.md](../../../docs/GRPC.md)**로 모듈화되어 있습니다. 전체 학습 로드맵은 [docs/MANUSCRIPT.md](../../../docs/MANUSCRIPT.md)를 참고하십시오.
|
||||
|
||||
[docs/GRPC.md](../../../docs/GRPC.md) 문서에서 다음 내용을 참고하실 수 있습니다:
|
||||
* **IDL ([protoapi.proto](./protoapi.proto)) 명세 및 필드 분석**
|
||||
* **Go에서의 `protoc` 설치 및 Stub 파일 컴파일 방법**
|
||||
* **gRPC 서버 코드 ([server.go](./server.go)) 구현 상세 분석**
|
||||
* **gRPC 클라이언트 코드 ([client.go](./client.go)) 커넥션 및 호출 흐름 분석**
|
||||
|
||||
---
|
||||
|
||||
## 🚀 빠른 실행 방법
|
||||
|
||||
이 예제는 리포지토리 루트의 `lib/main.go`를 통해 실행됩니다.
|
||||
|
||||
1. 리포지토리 루트의 `lib/main.go`를 엽니다.
|
||||
2. `main()` 함수 내에서 `grpcSample()`의 주석을 해제합니다.
|
||||
3. 리포지토리 루트에서 다음 명령어를 실행합니다:
|
||||
```bash
|
||||
go run ./lib
|
||||
```
|
||||
@@ -0,0 +1,220 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"grpccanary/lib/grpc/basic/protoapi"
|
||||
"io"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
)
|
||||
|
||||
func AskingDateTime(ctx context.Context, m protoapi.IoTServiceClient) (*protoapi.DateTime, error) {
|
||||
request := &protoapi.RequestDateTime{
|
||||
Value: "Please send me the date and time",
|
||||
}
|
||||
|
||||
return m.GetDate(ctx, request)
|
||||
}
|
||||
|
||||
func AskPass(ctx context.Context, m protoapi.IoTServiceClient, seed int64, length int64) (*protoapi.RandomPass, error) {
|
||||
request := &protoapi.RequestPass{
|
||||
Seed: seed,
|
||||
Length: length,
|
||||
}
|
||||
|
||||
return m.GetRandomPass(ctx, request)
|
||||
}
|
||||
|
||||
func AskUpdateSensingData(ctx context.Context, m protoapi.IoTServiceClient, deviceId string, temp float64, humid float64) (*protoapi.SensingResponse, error) {
|
||||
request := &protoapi.SensingData{
|
||||
DeviceId: deviceId,
|
||||
Temperature: temp,
|
||||
Humidity: humid,
|
||||
}
|
||||
|
||||
return m.UpdateSensingData(ctx, request)
|
||||
}
|
||||
|
||||
func AskUploadFile(ctx context.Context, m protoapi.IoTServiceClient, fileName string, fileData []byte) (*protoapi.UploadStatus, error) {
|
||||
stream, err := m.UploadFile(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chunkSize := 1024 // 1KB 단위 청크
|
||||
totalBytes := len(fileData)
|
||||
|
||||
for i := 0; i < totalBytes; i += chunkSize {
|
||||
end := i + chunkSize
|
||||
if end > totalBytes {
|
||||
end = totalBytes
|
||||
}
|
||||
|
||||
err := stream.Send(&protoapi.FileChunk{
|
||||
FileName: fileName,
|
||||
Content: fileData[i:end],
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return stream.CloseAndRecv()
|
||||
}
|
||||
|
||||
func AskListFiles(ctx context.Context, m protoapi.IoTServiceClient) (*protoapi.FileList, error) {
|
||||
return m.ListFiles(ctx, &protoapi.EmptyRequest{})
|
||||
}
|
||||
|
||||
func AskDownloadFile(ctx context.Context, m protoapi.IoTServiceClient, fileName string) ([]byte, error) {
|
||||
stream, err := m.DownloadFile(ctx, &protoapi.DownloadRequest{FileName: fileName})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var buffer []byte
|
||||
for {
|
||||
chunk, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffer = append(buffer, chunk.GetContent()...)
|
||||
}
|
||||
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
func AskSubscribeAlerts(ctx context.Context, m protoapi.IoTServiceClient, clientId string, topic string) {
|
||||
stream, err := m.SubscribeAlerts(ctx, &protoapi.AlertSubscription{
|
||||
ClientId: clientId,
|
||||
Topic: topic,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("Failed to subscribe alerts:", err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
alert, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
fmt.Println("Alert subscription stream closed by server.")
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
fmt.Printf("\n🔔 [ALERT RECEIVED] ID: %s | Device: %s | Msg: %s | Time: %s\n\n",
|
||||
alert.GetAlertId(), alert.GetDeviceId(), alert.GetMessage(),
|
||||
time.Unix(alert.GetTimestamp(), 0).Format("15:04:05"))
|
||||
}
|
||||
}
|
||||
|
||||
func ClientRun(addr string) {
|
||||
conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
fmt.Println("NewClient error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
client := protoapi.NewIoTServiceClient(conn)
|
||||
|
||||
// 백그라운드에서 실시간 경보 구독 기동
|
||||
alertCtx, alertCancel := context.WithCancel(context.Background())
|
||||
defer alertCancel()
|
||||
go AskSubscribeAlerts(alertCtx, client, "client-app-01", "temperature_warnings")
|
||||
// 구독 리시버 채널 등록을 위해 50ms 슬립
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
r, err := AskingDateTime(context.Background(), client)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Server Date and Time:", r.Value)
|
||||
|
||||
length := int64(rand.Intn(20))
|
||||
p, err := AskPass(context.Background(), client, 100, length+1)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Random Password:", p.Password)
|
||||
|
||||
res, err := AskUpdateSensingData(context.Background(), client, "sensor-room-01", 24.5, 52.3)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Sensing Update Success:", res.Success)
|
||||
fmt.Println("Sensing Update Message:", res.Message)
|
||||
|
||||
// 4단계: 파일 업로드 스트리밍 실행 예제
|
||||
dummyData := make([]byte, 10240) // 10KB 가상 더미 데이터
|
||||
for i := range dummyData {
|
||||
dummyData[i] = byte(rand.Intn(256))
|
||||
}
|
||||
fmt.Println("Uploading dummy file (10KB) via Client Streaming...")
|
||||
status, err := AskUploadFile(context.Background(), client, "firmware.bin", dummyData)
|
||||
if err != nil {
|
||||
fmt.Println("File upload failed:", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Upload Success:", status.Success)
|
||||
fmt.Println("Upload Message:", status.Message)
|
||||
fmt.Printf("Uploaded Bytes: %d bytes\n", status.BytesUploaded)
|
||||
|
||||
// 5단계: 파일 리스트 조회 실행 예제
|
||||
fmt.Println("Querying uploaded files metadata from Server...")
|
||||
list, err := AskListFiles(context.Background(), client)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to list files:", err)
|
||||
return
|
||||
}
|
||||
for i, f := range list.GetFiles() {
|
||||
fmt.Printf("[%d] Name: %s, Size: %d bytes, UploadedAt: %s\n",
|
||||
i+1, f.GetFileName(), f.GetFileSize(), time.Unix(f.GetUploadedAt(), 0).Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
|
||||
// 6단계: 파일 다운로드 스트리밍 실행 예제
|
||||
fmt.Println("Downloading file 'firmware.bin' via Server Streaming...")
|
||||
downloadedData, err := AskDownloadFile(context.Background(), client, "firmware.bin")
|
||||
if err != nil {
|
||||
fmt.Println("Failed to download file:", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Download completed. Received %d bytes.\n", len(downloadedData))
|
||||
|
||||
// 데이터 정합성(Integrity) 검증
|
||||
isMatch := true
|
||||
if len(dummyData) != len(downloadedData) {
|
||||
isMatch = false
|
||||
} else {
|
||||
for i := range dummyData {
|
||||
if dummyData[i] != downloadedData[i] {
|
||||
isMatch = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Printf("Data Integrity Checked (Upload vs Download matches?): %t\n", isMatch)
|
||||
|
||||
// 7단계: 임계값 초과 온습도 전송을 통한 Pub/Sub 실시간 알림 유발 시뮬레이션
|
||||
fmt.Println("Sending abnormal high-temperature sensing data (45.8°C)...")
|
||||
|
||||
alertRes, err := AskUpdateSensingData(context.Background(), client, "sensor-room-01", 45.8, 60.1)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Abnormal Sensing Update Success:", alertRes.Success)
|
||||
// 알림 이벤트가 비동기로 화면에 출력될 시간을 확보하기 위해 100ms 대기
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "./protoapi/;protoapi";
|
||||
|
||||
service IoTService {
|
||||
rpc GetDate (RequestDateTime) returns (DateTime);
|
||||
rpc UpdateSensingData (SensingData) returns (SensingResponse);
|
||||
rpc GetRandomPass (RequestPass) returns (RandomPass);
|
||||
rpc UploadFile (stream FileChunk) returns (UploadStatus);
|
||||
rpc ListFiles (EmptyRequest) returns (FileList);
|
||||
rpc DownloadFile (DownloadRequest) returns (stream FileChunk);
|
||||
rpc SubscribeAlerts (AlertSubscription) returns (stream AlertMessage);
|
||||
}
|
||||
|
||||
message FileChunk {
|
||||
string FileName = 1;
|
||||
bytes Content = 2;
|
||||
}
|
||||
|
||||
message UploadStatus {
|
||||
bool Success = 1;
|
||||
string Message = 2;
|
||||
int64 BytesUploaded = 3;
|
||||
}
|
||||
|
||||
message SensingData {
|
||||
string DeviceId = 1;
|
||||
double Temperature = 2;
|
||||
double Humidity = 3;
|
||||
}
|
||||
|
||||
message SensingResponse {
|
||||
bool Success = 1;
|
||||
string Message = 2;
|
||||
}
|
||||
|
||||
message DateTime {
|
||||
string Value = 1;
|
||||
}
|
||||
|
||||
message RequestDateTime {
|
||||
string Value = 2;
|
||||
}
|
||||
|
||||
message RequestPass {
|
||||
int64 Seed = 1;
|
||||
int64 Length = 8;
|
||||
}
|
||||
|
||||
message RandomPass {
|
||||
string Password = 1;
|
||||
}
|
||||
|
||||
message EmptyRequest {}
|
||||
|
||||
message FileMetadata {
|
||||
string FileName = 1;
|
||||
int64 FileSize = 2;
|
||||
int64 UploadedAt = 3;
|
||||
}
|
||||
|
||||
message FileList {
|
||||
repeated FileMetadata Files = 1;
|
||||
}
|
||||
|
||||
message DownloadRequest {
|
||||
string FileName = 1;
|
||||
}
|
||||
|
||||
message AlertSubscription {
|
||||
string ClientId = 1;
|
||||
string Topic = 2;
|
||||
}
|
||||
|
||||
message AlertMessage {
|
||||
string AlertId = 1;
|
||||
string DeviceId = 2;
|
||||
string Message = 3;
|
||||
int64 Timestamp = 4;
|
||||
}
|
||||
@@ -0,0 +1,871 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.11
|
||||
// protoc v3.21.12
|
||||
// source: protoapi.proto
|
||||
|
||||
package protoapi
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type FileChunk struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
FileName string `protobuf:"bytes,1,opt,name=FileName,proto3" json:"FileName,omitempty"`
|
||||
Content []byte `protobuf:"bytes,2,opt,name=Content,proto3" json:"Content,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *FileChunk) Reset() {
|
||||
*x = FileChunk{}
|
||||
mi := &file_protoapi_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *FileChunk) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FileChunk) ProtoMessage() {}
|
||||
|
||||
func (x *FileChunk) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FileChunk.ProtoReflect.Descriptor instead.
|
||||
func (*FileChunk) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *FileChunk) GetFileName() string {
|
||||
if x != nil {
|
||||
return x.FileName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *FileChunk) GetContent() []byte {
|
||||
if x != nil {
|
||||
return x.Content
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UploadStatus struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Success bool `protobuf:"varint,1,opt,name=Success,proto3" json:"Success,omitempty"`
|
||||
Message string `protobuf:"bytes,2,opt,name=Message,proto3" json:"Message,omitempty"`
|
||||
BytesUploaded int64 `protobuf:"varint,3,opt,name=BytesUploaded,proto3" json:"BytesUploaded,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *UploadStatus) Reset() {
|
||||
*x = UploadStatus{}
|
||||
mi := &file_protoapi_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *UploadStatus) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UploadStatus) ProtoMessage() {}
|
||||
|
||||
func (x *UploadStatus) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UploadStatus.ProtoReflect.Descriptor instead.
|
||||
func (*UploadStatus) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *UploadStatus) GetSuccess() bool {
|
||||
if x != nil {
|
||||
return x.Success
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *UploadStatus) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UploadStatus) GetBytesUploaded() int64 {
|
||||
if x != nil {
|
||||
return x.BytesUploaded
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type SensingData struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
DeviceId string `protobuf:"bytes,1,opt,name=DeviceId,proto3" json:"DeviceId,omitempty"`
|
||||
Temperature float64 `protobuf:"fixed64,2,opt,name=Temperature,proto3" json:"Temperature,omitempty"`
|
||||
Humidity float64 `protobuf:"fixed64,3,opt,name=Humidity,proto3" json:"Humidity,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *SensingData) Reset() {
|
||||
*x = SensingData{}
|
||||
mi := &file_protoapi_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *SensingData) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SensingData) ProtoMessage() {}
|
||||
|
||||
func (x *SensingData) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SensingData.ProtoReflect.Descriptor instead.
|
||||
func (*SensingData) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *SensingData) GetDeviceId() string {
|
||||
if x != nil {
|
||||
return x.DeviceId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *SensingData) GetTemperature() float64 {
|
||||
if x != nil {
|
||||
return x.Temperature
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *SensingData) GetHumidity() float64 {
|
||||
if x != nil {
|
||||
return x.Humidity
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type SensingResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Success bool `protobuf:"varint,1,opt,name=Success,proto3" json:"Success,omitempty"`
|
||||
Message string `protobuf:"bytes,2,opt,name=Message,proto3" json:"Message,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *SensingResponse) Reset() {
|
||||
*x = SensingResponse{}
|
||||
mi := &file_protoapi_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *SensingResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SensingResponse) ProtoMessage() {}
|
||||
|
||||
func (x *SensingResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SensingResponse.ProtoReflect.Descriptor instead.
|
||||
func (*SensingResponse) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *SensingResponse) GetSuccess() bool {
|
||||
if x != nil {
|
||||
return x.Success
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *SensingResponse) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type DateTime struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Value string `protobuf:"bytes,1,opt,name=Value,proto3" json:"Value,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DateTime) Reset() {
|
||||
*x = DateTime{}
|
||||
mi := &file_protoapi_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DateTime) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DateTime) ProtoMessage() {}
|
||||
|
||||
func (x *DateTime) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DateTime.ProtoReflect.Descriptor instead.
|
||||
func (*DateTime) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *DateTime) GetValue() string {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RequestDateTime struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Value string `protobuf:"bytes,2,opt,name=Value,proto3" json:"Value,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RequestDateTime) Reset() {
|
||||
*x = RequestDateTime{}
|
||||
mi := &file_protoapi_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RequestDateTime) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RequestDateTime) ProtoMessage() {}
|
||||
|
||||
func (x *RequestDateTime) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RequestDateTime.ProtoReflect.Descriptor instead.
|
||||
func (*RequestDateTime) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *RequestDateTime) GetValue() string {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RequestPass struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Seed int64 `protobuf:"varint,1,opt,name=Seed,proto3" json:"Seed,omitempty"`
|
||||
Length int64 `protobuf:"varint,8,opt,name=Length,proto3" json:"Length,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RequestPass) Reset() {
|
||||
*x = RequestPass{}
|
||||
mi := &file_protoapi_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RequestPass) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RequestPass) ProtoMessage() {}
|
||||
|
||||
func (x *RequestPass) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RequestPass.ProtoReflect.Descriptor instead.
|
||||
func (*RequestPass) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *RequestPass) GetSeed() int64 {
|
||||
if x != nil {
|
||||
return x.Seed
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RequestPass) GetLength() int64 {
|
||||
if x != nil {
|
||||
return x.Length
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type RandomPass struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Password string `protobuf:"bytes,1,opt,name=Password,proto3" json:"Password,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RandomPass) Reset() {
|
||||
*x = RandomPass{}
|
||||
mi := &file_protoapi_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RandomPass) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RandomPass) ProtoMessage() {}
|
||||
|
||||
func (x *RandomPass) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[7]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RandomPass.ProtoReflect.Descriptor instead.
|
||||
func (*RandomPass) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *RandomPass) GetPassword() string {
|
||||
if x != nil {
|
||||
return x.Password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type EmptyRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *EmptyRequest) Reset() {
|
||||
*x = EmptyRequest{}
|
||||
mi := &file_protoapi_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *EmptyRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*EmptyRequest) ProtoMessage() {}
|
||||
|
||||
func (x *EmptyRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[8]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use EmptyRequest.ProtoReflect.Descriptor instead.
|
||||
func (*EmptyRequest) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
type FileMetadata struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
FileName string `protobuf:"bytes,1,opt,name=FileName,proto3" json:"FileName,omitempty"`
|
||||
FileSize int64 `protobuf:"varint,2,opt,name=FileSize,proto3" json:"FileSize,omitempty"`
|
||||
UploadedAt int64 `protobuf:"varint,3,opt,name=UploadedAt,proto3" json:"UploadedAt,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *FileMetadata) Reset() {
|
||||
*x = FileMetadata{}
|
||||
mi := &file_protoapi_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *FileMetadata) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FileMetadata) ProtoMessage() {}
|
||||
|
||||
func (x *FileMetadata) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[9]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FileMetadata.ProtoReflect.Descriptor instead.
|
||||
func (*FileMetadata) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
func (x *FileMetadata) GetFileName() string {
|
||||
if x != nil {
|
||||
return x.FileName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *FileMetadata) GetFileSize() int64 {
|
||||
if x != nil {
|
||||
return x.FileSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *FileMetadata) GetUploadedAt() int64 {
|
||||
if x != nil {
|
||||
return x.UploadedAt
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type FileList struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Files []*FileMetadata `protobuf:"bytes,1,rep,name=Files,proto3" json:"Files,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *FileList) Reset() {
|
||||
*x = FileList{}
|
||||
mi := &file_protoapi_proto_msgTypes[10]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *FileList) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FileList) ProtoMessage() {}
|
||||
|
||||
func (x *FileList) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[10]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FileList.ProtoReflect.Descriptor instead.
|
||||
func (*FileList) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{10}
|
||||
}
|
||||
|
||||
func (x *FileList) GetFiles() []*FileMetadata {
|
||||
if x != nil {
|
||||
return x.Files
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DownloadRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
FileName string `protobuf:"bytes,1,opt,name=FileName,proto3" json:"FileName,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DownloadRequest) Reset() {
|
||||
*x = DownloadRequest{}
|
||||
mi := &file_protoapi_proto_msgTypes[11]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DownloadRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DownloadRequest) ProtoMessage() {}
|
||||
|
||||
func (x *DownloadRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[11]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DownloadRequest.ProtoReflect.Descriptor instead.
|
||||
func (*DownloadRequest) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{11}
|
||||
}
|
||||
|
||||
func (x *DownloadRequest) GetFileName() string {
|
||||
if x != nil {
|
||||
return x.FileName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type AlertSubscription struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
ClientId string `protobuf:"bytes,1,opt,name=ClientId,proto3" json:"ClientId,omitempty"`
|
||||
Topic string `protobuf:"bytes,2,opt,name=Topic,proto3" json:"Topic,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AlertSubscription) Reset() {
|
||||
*x = AlertSubscription{}
|
||||
mi := &file_protoapi_proto_msgTypes[12]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AlertSubscription) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AlertSubscription) ProtoMessage() {}
|
||||
|
||||
func (x *AlertSubscription) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[12]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AlertSubscription.ProtoReflect.Descriptor instead.
|
||||
func (*AlertSubscription) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{12}
|
||||
}
|
||||
|
||||
func (x *AlertSubscription) GetClientId() string {
|
||||
if x != nil {
|
||||
return x.ClientId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AlertSubscription) GetTopic() string {
|
||||
if x != nil {
|
||||
return x.Topic
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type AlertMessage struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AlertId string `protobuf:"bytes,1,opt,name=AlertId,proto3" json:"AlertId,omitempty"`
|
||||
DeviceId string `protobuf:"bytes,2,opt,name=DeviceId,proto3" json:"DeviceId,omitempty"`
|
||||
Message string `protobuf:"bytes,3,opt,name=Message,proto3" json:"Message,omitempty"`
|
||||
Timestamp int64 `protobuf:"varint,4,opt,name=Timestamp,proto3" json:"Timestamp,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AlertMessage) Reset() {
|
||||
*x = AlertMessage{}
|
||||
mi := &file_protoapi_proto_msgTypes[13]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AlertMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AlertMessage) ProtoMessage() {}
|
||||
|
||||
func (x *AlertMessage) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_protoapi_proto_msgTypes[13]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AlertMessage.ProtoReflect.Descriptor instead.
|
||||
func (*AlertMessage) Descriptor() ([]byte, []int) {
|
||||
return file_protoapi_proto_rawDescGZIP(), []int{13}
|
||||
}
|
||||
|
||||
func (x *AlertMessage) GetAlertId() string {
|
||||
if x != nil {
|
||||
return x.AlertId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AlertMessage) GetDeviceId() string {
|
||||
if x != nil {
|
||||
return x.DeviceId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AlertMessage) GetMessage() string {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AlertMessage) GetTimestamp() int64 {
|
||||
if x != nil {
|
||||
return x.Timestamp
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_protoapi_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_protoapi_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x0eprotoapi.proto\"A\n" +
|
||||
"\tFileChunk\x12\x1a\n" +
|
||||
"\bFileName\x18\x01 \x01(\tR\bFileName\x12\x18\n" +
|
||||
"\aContent\x18\x02 \x01(\fR\aContent\"h\n" +
|
||||
"\fUploadStatus\x12\x18\n" +
|
||||
"\aSuccess\x18\x01 \x01(\bR\aSuccess\x12\x18\n" +
|
||||
"\aMessage\x18\x02 \x01(\tR\aMessage\x12$\n" +
|
||||
"\rBytesUploaded\x18\x03 \x01(\x03R\rBytesUploaded\"g\n" +
|
||||
"\vSensingData\x12\x1a\n" +
|
||||
"\bDeviceId\x18\x01 \x01(\tR\bDeviceId\x12 \n" +
|
||||
"\vTemperature\x18\x02 \x01(\x01R\vTemperature\x12\x1a\n" +
|
||||
"\bHumidity\x18\x03 \x01(\x01R\bHumidity\"E\n" +
|
||||
"\x0fSensingResponse\x12\x18\n" +
|
||||
"\aSuccess\x18\x01 \x01(\bR\aSuccess\x12\x18\n" +
|
||||
"\aMessage\x18\x02 \x01(\tR\aMessage\" \n" +
|
||||
"\bDateTime\x12\x14\n" +
|
||||
"\x05Value\x18\x01 \x01(\tR\x05Value\"'\n" +
|
||||
"\x0fRequestDateTime\x12\x14\n" +
|
||||
"\x05Value\x18\x02 \x01(\tR\x05Value\"9\n" +
|
||||
"\vRequestPass\x12\x12\n" +
|
||||
"\x04Seed\x18\x01 \x01(\x03R\x04Seed\x12\x16\n" +
|
||||
"\x06Length\x18\b \x01(\x03R\x06Length\"(\n" +
|
||||
"\n" +
|
||||
"RandomPass\x12\x1a\n" +
|
||||
"\bPassword\x18\x01 \x01(\tR\bPassword\"\x0e\n" +
|
||||
"\fEmptyRequest\"f\n" +
|
||||
"\fFileMetadata\x12\x1a\n" +
|
||||
"\bFileName\x18\x01 \x01(\tR\bFileName\x12\x1a\n" +
|
||||
"\bFileSize\x18\x02 \x01(\x03R\bFileSize\x12\x1e\n" +
|
||||
"\n" +
|
||||
"UploadedAt\x18\x03 \x01(\x03R\n" +
|
||||
"UploadedAt\"/\n" +
|
||||
"\bFileList\x12#\n" +
|
||||
"\x05Files\x18\x01 \x03(\v2\r.FileMetadataR\x05Files\"-\n" +
|
||||
"\x0fDownloadRequest\x12\x1a\n" +
|
||||
"\bFileName\x18\x01 \x01(\tR\bFileName\"E\n" +
|
||||
"\x11AlertSubscription\x12\x1a\n" +
|
||||
"\bClientId\x18\x01 \x01(\tR\bClientId\x12\x14\n" +
|
||||
"\x05Topic\x18\x02 \x01(\tR\x05Topic\"|\n" +
|
||||
"\fAlertMessage\x12\x18\n" +
|
||||
"\aAlertId\x18\x01 \x01(\tR\aAlertId\x12\x1a\n" +
|
||||
"\bDeviceId\x18\x02 \x01(\tR\bDeviceId\x12\x18\n" +
|
||||
"\aMessage\x18\x03 \x01(\tR\aMessage\x12\x1c\n" +
|
||||
"\tTimestamp\x18\x04 \x01(\x03R\tTimestamp2\xcf\x02\n" +
|
||||
"\n" +
|
||||
"IoTService\x12&\n" +
|
||||
"\aGetDate\x12\x10.RequestDateTime\x1a\t.DateTime\x123\n" +
|
||||
"\x11UpdateSensingData\x12\f.SensingData\x1a\x10.SensingResponse\x12*\n" +
|
||||
"\rGetRandomPass\x12\f.RequestPass\x1a\v.RandomPass\x12)\n" +
|
||||
"\n" +
|
||||
"UploadFile\x12\n" +
|
||||
".FileChunk\x1a\r.UploadStatus(\x01\x12%\n" +
|
||||
"\tListFiles\x12\r.EmptyRequest\x1a\t.FileList\x12.\n" +
|
||||
"\fDownloadFile\x12\x10.DownloadRequest\x1a\n" +
|
||||
".FileChunk0\x01\x126\n" +
|
||||
"\x0fSubscribeAlerts\x12\x12.AlertSubscription\x1a\r.AlertMessage0\x01B\x16Z\x14./protoapi/;protoapib\x06proto3"
|
||||
|
||||
var (
|
||||
file_protoapi_proto_rawDescOnce sync.Once
|
||||
file_protoapi_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_protoapi_proto_rawDescGZIP() []byte {
|
||||
file_protoapi_proto_rawDescOnce.Do(func() {
|
||||
file_protoapi_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_protoapi_proto_rawDesc), len(file_protoapi_proto_rawDesc)))
|
||||
})
|
||||
return file_protoapi_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_protoapi_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
|
||||
var file_protoapi_proto_goTypes = []any{
|
||||
(*FileChunk)(nil), // 0: FileChunk
|
||||
(*UploadStatus)(nil), // 1: UploadStatus
|
||||
(*SensingData)(nil), // 2: SensingData
|
||||
(*SensingResponse)(nil), // 3: SensingResponse
|
||||
(*DateTime)(nil), // 4: DateTime
|
||||
(*RequestDateTime)(nil), // 5: RequestDateTime
|
||||
(*RequestPass)(nil), // 6: RequestPass
|
||||
(*RandomPass)(nil), // 7: RandomPass
|
||||
(*EmptyRequest)(nil), // 8: EmptyRequest
|
||||
(*FileMetadata)(nil), // 9: FileMetadata
|
||||
(*FileList)(nil), // 10: FileList
|
||||
(*DownloadRequest)(nil), // 11: DownloadRequest
|
||||
(*AlertSubscription)(nil), // 12: AlertSubscription
|
||||
(*AlertMessage)(nil), // 13: AlertMessage
|
||||
}
|
||||
var file_protoapi_proto_depIdxs = []int32{
|
||||
9, // 0: FileList.Files:type_name -> FileMetadata
|
||||
5, // 1: IoTService.GetDate:input_type -> RequestDateTime
|
||||
2, // 2: IoTService.UpdateSensingData:input_type -> SensingData
|
||||
6, // 3: IoTService.GetRandomPass:input_type -> RequestPass
|
||||
0, // 4: IoTService.UploadFile:input_type -> FileChunk
|
||||
8, // 5: IoTService.ListFiles:input_type -> EmptyRequest
|
||||
11, // 6: IoTService.DownloadFile:input_type -> DownloadRequest
|
||||
12, // 7: IoTService.SubscribeAlerts:input_type -> AlertSubscription
|
||||
4, // 8: IoTService.GetDate:output_type -> DateTime
|
||||
3, // 9: IoTService.UpdateSensingData:output_type -> SensingResponse
|
||||
7, // 10: IoTService.GetRandomPass:output_type -> RandomPass
|
||||
1, // 11: IoTService.UploadFile:output_type -> UploadStatus
|
||||
10, // 12: IoTService.ListFiles:output_type -> FileList
|
||||
0, // 13: IoTService.DownloadFile:output_type -> FileChunk
|
||||
13, // 14: IoTService.SubscribeAlerts:output_type -> AlertMessage
|
||||
8, // [8:15] is the sub-list for method output_type
|
||||
1, // [1:8] is the sub-list for method input_type
|
||||
1, // [1:1] is the sub-list for extension type_name
|
||||
1, // [1:1] is the sub-list for extension extendee
|
||||
0, // [0:1] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_protoapi_proto_init() }
|
||||
func file_protoapi_proto_init() {
|
||||
if File_protoapi_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_protoapi_proto_rawDesc), len(file_protoapi_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 14,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_protoapi_proto_goTypes,
|
||||
DependencyIndexes: file_protoapi_proto_depIdxs,
|
||||
MessageInfos: file_protoapi_proto_msgTypes,
|
||||
}.Build()
|
||||
File_protoapi_proto = out.File
|
||||
file_protoapi_proto_goTypes = nil
|
||||
file_protoapi_proto_depIdxs = nil
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc v3.21.12
|
||||
// source: protoapi.proto
|
||||
|
||||
package protoapi
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
IoTService_GetDate_FullMethodName = "/IoTService/GetDate"
|
||||
IoTService_UpdateSensingData_FullMethodName = "/IoTService/UpdateSensingData"
|
||||
IoTService_GetRandomPass_FullMethodName = "/IoTService/GetRandomPass"
|
||||
IoTService_UploadFile_FullMethodName = "/IoTService/UploadFile"
|
||||
IoTService_ListFiles_FullMethodName = "/IoTService/ListFiles"
|
||||
IoTService_DownloadFile_FullMethodName = "/IoTService/DownloadFile"
|
||||
IoTService_SubscribeAlerts_FullMethodName = "/IoTService/SubscribeAlerts"
|
||||
)
|
||||
|
||||
// IoTServiceClient is the client API for IoTService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type IoTServiceClient interface {
|
||||
GetDate(ctx context.Context, in *RequestDateTime, opts ...grpc.CallOption) (*DateTime, error)
|
||||
UpdateSensingData(ctx context.Context, in *SensingData, opts ...grpc.CallOption) (*SensingResponse, error)
|
||||
GetRandomPass(ctx context.Context, in *RequestPass, opts ...grpc.CallOption) (*RandomPass, error)
|
||||
UploadFile(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[FileChunk, UploadStatus], error)
|
||||
ListFiles(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*FileList, error)
|
||||
DownloadFile(ctx context.Context, in *DownloadRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FileChunk], error)
|
||||
SubscribeAlerts(ctx context.Context, in *AlertSubscription, opts ...grpc.CallOption) (grpc.ServerStreamingClient[AlertMessage], error)
|
||||
}
|
||||
|
||||
type ioTServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewIoTServiceClient(cc grpc.ClientConnInterface) IoTServiceClient {
|
||||
return &ioTServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *ioTServiceClient) GetDate(ctx context.Context, in *RequestDateTime, opts ...grpc.CallOption) (*DateTime, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(DateTime)
|
||||
err := c.cc.Invoke(ctx, IoTService_GetDate_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ioTServiceClient) UpdateSensingData(ctx context.Context, in *SensingData, opts ...grpc.CallOption) (*SensingResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(SensingResponse)
|
||||
err := c.cc.Invoke(ctx, IoTService_UpdateSensingData_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ioTServiceClient) GetRandomPass(ctx context.Context, in *RequestPass, opts ...grpc.CallOption) (*RandomPass, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(RandomPass)
|
||||
err := c.cc.Invoke(ctx, IoTService_GetRandomPass_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ioTServiceClient) UploadFile(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[FileChunk, UploadStatus], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &IoTService_ServiceDesc.Streams[0], IoTService_UploadFile_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[FileChunk, UploadStatus]{ClientStream: stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type IoTService_UploadFileClient = grpc.ClientStreamingClient[FileChunk, UploadStatus]
|
||||
|
||||
func (c *ioTServiceClient) ListFiles(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*FileList, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(FileList)
|
||||
err := c.cc.Invoke(ctx, IoTService_ListFiles_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ioTServiceClient) DownloadFile(ctx context.Context, in *DownloadRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FileChunk], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &IoTService_ServiceDesc.Streams[1], IoTService_DownloadFile_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[DownloadRequest, FileChunk]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type IoTService_DownloadFileClient = grpc.ServerStreamingClient[FileChunk]
|
||||
|
||||
func (c *ioTServiceClient) SubscribeAlerts(ctx context.Context, in *AlertSubscription, opts ...grpc.CallOption) (grpc.ServerStreamingClient[AlertMessage], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &IoTService_ServiceDesc.Streams[2], IoTService_SubscribeAlerts_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[AlertSubscription, AlertMessage]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type IoTService_SubscribeAlertsClient = grpc.ServerStreamingClient[AlertMessage]
|
||||
|
||||
// IoTServiceServer is the server API for IoTService service.
|
||||
// All implementations must embed UnimplementedIoTServiceServer
|
||||
// for forward compatibility.
|
||||
type IoTServiceServer interface {
|
||||
GetDate(context.Context, *RequestDateTime) (*DateTime, error)
|
||||
UpdateSensingData(context.Context, *SensingData) (*SensingResponse, error)
|
||||
GetRandomPass(context.Context, *RequestPass) (*RandomPass, error)
|
||||
UploadFile(grpc.ClientStreamingServer[FileChunk, UploadStatus]) error
|
||||
ListFiles(context.Context, *EmptyRequest) (*FileList, error)
|
||||
DownloadFile(*DownloadRequest, grpc.ServerStreamingServer[FileChunk]) error
|
||||
SubscribeAlerts(*AlertSubscription, grpc.ServerStreamingServer[AlertMessage]) error
|
||||
mustEmbedUnimplementedIoTServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedIoTServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedIoTServiceServer struct{}
|
||||
|
||||
func (UnimplementedIoTServiceServer) GetDate(context.Context, *RequestDateTime) (*DateTime, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetDate not implemented")
|
||||
}
|
||||
func (UnimplementedIoTServiceServer) UpdateSensingData(context.Context, *SensingData) (*SensingResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateSensingData not implemented")
|
||||
}
|
||||
func (UnimplementedIoTServiceServer) GetRandomPass(context.Context, *RequestPass) (*RandomPass, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRandomPass not implemented")
|
||||
}
|
||||
func (UnimplementedIoTServiceServer) UploadFile(grpc.ClientStreamingServer[FileChunk, UploadStatus]) error {
|
||||
return status.Error(codes.Unimplemented, "method UploadFile not implemented")
|
||||
}
|
||||
func (UnimplementedIoTServiceServer) ListFiles(context.Context, *EmptyRequest) (*FileList, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListFiles not implemented")
|
||||
}
|
||||
func (UnimplementedIoTServiceServer) DownloadFile(*DownloadRequest, grpc.ServerStreamingServer[FileChunk]) error {
|
||||
return status.Error(codes.Unimplemented, "method DownloadFile not implemented")
|
||||
}
|
||||
func (UnimplementedIoTServiceServer) SubscribeAlerts(*AlertSubscription, grpc.ServerStreamingServer[AlertMessage]) error {
|
||||
return status.Error(codes.Unimplemented, "method SubscribeAlerts not implemented")
|
||||
}
|
||||
func (UnimplementedIoTServiceServer) mustEmbedUnimplementedIoTServiceServer() {}
|
||||
func (UnimplementedIoTServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeIoTServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to IoTServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeIoTServiceServer interface {
|
||||
mustEmbedUnimplementedIoTServiceServer()
|
||||
}
|
||||
|
||||
func RegisterIoTServiceServer(s grpc.ServiceRegistrar, srv IoTServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedIoTServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&IoTService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _IoTService_GetDate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RequestDateTime)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(IoTServiceServer).GetDate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: IoTService_GetDate_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(IoTServiceServer).GetDate(ctx, req.(*RequestDateTime))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _IoTService_UpdateSensingData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SensingData)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(IoTServiceServer).UpdateSensingData(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: IoTService_UpdateSensingData_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(IoTServiceServer).UpdateSensingData(ctx, req.(*SensingData))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _IoTService_GetRandomPass_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RequestPass)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(IoTServiceServer).GetRandomPass(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: IoTService_GetRandomPass_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(IoTServiceServer).GetRandomPass(ctx, req.(*RequestPass))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _IoTService_UploadFile_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(IoTServiceServer).UploadFile(&grpc.GenericServerStream[FileChunk, UploadStatus]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type IoTService_UploadFileServer = grpc.ClientStreamingServer[FileChunk, UploadStatus]
|
||||
|
||||
func _IoTService_ListFiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(IoTServiceServer).ListFiles(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: IoTService_ListFiles_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(IoTServiceServer).ListFiles(ctx, req.(*EmptyRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _IoTService_DownloadFile_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(DownloadRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(IoTServiceServer).DownloadFile(m, &grpc.GenericServerStream[DownloadRequest, FileChunk]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type IoTService_DownloadFileServer = grpc.ServerStreamingServer[FileChunk]
|
||||
|
||||
func _IoTService_SubscribeAlerts_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(AlertSubscription)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(IoTServiceServer).SubscribeAlerts(m, &grpc.GenericServerStream[AlertSubscription, AlertMessage]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type IoTService_SubscribeAlertsServer = grpc.ServerStreamingServer[AlertMessage]
|
||||
|
||||
// IoTService_ServiceDesc is the grpc.ServiceDesc for IoTService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var IoTService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "IoTService",
|
||||
HandlerType: (*IoTServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetDate",
|
||||
Handler: _IoTService_GetDate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "UpdateSensingData",
|
||||
Handler: _IoTService_UpdateSensingData_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetRandomPass",
|
||||
Handler: _IoTService_GetRandomPass_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListFiles",
|
||||
Handler: _IoTService_ListFiles_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "UploadFile",
|
||||
Handler: _IoTService_UploadFile_Handler,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "DownloadFile",
|
||||
Handler: _IoTService_DownloadFile_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "SubscribeAlerts",
|
||||
Handler: _IoTService_SubscribeAlerts_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "protoapi.proto",
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"grpccanary/lib/grpc/basic/protoapi"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/reflection"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
var min = 0
|
||||
var max = 100
|
||||
var port = ":8080"
|
||||
|
||||
type UploadedFile struct {
|
||||
FileName string
|
||||
Content []byte
|
||||
UploadedAt int64
|
||||
}
|
||||
|
||||
var (
|
||||
fileStore = make(map[string]*UploadedFile)
|
||||
storeMu sync.RWMutex
|
||||
)
|
||||
|
||||
type AlertSubscriber struct {
|
||||
ClientId string
|
||||
Channel chan *protoapi.AlertMessage
|
||||
}
|
||||
|
||||
var (
|
||||
subscribers = make(map[string]*AlertSubscriber)
|
||||
subMu sync.Mutex
|
||||
)
|
||||
|
||||
func publishAlert(alert *protoapi.AlertMessage) {
|
||||
subMu.Lock()
|
||||
defer subMu.Unlock()
|
||||
for _, sub := range subscribers {
|
||||
select {
|
||||
case sub.Channel <- alert:
|
||||
default:
|
||||
fmt.Printf("Alert channel blocked for client %s, dropping event\n", sub.ClientId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func random(min, max int, src rand.Source) int {
|
||||
return rand.New(src).Intn(max-min) + min
|
||||
}
|
||||
|
||||
// Extra function for creating secure random numbers
|
||||
//
|
||||
// func randomSecure(min, max int) int {
|
||||
// v, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// return min
|
||||
// }
|
||||
// fmt.Println("**", v, min, max)
|
||||
|
||||
// return min + int(v.Uint64())
|
||||
// }
|
||||
|
||||
func getString(len int64, src rand.Source) string {
|
||||
temp := ""
|
||||
startChar := "!"
|
||||
var i int64 = 1
|
||||
for {
|
||||
// For getting valid ASCII characters
|
||||
myRand := random(0, 94, src)
|
||||
newChar := string(startChar[0] + byte(myRand))
|
||||
temp = temp + newChar
|
||||
if i == len {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
type IoTServer struct {
|
||||
protoapi.UnimplementedIoTServiceServer
|
||||
}
|
||||
|
||||
func (IoTServer) GetDate(ctx context.Context, r *protoapi.RequestDateTime) (*protoapi.DateTime, error) {
|
||||
currentTime := time.Now()
|
||||
response := &protoapi.DateTime{
|
||||
Value: currentTime.String(),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (IoTServer) UpdateSensingData(ctx context.Context, r *protoapi.SensingData) (*protoapi.SensingResponse, error) {
|
||||
fmt.Printf("Received sensing data - Device: %s, Temp: %.2f°C, Humid: %.2f%%\n", r.GetDeviceId(), r.GetTemperature(), r.GetHumidity())
|
||||
|
||||
// 임계값 초과(40도 초과) 시 실시간 Pub/Sub 경보 메시지 발행
|
||||
if r.GetTemperature() > 40.0 {
|
||||
fmt.Printf("⚠️ Critical temperature detected: %.2f°C! Publishing warning...\n", r.GetTemperature())
|
||||
publishAlert(&protoapi.AlertMessage{
|
||||
AlertId: fmt.Sprintf("alert-%d", time.Now().UnixNano()),
|
||||
DeviceId: r.GetDeviceId(),
|
||||
Message: fmt.Sprintf("Critical high temperature: %.2f°C (Humidity: %.2f%%)", r.GetTemperature(), r.GetHumidity()),
|
||||
Timestamp: time.Now().Unix(),
|
||||
})
|
||||
}
|
||||
|
||||
response := &protoapi.SensingResponse{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("Sensing data updated successfully for device %s", r.GetDeviceId()),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (IoTServer) GetRandomPass(ctx context.Context, r *protoapi.RequestPass) (*protoapi.RandomPass, error) {
|
||||
src := rand.NewSource(r.GetSeed())
|
||||
temp := getString(r.GetLength(), src)
|
||||
|
||||
response := &protoapi.RandomPass{
|
||||
Password: temp,
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (IoTServer) UploadFile(stream protoapi.IoTService_UploadFileServer) error {
|
||||
var totalBytes int64
|
||||
var fileName string
|
||||
var buffer []byte
|
||||
|
||||
for {
|
||||
chunk, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
fmt.Printf("File upload completed. Received %d bytes for file '%s'\n", totalBytes, fileName)
|
||||
|
||||
if fileName != "" {
|
||||
storeMu.Lock()
|
||||
fileStore[fileName] = &UploadedFile{
|
||||
FileName: fileName,
|
||||
Content: buffer,
|
||||
UploadedAt: time.Now().Unix(),
|
||||
}
|
||||
storeMu.Unlock()
|
||||
}
|
||||
|
||||
return stream.SendAndClose(&protoapi.UploadStatus{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("File '%s' uploaded successfully.", fileName),
|
||||
BytesUploaded: totalBytes,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("File upload error:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if fileName == "" {
|
||||
fileName = chunk.GetFileName()
|
||||
}
|
||||
buffer = append(buffer, chunk.GetContent()...)
|
||||
totalBytes += int64(len(chunk.GetContent()))
|
||||
}
|
||||
}
|
||||
|
||||
func (IoTServer) ListFiles(ctx context.Context, r *protoapi.EmptyRequest) (*protoapi.FileList, error) {
|
||||
storeMu.RLock()
|
||||
defer storeMu.RUnlock()
|
||||
|
||||
var files []*protoapi.FileMetadata
|
||||
for _, f := range fileStore {
|
||||
files = append(files, &protoapi.FileMetadata{
|
||||
FileName: f.FileName,
|
||||
FileSize: int64(len(f.Content)),
|
||||
UploadedAt: f.UploadedAt,
|
||||
})
|
||||
}
|
||||
|
||||
return &protoapi.FileList{Files: files}, nil
|
||||
}
|
||||
|
||||
func (IoTServer) DownloadFile(r *protoapi.DownloadRequest, stream protoapi.IoTService_DownloadFileServer) error {
|
||||
storeMu.RLock()
|
||||
f, exists := fileStore[r.GetFileName()]
|
||||
storeMu.RUnlock()
|
||||
|
||||
if !exists {
|
||||
return status.Errorf(codes.NotFound, "file %s not found", r.GetFileName())
|
||||
}
|
||||
|
||||
chunkSize := 1024 // 1KB 청크 단위
|
||||
totalBytes := len(f.Content)
|
||||
|
||||
for i := 0; i < totalBytes; i += chunkSize {
|
||||
end := i + chunkSize
|
||||
if end > totalBytes {
|
||||
end = totalBytes
|
||||
}
|
||||
|
||||
err := stream.Send(&protoapi.FileChunk{
|
||||
FileName: f.FileName,
|
||||
Content: f.Content[i:end],
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (IoTServer) SubscribeAlerts(r *protoapi.AlertSubscription, stream protoapi.IoTService_SubscribeAlertsServer) error {
|
||||
clientId := r.GetClientId()
|
||||
ch := make(chan *protoapi.AlertMessage, 10)
|
||||
sub := &AlertSubscriber{
|
||||
ClientId: clientId,
|
||||
Channel: ch,
|
||||
}
|
||||
|
||||
subMu.Lock()
|
||||
subscribers[clientId] = sub
|
||||
subMu.Unlock()
|
||||
|
||||
fmt.Printf("Client %s subscribed to alerts on topic '%s'\n", clientId, r.GetTopic())
|
||||
|
||||
for {
|
||||
select {
|
||||
case alert := <-ch:
|
||||
err := stream.Send(alert)
|
||||
if err != nil {
|
||||
subMu.Lock()
|
||||
delete(subscribers, clientId)
|
||||
subMu.Unlock()
|
||||
fmt.Printf("Client %s alert subscription disconnected: %v\n", clientId, err)
|
||||
return err
|
||||
}
|
||||
case <-stream.Context().Done():
|
||||
subMu.Lock()
|
||||
delete(subscribers, clientId)
|
||||
subMu.Unlock()
|
||||
fmt.Printf("Client %s unsubscribed (context done)\n", clientId)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ServerRun(addr string) {
|
||||
server := grpc.NewServer()
|
||||
var iotServer IoTServer
|
||||
protoapi.RegisterIoTServiceServer(server, iotServer)
|
||||
|
||||
reflection.Register(server)
|
||||
|
||||
listen, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Serving requests...")
|
||||
server.Serve(listen)
|
||||
}
|
||||
Reference in New Issue
Block a user