Bruce Wang
Published

Smart Table IoT

Simulate a smart study area that utilizes on IoT devices.

IntermediateShowcase (no instructions)2 hours520
Smart Table IoT

Things used in this project

Story

Read more

Schematics

RaspberryPi

Connection on the Raspberry

Arduino

Connection on the Arduino

Code

Telegram.py

Python
Code use to run Telegram Bot
import telepot
import re
from telepot.loop import MessageLoop
from telepot.namedtuple import ReplyKeyboardMarkup, KeyboardButton
from time import sleep
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
from datetime import datetime, timedelta
import boto3
import sys
from boto3.dynamodb.conditions import Key, Attr

#Preset token and stuff
bot_token = '[ENTER TOKEN HERE FOR TELEGRAM]'

host = "[ENTER AWS ENDPOINT HERE]"
rootCAPath = "certs/rootca.pem"
certificatePath = "certs/certificate.pem.crt"
privateKeyPath = "certs/private.pem.key"
dynamodb = boto3.resource('dynamodb', region_name='us-west-2')

# Respond when first receive message
def on_chat_message(msg):
	global chat_id
	global msgText
	content_type, chat_type, chat_id = telepot.glance(msg)
	print('Chat Message:', content_type, chat_type, chat_id)
	msgText = msg['text'] #Set text message to msgtext
	respondToMsg()

#Get Booking
def getBookedSlots(deviceName):
	try:
		now = datetime.now()
		time = now.strftime("%Y-%m-%dT")
		#time = now.strftime("2019-02-16T")
		table = dynamodb.Table('TehOKosong_Booking')
		DeviceId = deviceName
		#Query if any booking within time
		response = table.query(KeyConditionExpression=Key('DeviceId').eq(DeviceId)& Key('dateTimeIn').begins_with(time),ScanIndexForward=False)
		print(response)
		return response
	except:
		print(sys.exc_info()[0])
		print(sys.exc_info()[1])

def sendSlots(deviceName):
	bot.sendMessage(chat_id, 'Here are the slots booked today for '+deviceName)
	booking = getBookedSlots(deviceName)
	slotMsg = ""
	for items in booking["Items"]:
		dateIn = str(items["dateTimeIn"])
		dateOut = str(items["dateTimeOut"])
		dateIn = dateIn.split('T')[-1]
		dateOut = dateOut.split('T')[-1]
		slotMsg = slotMsg+dateIn+" - "+dateOut+"\n"
	bot.sendMessage(chat_id,slotMsg)
	
def respondToMsg():
	global chat_id
	global msgText
	if msgText == '/command':
		bot.sendMessage(chat_id, 'Which table Do you want to view?',
		reply_markup=ReplyKeyboardMarkup(
			keyboard=[
				[KeyboardButton(text="/tehokosongBRUCE"), KeyboardButton(text="/tehokosongXIANG")]
			]
		))
	elif msgText == '/tehokosongBRUCE':
		sendSlots("tehokosongBRUCE")
	elif msgText == '/tehokosongXIANG':
		sendSlots("tehokosongXIANG")
	else:
		msg = 'Use /command to access command for the system.'
		bot.sendMessage(chat_id, msg)



bot = telepot.Bot(bot_token)
MessageLoop(bot,on_chat_message).run_as_thread()

while True:
	sleep(5)

Main.py

Python
Used for running the Smart Table
from gpiozero import MotionSensor,Buzzer,LED,MCP3008, Button
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
from rpi_lcd import LCD
import serial
import picamera
from time import sleep
import json
from datetime import datetime, timedelta
import sys
from twilio.rest import Client
import re
import boto3
from boto3.dynamodb.conditions import Key, Attr

ser = serial.Serial('/dev/ttyUSB0', 9600) # Establish the connection on a specific port
sound_adc = MCP3008(channel=0)
light_adc = MCP3008(channel=1)
led = LED(18)
power = LED(21)
lcd = LCD()
deviceId = 'tehokosongBRUCE'
bz = Buzzer(23)
button = Button(24, pull_up=False)
currentBook = 0

#Preset token and stuff
account_sid = "[TWILLO SID]"
auth_token = "[AUTH TOKEN FOR TWILLO]"
client = Client(account_sid, auth_token)
twilio_hp = "[TWILLO HP]"

host = "[AWS ENDPOINT HERE]"
rootCAPath = "certs/rootca.pem"
certificatePath = "certs/certificate.pem.crt"
privateKeyPath = "certs/private.pem.key"
dynamodb = boto3.resource('dynamodb', region_name='us-west-2')

#Update PiState
def updateState(stat):
	try:
		table = dynamodb.Table('TehOKosong_PiState')
		table.update_item(
		Key={
			'DeviceId': deviceId
		},UpdateExpression='SET stat = :val1',ExpressionAttributeValues={':val1': stat})
	except:
		print(sys.exc_info()[0])
		print(sys.exc_info()[1])
	
#Get PiState	
def getState():
	try:
		table = dynamodb.Table('TehOKosong_PiState')

		response = table.query(KeyConditionExpression=Key('DeviceId').eq(deviceId),ScanIndexForward=False)
		return response
	except:
		print(sys.exc_info()[0])
		print(sys.exc_info()[1])

#Get Booking Time
def getNextBookingHour(now):
	#If minute is 45, get next hour instead
	hours = now.hour
	minutes = now.minute
	if minutes >= 45:
		hours += 1
	time = now.strftime("%Y-%m-%dT")
	if(len(str(hours))):
		time = time+"0"
	time = time+str(hours)
	return time

#Get Booking
def getBooking(now):
	try:
		table = dynamodb.Table('TehOKosong_Booking')
		time = getNextBookingHour(now)
		#Query if any booking within time
		response = table.query(KeyConditionExpression=Key('DeviceId').eq(deviceId)
		& Key('dateTimeIn').begins_with(time),ScanIndexForward=False)
		#print(response)
		return response
	except:
		print(sys.exc_info()[0])
		print(sys.exc_info()[1])

#Get RFID of User
def getRFID(userId):
	try:
		table = dynamodb.Table('TehOKosong_Accounts')

		response = table.query(KeyConditionExpression=Key('UserId').eq(userId),ScanIndexForward=False)
		return response["Items"][0]["rfid"]
	except:
		print(sys.exc_info()[0])
		print(sys.exc_info()[1])

def checkRFIDHist(now):
	try:
		hours = now.hour
		table = dynamodb.Table('TehOKosong_RFIDHist')
		time = now.strftime("%Y-%m-%dT")
		if(len(str(hours))):
			time = time+"0"
		queryTime = time+str(hours)+str(":5")
		#Query if any booking within 50minte period
		response = table.query(KeyConditionExpression=Key('DeviceId').eq(deviceId)
		& Key('dateTimeIn').begins_with(queryTime),ScanIndexForward=False)
		if response["Items"]:
			return true
		else:
			return false
		
	except:
		print(sys.exc_info()[0])
		print(sys.exc_info()[1])

#Get Name of User based on ID
def getName(userId):
	try:
		table = dynamodb.Table('TehOKosong_Accounts')
		response = table.query(KeyConditionExpression=Key('UserId').eq(userId),ScanIndexForward=False)
		#print response
		return response["Items"][0]["name"]
	except:
		print(sys.exc_info()[0])
		print(sys.exc_info()[1])

#Get Phone of User based on ID
def getPhone(userId):
	try:
		table = dynamodb.Table('TehOKosong_Accounts')
		response = table.query(KeyConditionExpression=Key('UserId').eq(userId),ScanIndexForward=False)
		return response["Items"][0]["phone"]
	except:
		print(sys.exc_info()[0])
		print(sys.exc_info()[1])


#Set Status Of Text
def setStatusText(stat):
	text = ""
	if stat == 1:
		text = 'Status: ON'
	elif stat == 2:
		text = 'Status: OFF'
	else:
		text = 'Status: AUTO'
		
	lcd.text(text, 2)
	#print(text)

def buzzOn():
	bz.on()

def buzzOff():
	bz.off()
	
def ledOn():
	led.on()
	
def ledOff():
	led.off()

def powerOn():
	power.on()
	
def powerOff():
	power.off()

def sendSMS(phoneNo, msg):
	message = client.api.account.messages.create(to=phoneNo,from_=twilio_hp,body=msg)

my_rpi = AWSIoTMQTTClient("Teh-OKosong-basicPubSub")
my_rpi.configureEndpoint(host, 8883)
my_rpi.configureCredentials(rootCAPath, privateKeyPath, certificatePath)

my_rpi.configureOfflinePublishQueueing(-1)  # Infinite offline Publish queueing
my_rpi.configureDrainingFrequency(2)  # Draining: 2 Hz
my_rpi.configureConnectDisconnectTimeout(10)  # 10 sec
my_rpi.configureMQTTOperationTimeout(5)  # 5 sec

# Connect
my_rpi.connect()
sleep(2)	


print("Program starting...")
lcd.text("Smart Table",1)
while True:
	now = datetime.now()
	minutes = now.minute
	seconds = now.second
	print (seconds)
	value = ser.readline()
	if not re.match('^\s+$',value):
		message = {}
		print("RFID: "+value)
		message["DeviceId"] = deviceId
		message["timestamp"] = now.isoformat()
		message["rfid"] = value
		my_rpi.publish("tehokosong/rfidhist", json.dumps(message), 1)
		booking = getBooking(now)
		
		#No booking exist within 15min period
		if not booking['Items']:
			powerOn()
			lcd.text("No Booking",1)
		#Booking exist within 15min period, power on only if match
		else:
			userId = booking['Items'][0]['userId']
			rfid = getRFID(userId)
			
			name = getName(userId)
			#Remove white space from both side
			rfid = rfid.strip(' \t\n\r')
			value = value.strip(' \t\n\r')
			lcd.text("Now : "+str(name), 1)
			
			#If RFID both match then on power
			if(str(rfid) == str(value)):
				powerOn()
			else:
				powerOff()
	
	#Get latest state from DynamoDB
	response = getState()
	
	#Set latest state to current 
	stat = (response['Items'][0]['stat'])
	lightThreshold = (response['Items'][0]['lightThreshold'])
	soundThreshold = (response['Items'][0]['soundThreshold'])
	
	#When button is press
	if button.is_pressed:
		print("Button Pressed")
		if stat == 0:
			stat = 1
		elif stat == 1:
			stat = 2
		elif stat == 2:
			stat = 0
		
		#Update state to dynamodb
		updateState(stat)
	
	#Check state value
	if stat == 2:
		ledOff()
		buzzOff()
		powerOff()
	elif stat == 1:
		ledOn()
	else:
		light_value = light_adc.value*1024
		sound_value = sound_adc.value*1024
		print("Sound: "+str(sound_value)+"  Light: "+str(light_value))
		if(light_value > lightThreshold):
			ledOn()
		else:
			ledOff()
		 
		if(sound_value > soundThreshold):
			buzzOn()
			lcd.text('Noise Level High', 2)
			sleep(3)
			buzzOff()
	
	setStatusText(stat)
	if minutes == 45 & textSent==0:
		booking = getBooking(now)
		if booking['Items']:
			userId = booking['Items'][0]['userId']
			name = getName(userId)
			phone = getPhone(userId)
			msg = "Hi "+name+", your booking is in 15 minutes time!"
			sendSMS(phone, msg)
			textSent = 1
		lcd.text("Next: "+str(name), 1)
	elif minutes == 00:
		name = getName(userId)
		lcd.text("Now : "+str(name), 1)
		textSent = 0
		# If no RFID tap within last 15 min
		if not checkRFIDHist(now):
			powerOff()

	sleep(2)

RFID.IO

Arduino
Used to run the RFID program
#include <MFRC522.h> 
#include <SPI.h>
 
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
 
void setup() 
{
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  //Serial.println("Approximate your card to the reader...");
  //Serial.println();

}
void loop() 
{
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    Serial.println();
    delay(3000);
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    Serial.println();
    delay(3000);
    return;
  }
  //Show UID on serial monitor
  //Serial.print("UID tag :");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? "0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  //Serial.println();
  //Serial.print("Message : ");
  content.toUpperCase();
  if (content.substring(1) == "BD 31 15 2B") //change here the UID of the card/cards that you want to give access
  {
    //Serial.println("Authorized access");
    //Serial.println();
    delay(3000);
  }
 
 else   {
    //Serial.println(" Access denied");
    delay(3000);
  }
  Serial.println();
} 

Credits

Bruce Wang

Bruce Wang

1 project • 0 followers

Comments