樹莓派型號:Zero W
樹莓派系統:Raspbian,2018-11-13-raspbian-stretch-lite.img
SD卡:閃迪32G class10 高速Micro SD卡(TF卡)
存儲工具:阿里雲->對象存儲
阿里雲的SDK文檔(有各種語言的版本,這里選的是Python),提供了上傳數據的樣例程序:
# -*- coding: utf-8 -*- import oss2 # 阿里雲主賬號AccessKey擁有所有API的訪問權限,風險很高。強烈建議您創建並使用RAM賬號進行API訪問或日常運維,請登錄 https://ram.console.aliyun.com 創建RAM賬號。 auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>') # Endpoint以杭州為例,其它Region請按實際情況填寫。 bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>') # <yourObjectName>上傳文件到OSS時需要指定包含文件后綴在內的完整路徑,例如abc/efg/123.jpg。 # <yourLocalFile>由本地文件路徑加文件名包括后綴組成,例如/users/local/myfile.txt。 bucket.put_object_from_file('<yourObjectName>', '<yourLocalFile>')
功能需求
間隔一段時間掃描一次<待上傳>目錄,如果該目錄下有數據文件,就將第一個文件上傳到對象存儲指定bucket(考慮到以后會有幾十台數據采集裝置,為了便於管理,每個裝置在bucket上有一個專屬的二級子目錄),上傳成功后將這個文件移動到<已上傳>目錄下。
環境准備
手動創建兩個工作目錄,分別用於存放<待上傳>和<已上傳>的數據文件:
mkdir -p ~/project/data/updating
mkdir -p ~/project/data/updated
updating目錄下用touch指令創建一個測試文件test.db:
pi@raspberrypi:~ $ cd ~/project/data/updating
pi@raspberrypi:~/project/data/updating $ touch test.db
程序文件
切換到主目錄下,創建test_upload.py文件,復制內容進去,保存退出
注意:<yourAccessKeyId>、<yourAccessKeySecret>、<yourBucketName>要改成自己的
pi@raspberrypi:~/project/data/updating $ cd ~
pi@raspberrypi:~ $ sudo nano test_upload.py
1 # -*- coding: utf-8 -*- 2 import os 3 import time 4 import shutil 5 import oss2 6 import ConfigParser 7 8 PRODUCT_TYPE = 'NULL' 9 DEVICE_ID = 999 #default 10 11 #---- 12 def UploadFile_oss2(localfile): 13 global PRODUCT_TYPE 14 global DEVICE_ID 15 16 access_key = '<yourAccessKeyId>' 17 secret_key = '<yourAccessKeySecret>' 18 19 try: 20 auth = oss2.Auth(access_key, secret_key) 21 bucket = oss2.Bucket(auth, 'oss-cn-beijing.aliyuncs.com', '<yourBucketName>') 22 23 # 文件是否存在 24 print '>> uploading local file: ' + localfile 25 if False == os.path.exists(localfile): 26 print '>> local file not exist: ' + localfile 27 return False 28 29 # 根據產品類型、樹莓派編號,生成二級目錄 30 objectname = PRODUCT_TYPE + '_' + str(DEVICE_ID).rjust(3,'0') \ 31 + '/' + os.path.basename(localfile) 32 print '>> upload result...' 33 result = bucket.put_object_from_file(objectname, localfile) 34 35 print result 36 37 # result.status 200 表示上傳成功 38 if result.status == 200: 39 return True 40 else: 41 return False 42 except: 43 return False 44 45 #---- 46 def UploadFile(localfile): 47 return UploadFile_oss2(localfile) 48 49 #---- 50 def main(): 51 global PRODUCT_TYPE 52 global DEVICE_ID 53 54 DB_UPDATING_DIR = '/home/pi/project/data/updating/' 55 DB_UPDATED_DIR = '/home/pi/project/data/updated/' 56 CONFIG_FILE = '/home/pi/project/config.ini' 57 file_path = '' 58 59 # time.sleep(10) 60 # 讀取產品類型、樹莓派編號 61 GetDeviceInfo(CONFIG_FILE) 62 63 print '>> uploading scheduler start...' 64 while True: 65 filelist = os.listdir(DB_UPDATING_DIR) 66 if len(filelist) > 0: 67 # 獲得<待上傳>文件夾下的第一個數據文件 68 file_path = os.path.join(DB_UPDATING_DIR, filelist[0]) 69 if os.path.exists(file_path): 70 print '>> file need upload: ' + file_path 71 if True == UploadFile(file_path): 72 # 上傳成功,將數據文件放到<已上傳>文件夾中 73 MoveFile(file_path, DB_UPDATED_DIR) 74 print '>> upload succeed: '+ file_path 75 76 # 每隔一段時間掃描一次<待上傳>文件夾(每小時生成一個新的數據文件) 77 time.sleep(30) 78 79 #---- 80 def GetDeviceInfo(file_path): 81 global PRODUCT_TYPE 82 global DEVICE_ID 83 84 # 讀取配置信息 85 PRODUCT_TYPE = 'NULL' 86 DEVICE_ID = 999 87 ''' 88 try: 89 config = ConfigParser.ConfigParser() 90 config.read(file_path) 91 if "device" in config.sections(): 92 PRODUCT_TYPE = config.get("device", "type") 93 DEVICE_ID = config.getint("device", "id") 94 except: 95 # 配置文件加載異常,使用默認參數:產品類型NULL 樹莓派編號999 96 PRODUCT_TYPE = 'NULL' 97 DEVICE_ID = 999 98 ''' 99 100 #---- 101 def MoveFile(src_file_path, dst_folder_path): 102 try: 103 if not os.path.exists(dst_folder_path): 104 os.mkdir(dst_folder_path) 105 shutil.move(src_file_path, dst_folder_path) 106 except: 107 return 108 109 #---- 110 if __name__ == '__main__': 111 main()
>> def UploadFile_oss2(localfile):
這個函數把本地文件上傳到阿里雲對象存儲的buckek空間。
基本是按照官方提供的樣例程序寫的,加了一些防止異常的冗余代碼。
上傳時使用二次子目錄,直接在objectname加上目錄就可以了 :
objectname = 'NULL_999/' + os.path.basename(localfile)
上傳結果result.status為200表示上傳成功。
>> def UploadFile(localfile):
調用UploadFile_oss2,隔離一下,萬一要改成其他雲。
>> def GetDeviceInfo(file_path):
獲取設備信息:產品信號、設備編號,每個設備根據這個信息,可以在bucket空間上創建專屬的二級子目錄,便於管理數據。
這些設置信息保存在一個配置文件中,用ConfigParser庫進行訪問,為了簡化操作現在這段代碼暫時注釋掉了,直接使用默認的設備信息。
>> def MoveFile(src_file_path, dst_folder_path):
文件上傳成功后,從<待上傳>移動到<已上傳>。
如果目標目錄不存在,使用os庫創建該目錄;使用shutil庫進行文件移動操作。
>> def main():
間隔一段時間掃描一次<待上傳>目錄,上傳該目錄下的第一個文件。
filelist = os.listdir(DB_UPDATING_DIR),獲得該目錄下的文件清單
os.path.join(DB_UPDATING_DIR, filelist[0]),獲得第一個文件的路徑
運行測試
運行test_upload.py,顯示數據上傳成功
pi@raspberrypi:~ $ python test_upload.py
切換到updated目錄下,文件已經移動過來了
pi@raspberrypi:~ $ cd ~/project/data/updated
pi@raspberrypi:~/project/data/updated $ ls
打開阿里雲app,管控->文件管理->xxxx_bucket_name,多了一個NULL_999的二級目錄,進入該目錄,test.db文件已經上傳成功了。