How to covert int to hex type value and save it in a string?
It is like that Routeros doest have the script function (but have toarray,tobool,totime etc.).
Doesnt truely RouterOS have the script function coverting int to hex ??
I need it in a layer7filter-script.
Thanks!
I don’t recall where I found this, but it should help…
# $dec has decimal value to convert
:local dec 3735928559
# $hexdigit set this to number of hex digits (max) you want
:local hexdigit 8
# $hex is string containing hex value
:local hex ""
:for i from=0 to=(4*($hexdigit-1)) step=4 do={
:set hex ([:pick "0123456789ABCDEF" (($dec>>$i)&0xf) ((($dec>>$i)&0xf)+1)].$hex)
}
:log info ("0x".$hex)
Is there a convenient way to convert in the opposite direction. From ASCII 2byte number to signed integer?
for example 0xFF85 to -123
Or at least some documentation regarding num and tonum functions beyond their wiki
found it fem minutes after posting question here (HexToNum and many others)
https://github.com/eworm-de/routeros-scripts/blob/main/global-functions
![]()
Glad you like it. ![]()
Some reasoning on this…
this function already exist on RouterOS, but I don’t want to belittle anyone’s work, it was just to let find out.
using this example, the second line is for simulating one string readed from other variables.
:put 0xFF85
:put [:tonum "0xFF85"]
The eworm function works, obviously :))
and this is a very great idea for solve mixed, upper or lowercase:
:local Hex “0123456789abcdef_eworm.de_ABCDEF”
[:find $Hex … ] % 16
:global HexToNum do={
:local Input [:tostr $1]
:local Hex "0123456789abcdef_eworm.de_ABCDEF"
:local Multi 1; :local Return 0
:for I from=([:len $Input] - 1) to=0 do={
:set Return ($Return + (([:find $Hex [:pick $Input $I]] % 16) * $Multi))
:set Multi ($Multi * 16)
}
:return $Return
}
:put [$HexToNum "0xFF85"]
whe have the same results:
65413
But is not what is wanted:
-123
2 Byte signed go to
-32.768 to 0 to 32767 (65536 possible values)
written on hex
(0x8000 + 0x0 = 8000) to (0x8000 + 0x7FFF = 0xFFFF) to 0x0 to 0x7FFF, simply most significative bit set = negative value
for obtain rapidly the wanted value, if decimal value from hex is > 32767, subtract 65536 to it, instead use directly the results.
65413 > 32767 ? Yes then 65413 - 65536 = -123
Using directly RouterOS (without create a function or add some sanity ckeck from the provided value):
:global lazyvar "FF85"
:set lazyvar [:tonum ("0x".$lazyvar)]
:if ($lazyvar > 32767) do={:set lazyvar ($lazyvar - 65536)}
:put $lazyvar
:set lazyvar
Using Earthworm Jim*** function (without add some sanity ckeck from the provided value):
:global SingleWordHexToNum do={
:local Input [:tostr $1]
:local Hex "0123456789abcdef_eworm.de_ABCDEF"
:local Multi 1; :local Return 0
:for I from=([:len $Input] - 1) to=0 do={
:set Return ($Return + (([:find $Hex [:pick $Input $I]] % 16) * $Multi))
:set Multi ($Multi * 16)
}
:if ($Return > 32767) do={ :return ($Return - 65536) } else={ :return $Return }
}
:put [$SingleWordHexToNum "0xFF85"]
***: do not offend, is one of my preferred game when I’m young, and is still on my heart
search tag # rextended int2hex num2hex integer number hexadecimal convert function
Function to convert integer to hex (only positive numbers)
:global num2hex do={
:local number [:tonum $1]
:local hexadec "0"
:local remainder 0
:local hexChars "0123456789ABCDEF"
:if ($number > 0) do={:set hexadec ""}
:while ( $number > 0 ) do={
:set remainder ($number % 16)
:set number (($number-$remainder) / 16)
:set hexadec ([:pick $hexChars $remainder].$hexadec)
}
:if ([:len $hexadec] = 1) do={:set hexadec "0$hexadec"}
:return "0x$hexadec"
}
:put [$num2hex 7366]
For simple 0-255 to hex:
:global numbyte2hex do={
:local input [:tonum $1]
:local hexchars "0123456789ABCDEF"
:local convert [:pick $hexchars (($input >> 4) & 0xF)]
:set convert ($convert.[:pick $hexchars ($input & 0xF)])
:return $convert
}
the script here
https://forum.mikrotik.com/viewtopic.php?f=2&t=57665&p=868898#p295501
must be simply updated and converted on a function and work better than mine to convert for example integer to signed Single Word Hexadecimal value,
with “right” byte shift and “and 0xf” can convert easily -123 on 2 signed byte to 0xFF85
Probably a reverse-function can be writed based on that method.
I did not know that :tonum can handle hex input… That could simplify my function a lot.
Guess I will not drop it completely, currently it understands converting internal ids (like *d3f) directly.
BTW, RouterOS handles up to 60 bit unsigned values (0xfffffffffffffff), as does my function. No idea why you want to limit to 16 bit signed values?
You do not notice the request from @rrwakc on previous post? :))
https://forum.mikrotik.com/viewtopic.php?f=2&t=57665&p=869033#p868885
I do not know why need that, but is for convert single word signed hex to integer
0xFF85 to -123
Ah, indeed missed that detail… My fault.
Now your explanation makes perfectly sense. ![]()
Now the forum is more rich on functions ;))
I really appreciate this:
:local Hex “0123456789abcdef_eworm.de_ABCDEF”
[:find $Hex … ] % 16
I was very impressed with the simplicity of the solution …
TLDR: Temperature in °C also gets negative.
Mikrotik released KNOT, which also has GPIO ports, MQTT publisher and BLE(bluetooth low energy)
There is a firmware hack to make cheap BLE temperature humidity sensors behave like standard BLE 0x181A Environmental sensors (google: Custom Firmware On Xiaomi Thermometers)
Bluetooth GATT id of 0x0181A represent standard environmental sensors that provide temperature as 16bit signed in HEX.
Extract the 4 hex characters, convert to decimal and divide by 10 and you get -12.3°C to send over MQTT
At the end you get a nice modular smart-home setup managed as all other Mikrotik devices (+decoder as script)
With all the new IoT devices coming I would not be surprised to see dedicated chapter here for IoT, MQTT, NB-IoT, Scriping etc.
Now that the MQTT client module is available someone with good scripting skills might probably be able to send traffic and networks statistics from 100s of old mikrotik devices to mqtt broker and some database from there.
I hope you like those functions
@rextended, FWIW your num2hex function still comes in handy... While num2hex is super helpful, half the code is doing that one conversion
: HOWTO: Import ZeroTier Members into Mikrotik DNS using $ZT2DNS
Since despite the new built-in ":convert", still cannot do "num2hex" and it just assumes strings, so you get ASCII codes for "1", "6" as hex:
:put [:convert from=raw to=hex 16]
3136
While Mikrotik in 7.15 did add a "byte-array" that go to/from hex, so if the ints are in an array type, [:convert] can help some cases:
:put [:convert from=byte-array to=hex {255;255}]
# ffff
And so the "numbyte2hex" for the "one hex char" case can be reduced, in 7.15, to:
:global "numbyte2hex-using-convert" do={
:return [:convert from=byte-array to=hex {$1}]
}
:put [$"numbyte2hex-using-convert" 255]
# ff
Not saying to replace your code — since you need 7.15 for the "byte-array". More FYI on the current state of these type conversions ![]()