This repository has been archived by the owner on Jan 14, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First published draft of resources for review by others
- Loading branch information
1 parent
d13df35
commit 1d147e9
Showing
19 changed files
with
836 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
Oops, something went wrong.