How do I connect to a Clover mini device using ONLY node? - javascript

I'm fairly new to Node, and I'm trying to connect to a Clover Mini device through a websocket using the API provided by Clover.
I've tried modifying the example code below to work using only node, but when I open it in node nothing happens. (No errors, just nothing happens at all)
It works in Chrome just fine, so what's missing?
https://github.com/clover/remote-pay-cloud
var $ = require('jQuery');
var clover = require("remote-pay-cloud");
var log = clover.Logger.create();
var connector = new clover.CloverConnectorFactory().createICloverConnector({
"oauthToken": "1e7a9007-141a-293d-f41d-f603f0842139",
"merchantId": "BBFF8NBCXEMDV",
"clientId": "3RPTN642FHXTX",
"remoteApplicationId": "com.yourname.yourapplication:1.0.0-beta1",
"deviceSerialId": "C031UQ52340015",
"domain": "https://sandbox.dev.clover.com/"
});
var ExampleCloverConnectorListener = function(cloverConnector) {
clover.remotepay.ICloverConnectorListener.call(this);
this.cloverConnector = cloverConnector;
};
ExampleCloverConnectorListener.prototype = Object.create(clover.remotepay.ICloverConnectorListener.prototype);
ExampleCloverConnectorListener.prototype.constructor = ExampleCloverConnectorListener;
ExampleCloverConnectorListener.prototype.onReady = function (merchantInfo) {
var saleRequest = new clover.remotepay.SaleRequest();
saleRequest.setExternalId(clover.CloverID.getNewId());
saleRequest.setAmount(10000);
this.cloverConnector.sale(saleRequest);
};
ExampleCloverConnectorListener.prototype.onVerifySignatureRequest = function (request) {
log.info(request);
this.cloverConnector.acceptSignature(request);
};
ExampleCloverConnectorListener.prototype.onConfirmPaymentRequest = function (request) {
this.cloverConnector.acceptPayment(request.payment);
};
ExampleCloverConnectorListener.prototype.onSaleResponse = function (response) {
log.info(response);
connector.dispose();
if(!response.getIsSale()) {
console.error("Response is not an sale!");
console.error(response);
}
};
var connectorListener = new ExampleCloverConnectorListener(connector);
connector.addCloverConnectorListener(connectorListener);
connector.initializeConnection();

After getting into contact with the developers at clover, their documentation had some errors. For other users sake here is the link to that issue on their gitub as well as some example code.
link to github issue
const endpoint = "ws://yourip:yourport/remote_pay";
var webSocketFactory = function () {
let webSocketOverrides = {
createWebSocket: function () {
// To support self-signed certificates you must pass rejectUnauthorized = false.
// https://github.com/websockets/ws/blob/master/examples/ssl.js
let sslOptions = {
rejectUnauthorized: false
};
// Use the ws library by default.
return new WebSocket(endpoint, sslOptions);
}
}
return Object.assign(new clover.CloverWebSocketInterface(endpoint), webSocketOverrides);
};
var ExampleWebsocketPairedCloverDeviceConfiguration = function () {
clover.WebSocketPairedCloverDeviceConfiguration.call(this,
endpoint, // endpoint
"com.cloverconnector.javascript.simple.sample:1.4", // Application Id
"Javascript Simple Sample", // posName
"Register_1", // serialNumber
null, // authToken().get(
webSocketFactory,
new clover.ImageUtil());
};

Related

Javascript working in Chrome, working in firefox locally, but not after deployment

This is part of a Spark Java app, but the error is happening in this JS part. The relevant code is as follows:
const addErrBox = async () => {
const controls = document.querySelector(".pure-controls");
const errBox = document.createElement("p");
errBox.setAttribute("id", "errBox");
errBox.setAttribute("style", "color:red");
errBox.innerHTML = "Short URL not valid or already in use!";
controls.appendChild(errBox);
}
const submitForm = () => {
const form = document.forms.namedItem("new-url-form");
const longUrl = form.elements["longUrl"];
const shortUrl = form.elements["shortUrl"];
const url = `/api/new`;
fetch(url, {
method: "POST",
body: `${longUrl.value};${shortUrl.value}`
})
.then((res) => {
if (!res.ok) {
if (document.getElementById("errBox") == null) {
addErrBox();
}
}
else {
document.getElementById("errBox")?.remove();
longUrl.value = "";
shortUrl.value = "";
refreshData();
}
});
};
(async () => {
await refreshData();
const form = document.forms.namedItem("new-url-form");
form.onsubmit = e => {
e.preventDefault();
submitForm();
}
})();
Basically, "/api/new" checks for validity of input, adds the data to database if valid and prints error otherwise. Now, when the input is valid, it seems to work. The "/api/new" code is in Java, which seems to work properly as well since I do get a 400 error. All of it works properly when built inside a docker locally, but when accessed over internet using Nginx reverse proxy, it stops working inside firefox. Chrome still works. I'm not sure what's happening.
The code for "/api/new" is this:
public static String addUrl(Request req, Response res) {
var body = req.body();
if (body.endsWith(";")) {
body = body + "$";
}
var split = body.split(";");
String longUrl = split[0];
if (split[1].equals("$")) {
split[1] = Utils.randomString();
}
String shortUrl = split[1];
shortUrl = shortUrl.toLowerCase();
var shortUrlPresent = urlRepository
.findForShortUrl(shortUrl);
if (shortUrlPresent.isEmpty() && Utils.validate(shortUrl)) {
return urlRepository.addUrl(longUrl, shortUrl);
} else {
res.status(HttpStatus.BAD_REQUEST_400);
return "shortUrl not valid or already in use";
}
}
Update: it suddenly started working, without any change on the server side. I think it was some kind of issue with caching, either in firefox, cloudflare or Nginx's part.

window.onload starts before indexed db statements

Good afternoon all,
My issue is javascript related, I have made one function called checkflights, a series of statements to open an indexeddb database and one window.onload that triggers checkflights.
It seems that the window.onload triggers before the open database statements and therefor the checkflights function does not run properly as the db is considered null.
Any solution? code here below. Thank you in advance for your support.
var db = null
const request = indexedDB.open('MyDataBase', '1')
//on upgrade needed
request.onupgradeneeded = e => {
var db = e.target.result
/* note = {
title: "note1",
text: "this is a note"
}*/
const myFlights = db.createObjectStore("my_flight", {
keyPath: "flightid"
})
}
request.onsuccess = e => {
var db = e.target.result
}
request.onerror = e => {
alert(`error: ${e.target.error} was found `)
}
window.onload = function () {
checkFlights()
}
function checkFlights() {
const tx = db.transaction("my_flight", "readonly");
// var objectStore = transaction.objectStore('my_flight');
const mesVols=tx.objectStore("my_flight")
var countRequest = mesVols.count();
countRequest.onsuccess = function() {
console.log(countRequest.result);
if(countRequest.result>0 && window.navigator.onLine){
sendFlights()
notify("Flights sent to server")
}
}
}
You are redeclaring db from the outer scope, by using var again.
When using var in a local scope, you are not affecting the variable from the outer scope and actually creating a new local db variable.
var db = null
const request = indexedDB.open('MyDataBase', '1');
//on upgrade needed
request.onupgradeneeded = e => {
db = e.target.result
/* note = {
title: "note1",
text: "this is a note"
}*/
const myFlights = db.createObjectStore("my_flight", {
keyPath: "flightid"
})
}
request.onsuccess = e => {
db = e.target.result
}
request.onerror = e => {
alert(`error: ${e.target.error} was found `)
}
window.onload = function () {
checkFlights()
}
function checkFlights() {
const tx = db.transaction("my_flight", "readonly");
// var objectStore = transaction.objectStore('my_flight');
const mesVols=tx.objectStore("my_flight")
var countRequest = mesVols.count();
countRequest.onsuccess = function() {
console.log(countRequest.result);
if(countRequest.result>0 && window.navigator.onLine){
sendFlights()
notify("Flights sent to server")
}
}
}
As suggested by #Kinglish in a comment above, you might need to wait for the request to be handled. IndexedDB does not return a promise but you could write an async/await wrapper yourself around the top part or consider using a library like https://github.com/jakearchibald/idb that will Promisify indexedDB.

node js self this call method

I'm working on NodeJS and I have this module:
Manager.js
with this code (this is not all the code...):
//
// Object Manager
function Manager(params) {
client = new ModbusRTU();
}
//connessione alla seriale per lettura modbus
Manager.prototype.connectClient = function(){
// try to connect
client.connectRTUBuffered ("/dev/ttyS3", { baudRate: 19200 })
.then(function()
{
mbsState = MBS_STATE_GOOD_CONNECT;
mbsStatus = "Connected, wait for reading...";
console.log(mbsStatus);
})
.catch(function(e)
{
mbsState = MBS_STATE_FAIL_CONNECT;
mbsStatus = e.message;
console.log("Error:"+e);
});
client.setTimeout (20);
}
//read data
Manager.prototype.readData = function(){
var self = this;
client.setID(2);
// try to read data
client.readCoils (0, 7, function(error,data){
if(!error){
self.checkEmergency();
}
});
}
//emergency
Manager.prototype.checkEmergency= function(){
}
exports.Manager=Manager;
client part of code is about a modbus application.
When I try to call "self.checkEmergency()" from readData, I have this error:
"self.checkEmergency() is not a function"
Why?
The method readData is called inside a method like this:
Manager.prototype.caller= function(){
var self = this;
self.readData();
}
I also have used self to pass the object to the callback...
Any idea?

combining knockout js with truffle app.js

I am learning on how to create a voting app with truffle and rendering on the screen everything goes well. So now I don't want to use vanilla js but want to add a framework to it, called knockout.js
I tried it in everyway but for some reason the knockout js is not working inside the app.js file given by truffle framework.
Here is the piece of code that works but it looks like the observables don't really work at all.
function AppViewModel() { // Loading the appviewmodel
var self = this;
App = {
web3Provider: null,
contracts: {},
account: '0x0',
init: function() {
return App.initWeb3();
},
initWeb3: function() {
// TODO: refactor conditional
if (typeof web3 !== 'undefined') {
// If a web3 instance is already provided by Meta Mask.
App.web3Provider = web3.currentProvider;
web3 = new Web3(web3.currentProvider);
} else {
// Specify default instance if no web3 instance provided
App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
web3 = new Web3(App.web3Provider);
}
return App.initContract();
},
initContract: function() {
$.getJSON("Election.json", function(election) {
// Instantiate a new truffle contract from the artifact
App.contracts.Election = TruffleContract(election);
// Connect provider to interact with contract
App.contracts.Election.setProvider(App.web3Provider);
return App.render();
});
},
render: function() {
var electionInstance;
var loader = $("#loader");
var content = $("#content");
var name = ko.observable('masnad'); //added the observable!
loader.show();
content.hide();
// Load account data
web3.eth.getCoinbase(function(err, account) {
if (err === null) {
App.account = account;
$("#accountAddress").html("Your Account: " + account);
}
});
// Load contract data
App.contracts.Election.deployed().then(function(instance) {
electionInstance = instance;
return electionInstance.candidatesCount();
}).then(function(candidatesCount) {
var candidatesResults = $("#candidatesResults");
candidatesResults.empty();
for (var i = 1; i <= candidatesCount; i++) {
electionInstance.candidates(i).then(function(candidate) {
console.log(candidate);
var id = candidate[0];
var name = candidate[1];
var voteCount = candidate[2];
// Render candidate Result
var candidateTemplate = "<tr><th>" + id + "</th><td>" + name + "</td><td>" + voteCount + "</td></tr>"
candidatesResults.append(candidateTemplate);
});
}
loader.hide();
content.show();
}).catch(function(error) {
console.warn(error);
});
}
};
}
$(document).ready(function () {
ko.applyBindings(new AppViewModel(), document.getElementById('vote_app'));
App.init();
});
I have attached comments on the above code where the knockout js observables are used but unfortunetly in the HTML file they don't exist.
Here is the piece of code on the HTML file that should work..
<h1 class="text-center"><span data-bind="text:name"></span></h1>
Knockout is not able to find the observable because you initialized it as a local variable, i.e., as var name = ...
Instead, you need to make it a property of the viewModel instance using the this operator, because that's how you expose it to the HTML.
Try replacing that line with
self.name = ko.observable('masnad');

IndexedDB via Lawnchair gets larger with every save

I am using Lawnchair.js on a mobile app I am building at work targeting iOS, Android, and Windows phones. My question is I have a relatively simple function(see below), that reads data from an object and saves it in the indexeddb database. It's about 4MB of data and on the first go round when I inspect in Internet explorer(via internet options), I can see the database is about 7MB. If I reload the page and re-run the same function with the same data, it increases to 14MB and then 20MB. Im using the same keys so my understanding is that this should just update the record but it's almost as if it's just inserting all new records every time. I have also had similar behavior using Lawnchair on mobile safari using websql adapter. Has anyone seen this before or have any suggestions as to why this might be ??.
The following code is from a function I am using to populate the database.
populateDatabase: function(database,callback) {
'use strict';
var key;
try {
for(key in MasterData){
if(MasterData.hasOwnProperty(key)){
var itemInfo = DataConfig.checkForDataUpdates[DataConfig.keyMap[key]];
database.save({key:itemInfo["name"],hash:itemInfo["version"],url:itemInfo["url"],data:MasterData[key]});
}
}
callback(true);
} catch(e){
callback(false);
}
}
MasterData is the large data file and itemInfo contains the key name, a hash that is later used to check an api for updates, and the relative url of where to update from. After I create the database I pass it into this function and then pass back true if the inserts are successful and false otherwise.
As previously mentioned, I have seen similar issues in iOS where calling database.save() was allocating a lot of memory but not releasing it and eventually causing a crash if it populated the database and then tried to update some records. Removing Lawnchair from the equation has kept it from crashing but it is still allocating a lot of memory when saving data. Not sure if this is normal for persistent storage on mobile devices, a bug in Lawnchair, or me being a noob and doing something terribly wrong but I could use some pointers on this as well as why indexeddb just keeps getting larger and larger on every save (at least during initial testing in IE10)??
EDIT: Source Code for indexed-db adapter is here:
https://github.com/brianleroux/lawnchair/blob/master/src/adapters/indexed-db.js
and here is the code for the save function I am using:
save:function(obj, callback) {
var self = this;
if(!this.store) {
this.waiting.push(function() {
this.save(obj, callback);
});
return;
}
var objs = (this.isArray(obj) ? obj : [obj]).map(function(o){if(!o.key) { o.key = self.uuid()} return o})
var win = function (e) {
if (callback) { self.lambda(callback).call(self, self.isArray(obj) ? objs : objs[0] ) }
};
var trans = this.db.transaction(this.record, READ_WRITE);
var store = trans.objectStore(this.record);
for (var i = 0; i < objs.length; i++) {
var o = objs[i];
store.put(o, o.key);
}
store.transaction.oncomplete = win;
store.transaction.onabort = fail;
return this;
},
When Creating a new instance, Lawnchair uses the init function from the indexed-db adapter which is the following.
init:function(options, callback) {
this.idb = getIDB();
this.waiting = [];
this.useAutoIncrement = useAutoIncrement();
var request = this.idb.open(this.name, STORE_VERSION);
var self = this;
var cb = self.fn(self.name, callback);
if (cb && typeof cb != 'function') throw 'callback not valid';
var win = function() {
// manually clean up event handlers on request; this helps on chrome
request.onupgradeneeded = request.onsuccess = request.error = null;
if(cb) return cb.call(self, self);
};
var upgrade = function(from, to) {
// don't try to migrate dbs, just recreate
try {
self.db.deleteObjectStore('teststore'); // old adapter
} catch (e1) { /* ignore */ }
try {
self.db.deleteObjectStore(self.record);
} catch (e2) { /* ignore */ }
// ok, create object store.
var params = {};
if (self.useAutoIncrement) { params.autoIncrement = true; }
self.db.createObjectStore(self.record, params);
self.store = true;
};
request.onupgradeneeded = function(event) {
self.db = request.result;
self.transaction = request.transaction;
upgrade(event.oldVersion, event.newVersion);
// will end up in onsuccess callback
};
request.onsuccess = function(event) {
self.db = event.target.result;
if(self.db.version != (''+STORE_VERSION)) {
// DEPRECATED API: modern implementations will fire the
// upgradeneeded event instead.
var oldVersion = self.db.version;
var setVrequest = self.db.setVersion(''+STORE_VERSION);
// onsuccess is the only place we can create Object Stores
setVrequest.onsuccess = function(event) {
var transaction = setVrequest.result;
setVrequest.onsuccess = setVrequest.onerror = null;
// can't upgrade w/o versionchange transaction.
upgrade(oldVersion, STORE_VERSION);
transaction.oncomplete = function() {
for (var i = 0; i < self.waiting.length; i++) {
self.waiting[i].call(self);
}
self.waiting = [];
win();
};
};
setVrequest.onerror = function(e) {
setVrequest.onsuccess = setVrequest.onerror = null;
console.error("Failed to create objectstore " + e);
fail(e);
};
} else {
self.store = true;
for (var i = 0; i < self.waiting.length; i++) {
self.waiting[i].call(self);
}
self.waiting = [];
win();
}
}
request.onerror = function(ev) {
if (request.errorCode === getIDBDatabaseException().VERSION_ERR) {
// xxx blow it away
self.idb.deleteDatabase(self.name);
// try it again.
return self.init(options, callback);
}
console.error('Failed to open database');
};
},
I think you keep adding data instead of updating the present data.
Can you provide some more information about the configuration of the store. Are you using an inline or external key? If it's an internal what is the keypath.

Categories

Resources