I'm trying to stream data every second from my server to the frontend. Currently I could only connect to the socket io and all the tutorials I found was using a chat application as an example.
The project consist of pymodbus so I could communicate to a plc and gather those data. The data is then visualize using reactjs
Python
from flask import Flask, jsonify
from flask_restful import Api, Resource
from flask_socketio import SocketIO, emit
import random
app = Flask(__name__)
app.config["SECRET_KEY"] = "somethingRandom"
app.config["DEBUG"] = True
api = Api(app)
socketio = SocketIO(app, cors_allowed_origins="*")
#app.route("/")
def hello_world():
return jsonify(mssg="hello world")
def PlcTankData():
i = 5
j = 0
while j != 5: # should be while True
j+=1
sample = random.randint(1, 10)
print(sample)
emit("newdata", {"td": sample}, namespace="/home")
socketio.sleep(1)
#socketio.on("connect", namespace="/home")
def frontend_connection():
print("Client is Connected")
emit("connect", {"hello": "world"})
PlcTankData()
class MachineStatus(Resource):
def put(self):
data = request.json
print(data)
api.add_resource(MachineStatus, '/machine-stat')
if __name__ == '__main__':
socketio.run(app, host="192.168.0.105", port=5000)
Reactjs
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import io from 'socket.io-client'
//To Control the machcine
const handleMachineStatus = async (e) => {
await axios
.put('http://192.168.0.105:5000/machine-status', { status: e.target.name })
.then((res) => {
console.log(res)
})
.catch((err) => console.log(err))
}
//To get real time data
useEffect(() => {
const socket = io.connect('http://192.168.0.105:5000/home')
socket.on('connect', (data) => console.log(data))
socket.on('newdata', (data) => console.log(data))
}, [])
I know that the while loop is the one causing the trouble cause the data is being thrown after the while loop is finish.
PS: I'm not sure if the react code also has a problem so I'll tag it.
The connect handler is not a good place to run a lengthy task, because Flask-SocketIO completes the connection process once you return from this handler.
I suggest you move your PlcTankData function to a separate event instead of calling it from the connect handler.
Related
I'm new to redux and I'm trying to fetch some data in my slice file, then put it in my state to use it across my app.
so I read the documentation in redux website. it says:
"Let's start by adding a thunk that will make an AJAX call to retrieve a list of posts. We'll import the client utility from the src/api folder, and use that to make a request to '/fakeApi/posts'."
and the code is:
import { createSlice, nanoid, createAsyncThunk } from '#reduxjs/toolkit'
import { client } from '../../api/client'
const initialState = {
posts: [],
status: 'idle',
error: null
}
export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {
const response = await client.get('/fakeApi/posts')
return response.data
})
so now I'm confused. How can I create the client file to use it?
and then, how can I save it in my state to re-use it?
it would be a huge help if you guide me!
Oh yeah now i understand what you want, client is just like fetch, i assume they are using axios , then in client.js file they are exporting axios at the end.
An example, client.js file:
import axios from "axios";
export const client = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
Then import it whereever you want:
import { client } from '../../api/client'
But you can also use axios directly without creating any instances .
As i said before you may use fetch instead, or any other http request package, but actually with axios you have more power and you can easily find a lot of documentations
You can get your reducer state with the use of useSelector and make sure
you write correct reducer state name instead of counter.
const count = useSelector((state) => state.counter.value);
You can dispatch your action by useDispatch hook and make sure you write correct action name instead of decrement.
const dispatch = useDispatch();
dispatch(decrement())
import of this two hooks
import { useSelector, useDispatch } from 'react-redux';
You can save your api response in posts state like this:
export const fetchPosts = createAsyncThunk('posts/fetchPosts', async ()
=> {
const response = await client.get('/fakeApi/posts')
state.posts = response.data
})
Full demo example of redux-toolkit: https://github.com/priyen27/redux-toolkit-demo
thanks for these answers. so I used it and now I get this error:
XHR failed loading: GET "https://excuser.herokuapp.com/v1/excuse"
that's the api link I want.
I used fetch as well and it worked correctly, but I don't know how to store it's data in my state. I used this function:
export async function fetchMyAPI() {
let response = await fetch(`https://excuser.herokuapp.com/v1/excuse`)
let data = await response.json()
return data[0].excuse
}
when I use it in my component and at the end I set is to some const it works perfect. but when I use it directly (like setData(fetchMyAPI())) it returns a promiss and I can't access data. what should I do? how can I store it in my state?
note that I fetch data in my slice component.
my final get api function:
const fetchExcuses = createAsyncThunk('excuses/fetchExcuses', async () => {
const response = await client.get('excuser.herokuapp.com/v1/excuse')
let data = await response.json()
})
I have made a lottery contract and now I want to connect it to the front-end which I will create with ReactJS. I have used Truffle framework for the deployment and tests for my contract.
npm i #truffle/contract
Then in utils/loadContract:
import contract from "#truffle/contract"
export const loadContract = async (name, provider) => {
// in truffle, contracts are in "contracts" directory
const res = await fetch(`/contracts/${name}.json`)
const Artifact = await res.json()
const _contract = contract(Artifact)
_contract.setProvider(provider)
let deployedContract = null
try {
deployedContract = await _contract.deployed()
} catch {
console.error("You are connected to the wrong network")
}
return deployedContract
}
Then load the contract inside app.jsx. First:
npm i #metamask/detect-provider
then write your code inside app.js
import detectEthereumProvider from '#metamask/detect-provider'
import { loadContract } from "./utils/load-contract";
import {useEffect, useState } from "react";
// in useEffect I load this state. So when your component is loaded, you would have access to web3Api.contract to call the contract methods
const [web3Api, setWeb3Api] = useState({
provider: null,
isProviderLoaded: false,
web3: null,
contract: null
})
// call this function inside useEFfect, if user connects to different account, you will update it
const setAccountListener = provider => {
provider.on("accountsChanged", _ => window.location.reload())
provider.on("chainChanged", _ => window.location.reload())
}
// useEffect is called before your component loaded
// load the contract, set the state, so when your compoent loaded, your state will be ready
useEffect(() => {
const loadProvider = async () => {
// if Metamask installed, this will detect its provider
const provider = await detectEthereumProvider()
// load the contract if provider exists
if (provider) {
// Lottery is not name of the file, it is NAME OF CONTRACT
const contract = await loadContract("Lottery", provider)
setAccountListener(provider)
setWeb3Api({
web3: new Web3(provider),
provider:provider,
// Now you set the contract.
// when your app.js loaded you will be able to call contract methods
contract:contract,
isProviderLoaded: true
})
} else {
setWeb3Api(api => ({...api, isProviderLoaded: true}))
console.error("Please, install Metamask.")
}
}
loadProvider()
}, [])
I'm working on a small react project and using axios interceptors to catch whether I'm in a localhost development environment or on the production deployed website.
What's happening is that when people sign up to my site, they click on the confirmation email link, and land on a certain "state" or whatever you call it or the application where the axios interceptor doesn't know what environment I'm on, and for a split second the wrong api call is made, to the right after it calling the right api uri.
Let me show this with some code:
export const App = () => {
useEffect(() => {
axios.interceptors.request.use((req) => {return { ...req, url: getBaseUri() + req.url
};})}, []);
return (
<div className="App">
<Routes />
</div>
)}
And then the methods:
const devUriBase = "http://localhost:8080";
const prodUriBase = "https://my-website.herokuapp.com";export function getBaseUri() {
return window.location.host.includes("localhost") ? devUriBase : prodUriBase;
}
Then on the verification page component, where I make the api call itself, for a moment the api call is made to the incorrect url so for a split second the component is shown, then it seems the useEffect jumps in and the api call is made again. None of the combinations I tried worked. I tried to make a config component and through children have the axios interceptor, putting this in the index instead, and I don't know what else. I've been struggling with this for 3 days, I thought it was time to ask.
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import { useToken } from '../../auth/useToken';
import { EmailVerificationSuccess } from './EmailVerificationSuccess';
import { EmailVerificationFail } from './EmailVerificationFail';
export const EmailVerificationLandingPage = () => {
const { verificationString } = useParams();
const [, setToken] = useToken();
const [state, setState] = useState('loading');
useEffect(() => {
const loadVerification = async () => {
try {
const response = await axios.put('/api/verify-email', { verificationString });
const { token } = response.data;
setToken(token);
setState('success');
} catch (e) {
setState('error');
}
}
loadVerification();
}, [setToken, verificationString]);
if (state === 'loading') return <p>Cargando...</p>;
if (state === 'error') return <EmailVerificationFail />
return <EmailVerificationSuccess />
I appreciate your help.
This did it.
When you add request interceptors, they are presumed to be asynchronous by default. This can cause a delay in the execution of your axios request when the main thread is blocked (a promise is created under the hood for the interceptor and your request gets put on the bottom of the call stack). If your request interceptors are synchronous you can add a flag to the options object that will tell axios to run the code synchronously and avoid any delays in request execution.
axios.interceptors.request.use(function (config) {
config.headers.test = 'I am only a header!';
return config;
}, null, { synchronous: true });
I am trying to mock my REST requests for a react/ts project when testing in Storybook using Axios. Even though I am setting the response to an array object, it still seems to be responding with a "Request failed with status code 404" status.
Here is my component making the REST call: TestPrompt.tsx
const onClickHandler = () => {
requestOrMock("http://localhost:9002/projectPlan/projectTasks?project=FAKEWID")
}
Here is the method my TestPrompt component is using to make the request: UtilityFunctions.ts
import axios from 'axios';
export const axiosMock = axios.create();
export const requestOrMock = async (uri: string) => {
const response = axiosMock.get(uri);
return response;
}
Here is my test that is mocking the response: Prompt.stories.tsx
import * as React from "react";
import {storiesOf} from '#storybook/react';
import TestPrompt from "../components/common/Prompt";
import MockAdapter from 'axios-mock-adapter';
import { axiosMock } from "../utils/utilityFunctions";
const mock = new MockAdapter(axiosMock);
const blankPromptRequestUri = "http://localhost:9002/projectPlan/projectTasks?project=FAKEWID";
const footballTeams = [
{
"descriptor": "New England Patriots",
"id": "NewEnglandPatriots"
},
{
"descriptor": "Seattle Seahawks",
"id": "SeattleSeahawks"
}
];
storiesOf('Components/MultiSelect', module)
.add('Prompt1', () => {
mock.onGet(blankPromptRequestUri).reply(200, footballTeams);
return (
<TestPrompt/>
);
})
When I click on this component in storybook, it sends out the request to the designated url, but it gets the 404 response rather than the footballTeams object I have specified. Any idea what I have done wrong? Thanks for your help.
If I get your problem correctly, you need to call onGet() of mock to setup the mock end point and then send a request to that end point.
mock.onGet("/teams").reply(200, footballTeams);
storiesOf('Components/MultiSelect', module)
.add('Prompt1', () => {
axios.get("/teams")
.then(res => console.log(res.data))
return (
<TestPrompt/>
);
})
The requests that were being made were being made relative to the host, so rather than "http://localhost:9002/projectPlan/projectTasks?project=FAKEWID" being sent, it was actually "/projectPlan/projectTasks?project=FAKEWID". It is likely that you will only need to pass in the routes here.
import firebase from "react-native-firebase";
remoteKey = "testJSON"
firebase
.config()
.fetch(0)
.then(() => {
return firebase.config().activateFetched();
})
.then(activated => {
if (!activated) console.log("Fetched data not activated");
return firebase.config().getKeysByPrefix(remoteKey);
});
I am calling this inside App.js in my react native project, but it gives the error "fetch() operation cannot be completed ,due to throttling"
What could be the issue ?
According to firebase documentation it means that config fetch was throttled
https://firebase.google.com/docs/reference/ios/firebaseremoteconfig/api/reference/Enums/FIRRemoteConfigFetchStatus?hl=vi
The Remote Config library has a client-side throttle to ensure you don’t ping the service too frequently. By setting your fetchDuration to 0, you’ll hit this throttle and your library will stop making calls.
Try changing .fetch(0) to .fetch() or use the following function to activate development mode
func activateDebugMode() {
let debugSettings = FIRRemoteConfigSettings(developerModeEnabled: true)
FIRRemoteConfig.remoteConfig().configSettings = debugSettings!
}
and call it before.
import firebase from "react-native-firebase";
remoteKey = "testJSON";
firebase
.config()
.fetch()
.then(() => {
return firebase.config().activateFetched();
})
.then(activated => {
if (!activated) console.log("Fetched data not activated");
return firebase.config().getKeysByPrefix(remoteKey);
});