├── moisture
├── moist_cmd.py
├── moist_cmp.py
├── moist_lcd.py
├── moist_ansi.py
├── moist_cmp2.py
├── mcp3008.py
├── moist_cmp3_lcd.py
└── moist_final.py
├── tweetbox
├── templates
│ ├── form1.html
│ ├── form3.html
│ └── form4.html
├── tweetbox.py
├── tweetbox2.py
├── tweetbox3.py
└── tweetbox4.py
├── pygamelcd
├── test1.py
├── test2.py
├── test3.py
├── test4.py
├── test5.py
├── pygameui-kitchensink.py
└── puitest.py
├── .gitattributes
├── motion
├── uploader.cfg
├── snap2drive.py
└── uploader.py
└── .gitignore
/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 |
--------------------------------------------------------------------------------
/tweetbox/templates/form1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Raspberry Pi Tweetbox
5 |
6 |
7 |
8 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/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()
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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_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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tweetbox/templates/form3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Raspberry Pi Tweetbox
5 |
6 |
7 |
8 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tweetbox/templates/form4.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Raspberry Pi Tweetbox
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | TweetBox
25 |
74 |
75 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/tweetbox/tweetbox.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate')
3 | from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
4 | from tweepy.streaming import StreamListener
5 | from tweepy import OAuthHandler
6 | from tweepy import Stream
7 | import json
8 | import threading
9 | import time
10 | import textwrap
11 | import subprocess
12 |
13 | api_key='---'
14 | api_secret='---'
15 |
16 | access_token_key='---'
17 | access_token_secret='---'
18 |
19 |
20 | class DisplayLoop(StreamListener):
21 | """
22 | This class is a listener for tweet stream data. It's also callable so it
23 | can run the main display thread loop to update the display.
24 | """
25 | def __init__(self):
26 | self.lcd = Adafruit_CharLCDPlate()
27 | self.lcd.backlight(self.lcd.RED)
28 | self.lcd.clear()
29 | self.backlight_map = {'clarkson':self.lcd.RED,
30 | 'pearl':self.lcd.GREEN,
31 | 'love':self.lcd.BLUE,
32 | 'hate':self.lcd.YELLOW,
33 | 'kyle':self.lcd.TEAL,
34 | 'like':self.lcd.VIOLET}
35 | self.msglist = []
36 | self.pos = 0
37 | self.tweet = 'Nothing yet'
38 |
39 | def set_backlight(self):
40 | words = self.tweet.lower().split(' ')
41 | use_default = True
42 | for w in words:
43 | if w in self.backlight_map:
44 | self.lcd.backlight(self.backlight_map[w])
45 | use_default = False
46 | break
47 | if use_default:
48 | self.lcd.backlight(self.lcd.WHITE)
49 |
50 | def on_data(self, data):
51 | tweet_data = json.loads(data)
52 | self.tweet = tweet_data['text'].encode('ascii', errors='backslashreplace')
53 | self.msglist = [x.ljust(16) for x in textwrap.wrap(str(self.tweet),16)]
54 | self.pos = 0
55 | self.set_backlight()
56 | self.scroll_message()
57 | return True
58 |
59 | def on_error(self, status):
60 | print status
61 |
62 | def write_message(self,msg):
63 | self.lcd.home()
64 | self.lcd.message(msg)
65 |
66 | def scroll_message(self):
67 | "Displays the page of text and updates the scroll position for the next call"
68 | if len(self.msglist) == 0:
69 | self.write_message(''.ljust(16)+'\n'+''.ljust(16))
70 | elif len(self.msglist) == 1:
71 | self.write_message(self.msglist[0]+'\n'+''.ljust(16))
72 | elif len(self.msglist) == 2:
73 | self.write_message(self.msglist[0]+'\n'+self.msglist[1])
74 | else:
75 | if self.pos >= len(self.msglist)-1:
76 | self.pos = 0
77 | else:
78 | self.write_message(self.msglist[self.pos]+'\n'+self.msglist[self.pos+1])
79 | self.pos+=1
80 |
81 | def get_ip_address(self,interface):
82 | "Returns the IP address for the given interface e.g. eth0"
83 | try:
84 | s = subprocess.check_output(["ip","addr","show",interface])
85 | return s.split('\n')[2].strip().split(' ')[1].split('/')[0]
86 | except:
87 | return '?.?.?.?'
88 |
89 | def __call__(self):
90 | while True:
91 | if self.lcd.buttonPressed(self.lcd.LEFT):
92 | self.write_message(self.get_ip_address('eth0').ljust(16)+'\n'+self.get_ip_address('wlan0').ljust(16))
93 | else:
94 | self.scroll_message()
95 | time.sleep(1)
96 |
97 | display_loop_instance = DisplayLoop()
98 |
99 | # Start the thread running the callable
100 | threading.Thread(target=display_loop_instance).start()
101 |
102 | # Log in to twitter and start the tracking stream
103 | auth = OAuthHandler(api_key, api_secret)
104 | auth.set_access_token(access_token_key, access_token_secret)
105 | stream = Stream(auth, display_loop_instance)
106 | stream.filter(track=['jeremy'])
107 |
--------------------------------------------------------------------------------
/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/tweetbox2.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate')
3 | from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
4 | from tweepy.streaming import StreamListener
5 | from tweepy import OAuthHandler
6 | from tweepy import Stream
7 | import json
8 | import threading
9 | import time
10 | import textwrap
11 | import subprocess
12 | import tornado.ioloop
13 | import tornado.web
14 |
15 |
16 | api_key='---'
17 | api_secret='---'
18 |
19 | access_token_key='---'
20 | access_token_secret='---'
21 |
22 |
23 | class DisplayLoop(StreamListener):
24 | """
25 | This class is a listener for tweet stream data. It's also callable so it
26 | can run the main display thread loop to update the display.
27 | """
28 | def __init__(self):
29 | self.lcd = Adafruit_CharLCDPlate()
30 | self.lcd.backlight(self.lcd.RED)
31 | self.lcd.clear()
32 | self.backlight_map = {'clarkson':self.lcd.RED,
33 | 'pearl':self.lcd.GREEN,
34 | 'love':self.lcd.BLUE,
35 | 'hate':self.lcd.YELLOW,
36 | 'kyle':self.lcd.TEAL,
37 | 'like':self.lcd.VIOLET}
38 | self.msglist = []
39 | self.pos = 0
40 | self.tweet = 'Nothing yet'
41 |
42 | def set_backlight(self):
43 | words = self.tweet.lower().split(' ')
44 | use_default = True
45 | for w in words:
46 | if w in self.backlight_map:
47 | self.lcd.backlight(self.backlight_map[w])
48 | use_default = False
49 | break
50 | if use_default:
51 | self.lcd.backlight(self.lcd.WHITE)
52 |
53 | def on_data(self, data):
54 | tweet_data = json.loads(data)
55 | self.tweet = tweet_data['text'].encode('ascii', errors='backslashreplace')
56 | self.msglist = [x.ljust(16) for x in textwrap.wrap(str(self.tweet),16)]
57 | self.pos = 0
58 | self.set_backlight()
59 | self.scroll_message()
60 | return True
61 |
62 | def on_error(self, status):
63 | print status
64 |
65 | def write_message(self,msg):
66 | self.lcd.home()
67 | self.lcd.message(msg)
68 |
69 | def scroll_message(self):
70 | "Displays the page of text and updates the scroll position for the next call"
71 | if len(self.msglist) == 0:
72 | self.write_message(''.ljust(16)+'\n'+''.ljust(16))
73 | elif len(self.msglist) == 1:
74 | self.write_message(self.msglist[0]+'\n'+''.ljust(16))
75 | elif len(self.msglist) == 2:
76 | self.write_message(self.msglist[0]+'\n'+self.msglist[1])
77 | else:
78 | if self.pos >= len(self.msglist)-1:
79 | self.pos = 0
80 | else:
81 | self.write_message(self.msglist[self.pos]+'\n'+self.msglist[self.pos+1])
82 | self.pos+=1
83 |
84 | def get_ip_address(self,interface):
85 | "Returns the IP address for the given interface e.g. eth0"
86 | try:
87 | s = subprocess.check_output(["ip","addr","show",interface])
88 | return s.split('\n')[2].strip().split(' ')[1].split('/')[0]
89 | except:
90 | return '?.?.?.?'
91 |
92 | def __call__(self):
93 | while True:
94 | if self.lcd.buttonPressed(self.lcd.LEFT):
95 | self.write_message(self.get_ip_address('eth0').ljust(16)+'\n'+self.get_ip_address('wlan0').ljust(16))
96 | else:
97 | self.scroll_message()
98 | time.sleep(1)
99 |
100 | class MainHandler(tornado.web.RequestHandler):
101 | def get(self):
102 | self.render("templates/form1.html")
103 |
104 | class ConfigHandler(tornado.web.RequestHandler):
105 | def post(self):
106 | config_track = self.get_argument("config_track")
107 | restart(config_track)
108 | self.write("Now tracking %s" % config_track)
109 |
110 |
111 | def restart(track_text):
112 | print "restarting"
113 | stream.disconnect()
114 | time.sleep(5) #Allow time for the thread to disconnect...
115 | stream.filter(track=[track_text], async=True)
116 |
117 | application = tornado.web.Application([
118 | (r"/", MainHandler),
119 | (r"/config", ConfigHandler),
120 | ])
121 |
122 |
123 | display_loop_instance = DisplayLoop()
124 |
125 | # Start the thread running the callable
126 | threading.Thread(target=display_loop_instance).start()
127 |
128 | # Log in to twitter and start the tracking stream
129 | auth = OAuthHandler(api_key, api_secret)
130 | auth.set_access_token(access_token_key, access_token_secret)
131 | stream = Stream(auth, display_loop_instance)
132 | stream.filter(track=['jeremy'], async=True)
133 | print "Starting"
134 | application.listen(8888)
135 | tornado.ioloop.IOLoop.instance().start()
136 | print "Stopping"
137 | stream.disconnect()
138 |
--------------------------------------------------------------------------------
/tweetbox/tweetbox3.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate')
3 | from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
4 | from tweepy.streaming import StreamListener
5 | from tweepy import OAuthHandler
6 | from tweepy import Stream
7 | import json
8 | import threading
9 | import time
10 | import textwrap
11 | import subprocess
12 | import tornado.ioloop
13 | import tornado.web
14 | import pickle
15 | from genericpath import exists
16 |
17 | api_key='---'
18 | api_secret='---'
19 |
20 | access_token_key='---'
21 | access_token_secret='---'
22 |
23 |
24 | class DisplayLoop(StreamListener):
25 | """
26 | This class is a listener for tweet stream data. It's also callable so it
27 | can run the main display thread loop to update the display.
28 | """
29 | PICKLE_FILE = '/home/pi/py/tweetbox.pkl'
30 |
31 | def __init__(self):
32 | self.lcd = Adafruit_CharLCDPlate()
33 | self.lcd.backlight(self.lcd.RED)
34 | self.lcd.clear()
35 | self.track_text = 'jeremy'
36 | self.backlight_map = {'red':self.lcd.RED,
37 | 'green':self.lcd.GREEN,
38 | 'blue':self.lcd.BLUE,
39 | 'yellow':self.lcd.YELLOW,
40 | 'teal':self.lcd.TEAL,
41 | 'violet':self.lcd.VIOLET}
42 | self.msglist = []
43 | self.pos = 0
44 | self.tweet = 'Nothing yet'
45 |
46 | def set_backlight(self):
47 | words = self.tweet.lower().split(' ')
48 | use_default = True
49 | for w in words:
50 | if w in self.backlight_map:
51 | self.lcd.backlight(self.backlight_map[w])
52 | use_default = False
53 | break
54 | if use_default:
55 | self.lcd.backlight(self.lcd.WHITE)
56 |
57 | def on_data(self, data):
58 | print data
59 | tweet_data = json.loads(data)
60 | self.set_text(tweet_data['text'].encode('ascii', errors='backslashreplace'))
61 |
62 | def set_text(self, text):
63 | self.tweet = text
64 | self.msglist = [x.ljust(16) for x in textwrap.wrap(str(self.tweet),16)]
65 | self.pos = 0
66 | self.set_backlight()
67 | self.scroll_message()
68 | return True
69 |
70 | def on_error(self, status):
71 | print status
72 |
73 | def write_message(self,msg):
74 | self.lcd.home()
75 | self.lcd.message(msg)
76 |
77 | def scroll_message(self):
78 | "Displays the page of text and updates the scroll position for the next call"
79 | if len(self.msglist) == 0:
80 | self.write_message(''.ljust(16)+'\n'+''.ljust(16))
81 | elif len(self.msglist) == 1:
82 | self.write_message(self.msglist[0]+'\n'+''.ljust(16))
83 | elif len(self.msglist) == 2:
84 | self.write_message(self.msglist[0]+'\n'+self.msglist[1])
85 | else:
86 | if self.pos >= len(self.msglist)-1:
87 | self.pos = 0
88 | else:
89 | self.write_message(self.msglist[self.pos]+'\n'+self.msglist[self.pos+1])
90 | self.pos+=1
91 |
92 | def get_ip_address(self,interface):
93 | "Returns the IP address for the given interface e.g. eth0"
94 | try:
95 | s = subprocess.check_output(["ip","addr","show",interface])
96 | return s.split('\n')[2].strip().split(' ')[1].split('/')[0]
97 | except:
98 | return '?.?.?.?'
99 |
100 | def write_config(self):
101 | data = {"track_text":self.track_text, "backlight_map":self.backlight_map}
102 | output = open(self.PICKLE_FILE, 'wb')
103 | pickle.dump(data, output)
104 | output.close()
105 |
106 | def read_config(self):
107 | if exists(self.PICKLE_FILE):
108 | pkl_file = open(self.PICKLE_FILE, 'rb')
109 | data = pickle.load(pkl_file)
110 | pkl_file.close()
111 | self.track_text = data["track_text"]
112 | self.backlight_map = data["backlight_map"]
113 |
114 | def __call__(self):
115 | while True:
116 | if self.lcd.buttonPressed(self.lcd.LEFT):
117 | self.write_message(self.get_ip_address('eth0').ljust(16)+'\n'+self.get_ip_address('wlan0').ljust(16))
118 | else:
119 | self.scroll_message()
120 | time.sleep(1)
121 |
122 | class MainHandler(tornado.web.RequestHandler):
123 | def get(self):
124 | inverted_map = {v:k for k, v in display_loop_instance.backlight_map.items()}
125 | self.render("templates/form3.html",
126 | config_track=display_loop_instance.track_text,
127 | config_red=inverted_map[Adafruit_CharLCDPlate.RED],
128 | config_green=inverted_map[Adafruit_CharLCDPlate.GREEN],
129 | config_blue=inverted_map[Adafruit_CharLCDPlate.BLUE],
130 | config_yellow=inverted_map[Adafruit_CharLCDPlate.YELLOW],
131 | config_teal=inverted_map[Adafruit_CharLCDPlate.TEAL],
132 | config_violet=inverted_map[Adafruit_CharLCDPlate.VIOLET])
133 |
134 | class ConfigHandler(tornado.web.RequestHandler):
135 | def post(self):
136 | config_track = self.get_argument("config_track")
137 | colour_map = {self.get_argument("config_red"):Adafruit_CharLCDPlate.RED,
138 | self.get_argument("config_green"):Adafruit_CharLCDPlate.GREEN,
139 | self.get_argument("config_blue"):Adafruit_CharLCDPlate.BLUE,
140 | self.get_argument("config_yellow"):Adafruit_CharLCDPlate.YELLOW,
141 | self.get_argument("config_teal"):Adafruit_CharLCDPlate.TEAL,
142 | self.get_argument("config_violet"):Adafruit_CharLCDPlate.VIOLET
143 | }
144 | set_config(config_track, colour_map)
145 | self.write("Now tracking %s" % config_track)
146 |
147 |
148 | def set_config(track_text, colour_map):
149 | print "restarting"
150 | display_loop_instance.set_text("Updating configuration")
151 | stream.disconnect()
152 | display_loop_instance.track_text = track_text
153 | display_loop_instance.backlight_map = colour_map
154 | display_loop_instance.write_config()
155 | time.sleep(5) #Allow time for the thread to disconnect...
156 | stream.filter(track=[display_loop_instance.track_text], async=True)
157 | display_loop_instance.set_text("Updated configuration")
158 |
159 | application = tornado.web.Application([
160 | (r"/", MainHandler),
161 | (r"/config", ConfigHandler),
162 | ])
163 |
164 |
165 | display_loop_instance = DisplayLoop()
166 | display_loop_instance.read_config()
167 |
168 | # Start the thread running the callable
169 | threading.Thread(target=display_loop_instance).start()
170 |
171 | # Log in to twitter and start the tracking stream
172 | auth = OAuthHandler(api_key, api_secret)
173 | auth.set_access_token(access_token_key, access_token_secret)
174 | stream = Stream(auth, display_loop_instance)
175 | stream.filter(track=[display_loop_instance.track_text], async=True)
176 | print "Starting"
177 | application.listen(8888)
178 | tornado.ioloop.IOLoop.instance().start()
179 | print "Stopping"
180 | stream.disconnect()
181 |
--------------------------------------------------------------------------------
/tweetbox/tweetbox4.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.append('/home/pi/py/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate')
3 | from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
4 | from tweepy.streaming import StreamListener
5 | from tweepy import OAuthHandler
6 | from tweepy import Stream
7 | import json
8 | import threading
9 | import time
10 | import textwrap
11 | import subprocess
12 | import tornado.ioloop
13 | import tornado.web
14 | import pickle
15 | from genericpath import exists
16 |
17 | api_key='---'
18 | api_secret='---'
19 |
20 | access_token_key='---'
21 | access_token_secret='---'
22 |
23 | class NullListener(StreamListener):
24 | def on_data(self, data):
25 | print data
26 |
27 | class DisplayLoop(StreamListener):
28 | """
29 | This class is a listener for tweet stream data. It's also callable so it
30 | can run the main display thread loop to update the display.
31 | """
32 | PICKLE_FILE = '/home/pi/py/tweetbox.pkl'
33 |
34 | def __init__(self):
35 | self.lcd = Adafruit_CharLCDPlate()
36 | self.lcd.backlight(self.lcd.RED)
37 | self.lcd.clear()
38 | self.track_text = 'jeremy'
39 | self.backlight_map = {'red':self.lcd.RED,
40 | 'green':self.lcd.GREEN,
41 | 'blue':self.lcd.BLUE,
42 | 'yellow':self.lcd.YELLOW,
43 | 'teal':self.lcd.TEAL,
44 | 'violet':self.lcd.VIOLET}
45 | self.msglist = []
46 | self.pos = 0
47 | self.tweet = 'Nothing yet'
48 |
49 | def set_backlight(self):
50 | words = self.tweet.lower().split(' ')
51 | use_default = True
52 | for w in words:
53 | if w in self.backlight_map:
54 | self.lcd.backlight(self.backlight_map[w])
55 | use_default = False
56 | break
57 | if use_default:
58 | self.lcd.backlight(self.lcd.WHITE)
59 |
60 | def on_data(self, data):
61 | print data
62 | tweet_data = json.loads(data)
63 | self.set_text(tweet_data['text'].encode('ascii', errors='backslashreplace'))
64 |
65 | def set_text(self, text):
66 | self.tweet = text
67 | self.msglist = [x.ljust(16) for x in textwrap.wrap(str(self.tweet),16)]
68 | self.pos = 0
69 | self.set_backlight()
70 | self.scroll_message()
71 | return True
72 |
73 | def on_error(self, status):
74 | print status
75 |
76 | def write_message(self,msg):
77 | self.lcd.home()
78 | self.lcd.message(msg)
79 |
80 | def scroll_message(self):
81 | "Displays the page of text and updates the scroll position for the next call"
82 | if len(self.msglist) == 0:
83 | self.write_message(''.ljust(16)+'\n'+''.ljust(16))
84 | elif len(self.msglist) == 1:
85 | self.write_message(self.msglist[0]+'\n'+''.ljust(16))
86 | elif len(self.msglist) == 2:
87 | self.write_message(self.msglist[0]+'\n'+self.msglist[1])
88 | else:
89 | if self.pos >= len(self.msglist)-1:
90 | self.pos = 0
91 | else:
92 | self.write_message(self.msglist[self.pos]+'\n'+self.msglist[self.pos+1])
93 | self.pos+=1
94 |
95 | def get_ip_address(self,interface):
96 | "Returns the IP address for the given interface e.g. eth0"
97 | try:
98 | s = subprocess.check_output(["ip","addr","show",interface])
99 | return s.split('\n')[2].strip().split(' ')[1].split('/')[0]
100 | except:
101 | return '?.?.?.?'
102 |
103 | def write_config(self):
104 | data = {"track_text":self.track_text, "backlight_map":self.backlight_map}
105 | output = open(self.PICKLE_FILE, 'wb')
106 | pickle.dump(data, output)
107 | output.close()
108 |
109 | def read_config(self):
110 | if exists(self.PICKLE_FILE):
111 | pkl_file = open(self.PICKLE_FILE, 'rb')
112 | data = pickle.load(pkl_file)
113 | pkl_file.close()
114 | self.track_text = data["track_text"]
115 | self.backlight_map = data["backlight_map"]
116 |
117 | def __call__(self):
118 | while True:
119 | if self.lcd.buttonPressed(self.lcd.LEFT):
120 | self.write_message(self.get_ip_address('eth0').ljust(16)+'\n'+self.get_ip_address('wlan0').ljust(16))
121 | else:
122 | self.scroll_message()
123 | time.sleep(1)
124 |
125 | class MainHandler(tornado.web.RequestHandler):
126 | def get(self):
127 | inverted_map = {v:k for k, v in display_loop_instance.backlight_map.items()}
128 | self.render("templates/form4.html",
129 | config_track=display_loop_instance.track_text,
130 | config_red=inverted_map[Adafruit_CharLCDPlate.RED],
131 | config_green=inverted_map[Adafruit_CharLCDPlate.GREEN],
132 | config_blue=inverted_map[Adafruit_CharLCDPlate.BLUE],
133 | config_yellow=inverted_map[Adafruit_CharLCDPlate.YELLOW],
134 | config_teal=inverted_map[Adafruit_CharLCDPlate.TEAL],
135 | config_violet=inverted_map[Adafruit_CharLCDPlate.VIOLET])
136 |
137 | def post(self):
138 | config_track = self.get_argument("config_track")
139 | colour_map = {self.get_argument("config_red"):Adafruit_CharLCDPlate.RED,
140 | self.get_argument("config_green"):Adafruit_CharLCDPlate.GREEN,
141 | self.get_argument("config_blue"):Adafruit_CharLCDPlate.BLUE,
142 | self.get_argument("config_yellow"):Adafruit_CharLCDPlate.YELLOW,
143 | self.get_argument("config_teal"):Adafruit_CharLCDPlate.TEAL,
144 | self.get_argument("config_violet"):Adafruit_CharLCDPlate.VIOLET
145 | }
146 | set_config(config_track, colour_map)
147 | #Use a redirect to avoid problems with refreshes in the browser from a form post
148 | self.redirect("/")
149 |
150 |
151 | def set_config(track_text, colour_map):
152 | print "restarting"
153 | display_loop_instance.set_text("Updating configuration")
154 | #Kill the old stream asynchronously
155 | global stream
156 | stream.listener = NullListener()
157 | stream.disconnect()
158 |
159 | display_loop_instance.track_text = track_text
160 | display_loop_instance.backlight_map = colour_map
161 | display_loop_instance.write_config()
162 |
163 | #Make a new stream
164 | stream = Stream(auth, display_loop_instance)
165 | stream.filter(track=[display_loop_instance.track_text], async=True)
166 | display_loop_instance.set_text("Updated configuration")
167 |
168 | application = tornado.web.Application([
169 | (r"/", MainHandler),
170 | ])
171 |
172 |
173 | display_loop_instance = DisplayLoop()
174 | display_loop_instance.read_config()
175 |
176 | # Start the thread running the callable
177 | threading.Thread(target=display_loop_instance).start()
178 |
179 | # Log in to twitter and start the tracking stream
180 | auth = OAuthHandler(api_key, api_secret)
181 | auth.set_access_token(access_token_key, access_token_secret)
182 | stream = Stream(auth, display_loop_instance)
183 | stream.filter(track=[display_loop_instance.track_text], async=True)
184 | print "Starting"
185 | application.listen(8888)
186 | tornado.ioloop.IOLoop.instance().start()
187 | print "Stopping"
188 | stream.disconnect()
189 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------