python-requests:
1 2 3 4 5 6 7 8 |
python-requests - позволяет python общаться с веб-серверами по протоколу http apt-get install install python-requests Проверка работы библиотеки python >>> import requests - импортировать библиотеку >>> r = requests.get('http://www.google.com/') - выполнить запрос >>> r.status_code - узнать ответ >>> r.text - посмотреть что прислал сервер |
Ответы сервера:
1 2 3 4 5 6 |
200 - успешно 301 - переехал навсегда 302 - переехал временно 401 - нет прав на доступ 404 - не найдено 500 - ошибка на сервере |
API
1 2 3 4 |
Application programming interface - позволяет разному софту взаимодействовать друг с другом и часто используется для обмена данными через интернет. http://api.wunderground.com/api/API_key/forecast/q/CA/San_Francisco.json - пример Несмотря на то,что J - означает JavaScript, JSON используется во многих языках программирования, особенно для взаимодействия приложений через API |
Кусок ответа от API Weather Underground:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
"response": { "version": "0.1", "termofService": "http://www.wunderground.com/weather/api/d/terms.html", "features": { "forecast": 1 } }, "forecast": { - корневой элемент структуры данных "txt_forecast": { - внутри forecast нас интересует txt_forecast "date":"10:00 AM EST", "forecastday": [ - внутри txt_forecast нас интересует forecastday { "period":0, "icon":"partlycloudy", "icon_url":"http://icons-ak.wxug.com/i/c/k/ psrtlycloudy.gif", "title":"Tuesday", "fcttext": "Party cloud.Nigh of 9C." - это и есть наш прогноз в текстовом формате "fcttext_metric":"Partly cloudy. High of 48F. Winds from the NNE at to 15 km/h.", "pop":"0" }, |
Создадим файл text-forecast.py:
1 2 3 4 5 6 7 8 9 10 11 |
nano text-forecast.py --------------------- import requests key = 'Вставь свой api ключ сюда' - сюда вставим наш ключ API ApiUrl = \ 'http://api.wunderground.com/api' + key + \ '/forecast/q/NY/New_York.json' r = requests.get(ApiUrl) - получаем прогноз для New_York forecast = r.json - берем текст ответа и делаем из него объект-словарь print forecast['forecast']['txt_forecast']['forecastday'][0]['fcttext'] - добираемся до нашего прогноза --------------------- |
Создадим файл umbrella-indecator.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
nano umbrella-indecator.py -------------------------- import requests import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setup(25, GPIO.OUT) key = 'Вставь свой api ключ сюда' - сюда вставим наш ключ API ApiUrl = \ 'http://api.wunderground.com/api' + key + \ '/forecast/q/NY/New_York.json' while True: r = requests.get(ApiUrl) - получаем прогноз для New_York forecast = r.json - берем текст ответа и делаем из него объект-словарь popValue = forecast['forecast']['txt_forecast']['forecastday'][0]['pop'] - считываем возможность выпадения осадков popValue = int(popValue) - конвертируем переменную popValue из строки в число if popValue >= 30: - если значение больше 30 включаем светодиод GPIO.output(25, GPIO.HIGH) else: - если popValue < 30 отключаем светодиод GPIO.output(25, GPIO.LOW) time.sleep(180) - ждем 3 минуты и повторяем снова -------------------------- |
Популярные API:
1 2 3 4 5 6 7 |
https://developers.facebook.com http://flickr.com/service/api/ https://developer.foursquare.com/ https://github.com/reddit/reddit/wiki/API http://www.twillo.com https://dev/twitter.com https://developers.google.com/youtube/ |
Веб-фреймворк Flask (Веб сервер на python)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
http://flask.pocoo.org/ apt-get install python-pip pip install flask nano hello-flask.py - создадим проверочный файл ------------------- from flask import Flask app = Flask(__name__) - создаем объект и называем его app @app.route("/") - запускаем код который идет ниже когда кто то пытается получить доступ к корню веб сервера def hello(): return "Hello World!" - посылаем клиенту строку Hello World! if __name__ == "__main__": - если скрипт запущен из командной строки... app.run(host='0.0.0.0', port=80, debug=True) - запустить сервер на 80 порту и сообщать о всех ошибках -------------------- Шаблон запросов Jinja2 Позволяет вам помечать маркерами те места в HTML файлах, в которые будет вставлено динамическое содержимое. http://jinja.pocoo.org/docs/templates Пример динамической страницы: nano hello-template.py ---------------------- from flask import Flask, render_template import datetime app = Flask(__name__) - создаем объект и называем его app @app.route("/") - запускаем код который идет ниже когда кто то пытается получить доступ к корню веб сервера def hello(): now = datetime.datetime.now() timeString = now.strftime("%Y-%m-%d %H:%M") templateData = { 'title' : 'HELLO', 'time' : timeString } return render_template('main.html', **templateData) - посылаем клиенту динамическую страницу if __name__ == "__main__": - если скрипт запущен из командной строки... app.run(host='0.0.0.0', port=80, debug=True) - запустить сервер на 80 порту и сообщать о всех ошибках ---------------------- nano main.html -------------- <!DOCTYPE html> <head> <title> {{ title }} </title> - заголовок страницы </head> <body> <h1> Hello, World!</h1> <h2> The date and time on the servers is: {{ time }} - выводим переменную </h2> </body> </html> -------------- |
Пример использования Python + Flask + GPIO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
nano hello-gpio.py ------------------ from flask import Flask, render_template import datetime import Rpi.GPIO as GPIO app = Flask(__name__) GPIO.setmode(GPIO.BCM) @app.route("/") def hello(): now = datetime.datetime.now() timeString = now.strftime("%Y-%m-%d %H:%M") templateData = { 'title' : 'HELLO!', 'time' : timeSring } return render_template('main.html', **templateData) @app.route("/readPin/<pin>") - добавляем динамический путь, в котором передается номер контакта def readPin(pin): try: - если при выполнении в коде возникнет ошибка выполнится код в блоке except GPIO.setup(int(pin), GPIO.IN) - берем из URL номер контакта, конвертируем его в число и используем if GPIO.input(int(pin)) == True: - если контакт в high выводим сообщение об этом response = " Pin number " + pin + "is high" else: - в противном случае выводим сообщение что он Low response = " Pin number " + pin + "is low" except: - если произошла ошибка выводим сообщение об этом response = "There was an error reading pin" + pin templateData = { 'title' : 'Status of Pin' + pin, 'response' response } return render_template('pin.html', **templateData) if __name__ == "__main__": app.run(host'0.0.0.0', port=80, debug=True) ------------------ nano pin.html ------------- <!DOCTYPE html> <head> <title>{{ title }}</title> </head> <body> <h1> Pin Status </h1> <h2> {{ response }} </h2> </body> </html> ------------- В браузере пишем запрос http://ip_server_or_name/readPin/24 И мы должны увидеть состояние контакта. |
Веб-лампа:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
nano weblam.py -------------- import RPi.GPIO as GPIO from flask import Flask, render_template, request app = Flask(__name__) GPIO.setmode(GPIO.BCM) pins = { 24 : {'name' : 'coffee maker', 'state' : GPIO.LOW}, 25 : {'name' : 'lamp', 'state' : GPIO.LOW} } - создаем объект-словарь с именем pins для того, чтобы хранить номер контакта, его название и состояние. for pin in pins: - делаем все используемые контакты с логическим 0 GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, GPIO.LOW) @app.route("/") def main(): for pin in pins: pins[pin]['state'] = GPIO.input(pin) - считываем состояние каждого контакта и сохраняем его в объект pins templateData = { 'pins' : pins - помещаем словарь pins в словарь, который потом передадим в шаблон. } return render_template('main.html', **templateData) - передаем объект, содержащий данные шаблону main.html и отдаем его пользователю @app.route("/<changePin>/<action>") - эта функция запускается, когда запрашивается URL с номером контакта и действием, которое нужно совершить над ним. def action(changePin, action): changePin = int(changePin) - конвертируем номер контакта, переданный в URL, в число. deviceName = pins[changePin]['name'] - берем название устройства, состояние которого хотим поменять if action == "on": - если запрашивается действие ON выполняем этот код GPIO.output(changePin, GPIO.HIGH) message = "Turned" + deviceName + " on." - устанавливаем контакт в положение high if action == "off": GPIO.output(changePin, GPIO.LOW) message == "Turned" + deviceName + " off." if action == "toggle"; GPIO.output(changePin, not GPIO.input(changePin)) - Считываем значение контакта и устанавливаем противоположное message == "Toggled" + deviceName + "." for pin in pins: pins[pin]['state'] = GPIO.input(pin) - считываем значение каждого контакта и сохраняем его в объект pins templateData = { 'message' : message, 'pins' : pins } - вместе с объектом pins передаем в шаблон сообщение return render_template('main.html', **templateData) if __name__ == "__main__": app.run(host='0.0.0.0', port=80, debug=True) nano templates/main.html ------------------------ <!DOCTYPE html> <head> <title>Current Status</title> </head> <body> <h1>Device Listing and Status</h1> {% for pin in pins %} - для каждого контакта в объекте pins <p> The {{ pins[pin].name}} - выводим название контакта {% if pins[pin].state == true %} - если он в состоянии high, выводим, что устройство включено, и даем ссылку на его выключение is currently on (<a href="/{{pin}}/off">turn off </a>) {% else %} - в противном случае, выводим, что устройство выключено, и даем ссылку на его выключение is currently off (<a href="/{{pin}}/on">turn on</a>) <% endif %} </p> {% endfor %} {% if message %} - если сообщение было передано показываем его <h2>{{ message }}</h2> {% endif %} </body> </html> ------------------------ http://ip_pi - при переходе на страницу мы увидем состояние устройств и можем его вкл/выкл http://ip_pi/pin/toggle - при переходе вот так изменение состояния контакта |
Доп материалы:
1 2 3 |
http://doc.python-requests.org/en/latest/ http://flask.pocoo.org/ http://flask.pocoo.org/extensions/ |