edited for code formatting
I'm trying to implement a Ble OTA system with a Esp32
I need to read a binary file into a Hex array and pass this over Ble to my Esp32 characteristic
The Esp32 works fine, and accepts an update from a simple Python3 script
the basics are below
`
# compute the packet size
packet_size = (512)
# split the firmware into packets
with open(file_path, "rb") as file:
while chunk := file.read(packet_size):
firmware.append(chunk)
# sequentially write all packets to OTA data
for i, pkg in enumerate(firmware):
print(f"Sending packet {i}/{len(firmware)-1}")
await client.write_gatt_char(
OTA_DATA_UUID,
pkg,
response=True
)`
Trying the same in Android java produces an array of unsigned ints, this does not seem to be compatible with the type of bytes that the Esp32 is expecting
heres a cut down example of what im trying
String path =
ContentUriUtils.INSTANCE.getFilePath(firmwareSelectActivity.this,
chosenFile);
File file = new File(path);
byte[] fileByteArray = readFile(file);
byte[][] test = splitArray(fileByteArray,512);
for(int i = 0;i < test.length;i++)
{ mBluetoothLeService.addBleOtaWriteByteCommandToQueue(BluetoothLeService
.getOtaTXcharacteristic(), test[i]);
}
The ESP32 OTA library is expecting the first byte to be 0xE9 to start the upgrade process. But I seem to be sending 0x13
Related
I have a perl code (say client) which sends packed data as HTTP POST to another perl code running on apache mod_perl module (say server).
In client side, I have the pack function like this,
$postData = pack("N a*", length($metaData), $metaData);
From perl pack document, it seems,
N -> An unsigned long (32-bit) in "network" (big-endian) order.
a -> A string with arbitrary binary data, will be null padded.
Now the $postData will be sent to server using perl LWP User Agent.
In the server side perl, we used to unpack like this,
# first reading the metaData Length
my $buf;
$request->read($buf, 4); #$request is apache request handler
my $metaDataLength = unpack("N", $buf);
# now read the metaData itself
$request->read($buf, $metaDataLength);
Now I have to do this server side data parsing in java (moving away from perl for some reasons). I have searched google for this and it seems to be not a single line solution as in perl. Some suggested to write our own unpack function. I am using java 1.7 version.
Is there any simple solution available in java for the above server side data parsing ?
Edit: Thanks Elliot for 'ByteBuffer' idea. The following code works fine for me,
InputStream is = request.getInputStream(); //request is HTTPServletRequest
byte[] bArr = new byte[4]; //reading first 4 bytes to get metaDataLength
int bytesRead = is.read(bArr);
ByteBuffer buf = ByteBuffer.wrap(bArr);
int metaDataLength = buf.getInt(); //shows value matches with clientside perl code.
potentially JBBP can be such one
final int value = JBBPParser.prepare("int;").parse(theInputStream).findFieldForType(JBBPFieldInt.class).getAsInt();
I have a java server communicating with a PHP script called from apache. I am aiming to send a JSON from the java server to the php client when requested, however there is some stuff getting prefixed when its received on the client.
JAVA
in = new BufferedReader(new InputStreamReader (socket.getInputStream()));
out= new DataOutputStream(socket.getOutputStream());
//The server receives a JSON from the PHP script and replies. It recives and converts to a Gson JSON no problem.
String reply = "{\"status\":\"reg\",\"token\":\""+client.getToken()+"\"}\r\n";
//reply = "HELLO\r";
out.writeUTF(reply);
PHP
$rec = socket_read($socket, 2048,PHP_NORMAL_READ);
echo "Receiving... ";
echo $rec;
The issue is that the message received is pre-fixed with some crap.
Output From PHP
Receiving... 1{"status":"reg","token":"QOPIPCNDI4K97QP0NAQF"}
If I send "HELLO\r"
Receiving... >HELLO
You shouldn't use DataOutputStream.writeUTF() unless you are using DataOutputStream.readUTF() to read the message.
Here is a snippet of the javadoc of writeUTF():
Writes a string to the underlying output stream using modified UTF-8
encoding in a machine-independent manner.
First, two bytes are written to the output stream as if by the
writeShort method giving the number of bytes to follow. This value is
the number of bytes actually written out, not the length of the
string. Following the length, each character of the string is output,
in sequence, using the modified UTF-8 encoding for the character. If
no exception is thrown, the counter written is incremented by the
total number of bytes written to the output stream. This will be at
least two plus the length of str, and at most two plus thrice the
length of str.
The bolded part above may tell you why you are getting weird characters at the beginning of your message.
Here is a workaround I believe will work in your case
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
out.write(os.getBytes("UTF-8"));
Reference: Why does DataOutputStream.writeUTF() add additional 2 bytes at the beginning?
So I read a file into a byte array and then I break it up into chunks and send it across the network with UDP.
Path path = Paths.get("files_upload/music.mp3");
byte[] objectBytes = Files.readAllBytes(path);
On the server I read all the chunks into a buffer and I end up with the same byte[] objectBytes as I had on the client. Now I want to write the file to disk using the original file name which is music.mp3 in this case. So how can I get the file name from the array of bytes?
The array of bytes doesn't contain the file name. You'd have to send it separately. You can call getFileName on your path, and then turn that into a byte array using getBytes() on the resulting string.
String fileName = path.getFileName();
byte[] fileNameBytes = fileName.getBytes();
You can then send this first and read it on the other end. Note, this wont contain the whole path, only the name of the file (music.mp3 in your case).
By the way, are you sure you want to be using UDP? What if you lose a packet or two when the data is being transferred? How do you detect that on the server?
I am developing a speech dictation app in android that send the recorded audio file through email. And its difficult to send large size wav files, so I am thinking about converting wav files to an appropriate format that can be sent easily by email.
After googling I found that .dss files consumes very less size and can be easily sent, but I don't know how to convert wav files into dss format. Your answers will be very helpfull.
I would recommend using Speex, since it is a free audio codec.
There also is a free java library, which you should be easy to use in android.
http://jspeex.sourceforge.net/
Also, there is the JSPeex SVN Repo, shich should get you started. It has some code examples for a player and a recorder:
http://jspeex.svn.sourceforge.net/viewvc/jspeex/main/trunk/player/src/main/java/org/xiph/speex/player/
Aswell as the javadoc http://jspeex.sourceforge.net/doc/index.html
I setuped ndk and used speex in my project. I am able to encode the wave file successfully, but when i try to decode it back the file size keeps on increasing to a large size. I have recorded the audio at a sample rate of 8000 and 16 BIT, MONO.
The code for decoding is given below:
#include <jni.h>
#include <stdio.h>
#include "speex/speex.h"
#define FRAME_SIZE 160
void Java_com_m2_iSmartDm_ISmartDMActivity_spxDec(JNIEnv * env, jobject jobj,
jstring dir1,jstring dir2)
{
const char *inFile= (*env)->GetStringUTFChars(env,dir1,0);
const char *outFile= (*env)->GetStringUTFChars(env,dir2,0);
FILE *fin;
FILE *fout;
/*Holds the audio that will be written to file (16 bits per sample)*/
short out[FRAME_SIZE];
/*Speex handle samples as float, so we need an array of floats*/
float output[FRAME_SIZE];
char cbits[200];
int nbBytes;
/*Holds the state of the decoder*/
void *state;
/*Holds bits so they can be read and written to by the Speex routines*/
SpeexBits bits;
int i, tmp;
/*Create a new decoder state in narrowband mode*/
state = speex_decoder_init(&speex_nb_mode);
/*Set the perceptual enhancement on*/
tmp=1;
speex_decoder_ctl(state, SPEEX_SET_ENH, &tmp);
fin = fopen(inFile, "r");
fout=fopen(outFile,"w");
speex_bits_init(&bits);
while (1)
{
/*Read the size encoded by sampleenc, this part will likely be
different in your application*/
fread(&nbBytes, sizeof(int), 1, fin);
if (feof(stdin))
break;
/*Read the "packet" encoded by sampleenc*/
fread(cbits, 1, nbBytes, fin);
/*Copy the data into the bit-stream struct*/
speex_bits_read_from(&bits, cbits, nbBytes);
/*Decode the data*/
speex_decode(state, &bits, output);
/*Copy from float to short (16 bits) for output*/
for (i=0;i<FRAME_SIZE;i++)
out[i]=output[i];
/*Write the decoded audio to file*/
fwrite(out, sizeof(short), FRAME_SIZE, fout);
}
/*Destroy the decoder state*/
speex_decoder_destroy(state);
/*Destroy the bit-stream truct*/
speex_bits_destroy(&bits);
fclose(fout);
fclose(fin);
}
Is there anything wrong in my code? Why it gives in such a large size?
I am sending some JSON data from my Flex application to the Java side for business processing. Now on top of that, I have added some code to compress(zLib) the data at Flex side and then pass it through Request and uncompress the same at java side.
But at the java layer, the uncompressed data is still not in readable/usable format.
Putting the code in here for reference.
Flex code for encoding
var bytes:ByteArray = new ByteArray();
bytes.writeObject(JSON.encode(someObj));
bytes.position = 0;
bytes.compress();
variables.encodeJSONStr = bytes;
requester.data = variables;
loader.load(requester);
Java code for decoding
String json = req.getParameter("encodeJSONStr");
byte[] input = json.getBytes();
Inflater decompresser = new Inflater();
decompresser.setInput(input);
byte[] result = new byte[1000];
int resultLength=0;
resultLength = decompresser.inflate(result);
decompresser.end();
String outputString = new String(result, 0, resultLength, "UTF-8");
System.out.println("\n\n resultLength>>>"+resultLength); // O/P comes as Zero
Can someone point put the issue in here or some better approach for compression of data when sending from Flex to Java ?
Some time ago I wrote a short post about sending compressed data between flex/java, maybe it helps: http://cornelcreanga.com/2008/07/actionscript-compressing-strings/
First you should try if Flex does the zLib compression properly (by uncompressing the data sent with another tool).
On the Java side you can try to use the InflaterInputStream which is easier to handle than the more low level Inflater. I had some issues with the Java native implementation and ended up using the jZlib which offers a zlib compression uncompression in pure Java.