• Tag Archives Node-RED
  • Using Node-RED to read a HF propagation map

    A few things to note.
    1. This ‘trick’ should work for any sort of image that you need to compare color values.
    2. I did not come up with the core code, I just asked the question.

    HF propagation is tricky.
    Thankfully a bunch of smart guys are running the show at the space weather services arm of the Australian BOM.
    They produce cool maps that show you what frequency you need to use to be able to (hopefully) pick up distant stations.
    The map is updated every hour for the past hour. While the data is an hour old, I have found that for what I need, one hour resolution is more than accurate enough.

    Here is what a typical map looks like.

    This one, taken at 3am in the morning (PST) is super ‘simple’, but it clearly shows how you need a higher frequency to cover more ground.
    As simple as it is the burning question remains…. How to automatically select the frequency from the image and so command the receiver to switch to said frequency? And what is said frequency?

    Enter Node-RED.

    Using the image-tools node, you can read the color value for a given x,y value.
    So, we set up a flow to first read and get the values of each part of the scale.
    We then map those color values to the scale frequencies. So in effect you end up with a number that represents the value in MHz for any location on the map.
    Here is a screen shot of the flow and I have clicked the 6MHz inject node to see the values in the debug tab.

    So now that we have that raw color value for that part of the scale, any x,y location will yield its MHz value to us…..
    Here is the flow to read the scale.
    [{"id":"2cdd6244.f73a8e","type":"change","z":"fa1bd60e.5b6d3","name":"","rules":[{"t":"set","p":"pixel","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":1860,"wires":[["86c9c963.a16eb8"]]},{"id":"ceebb092.cb7d3","type":"inject","z":"fa1bd60e.5b6d3","name":"8mhz scale","topic":"","payload":"{\"x\":130,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1760,"wires":[["2cdd6244.f73a8e"]]},{"id":"10a35d70.4e06a3","type":"inject","z":"fa1bd60e.5b6d3","name":"2mhz scale","topic":"","payload":"{\"x\":55,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1640,"wires":[["2cdd6244.f73a8e"]]},{"id":"6b28b2b0.54f2ac","type":"inject","z":"fa1bd60e.5b6d3","name":"4mhz scale","topic":"","payload":"{\"x\":80,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1680,"wires":[["2cdd6244.f73a8e"]]},{"id":"3c247f0f.dcc16","type":"inject","z":"fa1bd60e.5b6d3","name":"6mhz scale","topic":"","payload":"{\"x\":105,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1720,"wires":[["2cdd6244.f73a8e"]]},{"id":"d182e0ef.f5ddf","type":"inject","z":"fa1bd60e.5b6d3","name":"10mhz scale","topic":"","payload":"{\"x\":155,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1800,"wires":[["2cdd6244.f73a8e"]]},{"id":"9926806f.ef6c9","type":"inject","z":"fa1bd60e.5b6d3","name":"12mhz scale","topic":"","payload":"{\"x\":180,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1840,"wires":[["2cdd6244.f73a8e"]]},{"id":"97a5a697.65b2b8","type":"inject","z":"fa1bd60e.5b6d3","name":"14mhz scale","topic":"","payload":"{\"x\":205,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1880,"wires":[["2cdd6244.f73a8e"]]},{"id":"5f692af2.01b914","type":"inject","z":"fa1bd60e.5b6d3","name":"16mhz scale","topic":"","payload":"{\"x\":230,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1920,"wires":[["2cdd6244.f73a8e"]]},{"id":"cb3382d2.55a9","type":"inject","z":"fa1bd60e.5b6d3","name":"18mhz scale","topic":"","payload":"{\"x\":260,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":1960,"wires":[["2cdd6244.f73a8e"]]},{"id":"191be3a3.5d41fc","type":"inject","z":"fa1bd60e.5b6d3","name":"20mhz scale","topic":"","payload":"{\"x\":280,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":2000,"wires":[["2cdd6244.f73a8e"]]},{"id":"fd826f9a.89454","type":"inject","z":"fa1bd60e.5b6d3","name":"22mhz scale","topic":"","payload":"{\"x\":305,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":2040,"wires":[["2cdd6244.f73a8e"]]},{"id":"c77c41f4.0a48d","type":"inject","z":"fa1bd60e.5b6d3","name":"24mhz scale","topic":"","payload":"{\"x\":330,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":2080,"wires":[["2cdd6244.f73a8e"]]},{"id":"d6762d1a.9717e","type":"inject","z":"fa1bd60e.5b6d3","name":"28mhz scale","topic":"","payload":"{\"x\":355,\"y\":70}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":2120,"wires":[["2cdd6244.f73a8e"]]},{"id":"86c9c963.a16eb8","type":"jimp-image","z":"fa1bd60e.5b6d3","name":"","data":"http://www.sws.bom.gov.au/Images/HF%20Systems/Global%20HF/HAP%20Charts/Phoenix.gif","dataType":"str","ret":"img","parameter1":"img.png","parameter1Type":"str","parameter2":"","parameter2Type":"msg","parameter3":"","parameter3Type":"msg","parameter4":"","parameter4Type":"msg","parameter5":"","parameter5Type":"msg","parameter6":"","parameter6Type":"msg","parameter7":"","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","parameterCount":0,"jimpFunction":"none","selectedJimpFunction":{"name":"none","fn":"none","description":"Just loads the image.","parameters":[]},"x":610,"y":1860,"wires":[["c9ed63fd.f47b5"]]},{"id":"c9ed63fd.f47b5","type":"function","z":"fa1bd60e.5b6d3","name":"get value","func":"msg.image = msg.payload;\nvar x=msg.pixel.x;\nvar y=msg.pixel.y;\nmsg.payload = msg.image.getPixelColor(x, y); // returns the colour of that pixel e.g. 0xFFFFFFFF\nreturn msg;\n","outputs":1,"noerr":0,"x":760,"y":1860,"wires":[["42a68931.79f2e8","53feaf7a.64449"]]},{"id":"42a68931.79f2e8","type":"change","z":"fa1bd60e.5b6d3","name":"color to freq","rules":[{"t":"change","p":"payload","pt":"msg","from":"4278190335","fromt":"num","to":"2MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"4294902015","fromt":"num","to":"4MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"2155872511","fromt":"num","to":"6MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"8388863","fromt":"num","to":"8MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"16711935","fromt":"num","to":"10MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"16777215","fromt":"num","to":"12MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"8421631","fromt":"num","to":"14MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"65535","fromt":"num","to":"16MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"33023","fromt":"num","to":"18MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"2147483903","fromt":"num","to":"20MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"2147516671","fromt":"num","to":"22MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"4278255615","fromt":"num","to":"24MHz","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"2155905279","fromt":"num","to":"28MHz","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":910,"y":1860,"wires":[["a36c7916.597038"]]},{"id":"a36c7916.597038","type":"debug","z":"fa1bd60e.5b6d3","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1080,"y":1860,"wires":[]},{"id":"53feaf7a.64449","type":"debug","z":"fa1bd60e.5b6d3","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":920,"y":1940,"wires":[]}]

    Next I simply looked up the lat/long for the other locations of interest to me (San Francisco and New York) and put those x,y values into another flow that reads them every hour.
    The flow reads the color value of that pixel and does a look up for its value and converts that value to its MHz value.

    Note how this flow looks identical to the one above so I am not going to include the code for it.

    So now on my dashboard I can display the map and for any selected location on the map the predicted frequency needed to hear a station at that location for any given past hour.

    I then use that frequency to map to the HF ACARS (HFDL) channel number and command the receiver in Phoenix to switch to it every hour.
    Its not perfect, but its way way way better than manually keeping on top of all that.



  • Tracking Inmarsat 4-F3 with Node-RED

    For a year now I have been ‘tracking’ Inmarsat 4-F3 for my C-Band ADSC aircraft receiving ground station.
    It has been very crude tracking, but tracking none the less.
    I used a linear actuator with a position feedback resistor. Its worth noting that the position feedback is really critical. Without it you just don’t know where the dish is pointed.

    The actuator is very compact and was around 100 dollars, so not too bad in the over all cost of the project. Its worth noting that you can buy a version without the feedback resistor for about 20 bucks less, don’t skimp. You must have the feedback for this application.
    It is supposed to be lightly weather proof but even so I have it wrapped in a plastic bag to protect it mostly from the nightly runs of the irrigation system.
    Another thing of note is that the actuator is rated for 12 to 24 volts.
    At that voltage, it is way too fast for what we need…. so I have a 6 volt DC power supply driving the unit.

    Now the tracking.
    As you may recall from my main post on the subject, I knew from reading bit and pieces that the satellite makes a slow figure 8 in the sky over a 24 hour period.
    Here is what that oscillation looks like on a graph.

    You can sort of visualize the up and down and slide to side motion of the satellite over 24 hours.
    When we look at a heat map of what its doing in the sky, it all becomes clear.

    The satellite is up there in space, just over the equator, wobbling about.
    To do the initial tracking of it, I got some code help from my son….
    What we decided to do was to break the 24 hours up into 3 hour time slices and move the dish to a preset resistor location every time slice.
    I have removed the GUI so don’t have a screen shot, but it was a very simple grid of boxes that had the user entered resistor location for each time slot.
    Over a period of 2-3 weeks of me watching the signal strength in SDR# I got a feel for where each time slot needed to be and so tuned the dish tracking.
    It worked pretty good with one major flaw…. The satellite has an oh so slightly longer oscillation period than 24 hours.
    This meant that over the space of a month, I would need to re-tune all my 3 hour time slots (again and again).
    This was just way too high of a maintenance task for me.

    Node-RED to the rescue.
    There a group of three satellite tracking nodes; https://flows.nodered.org/node/node-red-contrib-satellites
    You can do a lot of cool things with them, but in the end we only need the one node. Since Inmarsat is not in its drop down pre-select list, we need the TLE node.
    Using the example flow on github you can pull down the TLE for any given satellite.
    Now we have the latest orbit parameters for the satellite we can now track it very accurately.
    (This is in fact how I got the above screen shots of the orbit oscillation and heat map).

    Every hour we run the orbit check and output the satellite position in x,y and z. (Note, I don’t use y or z).
    As you can see from the graph and the heat map, the longitude and altitude drift are not really enough for me to worry about (Or are they? Since I have only just got this going, I am still collecting data on if I should add another actuator and track azimuth well as elevation).
    The output latitude data simply goes into a range node which remaps the -3 to +3 deg swing to the resistor value in the actuator.
    The output of that node goes into the micro-controller which has some very simple code of making sure the resistor matches the commanded resistor value by switching the up and down motor relays.
    So, in short, every hour we send a resistor value that equates to the satellite position to a motor controller that measures the actual resistor value and adjusts it to match whats coming in.
    Here is what it looks like in action.

    Pretty easy to see where I turned on the new system. 8am Friday morning.
    Here is a week long graph that better shows how my tracking was working over the Node-RED tracking.

    It has transformed the tracking accuracy and will take the burden off me having to watch it and re-tune it.
    I can now just let it run knowing it is going to be super accurate all the time.
    To say I am very happy with how well it came together is an understatement.
    Why then did I not do it this way a year ago? I simply did not know about the TLE Node.



  • Remote control of SDRuno with MQTT and Node-RED

    Getting back to looking at HF ACARS messages again and so with that comes the need to tune to the best HF frequency. (Best is still based on propagation and is a topic for another blog).
    My HF station is in Arizona, and San Francisco is the best ground station for it to hear. New York is a close second.
    SF mostly runs on two frequencies, 6559KHz and 13276KHz with 5508KHz thrown in from time to time. NY is sort of the same but different.
    So, the question (or goal) is to be able to switch between those frequencies on some sort of time schedule. (Sort of based on day and night – ie, follow the HF propagation).

    For the longest time I got fixated on getting SDRuno to do the memory channel switching for me. Spent waaaaay to long looking for plug-ins that would do the job.
    Thought about trying to set up squelch-less scanning to do the job.
    Spent some time looking to get the RSP2 working under SDR# since it seemed to have more plug-ins and options.
    Turns out this was the wrong way of looking at the problem…. All very well to get the program to do the automatic switching – which it can’t do – but what if I want some other frequency at some other time?
    Better to have web site (Node-RED dashboard) control right?
    I mean the decoded data (the ACARS message) is displayed there anyway, so putting a button there just makes sense.
    We spent hours trying to figure out how to make it work, and minutes getting it working once we turned the problem around.

    So, long intro long.
    The key is to remove control from SDRuno and put it in the hands of the website / user / Node-RED.
    Press a button on the dashboard in one location and have it change the VFO frequency in another. Here is how we do that do.

    SDRuno can use a serial protocol called CAT. The software emulates a small subset of those CAT commands for a Kenwood TS-480 transceiver.
    What we need to do is setup a serial connection to SDRuno to send those CAT commands as needed.
    Start with a virtual serial cable. I downloaded and used http://com0com.sourceforge.net/ Simple and free. Hard to beat.
    Set up something like com3 and com4 in that program.
    Go into SDRuno and set up com3 as the CAT serial port. I just accepted the default baud, it does not really matter as even 300 baud will be overkill for changing a few frequencies. It should connect straight away.
    Now, in Node-RED running on the same computer as SDRuno add a serial node that is configured to com4.
    To prove it works, put down 2 debug nodes if you like and use them to change the frequencies back and forth.
    In short, what ever CAT commands you pump into com4 via Node-RED will come out of com3 and thus into SDRuno and the VFO will change frequency.

    Now with that working, add an MQTT node configured to your broker and connect it to your serial node.
    So now, when ever a payload is published to that topic it will be sent to com4.
    On the instance of Node-RED that is running the dashboard then, you add a button that publishes its value to the broker on that topic.
    Done.
    You now have control of the SDRuno VFO A frequency from your web page.



  • Terry doing Node-RED

    Can’t believe that this has not been blogged about till now…..
    Last night, on my usual Tuesday night phone call with my Dad, I mentioned that Terry will be back at Opto for a winter internship. Dad asked what he will be doing, I said, just like his summer internship, he will be making videos, I already have three subjects picked out for him…. Dad said, what videos did he do in the summer?

    This is one of about 5.

    You can probably see the others listed in the sidebar if you go to YouTube to watch it, I won’t bother listing them out.
    Enough to say, they are on a very popular topic, Node-RED, so they are doing really well (10,000 views in 2 months!!!!!).
    He presents well, so we are delighted to have him back for a few short weeks over the winter, not only but also, he programs waaaaaay better than I do and it comes out in the video.