Welcome to the new FlexRadio Community! Please review the new Community Rules and other important new Community information on the Message Board.
If you are having a problem, please check the Help Center for known solutions.
Need technical support from FlexRadio? It's as simple as Creating a HelpDesk ticket.

Metering class packet

W4WHLW4WHL Member
edited May 8 in SmartSDR API
I'm trying to decode the Metering packet, however i can't find any reference.  Since I do not use the API, do you have any documentation that explains how the payload is arranged?

What I'm looking for is what words in the payload represent SWR etc.

Thanks,

William
«1

Answers

  • Stu Phillips - K6TUStu Phillips - K6TU Member ✭✭
    edited May 8
    William,

    There is no documentation that describes what you want.  The meter data is sent with a VITA-49 header and is a stream extension packet.  The payload of the packet contains the meters with each meter sent as a 32 bit word - the top 16 bits is the meter number, the lower 16 bits is the value of the meter.

    Depending on the meter type, it has to be scaled in order to get the correct value.

    To determine which meter is which, you will need to do a "sub meter all" to get the status messages when meters are added or deleted from the radio.  Alternatively, since the TX meters are fixed, you can send a command "meter list" which will return the meter numbers, scale etc to you.

    Meter number 17 is the SWR value on my 6700 - I don't know if the meter numbers are the same across all models.
    #17.src=TX-#17.num=3#17.nam=SWR#17.low=1.0#17.hi=999.0#17.desc=RF SWR#17.unit=SWR#17.fps=20
    You can download the source code of the FlexLib from the FlexRadio web site at:

    http://www.flexradio.com/downloads/flexlib_api_v1-4-11-zip/

    The source code is the ultimate documentation source.

    Hope this helps.
    Stu K6TU
  • W4WHLW4WHL Member
    edited July 2016
    Stu,

    Thanks for the information, but what I need to know is the breakdown of the actual packet payload.  Since I do not use the API, I need to be able to **** the data I need directly out of the UDP packets. 

    I looking for a breakdown of the bytes in the payload, and what they are.  I can not find this anywhere in the API code.  But if anyone knows where the meter packets are parsed in the API, that would help

    Regards,

    William
  • Stu Phillips - K6TUStu Phillips - K6TU Member ✭✭
    edited August 2016
    Follow the link I inserted above and download the FlexLib source code.  The files you want are in the FlexLib directory with obvious names.

    Look for the file Meter.cs in that directory, then look at VitaPacket.cs in the Vita directory.

    Stu K6TU
  • Walt - KZ1FWalt - KZ1F Member
    edited November 2016
    Yep, you are correct, I explained it wrong to Enzo. This is from my code.

            int num_meters = payload_bytes / 4;

            ids = new short[num_meters];
            vals = new short[num_meters];

            for (int i = 0; i < num_meters; i++) {
                ids[i] = data.getShort(index);
                index += 2;
                vals[i] = data.getShort(index);
                index += 2;
            }


  • W4WHLW4WHL Member
    edited July 2016
    Thanks Walt that is helpful
  • W4WHLW4WHL Member
    edited July 2016
    Thanks Stu!  I found what I needed.

    William
  • IW7DMH, EnzoIW7DMH, Enzo Member ✭✭
    edited January 2017
    Please, can you "paste" here a sample metering packet so I can test my parser and be sure it works?
    I am having troubles with pkt_type, header.c and header.t fields. I can't get the expected value respectively 3, 0 and 0 typical of a metering packet.

    Thank you very much
    Enzo
  • W4WHLW4WHL Member
    edited January 2017
    Here is a packet

    38DF000A0000070000001C2D534C80020000000000000000000000000001CCB000078300000C00000000003400A100AF00B5009F00A1009C00A000A200A0009500A2009E00A200990098009A009C00AD00A800A2009A009C009200A500A200A30096009A00AB0098009D00AB00A6009B009C00A500AF00AC00BF00A600A400BE00A3009C009F00A1009E00A1009C009A009D00990092009B00A700A600A400A700A100A300A6009A00A000A5009400A000A5009F00A300A700A600AD00A100B700A800A6009C009200A0009D00A300B100930093009D00A500B5009B00940095009900A800BE00AC00A100A9009E009B0097009E00A900A600B900AF009900A700BC00BA00A7009B00A300A700A4009B00B000B300C600C200AE009C00AA00A3009E00A900A5009C009E00AD009C009F00A600B200AF00AD00AB00A2009A00A1009B00A200A9009D00A600A200A70098009B00A800AD00AF00B500B100A600A400A800A5009C009D00A900A100B600AB00A400930095009A009400950095009F00A300A500B700B600B100A6009D009E00B700AE00AD00A1009D00A5009F009B009B009B009C009B00A600B900BB00A40098008F009F0091009D00A7009D00A3009E009B009C009A009700A600A2009600A100A300A9009C009A00970094008E009A009C00A6009F009600AE00A2009C0091009A00A600A300A0009900990092009C00A1009800A200AD00B200A000960099009D00AB00A800A400AB00A6009900AA00AF009E00A000BA0094009800AB00A2009700AD00AD00C700AF00AB00AB00AD00AC00B200AA00B500B400A400A900A0009F00A200AE00970097009D00A100A900A200A200AE00B800BF00A4009A009E00AF00AE00A800AA00AB009C009E00AF00A70099009E00A6009E00A000AB00A600A000A700A800A1009C00A10096009E00A200A500A6009C00C100A900A400A000A600A30097008D0092009A009E00960096009800910099009D009800AB009F00A200AA0099009B00A700B000BE00A400A7009E009900A400AD00AB00A600B600A200B200AD00A7009D00A400B800C200C800AA00AE00A700A500B700AC00A0009B00A000BC00B900A800A500B600AA00B1009E0096009600910095009D009B00AE00B000B000B800A600A600B200A0009800A000A600B900AA00A200AF00AD00B000B000AF00A9009D00A3009E009800A400A700AC00AA00A900AA00A700B400B500A400A500B000AE00A900B000B600A3009F0099009A00AA00AF00B000AF00A100A900A200A200A600B100A800AE00B6009D0080008700A100A800A7009E00A500B200AB00A100A900BA00B7009B009A00AD00A3009D00A9009D00A900BD00B000A400AB00B100A400A200AE00A7009B0094009600A000B100A4009700A6009A00920091009F00AC00B100A50094009E00AE00A9009B009C009A009700A100A4009500A200B900C500A8009900A200AE00A900A9009900910095009B00AA00BC00BA00B100AD00A2009D00A900BE00A900B000AC00AD00A900A100B200AA00AB009F00AA00B300B600AE009F009F009F009900A4009D00970094009600A900A30098009500A400A900AA009E00A300AF00A500A000AA00B700B400AF00A800A300A300A500A600A400AA0098009F00AE00B6009D00A800AC00AE00A600A3009C009900A8008D009200A200A100AA00B700B000A900A100A1009E009A0094009A009F009E00A200A800990094009900A300AA009D009D00AE00BE00B900A900980093009400AD00A700A20096009D00A6009D009C00A700A7009A00910092009D00A1009D00A000AA0096009900A700A700A7009D00A9009E00A500A000A2009E00A200B400960098009A009B00A200AE00B4009D009A00B000B300AC009D009700A500A900AB00A500A1009900A300B000A600AD00A000A200A500A700AE00A100A600B300A200A200A3009900A7009F00A500A300A900AA009B00A1009D009900A400B800AC00A900A1009C009B00AD009E009E00A3009C00A500A500A0009E009A00A900B500A700AF00AA00B100A400AD00B700BC00A400AE00B400B700B600A900A1009C00A0009E00A100AF00B100B900B700A900A100A6009C00A700AC00AA00A900A4009B00A500AA00B000A600A8009A00A000A400A600AD00B200B100BB00AF00B000C000C300C400B900B900A40099009F00A2009500AF00AA00A200A3009A008A008C009E00A6009C009900A300A000A500AE00B500B100A2009A00A800A2009B00A4009F00A20099009600C700BA009C0094009C00AB00A700A700AE00AD00A8009E0098009A0099009D00A900AC00AB00A100A900A700A9009B00A00097009E00A7009B009C00A000A800A2009A00A900C300BC00B700BB00C300C300B900B100B100AF00B700A60094008F009900BC00AF00B000B500AA009B009E00AE00B400B000AC00AA00B900B700A400B500A9009800A300AD00A10098009B009B00A400A200A8009A00A400AA00A600AC0093009F009E009E00A3009D00A100B2009B00A200AA00B100A400A2008E00960096009B00A200A2009D00AB00B700B100AB00BC00B200B700C300B800A300A3009B00910098009700A000A700B500AC00B300AF00AB00A500A200A100A200B400B400AD00AA009F0091008C00A400A700AB00AC00A100A700A700A900A900A000AF00AE009A009A00A200A000A7009D00AB00AE00A700A200A000B000AB00AA00A800AE00C500C000A3009B00B000AD00A6009F00A000A200A5009C00A0008E009900A700AE00A300AB00AA009D009C00A300A700B500B600A6009C00A200A900B4009D009F00A300A70


  • IW7DMH, EnzoIW7DMH, Enzo Member ✭✭
    edited December 2016
    Thank you very much
  • Walt - KZ1FWalt - KZ1F Member
    edited November 2016
    Enzo, what are you using for a language?
  • IW7DMH, EnzoIW7DMH, Enzo Member ✭✭
    edited December 2016
    I am in the Arduino Due microcontroller enviroment. It uses Atmel SAM3X8E ARM Cortex-M3 CPU so I am using plain C for GUI and phisical devices like rotary encoders, pushbuttons and touch screen display. I also use C++ for support libraries. This is not my world as I am a SJCP and I don't like to deal with pointers and explicit memory allocation (and its related memory leaks).
    Anyway my challenge is going to end asa I'll complete the metering protocol. I would like to switch to another more powerful hw platform. I like UDOO as it has out of the box WIFI, GigaBit Ethernet port, Bluetooth and has a dedicated 15' capacitive touch screen. It includes also a native connection with a DUE board so I could reuse most of the code I have already written. UDOO can support different OS but I'll point to Android as it offers the best and innovative GUI.
    I hope in the mean time the someone :) can realease its libraries so I can go on without having to reinvent the wheel.
  • Walt - KZ1FWalt - KZ1F Member
    edited November 2016
    I have not conclusively decided whether to release the source of my library and/or the jar file representing my library. To be sure, it is not fully tested as yet, nor is it fully implemented. However, I am certainly willing to share snippets.

    I have made reference to work I did while at Monster.com processing the results of virtually every enter typed at any point in time with blindingly fast execution time. In that effort I became well versed with highly scalable nonblocking network IO. There is a package that does that but, at that time, was not mature enough for me to have used it. However, it is currently quite mature. I use that as the networking piece as I can simply add codex's and retrieve as a call back, a fully contained instance of the Vita-49 object having just arrived. In those, aforementioned, snippets, you'll see references, to getInt(index) and getFloat(index) and getByte(index). In viewing those method invocations you can see where the next item, int, byte, float, etc, is being processed.
    For both you and William, if it makes sense to use an object based approach, we can discuss it here or <my call> at arrl dot net. If, you'd rather blaze your own trail, but have questions, I will do my best to provide pointers.
  • W4WHLW4WHL Member
    edited January 2017
    Walt,

    I ran some test using your code snippet.  I dumped the payload from a meter packet into a byte buffer.



                            ByteBuffer tempbuff = ByteBuffer.wrap(tempdata);
                            index=0;
                            int num_meters = tempbuff.capacity() / 4;

                            short [] ids = new short[num_meters];
                            short [] vals = new short[num_meters];

                            for (int i = 0; i < num_meters; i++) {
                                ids[i] = tempbuff.getShort(index);
                                index+=2;
                                vals[i] = tempbuff.getShort(index);
                                index+=2;
                            }


    But I am getting non nonsensical data.  I assumed you were using bytebuffer hence the getShort(index).  But now not so sure.   There seems to be a repeating patern (underlined) in the data, but its making zero since to me.  Maybe I just don't understand what I'm looking at.  Any idea?


    ids [5080, 5336, 5584, 5840, 6125, 462, 708, 2179, 3072, 5080, 5336, 5584, 5840, 6125, 462, 708, 2179, 3072, 5080, 5336, 5584, 5840, 6125, 462, 708, 2179, 3072, 5080, 5336, etc ect ect

    value [-14592, -14592, -20736, -20736, 23040, 16896, 0, 0, 0, -14592, -14592, -20736, -20736, 23040, 16896, 0, 0, 0, -14592, -14592, -20736, -20736, 23040, 16896, 0, 0, 0, -14592, etc etc etc



    Regards,

    William








  • Walt - KZ1FWalt - KZ1F Member
    edited November 2016
    Hmmm, I never said metering was perfect. I was hopeful. So I am looking at a meter packet that just arrived. In it there are the two short arrays for id and value, here is what this packet has:

    id    value
    1      -12146
    2      -15360
    4      -32000
    5      -32000

    etc. Now, these are 16 bit signed fields. The way to convert them to unsigned shorts is to, effectively, cast them to ints by
    int foo = meterValue & 0x0000ffff or
    int foo = Short.toUnsignedInt(meterValue);

    this would render a +55670. I use option 2 Short.toUnsignedInt(). This is likely faster as it is evaluated to a native machine language instruction. I could be wrong as that is an implementation detail.

    Yes, and you were correct, these all come from ByteBuf.
  • IW7DMH, EnzoIW7DMH, Enzo Member ✭✭
    edited December 2016
    I don't know if I have understood William doubt, but I have also found a repeating pattern.
    Below are my notes about a test on my rig. It seems the packet has 48 meters, but they are 12 repeated 4 times.
    image
     
  • Walt - KZ1FWalt - KZ1F Member
    edited November 2016
    William and Enzo. While I answered a good question, it was entirely what you had asked William. The meter object gets constructed by two sources. The first is from the VitaMeterPacket, which defines the meter's values. The second, and the cause for your concern is the meterstatus message:
    status    String    ObjectVariable     ==
    3.src=TX-#3.num=8#3.nam=CODEC#3.low=-150.0#3.hi=20.0#3.desc=Signal strength of CODEC output#3.unit=dBFS#3.fps=10#


  • W4WHLW4WHL Member
    edited July 2016
    That was super helpful, and got me in the game!  Like for you !
  • Walt - KZ1FWalt - KZ1F Member
    edited November 2016
    Enzo, 48 sounds correct. Each meter is 4 bytes so 48 would be 12 meters.

    Sorry...above I meant wasn't entirely what you had asked.
    So in this case when the status arrives, it finds the partial meter object and fills in source, high low etc.
  • W4WHLW4WHL Member
    edited July 2016
    I see now that the data, comes in in chunks, not all meters are sent at the same time, they seem to alternate in a repeating pattern.  sometimes 1,2,4,5,7  other times 9,10, 13, 15, 17  and other times 19,20,21 etc ect.

    So what I did was just parse the incoming packets searching for the ID I want, then grab the next 16bits for the value.  This worked!

    Ok I now can pull live S-Meter data.  Now how do I convert this to a useful data?

    Im getting an integer of ~55468 that varies +- with singal strength.  So how do I convert this into dbm or s-units?

    Doing a sub meter all told me that id 21 was "signal strength in passband"

    I did something like this inside the for loop

    if ((ids[i] & 0x0000ffff) == 21){
         signalstrength = vals[i] & 0x0000ffff;
    }

    logging the output show the values corresponded to to the signal strength.

    So now how do I convert this value to something useful?

    William





  • edited May 8
    William, that makes my head hurt! And it's why I like C# and using the Flexlib API.
    The api spits out the value in dbm. I see the portability in doing it your way, but, I'm lazy and like Windows and MS Visual Studio for development.
    I envy your ability to get up to speed on Java development. If Flex radio ever needs another developer, you might just get a call!
    James
    WD5GWY
  • W4WHLW4WHL Member
    edited July 2016
    I'm anti the man, so I usually go against the grain.  This has its ups and downs LOL.  Anyway, my goal here is to someday make a career change.  I am a network security engineer for a large provider.  It pays well, but I'm burnt out.  My heart just isnt in it anymore. 

    But I 'm far from any sort of developer job.  But maybe in a few years I can think about a possible career change.

    William
  • edited May 2015
    Well, I hope you realize your dream. I wish I had followed mine years ago. Not that trucking is bad, but, if I could do it all over, I would have finished college and became a software developer. And if you can get into TEAM development, you should do well. James
  • Walt - KZ1FWalt - KZ1F Member
    edited November 2016
    William, HSB! I've spent a career in software development and, yes, it got to the point my heart just wasn't in it so I retired. I am over the **** on the portable library now so soon I will be testing the full bore facsimile to SSDR that is more feature rich and quite portable. I am guessing it be maybe another month (or a couple of days) to have it on Android. But, to your point I really would have enjoyed the security field. I was in the Security BU of CA Technologies working on Siteminder and Federation (less on SM and more on Fed), and that is another story.
  • W4WHLW4WHL Member
    edited July 2016
    My problem is, I'm 20y from retirement and my heart is not in it LOL.  I'm ex military, so I **** away my money having fun abroad.  Of course I got out after 9years as an E6.  Looking back I would be retired now drawing a pension. 

    Now 43, I'm no closer to retirement.  I have done the math, and I need to work 20 more years to retire with the money I want.  But I just can't see 20 more years with the stress level of doing security networking.

    Anyway,  Do you have any idea about my above question?

    Im getting an integer of ~55468 that varies +- with signal strength.  So how do I convert this into dbm or s-units?

    William

    
  • Walt - KZ1FWalt - KZ1F Member
    edited November 2016
    didn't someone say what comes out IS in dbm? I think that is a fair question and, short of temperature I am not sure I know the answer. The negative values are because it is showing in a signed short. I see you made them unsigned.  This other snippet should help but, as Stu has said there would be a conversion involved. So when you are receiving a meter status you should parse all the multi values, here is units:

                    case "unit": {
                        MeterUnits units = MeterUnits.None;
                        switch (value) {
                            case "dBm":
                                units = MeterUnits.Dbm;
                                break;
                            case "dBFS":
                                units = MeterUnits.Dbfs;
                                break;
                            case "Volts":
                                units = MeterUnits.Volts;
                                break;
                            case "amps":
                                units = MeterUnits.Amps;
                                break;
                            case "degC":
                                units = MeterUnits.Degrees;
                                break;
                            case "SWR":
                                units = MeterUnits.SWR;
                                break;
                        }

                        if (m.getUnits() != units) {
                            m.setUnits(units);
                        }
                    }
                    break;

    The 'for instance' that comes to mind is when 1.4 came out DDUtil said the radio was over 1,000 degrees. I believe it was Tim that said the new version of DDUtil fixed that and someone said the value had to be mulitplied by 64 or the old one was and now it no longer needed to be divided by 64...some such. I haven't looked at their doc but the answer may be there.
  • Stu Phillips - K6TUStu Phillips - K6TU Member ✭✭
    edited August 2016

    The meter values have to be scaled based on what their units of value are.

    Try this approach... (Sorry its Objective C) - you can find the same logic in the source of FlexLib.  

    William - until such time as there is a full document describing the API, the best solution is to read the FlexLib code.  Being able to pick up someone else's code and understand it is a great way to up your game when it comes to software development.

    Fortunately Eric writes really good code and its pretty straight forward.  Look at the file Meter.cs and you will see a very similar structure to the one below... there are only so many ways of skinning the cat!

    Stu K6TU
    - (void) updateMeter:(long)value {
        Float32 scaled_value = value;
        
        switch (self.units) {
            case voltUnits:
            case ampUnits:
                scaled_value /= 1024.0;
                break;
                
            case swrUnits:
            case dbmUnits:
            case dbfsUnits:
                scaled_value /= 128.0;
                break;
                
            case degreeUnits:
                scaled_value /= 64.0;
                break;
                
            default:
                break;
        }
        
        self.value = scaled_value;
    }
  • W4WHLW4WHL Member
    edited July 2016
    Where is this from?  I would need to see the method code used in the case/switch, such as MeterUnits.Dbm.  Where is this code from?

    Regards,

    William
  • W4WHLW4WHL Member
    edited July 2016
    Thanks Stu, you responded while I was writing my reply to James!


    William
  • Stu Phillips - K6TUStu Phillips - K6TU Member ✭✭
    edited August 2016
    The above snippet is code I wrote.

    You can find all the logic for parsing/decoding the meter values in the file Meter.cs that is in the FlexLib directory from the link I posted somewhere above.

    Go to the FlexRadio web site and download the source code of the FlexLib version that is written in C#.  Everything you need is in that code.

    Stu K6TU
  • Stu Phillips - K6TUStu Phillips - K6TU Member ✭✭
    edited August 2016
    Ah ha!  The case of the crossing responses! :-)

    Stu K6TU

Leave a Comment

Rich Text Editor. To edit a paragraph's style, hit tab to get to the paragraph menu. From there you will be able to pick one style. Nothing defaults to paragraph. An inline formatting menu will show up when you select text. Hit tab to get into that menu. Some elements, such as rich link embeds, images, loading indicators, and error messages may get inserted into the editor. You may navigate to these using the arrow keys inside of the editor and delete them with the delete or backspace key.