How to send data from barcode scanner MT2070 - bluetooth

i've got problems with the barcode scanner MT2070 from Motorola. I use the EMDK 2.6 for .NET(Update 2) to create strings from the scanned barcode, then transmit them to the host pc. But the transmit failed.
The MT2070 run with Windows CE5.0 and is connected over bluetooth to the cradle STB2078. But everytime i get "send failed" and the ResultCode is "E_INCORRECT_MODE".
The problem is that dont understand what they mean with "INCORRECT_MODE" i set it to DECODE and by RawData what is mean with source?
ScannerServicesClient scannerServices;
scannerServices = new ScannerServicesClient();
SCANNERSVC_MODE mode;
if(scannerServices.Connect(true))
{
Logger("start service with decode rights"); // primitiv method to see what happen
scannerServices.GetMode(out mode);
if (mode != SCANNERSVC_MODE.SVC_MODE_DECODE)
{
mode = SCANNERSVC_MODE.SVC_MODE_DECODE;
if (scannerServices.SetMode(mode) != RESULTCODE.E_OK)
{
Logger("cant set mode: " + mode.ToString());
}
}
// wanna know which connection is use
string connection = "";
switch (scannerServices.HostParameters.CurrentConnection)
{
case SCANNERSVC_DATA_CONNECTION.NO_CONNECTION:
connection = "Not connected";
break;
case SCANNERSVC_DATA_CONNECTION.BLUETOOTH:
connection = scannerServices.HostParameters.BluetoothConnection.ToString();
break;
case SCANNERSVC_DATA_CONNECTION.RS232:
connection = scannerServices.HostParameters.RS232Connection.ToString();
break;
case SCANNERSVC_DATA_CONNECTION.USB_CABLE:
connection = scannerServices.HostParameters.USBConnection.ToString();
break;
}
Logger(connection);
ScannerHostParameters scnHost = new ScannerHostParameters(scannerServices);
//example hello
string input = "hello"; //what should send
byte[] output = new byte[input.Length]; //field with converted data
byte source = 0; //<-- what mean source? i sum all byte-value but this cant be correct
for (int i = 0; i < input.Length; ++i)
{
output[i] = Convert.ToByte(input[i]);
source += output[i];
}
RawData rawData = new RawData(output, input.Length, source);
//RawParameters rawParam = new RawParameters();
//rawParam.BaudRate = RawParameters.RawBaudRates.RAWSERIAL_9600;
//rawParam.Type = RawParameters.RawHostType.Auto;
RESULTCODE result = scannerServices.SendRawData(rawData, 2000);
if(result == RESULTCODE.E_OK)
{
Logger("successful send");
}
else
{
Logger("Send failed: " + result.ToString());
}
Logger("ScannerService kill");
scannerServices.Disconnect();
}
Logger("\n");
scannerServices.Dispose();
scannerServices = null;
Thanks for your help! (and sorry for my english)

At some point (somewhere where you're setting the mode - I do it right after setting the mode) you'll want to do this:
//set raw mode
if (RESULTCODE.E_OK != scannerServices.SetAttributeByte((ushort)ATTRIBUTE_NUMBER.ATT_MIA_HOSTNUM, (byte)ENUM_HOSTS.HOST_RAW))
{
throw new Exception("Can't set RAW mode");
scannerServices.Disconnect();
scannerServices.Dispose();
return;
}
Where you have:
RawData rawData = new RawData(output, input.Length, source);
you can leave source as 0:
RawData rawData = new RawData(output, input.Length, 0);
Unfortunately I'm not the greatest when it comes to programming so I've only managed to stumble my way through getting my scanner to work. The documentation isn't great, in fact I find it severly lacking. Even the people at Motorola don't seem to know much about it or how to program it. I've been given misinformation by them on on at least one point.
I use the CDC COM Port Emulation mode for the scanner so that it shows up under Ports in Device Manager (I need the scanner to work with an old program we have which uses COM ports). A driver is also needed for this.
Depending on how you're using the scanner, the above may or may not work.

Related

Export Rich Text to plain text c#

Good day to Stackoverflow community,
I am in need of some expert assistance. I have an MVC4 web app that has a few rich text box fields powered by TinyMCE. Up until now the system is working great. Last week my client informed me that they want to export the data stored in Microsoft SQL to Excel to run custom reports.
I am able to export the data to excel with the code supplied. However it is exporting the data in RTF rather than Plain text. This is causing issues when they try to read the content.
Due to lack of knowledge and or understanding I am unable to figure this out. I did read that it is possible to use regex to do this however I have no idea how to implement this. So I turn to you for assistance.
public ActionResult ExportReferralData()
{
GridView gv = new GridView();
gv.DataSource = db.Referrals.ToList();
gv.DataBind();
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=UnderwritingReferrals.xls");
Response.ContentType = "application/ms-excel";
Response.AddHeader("Content-Type", "application/vnd.ms-excel");
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
gv.RenderControl(htw);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
return RedirectToAction("Index");
}
I would really appreciate any assistance. and thank you in advance.
I have looked for solutions on YouTube and web forums with out any success.
Kind Regards
Francois Muller
One option you can perform is to massage the Data you write to the XML file.
For example, idenfity in your string and replace it with string.Empty.
Similarly can be replaced with string.Empty.
Once you have identified all the variants of the Rich Text HTML tags, you can just create a list of the Tags, and inside a for FOR loop replace each of them with a suitable string.
Did you try saving the file as .xslx and sending over to the client.
The newer Excel format might handle the data more gracefully?
Add this function to your code, and then you can invoke the function passing it in the HTML string. The return output will be HTML free.
Warning: This does not work for all cases and should not be used to process untrusted user input. Please test it with variants of your input string.
public static string StripTagsCharArray(string source)
{
char[] array = new char[source.Length];
int arrayIndex = 0;
bool inside = false;
for (int i = 0; i < source.Length; i++)
{
char let = source[i];
if (let == '<')
{ inside = true; continue; }
if (let == '>') { inside = false; continue; }
if (!inside) { array[arrayIndex] = let; arrayIndex++; }
}
return new string(array, 0, arrayIndex);
}
So I managed to resolve this issue by changing the original code as follow:
As I'm only trying to convert a few columns, I found this to be working well. This will ensure each records is separated by row in Excel and converts the Html to plain text allowing users to add column filters in Excel.
I hope this helps any one else that has a similar issue.
GridView gv = new GridView();
var From = RExportFrom;
var To = RExportTo;
if (RExportFrom == null || RExportTo == null)
{
/* The actual code to be used */
gv.DataSource = db.Referrals.OrderBy(m =>m.Date_Logged).ToList();
}
else
{
gv.DataSource = db.Referrals.Where(m => m.Date_Logged >= From && m.Date_Logged <= To).OrderBy(m => m.Date_Logged).ToList();
}
gv.DataBind();
foreach (GridViewRow row in gv.Rows)
{
if (row.Cells[20].Text.Contains("<"))
{
row.Cells[20].Text = Regex.Replace(row.Cells[20].Text, "<(?<tag>.+?)(>|>)", " ");
}
if (row.Cells[21].Text.Contains("<"))
{
row.Cells[21].Text = Regex.Replace(row.Cells[21].Text, "<(?<tag>.+?)(>|>)", " ");
}
if (row.Cells[22].Text.Contains("<"))
{
row.Cells[22].Text = Regex.Replace(row.Cells[22].Text, "<(?<tag>.+?)(>|>)", " ");
}
if (row.Cells[37].Text.Contains("<"))
{
row.Cells[37].Text = Regex.Replace(row.Cells[37].Text, "<(?<tag>.+?)(>|>)", " ");
}
if (row.Cells[50].Text.Contains("<"))
{
row.Cells[50].Text = Regex.Replace(row.Cells[37].Text, "<(?<tag>.+?)(>|>)", " ");
}
}
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=Referrals " + DateTime.Now.ToString("dd/MM/yyyy") + ".xls");
Response.ContentType = "application/ms-excel";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.AddHeader("Content-Type", "application/vnd.ms-excel");
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
gv.RenderControl(htw);
//This code will export the data to Excel and remove all HTML Tags to pass everything into Plain text.
//I am using HttpUtility.HtmlDecode twice as the first instance changes null values to "Â" the second time it will run the replace code.
//I am using Regex.Replace to change the headings to more understandable headings rather than the headings produced by the Model.
Response.Write(HttpUtility.HtmlDecode(sw.ToString())
.Replace("Cover_Details", "Referral Detail")
.Replace("Id", "Identity Number")
.Replace("Unique_Ref", "Reference Number")
.Replace("Date_Logged", "Date Logged")
.Replace("Logged_By", "File Number")
.Replace("Date_Referral", "Date of Referral")
.Replace("Referred_By", "Name of Referrer")
.Replace("UWRules", "Underwriting Rules")
.Replace("Referred_To", "Name of Referrer")
);
Response.Flush();
Response.End();
TempData["success"] = "Data successfully exported!";
return RedirectToAction("Index");
}

device.GattServices returns an empty set for BLE devices on a Windows universal app

I am using the sample from Microsoft. When an advertisement is received I am calling
BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
and then
device.GattServices()
but that always returns an empty list. Why is this happening? I have found no answer whatsoever.
If you want this to work by using advertisement watcher, you need to target the windows 10 creators update(10.0;Build 15063) and use the latest SDK, otherwise you will have to pair the device first.
To get the GattServices, first check if the device is not null.
Then use:
var serviceResult = await bluetoothLeDevice.GetGattServicesAsync();
if (serviceResult.Status == GattCommunicationStatus.Success)
{
//Do something with servivicResult list
}
But there is a catch; It can be that serviceResult.Status returns success, but not all or no services have been found yet.
My solution is to put it in a loop with a short delay and try it a few times until serviceResult count stays the same.
I wanted to put more explanation in my comment, but something went wrong and cannot edit my comment so I will add it as an answer.
I had exactly the same problem. for some reason you have to initialize your BLEdevice as null.
private BluetoothLEDevice device = null;
Also to prevent that you advertisementWatcher is setting your device over and over, use an if statement to set it only when the divice is null,
if (device == null)
{
device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
}
or if you want to set multiple devices than add them to a collection and make sure each device is only added once.
This is my working code :
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher,
BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
BluetoothLEAdvertisementType advertisementType = eventArgs.AdvertisementType;
short rssi = eventArgs.RawSignalStrengthInDBm;
string localName = eventArgs.Advertisement.LocalName;
string manufacturerDataString = "";
var manufacturerSections = eventArgs.Advertisement.ManufacturerData;
if (manufacturerSections.Count > 0)
{
// Only print the first one of the list
var manufacturerData = manufacturerSections[0];
var data = new byte[manufacturerData.Data.Length];
using (var reader = DataReader.FromBuffer(manufacturerData.Data))
{
reader.ReadBytes(data);
}
manufacturerDataString = string.Format("0x{0}: {1}",
manufacturerData.CompanyId.ToString("X"),
BitConverter.ToString(data));
}
string res = string.Format("type={0}, rssi={1}, name={2}, manufacturerData=[{3}]",
advertisementType.ToString(),
rssi.ToString(),
localName,
manufacturerDataString);
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
textBoxWatcher.Text = res;
});
if (device == null)
{
device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
if (device != null)
{
var deviceInfo = device.DeviceInformation;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (device.Name != string.Empty)
{
//ResultCollection is a observable observable collection of blueutooth devices
// to bind to a listvieuw,it is not needed!
ResultCollection.Add(new BleDevice(device));
if (deviceInfo.Name == "HMSoft")
{
if (ResultCollection[0] is BleDevice bleDevice)
{
BleDeviceId = bleDevice.Id;
SelectedBleDeviceName = bleDevice.Name;
}
Connect();
}
}
});
}
}

visual c++ Serialport class handling data very slow

I'm trying to handle data recieved at about 1Hz from a robot through a serialport (bluetooth connection). I will recieve data with different headers determining what data will be recieved and what the expected length of the message is.
for example:
Header: sensorvalues (0x32) -> expected length 11 incl. header.
First i want to check if the byte is a header and if thats the case extract the expected length (in bytes).
I am using vc++ and the serialport class in the GUI.
The "seirialport->read(buffer, 0, expected length)" is very slow and not very reliable. I found some tips at http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport but the buffer still builds up to the point where I have about 200 bytes in the buffer, which is not very good when i need live sensorvalues displayed on the GUI.
The key parts of my code are:
System::Void MyForm::serialPort1_DataReceived_1(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e) {
if (serialPort1->BytesToRead > 0){
if (write_position == 0){
serialPort1->BaseStream->ReadAsync(data_recieved_buffer, 0, 1);
header = data_recieved_buffer[0];
if (this->InvokeRequired){
myrecievedata_delegate^ d = gcnew myrecievedata_delegate(&myrecievedata);
this->Invoke(d, gcnew array < Object^ > {'h'});
}
else
{
myrecievedata('h');
}
}
else if (this->serialPort1->BytesToRead > expected_length - 1)
{
serialPort1->BaseStream->ReadAsync(data_recieved_buffer, 0, expected_length - 1);
if (this->InvokeRequired){
myrecievedata_delegate^ d = gcnew myrecievedata_delegate(&myrecievedata);
this->Invoke(d, gcnew array < Object^ > {'b'});
}
else
{
myrecievedata('b');
}
}
else{
return;
}
}
and the recieved data is sent to
System::Void MyForm::myrecievedata(char status){
if (status == 'h'){
handleheader(header);
}
else if (status == 'b'){
handlebyte();
}
Is the problem at the serialport_datarecieved event? I can only think of invoke (which I have very little knowledge about) being the problem, still keeping the work in the serialport thread.
If that is the case how would I make sure that the data is handled in a different thread?
Thanks in advance!

Sending strings over Serial to Arduino

I'm currently experimenting with sending a string to my Arduino Yun and trying to get it to reply back depending on what I send it.
I picked up a framework of some code here and have been experimenting with it but apart from the serial monitor displaying 'ready' I can't make it go any further.
The code is:
//declace a String to hold what we're inputting
String incomingString;
void setup() {
//initialise Serial communication on 9600 baud
Serial.begin(9600);
while(!Serial);
//delay(4000);
Serial.println("Ready!");
// The incoming String built up one byte at a time.
incomingString = "";
}
void loop () {
// Check if there's incoming serial data.
if (Serial.available() > 0) {
// Read a byte from the serial buffer.
char incomingByte = (char)Serial.read();
incomingString += incomingByte;
// Checks for null termination of the string.
if (incomingByte == '\0') {
// ...do something with String...
if(incomingString == "hello") {
Serial.println("Hello World!");
}
incomingString = "";
}
}
}
Can anyone point me in the right direction?
Thanks
I suspect the problem is that you're adding the null terminator onto the end of your string when you do: incomingString += incomingByte. When you're working with string objects (as opposed to raw char * strings) you don't need to do that. The object will take care of termination on its own.
The result is that your if condition is effectively doing this: if ("hello\0" == "hello") .... Obviously they're not equal, so the condition always fails.
I believe the solution is just to make sure you don't append the byte if it's null.
Try This:
String IncomingData = "";
String Temp = "";
char = var;
void setup()
{
Serial.begin(9600);
//you dont have to use it but if you want
// if(Serial)
{
Serial.println("Ready");
}
//or
while(!Serial)
{delay(5);}
Serial.println("Ready");
void loop()
{
while(Serial.available())
{
var = Serial.read();
Temp = String(var);
IncomingData+= Temp;
//or
IncomingData.concat(Temp);
// you can try
IncomindData += String(var);
}
Serial.println(IncomingData);
IncomingData = "";
}

Windows + SetCommState how to set RTS?

I have an application that has been ported up from VC++ 6 where it worked fine. The code in question uses the WinAPI for a serial device driver. When ported to VS2012, the same code behaves rather differently.
Create a DCB, set SetCommState and go. CTS was set high, RTS was set high and you were on your way.
Since ported up to VS2012 Pro MFC, I am finding that it sets up SetCommState the same with or without hardware flow control:
memset(&dcb, 0x00, sizeof(dcb));
dcb.DCBlength = sizeof(DCB);
// Must be TRUE, only binary mode in Windows
dcb.fBinary = TRUE;
dcb.fParity = FALSE;
// XOn/XOff disabled
dcb.fTXContinueOnXoff = TRUE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.XonLim = 0;
dcb.XoffLim = 0;
dcb.XonChar = 0;
dcb.XoffChar = 0;
// Misc Stuff
dcb.EofChar = 0;
dcb.EvtChar = 0;
dcb.ErrorChar = 0;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fAbortOnError = FALSE;
// 8N1 Setup
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
// Baud Rate
if (dwBaudRate == BAUD_115200)
{
dcb.BaudRate = CBR_115200;
}
else
{
dcb.BaudRate = CBR_38400;
}
// setup hardware flow control
if (bHardware == eYesHardwareFlowControl)
{
// ================ FLOW CONTROL ON ================
switch (bIgnoreCTS)
{
case eIgnoreCTS:
dcb.fOutxCtsFlow = FALSE;
break;
case eEnableCTS:
dcb.fOutxCtsFlow = TRUE;
break;
default:
case eCTSDecideLater:
dcb.fOutxCtsFlow = TRUE;
break;
}
// DSR Flow Control
dcb.fDsrSensitivity = FALSE;
dcb.fOutxDsrFlow = FALSE;
// <<Hardware flow control On(TRUE) Off(FALSE)>>
dcb.fDtrControl = DTR_CONTROL_ENABLE;
// <<Hardware flow control On(_HANDSHAKE) Off(_ENBLE)>>
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
}
else
{
// ================ FLOW CONTROL OFF ================
switch (bIgnoreCTS)
{
case eIgnoreCTS:
dcb.fOutxCtsFlow = FALSE;
break;
case eEnableCTS:
dcb.fOutxCtsFlow = TRUE;
break;
default:
case eCTSDecideLater:
dcb.fOutxCtsFlow = FALSE;
break;
}
// DSR Flow Control
dcb.fDsrSensitivity = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
}
if (SetCommState(m_hIdComDev, &dcb) == WINDOWS_API_ZERO_IS_BAD)
{
dwLastError = GetLastError();
}
At this point, I have set up the DCB, cleared it. I don't read in the previous state is I don't want to trust any garbage of anyone that previously used the port. Then I set up every field with Baud, Flow Control and CTS Ignore being the only optional items.
So, what I've noticed is that I can create situation where the Device and the PC don't communicate. Now, mind you, they always did before and they always work with Hyperterminal, ProComm, TeraTerm and so on. What I can see is that when these comm programs start (and the old VC++ 6 App), when the device is created and set up, RTS is immediately set high.
Now, my App, once the DCB is set up, SetCommState called; RTS is always LOW. And when this happens, communications is toast.
I want to FORCE RTS to be high and thought I could do it like this:
if (EscapeCommFunction(m_hIdComDev, CLRRTS) == WINDOWS_API_ZERO_IS_BAD)
{
dwLastError = GetLastError();
}
if (EscapeCommFunction(m_hIdComDev, SETRTS) == WINDOWS_API_ZERO_IS_BAD)
{
dwLastError = GetLastError();
}
But this fails, it gives an error 87 (parameter error). And I cannot quite figure it out. Even if I just SETRTS high only, it fails.
Any ideas on how I can force Windows to set RTS high after I setup the comm parameters in the DCB?
Well it turned out to be a device problem and not a windows problem at all.

Resources