[ภาคแรก][ภาคสาม]
ต่อจากภาคแรกเราได้สร้างระบบจับภาพนิ่งพร้อมระบบตรวจจับการเคลื่อนไหวมาแล้ว ทีนี้เรามาเพิ่มประเด็นให้คิดต่อกันอีก 1 เรื่อง คือ
2. การแชร์พื้นที่ผ่าน cloud service
ส่วนตัวแล้วทางเลือกที่สองนี้น่าสนใจเพราะ สามารถเข้าถึงข้อมูลได้จากอินเตอร์เน็ต นับว่าตรงกับที่ต้องการมากกว่าทางเลือกแรก การเลือกบริการที่ต้องการ ในกรณีนี้ผมเลือกใช้ Google Drive เพราะมีบัญชีอยู่แล้ว ปัจจุบันได้โควต้าเนื้อที่ถึง 15 GB นับว่าพอเพียง ผมเลือกที่จะเปิดบัญชีใหม่เพื่อจะได้ไม่กระทบต่อข้อมูลที่มีอยู่ในบัญชีอื่น
...
ผลลัพธ์จาก code นี้เราจะได้ col ซึ่งเก็บข้อมูลของ Folder ที่เราต้องการนำภาพไปเก็บไว้
ทำ config file จะเป็นที่เราใช้เก็บข้อมูล สมมุติให้ชื่อ myconf.conf เนื้อหาก็จะประมาณนี้
[gdrive]
source=xxxxxx
[gmail]
name=xxxxxx
user=xxxxx@gmail.com
pwd=xxxxxx
[upload_folder]
folder=home_pics
2. สร้าง class
import os.path
import sys
import gdata.data
import gdata.docs.data
import gdata.docs.client
import ConfigParser
conf_file="myconf.conf"
class RaspiGData :
def __init__(self):
config = ConfigParser.ConfigParser()
config.read(conf_file)
self.source=config.get('gdrive',source)
self.username=config.get('gmail','user')
self.pwd=config.get('gmail','pwd')
self.folder=config.get('upload_folder','folder')
self.create_client()
def create_client(self):
self.client = gdata.docs.client.DocsClient(source=self.source)
self.client.http_client.debug = False
self.client.ClientLogin(self.username,self.pwd,service=self.client.auth_service, source=self.client.source)
def get_folder(self):
col = None
for resource in self.client.GetAllResources(
uri='/feeds/default/private/full/-/folder'):
if resource.title.text == self.folder :
col = resource
break
return col
def upload(self, file_path, folder_resource):
doc = gdata.docs.data.Resource(type='document', title=os.path.basename(file_path))
media = gdata.data.MediaSource()
media.SetFileHandle(file_path, 'image/jpeg')
doc = self.client.CreateResource(doc, media=media, collection=folder_resource)
return doc
def upload_image(self, image_file_path):
folder_resource = self.get_folder()
if not folder_resource:
raise Exception('Could not find the %s folder' % self.folder)
doc = self.upload(image_file_path, folder_resource)
1. Overhead ในการ login ไปที่ GDrive ทำบ่อย ๆ เข้า Google จะมองว่ามีเจตนาไม่ดีแอบแฝง อาจถูกบล๊อกจาก Google ได้ ดังนั้นควรทำเพียงครั้งเดียว
2. การเชื่อมต่อ internet เป็นอะไรที่บอกยากว่าจะเราจะได้ bandwidth คงที่ตลอดเวลาหรือไม่ ดังนั้นหากอยู่ในช่วงเวลาที่ upload ไม่เสร็จสักที ระบบจะเกิดคอขวดขึ้นทันที
เพื่อลดปัญหาดังกล่าวผมจะเพิ่มตัวช่วยเข้าไปอีก 3 ตัวคือ
1. threading ช่วยแยกงานออกเป็นสองงานอิสระต่อกันไม่ต้องรอ โดยผมแยกงานจับภาพนิ่งออกจากงาน upload ภาพนิ่ง
2. Queue แบบ First In First Out (FIFO) เพื่อใช้เก็บชื่อแฟ้มข้อมูลไว้ บน Raspi เพื่อส่งต่อไปให้งาน Upload อีกทอดหนึ่ง และ
3. Daemon เพื่อให้เราทำการ authenticate เข้าใช้บริการเพียงครั้งเดียว แล้วใช้ได้ไปจนงานเสร็จ ก็ทำให้งานนั้นทำตัวเป็น daemon เสียเลย
ค่อยมาว่าต่อกันในภาคสามเน้อ ครับ
---------------------------
เอกสารอ้างอิง
[1] http://www.tightvnc.com/
[2] http://www.computerhope.com/jargon/s/ssh.htm
[3] http://www.computerhope.com/jargon/f/ftp.htm
[4] http://www.computerhope.com/unix/scp.htm
[5] http://www.computerhope.com/unix/rsync.htm
[6] http://portforward.com/english/routers/port_forwarding/
[7] http://raspi.tv/2013/how-to-use-dropbox-with-raspberry-pi
[8] http://drive.google.com
[9] http://mogshade.wordpress.com/2012/12/23/simple-home-security-with-raspberry-pi-and-dropbox/
[11] https://www.copy.com/home/
[12] https://developers.google.com/gdata/articles/python_client_lib
[13] https://pip.pypa.io/en/latest/installing.html
[14] http://code.google.com/p/gdata-python-client/source/browse/#hg%2Fsamples%2Fdocs
ต่อจากภาคแรกเราได้สร้างระบบจับภาพนิ่งพร้อมระบบตรวจจับการเคลื่อนไหวมาแล้ว ทีนี้เรามาเพิ่มประเด็นให้คิดต่อกันอีก 1 เรื่อง คือ
ปัญหา : ในกรณีที่ไม่อยู่บ้านเราก็ยังสามารถดูภาพจากที่อื่นได้ผ่านอินเตอร์เน็ต
ทางเลือก
1. การทำ remote access2. การแชร์พื้นที่ผ่าน cloud service
เปรียบเทียบทางเลือก
1. Remote Access เนื่องจากระบบปฏิบัติการของ Raspberry Pi เป็น Linux ดังนั้น utlities ที่เกี่ยวกับเรื่องนี้ก็ต้องมาจากคู่มือ Linux ปัจจุบันที่ใช้กันอยู่ก็จะมี
- VNC [1] เป็น Graphic User Interface นิยมใช้งานกัน
- SSH [2] เป็น Command line ใช้กันเยอะเช่นกัน
- FTP [3] ต้องติดตั้ง Pi ให้ทำหน้าที่เป็น FTP server
- SCP [4] (Secured Copy)
- RSync [5]
- WebServer
2. การใช้พื้นที่ผ่าน Cloud Service
หากเราค้นหาบริการนี้ในอินเตอร์เน็ตจะพบว่ามีให้เลือกใช้เยอะเลย เช่น dropbox[7,9], google drive [8], skydrive, Box, Copy [11], etc.ส่วนตัวแล้วทางเลือกที่สองนี้น่าสนใจเพราะ สามารถเข้าถึงข้อมูลได้จากอินเตอร์เน็ต นับว่าตรงกับที่ต้องการมากกว่าทางเลือกแรก การเลือกบริการที่ต้องการ ในกรณีนี้ผมเลือกใช้ Google Drive เพราะมีบัญชีอยู่แล้ว ปัจจุบันได้โควต้าเนื้อที่ถึง 15 GB นับว่าพอเพียง ผมเลือกที่จะเปิดบัญชีใหม่เพื่อจะได้ไม่กระทบต่อข้อมูลที่มีอยู่ในบัญชีอื่น
ติดตั้ง Google Data Python Library
ต้องการ gdata python library เพราะเราต้องมี software จัดการนำเอาภาพที่บันทึกไปวางไว้บน Google Drive มีสองทางเลือก- การติดตั้งด้วย source code [12]
- ดาวน์โหลด source code จาก https://code.google.com/p/gdata-python-client/downloads/list
- แตกไฟล์ที่ได้บน Raspberry Pi เข้าไปใน folder ที่ได้ จะพบไฟล์ setup.py
- พิมพ์ python ./setup.py install
- ในกรณที่ติดตั้ง pip [13] ไว้แล้ว สามารถใช้คำสั่ง
pip install gdata
สร้าง Python Code
ท่านที่ไม่คุ้นเคยกับการใช้งาน gdata library อาจต้องทำงานเยอะหน่อย มีเอกสารบนเว็บมากมายให้ศึกษา แต่ที่ผมแนะนำคือการอ่าน code ตัวอย่างประกอบไปด้วย ซึ่งดูได้จาก [12 , 14 ] จะทำให้พบทางลัดในการทำงาน เพราะบางครั้งการทำตามขั้นตอนปรกติอาจเยิ่นเย้อไปหน่อย ผมสรุปเป็น 3 ขั้นตอนง่าย ๆ ดังนี้1. การทำ Authentication
ทาง Google เรียก Create client ซึ่งผลลัพธ์ของขั้นตอนนี้เราจะได้ client ที่นำไปใช้งานต่อไปimport gdata.datareturn client
import gdata.docs.data
import gdata.docs.client
def create_client():
source="<Any string>"
client = gdata.docs.client.DocsClient(source=source)
client.http_client.debug=False
client.ClientLogin(
"<your google email address>",
"<your password>",
service=client.auth_service,
source=source)
...
2. การหาตำแหน่งจัดเก็บเอกสาร
ในทางปฎิบัติเราต้องไปสร้าง folder ไว้กับ Google Drive ไว้ก่อนล่วงหน้าครับ ด้วยวิธีการปรกติ สมมุติว่าเราให้ folder ที่เอาไว้เก็บภาพของเราชื่อ "home_pics" ซึ่งข้อมูลตรงนี้เราต้องนำมาบอกให้โปรแกรมเรารับทราบdef get_folder() :
col = None
for resource in self.client.GetAllResources(uri='/feeds/default/private/full/-/folder'):
if resource.title.text == "home_pics" :
col = resource
break
return col
ผลลัพธ์จาก code นี้เราจะได้ col ซึ่งเก็บข้อมูลของ Folder ที่เราต้องการนำภาพไปเก็บไว้
3. การ upload ไฟล์รูปภาพ
def upload_image():
folder_resource = get_folder()
file_path="<image file location>"
doc = gdata.docs.data.Resource(type='document',title="my home picture")
media = gdata.data.MediaSource()
media.SetFileHandle(file_path, 'image/jpeg')
doc = self.client.CreateResource(doc, media=media, collection=folder_resource)
return doc
จับมารวมกัน
การเขียน code ของผมนั้น ผมชอบทำเป็น Modular จนเป็นนิสัย ดังนั้นตัวอย่างตรงนี้เป็นเรื่องของไสตล์ ไม่ได้อิงหลักการอะไรพิเศษหรือ framework อะไร นะครับทำ config file จะเป็นที่เราใช้เก็บข้อมูล สมมุติให้ชื่อ myconf.conf เนื้อหาก็จะประมาณนี้
[gdrive]
source=xxxxxx
[gmail]
name=xxxxxx
user=xxxxx@gmail.com
pwd=xxxxxx
[upload_folder]
folder=home_pics
2. สร้าง class
import os.path
import sys
import gdata.data
import gdata.docs.data
import gdata.docs.client
import ConfigParser
conf_file="myconf.conf"
class RaspiGData :
def __init__(self):
config = ConfigParser.ConfigParser()
config.read(conf_file)
self.source=config.get('gdrive',source)
self.username=config.get('gmail','user')
self.pwd=config.get('gmail','pwd')
self.folder=config.get('upload_folder','folder')
self.create_client()
def create_client(self):
self.client = gdata.docs.client.DocsClient(source=self.source)
self.client.http_client.debug = False
self.client.ClientLogin(self.username,self.pwd,service=self.client.auth_service, source=self.client.source)
def get_folder(self):
col = None
for resource in self.client.GetAllResources(
uri='/feeds/default/private/full/-/folder'):
if resource.title.text == self.folder :
col = resource
break
return col
def upload(self, file_path, folder_resource):
doc = gdata.docs.data.Resource(type='document', title=os.path.basename(file_path))
media = gdata.data.MediaSource()
media.SetFileHandle(file_path, 'image/jpeg')
doc = self.client.CreateResource(doc, media=media, collection=folder_resource)
return doc
def upload_image(self, image_file_path):
folder_resource = self.get_folder()
if not folder_resource:
raise Exception('Could not find the %s folder' % self.folder)
doc = self.upload(image_file_path, folder_resource)
รวมตัวกับภาคแรก
ท่านอาจต้องย้อนกลับไปดู flow chart ที่ให้ไว้ในภาคแรกกันก่อน (หากลืมไปแล้ว) code ในภาคนี้จะมาทำงานต่อจาก การบันทึกภาพเป็น jpeg นั้นเองมีบางอย่างไม่ถูกต้อง ?
พิจารณ Flow Chart แล้วก็ไม่น่าจะมีอะไรไม่ถูกต้อง จับภาพแล้วก็นำส่งไปที่ GDrive เลย algorithm นั้นถูกต้องแล้ว แต่ลองนึกถึงข้อเท็จจริงในทางปฎิบัตินะครับ ปัญหาที่จะเกิดขึ้นคือ1. Overhead ในการ login ไปที่ GDrive ทำบ่อย ๆ เข้า Google จะมองว่ามีเจตนาไม่ดีแอบแฝง อาจถูกบล๊อกจาก Google ได้ ดังนั้นควรทำเพียงครั้งเดียว
2. การเชื่อมต่อ internet เป็นอะไรที่บอกยากว่าจะเราจะได้ bandwidth คงที่ตลอดเวลาหรือไม่ ดังนั้นหากอยู่ในช่วงเวลาที่ upload ไม่เสร็จสักที ระบบจะเกิดคอขวดขึ้นทันที
เพื่อลดปัญหาดังกล่าวผมจะเพิ่มตัวช่วยเข้าไปอีก 3 ตัวคือ
1. threading ช่วยแยกงานออกเป็นสองงานอิสระต่อกันไม่ต้องรอ โดยผมแยกงานจับภาพนิ่งออกจากงาน upload ภาพนิ่ง
2. Queue แบบ First In First Out (FIFO) เพื่อใช้เก็บชื่อแฟ้มข้อมูลไว้ บน Raspi เพื่อส่งต่อไปให้งาน Upload อีกทอดหนึ่ง และ
3. Daemon เพื่อให้เราทำการ authenticate เข้าใช้บริการเพียงครั้งเดียว แล้วใช้ได้ไปจนงานเสร็จ ก็ทำให้งานนั้นทำตัวเป็น daemon เสียเลย
ค่อยมาว่าต่อกันในภาคสามเน้อ ครับ
---------------------------
เอกสารอ้างอิง
[1] http://www.tightvnc.com/
[2] http://www.computerhope.com/jargon/s/ssh.htm
[3] http://www.computerhope.com/jargon/f/ftp.htm
[4] http://www.computerhope.com/unix/scp.htm
[5] http://www.computerhope.com/unix/rsync.htm
[6] http://portforward.com/english/routers/port_forwarding/
[7] http://raspi.tv/2013/how-to-use-dropbox-with-raspberry-pi
[8] http://drive.google.com
[9] http://mogshade.wordpress.com/2012/12/23/simple-home-security-with-raspberry-pi-and-dropbox/
[11] https://www.copy.com/home/
[12] https://developers.google.com/gdata/articles/python_client_lib
[13] https://pip.pypa.io/en/latest/installing.html
[14] http://code.google.com/p/gdata-python-client/source/browse/#hg%2Fsamples%2Fdocs
ความคิดเห็น
แสดงความคิดเห็น