2

I'm attempting to create a Lua program to monitor periodic status pings of a slave device. The slave device sends its status in 16-bit hexadecimal words, which I need to convert to a binary string since each bit pertains to a property of the device. I can receive the input string, and I have a table containing 16 keys for each parameter. But I am having a difficult time understanding how to convert the hexadecimal word into a string of 16-bits so I can monitor it.

Here is a basic function of what I'm starting to work on.

function slave_Status(IP,Port,Name)
    status = path:read(IP,Port)
    sTable = {}
    if status then
        sTable.ready=bit32.rshift(status:byte(1), 0)
        sTable.paused=bit32.rshift(status:byte(1), 1)
        sTable.emergency=bit32.rshift(status:byte(1), 2)
        sTable.started=bit32.rshift(status:byte(1), 3)
        sTable.busy=bit32.rshift(status:byte(1), 4)
        sTable.reserved1=bit32.rshift(status:byte(1), 5)
        sTable.reserved2=bit32.rshift(status:byte(1), 6)
        sTable.reserved3=bit32.rshift(status:byte(1), 7)
        sTable.reserved4=bit32.rshift(status:byte(2), 0)
        sTable.delay1=bit32.rshift(status:byte(2), 1)
        sTable.delay2=bit32.rshift(status:byte(2), 2)
        sTable.armoff=bit32.rshift(status:byte(2), 3)
        sTable.shieldoff=bit32.rshift(status:byte(2), 4)
        sTable.diskerror=bit32.rshift(status:byte(2), 5)
        sTable.conoff=bit32.rshift(status:byte(2), 6)
        sTable.envoff=bit32.rshift(status:byte(2), 7)
    end
end

I hope this approach is understandable? I'd like to receive the Hex strings, for example 0x18C2 and turn that to 0001 1000 1100 0010, shifting the right-most bit to the right and placing that into the proper key. Then later in the function I would monitor if that bit had changed for the better or worse.

If I run a similar function in Terminator in Linux, and print out the pairs I get the following return:

49
24
12
6
3
1
0
0
56
28
14
7
3
1
0
0

This is where I am not understanding how to take each value and set it to bits

I'm pretty new to this so I do not doubt that there is an easier way to do this. If I need to explain further I will try.

2 Answers 2

3

tonumber(s, 16) will convert hex representation to decimal and string.char will return a symbol/byte representation of a number. Check this recent SO answer for an example of how they can be used; the solution in the answer may work for you.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your suggestion. I looked over the linked and understand why you provided it. But I like hjpotter's approach a bit more. Sorry but thank you for your input!
2

I'd approach this in a different fashion than the one suggested by Paul.

First, create a table storing the properties of devices:

local tProperty = {
    "ready",
    "paused",
    "emergency",
    "started",
    "busy",
    "reserved1",
    "reserved2",
    "reserved3",
    "reserved4",
    "delay1",
    "delay2",
    "armoff",
    "shieldoff",
    "diskerror",
    "conoff",
    "envoff",
}

Then, since your device sends the data as 0xYYYY, you can call tonumber directly (if not a string). Use a function to store each bit in a table:

function BitConvert( sInput )
    local tReturn, iNum = {}, tonumber( sInput ) -- optionally pass 16 as second argument to tonumber
    while iNum > 0 do
        table.insert( tReturn, 1, iNum % 2 )
        iNum = math.floor( iNum / 2 )
    end
    for i = #tProperty - #tReturn, 1, -1 do
        table.insert( tReturn, 1, 0 )
    end
    return tReturn
end

And then, map both the tables together:

function Map( tKeys, tValues )
    local tReturn = {}
    for i = 1, #tKeys do
        tReturn[ tKeys[i] ] = tValues[i]
    end
    return tReturn
end

In the end, you would have:

function slave_Status( IP, Port, Name )
    local status = path:read( IP, Port )
    local sTable = Map( tProperty, BitConvert(status) )
end

3 Comments

I separated your code and ran it in Terminator to better understand the method behind your madness. I ran only the BitConvert(sInput) and printed the key,value terms of tReturn{}. It does break it into binary which is great. But when it distributes the binary terms it seems to be in reverse. I like your approach because it explicitly shows me how you would approach this conversion methodically. But I need to switch the order it seems. I will see about flipping the order. Otherwise, I love your approach hjpotter92! Thank you.
@Pwrcdr87 If the order is reversed; change all table.insert( tReturn, 1, val ) to table.insert( tReturn, val )
changed table.insert(tReturn, 1, iNum%2) to table.insert(tReturn,iNum%2) and table.insert( tReturn, 1, 0 ) to table.insert( tReturn, 0 ). The order is flipped as you stated! I know I am new but I should have noticed that each entry was being placed into the first position of each list! Thank you very much hjpotter! Great answer!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.