How to print only datalabel out of whole scandata? - c#

I am a new bee to C# programming. I have a zebra bar code scanner. I made a C# code according to the software user manual. I am able to print the scandata. However this data consist of all the information about the scanner. It has serial number,module number,GUID,datatype and datalabel.
This datalabel is the information about the bar code. I am interested in this datalabel only. I need to develop further code using this datalabel.
How can I print only the datalabel?.
Here I am attaching my code. Thank you.
namespace ConsoleApp_scandata
{
class Program
{
//declare the core scanner class
static CCoreScannerClass cCoreScannerClass;
static void Main(string[] args)
{
cCoreScannerClass = new CoreScanner.CCoreScannerClass();
//CALL OPEN API
short[] scannerTypes = new short[1]; //scanner types intrested in
scannerTypes[0] = 1; // set all scanner types to 1
short numberOfScannerTypes = 1; // size of the scanner type array
int status; // Extend API return code
cCoreScannerClass.Open(0, scannerTypes, numberOfScannerTypes, out status);
if (status == 0)
Console.WriteLine("CoreScanner API OPEN");
else
Console.WriteLine("CoreScanner API CLOSED");
// Lists all scanners connected to the host computer.
// will return nothing
short numberOfScanners;
int[] connectedScannerIDList = new int[255];
string outXML;
cCoreScannerClass.GetScanners(out numberOfScanners, connectedScannerIDList, out outXML, out status);
//below does not work because string is an xml file and is never NULL
Console.WriteLine(outXML);
// Console.WriteLine(outXML.ToString());
cCoreScannerClass.BarcodeEvent += new _ICoreScannerEvents_BarcodeEventEventHandler(OnBarcodeEvent);
int opcode = 1001;
string inXML = "<inArgs>" +
"<cmdArgs>" +
"<arg-int>1</arg-int>" +
"<arg-int>1</arg-int>" +
"</cmdArgs>" +
"</inArgs>";
cCoreScannerClass.ExecCommand(opcode, ref inXML, out outXML, out status);
opcode = 2011;
inXML = "<inArgs>" +
"<scannerID>1</scannerID>" +
"</inArgs>";
cCoreScannerClass.ExecCommand(opcode, ref inXML, out outXML, out status);
while (true)
{
Console.Read();
}
}
private static void OnBarcodeEvent(short eventType, ref string pscanData)
{
Console.WriteLine("Scannner Event! Scan Data: " + pscanData);
}
}
}

Load pscanData in the XmlDocumentand your are ready to go, just copy this code:
private static void OnBarcodeEvent(short eventType, ref string pscanData)
{
Console.WriteLine("Scannner Event! Scan Data: " + pscanData);
XmlDocument xmlDoc = new XmlDocument();
//xmlDoc.LoadXml(pscanData); //You should use this line as far as your XML tags are correct
xmlDoc.LoadXml("<scandata>" +
"<modeldata>" +
"099909" +
"</modeldata>" +
"<datalabel>" +
"0x68 0x74 0x74" +
"</datalabel>" +
"</scandata>"); //I use this harcoded XML because I don't have your pscanData, just delete this line and uncoment the one above
XmlNodeList datalabel = xmlDoc.GetElementsByTagName("datalabel");
XmlNode allInDataLabel = datalabel.Item(0);
string whatDatalabelContains = allInDataLabel.InnerText;
Console.WriteLine("Datalabel: " + ToText(whatDatalabelContains));
}
Edit: Hex to text
private static string ToText(string yourHex)
{
StringBuilder sb = new StringBuilder();
string[] dataArr = yourHex.Split(new char[] { ' ' });
for (int i = 0; i < dataArr.Length; i++)
{
sb.Append(Char.ConvertFromUtf32(Convert.ToInt32(dataArr[i], 16)));
}
return sb.ToString();
}

Related

Getting a System.StackOverflowException' error

I am Getting this error An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll I know you are not supposed to have an infinite loop but its not an infinate loop because it just has too go till it gets a file number that has not been made yet. How can i go about this a better way?
private int x = 0;
public string clients = #"F:\Internal Jobs\Therm-Air Files\Program\P-1-2.0\Clients\";
public string tdate = DateTime.Today.ToString("MM-dd-yy");
public void saveloop()
{
string path = LoadPO.Text.Substring(0, LoadPO.Text.LastIndexOf("\\"));
string name = Path.GetFileName(path);
string t = Convert.ToString(x);
if (!File.Exists(path + #"\" + name + ".xlsx")) // This Line throws error
{
oSheet.SaveAs(path + #"\" + name + "-" + t + ".xlsx");
string prop = /* snipped for space reasons, just string concats */
string Combine = string.Empty;
int b = 0;
int c = cf.cPanel.Controls.Count;
string[] items = new string[c];
foreach (WProduct ewp in cf.cPanel.Controls)
{
string item = /* snipped for space reasons, just string concats */
items[b] = item;
b += 1;
}
Combine = prop + "^<";
foreach (var strings in items)
{
Combine += strings + "<";
}
File.WriteAllText(path + #"\" + name + ".txt", Combine);
}
else
{
x += 1;
saveloop();
}
The reason the code above is failing is because you do not use i in the name of the file so you can increment all you want it does not change the name.
You need to abstract the creation of the name of the file from the code that does the writing. Think of it as writing code in blocks of functionality.
public static string GetFileName(string path, string name)
{
var fileName = $#"{path}\{name}.xlsx";
int i = 0;
while (System.IO.File.Exists(fileName))
{
i++;
fileName = $#"{path}\{name}({i}).xlsx";
}
return fileName;
}
public void saveloop()
{
var fileName = GetFileName(path, name);
// use fileName from this point on
}

How to trigger/run events when using SpVoice/SpFileStream in C#

I am using SpVoice to generate audio files, using SpFileStream.
I need several information about the text to be spooken, f.ex word boundaries.
I try to add some events to execute when end of word occurs.
But the eventHandler does not run as expected.
I have tried to do as specified here SpVoice (Events) Interface (SAPI 5.3)
The code:
public void SpeakToFile(String toSpeak, string id)
{
SpVoice voiceNew = new SpVoice();
voiceNew.EventInterests = SpeechVoiceEvents.SVEWordBoundary;
voiceNew.Word +=VoiceNewOnWord;
SpFileStream outStream = new SpFileStream();
string wavPath = _fileHelper.GetTempFileNameWav(id);
outStream.Open(wavPath, SpeechStreamFileMode.SSFMCreateForWrite, DoEvents:true);
voiceNew.AudioOutputStream = outStream;
voiceNew.Speak(toSpeak);
outStream.Close();
}
private void VoiceNewOnWord(int streamNumber, object streamPosition, int characterPosition, int length)
{
Boundary boundary = new Boundary();
boundary.StreamPosition = streamPosition.ConvertTo<long>();
boundary.CharacterPosition = characterPosition;
boundary.Length = length;
log.Info("word_boundary2: - strPos : " + boundary.StreamPosition + " - charPos : " + boundary.CharacterPosition + " - length : " + boundary.Length);
}
Anyone?

Serializing a manually written code

I am having a problem receiving files from the client. Someone suggested that I should use binary serialization to send and receive messages in stream. Can you give me ideas on how I should serialize this? I just learned about serialization not long ago so I am quite confused on how I should associate it with my program.
This is the client that 'should' be serialize
public void sendthedata()
{
if (!_timer.Enabled) // If timer is not running send data and start refresh interval
{
SendData();
_timer.Enabled = true;
}
else // Stop timer to prevent further refreshing
{
_timer.Enabled = false;
}
}
private List<int> listedProcesses = new List<int>();
private void SendData()
{
String processID = "";
String processName = "";
String processPath = "";
String processFileName = "";
String processMachinename = "";
listBox1.BeginUpdate();
try
{
piis = GetAllProcessInfos();
for (int i = 0; i < piis.Count; i++)
{
try
{
if (!listedProcesses.Contains(piis[i].Id)) //placed this on a list to avoid redundancy
{
listedProcesses.Add(piis[i].Id);
processID = piis[i].Id.ToString();
processName = piis[i].Name.ToString();
processPath = piis[i].Path.ToString();
processFileName = piis[i].FileName.ToString();
processMachinename = piis[i].Machinename.ToString();
output.Text += "\n\nSENT DATA : \n\t" + processFileName + "\n\t" + processMachinename + "\n\t" + processID + "\n\t" + processName + "\n\t" + processPath + "\n";
}
}
catch (Exception ex)
{
wait.Abort();
output.Text += "Error..... " + ex.StackTrace;
}
NetworkStream ns = tcpclnt.GetStream();
String data = "";
data = "--++" + processFileName + " " + processMachinename + " " + processID + " " + processPath;
if (ns.CanWrite)
{
byte[] bf = new ASCIIEncoding().GetBytes(data);
ns.Write(bf, 0, bf.Length);
ns.Flush();
}
}
}
finally
{
listBox1.EndUpdate();
}
}
And deserializing in the server
private void recieveData()
{
NetworkStream nStream = tcpClient.GetStream();
ASCIIEncoding ascii = null;
while (!stopRecieving)
{
if (nStream.CanRead)
{
byte[] buffer = new byte[1024];
nStream.Read(buffer, 0, buffer.Length);
ascii = new ASCIIEncoding();
recvDt = ascii.GetString(buffer);
/*Received message checks if it has +##+ then the ip is disconnected*/
bool f = false;
f = recvDt.Contains("+##+");
if (f)
{
string d = "+##+";
recvDt = recvDt.TrimStart(d.ToCharArray());
clientDis();
stopRecieving = true;
}
//else if (recvDt.Contains("^^"))
//{
// new Transmit_File().transfer_file(file, ipselected);
//}
/* ++-- shutsdown/restrt/logoff/abort*/
else if (recvDt.Contains("++--"))
{
string d = "++--";
recvDt = recvDt.TrimStart(d.ToCharArray());
this.Invoke(new rcvData(addToOutput));
clientDis();
}
/*--++ Normal msg*/
else if (recvDt.Contains("--++"))
{
string d = "--++";
recvDt = recvDt.TrimStart(d.ToCharArray());
this.Invoke(new rcvData(addToOutput));
}
}
Thread.Sleep(1000);
}
}
public void addToOutput()
{
if (recvDt != null && recvDt != "")
{
output.Text += "\n Received Data : " + recvDt;
recvDt = null;
}
}
Thank you.
There are a couple of rules to follow when serialising a piece of data.
It's easy to convert data to bytes, but consider how to reconstruct the data on the other side. Assume that the server can't have any knowledge on what you sended.
In your serialiser you just convert a couple of strings into a byte[] and send it over. Example:
string x = "abcdef";
string y = "ghijk";
var bytes = Encoding.Ascii.GetBytes(x + y);
the server receives: "abcdefghijk";
Is it possible for the server to determine and reconstruct strings x and y?
Since the server has no knowledge of the length of either x and y: no.
There are ways to solve this:
Use fixed length fields. In my example x should always be 6 chars and y should always be 5 chars in length. decoding on the server then becomes as trivial as
string x = data.Substring(0, 6)
string y = data.Substring(6, 5)
Use delimiters between the fields. If you are familiar with cvs, the ',' splits the fields. This however has it drawbacks, how to handle a ',' somewhere in a string? The data send over would be like "abcdef,ghijk"
Send the size of each field before the content of the field.
A naive approach just to clarify: string x would be send as '6abcdef' and y as '5ghijk'
Doing all this things by hand can get really hairy and is something that I would consider only if really needed.
I would resort to existing frameworks that do an excellent job on this subject:
Json.net
protobuf ported by Jon skeet
In this case I would first create a class to define the data send to the server instead of a bunch of strings:
class ProcessInfo{
public string ProcessID {get;set;}
public string ProcessName {get;set;}
public string ProcessPath {get;set;}
public string ProcessFileName {get;set;}
public string ProcessMachinename {get;set;}
};
the using Json to serialise this:
var procinfo = new ProcessInfo{
ProcessId = "1",
...
};
var serialised = JsonConvert.SerializeObject(procinfo);
var bytes = Encoding.Utf8.GetBytes(serialised);
ns.Write(bytes, 0, bytes.Length);
And restore it on the server just by:
var procInfo = JsonConvert.DeserializeObject<ProcessInfo>(json);

mono-service keeps reserving memory untill raspberry pi is out of mem

So I have a background service written in C# which connects to a RFID-reader and reads out all the tags he sees. After that the service will place all tags in a database running on the Raspberry Pi as well. The problem is when I start the service that it keeps consuming more and more memory from the Pi. I've already ran it with mono-service --profile=default:alloc but this returns errors. Does anybody see anything in my code which could cause this memory usage?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using Impinj.OctaneSdk;
using MySql.Data.MySqlClient;
using Raspberry.IO.GeneralPurpose;
using System.IO.Ports;
using System.Xml;
using System.Threading;
namespace RFIDdaemon
{
public partial class RFIDdaemon : ServiceBase
{
// Create an instance of the ImpinjReader class.
static ImpinjReader reader = new ImpinjReader();
static int opIdUser, opIdTid;
static MySQL _oMySql = new MySQL(Properties.Resources.DatabaseHostname, Properties.Resources.Database, Properties.Resources.Uid, Properties.Resources.Pwd);
// Create a Dictionary to store the tags we've read.
static OutputPinConfiguration led1 = ConnectorPin.P1Pin18.Output();
static GpioConnection connection = new GpioConnection(led1);
static XmlDocument Power = new XmlDocument();
private Thread _oThread;
private ManualResetEvent _oManualResetEvent = new ManualResetEvent(false);
static string userData, tidData, epcData;
public RFIDdaemon()
{
this.ServiceName = "RFIDdaemon";
this.AutoLog = false;
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if (_oThread == null)
{
_oThread = new Thread(Reader);
}
if (!_oThread.IsAlive)
{
_oManualResetEvent.Reset(); //Reset reset event te continue thread
_oThread = new Thread(Reader); //New thread
_oThread.Name = "RFIDreader";
_oThread.IsBackground = true;
_oThread.Start();
}
}
protected override void OnStop()
{
// Stop reading.
reader.Stop();
GC.Collect();
// Disconnect from the reader.
reader.Disconnect();
connection.Close();
}
static void Reader()
{
try
{
// Connect to the reader.
// Change the ReaderHostname constant in SolutionConstants.cs
// to the IP address or hostname of your reader.
reader.Connect(Properties.Resources.ReaderIP);
// Assign the TagOpComplete event handler.
// This specifies which method to call
// when tag operations are complete.
reader.TagOpComplete += OnTagOpComplete;
// Get the default settings
// We'll use these as a starting point
// and then modify the settings we're
// interested in.
Settings settings = reader.QueryDefaultSettings();
double[] Results = ReadXml();
if(Results != null)
{
settings.Antennas.GetAntenna(1).TxPowerInDbm = Results[0];
settings.Antennas.GetAntenna(1).RxSensitivityInDbm = Results[1];
}
// Create a tag read operation for User memory.
TagReadOp readUser = new TagReadOp();
// Read from user memory
readUser.MemoryBank = MemoryBank.User;
// Read two (16-bit) words
readUser.WordCount = 2;
// Starting at word 0
readUser.WordPointer = 0;
// Create a tag read operation for TID memory.
TagReadOp readTid = new TagReadOp();
// Read from TID memory
readTid.MemoryBank = MemoryBank.Tid;
// Read two (16-bit) words
readTid.WordCount = 8;
// Starting at word 0
readTid.WordPointer = 0;
// Add these operations to the reader as Optimized Read ops.
// Optimized Read ops apply to all tags, unlike
// Tag Operation Sequences, which can be applied to specific tags.
// Speedway Revolution supports up to two Optimized Read operations.
settings.Report.OptimizedReadOps.Add(readUser);
settings.Report.OptimizedReadOps.Add(readTid);
// Store the operation IDs for later.
opIdUser = readUser.Id;
opIdTid = readTid.Id;
// Apply the newly modified settings.
reader.ApplySettings(settings);
// Start reading.
reader.Start();
}
catch (OctaneSdkException e)
{
// Handle Octane SDK errors.
Console.WriteLine("Octane SDK exception: {0}", e.Message);
//Console.ReadLine();
}
catch (Exception e)
{
// Handle other .NET errors.
Console.WriteLine("Exception : {0}", e.Message);
}
}
// This event handler will be called when tag
// operations have been executed by the reader.
static void OnTagOpComplete(ImpinjReader reader, TagOpReport report)
{
try
{
userData = tidData = epcData = "";
// Loop through all the completed tag operations
foreach (TagOpResult result in report)
{
// Was this completed operation a tag read operation?
if (result is TagReadOpResult)
{
// Cast it to the correct type.
TagReadOpResult readResult = result as TagReadOpResult;
// Save the EPC
epcData = readResult.Tag.Epc.ToHexString();
// Are these the results for User memory or TID?
if (readResult.OpId == opIdUser)
userData = readResult.Data.ToHexString();
if (readResult.OpId == opIdTid)
tidData = readResult.Data.ToHexString();
if (epcData != "")
{
InsertTag(epcData, tidData, userData, DateTime.Now);
}
readResult = null;
}
}
userData = tidData = epcData = null;
}
catch
{
}
}
static void InsertTag(string EPC, string TID, string User, DateTime TagreadTime)
{
try
{
DataTable Time = _oMySql.Select("SELECT Tijd FROM biketable WHERE EPC = '" + EPC + "';").Tables[0];
DateTime OldTime = Convert.ToDateTime(Time.Rows[0][0]);
TimeSpan diff = TagreadTime.Subtract(OldTime);
string formatForMySql = TagreadTime.ToString("yyyy-MM-dd HH:mm:ss");
if (diff.TotalSeconds > 20)
{
connection.Blink(led1, 100);
if (_oMySql.Select("SELECT Binnen From biketable WHERE EPC = '" + EPC + "';").Tables[0].Rows[0][0].ToString() == "True")
_oMySql.Update("UPDATE biketable SET Tijd = '" + formatForMySql + "', TID = '" + TID + "', UserMem ='" + User + "', Binnen = 'False' WHERE EPC = '" + EPC + "';");
else
_oMySql.Update("UPDATE biketable SET Tijd = '" + formatForMySql + "', TID = '" + TID + "', UserMem ='" + User + "', Binnen = 'True' WHERE EPC = '" + EPC + "';");
}
Time = null;
formatForMySql = null;
}
catch
{
}
}
static double[] ReadXml()
{
double[] Results = new double[2];
try
{
string dir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Power.Load(dir + #"\\Power.XML");
XmlNodeList TXpower = Power.GetElementsByTagName("TXpower");
XmlNodeList RXpower = Power.GetElementsByTagName("RXpower");
Results[0] = System.Convert.ToDouble(TXpower[0].InnerXml);
Results[1] = System.Convert.ToDouble(RXpower[0].InnerXml);
return Results;
}
catch (Exception e)
{
return null;
}
}
}
}
when I run tail -n 1000 /var/log/syslog I get the following messages: note the last messages where it kills the service
http://cl.ly/image/343p2i2y251L
How can I easily detect the memory leak?
Thanks in advance

How to keep logs in C#?

This is a WinForm written in C#.
Lets say I'm generating a random named text file in my selected directory. When the button is clicked teh first time, i write the data contained in the textboxes into that text file. If the user wants to do the same thing with different data in the textboxes then the click on the button should write the new data into the text file without losing the old data. It's like keeping logs, is this possible?
My code is like:
private readonly Random setere = new Random();
private const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private string RandomString()
{
char[] buffer = new char[5];
for (int i = 0; i < 5; i++)
{
buffer[i] = chars[setere.Next(chars.Length)];
}
return new string(buffer);
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult dia = MessageBox.Show("Wanna continue?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dia == DialogResult.Yes)
{
StreamWriter wFile = new StreamWriter("C:\\Users\\Ece\\Documents\\Testings\\" + RandomString() + ".txt");
wFile.WriteLine("Name Surname:" + text1.Text + text2.Text);
wFile.WriteLine("Other:" + text3.Text + text4.Text);
wFile.WriteLine("Money:" + textBox1.Text + " TL.");
wFile.WriteLine("*************************************");
wFile.Close();
}
else
{
return;
}
}
You can append to the text in the file.
See
File.AppendText
using (StreamWriter sw = File.AppendText(pathofFile))
{
sw.WriteLine("This");
sw.WriteLine("is Extra");
sw.WriteLine("Text");
}
where pathofFile is the path to the file to append to.
Have a look at using something like this:
StreamWriter fw = new StreamWriter(#"C:\Logs\MyFile.txt",true);
fw.WriteLine("Some Message" + Environment.Newline);
fw.Flush();
fw.Close();
Hope that helps. See MSDN StreamWriter for more information
Updated: Removed old example
Also if you are trying to create a unique file you can use Path.GetRandomFileName()
Again from the MSDN Books:
The GetRandomFileName method returns a
cryptographically strong, random
string that can be used as either a
folder name or a file name.
UPDATED: Added a Logger class example below
Add a new class to your project and add the following lines (this is 3.0 type syntax so you may have to adjust if creating a 2.0 version)
using System;
using System.IO;
namespace LogProvider
{
//
// Example Logger Class
//
public class Logging
{
public static string LogDir { get; set; }
public static string LogFile { get; set; }
private static readonly Random setere = new Random();
private const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public Logging() {
LogDir = null;
LogFile = null;
}
public static string RandomFileName()
{
char[] buffer = new char[5];
for (int i = 0; i < 5; i++)
{
buffer[i] = chars[setere.Next(chars.Length)];
}
return new string(buffer);
}
public static void AddLog(String msg)
{
String tstamp = Convert.ToString(DateTime.Now.Day) + "/" +
Convert.ToString(DateTime.Now.Month) + "/" +
Convert.ToString(DateTime.Now.Year) + " " +
Convert.ToString(DateTime.Now.Hour) + ":" +
Convert.ToString(DateTime.Now.Minute) + ":" +
Convert.ToString(DateTime.Now.Second);
if(LogDir == null || LogFile == null)
{
throw new ArgumentException("Null arguments supplied");
}
String logFile = LogDir + "\\" + LogFile;
String rmsg = tstamp + "," + msg;
StreamWriter sw = new StreamWriter(logFile, true);
sw.WriteLine(rmsg);
sw.Flush();
sw.Close();
}
}
}
Add this to your forms onload event
LogProvider.Logging.LogDir = "C:\\Users\\Ece\\Documents\\Testings";
LogProvider.Logging.LogFile = LogProvider.Logging.RandomFileName();
Now adjust your button click event to be like the following:
DialogResult dia = MessageBox.Show("Wanna continue?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dia == DialogResult.Yes)
{
StringBuilder logMsg = new StringBuilder();
logMsg.Append("Name Surname:" + text1.Text + text2.Text + Environment.NewLine);
logMsg.Append("Other:" + text3.Text + text4.Text + Environment.NewLine);
logMsg.Append("Money:" + textBox1.Text + " TL." + Environment.NewLine);
logMsg.Append("*************************************" + Environment.NewLine);
LogProvider.Logging.AddLog(logMsg.ToString());
} else
{
return;
}
Now you should only create one file for the entire time that application is running and will log to that one file every time you click your button.
You might want to take a look at log4net and the RollingFileAppender
Sure. Just open the file for appending with something like System.IO.File.AppendText

Categories