Evets of notification #18

Merged
duplingnedim merged 1 commits from evets-of-notification into main 2023-10-19 12:01:38 +02:00
7 changed files with 109 additions and 70 deletions

View File

@@ -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})
}

View File

@@ -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()})

View File

@@ -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
}

View File

@@ -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(&notifications).Error; err != nil {
if err := shared.GetDb().Where("company_id = ? AND created_at > ?", companyID, afterTime).Find(&notifications).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
}
}

View File

@@ -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)

View File

@@ -11,7 +11,7 @@ type Notification struct {
Title string
NotificationType string
Text string
UserID int
CompanyID int
}

View File

@@ -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
}