Commit 1dad5578 authored by liam.wadsworth's avatar liam.wadsworth

Final Commit

parents
class GUI:
instance = None
def __init__(self):
GUI.instance = self
print("Hello World GUI")
def getInstance():
if GUI.instance is None:
GUI()
return GUI.instance
def console(string):
gui = GUI.getInstance()
print(string)
def viewUser(self):
pass
def sendMessageModem(self, number, message):
# Main.messages.sendSMS(number, message)
pass
def sendMessageUser(self, number, message):
# Main.messages.recieveSMS(number, message)
pass
from GUI import GUI
from Messages import Messages
from Membership import Membership
class Main:
def __init__(self):
gui = GUI.getInstance()
messages = Messages.getInstance()
membership = Membership.getInstance()
self.manualtest()
def manualtest(self):
GUI.console("Hello World using GUI Console from Main")
Messages.sendSMS(123456789, "Pretending to send message")
Messages.recieveSMS(123456789, "Pretending to recieve message")
Messages.recieveSMS(123456789, "Hello")
Messages.recieveSMS(123456789, "Status")
Messages.recieveSMS(123456789, "Flip coin")
Main()
from abc import ABC
from GUI import GUI
class User:
name = None
number = None
active = True
services = None
def __init__(self, name, number):
from Services import ChainOfResponsibility
self.name = name
self.number = number
self.services = ChainOfResponsibility()
def getName(self):
return self.name
def getNumber(self):
return self.number
def receiveMessage(self, message):
self.services.requestStart(self, message) # sends messages to own Chain of Responsibility for processing
def sendMessage(self, message):
from Messages import Messages
Messages.sendSMS(self.number, message) # same interface regardless of live or test environment
class IteratorInterface(ABC):
# Iterator: Structures collection of user accounts, but allows editing and retrieval. Hides implementation.
# Defines an interface for accessing and traversing elements (though this is very java-esque)
def hasNext(self): pass
def nextUser(self): pass
def resetPosition(self): pass
def findUser(self, number): pass
def addUser(self, User): pass
def removeUser(self, User): pass
class AggregateInterface:
# Iterator: Structures collection of user accounts, but allows editing and retrieval. Hides implementation.
# defines an interface for creating an Iterator object (though this is very java-esque)
def getInstance(self):
pass
class ConcreteIterator(IteratorInterface):
# Iterator: Structures collection of user accounts, but allows editing and retrieval. Hides implementation.
# implements Iterator interface. Keeps track of current position.
nextUser = None
position = 0
userList = list() # data sturcture used, but specifics of such is encapsulated by iterator
def __init__(self):
self.position = 0
def hasNext(self): # identifies end of the list
if self.position >= len(self.userList) or self.userList is None:
return False
else:
return True
def nextUser(self): # advances current position to next user
if self.hasNext() == True:
user = self.userList[self.position]
self.position = self.position + 1
return user
else:
return None
def resetPosition(self): # resets position / iterator
self.position = 0
def findUser(self, numberOrName): # entry point to iterator for retrieving a user
iterator = ConcreteAggregate.getInstance()
iterator.resetPosition()
strExample = " "
intExample = 1
if type(numberOrName) == type(intExample): # code for finding user via matching number
while iterator.hasNext() == True:
user = iterator.nextUser()
if user.getNumber() == numberOrName:
return user
if type(numberOrName) == type(strExample): # code for finding user via matching name
while iterator.hasNext() == True:
user = iterator.nextUser()
if user.getName() == numberOrName:
return user
GUI.console("Error: User not found within Membership") # error state
return None
def addUser(self, user): # entry point to iterator for adding user to data structure
self.userList.append(user)
GUI.console(user.getName() + " added")
def removeUser(self, user): # entry point to iterator for removing user to data structure
self.userList.remove(user)
GUI.console(user.getName() + "deleted")
class ConcreteAggregate(AggregateInterface, ConcreteIterator):
# Iterator: Structures collection of user accounts, but allows editing and retrieval. Hides implementation.
# implements iterator creation to return an instance of the proper ConcreteIterator, similar to Singleton.
instance = None
def getInstance():
if ConcreteAggregate.instance is None:
ConcreteAggregate.instance = ConcreteAggregate()
return ConcreteAggregate.instance
def __init__(self):
self.instance = ConcreteIterator()
class BuilderInterface(ABC):
# Builder: Creates objects in a sequential way, allowing for customisation at any time
# defines an interface for creating a BuilderConcrete (though this is very java-esque)
def basicServices(self): pass
def otherServices(self): pass
class BuilderConcrete(BuilderInterface):
# Builder: Creates objects in a sequential way, allowing for customisation at any time
# handles requests from BuilderDirector to add/remove/edit parts of an object
def basicServices(self):
pass
def otherServices(self):
pass
class BuilderDirector:
# Builder: Creates objects in a sequential way, allowing for customisation at any time
# handles requests for new objects, defers add/remove/redit parts of object to BuilderConcrete
builder = None
def setBuilder(self, builder):
self.builder = builder
def newUser(self):
user = User()
pass
class Membership:
# Singleton: Constructor always returns the instance in play, this ensures that there is only one of this object
instance = None
userList = None
def __init__(self):
if Membership.instance is None:
Membership.instance = self
self.userList = ConcreteAggregate.getInstance()
# director = UserBuilderDirector() # not yet implemented
self.test() # FOR TESTING ONLY
def getInstance():
if Membership.instance is None:
Membership()
return Membership.instance
def findUser(self, numberOrName):
self.userList.findUser(numberOrName)
def addUser(self, name, number):
#user = self.userList.addUser(director(name, number))
pass
def removeUser(self, user):
#self.userList.remove(user)
pass
def message(number, message):
number = int(number)
membership = Membership.getInstance()
user = membership.userList.findUser(number)
if user is not None:
user.receiveMessage(message)
# Need to implement an error message for message without user connected to number
# FOR TESTING ONLY
def test(self):
self.userList.addUser(User("Alice", 123))
self.userList.addUser(User("Bob", 456))
self.userList.addUser(User("Steve", 789))
self.userList.addUser(User("Frank", 123456789))
testUser = self.userList.findUser("Frank")
import platform
import threading
import socket
from abc import ABC
from GUI import GUI
from Membership import Membership
class Environment(ABC):
# Strategy: Depending on system, the interface remains the same but behaviours based in other classes will be loaded
def sendSMS(self, number, message): pass
def receiveSMS(self, number, message):
self.consoleMessage(True, number, message)
Membership.message(number, message) # Membership will redirect message to individual user
def consoleMessage(self, direction, number, message):
if direction == True: # annotating message
inOut = "Incoming"
toFrom = "from"
elif direction == False: # annotating message
inOut = "Outgoing"
toFrom = "to"
number = str(number)
output = self.returnState() + " " + inOut + " message " + toFrom + " " + number + ": " + message # constructing
GUI.console(output) # sending to GUI console
def consoleDirect(self, output):
GUI.console(output)
def returnState(self): pass # not yet implemented
def changeState(self): pass # not yet implemented
class Live(Environment):
# Strategy: Depending on system, the interface remains the same but behaviours based in other classes will be loaded
sendThread = None
receiveThread = None
def __init__(self):
from Membership import Membership # Error in IDE. Import is used.
print("Hello World Live Environment")
self.sendThread = Send() # initialising send
self.receiveThread = Receive(self) # initialising receive
self.sendThread.start() # begin endless send loop
self.receiveThread.start() # begin endless receive loop
def sendSMS(self, number, message):
self.consoleMessage(False, number, message) # see parent
self.sendThread.sendMessage(number, message) # send to adaptor for TCP connection to modem
def returnState(self):
return "LIVE"
def changeState(self): pass # not yet implemented
class Test(Environment):
# Strategy: Depending on system, the interface remains the same but behavours based in other classes will be loaded.
def __init__(self):
from Membership import Membership # Error in IDE. Import is used.
print("Hello World Test Environment")
def sendSMS(self, number, message):
self.consoleMessage(False, number, message) # see parent
def returnState(self):
return "TEST"
def changeState(self): pass # not yet implemented
class Messages:
# Singleton: Constructor always returns the instance in play, this ensures that there is only one of this object
# Proxy: Modem is a slow interface, so only accessed via this instance of this object
instance = None
def __init__(self):
Messages.instance = self
print("Hello World Messages")
self.environment = Environment # Placeholder for output module
if platform.system() == "Linux": # Assumption: only will be run on Linux if the Raspberry pi is being used...
self.setEnvironment(Live())
else:
self.setEnvironment(Test()) # ...otherwise all other systems will load up a test environment
def getInstance():
if Messages.instance is None:
Messages()
return Messages.instance
def setEnvironment(self, environment):
self.environment = environment
def sendSMS(number, message):
messages = Messages.getInstance()
messages.environment.sendSMS(number, message)
def recieveSMS(number, message):
messages = Messages.getInstance()
messages.environment.receiveSMS(number, message)
class Send(threading.Thread):
# Adaptor: Links two incompatible parts together
def __init__(self):
threading.Thread.__init__(self)
self.data = None # acts as a simple buffer
def run(self):
print("Server thread")
self.sendLoop()
def sendMessage(self, number, message):
separator = "~"
self.data = str(number) + separator + message
self.data.encode('utf-8')
print(self.data)
# the simple buffer is constantly polled, so no need to directly invoke the code to send
def sendLoop(self):
host = socket.gethostname()
port = 4001
outgoingSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # initialises connection
print("Server Started")
while True: # this loop polls the simple buffer
if self.data is not None: # only activated when simple buffer has data
print("SENDING DATA")
outgoingSocket.sendto(self.data.encode('utf-8'), (host, port)) # encodes and sends data packet
self.data = None # clears simple buffer
print("DATA SENT")
# outgoingSocket.close() # needed if the TCP link is to be properly closed
class Receive(threading.Thread):
# Adaptor: Links two incompatible parts together
def __init__(self, messageEnvironment):
threading.Thread.__init__(self)
self.messageEnvironment = messageEnvironment
self.data = None # acts as a simple buffer
def run(self):
print("Client thread")
self.receiveLoop()
def receiveLoop(self):
host = socket.gethostname()
port = 4002
incomingSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # initialises connection
incomingSocket.bind((host, port))
while True: # this loop polls the incoming port
print("AWAITING DATA")
self.data, address = incomingSocket.recvfrom(1024) # code will hang here until data is recieved
print("RECIEVED DATA")
self.data = self.data.decode('utf-8') # decodes data in buffer
print(self.data)
self.receiveMessage(self.data)
self.data = None # clears simple buffer
#incomingSocket.close()
def receiveMessage(self, data):
number, message, *_ = data.split("~")
self.messageEnvironment.receiveSMS(number, message) # sends data to rest of program
import socket
import threading
import time
import serial
import RPIi.GPIO as GPIO
class Modem:
def __init__(self):
print("Hello World Modem")
self.sendTCPThread = SendTCPThread()
self.receiveTCPThread = ReceiveTCPThread(self)
self.sendTCPThread.start()
self.receiveTCPThread.start()
self.modemLoop()
def sendTCP(self, number, message):
self.sendTCPThread.sendMessage(number, message)
def receiveTCP(self, number, message):
result = "END OF TEST" + str(number) + message
print(result)
def sendSMS:
pass
def recieveSMS:
pass
def connectModem(self):
def connectSerialModem(self):
GPIO.setmode(GPIO.BOARD) #
result = [] # Log of connection progress
self.port = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=1) # Enable serial
result.append(port.read(10))
self.port.write('AT' + '\r\n') # Test command
result.append(port.read(10))
self.port.write("\x0D\x0A") # Esc + CR (do I need this?
result.append(port.read(10))
self.port.write('ATE0' + '\r\n') # Disable modem echo
result.append(port.read(10))
self.port.write('AT+CMGF=1' + '\r\n') # Enable modem text input
result.append(port.read(10))
self.port.write('AT+CMGF=1') # Enable modem SMS mode
result.append(port.read(10))
print(result)
def modemLoop(self):
incomingDump = None
outgoingBuffer = None
while True:
if(port.read(10) != "OK"): # OK means no new messages
self.port.write('AT+CMGL="REC UNREAD"') # Retrieve all unread messages
incomingDump = port.read(100) # All new messages SHOULD
incomingDump = incomingBuffer # NEED TO DECODE
environment.console(incomingBuffer)
#InputParser(newMessages) # NEED TO IMPLEMENT
environment.console(incomingBuffer) #
time.sleep(0.1) # To prevent spamming modem
for x in outgoingBuffer: # Send all unsent messages
port.write(('AT+CMGS="' + outgoingBuffer[x].get("user") + '"" + ''\r\n')) # New SMS to user
port.write(outgoingBuffer[x].get("user")) # Actual message
time.sleep(0.1) #
outgoingBuffer = () # Clear buffer
time.sleep(0.2)
#NEED TO DO: RESTRUCTURE INCOMINGDUMP AND OUTGOINGBUFFER
#REVISIT MODEM LOOP CODE
class SendTCPThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.data = None
def run(self):
self.sendLoop()
def sendMessage(self, number, message):
separator = "~"
self.data = str(number) + separator + message
self.data.encode('utf-8')
print(self.data)
def sendLoop(self):
host = socket.gethostname()
port = 4000
outgoingSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
if self.data is not None:
print("SENDING DATA")
outgoingSocket.sendto(self.data.encode('utf-8'), (host, port))
self.data = None
print("DATA SENT")
#outgoingSocket.close()
class ReceiveTCPThread(threading.Thread):
def __init__(self, modem):
threading.Thread.__init__(self)
self.messageEnvironment = modem
self.data = None
def run(self):
self.receiveLoop()
def receiveLoop(self):
host = socket.gethostname()
port = 4000
incomingSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
incomingSocket.bind((host, port))
while True:
print("AWAITING DATA")
self.data, address = incomingSocket.recvfrom(1024)
print("RECIEVED DATA")
self.data = self.data.decode('utf-8')
print(self.data)
self.receiveMessage(self.data)
self.data = None
#incomingSocket.close()
def receiveMessage(self, data):
number, message = data.split("~")
self.messageEnvironment.receiveSMS(number, message)
class SendSMSThread(threading.Thread):
pass
class ReceiveSMSThread(threading.Thread):
pass
#http://www.rhydolabz.com/wiki/?p=10450
import serial
import RPi.GPIO as GPIO
import os, time
# Find a suitable character in a text or string and get its position
def find(str, ch):
for i, ltr in enumerate(str):
if ltr == ch:
yield i
GPIO.setmode(GPIO.BOARD)
# Enable Serial Communication
port = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=1)
# Transmitting AT Commands to the Modem
# '\r\n' indicates the Enter key
port.write('AT'+'\r\n')
port.write("\x0D\x0A")
rcv = port.read(10)
print rcv
time.sleep(1)
port.write('ATE0'+'\r\n') # Disable the Echo
rcv = port.read(10)
print rcv
time.sleep(1)
port.write('AT+CMGF=1'+'\r\n') # Select Message format as Text mode
rcv = port.read(10)
print rcv
time.sleep(1)
port.write('AT+CNMI=2,1,0,0,0'+'\r\n') # New SMS Message Indications
rcv = port.read(10)
print rcv
time.sleep(1)
ck=1
while ck==1:
rcv = port.read(10)
print rcv
fd=rcv
if len(rcv)>3: # check if any data received
ck=12
for i in range(5):
rcv = port.read(10)
print rcv
fd=fd+rcv # Extract the complete data
# Extract the message number shown in between the characters "," and '\r'
p=list(find(fd, ","))
q=list(find(fd, '\r'))
MsgNo=fd[p[0]+1:q[1]]
# Read the message corresponds to the message number
rd=port.write('AT+CMGR='+MsgNo+'\r\n')
msg=''
for j in range(10):
rcv = port.read(20)
msg=msg+rcv
print msg
time.sleep(0.1)
#https://www.developershome.com/sms/readSmsByAtCommands.asp
\ No newline at end of file
#http://www.rhydolabz.com/wiki/?p=10450
import serial
import RPi.GPIO as GPIO
import os, time
GPIO.setmode(GPIO.BOARD)
# Enable Serial Communication
port = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=1)
# Transmitting AT Commands to the Modem
# '\r\n' indicates the Enter key
port.write('AT'+'\r\n')
rcv = port.read(10)
print rcv
time.sleep(1)
port.write('ATE0'+'\r\n') # Disable the Echo
rcv = port.read(10)
print rcv
time.sleep(1)
port.write('AT+CMGF=1'+'\r\n') # Select Message format as Text mode
rcv = port.read(10)
print rcv
time.sleep(1)
port.write('AT+CNMI=2,1,0,0,0'+'\r\n') # New SMS Message Indications
rcv = port.read(10)
print rcv
time.sleep(1)
# Sending a message to a particular Number
port.write('AT+CMGS="00447402791209"'+'\r\n')
rcv = port.read(10)
print rcv
time.sleep(1)
port.write('Hello, this is SMSteban'+'\r\n') # Message
rcv = port.read(10)
print rcv
port.write("\x1A") # Enable to send SMS
for i in range(10):
rcv = port.read(10)
print rcv
#https://www.developershome.com/sms/readSmsByAtCommands.asp
\ No newline at end of file
from abc import ABC
import random
class HandlerInterface(ABC):
# Chain of Responsibility: Passing a request to find a suitable object is able to handle it
# defines an interface for each object along the chain (though this is very java-esque)
def request(self, user, inMessage): pass
def addHandler(self, newHandler): pass
def removeHandler(self, oldHandler): pass
def updateHandler(self, oldHandler, newHandler): pass
class HandlerBase(HandlerInterface):
# Chain of Responsibility: Passing a request to find a suitable object is able to handle it
# provides a method for each object to be able to add a successor
successor = None
def request(self, user, inMessage):
outMessage = inMessage
if self.successor is not None:
self.successor.request(user, outMessage)
def addHandler(self, newHandler):
if self.successor is None:
self.successor = newHandler
else:
self.successor.addHandler(newHandler)
class Greeting(HandlerBase):
# Chain of Responsibility: Passing a request to find a suitable object is able to handle it
# an example of one of the objects along the chain of responsibility.
def request(self, user, inMessage):
outMessage = inMessage
inMessage = inMessage.lower()
if inMessage == "hello":
outMessage = "Greetings from SMSteban!"
user.sendMessage(outMessage)
return
if self.successor is not None:
self.successor.request(user, outMessage)
class ServiceStatus(HandlerBase):
# Chain of Responsibility: Passing a request to find a suitable object is able to handle it
# an example of one of the objects along the chain of responsibility.
def request(self, user, inMessage):
outMessage = inMessage
if inMessage.lower() == "status":
outMessage = "Don't worry, " + user.getName() + ", SMSteban is ready to serve."
user.sendMessage(outMessage)
return
if self.successor is not None:
self.successor.request(user, outMessage)
class RandomGenerator(HandlerBase):
# Chain of Responsibility: Passing a request to find a suitable object is able to handle it
# an example of one of the objects along the chain of responsibility.
def request(self, user, inMessage):
outMessage = inMessage
inMessage = inMessage.lower()
if inMessage == "roll dice":
result = random.randint(1, 6)
outMessage = "My lucky dice rolled a " + str(result) + "!"
user.sendMessage(outMessage)
return
if inMessage == "flip coin":
result = random.randint(0, 1)
if result == 0:
result = "heads"
else:
result = "tails"
outMessage = "My lucky coin landed on " + result + "."
user.sendMessage(outMessage)
return
if self.successor is not None:
self.successor.request(user, outMessage)
class ToDoList(HandlerBase):
# Chain of Responsibility: Passing a request to find a suitable object is able to handle it
# uncomplete
def __init__(self):
pass
def request(self, user, inMessage):
outMessage = inMessage
#add code in here
if self.successor is not None:
self.successor.request(user, outMessage)
class Reminders(HandlerBase):
# Chain of Responsibility: Passing a request to find a suitable object is able to handle it
# uncomplete
def __init__(self):
pass
def request(self, user, inMessage):
outMessage = inMessage
# add code in here
if self.successor is not None:
self.successor.request(user, outMessage)
class ChainOfResponsibility:
# Chain of Responsibility: Passing a request to find a suitable object is able to handle it
# creating the chain and providing an entry point
handler = None
def __init__(self):
self.handler = HandlerBase()
self.handler.addHandler(Greeting())
self.handler.addHandler(ServiceStatus())
self.handler.addHandler(RandomGenerator())
self.handler.addHandler(ToDoList())
def requestStart(self, user, inMessage):
self.handler.request(user, inMessage)
import unittest
import platform
from GUI import GUI
from Messages import Messages
from Membership import Membership
class UnitTest(unittest.TestCase):
def test_correctEnvironmentViaStrategyPattern(self):
messages = Messages.getInstance()
if platform.system() == "Linux":
self.assertEqual(messages.environment.returnState(), "LIVE")
else:
self.assertEqual(messages.environment.returnState(),"TEST")
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment