Ok... Working from memory:
1)Get node Red up and Running
2)Make sure these are installed: Dashboard Nodes(Obviously), contrib multistate switch(if you want the pcr1000 front end), node red node serial(If you want to hook it to your PCR1000)... (Those are the highlights, there might be another node or 2 that you have to palette manager install, but these were the main ones)
3)Create a static
directory under .node-red
to put your external but still cody type things that Node red needs for the knobs, dials and switches (I used .node-red/node-red-static
)
4)Edit your settings.js
in your .node-red
folder to reflect where the static folder is:
under the section:
/** When httpAdminRoot is used to move the UI to a different root path, the
* following property can be used to identify a directory of static content
* that should be served at http://localhost:1880/.
*/
//httpStatic: '/home/nol/node-red-static/',
httpStatic: '/home/username/.node-red/node-red-static/',
Obviously substituting username
for your user name as used when you log in...
- I then created a further 2 subdirectories in the
node-red-static
One is:.node-red/node-red-static/js
, the other is .node-red/node-red-static/png
... (no prizes for what they will contain eventually )
Edit: I suggest you use the same, as the templates for the knobs etc point at these folders specifically, if you use a different name, be prepared to edit them on your own!!
- Put the (mentioned above):
into the js
directory that you created...
-
rename it to input-knob.js
(You would probably have to restart Node Red at this point.)
-
Take this png:
Edit: (Right Click and save link as: TunerKnob1.png
)
and put it in your png
directory you created... (The png file looks weird onscreen, it is a 101 consecutive frame "filmstrip" of the tuning knob..)
- import the following nodes into a flow:
[
{
"id": "c701eed40e40f478",
"type": "ui_template",
"z": "68e5c71acc43e814",
"g": "d017b78c09ecbdbe",
"group": "62350f50d4b09ff8",
"name": "Knob_Tuner",
"order": 21,
"width": 1,
"height": 3,
"format": "<div ng-init=\"init()\" class=\"knobwrapper\">\n<input type=\"range\" \nid=\"{{'knob_'+$id}}\" \nng-model=\"knobvalue\" \nclass=\"input-knob\" \ndata-width = \"48\"\ndata-height = \"144\"\nmin=\"-10\" \nmax=\"10\" \nstep=\".1\" \ndata-src = \"/png/TunerKnob1.png\" \ndata-sprites = \"100\"\nng-mousedown=\"send({payload: true})\"\nng-mouseup=\"send({payload: false})\"\n/>\n</div>\n<script>\n(function(scope) {\n \n \n scope.inited = false \n scope.init = function(){\n if($(\"#knob_\"+scope.$id).length){\n actuallyInit() \n }\n else{\n setTimeout(function(){\n actuallyInit()\n },100)\n }\n }\n \n function actuallyInit(){ \n console.log(scope.$id,'actuallyInit()')\n $(\"#knob_\"+scope.$id).closest(\"md-card\").css('padding','unset')\n if(scope.initialvalue){ \n scope.knobvalue = scope.initialvalue \n }\n scope.inited = true\n }\nscope.$watch('msg', function(msg) {\n if (msg) { \n scope.incoming = true\n scope.knobvalue = msg.payload\n if(!scope.initialvalue){\n scope.initialvalue = msg.payload\n } \n }\n });\nscope.$watch('knobvalue', function(knobvalue) {\n if(!scope.inited){\n return\n }\n if(scope.incoming){\n scope.incoming = false\n return\n }\n if (knobvalue) {\n scope.send({payload:knobvalue}) \n }\n })\n \n \n})(scope);\n\n</script>",
"storeOutMessages": true,
"fwdInMessages": false,
"resendOnRefresh": true,
"templateScope": "local",
"className": "",
"x": 270,
"y": 1420,
"wires": [
[
"66e589fd4f7bfc62",
"0d95d7444a3048bc"
]
]
},
{
"id": "0d95d7444a3048bc",
"type": "debug",
"z": "68e5c71acc43e814",
"g": "d017b78c09ecbdbe",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 675,
"y": 1420,
"wires": [],
"l": false
},
{
"id": "62350f50d4b09ff8",
"type": "ui_group",
"name": "PCR1000",
"tab": "554e77d51ad13f2d",
"order": 1,
"disp": false,
"width": 25,
"collapse": false,
"className": ""
},
{
"id": "554e77d51ad13f2d",
"type": "ui_tab",
"name": "PCR1000",
"icon": "dashboard",
"disabled": false,
"hidden": false
}
]
Edit: Also add this css script to your flow (it is assigned to "site status" so it applies to your entire site, it wont display on the dashboard, but will point things in the right direction when an additional template is added for another knob... You only need one instance of this css script to use as many instances of the knob template that you place/copy/paste...
[
{
"id": "c57d58e3a3d7d9ef",
"type": "ui_template",
"z": "68e5c71acc43e814",
"g": "1501e67dfda50a42",
"group": "62350f50d4b09ff8",
"name": "Class=\"input-knob\" Style=\"knobwrapper\"",
"order": 2,
"width": 25,
"height": 1,
"format": "<script src=\"/js/input-knob.js\"></script>\n<style>.knobwrapper{\n width:100%;\n height:100%;\n display:flex;\n justify-content: center;\n align-items: center;\n }</style> ",
"storeOutMessages": true,
"fwdInMessages": true,
"resendOnRefresh": true,
"templateScope": "global",
"className": "",
"x": 300,
"y": 70,
"wires": [
[]
]
},
{
"id": "62350f50d4b09ff8",
"type": "ui_group",
"name": "Radio",
"tab": "554e77d51ad13f2d",
"order": 1,
"disp": false,
"width": "25",
"collapse": false,
"className": ""
},
{
"id": "554e77d51ad13f2d",
"type": "ui_tab",
"name": "PCR1000",
"icon": "dashboard",
"order": 1,
"disabled": false,
"hidden": false
}
]
10)You should have a vertical twiddly knob fader thing on your dash that spits out numbers when you move it... (It can be dragged up/down/left/right or use the mouse scroll wheel... if you click on it, it sends you a true, when you release the mouse button over it, it sends a false)... If you send it a number from -10 to 10, it repositions the knob onscreen...
11)Once you have this working, I will then send you my infantile effort at grabbing this data from the knob and boosting it into the tuner...
Knob samples and software to create the "png film strips" is available from:
https://www.g200kg.com/en/webknobman/gallery.php
Edit2: The number of frames you create in the filmstrip must be 1 more than what is defined in the knob's palette... (I suspect the knob designer counts from 0, Node-Red from 1...Or vice-versa)
Edit3: I have all of the knobs in both png and .knob format(for modding and re-exporting) for this little project and am willing to share..
Edit4: I have found the Java version of Knobman (from g200kg) works well and while not easy, is quite straightforward once you get the hang of it...
Edit5: Just realised - For this little project, I store all my flow context to disk instead of volatile ram (Allows things to remain set next time you fly it up) - To do so, I edited settings.js
and set the following section:
/** Context Storage
* The following property can be used to enable context storage. The configuration
* provided here will enable file-based context that flushes to disk every 30 seconds.
* Refer to the documentation for further options: https://nodered.org/docs/api/context/
*/
contextStorage: {
default: {
module:"localfilesystem"
},
},
Edit: Once you have edited this settings file, don't forget to restart Node-Red...
I hope I haven't forgotten anything... Hope this helps! (If I have forgotten something, don't be shy to mention it, I will edit this post and add it!)
Regds
Ed