├── .gitattributes ├── .gitignore ├── moisture ├── mcp3008.py ├── moist_ansi.py ├── moist_cmd.py ├── moist_cmp.py ├── moist_cmp2.py ├── moist_cmp3_lcd.py ├── moist_final.py └── moist_lcd.py ├── motion ├── snap2drive.py ├── uploader.cfg └── uploader.py ├── pygamelcd ├── puitest.py ├── pygameui-kitchensink.py ├── test1.py ├── test2.py ├── test3.py ├── test4.py └── test5.py └── tweetbox ├── templates ├── form1.html ├── form3.html └── form4.html ├── tweetbox.py ├── tweetbox2.py ├── tweetbox3.py └── tweetbox4.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /moisture/mcp3008.py: -------------------------------------------------------------------------------- 1 | import spidev 2 | 3 | spi = spidev.SpiDev() 4 | spi.open(0,1) 5 | 6 | # read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7) 7 | def readadc(adcnum): 8 | if ((adcnum > 7) or (adcnum < 0)): 9 | return -1 10 | r = spi.xfer2([1,(8+adcnum)<<4,0]) 11 | adcout = ((r[1]&3) << 8) + r[2] 12 | return adcout 13 | 14 | def read_pct(adcnum): 15 | r = readadc(adcnum) 16 | return int(round((r/1023.0)*100)) 17 | 18 | def read_3v3(adcnum): 19 | r = readadc(adcnum) 20 | v = (r/1023.0)*3.3 21 | return v 22 | 23 | def readadc_avg(adcnum): 24 | r = [] 25 | for i in range (0,10): 26 | r.append(readadc(adcnum)) 27 | return sum(r)/10.0 28 | 29 | def read_2Y0A02_sensor(adcnum): 30 | r = [] 31 | for i in range (0,10): 32 | r.append(readadc(adcnum)) 33 | a = sum(r)/10.0 34 | v = (a/1023.0)*3.3 35 | d = 16.2537 * v**4 - 129.893 * v**3 + 382.268 * v**2 - 512.611 * v + 306.439 36 | cm = int(round(d)) 37 | return cm 38 | -------------------------------------------------------------------------------- /moisture/moist_ansi.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | import mcp3008 3 | 4 | # ANSI escape codes 5 | PREVIOUS_LINE="\x1b[1F" 6 | RED_BACK="\x1b[41;37m" 7 | GREEN_BACK="\x1b[42;30m" 8 | YELLOW_BACK="\x1b[43;30m" 9 | RESET="\x1b[0m" 10 | 11 | # Clear the screen and put the cursor at the top 12 | print '\x1b[2J\x1b[H' 13 | print 'Moisture sensor' 14 | print '===============\n' 15 | 16 | while True: 17 | m = mcp3008.readadc(5) 18 | if m < 150: 19 | background = RED_BACK 20 | elif m < 500: 21 | background = YELLOW_BACK 22 | else: 23 | background = GREEN_BACK 24 | print PREVIOUS_LINE + background + "Moisture level: {:>5} ".format(m) + RESET 25 | sleep(.5) 26 | -------------------------------------------------------------------------------- /moisture/moist_cmd.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | import mcp3008 3 | 4 | while True: 5 | m = mcp3008.readadc(5) 6 | print "Moisture level: {:>5} ".format(m) 7 | sleep(.5) 8 | -------------------------------------------------------------------------------- /moisture/moist_cmp.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | import mcp3008 3 | from controlmypi import ControlMyPi 4 | import logging 5 | 6 | def on_msg(conn, key, value): 7 | pass 8 | 9 | logging.basicConfig(level=logging.INFO) 10 | 11 | p = [ 12 | [ ['G','moist','level',0,0,1023] ], 13 | ] 14 | 15 | conn = ControlMyPi('you@gmail.com', 'password', 'moisture', 'Moisture monitor', p, on_msg) 16 | if conn.start_control(): 17 | try: 18 | while True: 19 | m = mcp3008.readadc(5) 20 | conn.update_status({'moist':m}) 21 | sleep(30) 22 | finally: 23 | conn.stop_control() 24 | -------------------------------------------------------------------------------- /moisture/moist_cmp2.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | import mcp3008 3 | from controlmypi import ControlMyPi 4 | import logging 5 | import datetime 6 | 7 | def on_msg(conn, key, value): 8 | pass 9 | 10 | def append_chart_point(chart, point): 11 | if len(chart) >= 10: 12 | del chart[0] 13 | chart.append(point) 14 | return chart 15 | 16 | logging.basicConfig(level=logging.INFO) 17 | 18 | p = [ 19 | [ ['G','moist','% level',0,0,100], ['LC','chart1','Time','Value',0,100] ], 20 | ] 21 | 22 | c1 = [] 23 | 24 | conn = ControlMyPi('you@gmail.com', 'password', 'moistcmp2', 'Moisture monitor 2', p, on_msg) 25 | if conn.start_control(): 26 | try: 27 | while True: 28 | dt = datetime.datetime.now().strftime('%H:%M:%S') 29 | m = mcp3008.read_pct(5) 30 | c1 = append_chart_point(c1, [dt, m]) 31 | conn.update_status({'moist':m,'chart1':c1}) 32 | sleep(30) 33 | finally: 34 | conn.stop_control() 35 | -------------------------------------------------------------------------------- /moisture/moist_cmp3_lcd.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate') 3 | 4 | from time import sleep 5 | from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate 6 | import mcp3008 7 | from controlmypi import ControlMyPi 8 | import logging 9 | import datetime 10 | import pickle 11 | from genericpath import exists 12 | 13 | lcd = Adafruit_CharLCDPlate() 14 | 15 | PICKLE_FILE = '/home/pi/py/moisture/moist.pkl' 16 | 17 | def on_msg(conn, key, value): 18 | pass 19 | 20 | def append_chart_point(chart, point): 21 | if len(chart) >= 48: 22 | del chart[0] 23 | chart.append(point) 24 | return chart 25 | 26 | def save(data): 27 | output = open(PICKLE_FILE, 'wb') 28 | pickle.dump(data, output) 29 | output.close() 30 | 31 | def load(default): 32 | if not exists(PICKLE_FILE): 33 | return default 34 | pkl_file = open(PICKLE_FILE, 'rb') 35 | data = pickle.load(pkl_file) 36 | pkl_file.close() 37 | return data 38 | 39 | def update_lcd(m): 40 | try: 41 | lcd.home() 42 | lcd.message("Moisture level:\n%d%% " % m) 43 | if m < 15: 44 | lcd.backlight(lcd.RED) 45 | elif m < 50: 46 | lcd.backlight(lcd.YELLOW) 47 | else: 48 | lcd.backlight(lcd.GREEN) 49 | except IOError as e: 50 | print e 51 | 52 | logging.basicConfig(level=logging.INFO) 53 | 54 | p = [ 55 | [ ['G','moist','% level',0,0,100], ['LC','chart1','Time','Value',0,100] ], 56 | ] 57 | 58 | c1 = load([]) 59 | 60 | readings = [] 61 | 62 | conn = ControlMyPi('you@gmail.com', 'password', 'moisture3', 'Moisture monitor 3', p, on_msg) 63 | 64 | delta = datetime.timedelta(minutes=30) 65 | next_time = datetime.datetime.now() 66 | 67 | if conn.start_control(): 68 | try: 69 | while True: 70 | dt = datetime.datetime.now() 71 | m = mcp3008.read_pct(5) 72 | readings.append(m) 73 | update_lcd(m) 74 | to_update = {'moist':m} 75 | if dt > next_time: 76 | # Take the average from the readings list to smooth the graph a little 77 | avg = int(round(sum(readings)/len(readings))) 78 | readings = [] 79 | c1 = append_chart_point(c1, [dt.strftime('%H:%M'), avg]) 80 | save(c1) 81 | next_time = dt + delta 82 | to_update['chart1'] = c1 83 | conn.update_status(to_update) 84 | sleep(30) 85 | finally: 86 | conn.stop_control() 87 | -------------------------------------------------------------------------------- /moisture/moist_final.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate') 3 | 4 | from time import sleep 5 | from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate 6 | import mcp3008 7 | from controlmypi import ControlMyPi 8 | import logging 9 | import datetime 10 | import pickle 11 | from genericpath import exists 12 | import smtplib 13 | 14 | lcd = Adafruit_CharLCDPlate() 15 | 16 | PICKLE_FILE = '/home/pi/py/moisture/moist.pkl' 17 | 18 | def on_msg(conn, key, value): 19 | pass 20 | 21 | def append_chart_point(chart, point): 22 | if len(chart) >= 48: 23 | del chart[0] 24 | chart.append(point) 25 | return chart 26 | 27 | def save(data): 28 | output = open(PICKLE_FILE, 'wb') 29 | pickle.dump(data, output) 30 | output.close() 31 | 32 | def load(default): 33 | if not exists(PICKLE_FILE): 34 | return default 35 | pkl_file = open(PICKLE_FILE, 'rb') 36 | data = pickle.load(pkl_file) 37 | pkl_file.close() 38 | return data 39 | 40 | def update_lcd(m): 41 | try: 42 | lcd.home() 43 | lcd.message("Moisture level:\n%d%% " % m) 44 | if m < 15: 45 | lcd.backlight(lcd.RED) 46 | elif m < 50: 47 | lcd.backlight(lcd.YELLOW) 48 | else: 49 | lcd.backlight(lcd.GREEN) 50 | except IOError as e: 51 | print e 52 | 53 | def send_gmail(from_name, sender, password, recipient, subject, body): 54 | '''Send an email using a GMail account.''' 55 | senddate=datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d') 56 | msg="Date: %s\r\nFrom: %s <%s>\r\nTo: %s\r\nSubject: %s\r\nX-Mailer: My-Mail\r\n\r\n" % (senddate, from_name, sender, recipient, subject) 57 | server = smtplib.SMTP('smtp.gmail.com:587') 58 | server.starttls() 59 | server.login(sender, password) 60 | server.sendmail(sender, recipient, msg+body) 61 | server.quit() 62 | 63 | logging.basicConfig(level=logging.INFO) 64 | 65 | p = [ 66 | [ ['G','moist','level',0,0,100], ['LC','chart1','Time','Value',0,100] ], 67 | ] 68 | 69 | c1 = load([]) 70 | 71 | readings = [] 72 | 73 | conn = ControlMyPi('you@gmail.com', 'password', 'moisture', 'Moisture monitor', p, on_msg) 74 | 75 | delta = datetime.timedelta(minutes=30) 76 | next_time = datetime.datetime.now() 77 | 78 | delta_email = datetime.timedelta(days=1) 79 | next_email_time = datetime.datetime.now() 80 | 81 | if conn.start_control(): 82 | try: 83 | while True: 84 | dt = datetime.datetime.now() 85 | m = mcp3008.read_pct(5) 86 | readings.append(m) 87 | update_lcd(m) 88 | to_update = {'moist':m} 89 | 90 | # Update the chart? 91 | if dt > next_time: 92 | # Take the average from the readings list to smooth the graph a little 93 | avg = int(round(sum(readings)/len(readings))) 94 | readings = [] 95 | c1 = append_chart_point(c1, [dt.strftime('%H:%M'), avg]) 96 | save(c1) 97 | next_time = dt + delta 98 | to_update['chart1'] = c1 99 | conn.update_status(to_update) 100 | 101 | #Send an email? 102 | if dt > next_email_time: 103 | next_email_time = dt + delta_email 104 | if m < 40: 105 | send_gmail('Your Name', 'you@gmail.com', 'password', 'recipient@email.com', 'Moisture sensor level', 'The level is now: %s' % m) 106 | 107 | sleep(30) 108 | finally: 109 | conn.stop_control() 110 | -------------------------------------------------------------------------------- /moisture/moist_lcd.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate') 3 | 4 | from time import sleep 5 | from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate 6 | import mcp3008 7 | 8 | lcd = Adafruit_CharLCDPlate() 9 | 10 | while True: 11 | m = mcp3008.readadc(5) 12 | try: 13 | lcd.home() 14 | lcd.message("Moisture level:\n%d " % m) 15 | if m < 150: 16 | lcd.backlight(lcd.RED) 17 | elif m < 500: 18 | lcd.backlight(lcd.YELLOW) 19 | else: 20 | lcd.backlight(lcd.GREEN) 21 | except IOError as e: 22 | print e 23 | sleep(.5) 24 | -------------------------------------------------------------------------------- /motion/snap2drive.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jun 7, 2015 3 | 4 | @author: jeremyblythe 5 | ''' 6 | import sys 7 | #sys.path.insert(1, '/Library/Python/2.7/site-packages') 8 | 9 | import httplib2 10 | from apiclient import discovery 11 | from oauth2client import client 12 | from oauth2client.file import Storage 13 | from googleapiclient.http import MediaFileUpload 14 | 15 | if __name__ == '__main__': 16 | file_path = sys.argv[1] 17 | auth_required = True 18 | #Have we got some credentials already? 19 | storage = Storage('snap2drive_credentials.txt') 20 | credentials = storage.get() 21 | try: 22 | if credentials: 23 | # Check for expiry 24 | if credentials.access_token_expired: 25 | if credentials.refresh_token is not None: 26 | credentials.refresh(httplib2.Http()) 27 | auth_required = False 28 | else: 29 | auth_required = False 30 | except: 31 | # Something went wrong - try manual auth 32 | pass 33 | 34 | if auth_required: 35 | flow = client.flow_from_clientsecrets( 36 | 'client_secrets.json', 37 | scope='https://www.googleapis.com/auth/drive',#.metadata.readonly', 38 | redirect_uri='urn:ietf:wg:oauth:2.0:oob') 39 | 40 | auth_uri = flow.step1_get_authorize_url() 41 | 42 | print 'Go to this link in your browser:' 43 | print auth_uri 44 | 45 | auth_code = raw_input('Enter the auth code: ') 46 | 47 | credentials = flow.step2_exchange(auth_code) 48 | 49 | storage.put(credentials) 50 | 51 | #Get the drive service 52 | http_auth = credentials.authorize(httplib2.Http()) 53 | drive_service = discovery.build('drive', 'v2', http_auth) 54 | 55 | #Find the 'public' folder 56 | files = drive_service.files().list(q="title='public' and mimeType contains 'application/vnd.google-apps.folder' and trashed=false").execute() 57 | if len(files['items']) == 1: 58 | folder_id = files['items'][0]['id'] 59 | print folder_id 60 | #Delete the old lastsnap.jpg 61 | files = drive_service.files().list(q="title='lastsnap.jpg' and '%s' in parents and trashed=false" % folder_id).execute() 62 | if len(files['items']) >= 1: 63 | for f in files['items']: 64 | file_id = f['id'] 65 | drive_service.files().delete(fileId=file_id).execute() 66 | #Now upload the new one 67 | media = MediaFileUpload(file_path, mimetype='image/jpeg') 68 | response = drive_service.files().insert(media_body=media, body={'title':'lastsnap.jpg', 'parents':[{u'id': folder_id}]}).execute() 69 | print response 70 | else: 71 | print 'Could not find public folder' 72 | -------------------------------------------------------------------------------- /motion/uploader.cfg: -------------------------------------------------------------------------------- 1 | [oauth] 2 | folder = /home/pi/ 3 | 4 | [gmail] 5 | # GMail account credentials 6 | name = My Name 7 | user = gmailusername 8 | password = gmailpassword 9 | sender = me@gmail.com 10 | 11 | # Recipient email address (could be same as from_addr) 12 | recipient = me@gmail.com 13 | 14 | # Subject line for email 15 | subject = Motion detected 16 | 17 | # First line of email message 18 | message = Video uploaded 19 | 20 | [docs] 21 | # Folder (or collection) in Docs where you want the videos to go 22 | folder = motion 23 | snapshot-folder = public 24 | 25 | [options] 26 | # Delete the local video file after the upload 27 | delete-after-upload = true 28 | 29 | # Send an email after the upload 30 | send-email = true -------------------------------------------------------------------------------- /motion/uploader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ''' 3 | Created on 6 Jun 2012 4 | 5 | @author: Jeremy Blythe 6 | 7 | Motion Uploader - uploads videos to Google Drive 8 | 9 | Read the blog entry at http://jeremyblythe.blogspot.com for more information 10 | 11 | Version 2: 10 Jun 2015 - rewritten for Google oauth2 and apiclient 12 | ''' 13 | import sys 14 | 15 | import smtplib 16 | from datetime import datetime 17 | 18 | import os.path 19 | import logging 20 | 21 | import httplib2 22 | from apiclient import discovery 23 | from oauth2client import client 24 | from oauth2client.file import Storage 25 | from googleapiclient.http import MediaFileUpload 26 | 27 | import ConfigParser 28 | 29 | class MotionUploader: 30 | def __init__(self, config_file_path): 31 | # Load config 32 | config = ConfigParser.ConfigParser() 33 | config.read(config_file_path) 34 | 35 | # OAuth folder 36 | self.oauth_folder = config.get('oauth', 'folder') 37 | 38 | # GMail account credentials 39 | self.username = config.get('gmail', 'user') 40 | self.password = config.get('gmail', 'password') 41 | self.from_name = config.get('gmail', 'name') 42 | self.sender = config.get('gmail', 'sender') 43 | 44 | # Recipient email address (could be same as from_addr) 45 | self.recipient = config.get('gmail', 'recipient') 46 | 47 | # Subject line for email 48 | self.subject = config.get('gmail', 'subject') 49 | 50 | # First line of email message 51 | self.message = config.get('gmail', 'message') 52 | 53 | # Folder (or collection) in Docs where you want the videos to go 54 | self.folder = config.get('docs', 'folder') 55 | 56 | # Folder (or collection) in Docs where you want the snapshot to go 57 | self.snapshot_folder = config.get('docs', 'snapshot-folder') 58 | 59 | # Options 60 | self.delete_after_upload = config.getboolean('options', 'delete-after-upload') 61 | self.send_email = config.getboolean('options', 'send-email') 62 | 63 | self._create_drive() 64 | 65 | def _create_drive(self): 66 | """Create a Drive service.""" 67 | auth_required = True 68 | #Have we got some credentials already? 69 | storage = Storage(self.oauth_folder+'uploader_credentials.txt') 70 | credentials = storage.get() 71 | try: 72 | if credentials: 73 | # Check for expiry 74 | if credentials.access_token_expired: 75 | if credentials.refresh_token is not None: 76 | credentials.refresh(httplib2.Http()) 77 | auth_required = False 78 | else: 79 | auth_required = False 80 | except: 81 | # Something went wrong - try manual auth 82 | pass 83 | 84 | if auth_required: 85 | flow = client.flow_from_clientsecrets( 86 | self.oauth_folder+'client_secrets.json', 87 | scope='https://www.googleapis.com/auth/drive', 88 | redirect_uri='urn:ietf:wg:oauth:2.0:oob') 89 | 90 | auth_uri = flow.step1_get_authorize_url() 91 | 92 | print 'Go to this link in your browser:' 93 | print auth_uri 94 | 95 | auth_code = raw_input('Enter the auth code: ') 96 | credentials = flow.step2_exchange(auth_code) 97 | storage.put(credentials) 98 | 99 | #Get the drive service 100 | http_auth = credentials.authorize(httplib2.Http()) 101 | self.drive_service = discovery.build('drive', 'v2', http_auth) 102 | 103 | def _get_folder_id(self, folder_name): 104 | """Find and return the id of the folder given the title.""" 105 | files = self.drive_service.files().list(q="title='%s' and mimeType contains 'application/vnd.google-apps.folder' and trashed=false" % folder_name).execute() 106 | if len(files['items']) == 1: 107 | folder_id = files['items'][0]['id'] 108 | return folder_id 109 | else: 110 | raise Exception('Could not find the %s folder' % folder_name) 111 | 112 | def _send_email(self,msg): 113 | '''Send an email using the GMail account.''' 114 | senddate=datetime.strftime(datetime.now(), '%Y-%m-%d') 115 | m="Date: %s\r\nFrom: %s <%s>\r\nTo: %s\r\nSubject: %s\r\nX-Mailer: My-Mail\r\n\r\n" % (senddate, self.from_name, self.sender, self.recipient, self.subject) 116 | server = smtplib.SMTP('smtp.gmail.com:587') 117 | server.starttls() 118 | server.login(self.username, self.password) 119 | server.sendmail(self.sender, self.recipient, m+msg) 120 | server.quit() 121 | 122 | def upload_video(self, video_file_path): 123 | """Upload a video to the specified folder. Then optionally send an email and optionally delete the local file.""" 124 | folder_id = self._get_folder_id(self.folder) 125 | 126 | media = MediaFileUpload(video_file_path, mimetype='video/avi') 127 | response = self.drive_service.files().insert(media_body=media, body={'title':os.path.basename(video_file_path), 'parents':[{u'id': folder_id}]}).execute() 128 | #print response 129 | video_link = response['alternateLink'] 130 | 131 | if self.send_email: 132 | msg = self.message 133 | if video_link: 134 | msg += '\n\n' + video_link 135 | self._send_email(msg) 136 | 137 | if self.delete_after_upload: 138 | os.remove(video_file_path) 139 | 140 | def upload_snapshot(self, snapshot_file_path): 141 | """Upload a snapshot to the specified folder. Remove duplicates.""" 142 | folder_id = self._get_folder_id(self.snapshot_folder) 143 | file_name = os.path.basename(snapshot_file_path) 144 | #Delete the old snapshot 145 | files = self.drive_service.files().list(q="title='%s' and '%s' in parents and trashed=false" % (file_name, folder_id)).execute() 146 | if len(files['items']) >= 1: 147 | for f in files['items']: 148 | file_id = f['id'] 149 | self.drive_service.files().delete(fileId=file_id).execute() 150 | #Now upload the new one 151 | media = MediaFileUpload(snapshot_file_path, mimetype='image/jpeg') 152 | self.drive_service.files().insert(media_body=media, body={'title':file_name, 'parents':[{u'id': folder_id}]}).execute() 153 | 154 | def get_snapshot_url(self, snapshot_file_path): 155 | """Print out the public url for this snapshot.""" 156 | folder_id = self._get_folder_id(self.snapshot_folder) 157 | 158 | public_url = 'https://googledrive.com/host/%s/' % folder_id 159 | print public_url + os.path.basename(snapshot_file_path) 160 | 161 | if __name__ == '__main__': 162 | try: 163 | logging.basicConfig(level=logging.ERROR) 164 | if len(sys.argv) < 3: 165 | exit('Motion Uploader - uploads videos and snapshots to Google Drive\n'+ 166 | ' by Jeremy Blythe (http://jeremyblythe.blogspot.com)\n\n'+ 167 | ' Usage: uploader.py {config-file-path} {source-file-path} [option]\n'+ 168 | ' Options: snap : Upload a snapshot to the snapshot-folder\n'+ 169 | ' snapurl : Print the public url for the folder+file\n'+ 170 | ' None : Defaults to uploading video files') 171 | cfg_path = sys.argv[1] 172 | vid_path = sys.argv[2] 173 | if len(sys.argv) > 3: 174 | option = sys.argv[3] 175 | else: 176 | option = 'video' 177 | 178 | if not os.path.exists(cfg_path): 179 | exit('Config file does not exist [%s]' % cfg_path) 180 | if not os.path.exists(vid_path): 181 | exit('Source file does not exist [%s]' % vid_path) 182 | if option.lower() == 'snap': 183 | MotionUploader(cfg_path).upload_snapshot(vid_path) 184 | elif option.lower() == 'snapurl': 185 | MotionUploader(cfg_path).get_snapshot_url(vid_path) 186 | else: 187 | MotionUploader(cfg_path).upload_video(vid_path) 188 | except Exception as e: 189 | exit('Error: [%s]' % e) 190 | -------------------------------------------------------------------------------- /pygamelcd/puitest.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jul 12, 2014 3 | 4 | @author: jeremyblythe 5 | ''' 6 | import pygame 7 | # from pygame.locals import * 8 | import os 9 | # from time import sleep 10 | import pygameui as ui 11 | 12 | # pygame.init() 13 | # pygame.mouse.set_visible(False) 14 | # lcd = pygame.display.set_mode((320, 240)) 15 | # lcd.fill((0,0,0)) 16 | # pygame.display.update() 17 | 18 | import logging 19 | log_format = '%(asctime)-6s: %(name)s - %(levelname)s - %(message)s' 20 | console_handler = logging.StreamHandler() 21 | console_handler.setFormatter(logging.Formatter(log_format)) 22 | logger = logging.getLogger() 23 | logger.setLevel(logging.DEBUG) 24 | logger.addHandler(console_handler) 25 | 26 | os.putenv('SDL_FBDEV', '/dev/fb1') 27 | os.putenv('SDL_MOUSEDRV', 'TSLIB') 28 | os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen') 29 | 30 | LIST_WIDTH = 180 31 | MARGIN = 20 32 | SMALL_MARGIN = 10 33 | 34 | 35 | class PiTft(ui.Scene): 36 | def __init__(self): 37 | ui.Scene.__init__(self) 38 | 39 | self.on17_button = ui.Button(ui.Rect(MARGIN, MARGIN, 130, 60), '17 on') 40 | self.on17_button.on_clicked.connect(self.gpi_button) 41 | self.add_child(self.on17_button) 42 | 43 | self.on4_button = ui.Button(ui.Rect(170, MARGIN, 130, 60), '4 on') 44 | self.on4_button.on_clicked.connect(self.gpi_button) 45 | self.add_child(self.on4_button) 46 | 47 | self.off17_button = ui.Button(ui.Rect(MARGIN, 100, 130, 60), '17 off') 48 | self.off17_button.on_clicked.connect(self.gpi_button) 49 | self.add_child(self.off17_button) 50 | 51 | self.off4_button = ui.Button(ui.Rect(170, 100, 130, 60), '4 off') 52 | self.off4_button.on_clicked.connect(self.gpi_button) 53 | self.add_child(self.off4_button) 54 | 55 | self.progress_view = ui.ProgressView(ui.Rect(MARGIN, 200, 280, 40)) 56 | self.add_child(self.progress_view) 57 | 58 | self.volts_value = ui.Label(ui.Rect(135, 170, 50, 30), 'Hi!') 59 | self.add_child(self.volts_value) 60 | 61 | self.progress = 0 62 | 63 | def gpi_button(self, btn, mbtn): 64 | logger.info(btn.text) 65 | 66 | # label_height = ui.theme.current.label_height 67 | # scrollbar_size = ui.SCROLLBAR_SIZE 68 | 69 | # frame = ui.Rect(MARGIN, MARGIN, 200, label_height) 70 | # self.name_textfield = ui.TextField(frame, placeholder='Your name') 71 | # self.name_textfield.centerx = self.frame.centerx 72 | # self.add_child(self.name_textfield) 73 | 74 | # gridview = ui.GridView(ui.Rect(0, 0, 500, 500)) 75 | # self.scroll_gridview = ui.ScrollView(ui.Rect( 76 | # MARGIN, self.name_textfield.frame.bottom + MARGIN, 77 | # 200 - scrollbar_size, 250), gridview) 78 | # self.add_child(self.scroll_gridview) 79 | # 80 | # items = ['Apples', 'Bananas', 'Grapes', 'Cheese', 'Goats', 'Beer'] 81 | # labels = [ui.Label(ui.Rect( 82 | # 0, 0, LIST_WIDTH, label_height), item, halign=ui.LEFT) 83 | # for item in items] 84 | # list_view = ui.ListView(ui.Rect(0, 0, LIST_WIDTH, 400), labels) 85 | # list_view.on_selected.connect(self.item_selected) 86 | # list_view.on_deselected.connect(self.item_deselected) 87 | # self.scroll_list = ui.ScrollView(ui.Rect( 88 | # MARGIN, self.scroll_gridview.frame.bottom + MARGIN, 89 | # LIST_WIDTH, 80), list_view) 90 | # self.add_child(self.scroll_list) 91 | 92 | # self.greet_button = ui.Button(ui.Rect( 93 | # self.name_textfield.frame.right + SMALL_MARGIN, 94 | # self.name_textfield.frame.top, 0, 0), 'Submit') 95 | # self.greet_button.on_clicked.connect(self.greet) 96 | # self.add_child(self.greet_button) 97 | 98 | # self.image_view = ui.view_for_image_named('logo') 99 | # self.image_view.frame.right = self.frame.right - MARGIN 100 | # self.image_view.frame.top = MARGIN 101 | # self.add_child(self.image_view) 102 | # 103 | # self.checkbox = ui.Checkbox(ui.Rect( 104 | # self.scroll_gridview.frame.right + MARGIN, 105 | # self.scroll_gridview.frame.top, 106 | # 200, label_height), 'I eat food') 107 | # self.add_child(self.checkbox) 108 | # 109 | # self.checkbox1 = ui.Checkbox(ui.Rect( 110 | # self.checkbox.frame.left, 111 | # self.checkbox.frame.bottom + SMALL_MARGIN, 112 | # 200, label_height), 'I drink water') 113 | # self.add_child(self.checkbox1) 114 | # 115 | # self.checkbox2 = ui.Checkbox(ui.Rect( 116 | # self.checkbox.frame.left, 117 | # self.checkbox1.frame.bottom + SMALL_MARGIN, 118 | # 200, label_height), 'I exercise regularly') 119 | # self.add_child(self.checkbox2) 120 | # 121 | # info_image = ui.get_image('info') 122 | # self.info_button = ui.ImageButton(ui.Rect( 123 | # self.checkbox2.frame.left, 124 | # self.checkbox2.frame.bottom + MARGIN, 125 | # 0, 0), info_image) 126 | # self.info_button.on_clicked.connect(self.show_alert) 127 | # self.add_child(self.info_button) 128 | # 129 | # notify_image = ui.get_image('star') 130 | # self.notify_button = ui.ImageButton(ui.Rect( 131 | # self.info_button.frame.right + MARGIN, 132 | # self.info_button.frame.top, 133 | # 0, 0), notify_image) 134 | # self.notify_button.on_clicked.connect(self.show_notification) 135 | # self.add_child(self.notify_button) 136 | # 137 | # self.task_button = ui.Button(ui.Rect( 138 | # self.info_button.frame.left, 139 | # self.info_button.frame.bottom + MARGIN, 140 | # 0, 0), 'Consume!') 141 | # self.task_button.on_clicked.connect(self.run_fake_task) 142 | # self.add_child(self.task_button) 143 | # 144 | # self.running_task = False 145 | # self.progress_view = ui.ProgressView(ui.Rect( 146 | # self.frame.right - MARGIN - 180, 147 | # self.task_button.frame.centery - scrollbar_size // 2, 148 | # 180, scrollbar_size)) 149 | # self.add_child(self.progress_view) 150 | # self.progress_view.hidden = True 151 | # 152 | # labels2 = [ui.Label( 153 | # ui.Rect(0, 0, LIST_WIDTH, label_height), 154 | # 'Item %d' % (i + 1)) for i in range(10)] 155 | # for l in labels2: 156 | # l.halign = ui.LEFT 157 | # self.select_view = ui.SelectView(ui.Rect( 158 | # self.task_button.frame.left, 159 | # self.task_button.frame.bottom + MARGIN, 160 | # LIST_WIDTH, label_height), labels2) 161 | # self.select_view.on_selection_changed.connect(self.selection_changed) 162 | # self.add_child(self.select_view) 163 | # 164 | # self.hslider = ui.SliderView(ui.Rect( 165 | # self.select_view.frame.left, 166 | # self.select_view.frame.bottom + MARGIN*2, 167 | # 100, scrollbar_size), ui.HORIZONTAL, 0, 100) 168 | # self.hslider.on_value_changed.connect(self.value_changed) 169 | # self.add_child(self.hslider) 170 | # 171 | # self.vslider = ui.SliderView(ui.Rect( 172 | # self.hslider.frame.right + SMALL_MARGIN, 173 | # self.hslider.frame.centery, 174 | # scrollbar_size, 100), ui.VERTICAL, 0, 100) 175 | # self.vslider.on_value_changed.connect(self.value_changed) 176 | # self.add_child(self.vslider) 177 | # 178 | 179 | # 180 | # self.spinner = ui.SpinnerView(ui.Rect( 181 | # self.frame.right - MARGIN - ui.SpinnerView.size, 182 | # self.frame.bottom - MARGIN - ui.SpinnerView.size, 183 | # 0, 0)) 184 | # self.add_child(self.spinner) 185 | 186 | # def layout(self): 187 | # self.checkbox.toggle() 188 | # self.checkbox1.toggle() 189 | # ui.Scene.layout(self) 190 | 191 | # def item_selected(self, list_view, item, index): 192 | # item.state = 'selected' 193 | # 194 | # def item_deselected(self, list_view, item, index): 195 | # item.state = 'normal' 196 | # 197 | # def selection_changed(self, selection_view, item, index): 198 | # logger.info('new selection: %s' % str(item)) 199 | # 200 | # def value_changed(self, slider_view, value): 201 | # self.slider_value.text = '%d' % value 202 | 203 | def greet(self, btn, mbtn): 204 | name = self.name_textfield.text.strip() 205 | if len(name) == 0: 206 | name = 'uh, you?' 207 | ui.show_alert(title='Greetings!', message='Hello, %s' % name) 208 | 209 | # def show_alert(self, btn, mbtn): 210 | # msgs = [ 211 | # 'This is an alert', 212 | # 'This is an alert with\na line break in it', 213 | # 'This is a rather long alert that should ' + 214 | # 'automatically word wrap to multiple lines', 215 | # 'This is an very long alert that should ' + 216 | # 'automatically word wrap to multiple lines...' + 217 | # 'is this not the best thing EVAR? wow, mindblowing...' 218 | # ] 219 | # msg = random.choice(msgs) 220 | # ui.show_alert(msg) 221 | 222 | # def show_notification(self, btn, mbtn): 223 | # msgs = [ 224 | # 'Achievement Unlocked! Notification!', 225 | # 'This is a notification\nwith a linebreak in it', 226 | # 'This notification is rather long and should ' + 227 | # 'automatically word wrap to multiple lines' 228 | # ] 229 | # msg = random.choice(msgs) 230 | # ui.show_notification(msg) 231 | 232 | # def run_fake_task(self, btn, mbtn): 233 | # if not self.running_task: 234 | # self.task_button.enabled = False 235 | # self.progress_view.hidden = False 236 | # self.progress_view.progress = 0 237 | # self.running_task = True 238 | 239 | def update(self, dt): 240 | ui.Scene.update(self, dt) 241 | self.volts_value.text = '%.2f' % self.progress 242 | self.progress_view.progress = self.progress 243 | self.progress += 0.01 244 | if self.progress > 1.0: 245 | self.progress = 0 246 | # if self.running_task: 247 | # progress = min(1.0, self.progress_view.progress + 0.01) 248 | # self.progress_view.progress = progress 249 | # self.running_task = (self.progress_view.progress < 1.0) 250 | # self.task_button.enabled = not self.running_task 251 | # if self.task_button.enabled: 252 | # ui.show_alert("I'M FINISHED!", title='Milkshake') 253 | # self.progress_view.progress = 0 254 | # self.progress_view.hidden = True 255 | 256 | 257 | if __name__ == '__main__': 258 | ui.init('Raspberry Pi UI', (320, 240)) 259 | #pygame.mouse.set_visible(False) 260 | ui.scene.push(PiTft()) 261 | ui.run() 262 | 263 | 264 | -------------------------------------------------------------------------------- /pygamelcd/pygameui-kitchensink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import random 4 | import sys 5 | import os 6 | 7 | 8 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) 9 | import pygameui as ui 10 | 11 | 12 | import logging 13 | log_format = '%(asctime)-6s: %(name)s - %(levelname)s - %(message)s' 14 | console_handler = logging.StreamHandler() 15 | console_handler.setFormatter(logging.Formatter(log_format)) 16 | logger = logging.getLogger() 17 | logger.setLevel(logging.DEBUG) 18 | logger.addHandler(console_handler) 19 | 20 | 21 | LIST_WIDTH = 180 22 | MARGIN = 20 23 | SMALL_MARGIN = 10 24 | 25 | 26 | class KitchenSinkScene(ui.Scene): 27 | def __init__(self): 28 | ui.Scene.__init__(self) 29 | 30 | label_height = ui.theme.current.label_height 31 | scrollbar_size = ui.SCROLLBAR_SIZE 32 | 33 | frame = ui.Rect(MARGIN, MARGIN, 200, label_height) 34 | self.name_textfield = ui.TextField(frame, placeholder='Your name') 35 | self.name_textfield.centerx = self.frame.centerx 36 | self.add_child(self.name_textfield) 37 | 38 | gridview = ui.GridView(ui.Rect(0, 0, 500, 500)) 39 | self.scroll_gridview = ui.ScrollView(ui.Rect( 40 | MARGIN, self.name_textfield.frame.bottom + MARGIN, 41 | 200 - scrollbar_size, 250), gridview) 42 | self.add_child(self.scroll_gridview) 43 | 44 | items = ['Apples', 'Bananas', 'Grapes', 'Cheese', 'Goats', 'Beer'] 45 | labels = [ui.Label(ui.Rect( 46 | 0, 0, LIST_WIDTH, label_height), item, halign=ui.LEFT) 47 | for item in items] 48 | list_view = ui.ListView(ui.Rect(0, 0, LIST_WIDTH, 400), labels) 49 | list_view.on_selected.connect(self.item_selected) 50 | list_view.on_deselected.connect(self.item_deselected) 51 | self.scroll_list = ui.ScrollView(ui.Rect( 52 | MARGIN, self.scroll_gridview.frame.bottom + MARGIN, 53 | LIST_WIDTH, 80), list_view) 54 | self.add_child(self.scroll_list) 55 | 56 | self.greet_button = ui.Button(ui.Rect( 57 | self.name_textfield.frame.right + SMALL_MARGIN, 58 | self.name_textfield.frame.top, 0, 0), 'Submit') 59 | self.greet_button.on_clicked.connect(self.greet) 60 | self.add_child(self.greet_button) 61 | 62 | self.image_view = ui.view_for_image_named('logo') 63 | self.image_view.frame.right = self.frame.right - MARGIN 64 | self.image_view.frame.top = MARGIN 65 | self.add_child(self.image_view) 66 | 67 | self.checkbox = ui.Checkbox(ui.Rect( 68 | self.scroll_gridview.frame.right + MARGIN, 69 | self.scroll_gridview.frame.top, 70 | 200, label_height), 'I eat food') 71 | self.add_child(self.checkbox) 72 | 73 | self.checkbox1 = ui.Checkbox(ui.Rect( 74 | self.checkbox.frame.left, 75 | self.checkbox.frame.bottom + SMALL_MARGIN, 76 | 200, label_height), 'I drink water') 77 | self.add_child(self.checkbox1) 78 | 79 | self.checkbox2 = ui.Checkbox(ui.Rect( 80 | self.checkbox.frame.left, 81 | self.checkbox1.frame.bottom + SMALL_MARGIN, 82 | 200, label_height), 'I exercise regularly') 83 | self.add_child(self.checkbox2) 84 | 85 | info_image = ui.get_image('info') 86 | self.info_button = ui.ImageButton(ui.Rect( 87 | self.checkbox2.frame.left, 88 | self.checkbox2.frame.bottom + MARGIN, 89 | 0, 0), info_image) 90 | self.info_button.on_clicked.connect(self.show_alert) 91 | self.add_child(self.info_button) 92 | 93 | notify_image = ui.get_image('star') 94 | self.notify_button = ui.ImageButton(ui.Rect( 95 | self.info_button.frame.right + MARGIN, 96 | self.info_button.frame.top, 97 | 0, 0), notify_image) 98 | self.notify_button.on_clicked.connect(self.show_notification) 99 | self.add_child(self.notify_button) 100 | 101 | self.task_button = ui.Button(ui.Rect( 102 | self.info_button.frame.left, 103 | self.info_button.frame.bottom + MARGIN, 104 | 0, 0), 'Consume!') 105 | self.task_button.on_clicked.connect(self.run_fake_task) 106 | self.add_child(self.task_button) 107 | 108 | self.running_task = False 109 | self.progress_view = ui.ProgressView(ui.Rect( 110 | self.frame.right - MARGIN - 180, 111 | self.task_button.frame.centery - scrollbar_size // 2, 112 | 180, scrollbar_size)) 113 | self.add_child(self.progress_view) 114 | self.progress_view.hidden = True 115 | 116 | labels2 = [ui.Label( 117 | ui.Rect(0, 0, LIST_WIDTH, label_height), 118 | 'Item %d' % (i + 1)) for i in range(10)] 119 | for l in labels2: 120 | l.halign = ui.LEFT 121 | self.select_view = ui.SelectView(ui.Rect( 122 | self.task_button.frame.left, 123 | self.task_button.frame.bottom + MARGIN, 124 | LIST_WIDTH, label_height), labels2) 125 | self.select_view.on_selection_changed.connect(self.selection_changed) 126 | self.add_child(self.select_view) 127 | 128 | self.hslider = ui.SliderView(ui.Rect( 129 | self.select_view.frame.left, 130 | self.select_view.frame.bottom + MARGIN*2, 131 | 100, scrollbar_size), ui.HORIZONTAL, 0, 100) 132 | self.hslider.on_value_changed.connect(self.value_changed) 133 | self.add_child(self.hslider) 134 | 135 | self.vslider = ui.SliderView(ui.Rect( 136 | self.hslider.frame.right + SMALL_MARGIN, 137 | self.hslider.frame.centery, 138 | scrollbar_size, 100), ui.VERTICAL, 0, 100) 139 | self.vslider.on_value_changed.connect(self.value_changed) 140 | self.add_child(self.vslider) 141 | 142 | self.slider_value = ui.Label(ui.Rect( 143 | self.hslider.frame.centerx - 25, 144 | self.hslider.frame.bottom + MARGIN, 145 | 50, label_height), '') 146 | self.add_child(self.slider_value) 147 | 148 | self.spinner = ui.SpinnerView(ui.Rect( 149 | self.frame.right - MARGIN - ui.SpinnerView.size, 150 | self.frame.bottom - MARGIN - ui.SpinnerView.size, 151 | 0, 0)) 152 | self.add_child(self.spinner) 153 | 154 | def layout(self): 155 | self.checkbox.toggle() 156 | self.checkbox1.toggle() 157 | ui.Scene.layout(self) 158 | 159 | def item_selected(self, list_view, item, index): 160 | item.state = 'selected' 161 | 162 | def item_deselected(self, list_view, item, index): 163 | item.state = 'normal' 164 | 165 | def selection_changed(self, selection_view, item, index): 166 | logger.info('new selection: %s' % str(item)) 167 | 168 | def value_changed(self, slider_view, value): 169 | self.slider_value.text = '%d' % value 170 | 171 | def greet(self, btn, mbtn): 172 | name = self.name_textfield.text.strip() 173 | if len(name) == 0: 174 | name = 'uh, you?' 175 | ui.show_alert(title='Greetings!', message='Hello, %s' % name) 176 | 177 | def show_alert(self, btn, mbtn): 178 | msgs = [ 179 | 'This is an alert', 180 | 'This is an alert with\na line break in it', 181 | 'This is a rather long alert that should ' + 182 | 'automatically word wrap to multiple lines', 183 | 'This is an very long alert that should ' + 184 | 'automatically word wrap to multiple lines...' + 185 | 'is this not the best thing EVAR? wow, mindblowing...' 186 | ] 187 | msg = random.choice(msgs) 188 | ui.show_alert(msg) 189 | 190 | def show_notification(self, btn, mbtn): 191 | msgs = [ 192 | 'Achievement Unlocked! Notification!', 193 | 'This is a notification\nwith a linebreak in it', 194 | 'This notification is rather long and should ' + 195 | 'automatically word wrap to multiple lines' 196 | ] 197 | msg = random.choice(msgs) 198 | ui.show_notification(msg) 199 | 200 | def run_fake_task(self, btn, mbtn): 201 | if not self.running_task: 202 | self.task_button.enabled = False 203 | self.progress_view.hidden = False 204 | self.progress_view.progress = 0 205 | self.running_task = True 206 | 207 | def update(self, dt): 208 | ui.Scene.update(self, dt) 209 | if self.running_task: 210 | progress = min(1.0, self.progress_view.progress + 0.01) 211 | self.progress_view.progress = progress 212 | self.running_task = (self.progress_view.progress < 1.0) 213 | self.task_button.enabled = not self.running_task 214 | if self.task_button.enabled: 215 | ui.show_alert("I'M FINISHED!", title='Milkshake') 216 | self.progress_view.progress = 0 217 | self.progress_view.hidden = True 218 | 219 | 220 | if __name__ == '__main__': 221 | ui.init('pygameui - Kitchen Sink') 222 | ui.scene.push(KitchenSinkScene()) 223 | ui.run() 224 | -------------------------------------------------------------------------------- /pygamelcd/test1.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jul 12, 2014 3 | 4 | @author: jeremyblythe 5 | ''' 6 | import pygame 7 | import os 8 | from time import sleep 9 | 10 | os.putenv('SDL_FBDEV', '/dev/fb1') 11 | pygame.init() 12 | lcd = pygame.display.set_mode((320, 240)) 13 | lcd.fill((255,0,0)) 14 | pygame.display.update() 15 | sleep(1) 16 | 17 | pygame.mouse.set_visible(False) 18 | 19 | lcd.fill((0,0,0)) 20 | pygame.display.update() -------------------------------------------------------------------------------- /pygamelcd/test2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jul 12, 2014 3 | 4 | @author: jeremyblythe 5 | ''' 6 | import pygame 7 | import os 8 | from time import sleep 9 | import RPi.GPIO as GPIO 10 | 11 | #Note #21 changed to #27 for rev2 Pi 12 | button_map = {23:(255,0,0), 22:(0,255,0), 27:(0,0,255), 18:(0,0,0)} 13 | 14 | #Setup the GPIOs as inputs with Pull Ups since the buttons are connected to GND 15 | GPIO.setmode(GPIO.BCM) 16 | for k in button_map.keys(): 17 | GPIO.setup(k, GPIO.IN, pull_up_down=GPIO.PUD_UP) 18 | 19 | #Colours 20 | WHITE = (255,255,255) 21 | 22 | os.putenv('SDL_FBDEV', '/dev/fb1') 23 | pygame.init() 24 | pygame.mouse.set_visible(False) 25 | lcd = pygame.display.set_mode((320, 240)) 26 | lcd.fill((0,0,0)) 27 | pygame.display.update() 28 | 29 | font_big = pygame.font.Font(None, 100) 30 | 31 | while True: 32 | # Scan the buttons 33 | for (k,v) in button_map.items(): 34 | if GPIO.input(k) == False: 35 | lcd.fill(v) 36 | text_surface = font_big.render('%d'%k, True, WHITE) 37 | rect = text_surface.get_rect(center=(160,120)) 38 | lcd.blit(text_surface, rect) 39 | pygame.display.update() 40 | sleep(0.1) 41 | -------------------------------------------------------------------------------- /pygamelcd/test3.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jul 12, 2014 3 | 4 | @author: jeremyblythe 5 | ''' 6 | import pygame 7 | from pygame.locals import * 8 | import os 9 | from time import sleep 10 | import RPi.GPIO as GPIO 11 | 12 | #Setup the GPIOs as outputs - only 4 and 17 are available 13 | GPIO.setmode(GPIO.BCM) 14 | GPIO.setup(4, GPIO.OUT) 15 | GPIO.setup(17, GPIO.OUT) 16 | 17 | #Colours 18 | WHITE = (255,255,255) 19 | 20 | os.putenv('SDL_FBDEV', '/dev/fb1') 21 | os.putenv('SDL_MOUSEDRV', 'TSLIB') 22 | os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen') 23 | 24 | pygame.init() 25 | pygame.mouse.set_visible(False) 26 | lcd = pygame.display.set_mode((320, 240)) 27 | lcd.fill((0,0,0)) 28 | pygame.display.update() 29 | 30 | font_big = pygame.font.Font(None, 50) 31 | 32 | touch_buttons = {'17 on':(80,60), '4 on':(240,60), '17 off':(80,180), '4 off':(240,180)} 33 | 34 | for k,v in touch_buttons.items(): 35 | text_surface = font_big.render('%s'%k, True, WHITE) 36 | rect = text_surface.get_rect(center=v) 37 | lcd.blit(text_surface, rect) 38 | 39 | pygame.display.update() 40 | 41 | while True: 42 | # Scan touchscreen events 43 | for event in pygame.event.get(): 44 | if(event.type is MOUSEBUTTONDOWN): 45 | pos = pygame.mouse.get_pos() 46 | print pos 47 | elif(event.type is MOUSEBUTTONUP): 48 | pos = pygame.mouse.get_pos() 49 | print pos 50 | #Find which quarter of the screen we're in 51 | x,y = pos 52 | if y < 120: 53 | if x < 160: 54 | GPIO.output(17, False) 55 | else: 56 | GPIO.output(4, False) 57 | else: 58 | if x < 160: 59 | GPIO.output(17, True) 60 | else: 61 | GPIO.output(4, True) 62 | sleep(0.1) 63 | -------------------------------------------------------------------------------- /pygamelcd/test4.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jul 26, 2014 3 | 4 | @author: jeremyblythe 5 | ''' 6 | import pygame 7 | import os 8 | import pygameui as ui 9 | import logging 10 | import RPi.GPIO as GPIO 11 | 12 | #Setup the GPIOs as outputs - only 4 and 17 are available 13 | GPIO.setmode(GPIO.BCM) 14 | GPIO.setup(4, GPIO.OUT) 15 | GPIO.setup(17, GPIO.OUT) 16 | 17 | log_format = '%(asctime)-6s: %(name)s - %(levelname)s - %(message)s' 18 | console_handler = logging.StreamHandler() 19 | console_handler.setFormatter(logging.Formatter(log_format)) 20 | logger = logging.getLogger() 21 | logger.setLevel(logging.DEBUG) 22 | logger.addHandler(console_handler) 23 | 24 | os.putenv('SDL_FBDEV', '/dev/fb1') 25 | os.putenv('SDL_MOUSEDRV', 'TSLIB') 26 | os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen') 27 | 28 | MARGIN = 20 29 | 30 | class PiTft(ui.Scene): 31 | def __init__(self): 32 | ui.Scene.__init__(self) 33 | 34 | self.on17_button = ui.Button(ui.Rect(MARGIN, MARGIN, 130, 90), '17 on') 35 | self.on17_button.on_clicked.connect(self.gpi_button) 36 | self.add_child(self.on17_button) 37 | 38 | self.on4_button = ui.Button(ui.Rect(170, MARGIN, 130, 90), '4 on') 39 | self.on4_button.on_clicked.connect(self.gpi_button) 40 | self.add_child(self.on4_button) 41 | 42 | self.off17_button = ui.Button(ui.Rect(MARGIN, 130, 130, 90), '17 off') 43 | self.off17_button.on_clicked.connect(self.gpi_button) 44 | self.add_child(self.off17_button) 45 | 46 | self.off4_button = ui.Button(ui.Rect(170, 130, 130, 90), '4 off') 47 | self.off4_button.on_clicked.connect(self.gpi_button) 48 | self.add_child(self.off4_button) 49 | 50 | def gpi_button(self, btn, mbtn): 51 | logger.info(btn.text) 52 | 53 | if btn.text == '17 on': 54 | GPIO.output(17, False) 55 | elif btn.text == '4 on': 56 | GPIO.output(4, False) 57 | elif btn.text == '17 off': 58 | GPIO.output(17, True) 59 | elif btn.text == '4 off': 60 | GPIO.output(4, True) 61 | 62 | ui.init('Raspberry Pi UI', (320, 240)) 63 | pygame.mouse.set_visible(False) 64 | ui.scene.push(PiTft()) 65 | ui.run() 66 | 67 | 68 | -------------------------------------------------------------------------------- /pygamelcd/test5.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Jul 26, 2014 3 | 4 | @author: jeremyblythe 5 | ''' 6 | import sys 7 | sys.path.append('/home/pi/Adafruit-Raspberry-Pi-Python-Code/Adafruit_ADS1x15') 8 | 9 | import pygame 10 | import os 11 | import pygameui as ui 12 | import logging 13 | import RPi.GPIO as GPIO 14 | import signal 15 | from Adafruit_ADS1x15 import ADS1x15 16 | import threading 17 | import time 18 | 19 | ADS1015 = 0x00 # 12-bit ADC 20 | ADS1115 = 0x01 # 16-bit ADC 21 | 22 | # Select the gain 23 | # gain = 6144 # +/- 6.144V 24 | gain = 4096 # +/- 4.096V 25 | # gain = 2048 # +/- 2.048V 26 | # gain = 1024 # +/- 1.024V 27 | # gain = 512 # +/- 0.512V 28 | # gain = 256 # +/- 0.256V 29 | 30 | # Select the sample rate 31 | sps = 8 # 8 samples per second 32 | # sps = 16 # 16 samples per second 33 | # sps = 32 # 32 samples per second 34 | # sps = 64 # 64 samples per second 35 | # sps = 128 # 128 samples per second 36 | # sps = 250 # 250 samples per second 37 | # sps = 475 # 475 samples per second 38 | # sps = 860 # 860 samples per second 39 | 40 | # Initialise the ADC using the default mode (use default I2C address) 41 | # Set this to ADS1015 or ADS1115 depending on the ADC you are using! 42 | adc = ADS1x15(ic=ADS1115) 43 | 44 | #Setup the GPIOs as outputs - only 4 and 17 are available 45 | GPIO.setmode(GPIO.BCM) 46 | GPIO.setup(4, GPIO.OUT) 47 | GPIO.setup(17, GPIO.OUT) 48 | 49 | log_format = '%(asctime)-6s: %(name)s - %(levelname)s - %(message)s' 50 | console_handler = logging.StreamHandler() 51 | console_handler.setFormatter(logging.Formatter(log_format)) 52 | logger = logging.getLogger() 53 | logger.setLevel(logging.DEBUG) 54 | logger.addHandler(console_handler) 55 | 56 | os.putenv('SDL_FBDEV', '/dev/fb1') 57 | os.putenv('SDL_MOUSEDRV', 'TSLIB') 58 | os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen') 59 | 60 | MARGIN = 20 61 | 62 | class PotReader(): 63 | def __init__(self, pitft): 64 | self.pitft = pitft 65 | self.terminated = False 66 | 67 | def terminate(self): 68 | self.terminated = True 69 | 70 | def __call__(self): 71 | while not self.terminated: 72 | # Read channel 0 in single-ended mode using the settings above 73 | volts = adc.readADCSingleEnded(0, gain, sps) / 1000 74 | self.pitft.set_volts_label(volts) 75 | self.pitft.set_progress(volts / 3.3) 76 | 77 | class PiTft(ui.Scene): 78 | def __init__(self): 79 | ui.Scene.__init__(self) 80 | 81 | self.on17_button = ui.Button(ui.Rect(MARGIN, MARGIN, 130, 60), '17 on') 82 | self.on17_button.on_clicked.connect(self.gpi_button) 83 | self.add_child(self.on17_button) 84 | 85 | self.on4_button = ui.Button(ui.Rect(170, MARGIN, 130, 60), '4 on') 86 | self.on4_button.on_clicked.connect(self.gpi_button) 87 | self.add_child(self.on4_button) 88 | 89 | self.off17_button = ui.Button(ui.Rect(MARGIN, 100, 130, 60), '17 off') 90 | self.off17_button.on_clicked.connect(self.gpi_button) 91 | self.add_child(self.off17_button) 92 | 93 | self.off4_button = ui.Button(ui.Rect(170, 100, 130, 60), '4 off') 94 | self.off4_button.on_clicked.connect(self.gpi_button) 95 | self.add_child(self.off4_button) 96 | 97 | self.progress_view = ui.ProgressView(ui.Rect(MARGIN, 200, 280, 40)) 98 | self.add_child(self.progress_view) 99 | 100 | self.volts_value = ui.Label(ui.Rect(135, 170, 50, 30), '') 101 | self.add_child(self.volts_value) 102 | 103 | def gpi_button(self, btn, mbtn): 104 | logger.info(btn.text) 105 | 106 | if btn.text == '17 on': 107 | GPIO.output(17, False) 108 | elif btn.text == '4 on': 109 | GPIO.output(4, False) 110 | elif btn.text == '17 off': 111 | GPIO.output(17, True) 112 | elif btn.text == '4 off': 113 | GPIO.output(4, True) 114 | 115 | def set_progress(self, percent): 116 | self.progress_view.progress = percent 117 | 118 | def set_volts_label(self, volts): 119 | self.volts_value.text = '%.2f' % volts 120 | 121 | def update(self, dt): 122 | ui.Scene.update(self, dt) 123 | 124 | 125 | ui.init('Raspberry Pi UI', (320, 240)) 126 | pygame.mouse.set_visible(False) 127 | 128 | pitft = PiTft() 129 | 130 | # Start the thread running the callable 131 | potreader = PotReader(pitft) 132 | threading.Thread(target=potreader).start() 133 | 134 | def signal_handler(signal, frame): 135 | print 'You pressed Ctrl+C!' 136 | potreader.terminate() 137 | sys.exit(0) 138 | 139 | signal.signal(signal.SIGINT, signal_handler) 140 | 141 | ui.scene.push(pitft) 142 | ui.run() 143 | 144 | 145 | -------------------------------------------------------------------------------- /tweetbox/templates/form1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |