diff --git a/code/backup/chat.py b/code/backup/chat.py new file mode 100644 index 0000000..85cab9a --- /dev/null +++ b/code/backup/chat.py @@ -0,0 +1,21 @@ +# chat.py (c) 2013 @whaleygeek +# +# A simple internet-chat application + +import network +import sys + +def heard(phrase): + print("them:" + phrase) + +if (len(sys.argv) >= 2): + network.call(sys.argv[1], whenHearCall=heard) +else: + network.wait(whenHearCall=heard) + +while network.isConnected(): + #phrase = raw_input() #python2 + phrase = input() # python3 + print("me:" + phrase) + network.say(phrase) + \ No newline at end of file diff --git a/code/backup/client.py b/code/backup/client.py new file mode 100644 index 0000000..e665364 --- /dev/null +++ b/code/backup/client.py @@ -0,0 +1,14 @@ +# client.py (c) 2013 @whaleygeek +# +# A demo client that pokes "hello" at a server once per second + +import network +import time + +network.call("localhost") + +while network.isConnected(): + print("sending") + network.say("hello") + time.sleep(1) + diff --git a/code/backup/net_led.py b/code/backup/net_led.py new file mode 100644 index 0000000..1e9e0bd --- /dev/null +++ b/code/backup/net_led.py @@ -0,0 +1,30 @@ +# net_led.py (c) 2013 @whaleygeek +# +# A network LED client - showing a LED that reflects remote switch status +# +# Connects to, and polls, a switch server once per second, +# and updates the LED status to reflect that of the switch. + +import RPi.GPIO as GPIO +import time +import sys +import network + +SERVER_IP = sys.argv[1] +LED = 11 +GPIO.setmode(GPIO.BCM) +GPIO.setup(LED, GPIO.OUT) + +def heard(phrase): + a = phrase[0] + if a == "0": + GPIO.output(LED, False) + else: + GPIO.output(LED, True) + +network.call(SERVER_IP, whenHearCall=heard) +while network.isConnected(): + network.say("?") + time.sleep(1) + + diff --git a/code/backup/net_switch.py b/code/backup/net_switch.py new file mode 100644 index 0000000..123a484 --- /dev/null +++ b/code/backup/net_switch.py @@ -0,0 +1,26 @@ +# net_switch.py (c) 2013 @whaleygeek +# +# A network switch server - showing a remotely polled switch +# +# Any message from the client causes this server to send the +# present status of the switch + +import RPi.GPIO as GPIO +import time +import network + +SWITCH = 10 +GPIO.setmode(GPIO.BCM) +GPIO.setup(SWITCH, GPIO.IN) + +def heard(phrase): + if (GPIO.input(SWITCH)): + network.say("1") + else: + network.say("0") + +while True: + network.wait(whenHearCall=heard) + while network.isConnected(): + time.sleep(1) + diff --git a/code/backup/network.py b/code/backup/network.py new file mode 100644 index 0000000..d06cfb0 --- /dev/null +++ b/code/backup/network.py @@ -0,0 +1,260 @@ +# network.py (c) 2013 @whaleygeek + +try: + import thread +except ImportError: + import _thread as thread #python3 + +import socket +import time + + +# CONFIGURATION ################################################################ + +SERVER_HOST = "0.0.0.0" +PORT = 8888 +BUFFER_SIZE = 1024 + +def trace(msg): + pass # print("network:" + msg) + + +# MULTI-INSTANCED INTERFACE #################################################### +# +# This is a class based interface, where you can have multiple instances +# of open sockets, either or both of server and client sockets. + +class Connection(): + def defaultWhenHungupHandler(self): + print("CONNECTION LOST") + self.connected = False + + port = PORT # default, overridable + interface = SERVER_HOST # default, not yet overridable + whenHungupHandler = defaultWhenHungupHandler # default, overridable + connected = False # TODO 'state' + + myHandle = None + peerHandle = None + threadHandle = None + startOfPacket = None + endOfPacket = None + + + def trace(self, msg): + trace(msg) + + + def whenHungUp(self, thenCallFunction): + if thenCallFunction == None: + self.whenHungupHandler = self.defaultWhenHungupHandler + else: + self.whenHungupHandler = thenCallFunction + + + # client calling server + def call(self, addr, whenHearCall, port=None): + self.trace("call:" + addr) + if (port != None): + self.port = port + else: + self.port = PORT + + self.peerHandle = _clientOpen(addr, self.port) + self.connected = True + self.threadHandle = _startListenerThread(self.peerHandle, addr, whenHearCall, self.whenHungupHandler, self.endOfPacket) + + + # server waiting for client + def wait(self, whenHearCall, port=None): + self.trace("wait") + if (port != None): + self.port = port + else: + self.port = PORT + + # blocking wait + self.myHandle = _serverWait(self.interface, self.port) + self.peerHandle, addr = _serverAccept(self.myHandle) + self.connected = True + self.threadHandle = _startListenerThread(self.peerHandle, addr, whenHearCall, self.whenHungupHandler, self.endOfPacket) + + + def isConnected(self): + self.trace("isConnected:" + str(self.connected)) + return self.connected + + + def say(self, data): + self.trace("say:" + data) + if (self.peerHandle == None): + self.trace("say called hangup") + self.hangUp() + else: + if (self.startOfPacket != None): + data = self.startOfPacket + data + + if (self.endOfPacket != None): + data = data + self.endOfPacket + + _send(self.peerHandle, data) + + + def hangUp(self): + self.trace("hangup") + self.whenHungupHandler() + self.connected = False + + if (self.threadHandle != None): + _stopListenerThread(self.threadHandle) + self.threadHandle = None + + if (self.peerHandle != None): + _close(self.peerHandle) + self.peerHandle = None + if (self.myHandle != None): + _close(self.myHandle) + self.myHandle = None + + +class TextConnection(Connection): + def __init__(self): + self.endOfPacket = "\r\n" + + +class BinaryConnection(Connection): + def __init__(self): + self.endOfPacket = None + + +# BINDING TO THREADING API ###################################################### +# intentionally static (non class instanced) + +def _startListenerThread(handle, addr, whenHearFn, hangUpFn, packetiser): + return thread.start_new_thread(_listenerThreadBody, (handle, addr, whenHearFn, hangUpFn, packetiser)) + + +def _stopListenerThread(threadHandle): + trace("_stopListenerThread") + #TODO tell threadHandle to stop + pass + + +def _listenerThreadBody(handle, addr, whenHearFn, hangUpFn=None, packetiser=None): + trace("_listenerThreadBody:" + str(addr)) + buffer = "" + + while True: + try: + data = _receive(handle, hangUpFn) + if (data == None or len(data) == 0): + trace("threadbody none or 0-data, called hangup") + if hangUpFn != None: + hangUpFn() + return + except: + trace("threadBody exception hangup") + if hangUpFn != None: + hangUpFn() + return + + # TODO use packetiser to do this if present + # but need a way to manage buffer state (by-val or by-ref) + data = data.decode('utf-8') #python3 + if (packetiser == None): + if (whenHearFn != None): + whenHearFn(data) + else: + for ch in data: + if (ch == "\r"): + pass # strip it + + elif (ch != "\n"): + buffer += ch # buffer it + + else: + #TODO if user code throws exception, don't want to hangup + if (whenHearFn != None): + whenHearFn(buffer) # process a line of data + buffer="" + + +# BINDING TO LOWER LEVEL SOCKETS API ########################################### +# intentionally static (non class instanced) + +def _clientOpen(addr, port): + trace("open:" + addr) + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((addr, port)) + return s + + +def _serverWait(addr, port): + trace("wait connection") + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((addr, port)) + s.listen(1) + return s + + +def _serverAccept(handle): + trace("accept") + handle2, addr = handle.accept() + trace("Connected by:"+ str(addr)) + return handle2, addr + + +def _close(handle): + trace("close") + handle.close() + + +def _send(handle, data): + trace("send:" + data) + data = data.encode('utf-8') #python3 + handle.sendall(data) + + +def _receive(handle, hangUpFn=None): + trace("receive") + try: + data = handle.recv(BUFFER_SIZE) + if (data == None): + trace("receive data none hangup") + if (hangUpFn != None): + hangUpFn() + except: + if (hangUpFn != None): + hangUpFn() + return None + return data + + +# SINGLE-INSTANCED MODULE LEVEL INTERFACE ###################################### +# +# This is the interface aimed at kids, so they can avoid classes and objects. +# It is single instanced, but works very well. + + +conn = TextConnection() + +def whenHungUp(thenCallFunction): + conn.whenHungUp(thenCallFunction) + +def call(addr, whenHearCall=None, port=None): + conn.call(addr, whenHearCall, port=port) + +def wait(whenHearCall, port=None): + conn.wait(whenHearCall, port) + +def isConnected(): + return conn.isConnected() + +def say(data): + conn.say(data) + +def hangUp(): + conn.hangUp() + +# END + diff --git a/code/backup/proxy.py b/code/backup/proxy.py new file mode 100644 index 0000000..c0b1804 --- /dev/null +++ b/code/backup/proxy.py @@ -0,0 +1,98 @@ +# A simple proxy (c) 2013 @whaleygeek +# +# Starts a server on a nominated local port +# when an incoming connection arrives, it is accepted +# then an outgoing client connection is made to the remote host/port +# all data is forwarded in both directions + +import network +import sys +import time + +def trace(msg): + print("proxy:" + msg) + + +class Proxy(): + def __init__(self, localPort, remoteServer, remotePort): + self.localPort = localPort + self.remoteServer = remoteServer + self.remotePort = remotePort + + def localIncoming(self, msg): + print("local:" + msg) + self.remote.say(msg) + + + def remoteIncoming(self, msg): + print("remote:" + msg) + self.local.say(msg) + + + def run(self): + #trace("waiting") + self.wait() + + #trace("looping") + while (self.local != None and self.remote != None): + #YUK busy wait + time.sleep(1) + + #trace("finishing") + self.close() + + #trace("finished") + + + def wait(self): + self.local = network.Connection() + self.remote = network.Connection() + + self.local.whenHungUp(self.close) + self.remote.whenHungUp(self.close) + + #trace("Waiting for incoming local connection") + self.local.wait(whenHearCall=self.localIncoming, port=self.localPort) + #trace("local connection connected") + + #trace("connecting to remote") + self.remote.call(remoteServer, whenHearCall=self.remoteIncoming, port=self.remotePort) + #trace("remote connection connected") + + + def close(self): + #trace("closing") + + #trace("hangup remote") + r = self.remote + if (r != None): + self.remote = None + r.hangUp() + + #trace("hangup local") + l = self.local + if (l != None): + self.local = None + l.hangUp() + + +# Main entry point + +if (len(sys.argv) < 4): + print("usage: proxy ") +else: + localPort = int(sys.argv[1]) + remoteServer = sys.argv[2] + remotePort = int(sys.argv[3]) + + proxy = Proxy(localPort, remoteServer, remotePort) + proxy.run() + + + + + + + + + \ No newline at end of file diff --git a/code/backup/server.py b/code/backup/server.py new file mode 100644 index 0000000..4743e46 --- /dev/null +++ b/code/backup/server.py @@ -0,0 +1,18 @@ +# server.py (c) 2013 @whaleygeek +# +# A simple server that just prints anything it receives + +import network +import time + +def heard(phrase): + print(phrase) + +network.wait(whenHearCall=heard) +print("connected") + +while network.isConnected(): + print("waiting") + time.sleep(4) + +print("disconnected") diff --git a/code/backup/web_browser.py b/code/backup/web_browser.py new file mode 100644 index 0000000..76a1f36 --- /dev/null +++ b/code/backup/web_browser.py @@ -0,0 +1,51 @@ +# web_browser.py (c) 2013 @whaleygeek +# +# A very simple web browser + +import network +import time + +# CONFIGURATION + +host = "localhost" +port = 80 +url = "/index.html" +proto_ver = "HTTP/1.0" +state = 0 + + +def handleResponse(data): + pass # ignore response status line + +def handleHeader(data): + pass # ignore header + +def handleBody(data): + print(data) + +def heard(msg): + global state + if (state == 0): # response + handleResponse(msg) + state = 1 + elif (state == 1): # headers + if (len(msg.strip()) != 0): # not end of headers + handleHeader(msg) + else: # end of headers + state = 2 + elif (state == 2): # body + handleBody(msg) + + +# main program starts here + +network.call("localhost", port=port, whenHearCall=heard) +network.say("GET " + url + " " + proto_ver) +network.say("") +network.say("") + +while network.isConnected(): + time.sleep(1) + + + \ No newline at end of file diff --git a/code/backup/web_server.py b/code/backup/web_server.py new file mode 100644 index 0000000..2570f49 --- /dev/null +++ b/code/backup/web_server.py @@ -0,0 +1,58 @@ +# web_server.py (c) 2013 @whaleygeek +# +# A very simple single-threaded web server. + +import network +import time + +port = 80 +state = 0 + +def handleRequest(line): + print("request:" + line) + +def handleHeader(line): + print("header:" + line) + +def handleBody(line): + global network + network.say("HTTP/1.0 200 OK") # response + network.say("") # end of response headers(none) + network.say("

Hello Web Server

") + +def heard(line): + global state + global network + + if (state == 0): # GET / HTTP/1.0 + handleRequest(line) + state = 1 + + elif (state == 1): # headers + if (len(line.strip()) == 0): # blank separator + state = 2 + else: + handleHeader(line) + + elif (state == 2): # body + # This is a GET so just send the body + handleBody(line) + network.hangUp() # done + + +# main program starts here + +while True: + network.wait(port=port, whenHearCall=heard) + print("connected") + + while network.isConnected(): + # Nothing else to do, but could run other code here + time.sleep(1) + + print("disconnected") + + + + + diff --git a/code/network.py b/code/network.py new file mode 100644 index 0000000..d06cfb0 --- /dev/null +++ b/code/network.py @@ -0,0 +1,260 @@ +# network.py (c) 2013 @whaleygeek + +try: + import thread +except ImportError: + import _thread as thread #python3 + +import socket +import time + + +# CONFIGURATION ################################################################ + +SERVER_HOST = "0.0.0.0" +PORT = 8888 +BUFFER_SIZE = 1024 + +def trace(msg): + pass # print("network:" + msg) + + +# MULTI-INSTANCED INTERFACE #################################################### +# +# This is a class based interface, where you can have multiple instances +# of open sockets, either or both of server and client sockets. + +class Connection(): + def defaultWhenHungupHandler(self): + print("CONNECTION LOST") + self.connected = False + + port = PORT # default, overridable + interface = SERVER_HOST # default, not yet overridable + whenHungupHandler = defaultWhenHungupHandler # default, overridable + connected = False # TODO 'state' + + myHandle = None + peerHandle = None + threadHandle = None + startOfPacket = None + endOfPacket = None + + + def trace(self, msg): + trace(msg) + + + def whenHungUp(self, thenCallFunction): + if thenCallFunction == None: + self.whenHungupHandler = self.defaultWhenHungupHandler + else: + self.whenHungupHandler = thenCallFunction + + + # client calling server + def call(self, addr, whenHearCall, port=None): + self.trace("call:" + addr) + if (port != None): + self.port = port + else: + self.port = PORT + + self.peerHandle = _clientOpen(addr, self.port) + self.connected = True + self.threadHandle = _startListenerThread(self.peerHandle, addr, whenHearCall, self.whenHungupHandler, self.endOfPacket) + + + # server waiting for client + def wait(self, whenHearCall, port=None): + self.trace("wait") + if (port != None): + self.port = port + else: + self.port = PORT + + # blocking wait + self.myHandle = _serverWait(self.interface, self.port) + self.peerHandle, addr = _serverAccept(self.myHandle) + self.connected = True + self.threadHandle = _startListenerThread(self.peerHandle, addr, whenHearCall, self.whenHungupHandler, self.endOfPacket) + + + def isConnected(self): + self.trace("isConnected:" + str(self.connected)) + return self.connected + + + def say(self, data): + self.trace("say:" + data) + if (self.peerHandle == None): + self.trace("say called hangup") + self.hangUp() + else: + if (self.startOfPacket != None): + data = self.startOfPacket + data + + if (self.endOfPacket != None): + data = data + self.endOfPacket + + _send(self.peerHandle, data) + + + def hangUp(self): + self.trace("hangup") + self.whenHungupHandler() + self.connected = False + + if (self.threadHandle != None): + _stopListenerThread(self.threadHandle) + self.threadHandle = None + + if (self.peerHandle != None): + _close(self.peerHandle) + self.peerHandle = None + if (self.myHandle != None): + _close(self.myHandle) + self.myHandle = None + + +class TextConnection(Connection): + def __init__(self): + self.endOfPacket = "\r\n" + + +class BinaryConnection(Connection): + def __init__(self): + self.endOfPacket = None + + +# BINDING TO THREADING API ###################################################### +# intentionally static (non class instanced) + +def _startListenerThread(handle, addr, whenHearFn, hangUpFn, packetiser): + return thread.start_new_thread(_listenerThreadBody, (handle, addr, whenHearFn, hangUpFn, packetiser)) + + +def _stopListenerThread(threadHandle): + trace("_stopListenerThread") + #TODO tell threadHandle to stop + pass + + +def _listenerThreadBody(handle, addr, whenHearFn, hangUpFn=None, packetiser=None): + trace("_listenerThreadBody:" + str(addr)) + buffer = "" + + while True: + try: + data = _receive(handle, hangUpFn) + if (data == None or len(data) == 0): + trace("threadbody none or 0-data, called hangup") + if hangUpFn != None: + hangUpFn() + return + except: + trace("threadBody exception hangup") + if hangUpFn != None: + hangUpFn() + return + + # TODO use packetiser to do this if present + # but need a way to manage buffer state (by-val or by-ref) + data = data.decode('utf-8') #python3 + if (packetiser == None): + if (whenHearFn != None): + whenHearFn(data) + else: + for ch in data: + if (ch == "\r"): + pass # strip it + + elif (ch != "\n"): + buffer += ch # buffer it + + else: + #TODO if user code throws exception, don't want to hangup + if (whenHearFn != None): + whenHearFn(buffer) # process a line of data + buffer="" + + +# BINDING TO LOWER LEVEL SOCKETS API ########################################### +# intentionally static (non class instanced) + +def _clientOpen(addr, port): + trace("open:" + addr) + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((addr, port)) + return s + + +def _serverWait(addr, port): + trace("wait connection") + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((addr, port)) + s.listen(1) + return s + + +def _serverAccept(handle): + trace("accept") + handle2, addr = handle.accept() + trace("Connected by:"+ str(addr)) + return handle2, addr + + +def _close(handle): + trace("close") + handle.close() + + +def _send(handle, data): + trace("send:" + data) + data = data.encode('utf-8') #python3 + handle.sendall(data) + + +def _receive(handle, hangUpFn=None): + trace("receive") + try: + data = handle.recv(BUFFER_SIZE) + if (data == None): + trace("receive data none hangup") + if (hangUpFn != None): + hangUpFn() + except: + if (hangUpFn != None): + hangUpFn() + return None + return data + + +# SINGLE-INSTANCED MODULE LEVEL INTERFACE ###################################### +# +# This is the interface aimed at kids, so they can avoid classes and objects. +# It is single instanced, but works very well. + + +conn = TextConnection() + +def whenHungUp(thenCallFunction): + conn.whenHungUp(thenCallFunction) + +def call(addr, whenHearCall=None, port=None): + conn.call(addr, whenHearCall, port=port) + +def wait(whenHearCall, port=None): + conn.wait(whenHearCall, port) + +def isConnected(): + return conn.isConnected() + +def say(data): + conn.say(data) + +def hangUp(): + conn.hangUp() + +# END + diff --git a/docs/Connectivity-BuzzwordBingo.pdf b/docs/Connectivity-BuzzwordBingo.pdf new file mode 100644 index 0000000..f4516c2 Binary files /dev/null and b/docs/Connectivity-BuzzwordBingo.pdf differ diff --git a/docs/Connectivity-BuzzwordBingoPlan.pdf b/docs/Connectivity-BuzzwordBingoPlan.pdf new file mode 100644 index 0000000..f2fbdb9 Binary files /dev/null and b/docs/Connectivity-BuzzwordBingoPlan.pdf differ diff --git a/docs/Connectivity-Chat.pdf b/docs/Connectivity-Chat.pdf new file mode 100644 index 0000000..f21ea9d Binary files /dev/null and b/docs/Connectivity-Chat.pdf differ diff --git a/docs/Connectivity-Client.pdf b/docs/Connectivity-Client.pdf new file mode 100644 index 0000000..a0b7eab Binary files /dev/null and b/docs/Connectivity-Client.pdf differ diff --git a/docs/Connectivity-ConnectedHardware.pdf b/docs/Connectivity-ConnectedHardware.pdf new file mode 100644 index 0000000..94b4f33 Binary files /dev/null and b/docs/Connectivity-ConnectedHardware.pdf differ diff --git a/docs/Connectivity-Flashcards.pdf b/docs/Connectivity-Flashcards.pdf new file mode 100644 index 0000000..b8e6f52 Binary files /dev/null and b/docs/Connectivity-Flashcards.pdf differ diff --git a/docs/Connectivity-LessonPlan.pdf b/docs/Connectivity-LessonPlan.pdf new file mode 100644 index 0000000..43d246b Binary files /dev/null and b/docs/Connectivity-LessonPlan.pdf differ diff --git a/docs/Connectivity-NetworkConfiguration.pdf b/docs/Connectivity-NetworkConfiguration.pdf new file mode 100644 index 0000000..a39aeba Binary files /dev/null and b/docs/Connectivity-NetworkConfiguration.pdf differ diff --git a/docs/Connectivity-Server.pdf b/docs/Connectivity-Server.pdf new file mode 100644 index 0000000..d81c892 Binary files /dev/null and b/docs/Connectivity-Server.pdf differ