Рубрики
Raspberry Pi

raspberry pi / python / интернет

python-requests:

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 - посмотреть что прислал сервер

Ответы сервера:

200 - успешно
301 - переехал навсегда
302 - переехал временно
401 - нет прав на доступ
404 - не найдено
500 - ошибка на сервере

API

Application programming interface - позволяет разному софту взаимодействовать друг с другом 
и часто используется для обмена данными через интернет.
http://api.wunderground.com/api/API_key/forecast/q/CA/San_Francisco.json - пример 
Несмотря на то,что J - означает JavaScript, JSON используется во многих языках программирования, особенно для взаимодействия приложений через API

Кусок ответа от API Weather Underground:

"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:

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

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:

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)

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
--------------

   
       {{ title }}  - заголовок страницы 
      
   
   
        

Hello, World!

The date and time on the servers is: {{ time }} - выводим переменную

--------------

Пример использования Python + Flask + GPIO

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/")  - добавляем динамический путь, в котором передается номер контакта
    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
-------------

  
       {{ title }}
  


Pin Status

{{ response }}

------------- В браузере пишем запрос http://ip_server_or_name/readPin/24 И мы должны увидеть состояние контакта.

Веб-лампа:

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("//") -  эта функция запускается, когда запрашивается 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
------------------------


     Current Status

    
      

Device Listing and Status

{% for pin in pins %} - для каждого контакта в объекте pins

The {{ pins[pin].name}} - выводим название контакта {% if pins[pin].state == true %} - если он в состоянии high, выводим, что устройство включено, и даем ссылку на его выключение is currently on (turn off ) {% else %} - в противном случае, выводим, что устройство выключено, и даем ссылку на его выключение is currently off (turn on) <% endif %}

{% endfor %} {% if message %} - если сообщение было передано показываем его

{{ message }}

{% endif %} ------------------------ http://ip_pi - при переходе на страницу мы увидем состояние устройств и можем его вкл/выкл http://ip_pi/pin/toggle - при переходе вот так изменение состояния контакта

Доп материалы:

http://doc.python-requests.org/en/latest/
http://flask.pocoo.org/
http://flask.pocoo.org/extensions/