Open Cash Drawer via WebUSB JavaScript - webusb

I have a c# application that can open a cash drawer with the Windows Driver Installed. Pretty simple as the driver makes the USB device appears as a serial port:
SerialPort rsPort = new SerialPort(textBox1.Text);
byte[] openCmd = new byte[5];
openCmd[0] = 27;
openCmd[1] = 112;
openCmd[2] = 0;
openCmd[3] = 60;
openCmd[4] = 255;
rsPort.Open();
Thread.Sleep(100);
rsPort.Write(openCmd, 0, 5);
Thread.Sleep(100);
rsPort.Close();
I'm now trying to open the same USB cash Drawer via WebUSB. I've used ZaDig to install a generic USB drive and Chrome can see the USB device; can open the device; however, i'm struggling to send the correct commands.
Here is an image of the config:
Here is my current code:
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript WebUSB</h2>
<button id="myBtn">Try it</button>
<script>
document.getElementById("myBtn").addEventListener("click", talkToDrawer);
async function talkToDrawer() {
try {
let device = await navigator.usb.requestDevice({ filters: [{ vendorId: 1659 }] });
console.log(device);
await device.open(); // Begin a session.
await device.selectConfiguration(1); // Select configuration #1 for the device.
await device.claimInterface(0); // Request exclusive control over interface #2.
result = await device.controlTransferOut({
requestType: 'standard', // tried all combinations: standard / class / vendor
recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
request: 0x27,
value: 0,
index: 1
});
result = await device.controlTransferOut({
requestType: 'standard', // tried all combinations: standard / class / vendor
recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
request: 0x112,
value: 0,
index: 1
});
result = await device.controlTransferOut({
requestType: 'standard', // tried all combinations: standard / class / vendor
recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
request: 0x0,
value: 0,
index: 1
});
result = await device.controlTransferOut({
requestType: 'standard', // tried all combinations: standard / class / vendor
recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
request: 0x60,
value: 0,
index: 1
});
result = await device.controlTransferOut({
requestType: 'standard', // tried all combinations: standard / class / vendor
recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
request: 0x255,
value: 0,
index: 1
});
} catch (error) {
console.log(error);
}
}
</script>
</body>
</html>

Without knowing more about the device there are two errors I see in the code,
In the C# example the command is [27, 112, 0, 60, 255] with the values given in decimal while in the Javascript example the values are given as hexadecimal constants. The appropriate code for constructing the command buffer in Javascript is,
const cmd = new Uint8Array([27, 112, 0, 60, 255]);
Rather than using controlTransferOut() to send the data it is most likely correct to use transferOut() and select endpoint number 3. The Prolific USB-to-serial converter chips implement a protocol similar to the standard USB serial class, which uses a pair of bulk IN and OUT endpoints for the serial data stream,
result = await device.transferOut(3, cmd);
The remaining open question is whether you need to perform any control transfers before you can send this command. Control transfers are used to configure the device and for a USB-to-serial chip this usually involves things like setting baud rate or setting the DCE bit high. When reverse-engineering how to communicate with a USB device I recommend using Wireshark to view the USB traffic from a working driver.
Note, that if you are working with a serial device you should take a the Serial API. There is an experimental implementation available in Chrome behind the chrome://flags/#enable-experimental-web-platform-features flag. This API is designed for applications specifically targeting serial devices and avoids having to re-implement the driver for the USB-to-serial chip.

Related

SMPP send Message received different result in PDU - Confuse In Results

Implemented In Nodejs
using node-smpp library and Selenium SMPPSim Simulator
const smpp = require('smpp');
const session = new smpp.Session({host: 'localhost', port: 1234});
session.on('connect', () => {
isConnected = true;
session.bind_transceiver({
system_id: "SYSTEMID",
password: "PASSWORD",
}, (pdu) => {
if (pdu.command_status == 0) {
console.log('smpp connected !')
}
})
})
//**all pdu listener**
session.on('pdu', (pdu)=>{
console.log(pdu)
})
function sendMessage(from, to, text){
from = `+${from}`
to = `+${to}`
session.submit_sm({
source_addr: from,
destination_addr: to,
short_message: text
}, function(pdu) {
console.log(pdu)
if (pdu.command_status == 0) {
console.log(pdu.message_id);
}
});
}
sendMessage("1111", "2222", "Hello World!")
Output when sendMessage() method call:
PDU {
command_length: 18,
command_id: 2147483652,
command_status: 0,
sequence_number: 2,
command: 'submit_sm_resp',
message_id: '3' }
Here i'm using SMPPSim MO Injection Form
Output: when message sent selenium simulator:
PDU {
command_length: 63,
command_id: 5,
command_status: 0,
sequence_number: 8,
command: 'deliver_sm',
service_type: '',
source_addr_ton: 1,
source_addr_npi: 1,
source_addr: '111111',
dest_addr_ton: 1,
dest_addr_npi: 1,
destination_addr: '222222',
esm_class: 0,
protocol_id: 0,
priority_flag: 0,
schedule_delivery_time: '',
validity_period: '',
registered_delivery: 0,
replace_if_present_flag: 0,
data_coding: 0,
sm_default_msg_id: 0,
short_message: { message: 'Hello from SMPPSim' } }
confused between both result, if message sent using sendMessage() method then why its returning only submit_sm_resp, is it because of local machine ?? or something else ??
need help to understaning this behaviour.
I am not familiar with node-smpp or Selenium SMPPSim Simulator but they still use the SMPP protocol.
Your first output, from "sendMessage()", is the submit_sm_resp which is expected when one calls submit_sm.
However the second response you provided seems to be uncommon. As per the SMPP protocol found here I don't see any response types that natively return all the fields you have listed.
It might be possible that Selenium sends some of the parameters as TLV (Tagged Length Value) parameters or they just return you some extended data set built up on their side. Their documentation or source code might shed more light, if available.
On a side note, don't expect consistency of the SMPP protocol by 3rd party providers (ESMEs) or Short Message Service Center (SMSC). Even when I directly integrated into 4 cell service providers there were small discrepancies between them that required bespoke development.
You are talking about 2 different commands.
Your sendMessage() method sends an SMPP submit_sm ... for which you receive a submit_sm_resp from the simulator.
Injecting an MO from the simulator translates into a deliver_sm sent from the simulator to your app.
submit_sm is sent only from a smpp client(you) to a server(smsc/simulator)
deliver_sm is sent only from a smpp server(smsc/simulator) to a client(you)
It's perfectly normal for the sumbit_sm_resp to contain only those parameters. It is only an ACK/NACK for your submit_sm.
Similar, when the SMSC sents you a deliver_sm, you will respond with a deliver_sm_resp.

ESP32 missing names during BLE scan

I'm running a sample code from ESP32 examples and I'm scanning available BLE devices. I can see device MAC address etc. But for few devices I can't see their names.I am using ESP-WROOM-32 with hardware support checked out directly from their github.When I use LightBlue app for discovery of BLE Devices I can see names for more devices than ESP can. What can I change to see the names correctly? OR Can how can I parse device name from the data I'm receiving?
This callback code
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
Serial.print(" RSSI: ");
Serial.println(advertisedDevice.getRSSI());
}
};
produces this output:
Advertised Device: Name: , Address: 1d:0c:c7:3a:fb:c6, manufacturer data: 4c0009060378c0a81f12, payload: 1073609632
RSSI: -75

Redirect According To Device

In Node I am trying to send response according to device. If it is Web I am sending one kind of respone and If it is Mobile I am sending another kind of response. But I don't know how to find the device and implement condition.
TS
if(mobile){ //How to check whether it is mobile
res.send(res.mobile)
}
else if(web){ //How to check whether it is web
res.send(res.web)
}
else{
res.send(res.error)
}
You can use npm install node-device-detector --production
const DeviceDetector = require('node-device-detector');
const DeviceHelper = require('node-device-detector/helpers');
const detector = new DeviceDetector;
const userAgent = 'Mozilla/5.0 (Linux; Android 5.0; NX505J Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Mobile Safari/537.36';
const result = detector.detect(userAgent);
/* check device type (feature phone, smartphone or phablet) */
DeviceHelper.isMobile(result);
/* check device type is desktop */
DeviceHelper.isDesktop(result);
/* check device type is tablet */
DeviceHelper.isTabled(result);
/* check device type car (side panel in car) */
DeviceHelper.isCar(result);
/* check device type feature phone (push-button telephones) */
DeviceHelper.isFeaturePhone(result);
/* check device type smartphone */
DeviceHelper.isSmartphone(result);
/* check device type phablet */
DeviceHelper.isPhablet(result);
/* check device type game console (xBox, PlayStation, Nintendo etc) */
DeviceHelper.isConsole(result);
/* check device type smart speaker (Alisa, Alexa, HomePod etc) */
DeviceHelper.isSmartSpeaker(result);
/* check device type SmartTV/TV box */
DeviceHelper.isTv(result);
/* check device type portable camera */
DeviceHelper.isCamera(result);
/* portable terminal, portable projector */
DeviceHelper.isPeripheral(result);
/* */
DeviceHelper.isSmartDisplay(result);
/* check device type boxes, blu-ray players */
DeviceHelper.isPortableMediaPlayer(result);
/* check device type watches, headsets */
DeviceHelper.isWearable(result);
Replace userAgent with your Header : req.headers['user-agent'].
More example https://www.npmjs.com/package/node-device-detector

Sending Messages from Leaf Device Downstream device not being handled by IoT Edge running at Transparent Gateway

I have followed all the instruction for setting up a "Downstream Device" to send messages through IoT Edge running in Transparent Gateway. I believe my routing rules are correct, but my Function module is not receiving any of the Messages through the message flow.
These are the instruction I've followed:
https://learn.microsoft.com/en-us/azure/iot-edge/how-to-create-transparent-gateway-linux
I am using 2 Linxu VMs (ubuntu 16.04.5).
IoT Edge Transparent Gateway VM is configured with all the certs properly setup, configured and verified. I've been able to using the openssl tool from the
openssl s_client -connect {my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com:8883 -CAfile /certs/certs/azure-iot-test-only.root.ca.cert.pem -showcerts
Downstream device running on Linux VM with Certs installed and verified. My connection string is as follows:
HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key}=GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com
a. I have verified I get a successful verification of the SSL cert using the openssl tool.
b. I'm using the the following in my downstream device for my connection using the NodeJS SDK
var client = DeviceClient.fromConnectionString(connectionString, Mqtt);
c. I can see the messages showing up at the Azure IoT Hub in the Cloud, but I can't get my module running on the IoT Edge Transparent Gateway to be hit.
Here are my routing rules configured for the edgeHub as specified in "Routing messages from downstream devices" in the sample doc page.
This is what the example docs show:
{ "routes":{ "sensorToAIInsightsInput1":"FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint(\"/modules/ai_insights/inputs/input1\")", "AIInsightsToIoTHub":"FROM /messages/modules/ai_insights/outputs/output1 INTO $upstream" } }
This is what my routing configuration is set to:
"routes": {
"downstreamBatterySensorToBatteryDataFunctionInput1": "FROM /* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint(\"/modules/BatteryDataFunctionModule/inputs/input1\")",
"BatteryDataFunctionModuleToIoTHub": "FROM /messages/modules/BatteryDataFunctionModule/outputs/* INTO $upstream"
}
** Note that I've used by "FROM /* WHERE NOT IS_DEFINED" and "FROM /messages/* WHERE NOT IS_DEFINED"
My module on the IoT Edge is setup as a Function. When I use the out of the box example where the simulator device is another module running on the IoT Edge, then my function is hit correctly. Its only when I'm trying to use a "Downstream Device" that the module is not being triggered.
I have enabled "Debug Logging for the IoT Edge Service" running on my Transparent Gateway.
This is the basic Run method for the Function module:
#r "Microsoft.Azure.Devices.Client"
#r "Newtonsoft.Json"
using System.IO;
using Microsoft.Azure.Devices.Client;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
// Filter messages based on the temperature value in the body of the message and the temperature threshold value.
public static async Task Run(Message messageReceived, IAsyncCollector<Message> output, TraceWriter log)
{
How can I figure out how to get my Module running in IoT Edge to be hit/triggered from a Downstream device?
So, you say you are seeing messages show up in IoT Hub, but not in Edge... A couple of things:
you posted this as your connection string in your node app:
HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key}=GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com
Did you copy/paste this exactly? the reason I ask is that, between the shared access key and the word "GatewayHostName", you have an equals sign and not a semi-colon..
it should be:
HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key};GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com
(note the ';' before GatewayHostName… if you really did have an equals sign there instead of a semicolon, there's no telling what kind of chaos that would cause :-)
Secondly, in your route, you call your module BatteryDataFunctionModule.. just want to make sure that module name is exact, including being case-sensitive. You probably know that, but don't want to assume..
Finally, if the two things above check out, can you add an addition debugging route that sends the 'incoming data' to IoTHub as well..
"FROM /* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream"
so we can make sure the messages are actually making it through iot edge.
There are 2 problems that needed to be addressed to get the Downstream Device to communication
Thanks to #Steve-Busby-Msft I needed to have a semi-colon (;) at the end of the SharedAccessKey and before the GatewayHostName
you posted this as your connection string in your node app: HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key}=GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com
The NodeJS application Downstream Device also has to load up the cert correctly at the 'Application level'.
Notice the section of code for
var edge_ca_cert_path = '[Path to Edge CA certificate]';
Node JS Downstream Application
'use strict';
var fs = require('fs');
var Protocol = require('azure-iot-device-mqtt').Mqtt;
// Uncomment one of these transports and then change it in fromConnectionString to test other transports
// var Protocol = require('azure-iot-device-http').Http;
// var Protocol = require('azure-iot-device-amqp').Amqp;
var Client = require('azure-iot-device').Client;
var Message = require('azure-iot-device').Message;
// 1) Obtain the connection string for your downstream device and to it
// append this string GatewayHostName=<edge device hostname>;
// 2) The edge device hostname is the hostname set in the config.yaml of the Edge device
// to which this sample will connect to.
//
// The resulting string should look like the following
// "HostName=<iothub_host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>;GatewayHostName=<edge device hostname>"
var connectionString = '[Downstream device IoT Edge connection string]';
// Path to the Edge "owner" root CA certificate
var edge_ca_cert_path = '[Path to Edge CA certificate]';
// fromConnectionString must specify a transport constructor, coming from any transport package.
var client = Client.fromConnectionString(connectionString, Protocol);
var connectCallback = function (err) {
if (err) {
console.error('Could not connect: ' + err.message);
} else {
console.log('Client connected');
client.on('message', function (msg) {
console.log('Id: ' + msg.messageId + ' Body: ' + msg.data);
// When using MQTT the following line is a no-op.
client.complete(msg, printResultFor('completed'));
// The AMQP and HTTP transports also have the notion of completing, rejecting or abandoning the message.
// When completing a message, the service that sent the C2D message is notified that the message has been processed.
// When rejecting a message, the service that sent the C2D message is notified that the message won't be processed by the device. the method to use is client.reject(msg, callback).
// When abandoning the message, IoT Hub will immediately try to resend it. The method to use is client.abandon(msg, callback).
// MQTT is simpler: it accepts the message by default, and doesn't support rejecting or abandoning a message.
});
// Create a message and send it to the IoT Hub every second
var sendInterval = setInterval(function () {
var windSpeed = 10 + (Math.random() * 4); // range: [10, 14]
var temperature = 20 + (Math.random() * 10); // range: [20, 30]
var humidity = 60 + (Math.random() * 20); // range: [60, 80]
var data = JSON.stringify({ deviceId: 'myFirstDownstreamDevice', windSpeed: windSpeed, temperature: temperature, humidity: humidity });
var message = new Message(data);
message.properties.add('temperatureAlert', (temperature > 28) ? 'true' : 'false');
console.log('Sending message: ' + message.getData());
client.sendEvent(message, printResultFor('send'));
}, 2000);
client.on('error', function (err) {
console.error(err.message);
});
client.on('disconnect', function () {
clearInterval(sendInterval);
client.removeAllListeners();
client.open(connectCallback);
});
}
};
// Provide the Azure IoT device client via setOptions with the X509
// Edge root CA certificate that was used to setup the Edge runtime
var options = {
ca : fs.readFileSync(edge_ca_cert_path, 'utf-8'),
};
client.setOptions(options, function(err) {
if (err) {
console.log('SetOptions Error: ' + err);
} else {
client.open(connectCallback);
}
});

NFC Tag not working on Gear S2

Im trying to read the data in NFC tag using web development. I am able to detect tags from emulator, but on Gear S2 it does not work.
I have given all the privileges in config.xml
<tizen:privilege name="http://tizen.org/privilege/nfc.common"/>
<tizen:privilege name="http://tizen.org/privilege/nfc.tag"/>
<tizen:privilege name="http://tizen.org/privilege/bluetooth.admin"/>
<tizen:privilege name="http://tizen.org/privilege/nfc.admin"/>
<tizen:privilege name="http://tizen.org/privilege/nfc.cardemulation"/>
I am using whiztags NFC tags with Gear S2, they are working with my mobile(Nexus 5).
I have switched on the NFC in my watch, but still they don't respond to tags.
Code:
var adapter = tizen.nfc.getDefaultAdapter();
adapter.setPowered(
true, // Enable NFC adapter
function () {console.log('Power on success');}, // Handle succes
function () {console.log('Power on failed');}); // Handle failure
//
var onSuccessCB = {onattach : function(nfcTag) {
console.log("NFC Tag's type is " + nfcTag.type);
navigator.vibrate([600, 100, 300, 200, 0]);
for(var i in nfcTag.properties) {
console.log("key:" + i + " value:" + nfcTag.properties[i]);
}
}, ondetach : function() {
console.log("NFC Tag is detached");
}};
adapter.setTagListener(onSuccessCB);
The NFC API is optional for both Tizen mobile and wearable profiles, which means that it may not be supported in all mobile and wearable devices. The NFC API is supported on the Tizen wearable Emulator, but not on the Tizen mobile Emulator.
Please go through this link for more details.
I've seen some other people having same issue. Have a look on this link too.

Resources