Skip to content

Commit

Permalink
controllers created, routers created, device and user schema updated,…
Browse files Browse the repository at this point in the history
… publish/subscribe.ts updated, routes/server.ts updated
  • Loading branch information
KevinLemon112 committed Jun 22, 2024
1 parent 02256f9 commit e061b1c
Show file tree
Hide file tree
Showing 15 changed files with 1,304 additions and 357 deletions.
580 changes: 568 additions & 12 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"author": "",
"license": "ISC",
"dependencies": {
"@types/mqtt": "^2.5.0",
"@types/uuid": "^10.0.0",
"dotenv": "^16.4.1",
"express": "^4.18.2",
"jest": "^29.7.0",
Expand Down
139 changes: 139 additions & 0 deletions src/controllers/publishController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { Request, Response } from 'express';
import mqtt, { MqttClient } from 'mqtt';
import { v1 as uuidv1 } from 'uuid';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();
import db from '../notification/publish/db'; // Import the db.ts file to access the dbURI variable
import Device from '../models/DeviceSchema'; // Import Device model
import User from '../models/UserSchema'; // Import User model

const options = {
username: process.env.ACTIVE_MQ_USERNAME,
password: process.env.ACTIVE_MQ_PASSWORD,
clientId: `publish_${uuidv1()}`,
port: 1883,
};
const topic = process.env.ACTIVE_MQ_TOPIC as string; // Type assertion

// Establish Mongoose connection
mongoose.connect(db.dbURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
} as mongoose.ConnectOptions).then(() => {
console.log('MongoDB connected');
}).catch((error) => {
console.error('MongoDB connection error:', error);
});

// Register account
export const registerAccount = async (req: Request, res: Response) => {
try {
const { email, name, deletionDate, devicesLinked } = req.body;
const currentDate = new Date(); // Set current timestamp
const newAccountData = {
email,
name,
creationDate: currentDate,
lastUpdated: currentDate,
deletionDate: deletionDate ? new Date(deletionDate) : null,
};

const newAccount = new User(newAccountData);

// Handle devicesLinked
if (devicesLinked && devicesLinked.length > 0) {
const devices = await Device.insertMany(devicesLinked); // Use Device to refer to the Device model
newAccount.devicesLinked = devices.map((device: any) => device._id); // Use explicit typing or adjust as needed
} else {
newAccount.devicesLinked = [];
}

const savedAccount = await newAccount.save(); // Save the new account to the database
res.status(201).json(savedAccount); // HTTP 201 Created status code for successful creation
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
};

// Get all accounts
export const getAllAccounts = async (_req: Request, res: Response) => {
try {
const events = await User.find(); // Use User model
res.json(events);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
};

// Get account by ID
export const getAccountById = async (req: Request, res: Response) => {
try {
const event = await User.findById(req.params.id); // Use User model

if (!event) {
res.status(404).json({ error: 'Event not found' });
return;
}

if (!req.params.id) {
res.status(400).json({ error: 'Bad Request' });
return;
}

res.json(event);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
};

// Delete account by ID
export const deleteAccountById = async (req: Request, res: Response) => {
try {
const events = await User.findByIdAndDelete(req.params.id); // Use User model

if (!events) {
// If the document doesn't exist, return a 404 Not Found response
res.status(404).json({ error: 'Event not found' });
return;
}

// If the document is successfully deleted, return a success message
res.json({ message: 'Event deleted successfully' });
} catch (error) {
// If an error occurs during deletion, return a 500 Internal Server Error response
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
};

// Publish message to MQTT
export const publishMessage = async (req: Request, res: Response) => {
const client: MqttClient = mqtt.connect(process.env.ACTIVE_MQ_ENDPOINT as string, options);

const event = {
id: req.params.id,
message: "From Publish Service",
};

client.on('connect', () => {
console.log("Broker connected");
client.publish(topic, JSON.stringify(event), {}, (err) => {
if (err) {
console.error(`Error publishing message: ${err}`);
res.status(500).json({ error: 'Internal Server Error' });
} else {
client.end();
res.json(event);
}
});
});

client.on('error', (error) => {
console.log(error);
res.status(500).json({ error: 'Internal Server Error' });
});
};
73 changes: 73 additions & 0 deletions src/controllers/subscribeController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Request, Response } from 'express';
import mqtt, { MqttClient } from 'mqtt';
import { v1 as uuidv1 } from 'uuid';
import mongoose, { Schema, Document } from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();

const options = {
username: process.env.ACTIVE_MQ_USERNAME,
password: process.env.ACTIVE_MQ_PASSWORD,
clientId: `subscribe_${uuidv1()}`,
port: 1883,
};

const topic = process.env.ACTIVE_MQ_TOPIC as string; // Type assertion
const client: MqttClient = mqtt.connect(process.env.ACTIVE_MQ_ENDPOINT as string, options); // Type assertion

client.on('connect', () => {
client.subscribe(topic);
});

let message: string | null = null;

client.on('message', async (receivedTopic, msg) => {
console.log(`Message received on topic ${receivedTopic}`);
message = msg.toString();
console.log(`Message received: ${message}`);

// MongoDB logic for handling received message
try {
interface Subscription extends Document {
id: string;
message: string;
}

const subscriptionSchema = new Schema<Subscription>({
id: String,
message: String,
});

const SubscriptionModel = mongoose.model<Subscription>('Subscription', subscriptionSchema);

const subscription = {
id: uuidv1(),
message: message,
};

await SubscriptionModel.create(subscription);
} catch (error) {

// Simulate a 404 error
if (!message) {
throw { status: 404, message: 'Not Found' };
}

// Simulate a 403 error
if (message === 'Forbidden') {
throw { status: 403, message: 'Forbidden' };
}

// Simulate a 401 error
if (message === 'Unauthorized') {
throw { status: 401, message: 'Unauthorized' };
}

console.error(error);
}
});

// Check subscription status
export const checkSubscriptionStatus = (req: Request, res: Response) => {
res.status(200).json({ message: 'Subscriber is running' });
};
74 changes: 74 additions & 0 deletions src/controllers/userController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Request, Response } from 'express';
import Device, { DeviceInterface } from '../models/DeviceSchema'; // Import Device and DeviceInterface
import User, { UserInterface } from '../models/UserSchema'; // Import User and UserInterface

// Controller to handle user registration
export const registerUser = async (req: Request, res: Response): Promise<void> => {
try {
const { email, name, deletionDate, devicesLinked } = req.body;
const currentDate = new Date();

const newUser: UserInterface = new User({
email,
name,
creationDate: currentDate,
lastUpdated: currentDate,
deletionDate: deletionDate ? new Date(deletionDate) : null,
devicesLinked: [], // Initialize as an empty array
});

if (devicesLinked && devicesLinked.length > 0) {
// Assuming devicesLinked is an array of objects that match DeviceInterface
const devices: any[] = await Device.insertMany(devicesLinked); // Cast to any[] temporarily
newUser.devicesLinked = devices.map((device: any) => device._id); // Map to _id
}

const savedUser: UserInterface = await newUser.save();
res.status(201).json(savedUser);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
};

export const getAllUsers = async (_req: Request, res: Response): Promise<void> => {
try {
const users: UserInterface[] = await User.find().populate('devicesLinked');
res.json(users);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
};

export const getUserById = async (req: Request, res: Response): Promise<void> => {
try {
const user: UserInterface | null = await User.findById(req.params.id).populate('devicesLinked');

if (!user) {
res.status(404).json({ error: 'User not found' });
return;
}

res.json(user);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
};

export const deleteUserById = async (req: Request, res: Response): Promise<void> => {
try {
const deletedUser: UserInterface | null = await User.findByIdAndDelete(req.params.id);

if (!deletedUser) {
res.status(404).json({ error: 'User not found' });
return;
}

res.json({ message: 'User deleted successfully' });
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
};
90 changes: 52 additions & 38 deletions src/models/DeviceSchema.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,55 @@
import mongoose from 'mongoose';
import mongoose, { Schema, Document } from 'mongoose';

const DeviceSchema = new mongoose.Schema({
uuid: {
type: String,
unique: true
},
lastUpdated: {
type: Date,
default: new Date(),
required: true
},
powered: {
type: Boolean
},
poweredTimestamp: {
type: Date
},
connected: {
type: Boolean
},
connectedTimestamp: {
type: Date
},
color: {
type: String
},
colorTimestamp: {
type: String
},
brightness: {
type: Number
},
brightnessTimestamp:{
type: Date
}
})
export interface DeviceInterface extends Document {
uuid: string;
lastUpdated: Date;
powered?: boolean;
poweredTimestamp?: Date | null;
connected?: boolean;
connectedTimestamp?: Date | null;
color?: string;
colorTimestamp?: string;
brightness?: number;
brightnessTimestamp?: Date | null;
}

const Device = mongoose.model("Device", DeviceSchema);
const DeviceSchema: Schema = new mongoose.Schema({
uuid: {
type: String,
unique: true,
required: true,
},
lastUpdated: {
type: Date,
default: new Date(),
required: true,
},
powered: {
type: Boolean,
},
poweredTimestamp: {
type: Date,
},
connected: {
type: Boolean,
},
connectedTimestamp: {
type: Date,
},
color: {
type: String,
},
colorTimestamp: {
type: String,
},
brightness: {
type: Number,
},
brightnessTimestamp: {
type: Date,
},
});

module.exports = Device;
const Device = mongoose.model<DeviceInterface>('Device', DeviceSchema);

export default Device; // Export Device as default
Loading

0 comments on commit e061b1c

Please sign in to comment.