From 2e6046013183fc18e52e4cddac11e5b1bc2be082 Mon Sep 17 00:00:00 2001 From: Nedim Date: Mon, 16 Oct 2023 19:43:35 +0200 Subject: [PATCH] Added temperature exceded event --- controllers/devices_controller.go | 61 +++------------------ controllers/notifications_controller.go | 18 +++---- database/device/device.go | 72 +++++++++++++++++++++++++ database/notification/notificaiton.go | 8 +-- main.go | 7 ++- models/notification.go | 2 +- services/messaging/messaging_service.go | 11 +++- 7 files changed, 109 insertions(+), 70 deletions(-) diff --git a/controllers/devices_controller.go b/controllers/devices_controller.go index efd92bf..4b4aac3 100644 --- a/controllers/devices_controller.go +++ b/controllers/devices_controller.go @@ -3,7 +3,6 @@ package controllers import ( "context" "encoding/json" - "errors" "log" "math/big" "net/http" @@ -11,7 +10,6 @@ import ( "time" "github.com/gin-gonic/gin" - "github.com/jinzhu/gorm" "gitlab.com/pactual1/backend/config" "gitlab.com/pactual1/backend/database/contract" "gitlab.com/pactual1/backend/database/device" @@ -28,62 +26,18 @@ func SaveDeviceInfo(c *gin.Context) { err := json.Unmarshal(rawData, &deviceInfo) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON payload"}) - log.Printf("Invalid json pyload : %v", err) + log.Printf("Invalid json payload : %v", err) return } - deviceInfo.RawJSON = string(rawData) - deviceInfo.X = deviceInfo.AccInfo.X - deviceInfo.Y = deviceInfo.AccInfo.Y - deviceInfo.Z = deviceInfo.AccInfo.Z - - // Attempt to find the device by IMEI; if not found, create a new device - var device models.Device - if err := shared.GetDb().Unscoped().Where("device_id = ?", deviceInfo.ExternalDeviceID).First(&device).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - // Create new device - device = models.Device{ - IMEI: deviceInfo.IMEI, - IMSI: deviceInfo.IMSI, - DeviceID: deviceInfo.ExternalDeviceID, - DeviceConfiguration: string(rawData), - } - if err := shared.GetDb().Create(&device).Error; err != nil { - log.Printf("CREATE -Device DB Error: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not create new device"}) - return - } - deviceInfo.DeviceID = device.ID - } else { - log.Printf("CREATE -Device DB Error: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Database error"}) - return - } - } else { - log.Printf("Current device deleted at: %v", device.DeletedAt) - - if device.DeletedAt.Valid { - // Use raw SQL to update the record - if err := shared.GetDb().Exec("UPDATE devices SET deleted_at = NULL, company_id = NULL WHERE id = ?", device.ID).Error; err != nil { - log.Printf("UNDELETE -Device DB Error: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not revive deleted device"}) - return - } else { - log.Printf("Device undeleted successfuly : %v", device.DeletedAt) - } - } - deviceInfo.DeviceID = device.ID - } - - // Save deviceInfo to your database - if err := shared.GetDb().Create(&deviceInfo).Error; err != nil { - log.Printf("SaveDeviceInfo CREATE -DeviceInfo DB Error: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not save device info"}) + deviceInfo, currentDevice, err := device.SaveDeviceInfoToDB(deviceInfo, rawData) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } - if device.CurrentContractID != nil { - deviceContract, _, err := contract.GetContractByID(*device.CurrentContractID) + if currentDevice.CurrentContractID != nil { + deviceContract, _, err := contract.GetContractByID(*currentDevice.CurrentContractID) if err != nil { log.Printf("SaveDeviceInfo - GetContractByID error : %v", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not fetch device contract"}) @@ -99,7 +53,7 @@ func SaveDeviceInfo(c *gin.Context) { return } - err = blockchain.NewService(config.AppConfig.Blockchain).AddIOTData(context.Background(), shared.CovertUintToByte32(deviceContract.ID), shared.CovertUintToByte32(device.ID), big.NewInt(time.Now().Unix()), []byte(deviceInfoEncryptedStr)) + err = blockchain.NewService(config.AppConfig.Blockchain).AddIOTData(context.Background(), shared.CovertUintToByte32(deviceContract.ID), shared.CovertUintToByte32(currentDevice.ID), big.NewInt(time.Now().Unix()), []byte(deviceInfoEncryptedStr)) if err != nil { log.Printf("SaveDeviceInfo CREATE -DeviceInfo Blockchain Error: %v", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not save device info in blockchain"}) @@ -108,6 +62,7 @@ func SaveDeviceInfo(c *gin.Context) { } } + log.Printf("Successfully received and saved device info: %v", deviceInfo) c.JSON(http.StatusOK, gin.H{"message": "Successfully received and saved device info", "data": deviceInfo}) } diff --git a/controllers/notifications_controller.go b/controllers/notifications_controller.go index 9be2957..2719b6a 100644 --- a/controllers/notifications_controller.go +++ b/controllers/notifications_controller.go @@ -11,20 +11,20 @@ import ( ) func GetNotifications(c *gin.Context) { - // Get the User ID and Time from query parameters - userIDStr := c.DefaultQuery("user_id", "") + // Get the Company ID and Time from query parameters + companyIDStr := c.DefaultQuery("company_id", "") timeStr := c.DefaultQuery("time", "") - if userIDStr == "" || timeStr == "" { - log.Printf("GetNotifications Error: User ID and Time are required") - c.JSON(http.StatusBadRequest, gin.H{"error": "User ID and Time are required"}) + if companyIDStr == "" || timeStr == "" { + log.Printf("GetNotifications Error: Company ID and Time are required") + c.JSON(http.StatusBadRequest, gin.H{"error": "Company ID and Time are required"}) return } // Convert string to int for UserID - userID, err := strconv.Atoi(userIDStr) + userID, err := strconv.Atoi(companyIDStr) if err != nil { - log.Printf("GetNotifications Error: Invalid User ID: %v", err) + log.Printf("GetNotifications Error: Invalid Company ID: %v", err) c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid User ID"}) return } @@ -37,8 +37,8 @@ func GetNotifications(c *gin.Context) { } afterTime := time.Unix(timestamp, 0) - log.Printf("This is the User ID: %v and Time: %v", userID, afterTime) - notifications, st, err := notification.GetNotificationsForUserID(userID, afterTime) + log.Printf("This is the Company ID: %v and Time: %v", userID, afterTime) + notifications, st, err := notification.GetNotificationsForCompanyID(userID, afterTime) if err != nil { c.JSON(st, gin.H{"error": err.Error()}) diff --git a/database/device/device.go b/database/device/device.go index fe1d1d4..f1afc81 100644 --- a/database/device/device.go +++ b/database/device/device.go @@ -10,6 +10,7 @@ import ( "github.com/jinzhu/gorm" "gitlab.com/pactual1/backend/models" + "gitlab.com/pactual1/backend/services/messaging" "gitlab.com/pactual1/backend/shared" ) @@ -99,3 +100,74 @@ func GetDeviceInfoForContract(deviceID uint64, contract models.Contract) (models return featureCollection, 0, nil } + +func SaveDeviceInfoToDB(deviceInfo models.DeviceInfo, rawData []byte) (models.DeviceInfo, models.Device, error) { + deviceInfo.RawJSON = string(rawData) + deviceInfo.X = deviceInfo.AccInfo.X + deviceInfo.Y = deviceInfo.AccInfo.Y + deviceInfo.Z = deviceInfo.AccInfo.Z + + var device models.Device + if err := shared.GetDb().Unscoped().Where("device_id = ?", deviceInfo.ExternalDeviceID).First(&device).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + newDevice := models.Device{ + IMEI: deviceInfo.IMEI, + IMSI: deviceInfo.IMSI, + DeviceID: deviceInfo.ExternalDeviceID, + DeviceConfiguration: string(rawData), + } + if err := shared.GetDb().Create(&newDevice).Error; err != nil { + return deviceInfo, device, fmt.Errorf("CREATE -Device DB Error: %v", err) + } + deviceInfo.DeviceID = newDevice.ID + } else { + return deviceInfo, device, fmt.Errorf("CREATE -Device DB Error: %v", err) + } + } else { + if device.DeletedAt.Valid { + if err := shared.GetDb().Exec("UPDATE devices SET deleted_at = NULL, company_id = NULL WHERE id = ?", device.ID).Error; err != nil { + return deviceInfo, device, fmt.Errorf("UNDELETE -Device DB Error: %v", err) + } + } + deviceInfo.DeviceID = device.ID + } + + if err := shared.GetDb().Create(&deviceInfo).Error; err != nil { + return deviceInfo, device, fmt.Errorf("SaveDeviceInfo CREATE -DeviceInfo DB Error: %v", err) + } + + + go func(deviceInfo models.DeviceInfo) { + var contract models.Contract + if err := shared.GetDb().Where("device_ids @> ARRAY[?]::integer[]", deviceInfo.DeviceID).First(&contract).Error; err != nil { + log.Printf("could not find associated contract: %v", err) + + } + + messagingChannel:= messaging.GetMessagingChannel() + + if deviceInfo.Temperature > contract.MaxTemp || deviceInfo.Temperature < contract.MinTemp { + + notification := models.Notification{ + Title: "Temperature Alert", + NotificationType: "Temperature", + Text: fmt.Sprintf("Device %s has a temperature outside the permitted range.", deviceInfo.ExternalDeviceID), + CompanyID: int(contract.BuyerID), + } + + sellerNotification := models.Notification{ + Title: "Temperature Alert", + NotificationType: "Temperature", + Text: fmt.Sprintf("Device %s has a temperature outside the permitted range.", deviceInfo.ExternalDeviceID), + CompanyID: int(contract.SellerID), + } + + messagingChannel <- notification + messagingChannel <- sellerNotification + } + }(deviceInfo) + + + + return deviceInfo, device, nil +} \ No newline at end of file diff --git a/database/notification/notificaiton.go b/database/notification/notificaiton.go index ab5880f..0eb91db 100644 --- a/database/notification/notificaiton.go +++ b/database/notification/notificaiton.go @@ -12,18 +12,18 @@ import ( ) -func GetNotificationsForUserID(userID int, afterTime time.Time) ([]models.GetNotificationsResponse, int, error) { +func GetNotificationsForCompanyID(companyID int, afterTime time.Time) ([]models.GetNotificationsResponse, int, error) { // Create a slice to hold the notifications var notifications []models.Notification var customNotifications []models.GetNotificationsResponse // Fetch notifications from the database based on UserID and creation time - if err := shared.GetDb().Where("user_id = ? AND created_at > ?", userID, afterTime).Find(¬ifications).Error; err != nil { + if err := shared.GetDb().Where("company_id = ? AND created_at > ?", companyID, afterTime).Find(¬ifications).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - log.Printf("GetNotificationsForUserID Error: No notifications found: %v", err) + log.Printf("GetNotificationsForCompanyID Error: No notifications found: %v", err) return customNotifications, http.StatusNotFound, err } else { - log.Printf("GetNotificationsForUserID Error: Database error: %v", err) + log.Printf("GetNotificationsForCompanyID Error: Database error: %v", err) return customNotifications, http.StatusInternalServerError, err } } diff --git a/main.go b/main.go index 162410d..a9bcc36 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "gitlab.com/pactual1/backend/services/blockchain" "gitlab.com/pactual1/backend/services/contract" "gitlab.com/pactual1/backend/services/erp" + "gitlab.com/pactual1/backend/services/messaging" "gitlab.com/pactual1/backend/shared" "github.com/gin-gonic/gin" @@ -67,7 +68,11 @@ func main() { contractChannel := make(chan string) // Start services and pass the respective channels - // go messaging.MessagingService(messagingChannel) + notificationCh := make(chan models.Notification, 100) + // Create a new messaging service + messagingService := messaging.NewService(notificationCh, shared.GetDb()) + // Run the messaging service + go messagingService.MessagingService() go erp.ERPService(erpChannel) encryptionClient := shared.NewEncryptionClient(config.AppConfig.Service.BlockchainSecret) diff --git a/models/notification.go b/models/notification.go index 64eab20..11046ef 100644 --- a/models/notification.go +++ b/models/notification.go @@ -11,7 +11,7 @@ type Notification struct { Title string NotificationType string Text string - UserID int + CompanyID int } diff --git a/services/messaging/messaging_service.go b/services/messaging/messaging_service.go index d076d41..603dc17 100644 --- a/services/messaging/messaging_service.go +++ b/services/messaging/messaging_service.go @@ -1,4 +1,4 @@ -package notification +package messaging import ( "fmt" @@ -12,9 +12,12 @@ type service struct { db *gorm.DB } +var MessagingChannel chan models.Notification + func NewService(ch chan models.Notification, db *gorm.DB) service { + MessagingChannel = ch return service{ - ch: ch, + ch: MessagingChannel, db: db, } } @@ -28,4 +31,8 @@ func (s service) MessagingService() { fmt.Printf("Error saving notification to DB: %v\n", err) } } +} + +func GetMessagingChannel() chan models.Notification { + return MessagingChannel } \ No newline at end of file