split long hex numbers by 0D 0A in R - r

I want to write a code in R to split hex numbers by delimiters. I have a file including with all hex numbers separated by space like below:
0x01 0x02 0x03 0x04 0x0d 0x0a 0x05 0x06 0x07 0x0d 0x0a
I want to split all of these hex numbers by 0x0d (CR:carriage return) and 0x0a (LF: line feed), i mean i want output like this:
0x01 0x02 0x03 0x04
0x05 0x06 0x07
I think i can use functions like strsplit() but i dont know how. Would you please tell me how can i implement this in R?
Thanks.

Would a pair of gsub calls work?
text <- "0x01 0x02 0x03 0x04 0x0d 0x0a 0x05 0x06 0x07 0x0d 0x0a"
text <- gsub( "0x0d", "\r", text )
text <- gsub( "0x0a", "\n", text )
Which gives:
text
[1] "0x01 0x02 0x03 0x04 \r \n 0x05 0x06 0x07 \r \n"

library(purrr)
library(stringi)
library(magrittr)
# stringi & tidyverse
readLines(textConnection("0x01 0x02 0x03 0x04 0x0d 0x0a 0x05 0x06 0x07 0x0d 0x0a")) %>%
stri_split_fixed("0x0d 0x0a") %>%
.[[1]] %>%
stri_trim_both() %>%
discard(equals, "")
## [1] "0x01 0x02 0x03 0x04" "0x05 0x06 0x07"
# base R + a little tidyverse
readLines(textConnection("0x01 0x02 0x03 0x04 0x0d 0x0a 0x05 0x06 0x07 0x0d 0x0a")) %>%
strsplit("0x0d 0x0a") %>%
.[[1]] %>%
trimws() %>%
discard(equals, "")
## [1] "0x01 0x02 0x03 0x04" "0x05 0x06 0x07"
# old school R
con <- textConnection("0x01 0x02 0x03 0x04 0x0d 0x0a 0x05 0x06 0x07 0x0d 0x0a")
lines <- readLines(con)
lines <- strsplit(lines, "0x0d 0x0a")[[1]]
lines <- trimws(lines)
lines <- lines[lines != ""]
lines
## [1] "0x01 0x02 0x03 0x04" "0x05 0x06 0x07"
paste0() to make a single string with line breaks. cat() to display to the screen or write to a file as separate lines.

Related

R How to convert a byte in a raw vector into a ascii space

I am reading some very old files created by C code that consist of a header (ASCII) and then data. I use readBin() to get the header data. When I try to convert the header to a string it fails because there are 3 'bad' bytes. Two of them are binary 0 and the other binary 17 (IIRC).
How do I convert the bad bytes to ASCII SPACE?
I've tried some versions of the below code but it fails.
hd[hd == as.raw(0) | hd == as.raw(0x17)] <- as.raw(32)
I'd like to replace each bad value with a space so I don't have to recompute all the fixed data locations in parsing the string derived from hd.
I normally just go through a conversion to integer.
Suppose we have this raw vector:
raw_with_null <- as.raw(c(0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x00,
0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21))
We get an error if we try to convert it to character because of the null byte:
rawToChar(raw_with_null)
#> Error in rawToChar(raw_with_null): embedded nul in string: 'Hello\0World!'
It's easy to convert to numeric and replace any 0s or 23s with 32s (ascii space)
nums <- as.integer(raw_with_null)
nums[nums == 0 | nums == 23] <- 32
We can then convert nums back to raw and then to character:
rawToChar(as.raw(nums))
#> [1] "Hello World!"
Created on 2022-03-05 by the reprex package (v2.0.1)

arduino nano + nrf2401 CRC_lenght=disable

i have bought a arduino nano with a nrf2401 but the CRC_lenght is disable when i use the nf24/exemple/scanne
this is what i get
STATUS = 0x00 RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=0 TX_FULL=0
RX_ADDR_P0-1 = 0x0000000000 0x0000000000
RX_ADDR_P2-5 = 0x00 0x00 0x00 0x00
TX_ADDR = 0x0000000000
RX_PW_P0-6 = 0x00 0x00 0x00 0x00 0x00 0x00
EN_AA = 0x00
EN_RXADDR = 0x00
RF_CH = 0x00
RF_SETUP = 0x00
CONFIG = 0x00
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01
CRC Length = Disabled
PA Power = PA_MIN
000000000000000011111111111111112222222222222222333333333333333344444444444444445555555555555555666666666666666677777777777777
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
and i found on the web that normally it need to be like this
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xe7e7e7e7e7 0xc2c2c2c2c2
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xe7e7e7e7e7
RX_PW_P0-6 = 0x00 0x00 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x07
CONFIG = 0x0c
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_HIGH
why is the CRC Length and other things are not the same other things can be because of the brand but the most weird thing is hy CRC Length is disable instead off 16 bits
this is the cable settings
CE=pin7
CSN=pin8
SCK=pin13
MO=pin11
MI=pin12
of corse i have change this line RF24 radio(7,8); with the CE and CSN pin
"normally it need to be like this"
Why do you think that? Nothing needs to be like this unless you want to have the very same outcome.
NRF2401 has 144 configuration bits and they exist so you can configure them to your liking/needs.
As for all configurable things there are different configurations.
Yours looks like some default configuration as most values are 0 or disabled what I would expect when nothing has been configured yet.

How to convert a random string to a byte string

I generated a random string lets say using this randstring(RandomDevice(), 'a':'z', 15) Now I want its output as a byte string. How do I do that?
More context: What I am trying to do is to write something similar to python's os.urandom() function.
Julia doesn't seem to have Python like bytestrings at least in Base.
julia> using Random
julia> using Random: RandomDevice, randstring
julia> rs = randstring(RandomDevice(), 'a':'z', 15)
"wbfgxgoheksvxvx"
You can get a code units wrapper using the codeunits function, which returns a vector of Base.CodeUnits:
julia> cu = codeunits(rs)
15-element CodeUnits{UInt8,String}:
0x77
0x62
0x66
0x67
0x78
0x67
0x6f
0x68
0x65
0x6b
0x73
0x76
0x78
0x76
0x78
Or with the b"" non standard string literal macro:
julia> b"wbfgxgoheksvxvx"
15-element CodeUnits{UInt8,String}:
0x77
0x62
0x66
0x67
0x78
0x67
0x6f
0x68
0x65
0x6b
0x73
0x76
0x78
0x76
0x78
You can have a byte array like this:
julia> ba = Vector{UInt8}(rs)
15-element Array{UInt8,1}:
0x77
0x62
0x66
0x67
0x78
0x67
0x6f
0x68
0x65
0x6b
0x73
0x76
0x78
0x76
0x78
You could use the repr function, along with split and join functions to create your desired string:
julia> function bytestring(s::String)::String
ba = Vector{UInt8}(s)
return join([join(("\\x", split(repr(cu), "x")[2]), "") for cu in ba], "")
end
bytestring (generic function with 1 method)
julia> bytestring(rs)
"\\x77\\x62\\x66\\x67\\x78\\x67\\x6f\\x68\\x65\\x6b\\x73\\x76\\x78\\x76\\x78"
You can put that in a macro in order to create a custom non standard string literal:
julia> macro bs_str(s)
return bytestring(s)
end
#bs_str (macro with 1 method)
julia> bs"wbfgxgoheksvxvx"
"\\x77\\x62\\x66\\x67\\x78\\x67\\x6f\\x68\\x65\\x6b\\x73\\x76\\x78\\x76\\x78"
Finally you could compose it like this:
julia> urandom(r::Random.AbstractRNG, chars, n::Integer)::String = bytestring(randstring(r, chars, n))
urandom (generic function with 1 method)
julia> urandom(RandomDevice(), 'a':'z', 15)
"\\x67\\x61\\x78\\x64\\x71\\x68\\x73\\x77\\x76\\x6e\\x6d\\x6d\\x63\\x78\\x68"

igraph.to.gexf encoding issue

I'm trying to export a network I've built in igraph to a gexf format using rgexf so I can use it in Gephi. My basic code is below, plus then I have a few formatting things (removing labels and such) which I haven't included below.
df <- read.csv ("<file>", header = TRUE, sep = ",")
df.network <- graph.data.frame(df, directed=F)
V(df.network)$type <-bipartite.mapping(df.network)$type
plot(df.network, vertex.label.cex = 0.8, vertex.label.color = "black", layout=layout_with_kk, asp=0)
I then use the following
g1.gexf <- igraph.to.gexf(df.network)
but I get the following error message:
Input is not proper UTF-8, indicate encoding !
Bytes: 0xED 0x6E 0x20 0x46
Error: 1: Input is not proper UTF-8, indicate encoding !
Bytes: 0xED 0x6E 0x20 0x46
and g1.gexf isn't written. Can anyone help with what might have gone wrong?

Reading RAW data from an R socket

To exchange data very fast between Python and R I programmed a rather dirty solution, which works. On linux and OSX. May it not be that I now have to get this working in windows.
The below code runs a python script that builds a raw vector which can be serialised by RApiSerialise to an R object.
COMMAND = "python"
PATH_TO_SCRIPT='/GetCassandraData.py'
QueryCassandra <- function(query){
allArgs = c(PATH_TO_SCRIPT, query)
output.connection <- rawConnection(raw(length = 0), "r+")
exec_wait(COMMAND, args = allArgs, std_out = output.connection)
output <- rawConnectionValue(output.connection)
close(output.connection)
final <- unserializeFromRaw(output)
return(final)
}
This works as intended on OSX & linux however, windows has the tendancy to put a 0x0d (Carriage return) byte before a 0x0a (line feed) byte which makes RApiSerialise unable to deserialise it.
I am now attempting to solve the problem by communicating through sockets but I do not seem to be able to find a way to read data from a make.socket() object to a raw vector.
I have tried:
data <- read.socket(datasocket)
Which resulted in:
Error in read.socket(datasocket) :
embedded nul in string: 'X\n\0\0\0\002\0\003\004\002\0\002\003\0'
The function read.socket() tries to read a string and doesn't accept null bytes.
Is there a way to read socket data to a raw vector in R?
R server-side:
library(sys)
COMMAND = "python"
PATH_TO_SCRIPT='/lengthCheck.py'
allArgs = c(PATH_TO_SCRIPT)
sys::exec_background(COMMAND, args = allArgs, std_out = TRUE, std_err = TRUE)
datasocket <- socketConnection(port = 1205, server = TRUE, open = "w+b", blocking = TRUE)
on.exit(close(datasocket))
datasize <- readBin(datasocket, what = "double")
data <- readBin(datasocket, what = "raw", n = datasize)
Python client-side:
import struct
import socket
import time
your_raw_array_to_send = bytearray([0x58, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x00, 0x02, 0x03, 0x00])
arrayLength = len(your_raw_array_to_send)
datasize = struct.pack('d', arrayLength)
# Wait 100ms for R to set up a listening socket
time.sleep(.100)
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 1205))
client_socket.send(datasize)
client_socket.send(your_raw_array_to_send)
client_socket.close()

Resources