Extrair Notificações do Nubank

Fala pessoal, sou novo aqui e tô precisando de uma ajuda.

Vamos lá, meu projeto consiste na seguinte ideia; Toda vez que eu receber uma notificação de compra no meu celular pelo app da Nubank, o Home Assistant detecta via last_notification e com isso, gostaria que ele guardasse esse valor em um sensor. Com isso conseguir fazer medições mensais de gastos e também criar alertas de compras suspeitas.

Estava tentando resolver isso com uma automação, mas não consegui, achei melhor tentar criar o sensor abaixo:

# sensor.yaml    

- platform: template
      sensors:
        compras_cartão:
          friendly_name: "Compras Cartão"
          unit_of_measurement: "R$"
          value_template: >-
            {{ 'compra de R$' in states('sensor.pocophone_f1_last_notification') }} #Extrair valor
          attribute_templates:
            Vendedor: >        
              {{ 'compra de R$' in states('sensor.pocophone_f1_last_notification') }} #Extrair vendedor

(Acredito que eu precise pegar esse valor e filtrar para conseguir extrair apenas os dados, e talvez converter o número para float e atribuir ao sensor)

Porém, não sei como fazer o sensor pegar o valor após o “R$” e após o “em” guardar em varivável, e também tentar pegar o valor do nome do estabelecimento:

Notificação comum: Compra de R$ 8,99 APROVADA em Google playstore.

Resultado esperado: 8,99
Resultado esperado em vendedor: Google playstore

Agredeço desde já o apoio!

2 curtidas

Achei esse código que acho que você pode adaptar para seu uso

last_expense:
friendly_name: Last expense
unit_of_measurement: RON
value_template: >
    {{ state_attr('sensor.curve_email','subject') | regex_findall_index("\d+\.?\d+? RON") | replace(" RON","") | round(2) }}
attribute_templates:
  seller: >        
      {{ state_attr('sensor.curve_email','subject')[27:1000] | regex_findall_index(".* on") | replace(" on","")}}

Vc conhece o aplicativo Tasker?
Apesar de nunca ter usado essa função, eu sei que é possível fazer uma tabela Excel no Google com ele.

Então você poderia usar o tasker para extrair os valores e estabelecimento e enviar para a tabela no Google o valor estabelecimento, data e hora.

1 curtida

Esse código até ajuda, mas eu só não sei como fazer isso utilizando a notificação ao invés de outro sensor de msg por email, até tentei usar o mesmo esquema de email, mas o nubank não envia por email as compras, só outras notificações de aviso de fatura fechada.

Em relação ao Tasker, eu já usei bastante, mas queria tentar concetrar tudo no Home Assistant para não ter tanto local para modificar, acho que o meu problema é só na programação desse filtro que preciso fazer com o template, mas ainda tô tentando achar um projeto que use essas notificações como gatilho e trate elas.

Fiz uma simulação pelo nodered, e cheguei a esse resultado. Veja se te ajuda.

3 curtidas
[{"id":"da2a7d4feeab4bfc","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"d4fdce8cd64c620b","type":"server-state-changed","z":"da2a7d4feeab4bfc","name":"Last notification","server":"db1ab0af.caa65","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.s21_kelvin_last_notification","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":230,"y":220,"wires":[["fc02ff44cf8fc7fd"]]},{"id":"fc02ff44cf8fc7fd","type":"switch","z":"da2a7d4feeab4bfc","name":"Notificação da Nubank","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"Compra de","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":440,"y":220,"wires":[["35c151550e21a1b4"]]},{"id":"35c151550e21a1b4","type":"function","z":"da2a7d4feeab4bfc","name":"Separa valor e vendedor","func":"var preco = msg.payload.replace(/[^0-9.,]/g, '');\nmsg.payload_preco = \"R$ \" + preco;\n\nvar vendedor = msg.payload.substr(msg.payload.indexOf(\"em\") - msg.payload.length + 3);\nmsg.payload_vendedor = vendedor;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":670,"y":220,"wires":[["36db0a9b2ba2bd59","7f4afa89aabb3197","b8ef7b2b92fd4d77"]]},{"id":"36db0a9b2ba2bd59","type":"debug","z":"da2a7d4feeab4bfc","name":"debug 26","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":880,"y":220,"wires":[]},{"id":"aaf3b9d1f3594bbe","type":"inject","z":"da2a7d4feeab4bfc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Compra de R$ 8,99 APROVADA em Magazine Luiza","payloadType":"str","x":210,"y":280,"wires":[["fc02ff44cf8fc7fd"]]},{"id":"7f4afa89aabb3197","type":"ha-sensor","z":"da2a7d4feeab4bfc","name":"Valor","entityConfig":"ca034a0303d40563","version":0,"state":"payload_preco","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":870,"y":160,"wires":[[]]},{"id":"b8ef7b2b92fd4d77","type":"ha-sensor","z":"da2a7d4feeab4bfc","name":"Vendedor","entityConfig":"a0c47e2678336e78","version":0,"state":"payload_vendedor","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":880,"y":280,"wires":[[]]},{"id":"db1ab0af.caa65","type":"server","name":"Home Assistant","version":5,"addon":true,"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":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"ca034a0303d40563","type":"ha-entity-config","server":"db1ab0af.caa65","deviceConfig":"","name":"","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"nubank_valor"},{"property":"icon","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":false},{"id":"a0c47e2678336e78","type":"ha-entity-config","server":"db1ab0af.caa65","deviceConfig":"","name":"","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"nubank_vendedor"},{"property":"icon","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":false}]
2 curtidas

Só simulei, não testei com o last_notification mas se for o padrão que você comentou acredito que vai dar certo

image

Aqui vai servir para filtrar se tiver alguma notificação que contenha “Compra de” deduzimos que é da Nubank

Direto pelo homeassistasnt nunca fiz, utilizo somente o nodered para minhas automações, espero que de alguma forma te ajude.

1 curtida

Tem que brincar um pouco com template em Developer Tools.

Não sei se vai resolver seu problema, talvez vc tenha que adicionar mais alguns filtros

{{ state_attr('sensor.sm_g985f_last_notification', 'android.text') 
| regex_findall_index('(\d+\,\d+)') }}

{{ state_attr('sensor.sm_g985f_last_notification', 'android.text') 
| regex_findall_index('(?<=APROVADA em ).*')|replace(".", "") }}


Obrigado pela ajuda, não cheguei a testar pois deu certo a que Walber enviou, eu não costumo utilizar o node red, mas com certeza pode ajudar em outra dúvida nesse tipo :grin:

1 curtida

Deu certo, acho que só precisa de um replace para remover o ponto do valor, pois o padrão do Nubank é “R$ 1.460,53” peguei o mesmo replace abaixo e coloquei em cima para testar!

Agora, só vou descobrir as configurações desse sensor para ele se manter como um sensor de gasto crescente, pois do jeito que está, ele detecta a compra e logo depois fica indisponível.

image
Sensor fica indisponível mas mostra o histórico no LogBook

image
Fiz uma compra de 1.642,62 mas só detectou o 642,62 antes da modificação do replace, e depois fiz uma compra de 7,92

{{ state_attr('sensor.sm_g985f_last_notification', 'android.text') 
|replace(".", "")
| regex_findall_index('(\d+\,\d+)') }}

Talvez vc tenha que conseguir filtrar o sensor pelo aplicativo Nubank, se o HA pegar qualquer notificação de outro aplicativo contendo valor vc vai ter erro nos valores.

Acho que vc vai ter que usar o utility meter

Boa pessoal, gostei da ideia e há um tempo atrás queria fazer algo do tipo.
Me permitem fazer um vídeo com isso?
Acho que pode ajudar muita gente também.

Fiz os testes aqui e aparentemente funcionando, fiz via NR também, ajustei algumas coisas baseado no do @kelvinrafaeli , transformei para número e montei o sensor, comprei algo baratinho na GPlay só para testar.


1 curtida

@Choske claro! Pode fazer

Vcs conseguiram pegar a notificação em IOS?
Parece que não tem a opção igual a do Android
@kelvinrafaeli

@kelvinrafaeli, @Tecker @Walber
pensando aqui com meus parafusos, acredito que precise fazer outra validação, as compras REPROVADAS tbm entrariam nesse fluxo né?
Precisa por essa lógica tbm!

inclui o status da compra no sensor tbm, só filtrar depois.

[{"id":"d4fdce8cd64c620b","type":"server-state-changed","z":"f727fdcc.c16a4","name":"Last notification","server":"d854bbe5.321208","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.redminote10pro_last_notification","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":140,"y":2380,"wires":[["fc02ff44cf8fc7fd"]]},{"id":"fc02ff44cf8fc7fd","type":"switch","z":"f727fdcc.c16a4","name":"Notificação da Nubank","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"Compra de","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":370,"y":2380,"wires":[["35c151550e21a1b4"]]},{"id":"35c151550e21a1b4","type":"function","z":"f727fdcc.c16a4","name":"Separa valor e vendedor","func":"msg.status = msg.payload.split(' ')[4]\n\n\nvar preco = msg.payload.replace(/[^0-9.,]/g, '');\nmsg.payload_preco = \"R$ \" + preco;\nmsg.payload_preco_numero = parseFloat(preco.replace(',','.'))\n\nvar vendedor = msg.payload.substr(msg.payload.indexOf(\"em\") - msg.payload.length + 3);\nmsg.payload_vendedor = vendedor;\n\n// msg.entity_id = 'sensor.gastos_nubank'\n\n// msg.payload = {\n//     data: {\n//         state: msg.payload_preco_numero,\n//         attributes: {\n//             local: msg.payload_vendedor,\n//             status: msg.status,\n//             unit_of_measurement: 'R$',\n//             icon: 'local/imgs/logo_nubank.svg',\n//             friendly_name: 'Última Compra - NuBank',\n//         }\n//     }\n// };\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":600,"y":2380,"wires":[["46c1a3acbdcf528e"]]},{"id":"36db0a9b2ba2bd59","type":"debug","z":"f727fdcc.c16a4","name":"debug 26","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":980,"y":2380,"wires":[]},{"id":"aaf3b9d1f3594bbe","type":"inject","z":"f727fdcc.c16a4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Compra de R$ 89,99 REPROVADA em Kabum","payloadType":"str","x":150,"y":2460,"wires":[["fc02ff44cf8fc7fd"]]},{"id":"679d3dfb4259d5d0","type":"comment","z":"f727fdcc.c16a4","name":"Notificação Nubank","info":"","x":170,"y":2320,"wires":[]},{"id":"46c1a3acbdcf528e","type":"ha-sensor","z":"f727fdcc.c16a4","name":"","entityConfig":"fdbe335b747f1cbe","version":0,"state":"payload_preco_numero","stateType":"msg","attributes":[{"property":"vendedor","value":"payload_vendedor","valueType":"msg"},{"property":"status","value":"status","valueType":"msg"}],"inputOverride":"allow","outputProperties":[],"x":810,"y":2380,"wires":[["36db0a9b2ba2bd59"]]},{"id":"d854bbe5.321208","type":"server","name":"Home Assistant","version":4,"addon":true,"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":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m"},{"id":"fdbe335b747f1cbe","type":"ha-entity-config","server":"d854bbe5.321208","deviceConfig":"","name":"gastos_nubank","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Última Compra - NuBank"},{"property":"icon","value":"local/imgs/logo_nubank.svg"},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"R$"},{"property":"state_class","value":""}],"resend":false}]
regex_findall_index('(\d+\,\d+ APROVADA)')

Talvez assim funcione, tô longe do PC agora

Da não…
Tem que arrumar um jeito de filtrar pela palavra aprovada para depois fazer o replace e regex

EDIT 2

{% if 'APROVADA' in state_attr('sensor.sm_g985f_last_notification', 'android.text') %}
{{(state_attr('sensor.sm_g985f_last_notification', 'android.text') 
|replace(".", "")
|regex_findall_index('(\d+\,\d+)'))}}
{% endif %}

Usando o switch é fácil

image

Se tiver a palavra aprovado faz uma coisa se tiver a palavra reprovado faz outra.

boa, esquecemos que o switch tem a opção “contains”, brabíssimo!!

1 curtida

Fiz ambos os métodos aqui, deixei para a pessoa escolher qual se adaptar melhor.

e o card ficou bonitin -

image

Mais detalhes no vídeo logo \õ
valeu galera vcs são fera!

1 curtida