Controlamos la iluminación del apartamento (NooLite, Raspberry Pi y WebIOPi)

Quiero compartir la experiencia de usar el sistema de hogar inteligente NooLite junto con el Raspberry Pi Modelo B (en adelante RPI ) en un apartamento de dos habitaciones.
Sobre el sistema NooLite se escribieron repetidamente en un concentrador:

En este artículo te diré:



  • ( ): RPI + WebIOPi (UART+REST) + NooLite
  • : NooLite —
  • ( , ): Android, WEB-, bash shell (python script)

Quizás alguien piense: "No me molestaría con RPI por el simple hecho de controlar la iluminación del apartamento desde un teléfono móvil, pero me daría cuenta de todo con un vaso de plástico, un guijarro y un hilo en un Arduino con un escudo de Wi-Fi o uno más simple". implementación concisa en el microcontrolador AVR ".
Pero, como ya estaba acumulando polvo en el estante RPI y fui superado por el deseo de hacer una iluminación "inteligente" utilizando la plataforma RPI, decidí tomarlo como base. Además, la posibilidad de utilizar RPI proporciona un buen margen para ampliar la funcionalidad de la "casa inteligente".

Datos de entrada


  • Apartamento de 2 habitaciones P44T sin reparación en un edificio nuevo
  • RPI (fue adquirido hace dos años por interés)
  • deseo de realizar iluminación inteligente

Durante un tiempo estuve mirando varias plataformas y tecnologías de la casa inteligente, como resultado, la elección recayó en el sistema NooLite, basado en lo siguiente:
  • precio adecuado en comparación con sistemas similares (Z-Wave, EnOcean, ZigBee)
  • Confío en los productos fabricados en Bielorrusia.
  • protocolo abierto
  • muchos ejemplos de uso en internet
  • 433 MHz extendido y ratificado por SCRF

También llamé la atención sobre la plataforma Wiren Board basada en ARM9 para la automatización del hogar con una rica funcionalidad para todas las necesidades imaginables e inimaginables. Estuve especialmente satisfecho con la característica asesina: un módulo de radio de 433 MHz, que en mi caso es adecuado para controlar las unidades de potencia NooLite. Pero como ya tengo un RPI, vamos a construir sobre esto.
Para implementar la iluminación "inteligente" en el apartamento, necesitaba resolver las siguientes tareas:
  1. determinar el escenario de iluminación óptimo en un apartamento de dos habitaciones
  2. definir un método para integrarse con RPI y colocar baja corriente
  3. elige una envoltura para controlar
  4. hacer una lista de compras
  5. coordinar lo anterior con su esposa
  6. comprar los componentes necesarios
  7. vincular controles remotos y depurar integración RPI> NooLite
  8. encontrar y comprar interruptores adecuados para controles remotos
  9. colocar bloques de energía e interruptores
  10. desarrollar una aplicación móvil para Android

Los elementos 1 y 4-6 se pueden repetir en un ciclo.
Precio de emisión:
  • RPI [1 pieza]
  • Módulo NooLite MT1132 [1 140 ₽ X 1 pc] 1 140 ₽
  • Bloques de alimentación NL [1240 ₽ X 11 piezas] 13 640 ₽
  • Paneles de control estacionarios NL [1 340 ₽ X 7 piezas] 9 380 ₽
  • Llavero de control remoto NL [1 550 ₽ X 1 pc] 1 550 ₽
  • Sensor de movimiento NL [1 550 ₽ X 1 pc] 1 550 ₽
  • Cajas de montaje, soportes, módulos de teclado / botón (interruptores), marcos (comprados individualmente)
  • amigos con una impresora 3D - gratis

Total: ~ 27 000 ₽ + controlador de 3 000 ₽.

Escenario de iluminación del apartamento


A continuación se muestra el diseño del chaleco de dos habitaciones P44T de esquina con un ventanal.

Está previsto controlar la iluminación con NooLite en todas las habitaciones, excepto la logia, el baño y el inodoro.
El corredor

2 puntos de iluminación con modo relé (encendido / apagado).
El sensor de movimiento PM111 debe controlar un punto de luz no tan brillante . Esto permitirá en la oscuridad iluminar el camino del vagabundo nocturno en busca de las luces del hambre nocturna.

Ambos puntos de iluminación deben ser controlados por un interruptor fijo ubicado al lado de la puerta principal. El interruptor debe incluir el escenario "apague las luces en todo el departamento".
El sensor de movimiento térmico entra en modo de espera (comienza a responder al movimiento de los objetos térmicos) cuando configura el nivel requerido de iluminación de la habitación y la sensibilidad. Por lo general, durante el día no hay necesidad de parpadear la luz en el pasillo para pasar.
De las instrucciones para el sensor:
Si la iluminación cerca del sensor PM111 es más alta que la establecida por el regulador de iluminancia, entonces el sensor está en modo de espera. Al mismo tiempo, su consumo de corriente es mínimo (menos de 1 μA) y el sensor de movimiento térmico está desactivado. Cuando la iluminación cae por debajo de un nivel predeterminado, el sensor entra en modo de espera.

Las luces en el inodoro y el baño están controladas por un interruptor estacionario clásico. La luz y el ventilador en el inodoro están conectados a través de un relé de tiempo F&F PO-415 (también bielorrusos) en un riel DIN.

Como resultado del cierre del contacto de control 6, los contactos de relé 11, 12 están cerrados. Abrir el contacto de control 6 provoca una cuenta regresiva del tiempo establecido, después de lo cual se detiene el funcionamiento del PO-415.

El interruptor de pasillo estacionario debe ser del tipo de un botón pulsador, ya que invocar un script implica presionar un botón (el script no tiene estados ON / OFF).
Además, el botón es necesario si necesitamos apagar la luz ya encendida por el sensor de movimiento, cuando el temporizador del sensor está configurado para no apagar la luz durante varios minutos después de activarse. La clave no cabe en este caso.
Total al final del pasillo:
  • Dos unidades de potencia de tipo relé 200 W ( SU111-200 en modo relé)
  • un interruptor estacionario de 3 botones ( PK313 Remote ):
    • Botón 1 - encendido / apagado del punto de luz de iluminación 1
    • botón 2 - encendido / apagado del punto de luz de iluminación 2
    • botón 3 - apaga la luz en todo el departamento (guión)



Cocina

Tres puntos de iluminación:
  • lámpara sobre la mesa ( modo de relé SU111-200 )
  • iluminación puntual en techo tensado ( modo de relé SU111-200 )
  • Tira de LED para iluminar la superficie de trabajo de la cocina ( modo de relé SU111-200 )

Los puntos de iluminación se controlan mediante un interruptor de 3 botones ( control remoto PK311 ) ubicado en la entrada de la cocina.

Sala de estar y balcón

Dos puntos de iluminación en modo relé ( SU111-200 ):
  • iluminación principal en la sala de estar
  • luz en el balcón

Cada punto de iluminación está controlado por 2 interruptores:
  • Interruptor estacionario de 2 botones en el balcón ( PK313 Remote ):
    • Botón 1 - luz de encendido / apagado en el balcón
    • botón 2 - encender / apagar la luz en la sala de estar

  • Interruptor estacionario de 2 teclas en la sala de estar ( PK314 Remote ):
    • tecla 1 - encender / apagar la luz en la sala de estar
    • tecla 2 - luz de encendido / apagado en el balcón



Quizás alguien pregunte "¿por qué no poner un interruptor de 2 teclas en el balcón como en la sala de estar?" o "¿por qué no poner botones en todo el apartamento?".
Sucedió que al principio se suponía que debía instalar un interruptor de 3 botones con un botón de escenario en el balcón, pero luego cambiaron de opinión al elegir el diseño de los interruptores. También se supuso que habría botones en el pasillo y en la cocina, e interruptores de llave en la sala de estar, dormitorio y balcón para preservar el diseño.
Más tarde quise atenuar la luz con un interruptor junto a la cama, así que todo salió mal. Para preservar el diseño de los interruptores automáticos, tuve que viajar por muchos mercados de construcción, visitar una docena de sitios de Internet, más sobre esto más adelante en la sección " Buscar y comprar interruptores automáticos adecuados para controles remotos ".
Dormitorio

Sección 1 (cama)
Por lo general, los bloques de alimentación se encuentran en cada punto de iluminación. Un punto de iluminación: una unidad de potencia. En mi escenario de iluminación, hay una desviación de la lógica tradicional. En la "sección 1" de la habitación, se supone que debe instalar una lámpara con dos unidades de potencia, una de las cuales estará atenuada.
Sección 2 (ventana salediza)
Además de los interruptores fijos, todos los puntos de iluminación deben controlarse desde un control remoto de bolsillo como consola de respaldo y RPI. Para llavero:
  • botón A (encender / apagar la luz en el pasillo y en la cocina)
  • botón B (enciende / apaga la luz en la sala de estar y en el balcón)
  • botón C (encender / apagar la luz en el dormitorio)


Definición de colocación de baja corriente y método de integración de NooLite C para RPI


Diré de inmediato, la integración es simple. NooLite tiene un módulo MT1132 . El módulo recibe un paquete de control a través de UART de algún controlador, en mi caso es un RPI, transmite un comando por aire a dispositivos ejecutivos (bloques de alimentación) y responde con la construcción OK / r \ n, todo se describe en las instrucciones del módulo .
Tensión de alimentación del módulo (VCC Upit)2.7-5.5 V
rango de voltaje de entrada en Rx0 - Arriba
TTL HIGH LVL (unidad lógica) en Upit = 5 V2 - Upit (5 V)
TTL LOW LVL (cero lógico) en Upit = 5 V0-0.8 V
TTL HIGH LVL (unidad lógica) en Upit = 3.3 V2-3.3 V
TTL LOW LVL (cero lógico) en Upit = 3.3 V0-0.8 V
Velocidad UART9600 baudios


Dado que las líneas RPART UART funcionan con niveles TTL de 3.3 V, usaremos 3.3 V como la potencia U del módulo.

Puede usar tres líneas en el MT1132: VCC, GND y RX, para transmitir un paquete de control. Hice esto al depurar: no leí la respuesta "OK \ r \ n" del MT1132, fue suficiente para mí observar el indicador de la unidad de alimentación conectada. Tras la aceptación exitosa del comando "vinculante", se inicia un parpadeo frecuente del LED incorporado en la unidad de alimentación.
Otro punto, la potencia del transmisor de radio con potencia U de 3.3 V a 3.3 mW, con potencia U de 5 V a 5 mW. La distancia máxima a la unidad de potencia es de 70 m.

Sobre el paquete de control


El paquete de control consta de 12 bytes:
ST, B0, B1, B2, B3, B4, B5, B6, B7, B8, CS, SP
ST - byte de inicio, siempre 85
B0..B8 - carga útil (comandos de control)
CS - comprobar suma El byte menos significativo de la suma de los primeros 10 bytes
SP (ST a B8) SP - detener byte.
De acuerdo con las instrucciones, escribí los bytes de control que necesito:
B1 - comando de control con valores:
  • 0 - apaga la carga
  • 2 - enciende la carga
  • 4 - enciende o apaga la carga
  • 9 - desacoplamiento (iniciar el proceso de borrar la dirección de la memoria de la unidad de alimentación)
  • 15 - encuadernación (registre la dirección del módulo en la unidad de alimentación)

B4 - dirección del canal (de 0 a 31). Solo 32 canales.
otros bytes por defecto, excepto la suma de verificación.
B0 : configuración del modo de transmisión del módulo.
Si el valor 80 (0x50) se pasa a B0, entonces:
  • cantidad de repeticiones - 2
  • bitrate 2-1000 bps
  • modo 0: envía un comando


Como resultado, compilé tal tabla con los paquetes de control necesarios para mí.
Colocación en el cuadro eléctrico

Se decidió instalar una corriente débil en la centralita interna:
  • El RPI se monta en un riel DIN uniendo amigos impresos en una impresora 3D
  • Módulo MT1132 para controlar unidades de potencia por aire
  • dos ~ 220 enchufes en DIN para la conexión de unidades de alimentación de un enrutador y RPI


Depuración de integración y selección de envoltorios para gestión


Prerrequisitos:
  • RPI
  • Módulo MT1132
  • cables de madre a madre para conectar los pines MT1132 y RPI GPIO
  • Tarjeta SD con cualquier imagen RPI preinstalada
  • acceso a la consola RPI SHELL (bash, csh, korn, etc.) (teclado directo o remoto a través de SSH)
  • paquetes de control preparados
  • biblioteca para trabajar con UART a través del encabezado GPIO en RPI

Mientras preparaba la imagen, detecté un error genial en el Macbook Air mientras grababa la imagen Raspbian-wheezy debajo de la raíz (aunque para mí esta es una característica: protección adicional contra escritura, solo piense nuevamente antes de sobrescribir los datos):
dd bs=1m if=2015-02-16-raspbian-wheezy.img of=/dev/disk2

La consola devolvió:
dd: /dev/disk2: Permission denied 

Con el bloqueo eliminado en la tarjeta SD, debajo de la raíz y las modificaciones correctas en / dev / disk2 ...
Luego encontré un intercambio sobre este tema , alguien ayudó a volar en la ranura SD en la amapola, alguien consiguió una máquina tragamonedas. Vencer a un macbook es un desperdicio hoy, y como resultado, una pequeña brecha me ayudó: si la tarjeta SD no está completamente insertada, todo funcionará.
Durante la depuración, tuve que cultivar colectivamente, porque no había conectores adecuados de madre a madre.

Teniendo en cuenta que necesitaba un contenedor para controlar las unidades de potencia a través de WEB, la capacidad de realizar solicitudes REST en el futuro y una biblioteca UART desde una caja, la elección recayó en WebIOPi .

Aunque quería construir OpenHAB debido a la arquitectura genial. La plataforma de automatización se describió en Habré .
Definitivamente usaré esta plataforma en el futuro, pero por ahora, para mi "Lista de deseos", la plataforma elegida es suficiente.
Arquitectura general de interacción


Configuración de WebIOPi mínimo
Usando las instrucciones proporcionadas en el sitio web del proyecto:
  1. instale el marco de WebIOPi siguiendo estos pasos
    • Instalación
    • Ejecutando WebIOPi (Daemon)
    • Inicio automático en el arranque

  2. configure UART cambiando 3 archivos: / etc / inittab, /boot/cmdline.txt, / etc / webiopi / config. Pasos:
    • Uart a bordo
    • Configuración de WebIOPi

  3. reproducimos las acciones descritas en la sección
    • Truco de Loopback en serie (envíenos la "cadena" a través de UART y léala a través de la interfaz WEBIOPi en la sección Monitor en serie)
    • el video en la sección Serial Monitor muestra el proceso



Instale un puente para probar el bucle UART.
Usando la tabla compilada previamente con los paquetes de control, escribiremos un script simple de Python para administrar el módulo desde RPI SHELL.
Script de Shell RPI para el módulo MT1132
#!/usr/bin/python
import sys, getopt
def main(argv):
   ch = ''
   cmd = ''
   try:
      opts, args = getopt.getopt(argv,"h:",["ch=","cmd="])
   except getopt.GetoptError:
      print 'mt1132.py --ch <channel_number> --cmd <ON/OFF/BIND/UNBIND>'
      sys.exit(2)
   for opt, arg in opts:
      if opt == '-h':
         print 'mt1132.py --ch <channel_number> --cmd <ON/OFF/BIND/UNBIND>'
         sys.exit()
      elif opt in ("--ch"):
         ch = arg
      elif opt in ("--cmd"):
         cmd = arg
   print 'Channel: ', ch
   print 'Command: ', cmd
   if cmd=='ON' and ch!='':
        if ch=='0':
                print 'Switch ON channel 0'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00a7, 0x00aa])
        elif ch=='1':
                print 'Switch ON channel 1'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00a8, 0x00aa])
        elif ch=='2':
                print 'Switch ON channel 2'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00a9, 0x00aa])
        elif ch=='3':
                print 'Switch ON channel 3'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00aa, 0x00aa])
        elif ch=='4':
                print 'Switch ON channel 4'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00ab, 0x00aa])
        elif ch=='5':
                print 'Switch ON channel 5'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00ac, 0x00aa])
        elif ch=='6':
                print 'Switch ON channel 6'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00ad, 0x00aa])
        elif ch=='7':
                print 'Switch ON channel 7'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00ae, 0x00aa])
        elif ch=='8':
                print 'Switch ON channel 8'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00af, 0x00aa])
        elif ch=='9':
                print 'Switch ON channel 9'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00b0, 0x00aa])
        elif ch=='10':
                print 'Switch ON channel 10'
                serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00b1, 0x00aa])
   if cmd=='OFF' and ch!='':
        if ch=='0':
                print 'Switch OFF channel 0'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00a5, 0x00aa])
        elif ch=='1':
                print 'Switch OFF channel 1'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00a6, 0x00aa])
        elif ch=='2':
                print 'Switch OFF channel 2'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00a7, 0x00aa])
        elif ch=='3':
                print 'Switch OFF channel 3'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00a8, 0x00aa])
        elif ch=='4':
                print 'Switch OFF channel 4'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00a9, 0x00aa])
        elif ch=='5':
                print 'Switch OFF channel 5'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00aa, 0x00aa])
        elif ch=='6':
                print 'Switch OFF channel 6'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00ab, 0x00aa])
        elif ch=='7':
                print 'Switch OFF channel 7'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00ac, 0x00aa])
        elif ch=='8':
                print 'Switch OFF channel 8'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00ad, 0x00aa])
        elif ch=='9':
                print 'Switch OFF channel 9'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00ae, 0x00aa])
        elif ch=='10':
                print 'Switch OFF channel 10'
                serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00ae, 0x00aa])
   if cmd=='BIND' and ch!='':
        if ch=='0':
                print 'BIND channel 0'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00b4, 0x00aa])
        elif ch=='1':
                print 'BIND channel 1'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00b5, 0x00aa])
        elif ch=='2':
                print 'BIND channel 2'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00b6, 0x00aa])
        elif ch=='3':
                print 'BIND channel 3'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00b7, 0x00aa])
        elif ch=='4':
                print 'BIND channel 4'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00b8, 0x00aa])
        elif ch=='5':
                print 'BIND channel 5'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00b9, 0x00aa])
        elif ch=='6':
                print 'BIND channel 6'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00ba, 0x00aa])
        elif ch=='7':
                print 'BIND channel 7'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00bb, 0x00aa])
        elif ch=='8':
                print 'BIND channel 8'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00bc, 0x00aa])
        elif ch=='9':
                print 'BIND channel 9'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00bd, 0x00aa])
        elif ch=='10':
                print 'BIND channel 10'
                serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00be, 0x00aa])
   if cmd=='UNBIND' and ch!='':
        if ch=='0':
                print 'UNBIND channel 0'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00ae, 0x00aa])
        elif ch=='1':
                print 'UNBIND channel 1'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00af, 0x00aa])
        elif ch=='2':
                print 'UNBIND channel 2'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00b0, 0x00aa])
        elif ch=='3':
                print 'UNBIND channel 3'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00b1, 0x00aa])
        elif ch=='4':
                print 'UNBIND channel 4'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00b2, 0x00aa])
        elif ch=='5':
                print 'UNBIND channel 5'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00b3, 0x00aa])
        elif ch=='6':
                print 'UNBIND channel 6'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00b4, 0x00aa])
        elif ch=='7':
                print 'UNBIND channel 7'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00b5, 0x00aa])
        elif ch=='8':
                print 'UNBIND channel 8'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00b6, 0x00aa])
        elif ch=='9':
                print 'UNBIND channel 9'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00b7, 0x00aa])
        elif ch=='10':
                print 'UNBIND channel 10'
                serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00b8, 0x00aa])
if __name__ == "__main__":
   main(sys.argv[1:])


Para controlar MT1132 desde la consola de shell, ejecute los siguientes comandos

mt1132.py --ch <channel_number> --cmd <ON/OFF/BIND/UNBIND>


Ajustamos la API REST El marco WebIOPi proporciona control a través de solicitudes HTTP en el estilo REST , lo que facilita la fijación de clientes móviles y simplifica la interacción cliente-servidor.
Copie y pegue el marco API REST usando el enlace de arriba:
  • Obtener la función GPIO
  • Establecer la función GPIO
  • Obtenga valor GPIO
  • Establecer valor GPIO
  • Salida de un solo pulso
  • Secuencia de bits de salida
  • Salida PWM con una relación de ciclo de trabajo
  • Salida PWM con un ángulo para servos
  • Llamar a una macro en el servidor
  • Obtenga el estado / configuración completo de GPIO

Nuestro caso es "Llamar a una macro en el servidor". La descripción no es grasa, pero es suficiente para el experimento:
HTTP POST / macros / (macro) / (args)
  • Devuelve el valor devuelto por la macro.

Como (macro) aún no se ha preparado, revisaremos el REST "Obtener el estado / configuración GPIO completo", y para esto necesitamos hacer una solicitud HTTP GET / *.
Abrimos cualquier cliente API REST, utilicé el cliente DHC para el navegador Chrome. Estamos intentando realizar una solicitud REST para obtener la hora actual.

Configuración de WebIOPi (/ etc / webiopi / config)

En la sección [DISPOSITIVOS] :
Agregue un dispositivo serie (UART GPIO): este es nuestro módulo MT1132, donde
ttyAMA0 es el dispositivo (puerto) que ve el núcleo de Raspbian, la velocidad en
baudios es la velocidad en Intercambio de información en baudios a través de esta interfaz UART.
9600 baudios / (8 + 1 bit de inicio + 1 bit de parada) = 960 bytes / s.
En la sección [SCRIPTS] (scripts personalizados):
Agregue la cadena myscrypt = /home/pi/smarthome/python/mt1132.py para conectar nuestro script al marco.
En la sección [REST] (configuración de control GPIO a través de la API REST. Opcional):
gpio-post-value = false - prohíbe cambiar los niveles lógicos BAJO / ALTO en los pines GPIO a través de solicitudes REST;
gpio-post-function = false: prohíbe cambiar la configuración IN / OUT en los pines GPIO a través de solicitudes REST.
Los ajustes restantes no se modifican.
[COAP] :
no toqué, desconectar. Si bien no tengo idea de con qué se come y dónde se usa. Grabé solo esta línea en mi cabeza: oAP - es un protocolo de transferencia web especializado para usar con nodos restringidos y redes restringidas en elInternet of Things , diseñado para aplicaciones de máquina a máquina (M2M) como la energía inteligente y la automatización de edificios ".
Quizás en Habr alguien abre casos útiles de uso.
Agregue macros para solicitudes REST a un script previamente preparado.
# Channel 0	
@webiopi.macro	
def ch0(cmd):
	if cmd=='on':
		serial.writeBytes([0x55, 0x50, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00a7, 0x00aa])
		webiopi.sleep(1)
		resp = 'Channel: 0, Cmd: ' + cmd + ', Status: ' + serial.readString()
	if cmd=='off':
		serial.writeBytes([0x55, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00a5, 0x00aa])
		webiopi.sleep(1)
		resp = 'Channel: 0, Cmd: ' + cmd + ', Status: ' + serial.readString()
	if cmd=='unbind':
		serial.writeBytes([0x55, 0x50, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00ae, 0x00aa])
		webiopi.sleep(1)
		resp = 'Channel: 0, Cmd: ' + cmd + ', Status: ' + serial.readString()
	if cmd=='bind':
		serial.writeBytes([0x55, 0x50, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00b4, 0x00aa])
		webiopi.sleep(1)
		resp = 'Channel: 0, Cmd: ' + cmd + ', Status: ' + serial.readString()
	return resp 


Prueba de solicitudes REST con macros

Enviamos una solicitud REST para "vincular la dirección del tercer canal NooLite MT1132 al bloque de alimentación en el que se inicia la vinculación" a través de DHC.
Si el paquete de control se envía con éxito, el módulo MT1132 responderá a través de UART TX al GPIO UART RX "OK". Si tiene éxito, la unidad de alimentación recordará la dirección del canal y parpadeará intensamente con el LED verde incorporado.

Cliente simple para Android


Inicialmente, no planeaba escribir una aplicación para Android, debido a que no tenía idea, tenía la intención de restringirme a un navegador. Luego, accidentalmente, entró en el canal de inicio de Android . El autor, Dmitry, cuenta en detalle con Andryukha cómo comenzar rápidamente su primer proyecto bajo la plataforma Androyd. ¡Muchas gracias al autor por el proyecto y el arduo trabajo!
Después de ver y completar no más de veinte lecciones, comencé a crear mi sencilla aplicación de control de iluminación. Para el desarrollo utilicé IDE Android Studio, como indica Google, basado en IntelliJ IDEA.
Interfaz El
resultado fue una interfaz muy ascética:

main.xml TAL CUAL
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/hl7"
    android:padding="2dp"
    android:clickable="false">

    <!-- -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/r1c1"
            android:textSize="18sp"
            android:layout_width="110dp"
            android:layout_height="match_parent"
            android:padding="4dp"
            android:layout_margin="1dp"
            android:text=""
            android:background="@color/hl4"
            android:layout_weight="1"
            android:gravity="center"
            android:textColor="@color/white" />
        <TextView
            android:textColor="@color/white"
            android:textSize="18sp"
            android:id="@+id/r1c2"
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:padding="4dp"
            android:text=" "
            android:layout_margin="1dp"
            android:background="@color/hl4"
            android:layout_weight="2"
            android:gravity="center"/>
        <TextView
            android:textColor="@color/white"
            android:textSize="18sp"
            android:id="@+id/r1c3"
            android:layout_width="150dp"
            android:layout_height="match_parent"
            android:padding="4dp"
            android:text=""
            android:layout_margin="1dp"
            android:background="@color/hl4"
            android:layout_weight="3"
            android:gravity="center"/>
    </LinearLayout>

    <!--  -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="110dp"
            android:layout_height="match_parent"
            android:textColor="@color/black"
            android:textSize="16sp"
            android:text="@string/room1txt"
            android:id="@+id/room1"
            android:layout_weight="1"
            android:layout_margin="1dp"
            android:padding="4dp"
            android:gravity="center"
            android:background="@color/holotheme_color"
            android:textStyle="bold" />
        <LinearLayout
            android:orientation="vertical"
            android:background="@color/hl8"
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:layout_margin="1dp"
            android:gravity="center|top">
            <TextView
                android:layout_width="match_parent"
                android:textColor="@color/hl9"
                android:layout_height="36dp"
                android:text="@string/place1txt"
                android:id="@+id/r1switch1"
                android:textSize="13sp"
                android:padding="4dp"
                android:gravity="center_vertical|left"
                android:background="@drawable/hover1"
                android:clickable="true"/>
            <TextView
                android:textSize="13sp"
                android:layout_width="match_parent"
                android:layout_height="36dp"
                android:textColor="@color/hl9"
                android:text="@string/place5txt"
                android:id="@+id/r1switch2"
                android:padding="4dp"
                android:gravity="center_vertical|left"
                android:background="@drawable/hover1"
                android:clickable="true"/>
            <TextView
                android:textSize="13sp"
                android:layout_width="match_parent"
                android:layout_height="36dp"
                android:textColor="@color/hl9"
                android:text="@string/place2txt"
                android:id="@+id/r1switch3"
                android:padding="4dp"
                android:gravity="center_vertical|left"
                android:background="@drawable/hover1"
                android:clickable="true"/>
        </LinearLayout>
        <LinearLayout
            android:background="@color/hl8"
            android:orientation="vertical"
            android:layout_width="150dp"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:gravity="center"
            android:layout_margin="1dp">
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="36dp">
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text=""
                    android:id="@+id/r1b1on" />
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_weight="1"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text=""
                    android:id="@+id/r1b1off" />
            </LinearLayout>
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="36dp">
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    android:text=""
                    android:id="@+id/r1b2on" />
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_weight="1"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text=""
                    android:id="@+id/r1b2off" />
            </LinearLayout>
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="36dp">
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text=""
                    android:id="@+id/r1b3on" />
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    android:text=""
                    android:id="@+id/r1b3off" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>

    <!--  -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">
        <TextView
            android:layout_width="110dp"
            android:layout_height="match_parent"
            android:textSize="16sp"
            android:text="@string/room2txt"
            android:id="@+id/room2"
            android:layout_weight="1"
            android:layout_margin="1dp"
            android:padding="4dp"
            android:gravity="center"
            android:background="@color/holotheme_color"
            android:textColor="@color/black"
            android:textStyle="bold"/>
        <TextView
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:textSize="13sp"
            android:text="@string/place1txt"
            android:textColor="@color/hl9"
            android:id="@+id/r2switch1"
            android:layout_weight="2"
            android:layout_margin="1dp"
            android:padding="4dp"
            android:gravity="center|left"
            android:background="@color/hl8"/>
        <LinearLayout
            android:background="@color/hl8"
            android:orientation="horizontal"
            android:layout_width="150dp"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:gravity="center"
            android:layout_margin="1dp">
            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="36dp"
                android:layout_weight="1"
                android:text=""
                android:id="@+id/r2b1on" />
            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="wrap_content"
                android:layout_weight="1"
                android:layout_height="36dp"
                android:text=""
                android:id="@+id/r2b1off" />
        </LinearLayout>
    </LinearLayout>

    <!--  -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">
        <TextView
            android:layout_width="110dp"
            android:layout_height="match_parent"
            android:textSize="16sp"
            android:text="@string/room3txt"
            android:id="@+id/room3"
            android:layout_weight="1"
            android:layout_margin="1dp"
            android:padding="4dp"
            android:textColor="@color/black"
            android:gravity="center"
            android:background="@color/holotheme_color"
            android:textStyle="bold"/>
        <TextView
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:textSize="13sp"
            android:textColor="@color/hl9"
            android:text="@string/place1txt"
            android:id="@+id/r3switch1"
            android:layout_weight="2"
            android:layout_margin="1dp"
            android:padding="4dp"
            android:gravity="center|left"
            android:background="@color/hl8"
            android:clickable="true"/>
        <LinearLayout
            android:background="@color/hl8"
            android:orientation="horizontal"
            android:layout_width="150dp"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:gravity="center"
            android:layout_margin="1dp">
            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="36dp"
                android:layout_weight="1"
                android:text=""
                android:id="@+id/r3b1on" />
            <Button
                style="?android:attr/buttonStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="36dp"
                android:layout_weight="1"
                android:text=""
                android:id="@+id/r3b1off" />
        </LinearLayout>
    </LinearLayout>

    <!--    -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="110dp"
            android:layout_height="match_parent"
            android:textSize="16sp"
            android:text="@string/room4txt"
            android:id="@+id/room4"
            android:layout_weight="1"
            android:layout_margin="1dp"
            android:padding="4dp"
            android:gravity="center"
            android:background="@color/holotheme_color"
            android:textColor="@color/black"
            android:textStyle="bold" />
        <LinearLayout
            android:orientation="vertical"
            android:background="@color/hl8"
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:layout_margin="1dp"
            android:gravity="center">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="37dp"
                android:text="@string/place6txt"
                android:textColor="@color/hl9"
                android:id="@+id/r4switch1"
                android:textSize="13sp"
                android:padding="4dp"
                android:gravity="center_vertical|left"
                android:background="@drawable/hover1"
                android:clickable="true"/>
            <TextView
                android:layout_width="match_parent"
                android:layout_height="37dp"
                android:text="@string/place8txt"
                android:textColor="@color/hl9"
                android:id="@+id/r4switch3"
                android:textSize="13sp"
                android:padding="4dp"
                android:gravity="center_vertical|left"
                android:background="@drawable/hover1"
                android:clickable="true"/>
            <TextView
                android:textSize="13sp"
                android:layout_width="match_parent"
                android:textColor="@color/hl9"
                android:layout_height="37dp"
                android:text="@string/place7txt"
                android:id="@+id/r4switch2"
                android:padding="4dp"
                android:gravity="center_vertical|left"
                android:background="@drawable/hover1"
                android:clickable="true"/>
        </LinearLayout>
        <LinearLayout
            android:background="@color/hl8"
            android:orientation="vertical"
            android:layout_width="150dp"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:gravity="center"
            android:layout_margin="1dp">
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="37dp">
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text=""
                    android:id="@+id/r4b1on" />
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    android:text=""
                    android:id="@+id/r4b1off" />
            </LinearLayout>
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="36dp">
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text=""
                    android:id="@+id/r4b3on" />
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    android:text=""
                    android:id="@+id/r4b3off" />
            </LinearLayout>
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="36dp">
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text=""
                    android:id="@+id/r4b2on" />
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    android:text=""
                    android:id="@+id/r4b2off" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>


    <!--  -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="110dp"
            android:layout_height="match_parent"
            android:textSize="16sp"
            android:text="@string/room5txt"
            android:id="@+id/room5"
            android:layout_weight="1"
            android:layout_margin="1dp"
            android:padding="4dp"
            android:gravity="center"
            android:textColor="@color/black"
            android:background="@color/holotheme_color"
            android:textStyle="bold" />
        <LinearLayout
            android:orientation="vertical"
            android:background="@color/hl8"
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:layout_margin="1dp"
            android:gravity="center">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="36dp"
                android:text="@string/place3txt"
                android:textColor="@color/hl9"
                android:id="@+id/r5switch1"
                android:textSize="13sp"
                android:padding="4dp"
                android:gravity="center_vertical|left"
                android:background="@drawable/hover1"
                android:clickable="true"/>
            <TextView
                android:textSize="13sp"
                android:layout_width="match_parent"
                android:layout_height="37dp"
                android:textColor="@color/hl9"
                android:text="@string/place4txt"
                android:id="@+id/r5switch2"
                android:padding="4dp"
                android:gravity="center_vertical|left"
                android:background="@drawable/hover1"
                android:clickable="true"/>
        </LinearLayout>
        <LinearLayout
            android:background="@color/hl8"
            android:orientation="vertical"
            android:layout_width="150dp"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:gravity="center"
            android:layout_margin="1dp">
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="36dp">
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text=""
                    android:id="@+id/r5b1on" />
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    android:text=""
                    android:id="@+id/r5b1off" />
            </LinearLayout>
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="37dp">
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text=""
                    android:id="@+id/r5b2on" />
                <Button
                    style="?android:attr/buttonStyleSmall"
                    android:layout_width="wrap_content"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    android:text=""
                    android:id="@+id/r5b2off" />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>

</LinearLayout>


Los métodos de OnClick están vinculados a botones.
@Override
    public void onClick(View v) {
        // define the button switch that invoked the listener by id
        switch (v.getId()) {
            // Buttons room1 
            case R.id.r1b1on: // 
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room1txt)+" > "+r1sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch4url) + "on";
                new ParseTask().execute();
                break;

Switch define la vista de ID del elemento del botón, muestra un mensaje TOAST en la pantalla y realiza una solicitud HTTP al RPI a través de HttpURLConnection dentro de AsyncTask (llame a ParseTask (). Execute ();).
Interacción con el backend
HttpURLConnection: una clase para la interacción a través del protocolo HTTP.
Método de clase AsyncTask doInBackground: realiza tareas pesadas en una secuencia de fondo separada y devuelve el resultado a la secuencia de la interfaz de usuario.
HttpURLConnection se ejecuta en el método doInBackground.
Esta técnica a menudo se encuentra en Internet para implementar el intercambio de datos a través del protocolo HTTP.
webiopiurl = getString(R.string.ch4url) + "on";

Sustituye una constante del archivo strings.xml en los recursos del proyecto
<string name="ch4url">http://192.168.1.154:8000/macros/ch4/</string>

Entonces, la URL completa para habilitar el canal 4 se ve así
http://192.168.1.154:8000/macros/ch4/on

// HTTP Query to backend in REST style
    private class ParseTask extends AsyncTask<Void, Void, String> {
        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;
        String result = "";
        String BASIC_AUTH = "Basic "
                + Base64.encodeToString((getString(R.string.login) + ":" + getString(R.string.pwd)).getBytes(), Base64.NO_WRAP);

        @Override
        protected String doInBackground(Void... params) {
            //    REST 
            try {
                URL url = new URL(webiopiurl);
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestMethod("POST");
                urlConnection.setRequestProperty("Authorization", BASIC_AUTH);
                urlConnection.connect();
                //    backend webiopi
                InputStream inputStream = urlConnection.getInputStream();
                StringBuffer buffer = new StringBuffer();
                reader = new BufferedReader(new InputStreamReader(inputStream));
                String line;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }
                result = buffer.toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }

código MainActivity.java TAL CUAL
package ru.bbq.smarthome_App;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends ActionBarActivity implements View.OnClickListener {
    // Add logger
    public static String LOG_TAG = "my_log";
    public static String webiopiurl = "";
    // switch buttons
    TextView r1sw1;
    TextView r1sw2;
    TextView r1sw3;
    TextView r2sw1;
    TextView r3sw1;
    TextView r4sw1;
    TextView r4sw2;
    TextView r4sw3;
    TextView r5sw1;
    TextView r5sw2;
    // ON OFF buttons
    Button r1b1on;
    Button r1b1off;
    Button r1b2on;
    Button r1b2off;
    Button r1b3on;
    Button r1b3off;
    Button r2b1on;
    Button r2b1off;
    Button r3b1on;
    Button r3b1off;
    Button r4b1on;
    Button r4b1off;
    Button r4b2on;
    Button r4b2off;
    Button r4b3on;
    Button r4b3off;
    Button r5b1on;
    Button r5b1off;
    Button r5b2on;
    Button r5b2off;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // find View-elements and buttons
        r1sw1 = (TextView) findViewById(R.id.r1switch1); // room1switch1
        r1sw2 = (TextView) findViewById(R.id.r1switch2); // room1switch2
        r1sw3 = (TextView) findViewById(R.id.r1switch3); // room1switch3
        r2sw1 = (TextView) findViewById(R.id.r2switch1); // room2switch1
        r3sw1 = (TextView) findViewById(R.id.r3switch1); // room3switch1
        r4sw1 = (TextView) findViewById(R.id.r4switch1); // room4switch1
        r4sw2 = (TextView) findViewById(R.id.r4switch2); // room4switch2
        r4sw3 = (TextView) findViewById(R.id.r4switch3); // room4switch3
        r5sw1 = (TextView) findViewById(R.id.r5switch1); // room5switch1
        r5sw2 = (TextView) findViewById(R.id.r5switch2); // room5switch2
        r1b1on = (Button) findViewById(R.id.r1b1on);    // room1 button1 ON
        r1b1off = (Button) findViewById(R.id.r1b1off);  // room1 button1 OFF
        r1b2on = (Button) findViewById(R.id.r1b2on);    // room1 button2 ON
        r1b2off = (Button) findViewById(R.id.r1b2off);  // room1 button2 OFF
        r1b3on = (Button) findViewById(R.id.r1b3on);    // room1 button3 ON
        r1b3off = (Button) findViewById(R.id.r1b3off);  // room1 button3 OFF
        r2b1on = (Button) findViewById(R.id.r2b1on);    // room2 button1 ON
        r2b1off = (Button) findViewById(R.id.r2b1off);  // room2 button1 OFF
        r3b1on = (Button) findViewById(R.id.r3b1on);    // room3 button1 ON
        r3b1off = (Button) findViewById(R.id.r3b1off);  // room3 button1 OFF
        r4b1on = (Button) findViewById(R.id.r4b1on);    // room4 button1 ON
        r4b1off = (Button) findViewById(R.id.r4b1off);  // room4 button1 OFF
        r4b2on = (Button) findViewById(R.id.r4b2on);    // room4 button2 ON
        r4b2off = (Button) findViewById(R.id.r4b2off);  // room4 button2 OFF
        r4b3on = (Button) findViewById(R.id.r4b3on);    // room4 button3 ON
        r4b3off = (Button) findViewById(R.id.r4b3off);  // room4 button3 OFF
        r5b1on = (Button) findViewById(R.id.r5b1on);    // room5 button1 ON
        r5b1off = (Button) findViewById(R.id.r5b1off);  // room5 button1 OFF
        r5b2on = (Button) findViewById(R.id.r5b2on);    // room5 button2 ON
        r5b2off = (Button) findViewById(R.id.r5b2off);  // room5 button2 OFF

        //assign listeners to buttons
        r1b1on.setOnClickListener(this);
        r1b1off.setOnClickListener(this);
        r1b2on.setOnClickListener(this);
        r1b2off.setOnClickListener(this);
        r1b3on.setOnClickListener(this);
        r1b3off.setOnClickListener(this);
        r2b1on.setOnClickListener(this);
        r2b1off.setOnClickListener(this);
        r3b1on.setOnClickListener(this);
        r3b1off.setOnClickListener(this);
        r4b1on.setOnClickListener(this);
        r4b1off.setOnClickListener(this);
        r4b2on.setOnClickListener(this);
        r4b2off.setOnClickListener(this);
        r4b3on.setOnClickListener(this);
        r4b3off.setOnClickListener(this);
        r5b1on.setOnClickListener(this);
        r5b1off.setOnClickListener(this);
        r5b2on.setOnClickListener(this);
        r5b2off.setOnClickListener(this);
    }

    // Define On ClickView method
    @Override
    public void onClick(View v) {
        // define the button switch that invoked the listener by id
        switch (v.getId()) {
            // Buttons room1 
            case R.id.r1b1on: // 
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room1txt)+" > "+r1sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch4url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r1b1off: // 
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room1txt)+" > "+r1sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch4url) + "off";
                new ParseTask().execute();
                break;
            case R.id.r1b2on: //  
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room1txt)+" > "+r1sw2.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch3url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r1b2off: //  
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room1txt)+" > "+r1sw2.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch3url) + "off";
                new ParseTask().execute();
                break;
            case R.id.r1b3on: // LED 
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room1txt)+" > "+r1sw3.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch2url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r1b3off: // LED 
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room1txt)+" > "+r1sw3.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch2url) + "off";
                new ParseTask().execute();
                break;
            // Buttons room2 
            case R.id.r2b1on:
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room2txt)+" > "+r2sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch6url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r2b1off:
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room2txt)+" > "+r2sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch6url) + "off";
                new ParseTask().execute();
                break;
            // Buttons room3 
            case R.id.r3b1on:
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room3txt)+" > "+r3sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch5url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r3b1off:
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room3txt)+" > "+r3sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch5url) + "off";
                new ParseTask().execute();
                break;
            // Buttons room4 bedroom
            case R.id.r4b1on: //    
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room4txt)+" > "+r4sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch8url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r4b1off: //    
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room4txt)+" > "+r4sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch8url) + "off";
                new ParseTask().execute();
                break;
            case R.id.r4b2on: //    
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room4txt)+" > "+r4sw2.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch7url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r4b2off: //    
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room4txt)+" > "+r4sw2.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch7url) + "off";
                new ParseTask().execute();
                break;
            case R.id.r4b3on: //   dimmer
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room4txt)+" > "+r4sw3.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch9url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r4b3off: //   dimmer
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room4txt)+" > "+r4sw3.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch9url) + "off";
                new ParseTask().execute();
                break;
            // Buttons room5 corridor
            case R.id.r5b1on:
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room5txt)+" > "+r5sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch1url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r5b1off:
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room5txt)+" > "+r5sw1.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch1url) + "off";
                new ParseTask().execute();
                break;
            case R.id.r5b2on:
                Toast.makeText(this, getString(R.string.bon)+" '"+getString(R.string.room5txt)+" > "+r5sw2.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch0url) + "on";
                new ParseTask().execute();
                break;
            case R.id.r5b2off:
                Toast.makeText(this, getString(R.string.boff)+" '"+getString(R.string.room5txt)+" > "+r5sw2.getText()+"'", Toast.LENGTH_SHORT).show();
                webiopiurl = getString(R.string.ch0url) + "off";
                new ParseTask().execute();
                break;
        }
    }

    // HTTP Query to backend in REST style
    private class ParseTask extends AsyncTask<Void, Void, String> {
        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;
        String result = "";
        String BASIC_AUTH = "Basic "
                + Base64.encodeToString((getString(R.string.login) + ":" + getString(R.string.pwd)).getBytes(), Base64.NO_WRAP);
        @Override
        protected String doInBackground(Void... params) {
            //    REST 
            try {
                URL url = new URL(webiopiurl);
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestMethod("POST");
                urlConnection.setRequestProperty("Authorization", BASIC_AUTH);
                urlConnection.connect();
                //    backend webiopi
                InputStream inputStream = urlConnection.getInputStream();
                StringBuffer buffer = new StringBuffer();
                reader = new BufferedReader(new InputStreamReader(inputStream));
                String line;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }
                result = buffer.toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }

        @Override
        protected void onPostExecute(String str) {
            super.onPostExecute(str);
            //  ,    plain text ( JSON)
            //    log
            Log.d(LOG_TAG, str);
            //  TOAST -   webiopi     MT1132
            Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
        }
    }

}



Encuentre y compre interruptores adecuados para controles remotos


Basado en el escenario de iluminación, este proyecto utiliza teclados y botones / interruptores NooLite incorporados fijos, es necesario proporcionar la capacidad de instalar interruptores con tres módulos (botones / teclas), preservando el diseño de los interruptores (todos los interruptores deben tener el mismo aspecto).
Al elegir interruptores, considere la posibilidad de:
  • instalación de dos o tres módulos en el soporte de interruptores
  • instalación de botones y módulos de teclado

Los interruptores de luz de vida bticino son adecuados para estas condiciones. En la foto de abajo, los módulos ensamblados con el control remoto NooLite.


Unidad de alimentación en el techo durante la depuración. Depuración

en el sitio .

Panel eléctrico con corriente débil ubicada en el interior.

Gracias por su atención. ¡Que tengas un buen día!

Source: https://habr.com/ru/post/es382689/


All Articles