Experimental NCID client

A first cut of a experimental NCID client for node red.

This flow shows a log of the last few calls received. The latest call appears as a link to who-called-me.co.uk so that you can see if the call is a spammer. You can change to link to a service that suits your country.

You will need to have a NCID server running listening to calls on your phone line. See http://ncid.sourceforge.net/

I am using a raspberry pi zero and a usb modem to listen to incomming calls.

The TCP nodes in the flow need to be altered to point at the machine where your NCID server is running.

This is very experimental at the moment with almost no error checking. Hopefully things will improve overtime.

[{"id":"d087fa29.08fdc8","type":"tab","label":"NCID Client","disabled":false,"info":""},{"id":"42763b57.5ab144","type":"tcp in","z":"d087fa29.08fdc8","name":"","server":"client","host":"192.168.1.231","port":"3333","datamode":"stream","datatype":"utf8","newline":"\\n","topic":"","base64":false,"x":169.07299041748047,"y":134.71542167663574,"wires":[["c3be637e.fd658","8109a6f3.ee6178"]]},{"id":"ce83c355.e1f9e","type":"inject","z":"d087fa29.08fdc8","name":"Keep Awake","topic":"","payload":"\\n","payloadType":"str","repeat":"60","crontab":"","once":false,"onceDelay":0.1,"x":235.07647705078125,"y":435.9586067199707,"wires":[["e9329d64.aac1c"]]},{"id":"bb712277.8e702","type":"comment","z":"d087fa29.08fdc8","name":"Interface to NCID","info":"","x":141.06943130493164,"y":38.05909538269043,"wires":[]},{"id":"84df26b1.97ec88","type":"ui_text","z":"d087fa29.08fdc8","group":"9a6c950b.59f2e8","order":1,"width":0,"height":0,"name":"","label":"Who Called Me","format":"<a href=\"https://who-called.co.uk/Number/{{msg.NMBR}}\">{{msg.NMBR}}</a>","layout":"row-left","x":943.0764617919922,"y":141.46883392333984,"wires":[]},{"id":"52dc5756.dc0588","type":"ui_text","z":"d087fa29.08fdc8","group":"9a6c950b.59f2e8","order":2,"width":0,"height":0,"name":"Last Caller Details","label":"{{msg.DATE}} {{msg.TIME}}","format":"{{msg.NAME}} {{msg.NMBR}}","layout":"row-left","x":957.0695037841797,"y":200.47920989990234,"wires":[]},{"id":"4d8e1ccb.6d87a4","type":"ui_text_input","z":"d087fa29.08fdc8","name":"","label":"Alias","group":"9a6c950b.59f2e8","order":3,"width":"4","height":"1","passthru":false,"mode":"text","delay":"0","topic":"","x":379.0833511352539,"y":619.6116361618042,"wires":[["8869bdc5.f0ed2"]]},{"id":"8869bdc5.f0ed2","type":"function","z":"d087fa29.08fdc8","name":"Set Alias","func":"return {payload:'REQ: alias add \"' + flow.get(\"NMBR\") + '&&' + msg.payload + '\" \"NAMEDEP&&POTS\"\\n'};","outputs":1,"noerr":0,"x":587.0833282470703,"y":618.3128910064697,"wires":[["e9329d64.aac1c"]]},{"id":"50c71a77.920124","type":"ui_template","z":"d087fa29.08fdc8","group":"9a6c950b.59f2e8","name":"CID Log","order":6,"width":"6","height":"6","format":"<ul ng-style=\"{'white-space': 'nowrap'}\">\n    <li ng-repeat=\"x in msg.payload\">\n        <font color=\"red\" size=\"2\">{{x.NAME}}</font>\n        <font size=\"2\">{{x.NMBR}} {{x.DATE}} {{x.TIME}}</font>\n    </li>\n</ul>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":922.0173568725586,"y":81.23273372650146,"wires":[[]]},{"id":"c7e599f0.62baf8","type":"ui_button","z":"d087fa29.08fdc8","name":"","group":"9a6c950b.59f2e8","order":4,"width":"1","height":"1","passthru":false,"label":"","color":"black","bgcolor":"#E0E0E0","icon":"clear","payload":"","payloadType":"num","topic":"","x":165.0798568725586,"y":621.4584655761719,"wires":[["4d8e1ccb.6d87a4"]]},{"id":"c3be637e.fd658","type":"function","z":"d087fa29.08fdc8","name":"Parse Input","func":"// convert a call line to an object\nfunction toObject(str)\n{\n    var items = str.split(\"*\");\n    \n    var data = {};\n    data.Type = items[0].trim();\n    for(var i = 1; i < items.length; i += 2)\n        data[items[i]] = items[i+1];\n        \n        \n    // reformat the date and time fields\n    if(data.hasOwnProperty(\"DATE\"))\n        data.DATE = data.DATE.slice(2,4) + \"-\" + data.DATE.slice(0,2) + \"-\" + data.DATE.slice(4);\n    if(data.hasOwnProperty(\"TIME\"))\n        data.TIME = data.TIME.slice(0,2) + \":\" + data.TIME.slice(2);\n\n    return data;\n}\n\nfunction isOneOf(itms)\n{\n    for(var i = 0; i < itms.length; ++i)\n        if( msg.payload.startsWith(itms[i]) === true)\n            return true;\n    return false;\n}\n\nflow.set(\"SESSION\", msg._session);  // remember the session\n\n\n// detect and parse out any call log messages\nif( isOneOf([\"CID:\", \"CIDLOG:\", \"CIDINFO:\", \"CALLINFO:\", \"MSGLOG:\", \"MSG:\", \"END:\",\"HUP:\",\"LOG:\",\"INFO:\", \"OPT:\"]))\n    return [toObject(msg.payload), null, null];\n\n// detect response messages\nif( isOneOf([\"200\",\"210\",\"250\",\"251\",\"252\",\"253\",\"300\",\"400\",\"401\",\"402\",\"403\",\"410\",\"411\"]))\n    return [null,msg,null];\n\n\n// anything else\nreturn [null,null,msg];","outputs":3,"noerr":0,"x":226.06951904296875,"y":262.52779388427734,"wires":[["67d65472.4fce6c"],["5b4e40b2.28b7f"],["bad4830f.7dce1"]],"outputLabels":["call type","response","other"]},{"id":"bad4830f.7dce1","type":"debug","z":"d087fa29.08fdc8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":481.0800094604492,"y":352.60759353637695,"wires":[]},{"id":"5b4e40b2.28b7f","type":"function","z":"d087fa29.08fdc8","name":"Responses","func":"// Server API message\nif(msg.payload.startsWith(\"210 \") === true)\n{\n    return [{payload:\"HELLO: IDENT: client node-red\\n\"}, null];\n}\n\n//End of connection startup\nif(msg.payload.startsWith(\"300 \") === true)\n{\n    return [{payload:\"REQ: ACK\\n\"},null];\n}\n\n// end of call log\nif(msg.payload.startsWith(\"250 \") === true)\n{\n    return [null,null];\n}\n\n// server ident\nif(msg.payload.startsWith(\"200 \") === true)\n{\n    return [null,null];\n}\n\n\nreturn [null,msg];\n","outputs":2,"noerr":0,"x":540.0764541625977,"y":257.3020849227905,"wires":[["e9329d64.aac1c"],["f93aa23.c5ae26"]],"outputLabels":["output","other"]},{"id":"67d65472.4fce6c","type":"function","z":"d087fa29.08fdc8","name":"Handle Call records","func":"function addToCallLog(data)\n{\n    // initialise the array if it doesn't exist already\n    var cidlog = flow.get('cidlog') || [];\n\n    cidlog.unshift(msg); // insert at the start of the array\n\n    while (cidlog.length > 20) // remember the last n logs\n        cidlog.pop();   // remove from the end\n\n    // store the value back\n    flow.set('cidlog',cidlog);\n    return cidlog;\n}\n\n\nif( msg.Type === \"CIDLOG:\")\n{\n    return [{payload:addToCallLog(msg)}, msg, null];\n}\n\n\n// process the CID record\nif( msg.Type === \"CID:\")\n{\n    flow.set(\"NMBR\", msg.NMBR);\n    flow.set(\"NAME\", msg.NAME);\n\n    return [{payload:addToCallLog(msg)}, msg, null];\n}\n\nreturn [null,null,null];","outputs":3,"noerr":0,"x":581.0694274902344,"y":142.30212783813477,"wires":[["50c71a77.920124"],["84df26b1.97ec88","52dc5756.dc0588"],["e9329d64.aac1c"]],"outputLabels":["cidlog","cid","update"]},{"id":"a47543ea.ceddf","type":"ui_toast","z":"d087fa29.08fdc8","position":"top right","displayTime":"10","highlight":"","outputs":0,"ok":"OK","cancel":"","topic":"","name":"","x":998.0729675292969,"y":608.9966869354248,"wires":[]},{"id":"f93aa23.c5ae26","type":"debug","z":"d087fa29.08fdc8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":862.0173263549805,"y":297.01039600372314,"wires":[]},{"id":"fece3a9f.972948","type":"ui_button","z":"d087fa29.08fdc8","name":"","group":"9a6c950b.59f2e8","order":5,"width":"1","height":"1","passthru":false,"label":"Refresh","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":189.01731491088867,"y":539.0105400085449,"wires":[["41e00e3.01f5ff"]]},{"id":"8109a6f3.ee6178","type":"debug","z":"d087fa29.08fdc8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":430.08331298828125,"y":68.59721946716309,"wires":[]},{"id":"e9329d64.aac1c","type":"function","z":"d087fa29.08fdc8","name":"Add session","func":"msg._session = flow.get(\"SESSION\");\n\nreturn msg;","outputs":1,"noerr":0,"x":803.0833969116211,"y":485.9757843017578,"wires":[["a47543ea.ceddf","25e7b95f.f12626","315d7c16.21e4b4"]]},{"id":"25e7b95f.f12626","type":"debug","z":"d087fa29.08fdc8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1083.0833892822266,"y":538.2743301391602,"wires":[]},{"id":"315d7c16.21e4b4","type":"tcp out","z":"d087fa29.08fdc8","host":"","port":"","beserver":"reply","base64":false,"end":false,"name":"","x":1066.0694732666016,"y":444.0903091430664,"wires":[]},{"id":"41e00e3.01f5ff","type":"function","z":"d087fa29.08fdc8","name":"Reread call log","func":"// clear the call log\nflow.set('cidlog',[]);\n\nmsg.payload = \"REQ: REREAD\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":462.07643127441406,"y":536.9722671508789,"wires":[["e9329d64.aac1c"]]},{"id":"9a6c950b.59f2e8","type":"ui_group","z":"","name":"Caller ID","tab":"2f831b66.758144","order":4,"disp":true,"width":"6","collapse":false},{"id":"2f831b66.758144","type":"ui_tab","z":"","name":"Home","icon":"dashboard","order":1}]

Flow Info

Created 6 years, 8 months ago
Rating: not yet rated

Owner

Actions

Rate:

Node Types

Core
  • comment (x1)
  • debug (x4)
  • function (x6)
  • inject (x1)
  • tcp in (x1)
  • tcp out (x1)
Other
  • tab (x1)
  • ui_button (x2)
  • ui_group (x1)
  • ui_tab (x1)
  • ui_template (x1)
  • ui_text (x2)
  • ui_text_input (x1)
  • ui_toast (x1)

Tags

  • Dashboard
  • ncid
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option