i'm new to react-native and i'm using the library react-native-ble-plx to connect a Heart Sensor to my app and show it's values.
At this point i managed to connect it via bluetooth and store the information on a buffer where i can see with console.log(buffer), as shown in next picture.
My question is how can i render this information to the application? I don't know how to handle it from that buffer.
edit: I specifically want the 2nd value of that buffer (the one that normally is 70)
Here is the code:
scanAndConnect() {
this.manager.startDeviceScan(null,
null, (error, device) => {
this.info("Scanning...");
if (error) {
this.error(error.message);
return;
}
console.log(device.name)
//if (device && device.name == 'Inspire HR') {
if (device && device.name == 'HX-00043494') {
this.manager.stopDeviceScan()
device.connect()
.then((device) => {
this.info("Discovering services and characteristics ")
return device.discoverAllServicesAndCharacteristics()
}).then((device) => {
this.info("Setting notifications")
``return this.Async_setupNotifications(device);
})
.then(() => {
this.info("Listening...")
return this.setupNotifications(device)
}, (error) => {
this.error(error.message)
})
}
})`
}
async Async_setupNotifications(device) {
this.manager.characteristic = device.characteristicsForService("0000180d-0000-1000-8000-00805f9b34fb");
const buf = Buffer.from(characteristic.value, "base64");
console.log(buf);
console.log (buf[1]);
this.manager.characteristic.isNotifying = true;
this.manager.characteristic.isReadable = true;
if (error) {
this.error(error.message)
}
return ;
}
Thanks a lot for the help so far
Assuming that you are doing console.log from within the application, you need to access the data via buffer.data[1], it should give you the second value.
If the buffer is a global variable, simple example how to render in React Native Component:
import React from 'react';
import {View,Text} from 'react-native';
let buffer;
export default class YourComponent extends React.Component {
Async_setupNotifications = async (device) => { // call this method from within your code
this.manager.characteristic =
device.characteristicsForService("0000180d-0000-1000-8000-00805f9b34fb");
const buf = Buffer.from(characteristic.value, "base64");
console.log(buf);
console.log (buf[1]);
this.setState({pulse: buf.data[1]}); // assign the needed data to state
}
render() {
return(
<View>
<Text>{this.state.pulse}</Text>
</View>
)
}
}
Related
I am getting the following error when I run myu application and click on a submit button,
React has detected a change in the order of Hooks called by SideBarItemTemplateWithData. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks
Previous render Next render
------------------------------------------------------
1. useContext useContext
2. useMemo useState
My SideBarItemTemplateWithData,
RoomListRowProps): ReactElement {
const { sidebar } = useLayout();
let priority:any;
let userRoomId:any;
let data:any;
const href = roomCoordinator.getRouteLink(room.t, room) || '';
const title = roomCoordinator.getRoomName(room.t, room) || '';
if (room && room.v && room.v._id) {
userRoomId = room.v._id;
}
if (room && room.priorityId) {
data = useEndpoint('GET', `/v1/livechat/priorities/${room.priorityId}`);
}
if (data && data.value && data.value.name) {
priority = data.value.name.toLowerCase();
}
const {
lastMessage,
hideUnreadStatus,
hideMentionStatus,
unread = 0,
alert,
userMentions,
groupMentions,
tunread = [],
tunreadUser = [],
rid,
t: type,
cl,
} = room;
<SideBarItemTemplate
userId={userRoomId}
priority={priority}
is='a'
/>
I am getting the error when I run the above code but when I comment the following line it is working fine,
if (room && room.priorityId) {
data = useEndpoint('GET', `/v1/livechat/priorities/${room.priorityId}`);
}
The below line returns a promise,
useEndpoint('GET', `/v1/livechat/priorities/${room.priorityId}`);
Can anyone suggest me to how can I modify it o that the issue will be resolved. Thanks
useEndPoint code,
export const useEndpoint = <TMethod extends Method, TPath extends PathFor<TMethod>>(
method: TMethod,
path: TPath,
): EndpointFunction<TMethod, MatchPathPattern<TPath>> => {
const { callEndpoint } = useContext(ServerContext);
return useCallback((params: any) => callEndpoint(method,
path, params), [callEndpoint, path, method]);
};
How to use useEndPoint,
const sendEmailCode = useEndpoint('POST', '/v1/users.2fa.sendEmailCode');
await sendEmailCode({ emailOrUsername });
My Code,
const priorityData = useEndpoint('GET', `/v1/livechat/priorities/${room.priorityId}`);
if (room && room.v && room.v._id) {
userRoomId = room.v._id;
}
const onClickResendCode = async (): Promise<any> => {
try {
let priorityVal = '';
let data = await priorityData();
if (data && data.name) {
priorityVal = data.name.toLowerCase();
}
return priorityVal;
} catch (error) {
throw error;
}
};
priority = onClickResendCode();
Can anyone please suggest how can I modify the api call
The error is not about the promise, is about the order of the hook. In React you must keep the order of all your hook. You should not use your hook in a if or a loop.
This is the error.
if (room && room.priorityId) {
data = useEndpoint('GET', `/v1/livechat/priorities/${room.priorityId}`);
}
it should be
data = useEndpoint('GET', `/v1/livechat/priorities/${room.priorityId}`);
You can use if in the callEndpoint function, which is not a react hook.
I'm new to nextjs and I'm creating API on next.js to perform db update using the pg-promise. However, it always hit the WARNING: Creating a duplicate database object for the same connection on console when the app is calling the API.
I tried browsing the docs but couldn't find a solution. I also tried solution (update-2) mentioned on stackoverflow page below, but the warning still exists.
Where should I initialize pg-promise
I think the problem is on the method I used to set the columnset. However I can't find proper way to do it. How should I fix it with pg-promise ?
Db setting code:
import ConfigEnv from 'utils/configuration';
import * as pgLib from 'pg-promise';
const initOptions = {
capSQL: true,
};
const pgp = require('pg-promise')(initOptions);
interface IDatabaseScope {
db: pgLib.IDatabase<any>;
pgp: pgLib.IMain;
}
export function createSingleton<T>(name: string, create: () => T): T {
const s = Symbol.for(name);
let scope = (global as any)[s];
if (!scope) {
scope = {...create()};
(global as any)[s] = scope;
}
return scope;
}
export function getDB(): IDatabaseScope {
return createSingleton<IDatabaseScope>('my-app-db-space', () => {
return {
db: pgp(ConfigEnv.pgp),
pgp
};
});
}
API code:
import {getDB} from 'db/pgpdb';
const {db, pgp} = getDB();
const cs = new pgp.helpers.ColumnSet([
'?detail_id',
'age',
'name'
// 'last_modified_date',
], {
table: 'user_detail',
})
export default async (req, res) => {
try {
// generating the update query where it is needed:
const update = pgp.helpers.update(req.body.content, cs) + ` WHERE v.detail_id = t.detail_id`;
// executing the query
await db
.none(update)
.then(() => {
return res.status(200).end();
})
.catch((error) => {
console.log('error', error);
return res.status(500).send(error);
});
} catch (error) {
console.log(error);
}
};
I started integrating websockets into an existing React/Django app following along with this example (accompanying repo here). In that repo, the websocket interface is in websockets.js, and is implemented in containers/Chat.js.
I can get that code working correctly as-is.
I then started re-writing my implementation to use Hooks, and hit a little wall. The data flows through the socket correctly, arrives in the handler of each client correctly, and within the handler can read the correct state. Within that handler, I'm calling my useState function to update state with the incoming data.
Originally I had a problem of my single useState function within addMessage() inconsistently firing (1 in 10 times?). I split my one useState hook into two (one for current message, one for all messages). Now in addMessage() upon receiving data from the server, my setAllMessages hook will only update the client where I type the message in - no other clients. All clients receive/can log the data correctly, they just don't run the setAllMessages function.
If I push to an empty array outside the function, it works as expected. So it seems like a problem in the function update cycle, but I haven't been able to track it down.
Here's my version of websocket.js:
class WebSocketService {
static instance = null;
static getInstance() {
if (!WebSocketService.instance) {
WebSocketService.instance = new WebSocketService();
}
return WebSocketService.instance;
}
constructor() {
this.socketRef = null;
this.callbacks = {};
}
disconnect() {
this.socketRef.close();
}
connect(chatUrl) {
const path = `${URLS.SOCKET.BASE}${URLS.SOCKET.TEST}`;
this.socketRef = new WebSocket(path);
this.socketRef.onopen = () => {
console.log('WebSocket open');
};
this.socketRef.onmessage = e => {
this.socketNewMessage(e.data);
};
this.socketRef.onerror = e => {
console.log(e.message);
};
this.socketRef.onclose = () => {
this.connect();
};
}
socketNewMessage(data) {
const parsedData = JSON.parse(data);
const { command } = parsedData;
if (Object.keys(this.callbacks).length === 0) {
return;
}
Object.keys(SOCKET_COMMANDS).forEach(clientCommand => {
if (command === SOCKET_COMMANDS[clientCommand]) {
this.callbacks[command](parsedData.presentation);
}
});
}
backend_receive_data_then_post_new(message) {
this.sendMessage({
command_for_backend: 'backend_receive_data_then_post_new',
message: message.content,
from: message.from,
});
}
sendMessage(data) {
try {
this.socketRef.send(JSON.stringify({ ...data }));
} catch (err) {
console.log(err.message);
}
}
addCallbacks(allCallbacks) {
Object.keys(SOCKET_COMMANDS).forEach(command => {
this.callbacks[SOCKET_COMMANDS[command]] = allCallbacks;
});
}
state() {
return this.socketRef.readyState;
}
}
const WebSocketInstance = WebSocketService.getInstance();
export default WebSocketInstance;
And here's my version of Chat.js
export function Chat() {
const [allMessages, setAllMessages] = useState([]);
const [currMessage, setCurrMessage] = useState('');
function waitForSocketConnection(callback) {
setTimeout(() => {
if (WebSocketInstance.state() === 1) {
callback();
} else {
waitForSocketConnection(callback);
}
}, 100);
}
waitForSocketConnection(() => {
const allCallbacks = [addMessage];
allCallbacks.forEach(callback => {
WebSocketInstance.addCallbacks(callback);
});
});
/*
* This is the problem area
* `incoming` shows the correct data, and I have access to all state
* But `setAllMessages` only updates on the client I type the message into
*/
const addMessage = (incoming) => {
setAllMessages([incoming]);
};
// update with value from input
const messageChangeHandler = e => {
setCurrMessage(e.target.value);
};
// Send data to socket interface, then to server
const sendMessageHandler = e => {
e.preventDefault();
const messageObject = {
from: 'user',
content: currMessage,
};
setCurrMessage('');
WebSocketInstance.backend_receive_data_then_post_new(messageObject);
};
return (
<div>
// rendering stuff here
</div>
);
}
There is no need to rewrite everything into functional components with hooks.
You should decompose it functionally - main (parent, class/FC) for initialization and providing [data and] methods (as props) to 2 functional childrens/components responsible for rendering list and input (new message).
If you still need it ... useEffect is a key ... as all code is run on every render in functional components ... including function definitions, redefinitions, new refs, duplications in callbacks array etc.
You can try to move all once defined functions into useEffect
useEffect(() => {
const waitForSocketConnection = (callback) => {
...
}
const addMessage = (incoming) => {
setAllMessages([incoming]);
};
waitForSocketConnection(() => {
...
}
}, [] ); // <<< RUN ONCE
I'm upldating my app layout by json loaded from api in app.js (saved by reloadLayoutsConfig function). When I want to access my data inside app everything is ok but how can I load layout inside my layoutRedux file?
export const reloadLayoutsConfig = async (newLayoutsConfig) => {
try {
await AsyncStorage.setItem("#LayoutsConfig", JSON.stringify(newLayoutsConfig));
} catch (error) {
console.log("error save user data", error);
}
};
export const getLayoutsConfig = async () => {
try {
const LayoutsConfig = await AsyncStorage.getItem("#LayoutsConfig");
return JSON.parse(LayoutsConfig);
} catch (error) {
console.log(error);
}
};
These two functions work like a charm, whenever I need a value I just do this:
getLayoutsConfig().then((LayoutsConfig) => {
this.setState({ LayoutsConfig : LayoutsConfig });
});
This is my layoutRedux:
import { getLayoutsConfig} from '#config'
const types = {
// LOTS OF CODE
}
const initialState = {
layout: [],
isFetching: false,
}
var layouts = [];
// OLD TYPE FROM STORED JSON FILE IN CODE
var layouts = [...LayoutsConfig];
// NEW WAY FROM LOADED JSON FILE FROM API
getLayoutsConfig().then((LayoutsConfig) => {
layouts = LayoutsConfig;
});
initialState.layout = layouts;
export const actions = {
// LOTS OF CODE
}
export const reducer = (state = initialState, action) => {
// LOTS OF CODE
}
I have mentioned my old and new way to access json file in same code for you to check it. In older version I used to have layout.json file in my code and when I needed to access file i just used it like this:
import { LayoutsConfig } from '#config'
var layouts = [...LayoutsConfig];
in config :
export const LayoutsConfig = AppConfig.LayoutsConfig;
but now i call it like this :
var layouts = [];
getLayoutsConfig().then((LayoutsConfig) => {
layouts = LayoutsConfig;
});
I get error like layout is not loaded. What can I do and how to call my function?
I am trying to make stores which can be accessed by Screens. File structure:
index.ios.js
/app/index.js
/app/store/database.js
/app/store/userStore.js
index.ios.js :
import { AppRegistry } from 'react-native';
import App from './app/index';
AppRegistry.registerComponent('AwesomeProject', () => App);
/app/index.js :
import React, { Component} from 'react';
import {
Text,
View,
} from 'react-native';
import userStore from './store/userStore';
import ViewBackground from './components/ViewBackground';
class App extends Component {
constructor(props){
super(props);
this.isLoggedIn = true;
}
componentDidMount() {
this.fetchUsers().done();
}
async fetchUsers(){
console.log('Before User Fetch');
var result = await userStore.getAllUsers();
console.log('After User Fetch');
}
render() {
if(this.isLoggedIn){
return this.loggedInView();
}else{
return this.loggedOutView();
}
}
loggedInView(){
return <ViewBackground>
</ViewBackground>
}
loggedOutView(){
return <View>
<Text>Hi, This is logged Out view </Text>
</View>
}
}
export default App;
/app/store/userStore.js :
import React from 'react';
import database from './database';
class UserStore{
async getAllUsers(){
let query = {
type: 'SELECT',
sql: 'SELECT * FROM Users',
vals: [],
}
let queries = [query];
console.log('in store before');
let dbResult = await database.runQuery(queries);
console.log('in store after');
return dbResult;
}
}
const userStore = new UserStore;
export default userStore;
/app/store/database.js :
'use strict';
import React from 'react';
import SQLite from 'react-native-sqlite-storage';
SQLite.enablePromise(true);
var database_name = "test.db";
var database_version = "1.0";
var database_displayname = "Test";
var database_size = 1024 * 1024 * 10;
class Database {
constructor(){
SQLite.openDatabase(database_name, database_version, database_displayname, database_size).then(this.dbOpenSuccess).catch(this.dbOpenError);
}
dbOpenSuccess(dbInstance){
this.conn = dbInstance;
}
dbOpenError(err) {
}
getConnection() {
return this.conn;
}
setUpDatabase(){
let queries = [
'CREATE TABLE IF NOT EXISTS Users (user_id INTEGER PRIMARY KEY, f_name VARCHAR(64), l_name VARCHAR(64), email_id VARCHAR(128), mobile VARCHAR(10))'
];
this.conn.transaction( tx => {
queries.map( q => {
tx.executeSql(q, [], res => {}, err => {});
});
});
}
async runQuery(queries) {
await this.conn.transaction(tx => {
return Promise.all(queries.map(async (q) => {
try {
let results = null;
switch(q.type){
case 'SELECT':
results = await tx.executeSql(q.sql, q.vals);
console.log('Query', q, 'Executed. results:', results);
break;
}
} catch(err) {
console.log('Something went wrong while executing query', q, 'error is', err);
}
}));
});
return false;
}
closeDatabase(){
this.conn.close().then(this.dbCloseSuccess).catch(this.dbCloseError);
}
dbCloseSuccess(res) {
}
dbCloseError(err){
}
}
const dbInstance = new Database();
dbInstance.setUpDatabase();
export default dbInstance;
In /app/index.js I am trying to fetch users from userStore.js which will call database.js to retrieve the users from database. I want to pause execution when I fetch users from database, so tried async/await. I used console.log() to check whether execution paused. None of async/await is working. I am getting response after all console.log is done.
I want it to wait until I receive data from database.
You need to wrap it in a Promise, then resolve the result when sql execution is done.
for example
async () => {
return new Promise((resolve, reject) => {
db.transaction(tx => {
tx.executeSql('SELECT * FROM users;', [], (tx, results) => {
const { rows } = results;
let users = [];
for (let i = 0; i < rows.length; i++) {
users.push({
...rows.item(i),
});
}
resolve(users);
});
});
});
}
let SQLite = require('react-native-sqlite-storage');
const DB = SQLite.openDatabase({name:'test.db',createFromLocation:'~sqlitedb.db'});
class Database{
db;
constructor(db){
this.db =db;
}
executeSql = (sql,params=[])=>new Promise((resolve , reject)=>{
this.db.transaction((trans)=>{
trans.executeSql(sql,params,(db,results)=>{
resolve(results);
},
(error)=>{
reject(error);
});
});
});
}
export default (new Database(DB));
use
import Database from 'database';
try
{
results = await DB.excuteSql("SQL",['params']);
}
catch(e)
{
}
The following worked for me:
import { openDatabase } from 'react-native-sqlite-storage'
const db = openDatabase({
name: 'app.db',
location: 'default',
})
export default function App() {
useEffect(() => {
db.then((db) => {
db.transaction((tx) => {
tx.executeSql('SELECT this from that', [])
})
})
/* Rest of the component... */
}
openDatabase returns a Promise, on resolving which we get the actual db on which we can run db.transaction().
You could use the async/await syntax too, but that would be a lot of encapsulation, and so .then() is always cleaner.
This is different from the "expo-sqlite" package, because db = openDatabase('app.db') does not return a Promise there. Instead, you can run db.transaction() directly.
just add this lines
import {enablePromise, openDatabase } from 'react-native-sqlite-storage';
enablePromise(true)
I follow this way to do DB operations
export const fetchUsers = async () => {
return new Promise((resolve, reject) => {
db.transaction(txn => {
txn.executeSql('SELECT * FROM "Users";', [], (tx, res) => (
resolve(res.rows.raw())
))
})
})
}
rows.raw() will return the data as object
(async()=>{
data= await fetchUsers()
})()