I built simple weather webpage basing on the tutorial. and I have a webpage with below JS code;
I have also Node JS code( on the bottom) for temperature and pressure sensor written with Johnny-Five. This works perfectly but what I wanna do is display readouts from the sensors setup with NodeJS on the webpage. What is the best approach to do that? I tried to setup this with websocket but it was not really working.
let weather = {
apiKey: "xxxxxxxxxxxxxx",
fetchWeather: function (city) {
fetch(
"https://api.openweathermap.org/data/2.5/weather?q=" + city + "&units=metric&appid=" + this.apiKey
).then((response) => {
return response.json();
})
.then((data) => this.displayWeather(data));
},
displayWeather: function (data) {
const { name } = data;
const { icon, description } = data.weather[0];
const { temp, humidity, pressure } = data.main;
const { speed } = data.wind;
const temperatura = Math.round(temp);
document.querySelector(".miasto").innerText = "Pogoda w " + name;
document.querySelector(".icon").src =
"https://openweathermap.org/img/wn/" + icon + ".png";
document.querySelector(".opis").innerText = description;
document.querySelector(".temperatura").innerText = temperatura + "°C";
document.querySelector(".wilgotnosc").innerText =
"Wilgotność: " + humidity + "%";
document.querySelector(".cisnienie").innerText =
"Ciśnienie: " + pressure + "HPa";
document.querySelector(".wiatr").innerText =
"Prędkość wiatru: " + speed + " km/h";
document.querySelector(".pogoda").classList.remove("loading");
document.body.style.backgroundImage =
"url('https://source.unsplash.com/1600x900/?" + name + "')";
},
search: function () {
this.fetchWeather(document.querySelector(".search-bar").value);
},
};
document.querySelector(".search button").addEventListener("click", function () {
weather.search();
});
document
.querySelector(".search-bar")
.addEventListener("keyup", function (event) {
if (event.key == "Enter") {
weather.search();
}
});
weather.fetchWeather("Katowice");
var five = require("johnny-five");
var board = new five.Board(
{
port: "COM4"
}
);
board.on("ready", function() {
var multi = new five.Multi({
controller: "BMP180",
freq: 500
});
multi.on("change", function() {
console.log("Termometr");
console.log(" Temperatura : ", this.thermometer.celsius, " ℃");
console.log("--------------------------------------");
var pressure2 = Math.round(this.barometer.pressure*100, 1)/10;
console.log("Barometr");
console.log(" Ciśnienie : ", pressure2, " HPa" );
console.log("--------------------------------------");
});
});
I managed to solve the issue. Quite simple but mybe it will help someone here
Data which I am sending are
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8085 })
var obj = {
press: "69",
temp: "24"
}
wss.on("connection", ws => {
ws.send(JSON.stringify(obj));
} );
And I get it:
const ws = new WebSocket("ws://localhost:8085");
ws.addEventListener("open", () => {
console.log("We are connected");
ws.addEventListener("message", (data) => {
console.log(JSON.parse(data.data));
});
});
Related
I have two Temp. Sensors on my Raspberry Pi and I have a node.js Express app. I want to create nedb databases dynamically of an array with sensor objects.
So I have an object with sensors in it:
sensors: [
{
name: "Indoor",
type: 22,
pin: 21
},
{
name: "Outdoor",
type: 22,
pin: 21
}
]};
Now I want to create for every Sensor three database:
databaseSetup(app.sensors);
function databaseSetup(sensor){
const dataStore = require('nedb');
const databaseVariables = [];
sensor.forEach((sensor) => {
const live = 'live' + sensor.name;
const seconds = 'seconds' + sensor.name;
const hours = 'hours' + sensor.name;
const test = {
live: new dataStore(`./databases/temp/${sensor.name}/live.db`),
seconds: new dataStore(`./databases/temp/${sensor.name}/seconds.db`),
hours: new dataStore(`./databases/temp/${sensor.name}/hours.db`) }
databaseVariables.push(test);
});
}
But this is not working. Can someone help me please?
I am not sure why you trying to do cause in my mind this is a bad practice. but you can make it dynamic. something like this:
const dt = require('nedb');
const db = [];
//USING LOOP and FUNCTION
let list = [{ name: "GasSensor" }, { name: "TempSensor" }];
let index = 0;
//BAD Practice
let setup = () => {
if (index + 1 > list.length) return;
let newInstance = new dt({ filename: 'nodejs/data/nedb_' + list[index].name, autoload: true });
console.log("Working on index " + (index + 1));
newInstance.loadDatabase((err) => {
if (err) {
//...
} else {
db.push(newInstance);
}
index++;
setup();
});
}
setup();
And also with API:
const exp = require("express");
const app = exp();
const dt = require('nedb');
const db = [];
app.get("/make/db/:name", (q, r) => {
//BAD PRACTICE
//JUST FOR TEST
let newInstance = new dt({ filename: 'nodejs/data/nedb_' + q.params.name, autoload: true });
newInstance.loadDatabase((err) => {
if (err) {
console.log(err + "");
r.send("ERROR");
}
else {
db.push(newInstance);
console.log("Database is loaded");
r.send("NEW DB CREATED");
}
});
});
app.listen(3000);
I have a Node API communicating with MongoDB install. The MongoDB node api ("mongodb": "^3.5.9") insists on converting date objects into String before updating to the db. Can anybody please help?
app.post("/api/updateDocument",auth,(req,res) => {
const collection = req.body.Collection;
incomingmap = req.body.inComingMap
const searchval = req.body.searchVal;
const searchvar = req.body.searchVar;
let findargs = {}
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://...";
MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true },function(err,db) {
if (err) throw err;
var dbo = db.db();
var coll = dbo.collection(collection);
coll.find({}).toArray(function(err,data) {
data.forEach((item) => {
if (item[searchvar] == searchval) {
for (let key in incomingmap) {
value=incomingmap[key]
console.log(key + " : " + value);
try {
da=Date.parse(value);
//incomingmap[key]=da.toIs;
coll.updateOne({_id:item._id},{$set: {key:da}},function() {})
} catch{
//coll.updateOne({_id:item._id},{$set: {key: value}},function() {})
}
}
return res.json({message:searchval+' updated.'})
} else {
setTimeout(() => {
res.end(`${searchval} could not be found.`)
}, 1000)
}
})
})
})
})
Expected Result
"calibration" : ISODate("2021-11-07T11:23:01.306Z"),
Actual Result
"calibration" : "2021-11-07T01:00:00.000Z",
I wrote a new function to parse the dates and store them back into the inComingMap
for (let key in incomingmap) {
value=incomingmap[key]
console.log(key + ": " + value);
try
{
da=new Date(value);
incomingmap[key]=da;
console.log(key + " = " + value +" is a date "+da);
map[key]=da
}
catch {
map[key]=value
console.log("K"+key + " V" + value );
}
}
I am using xvbf in node application to run a chrome client for capturing web site screens in background. From a web page i am passing data to my webservice as at the bottom of this code part to START_CAPTURE and STOP_CAPTURE.
const puppeteer = require('puppeteer');
const Xvfb = require('xvfb');
var exec = require('child_process').exec;
const os = require('os');
const homedir = os.homedir();
const platform = os.platform();
const http = require('http');
const StringDecoder = require('string_decoder').StringDecoder;
const http_port = 8000;
const ffmpegServer = config.ffmpegServer + ":" + config.ffmpegServerPort;
var xvfb = new Xvfb({
silent: true,
xvfb_args: ["-screen", "0", "1280x800x24", "-ac", "-nolisten", "tcp", "-dpi", "96", "+extension", "RANDR"]
});
var action = "";
var width = 1280;
var height = 720;
var options = {
headless: false,
args: [
'--enable-usermedia-screen-capturing',
'--allow-http-screen-capture',
'--load-extension=' + __dirname,
'--disable-extensions-except=' + __dirname,
'--disable-infobars',
'--start-fullscreen',
'--app=https://www.google.com/'`
],
}
options.executablePath = "/usr/bin/google-chrome"
async function main() {
try{
if(platform == "linux"){
xvfb.startSync()
}
var exportname = 'video.webm'
var url = 'https://www.google.com/';
var duration = 30;
const browser = await puppeteer.launch(options)
const pages = await browser.pages()
const page = pages[0]
page.on('console', msg => {
var m = msg.text();
console.log('PAGE LOG:', m)
});
await page._client.send('Emulation.clearDeviceMetricsOverride')
await page.goto(url, {waitUntil: 'networkidle2'})
await page.setBypassCSP(true);
if(duration > 0){
await page.waitFor((duration * 1000))
}else{
while(action!="STOP_CAPTURE"){
try {
await page.waitForSelector('[class^=modal] > [class^=content] > button[description="Logs you out"]', {
timeout: 1000
});
} catch (err) {
// Do nothing
}
}
}
await page.close()
await browser.close()
if(platform == "linux"){
xvfb.stopSync()
}
fs.unlinkSync(homedir + "/video.webm");
}catch(err) {
console.log(err)
}
}
// Instantiate the HTTP server.
const httpServer = http.createServer((req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
if (req.method == 'POST') {
var jsonString = '';
var buffers = [];
req.on('data', function (chunk) {
buffers.push(chunk);
});
req.on('error', (err) => {
// This prints the error message and stack trace to `stderr`.
console.log("Error: %s \n" + err.stack);
});
req.on('end', function () {
try {
jsonString = JSON.parse(Buffer.concat(buffers).toString());
var action = jsonString.markers[0]['action'];
if(action=="START_CAPTURE"){
main();
}
}
catch(e) {
jsonString = JSON.parse(JSON.stringify(Buffer.concat(buffers).toString()));
console.log('\nError \n ' + JSON.stringify(jsonString));
}
});
}
res.end();
console.log('Response ended here. \n ');
});
httpServer.listen(http_port, () => {
console.log("Web server is listening on port %s \n", http_port);
});
This is how it works.
I am clicking a button (START_CAPTURE) from my web site to start capturing. Then capture start. Then i am clicking a button (STOP_CAPTURE) to stop capturing.
everything is working fine. If i do like this.
But if i click START_CAPTURE using two different browsers, then i clicked on STOP_CAPTURE button from any browser window, both instances are getting stop.
I know it is happened because of this lines.
while(action!="STOP_CAPTURE"){
try {
await page.waitForSelector('[class^=modal] > [class^=content] > button[description="Logs you out"]', {
timeout: 1000
});
} catch (err) {
// Do nothing
}
}
Is there anyway to stop only requested instance ? How can i achieve it ?
I want to test the jobs I'm running with agenda. I have written the following test but then I realized that all the expect()... functions are not getting called before it determines that the test had passed or failed. I put some console.log() by all the expect() functions and they do get called just not before it determines if the tests result. I tried adding expect.assertions(6); at the top of the test but it didn't make the test wait longer, it just failed saying it didn't find all 6.
How do I make jest wait for the whole test to finish?
This is the code I want to test:
rules.js
const Account = require("./../models/user.account");
const Listing = require("./../models/user.account.listing");
const Message = require("./../models/user.account.listing.message");
const MessageRule = require("./../models/user.account.listing.messageRule");
const Reservation = require("./../models/user.account.listing.reservation");
const Core = require("./../core");
const moment = require("moment-timezone");
require("colors");
module.exports = function(agenda) {
agenda.define("send message", {priority: "highest"}, async (job, done) => {
try {
console.time("send message " + job.attrs._id);
const userID = job.attrs.data.userID;
const listingID = job.attrs.data.listingID;
const reservationID = job.attrs.data.reservationID;
const messageRuleID = job.attrs.data.messageRuleID;
const sendDate = job.attrs.data.sendDate;
//console.log("Rule Job:".cyan + " send message - listingID: " + listingID);
let messageQuery = {
userID,
listingID,
reservationID,
messageRuleID
};
let message = await Message.findOne(messageQuery);
if (message) {
throw new Error(
"Message has already been sent. userID: " +
userID +
" listingID: " +
listingID +
" reservationID: " +
reservationID +
" messageRuleID: " +
messageRuleID +
" message._id: " +
message._id +
" message.sendDate: " +
message.sendDate +
" message.sentDate: " +
message.sentDate
);
} else {
const isLastMinuteMessage = false;
let listing = await Listing.findById(listingID);
let account = await Account.findById(listing.accountID);
let messageRule = await MessageRule.findById(messageRuleID);
let reservation = await Reservation.findById(reservationID);
// Check that it found all of the required documents
if (!listing || !listing._id) {
throw new Error("Missing the listing document. userID: " + userID + " listingID: " + listingID);
}
if (!account || !account._id) {
throw new Error(
"Missing the account document. userID: " + userID + " accountID: " + listing.accountID
);
}
if (!messageRule || !messageRule._id) {
throw new Error(
"Missing the messageRule document. userID: " + userID + " messageRuleID: " + messageRuleID
);
}
if (!reservation || !reservation._id) {
throw new Error(
"Missing the reservation document. userID: " + userID + " reservationID: " + reservationID
);
}
// Double check the send date by recalculating it then checking comparing them
if (messageRule.event == "checkin" || messageRule.event == "checkout") {
let sendDateCheck = moment.tz(
reservation.startDate + " " + messageRule.time,
"YYYY-MM-DD H",
listing.timeZone
);
if (messageRule.event == "checkout") {
sendDateCheck = sendDateCheck.add(reservation.nights, "day");
}
sendDateCheck = sendDateCheck.add(messageRule.days, "day");
if (!sendDateCheck.isSame(sendDate)) {
throw new Error(
"Message send date and calculated send date don't match. userID: " +
userID +
" listingID: " +
listingID +
" reservationID: " +
reservationID +
" messageRuleID: " +
messageRuleID +
" sendDate: " +
moment(sendDate).format() +
" sendDateCheck: " +
moment(sendDateCheck).format()
);
}
}
await Core.buildMessage(account, listing, messageRule, reservation, isLastMinuteMessage);
}
console.timeEnd("send message " + job.attrs._id);
done();
} catch (error) {
console.error("Rule Job: send message", error);
return done(error);
}
});
};
And here is my test:
rules.test.js
const Account = require("./../models/user.account");
const Listing = require("./../models/user.account.listing");
const Message = require("./../models/user.account.listing.message");
const MessageRule = require("./../models/user.account.listing.messageRule");
const Reservation = require("./../models/user.account.listing.reservation");
const Core = require("./../core");
const Rules = require("./rules");
const Docs = require("./../tests/docs");
describe("Tests for rules.js", () => {
// Mock moment()
Date.now = jest.fn(() => 1538794832371); //October 5th 2018 8pm PST
beforeEach(() => {
jest.clearAllMocks();
});
describe("rules()", () => {
it("should send a message, message exists but is enabled", async () => {
// Mock Message
// Message.findOne()
const MessageFindOneMock = jest.spyOn(Message, "findOne");
const MessageFindOneResult = Docs.messageReviewReminderDisabledThenEnabled;
const MessageFindOne = jest.fn(() => MessageFindOneResult);
MessageFindOneMock.mockImplementation(MessageFindOne);
const userID = Docs.userID;
const reservation = Docs.reservationInTheFuture;
const messageRule = Docs.messageRuleCheckUp;
const accountID = Docs.listing.accountID;
const listingID = Docs.listing._id;
const reservationID = reservation._id;
const messageRuleID = messageRule._id;
// Mock Listing
// Listing.findById()
const ListingFindByIdMock = jest.spyOn(Listing, "findById");
const ListingFindByIdResult = Docs.listing;
const ListingFindById = jest.fn(() => ListingFindByIdResult);
ListingFindByIdMock.mockImplementation(ListingFindById);
// Mock Account
// Account.findById()
const AccountFindByIdMock = jest.spyOn(Account, "findById");
const AccountFindByIdResult = {_id: accountID};
const AccountFindById = jest.fn(() => AccountFindByIdResult);
AccountFindByIdMock.mockImplementation(AccountFindById);
// Mock MessageRule
// MessageRule.findById()
const MessageRuleFindByIdMock = jest.spyOn(MessageRule, "findById");
const MessageRuleFindByIdResult = messageRule;
const MessageRuleFindById = jest.fn(() => MessageRuleFindByIdResult);
MessageRuleFindByIdMock.mockImplementation(MessageRuleFindById);
// Mock Reservation
// Reservation.findById()
const ReservationFindByIdMock = jest.spyOn(Reservation, "findById");
const ReservationFindByIdResult = reservation;
const ReservationFindById = jest.fn(() => ReservationFindByIdResult);
ReservationFindByIdMock.mockImplementation(ReservationFindById);
// Mock Core
// Core.buildMessage()
const CoreBuildMessageMock = jest.spyOn(Core, "buildMessage");
const CoreBuildMessage = jest.fn((account, listing, messageRule, reservation, isLastMinuteMessage) => {
expect(account._id).toBe(accountID);
expect(listing._id).toBe(listingID);
expect(messageRule._id).toBe(messageRuleID);
expect(reservation._id).toBe(reservationID);
});
CoreBuildMessageMock.mockImplementation(CoreBuildMessage);
// Run test
const sendDate = "2018-11-08T10:00:00-06:00";
const done = jest.fn(error => {
expect(error).toBeFalsy();
expect(CoreBuildMessage).toHaveBeenCalledTimes(10);
});
const job = {
attrs: {
data: {
userID,
listingID,
reservationID,
messageRuleID,
sendDate
}
}
};
let agenda = {
define: jest.fn((name, options, callback) => {
if (name == "send message") {
callback(job, done);
}
})
};
Rules(agenda);
});
});
});
In your rules.js you have defined your callback as an async function:
agenda.define("send message", {priority: "highest"}, async (job, done) // <--- this
However you are calling it with:
define: jest.fn((name, options, callback) => {
if (name == "send message") {
callback(job, done);
}
})
So there is no await there ...
Which explains why you get stuff running but not awaiting for it to finish.
Should be something like:
define: await jest.fn((name, options, callback) => {
if (name == "send message") {
await callback(job, done);
}
})
How can I make my db queries synchronous with with my promise base function? In my code, I am running 3 db operations inside 3 different functions which need to be run in order, like waterfall model. The functions are running in waterfall model but db queries inside those functions are working in asynchronous. I need to run db queries inside those function in synchronous.
In this example I am expecting in console:
1
2
3
4
But I am getting
1
3
2
4
Code:
const Promise = require('bluebird');
// DB Settings
const dbConfig = {
user: process.env.DBUSER,
password: process.env.DBPWD,
database: process.env.DBNAME,
host: process.env.DBHOST,
port: process.env.DBPORT,
poolSize: 10, // max number of clients in the pool
//poolIdleTimeout: 30000, // how long a client is allowed to remain idle before being closed
//reapIntervalMillis: 1000 //frequency to check for idle clients within the client pool
};
const pgp = require('pg-promise')();
const db = pgp(dbConfig);
var currentStatus = '',newStatus = '';
const _updateCurrentStatus = () => new Promise((resolve, reject) => {
const _getCurrentStatus = (_userId) => new Promise((_resolve, _reject) => {
console.log("1");
let statusQuery = "SELECT status FROM users WHERE id=" + _userId;
db.one(statusQuery).then(function (data) {
console.log("2");
currentStatus = data.status;
_resolve();
}).catch(function (error) {
_reject(error);
});
});
const _setUpdateStatus = (cStatus, nStatus) => new Promise((_resolve, _reject) => {
if(allApproved){
if(cStatus == 'nvd_pending'){
//nStatus = 'finance_pending';
newStatus = 'finance_pending';
}else if(cStatus == 'finance_pending'){
//nStatus = 'oracle_pending';
newStatus = 'oracle_pending';
}else if(cStatus == 'oracle_pending'){
//nStatus = 'active';
newStatus = 'active';
}else{
//nStatus = cStatus;
newStatus = cStatus;
}
}else{
//nStatus = 'nvd_pending';
newStatus = 'nvd_pending';
}
//_resolve(nStatus);
_resolve();
});
const _updateStatus = (_newStatus, _payLoad) => new Promise((_resolve, _reject) => {
console.log("3");
let updateuserQuery = "UPDATE users SET status = '"+ _newStatus + "' WHERE id=" + _payLoad.user_id;
let updatePanQuery = "UPDATE user_documents SET status = '" + _payLoad.panstatus + "' WHERE id= " + _payLoad.panid + " AND user_id=" + _payLoad.user_id;
let updateFinanceQuery = "UPDATE user_finance_details SET status = '" + _payLoad.financestatus +" 'WHERE id= " + _payLoad.financeid + " AND user_id=" + _payLoad.user_id;
db.tx(function (t) {
console.log("4");
// `t` and `this` here are the same;
// this.ctx = transaction config + state context;
return t.batch([
t.none(updateuserQuery),
t.none(updatePanQuery),
t.none(updateFinanceQuery)
]);
}).then(function (data) {
_resolve(data);
}).catch(function (error) {
_reject(error);
});
});
_getCurrentStatus(payLoad.user_id)
.then(_setUpdateStatus)
.then( _updateStatus(newStatus, payLoad))
.then( values => {
resolve(values);
},error => {
reject(error);
})
.catch((error) => reject(error));
});
You are overcomplicating thing here. First feedback is that you don't need those new Promise wrappers, since pg-promise is already creating promises. You can greatly flatten things here:
function getCurrentStatus(userId) {
console.log("1");
let statusQuery = "SELECT status FROM users WHERE id=" + userId;
return db.one(statusQuery).then(function (data) {
console.log("2");
return data.status;
});
}
function getUpdatedStatus(cStatus)
console.log('2');
if (allApproved) {
if(cStatus == 'nvd_pending'){
newStatus = 'finance_pending';
} else if (cStatus == 'finance_pending'){
newStatus = 'oracle_pending';
} else if (cStatus == 'oracle_pending'){
newStatus = 'active';
} else {
newStatus = cStatus;
}
} else {
newStatus = 'nvd_pending';
}
return newStatus;
}
function updateStatus(newStatus, payLoad) {
console.log("3");
let updateuserQuery = "UPDATE users SET status = '"+ newStatus + "' WHERE id=" + payLoad.user_id;
let updatePanQuery = "UPDATE user_documents SET status = '" + payLoad.panstatus + "' WHERE id= " + payLoad.panid + " AND user_id=" + payLoad.user_id;
let updateFinanceQuery = "UPDATE user_finance_details SET status = '" + payLoad.financestatus +" 'WHERE id= " + payLoad.financeid + " AND user_id=" + payLoad.user_id;
return db.tx(function (t) {
console.log("4");
// `t` and `this` here are the same;
// this.ctx = transaction config + state context;
return t.batch([
t.none(updateuserQuery),
t.none(updatePanQuery),
t.none(updateFinanceQuery)
]);
});
});
function updateCurrentStatus(payLoad) {
return getCurrentStatus(payLoad.user_id)
.then(cStatus => getUpdatedStatus(cStatus))
.then(newStatus => updateStatus(newStatus, payLoad));
}
The specific reason you're seeing 3 out of order is because you're calling it immediately via _updateStatus(newStatus, payLoad) instead of wrapping it in a function (see my suggested code updates above).