Reading GPS data from Teltonika FM4200 - c#

I have configured the GPS device and created a listener application in C#. I receive only the IMEI Number from the device and not any GPS NMEA data.
But for checking when i check the same in GPS Gate Server it displays the movement in map.
any suggestions!!!
Below is how the handling of data is performed
TcpClient client = (TcpClient)tcpClient;
Byte[] bytes = new Byte[10000];
String data = null;
int i;
NetworkStream stream = client.GetStream();
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
}
Console.WriteLine(data);
When it goes in the while loop it just waits and sleep :(

I think that device havaing pattern like
Step1:After Receving IMEI number
Step2:Replay "01" Status to the same newwork
Code:
TcpClient newClient = (TcpClient)client;
NetworkStream ns = newClient.GetStream()
byte[] bytes = new byte[1024];
bytes = Encoding.ASCII.GetBytes("X");
Console.WriteLine("X");
ns.Write(bytes, 0, bytes.Length);

First when module connects to server, module sends its IMEI. IMEI is
sent the same way as encoding barcode.
First comes short identifying number of bytes written and then goes IMEI as text
(bytes). For example IMEI 123456789012345 would be sent as
000F313233343536373839303132333435 After receiving IMEI,
server should determine if it would accept data from this module. If yes,server will reply to module 01 if not 00. Note that confirmation should be sent as binary packet.
Then module starts to send firstAVL data packet.
After server receives packet and parses it, server must report to module number of data received as integer(four bytes). If sent data number and reported by server doesn’t match module resends sent data.
Ref. FMXXXX Protocols V2.7

I think you need to do something like this (simple solution). If you can get it work, maybe you should check on some asynchronous sockets/tcp connections
TcpClient client = (TcpClient)tcpClient;
Byte[] bytes = new Byte[10000];
String data = null;
int i;
NetworkStream stream = client.GetStream();
// Will get data as long as data is available after 1st read
do
{
i = stream.Read(bytes, 0, bytes.Length)
data = String.Concat(data, System.Text.Encoding.ASCII.GetString(bytes, 0, i));
}
while(stream.DataAvailable);
// Write the data to console (first time it should be IMEI
Console.WriteLine(data);
// Write 1 to the stream, note it must probably be byte value 1 -> 0x01
// Flush output stream after writing to prevent buffering
data = "";
// Now try if more data comes in after IMEI and 0x01 reply
do
{
i = stream.Read(bytes, 0, bytes.Length)
data = String.Concat(data, System.Text.Encoding.ASCII.GetString(bytes, 0, i));
}
while(stream.DataAvailable);
// Write date to console - move inside the while loop if data keeps coming in
Console.WriteLine(data);

You have to configure your tracker first using below steps as in figure:
To initiate configuration process, configuration server sends binary initiation SMS (“Push” SMS) containing server host(ip address) and tcp port device should connect to and waits for TCP connection.
Upon reception of “push” SMS, device tries to establish TCP connection to configuration server using GPRS. If TCP connection attempt succeeds, server sends out configuration data to device over established connection, device confirms configuration reception and configures itself.
If device doesn‘t connect to server in TcpWaitTimeout time, server stops waiting for TCP connection, sends out configuration data using binary SMS, and waits for confirmation SMS from device. If confirmation SMS doesn‘t arrive in specified time, server assumes that configuration process failed.
Reference file:
https://sourceforge.net/p/opengts/discussion/579834/thread/6fd0ffe8/6213/attachment/FMXXXX%20Protocols%20v2.10.pdf

Here is a parser for FM1100 this may help you to write code for FM4200 model
https://github.com/temala/Teltonika-FM1100
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Data;
using System.Net.Sockets;
using System.Linq;
using System.IO;
namespace TeltonikaParser
{
public class Protocol_TeltonikaFMXXXX
{
private const int CODEC_FMXXX = 0x08;
private const int ACC = 1;
private const int DOOR = 2;
private const int Analog = 4;
private const int GSM = 5;
private const int SPEED = 6;
private const int VOLTAGE = 7;
private const int GPSPOWER = 8;
private const int TEMPERATURE = 9;
private const int ODOMETER = 16;
private const int STOP = 20;
private const int TRIP = 28;
private const int IMMOBILIZER = 29;
private const int AUTHORIZED = 30;
private const int GREEDRIVING = 31;
private const int OVERSPEED = 33;
private static string Parsebytes(Byte[] byteBuffer, int index, int Size)
{
return BitConverter.ToString(byteBuffer, index, Size).Replace("-", string.Empty);
}
private static string parseIMEI(Byte[] byteBuffer, int size)
{
int index = 0;
var result = Parsebytes(byteBuffer, index, 2);
return result;
}
private static bool checkIMEI(string data)
{
Console.WriteLine(data.Length);
if (data.Length == 15)
return true;
return false;
}
private static List<Position> ParsePositions(Byte[] byteBuffer, int linesNB)
{
int index = 0;
index += 7;
uint dataSize = byteBuffer[index];
index++;
uint codecID = byteBuffer[index];
if (codecID == CODEC_FMXXX)
{
index++;
uint NumberOfData = byteBuffer[index];
Console.WriteLine("{0} {1} {2} ", codecID, NumberOfData, dataSize);
List<Position> result = new List<Position>();
index++;
for (int i = 0; i < NumberOfData; i++)
{
Position position = new Position();
var timestamp = Int64.Parse(Parsebytes(byteBuffer, index, 8), System.Globalization.NumberStyles.HexNumber);
index += 8;
position.Time = DateTime.Now;
var Preority = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
position.Lo = Int32.Parse(Parsebytes(byteBuffer, index, 4), System.Globalization.NumberStyles.HexNumber) / 10000000.0;
index += 4;
position.La = Int32.Parse(Parsebytes(byteBuffer, index, 4), System.Globalization.NumberStyles.HexNumber) / 10000000.0;
index += 4;
var Altitude = Int16.Parse(Parsebytes(byteBuffer, index, 2), System.Globalization.NumberStyles.HexNumber);
index += 2;
var dir = Int16.Parse(Parsebytes(byteBuffer, index, 2), System.Globalization.NumberStyles.HexNumber);
if (dir < 90) position.Direction = 1;
else if (dir == 90) position.Direction = 2;
else if (dir < 180) position.Direction = 3;
else if (dir == 180) position.Direction = 4;
else if (dir < 270) position.Direction = 5;
else if (dir == 270) position.Direction = 6;
else if (dir > 270) position.Direction = 7;
index += 2;
var Satellite = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
if (Satellite >= 3)
position.Status = "A";
else
position.Status = "L";
position.Speed = Int16.Parse(Parsebytes(byteBuffer, index, 2), System.Globalization.NumberStyles.HexNumber);
index += 2;
int ioEvent = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
int ioCount = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
//read 1 byte
{
int cnt = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
for (int j = 0; j < cnt; j++)
{
int id = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
//Add output status
switch (id)
{
case ACC:
{
var value = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
position.Status += value == 1 ? ",ACC off" : ",ACC on";
index++;
break;
}
case DOOR:
{
var value = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
position.Status += value == 1 ? ",door close" : ",door open";
index++;
break;
}
case GSM:
{
var value = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
position.Status += string.Format(",GSM {0}", value);
index++;
break;
}
case STOP:
{
var value = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
position.StopFlag = value == 1;
position.IsStop = value == 1;
index++;
break;
}
case IMMOBILIZER:
{
var value = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
position.Alarm = value == 0 ? "Activate Anti-carjacking success" : "Emergency release success";
index++;
break;
}
case GREEDRIVING:
{
var value = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
switch (value)
{
case 1:
{
position.Alarm = "Acceleration intense !!";
break;
}
case 2:
{
position.Alarm = "Freinage brusque !!";
break;
}
case 3:
{
position.Alarm = "Virage serré !!";
break;
}
default:
break;
}
index++;
break;
}
default:
{
index++;
break;
}
}
}
}
//read 2 byte
{
int cnt = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
for (int j = 0; j < cnt; j++)
{
int id = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
switch (id)
{
case Analog:
{
var value = Int16.Parse(Parsebytes(byteBuffer, index, 2), System.Globalization.NumberStyles.HexNumber);
if (value < 12)
position.Alarm += string.Format("Low voltage", value);
index += 2;
break;
}
case SPEED:
{
var value = Int16.Parse(Parsebytes(byteBuffer, index, 2), System.Globalization.NumberStyles.HexNumber);
position.Alarm += string.Format("Speed", value);
index += 2;
break;
}
default:
{
index += 2;
break;
}
}
}
}
//read 4 byte
{
int cnt = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
for (int j = 0; j < cnt; j++)
{
int id = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
switch (id)
{
case TEMPERATURE:
{
var value = Int32.Parse(Parsebytes(byteBuffer, index, 4), System.Globalization.NumberStyles.HexNumber);
position.Alarm += string.Format("Temperature {0}", value);
index += 4;
break;
}
case ODOMETER:
{
var value = Int32.Parse(Parsebytes(byteBuffer, index, 4), System.Globalization.NumberStyles.HexNumber);
position.Mileage = value;
index += 4;
break;
}
default:
{
index += 4;
break;
}
}
}
}
//read 8 byte
{
int cnt = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
for (int j = 0; j < cnt; j++)
{
int id = byte.Parse(Parsebytes(byteBuffer, index, 1), System.Globalization.NumberStyles.HexNumber);
index++;
var io = Int64.Parse(Parsebytes(byteBuffer, index, 8), System.Globalization.NumberStyles.HexNumber);
position.Status += string.Format(",{0} {1}", id, io);
index += 8;
}
}
result.Add(position);
Console.WriteLine(position.ToString());
}
return result;
}
return null;
}
public static Byte[] DealingWithHeartBeat(string data)
{
Byte[] result = { 1 };
if (checkIMEI(data))
{
return result;
}
return null;
}
public static string ParseHeartBeatData(Byte[] byteBuffer, int size)
{
var IMEI = parseIMEI(byteBuffer, size);
if (checkIMEI(IMEI))
{
return IMEI;
}
else
{
int index = 0;
index += 7;
uint dataSize = byteBuffer[index];
index++;
uint codecID = byteBuffer[index];
if (codecID == CODEC_FMXXX)
{
index++;
uint NumberOfData = byteBuffer[index];
return NumberOfData.ToString();
}
}
return string.Empty;
}
public static List<Position> ParseData(Byte[] byteBuffer, int size)
{
List<Position> result = new List<Position>();
result = ParsePositions(byteBuffer, size);
return result;
}
public static Position GetGPRSPos(string oneLine)
{
return null;
}
}
}

Related

NAudio SampleProvider not updating buffer on Read as expected

I am trying to use Naudio to input audio and then output it again after it has been processed by a plugin. To do the output step I have created a custom SampleProvider but the buffer is not behaving as I expect and I can't hear any sound. The code that reads the audio and attempts to play it again is as follows
var audioFile = new AudioFileReader(#"C:\Users\alex.clayton\Downloads\Rhythm guitar.mp3");
PluginContext.PluginCommandStub.Commands.MainsChanged(true);
PluginContext.PluginCommandStub.Commands.StartProcess();
var vstSampleProvider = new VstSampleProvider(44100, 2);
var devices = DirectSoundOut.Devices.Last();
var output = new DirectSoundOut(devices.Guid);
output.Init(vstSampleProvider);
int chunckStep = 0;
while (chunckStep < audioFile.Length)
{
var nAudiobuffer = new float[blockSize * 2];
audioFile.Read(nAudiobuffer, 0, blockSize * 2);
var leftSpan = inputMgr.Buffers.ToArray()[0].AsSpan();
for (int i = 0; i < blockSize; i++)
{
leftSpan[i] = nAudiobuffer[i*2] / int.MaxValue;
}
var rightSpan = inputMgr.Buffers.ToArray()[0].AsSpan();
for (int i = 1; i < blockSize; i++)
{
rightSpan[i] = nAudiobuffer[i*2 + 1] / int.MaxValue;
}
PluginContext.PluginCommandStub.Commands.ProcessReplacing(inputBuffers, outputBuffers);
vstSampleProvider.LoadBuffer(outputBuffers);
chunckStep += blockSize;
}
PluginContext.PluginCommandStub.Commands.StopProcess();
PluginContext.PluginCommandStub.Commands.MainsChanged(false);
output.Play();
The Sample provider code is this
public class VstSampleProvider : ISampleProvider
{
private readonly int _sampleRate;
private readonly int _channels;
private readonly Queue<float> _buffer;
public VstSampleProvider(int sampleRate, int channels)
{
_sampleRate = sampleRate;
_channels = channels;
_buffer = new Queue<float>();
}
public WaveFormat WaveFormat => WaveFormat.CreateIeeeFloatWaveFormat(_sampleRate, _channels);
public void LoadBuffer(VstAudioBuffer[] outputBuffers)
{
var totalSampleCount = outputBuffers[0].SampleCount * _channels;
try
{
if (_channels == 1)
for (int i = 0; i < totalSampleCount; i++)
{
_buffer.Enqueue(outputBuffers[0][i]);
}
else
{
for (int i = 0; i < totalSampleCount; i++)
{
if (i % 2 == 0)
{
var value = outputBuffers[0][i / 2];
_buffer.Enqueue(value);
}
else
_buffer.Enqueue(outputBuffers[1][(i - 1) / 2]);
}
}
}
catch (Exception ex)
{
// Probably should log or something
}
}
public int Read(float[] buffer, int offset, int count)
{
if (_buffer.Count < count)
return 0;
if (offset > 0)
throw new NotImplementedException();
for (int i = 0; i < count; i++)
{
var value = _buffer.Dequeue();
buffer[i] = value;
}
if (buffer.Any(f => f > 1))
{
return count;
}
return count;
}
}
When I look at the values being dequeued they are all between -1 and 1, as expected but when I put a break point on the line after if (buffer.Any(f => f > 1)) I can see that the buffer values are integers larger than 1 or 0 and bear no resemblance to the dequeued values that, I thought, were added to the buffer.
I expect I have not understood something about how the SampleProvider is supposed to work byt looing at ones already in Naudio I cant see what I'm doing wrong.
Any help would be much appreciated. Thank you
So it turns out that the main issue was reading the input file and turning the volume down, so I was playing but very quietly.
leftSpan[i] = nAudiobuffer[i*2] / int.MaxValue
There was no need for the / int.MaxValue

C# Function to translate Binary-Code

Right now I try to write a C# Program to translate 8 Base Binary into Text.
But I guess I am not experienced enough with C# to truly make it Work.
I think the code I come up with, should, from a logical Point-of-View somewhat do what I want, but the Syntax isn't properly doing it, since don´t know it better.
This is what I have so far:
using System;
using System.Linq;
using System.Text;
class binaryTranslate
{
public int convertBin(string CodeInput)
{
int [] code = CodeInput.ToArray();
int CodeCount = code.ToString().Length;
int EightBaseSegAmount = CodeCount / 8;
int ByteCapacity = 8;
StringBuilder translated = new StringBuilder();
for (var i = 1; i < EightBaseSegAmount + 1; i++)
{
StringBuilder Byte = new StringBuilder(ByteCapacity);
int ByteStart = (i * 8) - 8;
int ByteEnd = (i * 8) - 1;
int ByteIncrement = 1;
for (var j = ByteStart ; j < ByteEnd + 1; j++)
{
Byte.Append(code[j]);
}
for (var k = 0; k > 7; k++)
{
int BitValue = 128;
if (Byte[k] == 1)
{
if (k > 0)
{
int Squared = Math.Pow(2, k);
ByteIncrement += BitValue / Squared;
}
else
{
ByteIncrement += BitValue;
}
}
}
char toSymbol = Convert.ToChar(ByteIncrement);
translated.Append(toSymbol);
}
return translated;
}
public static int Main()
{
convertBin("010010000110000101101100011011000110111100100001");
}
}
First of all, your code won't compile. Here are the errors/mistakes.
The first one is, at the first line of your function, you are converting the input string to an array using String.ToArray(), which returns a char[] but your try to assign it to a variable (code) typed int[]. You can solve this by replacing the int[] with either char[] or var.
The second one is, inside the second for loop (k = 0; k > 7), you use Math.Pow() and assign it's return value to an int variable (Squared). But Math.Pow returns double. You can solve this by casting the return value of Math.Pow to int. Like; int Squared = (int)Math.Pow(2, k);
The last thing is not easily solvable like the first two because, your code is not exactly correct. You are trying to return something called translated, which is a variable of type StringBuilder. But your function is defined to return an int.
Now these were compile errors. There are a bunch of logical and decision errors/mistakes. Your algorithm also isn't very correct.
Here is a sample code you can use/examine. I'd like to help you further, why your code was incorrect, what was your design mistakes etc. if you want to.
class binaryTranslate
{
public enum IncompleteSegmentBehavior
{
Skip = 0,
ZerosToStart = 1,
ZerosToEnd = 2
}
private byte ConvertBinstrToByte(string sequence)
{
if (string.IsNullOrEmpty(sequence))
return 0; // Throw?
if (sequence.Length != sizeof(byte) * 8)
return 0; // Throw?
const char zero = '0';
const char one = '1';
byte value = 0;
for (int i = 0; i < sequence.Length; i++)
{
if (sequence[i] != zero && sequence[i] != one)
return 0; // Throw
value |= (byte)((sequence[i] - zero) << (7 - i));
}
return value;
}
private string HandleIncompleteSegment(string segment, int segmentSize, IncompleteSegmentBehavior behavior)
{
string result = null;
var zeroAppender = new StringBuilder();
for (int i = 0; i < segmentSize - segment.Length; i++)
zeroAppender.Append('0');
var zeros = zeroAppender.ToString();
switch (behavior)
{
case IncompleteSegmentBehavior.Skip:
break;
case IncompleteSegmentBehavior.ZerosToStart:
result = zeros + result;
break;
case IncompleteSegmentBehavior.ZerosToEnd:
result = result + zeros;
break;
default:
break;
}
return result;
}
public byte[] ConvertBinstrToBytes(string binarySequence, IncompleteSegmentBehavior behavior = IncompleteSegmentBehavior.Skip)
{
var segmentSize = sizeof(byte) * 8;
var sequenceLength = binarySequence.Length;
var numberOfBytes = (int)Math.Ceiling((double)sequenceLength / segmentSize);
var bytes = new byte[numberOfBytes];
for (int i = 0; i < numberOfBytes; i++)
{
var charactersLeft = sequenceLength - i * segmentSize;
var segmentLength = (charactersLeft < segmentSize ? charactersLeft : segmentSize);
var segment = binarySequence.Substring(i * segmentSize, segmentLength);
if (charactersLeft < segmentSize)
{
segment = HandleIncompleteSegment(segment, segmentSize, behavior);
if (segment == null)
continue;
}
bytes[i] = ConvertBinstrToByte(segment);
}
return bytes;
}
}
This code passes these assertions.
var bytes = new binaryTranslate()
.ConvertBinstrToBytes("00000000");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b00000000);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("10000000");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b10000000);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("11111111");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b11111111);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("00000001");
Assert.Equal(bytes.Length, 1);
Assert.Equal(bytes[0], 0b00000001);
bytes = new binaryTranslate()
.ConvertBinstrToBytes("1100110000110011");
Assert.Equal(bytes.Length, 2);
Assert.Equal(bytes[0], 0b11001100);
Assert.Equal(bytes[1], 0b00110011);
If you are really converting to a string the code should look like this
namespace binaryTranslate
{
class Program
{
static void Main(string[] args)
{
//convertBin("01001000 01100001 01101100 01101100 01101111 00100001");
string results = BinaryTranslate.convertBin(new byte[] { 0x44, 0x61, 0x6c, 0x6c, 0x6f, 0x21 });
}
}
public class BinaryTranslate
{
public static string convertBin(byte[] CodeInput)
{
return string.Join("", CodeInput.Select(x => x.ToString("X2")));
}
}
}
this should do the trick.
public static string FromBinary(string binary)
{
int WordLength = 8;
binary = binary.Replace(' ', '');
while(binary.Length % WordLength != 0)
binary += "0";
string output = String.Empty;
string word = String.Empty;
int offset = 0;
while(offset < binary.Length)
{
int tmp = 0;
word = binary.Substring(offset, 8);
for(int i=0; i<(WordLength - 1); i++)
if(word[i] == '1')
tmp += (int) Math.Pow(2, i);
output += Convert.ToChar(tmp);
offset += WordLength;
}
return output;
}

Send many variables from Unity To Arduino

I'm trying to send many ints to my "masterArduino".
Because the SerialPort object only send strings. I've tried many things including:
Creating a string from ints (didn't work because the size of the string.length is dynamic).
Then I tried to convert these ints to chars, this because all values are between 0-255, then put the char into a string and send it.
This sort of works. However, I think there is no value for 0 in char world. So the data is not right. But there must be a better way?
void sendInfo() {
for (var i = 0; i < peltiers.Length; i++) {
char tempHot = (char) peltiers[i].GetComponent<Peltier>().hot;
char charTemp = (char) peltiers[i].GetComponent<Peltier>().temp;
peltierInfo += tempHot.ToString();
peltierInfo += charTemp.ToString();
}
sp.WriteLine(peltierInfo);
Debug.Log(peltierInfo);
sp.BaseStream.Flush();
peltierInfo = "";
}
Any help would be greatly appreciated! Thanks!
Arduino Code:
void loop() {
int serialIndex = 0;
int i2cIndex = 0;
while (0 < Serial.available()) { // loop through all the received bytes
char bufferByte = 0;
bufferByte = Serial.read();
serialBuffer[serialIndex] = (byte) bufferByte; // put current index byte in array
serialIndex ++; // add index.
if (serialIndex%12==0 && serialIndex != 0) {
sendBytes(0);
}
}
//sendBytes(0);
delay(50);
}
void sendBytes(int slave) {
byte i2cBuffer[12];
int bufferIndex = slave * 12;
for (int i = 0; i < 12; i++) {
i2cBuffer[i] = serialBuffer[i + bufferIndex];
}
Wire.beginTransmission(slave+1);
Wire.write(i2cBuffer, 12);
Wire.endTransmission();
}
To be able to send any integers, first encode them into a string, separate them by something (e.g the '\0' char) and then decode the string.
void sendInfo() {
...
peltierInfo += peltiers[i].GetComponent<Peltier>().hot.ToString();
peltierInfo += '\0';
peltierInfo += peltiers[i].GetComponent<Peltier>().temp.ToString();
peltierInfo += '\0';
...
}
void loop() {
int serialIndex = 0;
int i2cIndex = 0;
// set to how many digits there can be in an incoming number plus 1
int maxNumberLen = 20;
char buffer[20];
// position at which we now put a char that makes up our number
char* currentCharPtr = buffer;
while (0 < Serial.available()) { // loop through all the received bytes
char bufferByte = 0;
bufferByte = Serial.read();
*currentCharPtr = bufferByte;
// move pointer forward
currentCharPtr ++;
// end of a number in string
if (bufferByte == '\0') {
printf("Got number %s\n", buffer);
// atoi parses string to int
serialBuffer[serialIndex] = atoi(buffer);
serialIndex ++;
if(serialIndex%12==0 && serialIndex != 0){
sendBytes(0);
}
// fill buffer with zeros after we found a number
memset(buffer, 0, 20);
currentCharPtr = buffer;
}
}
//sendBytes(0);
delay(50);
}
Thanks for the reply, your answer was exactly how i got it working. I just did it slightly different and didn't had the time to upload this post. What way is better, or is it just a matter of taste?
Unity
void sendInfo()
{
for (int i = 0; i < peltiers.Length; i++)
{
peltierInfo += ",";
peltierInfo += peltiers[i].GetComponent<Peltier>().hot.ToString();
peltierInfo += ",";
peltierInfo += peltiers[i].GetComponent<Peltier>().temp.ToString("D3");
}
//Debug.Log(peltierInfo);
sp.WriteLine(peltierInfo);
sp.BaseStream.Flush();
peltierInfo = "";
}
Arduino
void loop() {
int serialIndex = 0;
if(Serial.available() > 0){
while (0 < Serial.available()) { // loop through all the received bytes
String bufferString;
uint8_t bufferInt;
bufferString = Serial.readStringUntil(',');
bufferInt = bufferString.toInt();
serialBuffer[serialIndex] = bufferInt; // put current index byte in array
serialIndex ++; // add index.
}
sendBytes(0);
}
delay(50);
}
thanks for the help!

C# Iterate through binary file and build a text file with found bytes

I try to be more specific.
I have a binary file which has some portions of text inside.
I want to search for some byte sequence in the binary file, if the sequences are found take the byte arrays and build a text file with them.
So the step has to be repeated till the end of the binary file.
I used BinaryReader to search for a byte sequence, in order to validate the binary file, but now I am stuck on how to proceed with this combination.
My other issue is that I have to skip certain portions of the binary file until the next sequence is found.
So for example, I find the first sequence at 0x10 and it lasts for 10 bytes. Then I have to skip 32 bytes where another byte sequence then starts for x bytes till a tail byte that marks the end of the sequence.
Each time a byte sequence is found I have to save it in a text file, finally writing it to disk.
Any help?
Something like this, then:
class Program
{
const string filename = "some file";
static void Main(string[] args)
{
byte[] bytes = System.IO.File.ReadAllBytes(filename);
string[] find = new string[] { "me", "you" };
int offsetAfterFind = 32;
int pos = 0;
while (pos < bytes.Length)
{
bool isFound = false;
int index = 0;
while (!isFound && index < find.Length)
{
bool isMatch = true;
for (int n = 0; n < find[index].Length; n++)
{
if (pos + n >= bytes.Length)
{
isMatch = false;
}
else
{
if (bytes[pos + n] != find[index][n]) isMatch = false;
}
}
if (isMatch)
{
isFound = true;
break;
}
index++;
}
if (isFound)
{
Console.WriteLine(String.Format("Found {0} at {1}", find[index], pos));
pos += find[index].Length + offsetAfterFind;
}
else
{
pos++;
}
}
}
}
All right. I managed to do it and maybe this will be useful to someone else:
public static void ConvertToSRTSubs()
{
byte [] openingTimeWindow = Encoding.ASCII.GetBytes("["); \\Timespan in the binary is wrapped around square brackets
byte [] nextOpening = Encoding.ASCII.GetBytes("[00"); \\ I need this as a point to get the end of the sentence, because there is a fixed size between sentences and next timespan.
byte [] closingTimeWindow = Encoding.ASCII.GetBytes("]"); \\End of the timespan
int found = 0; \\This will iterate through every timespan match
int backPos = 0; \\Pointer to the first occurrence
int nextPos = 0;
int sentenceStartPos = 0;
int newStartFound = 0;
string srtTime = String.Empty;
string srtSentence = String.Empty;
byte[] array = File.ReadAllBytes(Path.Combine(coursePath, hashedSubFileName));
try
{
using (StreamWriter s = new StreamWriter(Video.outPath + ext, false))
{
for (int i = 0; i < array.Length; i++)
{
if (openingTimeWindow[0] == array[i] && closingTimeWindow[0] == array[i + 12])
{
found++;
s.WriteLine(found);
try
{
backPos = i;
for (i = backPos + 12; i < array.Length; i++ )
{
if (newStartFound == 1)
break;
if (nextOpening[0] == array[i] && nextOpening[1] == array[i + 1] && nextOpening[2] == array[i + 2])
{
nextPos = i - 19;
newStartFound++;
}
}
i = backPos;
newStartFound = 0;
sentenceStartPos = backPos + 27;
sentenceSize = nextPos - sentenceStartPos;
if (sentenceSize < 0) sentenceSize = 1;
byte[] startTime = new byte[11];
byte[] sentence = new byte[sentenceSize];
Array.Copy(array, backPos + 1, startTime, 0, 11);
Array.Copy(array, sentenceStartPos, sentence, 0, sentenceSize);
srtTimeRaw = srtTime = Encoding.UTF8.GetString(startTime);
srtTime = srtTimeRaw.Replace('.', ',') + "0" + " --> " + span;
s.WriteLine(srtTime);
srtSentence = Encoding.UTF8.GetString(sentence);
s.WriteLine(srtSentence);
s.WriteLine();
}
catch (ArgumentException argex)
{
MessageBox.Show(argex.ToString());
}
}
}
}
}
catch (DirectoryNotFoundException dex)
{
MessageBox.Show(dex.ToString());
}
}
Maybe not the cleanest code, but it works :)

Convert byte/int to List<int> reversed and vice versa

Was wondering how can I convert an int to a List in reverse order padded with zeroes and vice versa?
Have a byte that represents List(8), sometimes 2 bytes for List(16), 8 bytes for List(64); so looking for a good solution to handle converting to an int list, manipulate then back again.
e.g. Input of 3 to a List of 1,1,0,0,0,0,0,0
Or input of 42 to a List of 0,1,0,1,0,1,0,0
And vice-versa, take a List of 1,1,0,0,0,0,0,0 and return 3 or List of 0,1,0,1,0,1,0,0 and return 42
What I have done at present is build a couple of functions to handle both scenarios, all works fine, just wondering if there is a better / more elegant solution that I've completelt overlooked?
private List<int> IntToList(int _Input)
{
string _Binary = ReverseString(Convert.ToString(_Input, 2).PadLeft(8, '0'));
List<int> _List = new List<int>(8);
for (int i = 0; i < _Binary.Length; i++)
{
_List.Add(Convert.ToInt32(_Binary.Substring(i, 1)));
}
return _List;
}
private int IntsToByte(List<int> _List)
{
string _Binary = "";
for (int i = 7; i > -1; i--)
{
_Binary += _List[i];
}
return Convert.ToInt32(_Binary, 2);
}
You can work with bitwise operations. They might be fast.
Warning : Be aware of Little/Big Endian (More here)
The following code works :
private List<int> IntToList(int _Input, int _MaxSize = 8)
{
int padding = 1;
List<int> resultList = new List<int>(_MaxSize);
while (padding < 1 << _MaxSize)
{
resultList.Add((_Input & padding) == padding ? 1 : 0);
padding = padding << 1;
}
return resultList;
}
private int IntsToByte(List<int> _List)
{
int result = 0, padding = 0;
foreach (int i in _List)
{
result = result | (i << padding++);
}
return result;
}
This should work
int number = 42
char[] reverse = Convert.ToString(number, 2).PadLeft(8, '0').ToCharArray();
Array.Reverse(reverse);
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<ulong> results = null;
List<byte> output = null;
List<byte> input1 = new List<byte>() { 1, 1, 0, 0, 0, 0, 0, 0 };
results = ReadList(input1, 1);
output = WriteList(results,1);
List<byte> input2 = new List<byte>() { 0, 1, 0, 1, 0, 1, 0, 0 };
results = ReadList(input2, 1);
output = WriteList(results,1);
}
static List<ulong> ReadList(List<byte> input, int size)
{
List<ulong> results = new List<ulong>();
input.Reverse();
MemoryStream stream = new MemoryStream(input.ToArray());
BinaryReader reader = new BinaryReader(stream);
int count = 0;
ulong newValue = 0;
while (reader.PeekChar() != -1)
{
switch (size)
{
case 1:
newValue = ((ulong)Math.Pow(2, size) * newValue) + (ulong)reader.ReadByte();
break;
case 2:
newValue = ((ulong)Math.Pow(2, size) * newValue) + (ulong)reader.ReadInt16();
break;
}
if (++count == size)
{
results.Add(newValue);
newValue = 0;
count = 0;
}
}
return results;
}
static List<byte> WriteList(List<ulong> input, int size)
{
List<byte> results = new List<byte>();
foreach (ulong num in input)
{
ulong result = num;
for (int count = 0; count < size; count++)
{
if (result > 0)
{
byte bit = (byte)(result % Math.Pow(2, size));
results.Add(bit);
result = (ulong)(result / Math.Pow(2, size));
}
else
{
results.Add(0);
}
}
}
results.Reverse();
return results;
}
}
}
​
Solution from OP.
Have gone with Jean Bob's suggestion of using BitWise.
For anyone elses benefit, here is my modified version to read / write in blocks of 8 to/from the list.
private List<int> IntToList(List<int> _List, int _Input)
{
int _Padding = 1;
while (_Padding < 1 << 8)
{
_List.Add((_Input & _Padding) == _Padding ? 1 : 0);
_Padding = _Padding << 1;
}
return _List;
}
private int IntsToByte(List<int> _List, int l)
{
int _Result = 0, _Padding = 0;
for (int i = l; i < (l + 8); i++)
{
_Result = _Result | (_List[i] << _Padding++);
}
return _Result;
}

Categories

Resources