textual version display on boot
This commit is contained in:
parent
2f44e49150
commit
d1d0ee2aef
72
README.md
72
README.md
@ -2,40 +2,21 @@
|
||||
|
||||

|
||||
|
||||
EBB is an e-paper bulletin board that syncs over [Scuttlebutt](https://scuttlebutt.nz) (SSB). This program is in alpha so proceed at your own risk :)
|
||||
EBB is an e-paper bulletin board that syncs over [Scuttlebutt](https://scuttlebutt.nz) (SSB). EBB is a [Slow Web](https://www.are.na/morgan-sutherland/slow-web) device. As such it is not intended to be *fast*. Thus users must exercise great patience while operating EBB.
|
||||
|
||||
## Usage
|
||||
|
||||
EBB is a [Slow Web](https://www.are.na/morgan-sutherland/slow-web) device. As such it is not intended to be *fast*. Thus users must exercise great patience while operating EBB.
|
||||
Check out the [operators manual (pdf)](http://teafry.me/ebb/operatorsmanual.pdf)
|
||||
|
||||
After you plug in the device, while the program is loading, the LED is purple, indicating you should wait before interacting with the device. Every couple hours the EBB db is synchronized with SSB and during this time the LED shines white (also wait to interact).
|
||||
|
||||
The device will automatically rotate through images in the database after a set period of time.
|
||||
|
||||
There are 5 buttons on the left side, they are numbered 1-5 from top to bottom:
|
||||
|
||||
**button 1:** takes a photo. The LED will go green while the photo is being taken. The photo will be taken when the red light on the camera itself goes out. A soon-to-be-written feature will allow the user to decide whether they want to keep the photo just taken and whether to store it locally or to post it to SSB.
|
||||
|
||||
**button 2:** advance to the next photo. LED will turn blue while this action is busy.
|
||||
|
||||
**button 3:** currently this button goes to the previous photo in the database (LED will turn blue while this action is busy) but soon the plan is for it to provide a menu with the options:
|
||||
* power down
|
||||
* add friend (via QR)
|
||||
* show my QR (take pic/read the QR, txt to friend)
|
||||
|
||||
**button 4:** delete current photo. LED will go red and an alert with instructions is presented to the user on the e-paper screen. Press button 4 again to confirm delete or press any other button to cancel. The actual BMP wont be deleted, only the entry in the database (and of course it can't be deleted from SSB, so).
|
||||
|
||||
**button 5:** display the weather (currently doesn't work; a planned feature :)
|
||||
|
||||
----------
|
||||
<br>
|
||||
|
||||
## Building one
|
||||
|
||||
There are *a lot* of steps here, this is not for the faint of heart. But if you're handy on the commandline it shouldn't be too bad. I intend to streamline setup greatly.
|
||||
This program is in alpha so proceed at your own risk :)
|
||||
|
||||
### hardware
|
||||
|
||||
This would probably work with a variety of parts but here are the recommended hardware components:
|
||||
recommended hardware components:
|
||||
|
||||
| part | cost | link |
|
||||
| -------- | -------- | -------- |
|
||||
@ -45,7 +26,6 @@ This would probably work with a variety of parts but here are the recommended ha
|
||||
| micro-sd card | variable, $5.8 on amazon | |
|
||||
| buttons | $7 | https://www.adafruit.com/product/3582 |
|
||||
| camera | $7 | [aliexpres](https://www.aliexpress.com/item/32788881215.html?spm=a2g0s.12269583.0.0.55eb6619CDSuac) (confirmed works) or [alt-aliexpress](https://www.aliexpress.com/item/32293433078.html?spm=a2g0s.9042311.0.0.349f4c4dYCXYQ3)|
|
||||
| -------- | -------- | -------- |
|
||||
| total: | | $65 plus shipping and tax, ~$75 total |
|
||||
|
||||
you'll also need a micro-usb cable, usb power supply and materials to build a case from.
|
||||
@ -56,35 +36,39 @@ you'll also need a micro-usb cable, usb power supply and materials to build a ca
|
||||
|
||||
2. Then you just gotta plug in the camera and pop the e-paper hat on top of the headers.
|
||||
|
||||
3. build a case out of lego or something. Have fun with it :)
|
||||
3. build a case out of lego or something. Have fun with it. I've found it handy to mount the camera to some articulating lego to more easily take pictures of more things.
|
||||
|
||||
|
||||
### software
|
||||
|
||||
1. download [raspbian lite](https://www.raspberrypi.org/downloads/raspbian/)(or whatever basic raspbian image)
|
||||
1. download [raspbian lite](https://www.raspberrypi.org/downloads/raspbian/) (or whatever basic raspbian image)
|
||||
2. [write the image to your SD card](https://www.raspberrypi.org/documentation/installation/installing-images/)
|
||||
3. follow [these instructions](https://desertbot.io/blog/ssh-into-pi-zero-over-usb) to get into it over usb. AND OR, put in wifi credentials onto the card. [This page](https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md) says how to do it.
|
||||
3. [Put in wifi credentials into the WPA_supplicant.conf file](https://raspberrypi.stackexchange.com/questions/67649/raspberry-pi-zero-w-headless-using-wpa-supplicant-conf-not-working).
|
||||
4. [enable SSH on the device](https://www.raspberrypi.org/documentation/remote-access/ssh/)
|
||||
4. put the card in the pi and boot it up
|
||||
5. ssh-in (or connect to monitor if you didn't do step 3, connect to monitor/keyboard...)
|
||||
6. use `sudo raspi-config`[(howto)](https://www.raspberrypi.org/documentation/configuration/raspi-config.md) to change timezone, set a new hostname, enable ssh, change user password, enable SPI (for e-paper screen), enable I2C (for button shim), enable camera.
|
||||
6. use `sudo raspi-config` [(howto)](https://www.raspberrypi.org/documentation/configuration/raspi-config.md) to adjust:
|
||||
|
||||
- set a new hostname
|
||||
- enable ssh (if you haven't already)
|
||||
- change user password
|
||||
- enable SPI (for e-paper screen)
|
||||
- enable I2C (for button shim)
|
||||
- enable camera.
|
||||
- timezone config
|
||||
|
||||
|
||||
7. run all this stuff: (this should all be scripted but for now we're setting all these parts up manually...)
|
||||
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
sudo apt install unattended-upgrades
|
||||
sudo apt install python-dev
|
||||
sudo apt install python-pip
|
||||
sudo apt install python-buttonshim
|
||||
sudo apt install libjpeg-dev zlib1g-dev
|
||||
sudo apt install git
|
||||
pip install spidev
|
||||
pip install tinydb
|
||||
pip install pillow --no-cache-dir
|
||||
sudo apt update -y && sudo apt upgrade -y
|
||||
sudo apt install unattended-upgrades python-dev python-pip python-buttonshim libjpeg-dev zlib1g-dev git -y
|
||||
pip install spidev tinydb pillow --no-cache-dir
|
||||
```
|
||||
|
||||
need to install an ARMv6 compatible NPM. This should work:
|
||||
(third line can take a while...)
|
||||
|
||||
Now need to install an ARMv6 compatible NPM. This should work:
|
||||
```
|
||||
curl -o node.tar.gz https://unofficial-builds.nodejs.org/download/release/v13.8.0/node-v13.8.0-linux-armv6l.tar.gz
|
||||
tar -xzf node.tar.gz
|
||||
@ -93,9 +77,11 @@ sudo cp -r node-v13.8.0-linux-armv6l/* /usr/local
|
||||
|
||||
If that doesn't work you can [read more about installing node on arm v6 architecture](https://www.thepolyglotdeveloper.com/2018/03/install-nodejs-raspberry-pi-zero-w-nodesource/). Also [the builds are here](https://unofficial-builds.nodejs.org/).
|
||||
|
||||
|
||||
<br>
|
||||
#### clone the repo
|
||||
`git clone https://git.laboratoryb.org/trav/ebb.git` ideally right in your home directory.
|
||||
ideally right in your home directory.
|
||||
|
||||
`git clone https://git.laboratoryb.org/trav/ebb.git`
|
||||
|
||||
#### setup SSB
|
||||
I can't remember how I got ssb-server to work, `sudo npm install -g ssb-server` throws `illegal instruction`. Something to do with a woknky version of Node. So my **extremely** hacky workaround is to unzip `ssb-server.zip` from the install directory into `/usr/local/lib/node_modules/`. This is v bad and needs to be fixed asap. [SSB-server](https://github.com/ssbc/ssb-server) is made available via the MIT licese.
|
||||
|
||||
14
addtoDB.py
14
addtoDB.py
@ -36,12 +36,14 @@ def addFile(pathToImage, pathToDB, SSBidentify):
|
||||
#print("heres the whole db")
|
||||
#print(db.all())
|
||||
|
||||
#SEND TO SSB! WOOOO
|
||||
try:
|
||||
result = subprocess.call('./ssbpost.sh ' + pathToImage, shell=True)
|
||||
except:
|
||||
print 'traceback.format_exc():\n%s' % traceback.format_exc()
|
||||
exit()
|
||||
#unless you say don't post to ssb, post to ssb
|
||||
if SSBidentify != -1:
|
||||
#SEND TO SSB! WOOOO
|
||||
try:
|
||||
result = subprocess.call('./ssbpost.sh ' + pathToImage, shell=True)
|
||||
except:
|
||||
print 'traceback.format_exc():\n%s' % traceback.format_exc()
|
||||
exit()
|
||||
|
||||
return pathToImage
|
||||
|
||||
|
||||
167
carousel.py
167
carousel.py
@ -5,6 +5,7 @@
|
||||
#
|
||||
# carousel iterates through all posts in posts.json
|
||||
|
||||
import os
|
||||
import epd4in2
|
||||
import traceback
|
||||
import time
|
||||
@ -29,9 +30,9 @@ buttonshim.set_pixel(0xFF, 0x00, 0xFF)
|
||||
intervalTime = 1800
|
||||
syncTime = 3600
|
||||
#keep track of where we are moving through intervalTime, syncTime and where we are in the db, and what flier we're currently displaying
|
||||
timeIndex = intervalTime
|
||||
timeIndex = 1200
|
||||
syncIndex = 0
|
||||
dbIndex = 0
|
||||
dbIndex = 1
|
||||
flierPath = "noneyet"
|
||||
button_flag = "null"
|
||||
|
||||
@ -50,17 +51,27 @@ for item in db:
|
||||
dbCount = item.doc_id
|
||||
print dbCount
|
||||
|
||||
#initialize display
|
||||
#PIL.Image.new(mode, size, color=0)
|
||||
#initialize display and display boot image
|
||||
#grab the entry at dbIndex, newFlier is a dict
|
||||
newFlier = db.get(doc_id=dbIndex)
|
||||
flierPath = newFlier["path"]
|
||||
Limage = Image.new('1', (epd4in2.EPD_HEIGHT, epd4in2.EPD_WIDTH), 255) # 255: clear the frame
|
||||
try:
|
||||
font36 = ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', 36)
|
||||
epd = epd4in2.EPD()
|
||||
epd.init()
|
||||
bmp = Image.open(flierPath)
|
||||
Limage.paste(bmp)
|
||||
draw = ImageDraw.Draw(Limage)
|
||||
draw.text((2, 240), 'EBB', font = font18, fill = 255)
|
||||
draw.text((2, 260), 'version .02', font = font18, fill = 255)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
time.sleep(2)
|
||||
epd.sleep()
|
||||
except:
|
||||
print 'traceback.format_exc():\n%s' % traceback.format_exc()
|
||||
exit()
|
||||
|
||||
|
||||
## button press contingencies ##
|
||||
@buttonshim.on_press(buttonshim.BUTTON_A)
|
||||
def button_a(button, pressed):
|
||||
@ -140,10 +151,9 @@ while True:
|
||||
|
||||
flierPath = newFlier["path"]
|
||||
|
||||
#display the images
|
||||
#display the image
|
||||
try:
|
||||
epd.init()
|
||||
#Limage = Image.new('1', (epd4in2.EPD_HEIGHT, epd4in2.EPD_WIDTH), 255) # 255: clear the frame
|
||||
bmp = Image.open(flierPath)
|
||||
Limage.paste(bmp)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
@ -159,39 +169,132 @@ while True:
|
||||
|
||||
#take pic
|
||||
if button_flag == "button_1":
|
||||
|
||||
#generate unique file_name
|
||||
unique = uuid.uuid4()
|
||||
unique = str(unique)
|
||||
jpgpath = imagesPath + unique + '.jpg'
|
||||
|
||||
#take photo
|
||||
try:
|
||||
result = subprocess.call(['raspistill', '-o', jpgpath, '-vf', '-w', '300', '-h', '400', '-t', '1000'])
|
||||
except:
|
||||
print 'traceback.format_exc():\n%s' % traceback.format_exc()
|
||||
exit()
|
||||
|
||||
#generate unique bmp name
|
||||
bmpath = imagesPath + str(unique) + '.bmp'
|
||||
bmpath = imagesPath + unique + '.bmp'
|
||||
|
||||
#convert to bmp
|
||||
im = Image.open(jpgpath)
|
||||
im = im.convert("1")
|
||||
im.save(bmpath)
|
||||
|
||||
#add that file to the db. 0 is because this isn't coming from SSB, it's local
|
||||
addtoDB.addFile(bmpath,dbPath,0)
|
||||
#update dbCount
|
||||
for item in db:
|
||||
dbCount = item.doc_id
|
||||
#loop in case we wanna re-take it
|
||||
exitPhotoMode = False
|
||||
while exitPhotoMode == False:
|
||||
|
||||
#display the image
|
||||
epd.init()
|
||||
Limage2 = Image.new('1', (epd4in2.EPD_HEIGHT, epd4in2.EPD_WIDTH), 255) # 255: clear the frame
|
||||
bmp = Image.open(bmpath)
|
||||
Limage.paste(bmp)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
#ok green done
|
||||
#take photo
|
||||
try:
|
||||
result = subprocess.call(['raspistill', '-o', jpgpath, '-vf', '-hf', '-w', '300', '-h', '400', '-t', '1000'])
|
||||
except:
|
||||
print 'traceback.format_exc():\n%s' % traceback.format_exc()
|
||||
exit()
|
||||
|
||||
#convert to bmp
|
||||
im = Image.open(jpgpath)
|
||||
im = im.convert("1")
|
||||
im.save(bmpath)
|
||||
|
||||
#display the image
|
||||
epd.init()
|
||||
bmp = Image.open(bmpath)
|
||||
Limage.paste(bmp)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
|
||||
#wait for user decision on photo
|
||||
waited = 0
|
||||
button_flag = "none"
|
||||
|
||||
#strobe light green yellow red for a while
|
||||
while (button_flag == "none") and (waited < 30):
|
||||
buttonshim.set_pixel(0xFF, 0x00, 0x00)
|
||||
time.sleep(.2)
|
||||
buttonshim.set_pixel(0xFF, 0xFF, 0x00)
|
||||
time.sleep(.2)
|
||||
buttonshim.set_pixel(0x00, 0xFF, 0x00)
|
||||
time.sleep(.2)
|
||||
buttonshim.set_pixel(0xFF, 0xFF, 0x00)
|
||||
time.sleep(.2)
|
||||
waited+=1
|
||||
|
||||
#if still not sure, give em the menu
|
||||
if button_flag == "none":
|
||||
#ok time to display menu
|
||||
draw = ImageDraw.Draw(Limage)
|
||||
font18 = ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', 24)
|
||||
draw.text((2, 0), 'press button 1 to:', font = font18, fill = 255)
|
||||
draw.text((2, 40), 'post online', font = font18, fill = 255)
|
||||
draw.text((2, 80), 'button 2: post photo', font = font18, fill = 255)
|
||||
draw.text((2, 120), 'here only', font = font18, fill = 255)
|
||||
draw.text((2, 160), 'button 3: retake', font = font18, fill = 255)
|
||||
draw.text((2, 200), 'buttons 4 or 5:', font = font18, fill = 255)
|
||||
draw.text((2, 240), 'exit photo mode', font = font18, fill = 255)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
|
||||
#now just wait for them to press something
|
||||
while button_flag == "none":
|
||||
buttonshim.set_pixel(0xFF, 0x00, 0x00)
|
||||
time.sleep(.2)
|
||||
buttonshim.set_pixel(0xFF, 0xFF, 0x00)
|
||||
time.sleep(.2)
|
||||
buttonshim.set_pixel(0x00, 0xFF, 0x00)
|
||||
time.sleep(.2)
|
||||
buttonshim.set_pixel(0xFF, 0xFF, 0x00)
|
||||
time.sleep(.2)
|
||||
|
||||
#led to thinking mode
|
||||
buttonshim.set_pixel(0x00, 0x00, 0xFF)
|
||||
|
||||
#post to ssb
|
||||
if button_flag == "button_1":
|
||||
button_flag == "null"
|
||||
#add the photo to the db/ssb
|
||||
addtoDB.addFile(bmpath,dbPath,0)
|
||||
#update dbCount
|
||||
for item in db:
|
||||
dbCount = item.doc_id
|
||||
exitPhotoMode = True
|
||||
|
||||
#display the image to clear the menu (also display text "posted")
|
||||
font18 = ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', 24)
|
||||
bmp = Image.open(bmpath)
|
||||
Limage.paste(bmp)
|
||||
draw = ImageDraw.Draw(Limage)
|
||||
draw.text((2, 240), 'PHOTO POSTED', font = font18, fill = 255)
|
||||
draw.text((2, 260), 'online!', font = font18, fill = 255)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
|
||||
#post only locally
|
||||
if button_flag == "button_2":
|
||||
button_flag == "null"
|
||||
#add that file to the db. -1 tells addtoDB not to post to ssb.
|
||||
addtoDB.addFile(bmpath,dbPath,-1)
|
||||
#update dbCount
|
||||
for item in db:
|
||||
dbCount = item.doc_id
|
||||
exitPhotoMode = True
|
||||
#display the image to clear the menu (also display text "posted")
|
||||
font18 = ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', 24)
|
||||
bmp = Image.open(bmpath)
|
||||
Limage.paste(bmp)
|
||||
draw = ImageDraw.Draw(Limage)
|
||||
draw.text((2, 240), 'PHOTO POSTED', font = font18, fill = 255)
|
||||
draw.text((2, 260), 'to this device only', font = font18, fill = 255)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
|
||||
#reshoot the picture
|
||||
if button_flag == "button_3":
|
||||
button_flag == "null"
|
||||
#nothin! loop around... exitPhotoMode still false
|
||||
|
||||
#exit photomode, delete photo
|
||||
if (button_flag == "button_4") or (button_flag == "button_5"):
|
||||
button_flag == "null"
|
||||
exitPhotoMode = True
|
||||
os.remove(bmpath)
|
||||
os.remove(jpgpath)
|
||||
|
||||
#led off
|
||||
buttonshim.set_pixel(0x00, 0x00, 0x00)
|
||||
time.sleep(3)
|
||||
timeIndex+=2
|
||||
@ -290,7 +393,7 @@ while True:
|
||||
|
||||
#display the weather
|
||||
epd.init()
|
||||
Limage2 = Image.new('1', (epd4in2.EPD_HEIGHT, epd4in2.EPD_WIDTH), 255) # 255: clear the frame
|
||||
Limage = Image.new('1', (epd4in2.EPD_HEIGHT, epd4in2.EPD_WIDTH), 255) # 255: clear the frame
|
||||
bmp = Image.open("btv.bmp")
|
||||
Limage.paste(bmp)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
|
||||
BIN
etc/examples and tests/100x100.bmp
Normal file
BIN
etc/examples and tests/100x100.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
etc/examples and tests/4in2.bmp
Normal file
BIN
etc/examples and tests/4in2.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
99
etc/examples and tests/buttonshimexamplepihole.py
Normal file
99
etc/examples and tests/buttonshimexamplepihole.py
Normal file
@ -0,0 +1,99 @@
|
||||
#!/user/bin/env python
|
||||
|
||||
import signal
|
||||
import buttonshim
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
print("""
|
||||
Pi-Hole Button Control Running....
|
||||
|
||||
Press Ctrl+C to Exit.
|
||||
""")
|
||||
|
||||
#Cycle and clear LEDs on startup (visual indication the script is running)
|
||||
buttonshim.set_pixel(255,0,0)
|
||||
time.sleep(0.3)
|
||||
buttonshim.set_pixel(0,255,0)
|
||||
time.sleep(0.3)
|
||||
buttonshim.set_pixel(0,0,255)
|
||||
time.sleep(0.3)
|
||||
buttonshim.set_pixel(0,0,0)
|
||||
pressId = 0
|
||||
|
||||
while True:
|
||||
def DisablePiholeTimer(numSecs):
|
||||
global pressId
|
||||
loopId = pressId
|
||||
for i in range(0,numSecs):
|
||||
if ( loopId != pressId):
|
||||
print "Ending loop with ID: " + str(loopId)
|
||||
return
|
||||
print "Pi-Hole disabled for " + str(numSecs-i)
|
||||
buttonshim.set_pixel(255,255,0)
|
||||
time.sleep(0.5)
|
||||
buttonshim.set_pixel(255,150,0)
|
||||
time.sleep(0.5)
|
||||
buttonshim.set_pixel(0,0,0)
|
||||
print "Pi-Hole reenabled"
|
||||
|
||||
def SuspendPihole():
|
||||
global pressId
|
||||
loopId = pressId
|
||||
print "Pi-Hole suspended"
|
||||
while (loopId == pressId):
|
||||
buttonshim.set_pixel(255,0,0)
|
||||
time.sleep(0.5)
|
||||
buttonshim.set_pixel(0,0,0)
|
||||
time.sleep(0.5)
|
||||
|
||||
def EnablePihole():
|
||||
global pressId
|
||||
loopId = pressId
|
||||
print "Pi-Hole enabled"
|
||||
for i in range(0,2):
|
||||
buttonshim.set_pixel(0,255,0)
|
||||
time.sleep(0.3)
|
||||
buttonshim.set_pixel(0,0,0)
|
||||
time.sleep(0.3)
|
||||
|
||||
|
||||
@buttonshim.on_press(buttonshim.BUTTON_A)
|
||||
def button_a(button, pressed):
|
||||
print "Disabling Pi-Hole for 300s"
|
||||
global pressId
|
||||
pressId += 1
|
||||
subprocess.call(['pihole','disable','300s'])
|
||||
DisablePiholeTimer(int(300))
|
||||
|
||||
@buttonshim.on_press(buttonshim.BUTTON_B)
|
||||
def button_b(button, pressed):
|
||||
print "Disabling Pi-Hole for 1800s"
|
||||
global pressId
|
||||
pressId += 1
|
||||
subprocess.call(['pihole','disable','1800s'])
|
||||
DisablePiholeTimer(int(1800))
|
||||
|
||||
@buttonshim.on_press(buttonshim.BUTTON_C)
|
||||
def button_c(button, pressed):
|
||||
print "This button, it does nothing"
|
||||
|
||||
@buttonshim.on_press(buttonshim.BUTTON_D)
|
||||
def button_d(button, pressed):
|
||||
print "Suspending Pi-Hole"
|
||||
global pressId
|
||||
pressId += 1
|
||||
subprocess.call(['pihole','disable'])
|
||||
SuspendPihole()
|
||||
|
||||
@buttonshim.on_press(buttonshim.BUTTON_E)
|
||||
def button_e(button, pressed):
|
||||
print "Enabling Pi-Hole"
|
||||
global pressId
|
||||
pressId += 1
|
||||
subprocess.call(['pihole','enable'])
|
||||
EnablePihole()
|
||||
|
||||
|
||||
|
||||
signal.pause()
|
||||
279
etc/examples and tests/epd4in2.py
Normal file
279
etc/examples and tests/epd4in2.py
Normal file
@ -0,0 +1,279 @@
|
||||
# /*****************************************************************************
|
||||
# * | File : EPD_1in54.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Electronic paper driver
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V3.0
|
||||
# * | Date : 2018-11-06
|
||||
# * | Info : python2 demo
|
||||
# * 1.Remove:
|
||||
# digital_write(self, pin, value)
|
||||
# digital_read(self, pin)
|
||||
# delay_ms(self, delaytime)
|
||||
# set_lut(self, lut)
|
||||
# self.lut = self.lut_full_update
|
||||
# * 2.Change:
|
||||
# display_frame -> TurnOnDisplay
|
||||
# set_memory_area -> SetWindow
|
||||
# set_memory_pointer -> SetCursor
|
||||
# get_frame_buffer -> getbuffer
|
||||
# set_frame_memory -> display
|
||||
# * 3.How to use
|
||||
# epd = epd2in7.EPD()
|
||||
# epd.init(epd.lut_full_update)
|
||||
# image = Image.new('1', (epd1in54.EPD_WIDTH, epd1in54.EPD_HEIGHT), 255)
|
||||
# ...
|
||||
# drawing ......
|
||||
# ...
|
||||
# epd.display(getbuffer(image))
|
||||
# ******************************************************************************/
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documnetation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
import epdconfig
|
||||
from PIL import Image
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
# Display resolution
|
||||
EPD_WIDTH = 400
|
||||
EPD_HEIGHT = 300
|
||||
|
||||
# GDEW042T2 commands
|
||||
PANEL_SETTING = 0x00
|
||||
POWER_SETTING = 0x01
|
||||
POWER_OFF = 0x02
|
||||
POWER_OFF_SEQUENCE_SETTING = 0x03
|
||||
POWER_ON = 0x04
|
||||
POWER_ON_MEASURE = 0x05
|
||||
BOOSTER_SOFT_START = 0x06
|
||||
DEEP_SLEEP = 0x07
|
||||
DATA_START_TRANSMISSION_1 = 0x10
|
||||
DATA_STOP = 0x11
|
||||
DISPLAY_REFRESH = 0x12
|
||||
DATA_START_TRANSMISSION_2 = 0x13
|
||||
LUT_FOR_VCOM = 0x20
|
||||
LUT_WHITE_TO_WHITE = 0x21
|
||||
LUT_BLACK_TO_WHITE = 0x22
|
||||
LUT_WHITE_TO_BLACK = 0x23
|
||||
LUT_BLACK_TO_BLACK = 0x24
|
||||
PLL_CONTROL = 0x30
|
||||
TEMPERATURE_SENSOR_COMMAND = 0x40
|
||||
TEMPERATURE_SENSOR_SELECTION = 0x41
|
||||
TEMPERATURE_SENSOR_WRITE = 0x42
|
||||
TEMPERATURE_SENSOR_READ = 0x43
|
||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50
|
||||
LOW_POWER_DETECTION = 0x51
|
||||
TCON_SETTING = 0x60
|
||||
RESOLUTION_SETTING = 0x61
|
||||
GSST_SETTING = 0x65
|
||||
GET_STATUS = 0x71
|
||||
AUTO_MEASUREMENT_VCOM = 0x80
|
||||
READ_VCOM_VALUE = 0x81
|
||||
VCM_DC_SETTING = 0x82
|
||||
PARTIAL_WINDOW = 0x90
|
||||
PARTIAL_IN = 0x91
|
||||
PARTIAL_OUT = 0x92
|
||||
PROGRAM_MODE = 0xA0
|
||||
ACTIVE_PROGRAMMING = 0xA1
|
||||
READ_OTP = 0xA2
|
||||
POWER_SAVING = 0xE3
|
||||
class EPD:
|
||||
def __init__(self):
|
||||
self.reset_pin = epdconfig.RST_PIN
|
||||
self.dc_pin = epdconfig.DC_PIN
|
||||
self.busy_pin = epdconfig.BUSY_PIN
|
||||
self.width = EPD_WIDTH
|
||||
self.height = EPD_HEIGHT
|
||||
|
||||
lut_vcom0 = [
|
||||
0x00, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x00, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
lut_ww = [
|
||||
0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
lut_bw = [
|
||||
0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
lut_wb = [
|
||||
0x80, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x80, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
lut_bb = [
|
||||
0x80, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x80, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]
|
||||
|
||||
# Hardware reset
|
||||
def reset(self):
|
||||
epdconfig.digital_write(self.reset_pin, GPIO.HIGH)
|
||||
epdconfig.delay_ms(200)
|
||||
epdconfig.digital_write(self.reset_pin, GPIO.LOW) # module reset
|
||||
epdconfig.delay_ms(200)
|
||||
epdconfig.digital_write(self.reset_pin, GPIO.HIGH)
|
||||
epdconfig.delay_ms(200)
|
||||
|
||||
def send_command(self, command):
|
||||
epdconfig.digital_write(self.dc_pin, GPIO.LOW)
|
||||
epdconfig.spi_writebyte([command])
|
||||
|
||||
def send_data(self, data):
|
||||
epdconfig.digital_write(self.dc_pin, GPIO.HIGH)
|
||||
epdconfig.spi_writebyte([data])
|
||||
|
||||
def wait_until_idle(self):
|
||||
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
|
||||
epdconfig.delay_ms(100)
|
||||
|
||||
def set_lut(self):
|
||||
self.send_command(LUT_FOR_VCOM) # vcom
|
||||
for count in range(0, 44):
|
||||
self.send_data(self.lut_vcom0[count])
|
||||
self.send_command(LUT_WHITE_TO_WHITE) # ww --
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.lut_ww[count])
|
||||
self.send_command(LUT_BLACK_TO_WHITE) # bw r
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.lut_bw[count])
|
||||
self.send_command(LUT_WHITE_TO_BLACK) # wb w
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.lut_bb[count])
|
||||
self.send_command(LUT_BLACK_TO_BLACK) # bb b
|
||||
for count in range(0, 42):
|
||||
self.send_data(self.lut_wb[count])
|
||||
|
||||
def init(self):
|
||||
if (epdconfig.module_init() != 0):
|
||||
return -1
|
||||
# EPD hardware init start
|
||||
self.reset()
|
||||
|
||||
self.send_command(POWER_SETTING)
|
||||
self.send_data(0x03) # VDS_EN, VDG_EN
|
||||
self.send_data(0x00) # VCOM_HV, VGHL_LV[1], VGHL_LV[0]
|
||||
self.send_data(0x2b) # VDH
|
||||
self.send_data(0x2b) # VDL
|
||||
self.send_command(BOOSTER_SOFT_START)
|
||||
self.send_data(0x17)
|
||||
self.send_data(0x17)
|
||||
self.send_data(0x17)
|
||||
self.send_command(POWER_ON)
|
||||
self.wait_until_idle()
|
||||
self.send_command(PANEL_SETTING)
|
||||
self.send_data(0xbf) # KW-BF KWR-AF BWROTP 0f
|
||||
self.send_data(0x0d)
|
||||
self.send_command(PLL_CONTROL)
|
||||
self.send_data(0x3c) # 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
|
||||
|
||||
self.send_command(0x61); # resolution setting
|
||||
self.send_data(0x01);
|
||||
self.send_data(0x90); # 128
|
||||
self.send_data(0x01);
|
||||
self.send_data(0x2c);
|
||||
|
||||
self.send_command(0x82); # vcom_DC setting
|
||||
self.send_data(0x28);
|
||||
|
||||
self.send_command(0X50); # VCOM AND DATA INTERVAL SETTING
|
||||
self.send_data(0x97); # 97white border 77black border VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7
|
||||
|
||||
self.set_lut()
|
||||
# EPD hardware init end
|
||||
return 0
|
||||
|
||||
def getbuffer(self, image):
|
||||
# print "bufsiz = ",(self.width/8) * self.height
|
||||
buf = [0xFF] * ((self.width/8) * self.height)
|
||||
image_monocolor = image.convert('1')
|
||||
imwidth, imheight = image_monocolor.size
|
||||
pixels = image_monocolor.load()
|
||||
# print "imwidth = %d, imheight = %d",imwidth,imheight
|
||||
if(imwidth == self.width and imheight == self.height):
|
||||
print "Horizontal"
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
# Set the bits for the column of pixels at the current position.
|
||||
if pixels[x, y] == 0:
|
||||
buf[(x + y * self.width) / 8] &= ~(0x80 >> (x % 8))
|
||||
elif(imwidth == self.height and imheight == self.width):
|
||||
print "Vertical"
|
||||
for y in range(imheight):
|
||||
for x in range(imwidth):
|
||||
newx = y
|
||||
newy = self.height - x - 1
|
||||
if pixels[x, y] == 0:
|
||||
buf[(newx + newy*self.width) / 8] &= ~(0x80 >> (y % 8))
|
||||
return buf
|
||||
|
||||
def display(self, image):
|
||||
self.send_command(DATA_START_TRANSMISSION_1)
|
||||
for i in range(0, self.width * self.height / 8):
|
||||
self.send_data(0xFF)
|
||||
self.send_command(DATA_START_TRANSMISSION_2)
|
||||
for i in range(0, self.width * self.height / 8):
|
||||
self.send_data(image[i])
|
||||
self.send_command(DISPLAY_REFRESH)
|
||||
self.wait_until_idle()
|
||||
|
||||
def Clear(self, color):
|
||||
self.send_command(DATA_START_TRANSMISSION_1)
|
||||
for i in range(0, self.width * self.height / 8):
|
||||
self.send_data(0xFF)
|
||||
self.send_command(DATA_START_TRANSMISSION_2)
|
||||
for i in range(0, self.width * self.height / 8):
|
||||
self.send_data(0xFF)
|
||||
self.send_command(DISPLAY_REFRESH)
|
||||
self.wait_until_idle()
|
||||
|
||||
def sleep(self):
|
||||
self.send_command(POWER_OFF)
|
||||
self.wait_until_idle()
|
||||
self.send_command(DEEP_SLEEP)
|
||||
self.send_data(0XA5)
|
||||
### END OF FILE ###
|
||||
|
||||
73
etc/examples and tests/epdconfig.py
Normal file
73
etc/examples and tests/epdconfig.py
Normal file
@ -0,0 +1,73 @@
|
||||
# /*****************************************************************************
|
||||
# * | File : EPD_1in54.py
|
||||
# * | Author : Waveshare team
|
||||
# * | Function : Hardware underlying interface
|
||||
# * | Info :
|
||||
# *----------------
|
||||
# * | This version: V2.0
|
||||
# * | Date : 2018-11-01
|
||||
# * | Info :
|
||||
# * 1.Remove:
|
||||
# digital_write(self, pin, value)
|
||||
# digital_read(self, pin)
|
||||
# delay_ms(self, delaytime)
|
||||
# set_lut(self, lut)
|
||||
# self.lut = self.lut_full_update
|
||||
# ******************************************************************************/
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documnetation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
import spidev
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
|
||||
# Pin definition
|
||||
RST_PIN = 17
|
||||
DC_PIN = 25
|
||||
CS_PIN = 8
|
||||
BUSY_PIN = 24
|
||||
|
||||
# SPI device, bus = 0, device = 0
|
||||
SPI = spidev.SpiDev(0, 0)
|
||||
|
||||
def digital_write(pin, value):
|
||||
GPIO.output(pin, value)
|
||||
|
||||
def digital_read(pin):
|
||||
return GPIO.input(BUSY_PIN)
|
||||
|
||||
def delay_ms(delaytime):
|
||||
time.sleep(delaytime / 1000.0)
|
||||
|
||||
def spi_writebyte(data):
|
||||
SPI.writebytes(data)
|
||||
|
||||
def module_init():
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setwarnings(False)
|
||||
GPIO.setup(RST_PIN, GPIO.OUT)
|
||||
GPIO.setup(DC_PIN, GPIO.OUT)
|
||||
GPIO.setup(CS_PIN, GPIO.OUT)
|
||||
GPIO.setup(BUSY_PIN, GPIO.IN)
|
||||
SPI.max_speed_hz = 2000000
|
||||
SPI.mode = 0b00
|
||||
return 0;
|
||||
|
||||
### END OF FILE ###
|
||||
58
etc/examples and tests/photodisplaytest.py
Normal file
58
etc/examples and tests/photodisplaytest.py
Normal file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
#this script takes a file as an option and adds that file to the db
|
||||
|
||||
import optparse
|
||||
import traceback
|
||||
import os, sys
|
||||
import time
|
||||
import uuid
|
||||
import subprocess
|
||||
import epd4in2
|
||||
import traceback
|
||||
from PIL import Image,ImageDraw,ImageFont
|
||||
|
||||
#generate unique file_name
|
||||
unique = uuid.uuid4()
|
||||
unique = str(unique)
|
||||
jpgpath = 'photos/' + unique + '.jpg'
|
||||
bmppath = 'photos/' + unique + '.bmp'
|
||||
|
||||
#take photo
|
||||
try:
|
||||
result = subprocess.call(['raspistill', '-o', jpgpath])
|
||||
print (result)
|
||||
|
||||
except:
|
||||
print 'traceback.format_exc():\n%s' % traceback.format_exc()
|
||||
exit()
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
#convert
|
||||
size = 400, 300
|
||||
im = Image.open(jpgpath)
|
||||
print("opening...")
|
||||
print (jpgpath)
|
||||
im = im.rotate(180, Image.NEAREST, "expand=1")
|
||||
im.thumbnail(size, Image.BICUBIC)
|
||||
im = im.convert("1")
|
||||
im.save(bmppath)
|
||||
print("saving to...")
|
||||
print (bmppath)
|
||||
|
||||
#print!
|
||||
try:
|
||||
epd = epd4in2.EPD()
|
||||
epd.init()
|
||||
Himage2 = Image.new('1', (epd4in2.EPD_WIDTH, epd4in2.EPD_HEIGHT), 255) # 255: clear the frame
|
||||
bmp = Image.open(bmppath)
|
||||
Himage.paste(bmp)
|
||||
epd.display(epd.getbuffer(Himage))
|
||||
time.sleep(2)
|
||||
epd.sleep()
|
||||
|
||||
except:
|
||||
print 'traceback.format_exc():\n%s' % traceback.format_exc()
|
||||
exit()
|
||||
20
etc/examples and tests/rainbow.py
Normal file
20
etc/examples and tests/rainbow.py
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import time
|
||||
import buttonshim
|
||||
print ("white")
|
||||
buttonshim.set_pixel(0xFF, 0xFF, 0xFF)
|
||||
time.sleep(3)
|
||||
print ("blue")
|
||||
buttonshim.set_pixel(0x00, 0x00, 0xff)
|
||||
time.sleep(3)
|
||||
print ("green")
|
||||
buttonshim.set_pixel(0x00, 0xff, 0x00)
|
||||
time.sleep(3)
|
||||
print ("yellow?")
|
||||
buttonshim.set_pixel(0xff, 0xff, 0x00)
|
||||
time.sleep(3)
|
||||
print ("red")
|
||||
buttonshim.set_pixel(0xff, 0x00, 0x00)
|
||||
time.sleep(3)
|
||||
BIN
etc/examples and tests/upload.bmp
Normal file
BIN
etc/examples and tests/upload.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
71
etc/examples and tests/wavesharedemo.py
Normal file
71
etc/examples and tests/wavesharedemo.py
Normal file
@ -0,0 +1,71 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import epd4in2
|
||||
import time
|
||||
from PIL import Image,ImageDraw,ImageFont
|
||||
import traceback
|
||||
|
||||
try:
|
||||
epd = epd4in2.EPD()
|
||||
epd.init()
|
||||
epd.Clear(0xFF)
|
||||
|
||||
# Drawing on the Horizontal image
|
||||
Himage = Image.new('1', (epd4in2.EPD_WIDTH, epd4in2.EPD_HEIGHT), 255) # 255: clear the frame
|
||||
# Drawing on the Vertical image
|
||||
Limage = Image.new('1', (epd4in2.EPD_HEIGHT, epd4in2.EPD_WIDTH), 255) # 255: clear the frame
|
||||
|
||||
# Horizontal
|
||||
print "Drawing"
|
||||
draw = ImageDraw.Draw(Himage)
|
||||
font24 = ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', 24)
|
||||
draw.text((10, 0), 'hello world', font = font24, fill = 0)
|
||||
draw.text((10, 20), '2.9inch e-Paper', font = font24, fill = 0)
|
||||
draw.text((150, 0), u'微雪电子', font = font24, fill = 0)
|
||||
draw.line((20, 50, 70, 100), fill = 0)
|
||||
draw.line((70, 50, 20, 100), fill = 0)
|
||||
draw.rectangle((20, 50, 70, 100), outline = 0)
|
||||
draw.line((165, 50, 165, 100), fill = 0)
|
||||
draw.line((140, 75, 190, 75), fill = 0)
|
||||
draw.arc((140, 50, 190, 100), 0, 360, fill = 0)
|
||||
draw.rectangle((80, 50, 130, 100), fill = 0)
|
||||
draw.chord((200, 50, 250, 100), 0, 360, fill = 0)
|
||||
epd.display(epd.getbuffer(Himage))
|
||||
time.sleep(2)
|
||||
|
||||
# Vertical
|
||||
draw = ImageDraw.Draw(Limage)
|
||||
font18 = ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', 18)
|
||||
draw.text((2, 0), 'hello world', font = font18, fill = 0)
|
||||
draw.text((2, 20), '2.9inch epd', font = font18, fill = 0)
|
||||
draw.text((20, 50), u'微雪电子', font = font18, fill = 0)
|
||||
draw.line((10, 90, 60, 140), fill = 0)
|
||||
draw.line((60, 90, 10, 140), fill = 0)
|
||||
draw.rectangle((10, 90, 60, 140), outline = 0)
|
||||
draw.line((95, 90, 95, 140), fill = 0)
|
||||
draw.line((70, 115, 120, 115), fill = 0)
|
||||
draw.arc((70, 90, 120, 140), 0, 360, fill = 0)
|
||||
draw.rectangle((10, 150, 60, 200), fill = 0)
|
||||
draw.chord((70, 150, 120, 200), 0, 360, fill = 0)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
time.sleep(2)
|
||||
|
||||
print "read bmp file"
|
||||
Himage = Image.open('4in2.bmp')
|
||||
epd.display(epd.getbuffer(Himage))
|
||||
time.sleep(2)
|
||||
|
||||
print "read bmp file on window"
|
||||
Himage2 = Image.new('1', (epd4in2.EPD_WIDTH, epd4in2.EPD_HEIGHT), 255) # 255: clear the frame
|
||||
bmp = Image.open('100x100.bmp')
|
||||
Himage2.paste(bmp, (50,10))
|
||||
epd.display(epd.getbuffer(Himage2))
|
||||
time.sleep(2)
|
||||
|
||||
epd.sleep()
|
||||
|
||||
except:
|
||||
print 'traceback.format_exc():\n%s' % traceback.format_exc()
|
||||
exit()
|
||||
|
||||
20
etc/sleep.py
Normal file
20
etc/sleep.py
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
#this is a way to manually sleep the display if the code crashed before the epd.sleep() command
|
||||
|
||||
import epd4in2
|
||||
import traceback
|
||||
import time
|
||||
import signal
|
||||
|
||||
#initialize display
|
||||
try:
|
||||
epd = epd4in2.EPD()
|
||||
epd.init()
|
||||
time.sleep(2)
|
||||
epd.sleep()
|
||||
print ("the display sleeps ZZZzzzz....")
|
||||
except:
|
||||
print 'traceback.format_exc():\n%s' % traceback.format_exc()
|
||||
exit()
|
||||
@ -4,7 +4,7 @@ After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/python -u carousel.py
|
||||
WorkingDirectory=/home/pi/bb
|
||||
WorkingDirectory=/home/pi/ebb
|
||||
StandardOutput=inherit
|
||||
StandardError=inherit
|
||||
Restart=always
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 352 KiB |
@ -8,6 +8,7 @@ import json
|
||||
import re
|
||||
import subprocess
|
||||
import datetime
|
||||
import time
|
||||
import traceback
|
||||
import iterparse
|
||||
import uuid
|
||||
@ -33,6 +34,12 @@ def fresh():
|
||||
root_entry = db.get(doc_id=1)
|
||||
last_run = root_entry["date"]
|
||||
|
||||
#if last run is never ran then only look back 1 month (new installs don't need EVERY old post...)
|
||||
if last_run==4:
|
||||
whatever=time.time()
|
||||
whaever-=2700000
|
||||
last_run=int(whatever)
|
||||
|
||||
newssb="nada"
|
||||
newssbcmd = 'ssb-server createLogStream --reverse 1 --gt ' + str(last_run)
|
||||
|
||||
|
||||
10
weather.py
Normal file
10
weather.py
Normal file
@ -0,0 +1,10 @@
|
||||
proc = subprocess.Popen(["curl", "wttr.in"], stdout=subprocess.PIPE)
|
||||
(out, err) = proc.communicate()
|
||||
#display the weather
|
||||
Limage = Image.new('1', (epd4in2.EPD_HEIGHT, epd4in2.EPD_WIDTH), 255) # 255: clear the frame
|
||||
draw = ImageDraw.Draw(Limage)
|
||||
font12 = ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', 12)
|
||||
draw.text((10, 0), out, font = font12, fill = 0)
|
||||
epd.display(epd.getbuffer(Limage))
|
||||
time.sleep(1)
|
||||
epd.sleep()
|
||||
Loading…
Reference in New Issue
Block a user