[Compartilhando] Monitoramento Metrô/CPTM via Node-Red

Fala Pessoal,

Compartilhando com vocês um projetinho que monitora as Linhas de Metrô e Trem de São Paulo/SP baseado no Rastreamento Correios [Node-Red] do queridissimo @kelvinrafaeli.

Ahaaaa José, mas eu não uso metrô e CPTM de SP!!! Tranquilo, espero que sirva de inspiração para te ajudar em alguma outra necessidade.

Node Red

Código Node-Red:

[{"id":"a9677bd61d822a0b","type":"group","z":"ae486ad7c144f9df","name":"Metrô SP","style":{"stroke":"#a4a4a4","fill":"#e1e1e1","label":true,"color":"#000000"},"nodes":["1d45cb0596f828cb","795606b7d45dde2a","3b95ce65a0a271ac","d74b89b621ccbf65","1cadc20bd1bdc102","159ac8b655c8c06a","d37a60a3885b8973","9ece87c268947457"],"x":34,"y":259,"w":832,"h":142},{"id":"1d45cb0596f828cb","type":"inject","z":"ae486ad7c144f9df","g":"a9677bd61d822a0b","name":"Digitar Chave token e IP","props":[{"p":"payload"}],"repeat":"1800","crontab":"","once":true,"onceDelay":"2","topic":"","payload":"","payloadType":"date","x":95,"y":300,"wires":[["795606b7d45dde2a"]],"l":false},{"id":"795606b7d45dde2a","type":"change","z":"ae486ad7c144f9df","g":"a9677bd61d822a0b","name":"Token e IP HASS","rules":[{"t":"set","p":"token","pt":"flow","to":"SEU_TOKEN_AQUI","tot":"str"},{"t":"set","p":"ip","pt":"flow","to":"192.168.15.83:8123","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":300,"wires":[[]]},{"id":"3b95ce65a0a271ac","type":"switch","z":"ae486ad7c144f9df","g":"a9677bd61d822a0b","name":"","property":"from","propertyType":"msg","rules":[{"t":"eq","v":"to","vt":"msg"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":790,"y":360,"wires":[[],["d74b89b621ccbf65"]]},{"id":"d74b89b621ccbf65","type":"http request","z":"ae486ad7c144f9df","g":"a9677bd61d822a0b","name":"Site","method":"GET","ret":"txt","paytoqs":"body","url":"http://apps.cptm.sp.gov.br:8080/AppMobileService/api/LinhasMetropolitanas","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":270,"y":360,"wires":[["1cadc20bd1bdc102"]]},{"id":"1cadc20bd1bdc102","type":"json","z":"ae486ad7c144f9df","g":"a9677bd61d822a0b","name":"","property":"payload","action":"","pretty":false,"x":390,"y":360,"wires":[["159ac8b655c8c06a"]]},{"id":"159ac8b655c8c06a","type":"function","z":"ae486ad7c144f9df","g":"a9677bd61d822a0b","name":"Cria Sensor","func":"msg.from = msg.from + 1;\n\nmsg.entity_id = 'sensor.transporte_' + msg.from;\n\n// Verificar se payload é um array e se o índice from é válido\nif (!Array.isArray(msg.payload) || msg.from >= msg.payload.length) {\n    // Encerra o fluxo se a condição não for atendida\n    return null;\n}\n\nvar dados = msg.payload[msg.from];\n\nif (!dados) {\n    return null; // Garante que não tenta acessar propriedades de um objeto indefinido\n}\n\nvar status = dados.Status || \"Desconhecido\";\nvar descricao = dados.Descricao || \"Sem Detalhamento\";\nvar linha_id = dados.LinhaId || \"N/A\";\nvar nome = (dados.Nome || \"Sem Nome\").charAt(0).toUpperCase() + (dados.Nome || \"\").slice(1).toLowerCase();\nvar tipo = dados.Tipo || \"N/A\";\n\nvar data_geracao = new Date(dados.DataGeracao || Date.now());\nvar data_formatada = data_geracao.toLocaleString('pt-BR');\n\nmsg.payload = {\n    data: {\n        state: status,\n        attributes: {\n            nome: nome,\n            status: status,\n            descricao: descricao,\n            linha_id: linha_id,\n            tipo: tipo,\n            data_geracao: data_formatada,\n            texto_sensor: `- Status: ${status}\\n- Descrição:\\n          ${descricao}\\n- Atualização: ${data_formatada}`,\n            friendly_name: `Linha ${linha_id} ${nome}`,\n        }\n    }\n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":360,"wires":[["9ece87c268947457"]]},{"id":"d37a60a3885b8973","type":"inject","z":"ae486ad7c144f9df","g":"a9677bd61d822a0b","name":"","props":[{"p":"from","v":"-1","vt":"num"},{"p":"to","v":"13","vt":"num"}],"repeat":"120","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":360,"wires":[["d74b89b621ccbf65"]]},{"id":"9ece87c268947457","type":"ha-api","z":"ae486ad7c144f9df","g":"a9677bd61d822a0b","name":"","server":"2b35d450378a9ff7","version":1,"debugenabled":false,"protocol":"http","method":"post","path":"/api/states/{{entity_id}}","data":"","dataType":"json","responseType":"json","outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"results"}],"x":670,"y":360,"wires":[["3b95ce65a0a271ac"]]},{"id":"2b35d450378a9ff7","type":"server","name":"Home Assistant","version":5,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":": ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"default","statusTimeFormat":"h:m","enableGlobalContextStore":false}]

Lovelace

Código Lovelace

- type: vertical-stack
  cards:
    - type: custom:button-card
      layout: icon_name
      name: Situação Linhas Metrô/CPTM SP
      icon: mdi:train
      styles:
        grid:
          - grid-template-areas: '"n i"'
          - grid-template-columns: 1fr 20%
        icon:
          - align-self: end
          - color: var(--text-primary-color)
          - height: 35px
        card:
          - padding: 4px
          - height: 40px
          - background: '#001487'
        name:
          - color: var(--text-primary-color)
          - justify-self: start
          - padding-left: 10%
          - font-weight: 400
          - font-size: 18px
    - type: custom:auto-entities
      card:
        type: grid
        columns: 1
        square: false
      card_param: cards
      show_empty: false
      filter:
        include:
          - entity_id: sensor.transporte_*
            options:
              type: custom:mushroom-template-card
              entity: this.entity_id
              primary: '{{ state_attr(''this.entity_id'', ''friendly_name'') }}'
              secondary: '{{ state_attr(''this.entity_id'', ''texto_sensor'') }}'
              icon: |-
                {% if
                  states['this.entity_id'].state == "Informação indisponível" %} mdi:close-box {% elif
                  states['this.entity_id'].state == "Operação Normal" %} mdi:check-circle {% elif
                  states['this.entity_id'].state == "Operação Parcial" %} mdi:alert-rhombus-outline {% elif
                  states['this.entity_id'].state == "Operação com Impacto Pontual" %} mdi:alert-circle {% elif
                  states['this.entity_id'].state == "Circulação de Trens" %} mdi:alert-circle {% elif
                  states['this.entity_id'].state == "Velocidade Reduzida" %} mdi:speedometer-slow {% elif
                  states['this.entity_id'].state == "Atividade Programada" %} mdi:calendar-clock {% elif
                  states['this.entity_id'].state == "Operação Encerrada" %} mdi:close-circle {% elif
                  states['this.entity_id'].state == "Operações Encerradas" %} mdi:close-circle {% endif %}
              icon_color: |-
                {% if
                  states['this.entity_id'].state == "Informação indisponível" %} red {% elif 
                  states['this.entity_id'].state == "Operação Normal" %} green {% elif 
                  states['this.entity_id'].state == "Operação Parcial" %} red {% elif
                  states['this.entity_id'].state == "Operação com Impacto Pontual" %} yellow {% elif
                  states['this.entity_id'].state == "Circulação de Trens" %} '#e1762b' {% elif
                  states['this.entity_id'].state == "Velocidade Reduzida" %} '#e2d96e' {% elif
                  states['this.entity_id'].state == "Atividade Programada" %} yellow {% elif
                  states['this.entity_id'].state == "Operação Encerrada" %} '#d0cace' {% elif
                  states['this.entity_id'].state == "Operações Encerradas" %} '#d0cace' {% endif %}
              multiline_secondary: true
              tap_action:
                action: more-info
              order_by:
                last_changed: asc
      sort:
        count: 15
2 curtidas

Opa, fiz a configuração, mas apareceu somente a barra de título (Azul) no dashboard do Lovelace, tem alguma configuação específica que preciso fazer no HA? Obrigado

Mals Mano, jurava que tinha respondido…

Especifica não tem não, vc tem o complemento button-card? Inseriu o seu IP e o Token de Longa Duração?

Tenta colocar Debug nos nós do Node Red e vê se tá dando erro na criação do Sensor.

Opa, tudo bem…
Fiz a revisão em todos os componentes inclusive com o debug, mas não funcionou… Não sei se é a minha versão do HAOS ou de algum componente que pode ser incompatível, mas sem problemas, mesmo assim obrigado pelas dicas.