Controlar Box UMA da NOS RF

Nós a falarmos e hoje a NOS lançou uma nova UI para a box UMA (ainda não consegui confirmar na Iris). Uma mudança muito grande na abordagem aos conteúdos, não sei se estou fã, vamos ver nos próximos dias.

O que é mais estranho é que nesta actualização há agora uma opção para a NOS Comando que eles descontinuaram… alguém pode ver se esta opção existia na versão anterior da UMA?

Se a APP já foi descontinuada porque raio mantêm esta opção numa actualização de 2025?? Isto faz tanto sentido como terem tirado a app da PlayStore mas quem a tinha instalado conseguia continuar a usar…

Como está do vosso lado?

1 Curtiu

Não era muito usada porque foi tirada da Playstore, não sei quando mas tiraram. Só continuava a funcionar para quem já a tinha instalado antes.

O Luis Boaventura já fez esse trabalho nuns posts acima neste tópico, a imagem seguinte é dele

1 Curtiu

Bom dia malta.

Eu confesso que ja fiz coisas com um ESP32-S3, emulação de teclado e mandando esses comandos a BOX UMA responde. Depois parei porque cada vez uso menos a BOX, e não tenho conhecimentos para integrar isso no ESPHome, para fazer um componente, disponibilizei-me para ajudar e testar no ESPHome, mas não apareceu ninguem com vontade de pagar nisso…
Se alguem quiser pegar e tiver conhecimentos, use um ESP32-S3, ligado na porta USB do ESP a porta USB da BOX, use o exemplo em arduino de teclado e mande as teclas, basicamente foi até onde fui…
Depois é integrar isso no ESPHome, não sei se eventualmente já haverá um componente que emule um teclado, se assim for é só associar as teclas ás funcoes…
Boa sorte malta!

CF

vou mandar vir uns esps com USB HID - ESP32-S3, ESP32-S2 ou Lolin S2 Mini pois não tenho nenhum.
mal os tenha começo a explorar e dou feedback. a ideia é usar o esphome.

Vou validar isso.

Ativar isso pode ser a chave para voltar a fazer pedidos.

Eu disse que provavelmente estavam a criar algo novo por causa dessa atualização.

Logo já testo a ver se passa a funcionar

Já consegui configurar um ESP32-S2 ligado diretamente na porta USB da box uma.
Tentei com esphome, mas sem sucesso. Estou a usar Arduino e publicar no MQTT.
Para mim usar esphome ou mqtt vai dar ao mesmo, pois consigo ter as funções pretendidas.

Passo a passo: https://github.com/ruilima/ESP32-S2-HID-NOS-UMA

Excelente trabalho vou comprar um e usar essa opção.

Depois direcionar as minhas automacoes para mudar para a sic e assim

Muito obrigado por este trabalho

por isso comprei um IR baratinho e faz o trabalho e so falar muda para x canal aumenta o volume da um bocado de trabalho configurar botao por botao para ficar bonitinho mas depois de criar umas quantas cenas e so falar e como a minha tv nao e tao avançada nao tem como lhe dizer ei siri coloca o volume em 60 ou qualquer numero pois nao tem acesso ao volume master mas com um pouco de codigo da para fazer um encremento de volume tipo aumenta o volume em 10% ele so vai repetir o clicar do comando 10 vezes ehehe e uma bosta é mas funciona para mim com paciencia criei cenas para quando quero jogar digo jogar ele liga a tv espera um pouco carrega source depois esquerda ou direira do comando e ok e muda de hdmi1 para hdmi2 e vice versa apenas pedindo para ativar a cena “nome X” opçao bem barata

Pessoal, do meu lado a app Nos Comando voltou a funcionar a 100% na Iris e na UMA funciona quase tudo - as teclas de volume não funcionam. Vai-se lá perceber…

E do vosso lado?

Sim @ricardopinto voltou a funcionar embora algumas teclas não funcionam. Sendo que já existe a solução usando o ESP32-S2 vou continuar a usa-lo pois é mais rápido e garante que funciona sempre. Tenho os dois métodos a funcionar - se um não der o outro dá. :wink:

1 Curtiu

Sim confirmo voltou a funcionar.

Mas claramente vou comprar o esp32 para ficar uma segunda alternativa

Viva pessoal,

Cansei-me da app da nos comando e avancei para outra solução.

Comprei esta board a pouco mais de 5€ https://pt.aliexpress.com/item/1005010708666199.html (ESP32 S2) e com a ajuda do Chatgpt meti-a a funcionar como um teclado que aceita comandos por wifi.

Estes foram os passos que segui:

:toolbox: PASSO 1 - Preparar Arduino IDE

1. Instalar suporte ESP32

No Arduino IDE:

:point_right: Ficheiro → Preferências
:point_right: Em “Additional Board URLs” mete:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Depois:

:point_right: Ferramentas → Board → Board Manager
:point_right: procurar: esp32 by Espressif
:point_right: instalar

2. Escolher a board correta

:point_right: Ferramentas → Board:

Escolhe algo tipo:

  • ESP32S2 Dev Module

:electric_plug: PASSO 2 - Ligar e testar comunicação

Liga ao PC carregando no botão que vem na board

Depois:

:point_right: Ferramentas → Porta
Seleciona a porta que apareceu

:keyboard: PASSO 3 - Firmware teclado

Este foi o código que usei para aceitar teclas multimédia para controlar o volume

#include <WiFi.h>
#include <WebServer.h>
#include "USB.h"
#include "USBHIDKeyboard.h"
#include "USBHIDConsumerControl.h"

const char* ssid = "O_TEU_WIFI";
const char* password = "A_PASSWORD_DO_TEU_WIFI";

WebServer server(80);
USBHIDKeyboard Keyboard;
USBHIDConsumerControl Consumer;


void handleRoot() {
  String msg;
  msg += "ESP32-S2 Keyboard Ready\n";
  msg += "IP: " + WiFi.localIP().toString() + "\n\n";
  msg += "Use:\n";
  msg += "/type?text=Ola mundo\n";
  msg += "/key?name=ENTER\n";
  msg += "/key?name=MUTE\n";
  msg += "/key?name=VOLUP\n";
  msg += "/key?name=VOLDOWN\n";
  server.send(200, "text/plain", msg);
}

// --- escrever texto ---
void handleType() {
  if (!server.hasArg("text")) {
    server.send(400, "text/plain", "Falta parametro text");
    return;
  }

  String text = server.arg("text");
  Keyboard.print(text);
  server.send(200, "text/plain", "OK");
}

// --- teclas especiais ---
void handleKey() {
  if (!server.hasArg("name")) {
    server.send(400, "text/plain", "Falta parametro name");
    return;
  }

  String k = server.arg("name");
  k.toUpperCase();

  if (k == "ENTER") Keyboard.write(KEY_RETURN);
  else if (k == "TAB") Keyboard.write(KEY_TAB);
  else if (k == "ESC") Keyboard.write(KEY_ESC);
  else if (k == "BACK" || k == "BACKSPACE") Keyboard.write(KEY_BACKSPACE);
  else if (k == "DELETE") Keyboard.write(KEY_DELETE);
  else if (k == "SPACE") Keyboard.write(' ');

  else if (k == "UP") Keyboard.write(KEY_UP_ARROW);
  else if (k == "DOWN") Keyboard.write(KEY_DOWN_ARROW);
  else if (k == "LEFT") Keyboard.write(KEY_LEFT_ARROW);
  else if (k == "RIGHT") Keyboard.write(KEY_RIGHT_ARROW);

  else if (k == "HOME") Keyboard.write(KEY_HOME);
  else if (k == "END") Keyboard.write(KEY_END);
  else if (k == "PAGEUP") Keyboard.write(KEY_PAGE_UP);
  else if (k == "PAGEDOWN") Keyboard.write(KEY_PAGE_DOWN);

  else if (k == "F1") Keyboard.write(KEY_F1);
  else if (k == "F2") Keyboard.write(KEY_F2);
  else if (k == "F3") Keyboard.write(KEY_F3);
  else if (k == "F4") Keyboard.write(KEY_F4);
  else if (k == "F5") Keyboard.write(KEY_F5);
  else if (k == "F6") Keyboard.write(KEY_F6);
  else if (k == "F7") Keyboard.write(KEY_F7);
  else if (k == "F8") Keyboard.write(KEY_F8);
  else if (k == "F9") Keyboard.write(KEY_F9);
  else if (k == "F10") Keyboard.write(KEY_F10);
  else if (k == "F11") Keyboard.write(KEY_F11);
  else if (k == "F12") Keyboard.write(KEY_F12);

  else if (k == "MUTE") {
    Consumer.press(HID_USAGE_CONSUMER_MUTE);
    delay(50);
    Consumer.release();
  }
  else if (k == "VOLUP") {
    Consumer.press(HID_USAGE_CONSUMER_VOLUME_INCREMENT);
    delay(50);
    Consumer.release();
  }
  else if (k == "VOLDOWN") {
    Consumer.press(HID_USAGE_CONSUMER_VOLUME_DECREMENT);
    delay(50);
    Consumer.release();
  }

  else {
    server.send(400, "text/plain", "Tecla nao suportada");
    return;
  }

  server.send(200, "text/plain", "OK");
}

void setup() {
  Keyboard.begin();
  Consumer.begin();
  USB.begin();

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) delay(250);

  server.on("/", handleRoot);
  server.on("/type", handleType);
  server.on("/key", handleKey);

  server.begin();
}

void loop() {
  server.handleClient();
}

E o mais importante está feito! A board passa a ser reconhecida como um teclado wifi quando ligada a uma box UMA 4K. Comprei a versão com case mas foi desnecessário porque com a case não cabe na porta USB.

Depois foi só fixar um IP para a board e fazer a integração no Home Assistant.

Depois fiz os seguintes passos:

1 - No configuration.yaml adicionei o código

rest_command: !include rest_command.yaml

2 - Depois criar um ficheiro chamado rest_command.yaml com o seguinte código

  box_uma_power:
    url: "http://IP_do_ESP32_S2/key?name=F12"
    method: GET

  box_uma_play_pause:
    url: "http://IP_do_ESP32_S2/type?text=p"
    method: GET

  box_uma_rewind:
    url: "http://IP_do_ESP32_S2/type?text=r"
    method: GET

  box_uma_fast_forward:
    url: "http://IP_do_ESP32_S2/type?text=f"
    method: GET

  box_uma_back:
    url: "http://IP_do_ESP32_S2/key?name=BACKSPACE"
    method: GET

  box_uma_home:
    url: "http://IP_do_ESP32_S2/key?name=HOME"
    method: GET

  box_uma_info:
    url: "http://IP_do_ESP32_S2/key?name=F1"
    method: GET

  box_uma_c_plus:
    url: "http://IP_do_ESP32_S2/key?name=PAGEUP"
    method: GET

  box_uma_c_minus:
    url: "http://IP_do_ESP32_S2/key?name=PAGEDOWN"
    method: GET

  box_uma_vol_plus:
    url: "http://IP_do_ESP32_S2/key?name=VOLUP"
    method: GET

  box_uma_vol_minus:
    url: "http://IP_do_ESP32_S2/key?name=VOLDOWN"
    method: GET

  box_uma_vol_mute:
    url: "http://IP_do_ESP32_S2/key?name=MUTE"
    method: GET

  box_uma_netflix:
    url: "http://IP_do_ESP32_S2/key?name=F7"
    method: GET

  box_uma_apps:
    url: "http://IP_do_ESP32_S2/key?name=F8"
    method: GET

  box_uma_prime_video:
    url: "http://IP_do_ESP32_S2/key?name=F9"
    method: GET

  box_uma_up:
    url: "http://IP_do_ESP32_S2/key?name=UP"
    method: GET

  box_uma_down:
    url: "http://IP_do_ESP32_S2/key?name=DOWN"
    method: GET

  box_uma_left:
    url: "http://IP_do_ESP32_S2/key?name=LEFT"
    method: GET

  box_uma_right:
    url: "http://IP_do_ESP32_S2/key?name=RIGHT"
    method: GET

  box_uma_ok:
    url: "http://IP_do_ESP32_S2/key?name=ENTER"
    method: GET

  box_uma_0:
    url: "http://IP_do_ESP32_S2/type?text=0"
    method: GET

  box_uma_1:
    url: "http://IP_do_ESP32_S2/type?text=1"
    method: GET

  box_uma_2:
    url: "http://IP_do_ESP32_S2/type?text=2"
    method: GET

  box_uma_3:
    url: "http://IP_do_ESP32_S2/type?text=3"
    method: GET

  box_uma_4:
    url: "http://IP_do_ESP32_S2/type?text=4"
    method: GET

  box_uma_5:
    url: "http://IP_do_ESP32_S2/type?text=5"
    method: GET

  box_uma_6:
    url: "http://IP_do_ESP32_S2/type?text=6"
    method: GET

  box_uma_7:
    url: "http://IP_do_ESP32_S2/type?text=7"
    method: GET

  box_uma_8:
    url: "http://IP_do_ESP32_S2/type?text=8"
    method: GET

  box_uma_9:
    url: "http://IP_do_ESP32_S2/type?text=9"
    method: GET

3 - Validar tudo e reiniciar o HA

4 - Agora é altura de fazer o card. Fiz o seguinte mas confesso que ainda não está como eu gosto, tentei replicar o layout do comando.

type: vertical-stack
cards:
  - type: markdown
    content: '## Box Uma'
  - type: grid
    columns: 3
    square: true
    cards:
      - type: button
        icon: mdi:volume-off
        tap_action:
          action: call-service
          service: rest_command.box_uma_vol_mute
      - type: button
        name: ' '
        tap_action:
          action: none
      - type: button
        icon: mdi:power
        tap_action:
          action: call-service
          service: rest_command.box_uma_power
  - type: grid
    columns: 3
    square: false
    cards:
      - type: button
        icon: mdi:rewind
        tap_action:
          action: call-service
          service: rest_command.box_uma_rewind
      - type: button
        icon: mdi:play-pause
        tap_action:
          action: call-service
          service: rest_command.box_uma_play_pause
      - type: button
        icon: mdi:fast-forward
        tap_action:
          action: call-service
          service: rest_command.box_uma_fast_forward
  - type: grid
    columns: 3
    square: true
    cards:
      - type: button
        name: ' '
        tap_action:
          action: none
      - type: button
        icon: mdi:arrow-up
        tap_action:
          action: call-service
          service: rest_command.box_uma_up
      - type: button
        name: ' '
        tap_action:
          action: none
      - type: button
        icon: mdi:arrow-left
        tap_action:
          action: call-service
          service: rest_command.box_uma_left
      - type: button
        icon: mdi:checkbox-blank-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_ok
      - type: button
        icon: mdi:arrow-right
        tap_action:
          action: call-service
          service: rest_command.box_uma_right
  - type: grid
    columns: 3
    square: true
    cards:
      - type: button
        name: ' '
        tap_action:
          action: none
      - type: button
        icon: mdi:arrow-down
        tap_action:
          action: call-service
          service: rest_command.box_uma_down
      - type: button
        name: ' '
        tap_action:
          action: none
  - type: grid
    columns: 3
    square: false
    cards:
      - type: button
        icon: mdi:keyboard-backspace
        tap_action:
          action: call-service
          service: rest_command.box_uma_back
      - type: button
        icon: mdi:home
        tap_action:
          action: call-service
          service: rest_command.box_uma_home
      - type: button
        icon: mdi:information
        tap_action:
          action: call-service
          service: rest_command.box_uma_info
  - type: grid
    columns: 4
    square: true
    cards:
      - type: button
        icon: mdi:volume-plus
        tap_action:
          action: call-service
          service: rest_command.box_uma_vol_plus
      - type: button
        name: ' '
        tap_action:
          action: none
      - type: button
        name: ' '
        tap_action:
          action: none
      - type: button
        icon: mdi:arrow-up-circle
        tap_action:
          action: call-service
          service: rest_command.box_uma_c_plus
  - type: grid
    columns: 4
    square: true
    cards:
      - type: button
        icon: mdi:volume-minus
        tap_action:
          action: call-service
          service: rest_command.box_uma_vol_minus
      - type: button
        name: ' '
        tap_action:
          action: none
      - type: button
        name: ' '
        tap_action:
          action: none
      - type: button
        icon: mdi:arrow-down-circle
        tap_action:
          action: call-service
          service: rest_command.box_uma_c_minus
  - type: grid
    columns: 3
    square: true
    cards:
      - type: button
        icon: mdi:netflix
        tap_action:
          action: call-service
          service: rest_command.box_uma_netflix
      - type: button
        icon: mdi:apps
        tap_action:
          action: call-service
          service: rest_command.box_uma_apps
      - type: button
        icon: mdi:youtube
        tap_action:
          action: call-service
          service: script.box_uma_youtube
  - type: grid
    columns: 5
    square: true
    cards:
      - type: button
        icon: mdi:numeric-1-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_1
      - type: button
        icon: mdi:numeric-2-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_2
      - type: button
        icon: mdi:numeric-3-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_3
      - type: button
        icon: mdi:numeric-4-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_4
      - type: button
        icon: mdi:numeric-5-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_5
      - type: button
        icon: mdi:numeric-6-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_6
      - type: button
        icon: mdi:numeric-7-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_7
      - type: button
        icon: mdi:numeric-8-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_8
      - type: button
        icon: mdi:numeric-9-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_9
      - type: button
        icon: mdi:numeric-0-circle-outline
        tap_action:
          action: call-service
          service: rest_command.box_uma_0

Quem quiser dar sugestões, serão bem-vindas!

5 - Com os commands definidos quis testar uma coisa que o comando não permite, um botão para iniciar logo o Youtube. A ideia foi criar um script que simulasse as teclas necessárias até chegar à APP Youtube mas que podem mudar a qualquer altura.

Este foi o script que fiz

box_uma_youtube:
  alias: Box Uma - Youtube
  sequence:
  - action: rest_command.box_uma_apps
  - delay:
      milliseconds: 500
  - repeat:
      count: 7
      sequence:
      - action: rest_command.box_uma_right
      - delay:
          milliseconds: 250
  - delay:
      milliseconds: 400
  - action: rest_command.box_uma_ok
  mode: single
  description: ''
  icon: mdi:youtube

Este script simula carregar no botão das APPs, andar para a direita 7 vezes e carregar em OK.

Seguindo esta lógica podem fazer diferentes automações e botões como a APP do TVCine+

Também queria testar botões para os canais em vez de apenas números.

Com esta base a imaginação é mesmo o limite.

O que isto não permite fazer é saber o estado da box (precisamos de uma tomada wifi/zigbee para saber se está on ou off) ou o tipo de conteúdo que está a dar mas já me permite controlar a box pelo home assistant.

Espero que seja útil para mais alguém!


Copyright © 2017-. Todos os direitos reservados
CPHA.pt - info@cpha.pt


FAQ | Termos de Serviço/Regras | Política de Privacidade