Implement Socket.io like provider using NestJS - socket.io

I am new using NestJS, and I want to implement Socket.io like provider using NestJS.
I have this codes, but I am not sure how I need to do right the socket.module with provider:
socket.gateway.ts
import { Server } from 'socket.io';
import * as express from 'express';
import { createServer } from 'http';
import { WebSocketGateway, WebSocketServer } from '#nestjs/websockets';
import { Inject, Injectable } from '#nestjs/common';
const app = express();
const server = createServer(app);
const io = new Server(server);
interface IPlayer {
name: string;
position: { x: number; y: number; z: number };
rotation: { x: number; y: number; z: number };
health: number;
}
interface IEnemySpawnPoint {
position: { x: number; y: number; z: number };
rotation: { x: number; y: number; z: number };
}
#Injectable()
#WebSocketGateway()
export class SocketGateway {
#WebSocketServer()
SocketGateway(): void {
// global variables for the server
let enemies: IPlayer[] = [];
let playerSpawnPoints: IPlayer[] = [];
let clients: IPlayer[] = [];
io.on('connection', function (socket) {
let currentPlayer: IPlayer = {
name: 'unknown',
position: { x: 0, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
health: 0,
};
currentPlayer.name = 'unknown';
socket.on('player connect', function () {
console.log(currentPlayer.name + ' recv: player connect');
for (let i = 0; i < clients.length; i++) {
const playerConnected = {
name: clients[i].name,
position: clients[i].position,
rotation: clients[i].position,
health: clients[i].health,
};
// in your current game, we need to tell you about the other players.
socket.emit('other player connected', playerConnected);
console.log(
currentPlayer.name +
' emit: other player connected: ' +
JSON.stringify(playerConnected),
);
}
});
socket.on('play', function (data) {
console.log(
currentPlayer.name + ' recv: play: ' + JSON.stringify(data),
);
// if this is the first person to join the game init the enemies
let numberOfEnemies;
if (clients.length === 0) {
numberOfEnemies = data.enemySpawnPoints.length;
enemies = [];
data.enemySpawnPoints.forEach(function (
enemySpawnPoint: IEnemySpawnPoint,
) {
const enemy = {
name: guid(),
position: enemySpawnPoint.position,
rotation: enemySpawnPoint.rotation,
health: 100,
};
enemies.push(enemy);
});
playerSpawnPoints = [];
data.playerSpawnPoints.forEach(function (
_playerSpawnPoint: IEnemySpawnPoint,
) {
const playerSpawnPoint = {
name: guid(),
position: _playerSpawnPoint.position,
rotation: _playerSpawnPoint.rotation,
health: 100,
};
playerSpawnPoints.push(playerSpawnPoint);
});
}
const enemiesResponse = {
enemies: enemies,
};
// we always will send the enemies when the player joins
console.log(
currentPlayer.name +
' emit: enemies: ' +
JSON.stringify(enemiesResponse),
);
socket.emit('enemies', enemiesResponse);
const randomSpawnPoint =
playerSpawnPoints[
Math.floor(Math.random() * playerSpawnPoints.length)
];
currentPlayer = {
name: data.name,
position: randomSpawnPoint.position,
rotation: randomSpawnPoint.rotation,
health: 100,
};
clients.push(currentPlayer);
// in your current game, tell you that you have joined
console.log(
currentPlayer.name + ' emit: play: ' + JSON.stringify(currentPlayer),
);
socket.emit('play', currentPlayer);
// in your current game, we need to tell the other players about you.
socket.broadcast.emit('other player connected', currentPlayer);
});
socket.on('player move', function (data) {
console.log('recv: move: ' + JSON.stringify(data));
currentPlayer.position = data.position;
socket.broadcast.emit('player move', currentPlayer);
});
socket.on('player turn', function (data) {
console.log('recv: turn: ' + JSON.stringify(data));
currentPlayer.rotation = data.rotation;
socket.broadcast.emit('player turn', currentPlayer);
});
socket.on('player shoot', function () {
console.log(currentPlayer.name + ' recv: shoot');
const data = {
name: currentPlayer.name,
};
console.log(
currentPlayer.name + ' bcst: shoot: ' + JSON.stringify(data),
);
socket.emit('player shoot', data);
socket.broadcast.emit('player shoot', data);
});
socket.on('health', function (data) {
console.log(
currentPlayer.name + ' recv: health: ' + JSON.stringify(data),
);
// only change the health once, we can do this by checking the originating player
if (data.from === currentPlayer.name) {
let indexDamaged = 0;
if (!data.isEnemy) {
clients = clients.map(function (client, index) {
if (client.name === data.name) {
indexDamaged = index;
client.health -= data.healthChange;
}
return client;
});
} else {
enemies = enemies.map(function (enemy, index) {
if (enemy.name === data.name) {
indexDamaged = index;
enemy.health -= data.healthChange;
}
return enemy;
});
}
const response = {
name: !data.isEnemy
? clients[indexDamaged].name
: enemies[indexDamaged].name,
health: !data.isEnemy
? clients[indexDamaged].health
: enemies[indexDamaged].health,
};
console.log(
currentPlayer.name + ' bcst: health: ' + JSON.stringify(response),
);
socket.emit('health', response);
socket.broadcast.emit('health', response);
}
});
socket.on('message', function (message) {
console.log('message', message);
socket.emit('message', message);
});
socket.on('disconnect', function () {
console.log(
currentPlayer.name + ' recv: disconnect ' + currentPlayer.name,
);
socket.broadcast.emit('other player disconnected', currentPlayer);
console.log(
currentPlayer.name +
' bcst: other player disconnected ' +
JSON.stringify(currentPlayer),
);
for (let i = 0; i < clients.length; i++) {
if (clients[i].name === currentPlayer.name) {
clients.splice(i, 1);
}
}
});
});
console.log('--- server is running ...', process.env.PORT || 80);
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return (
s4() +
s4() +
'-' +
s4() +
'-' +
s4() +
'-' +
s4() +
'-' +
s4() +
s4() +
s4()
);
}
}
}
socket.module.ts
import { Module } from '#nestjs/common';
import { SocketGateway } from '#src/socket/socket.gateway';
#Module({
providers: [
{
provide: 'SOCKET_CONNECTION',
useFactory: async (): Promise<SocketGateway> => {
return new SocketGateway();
},
},
],
})
export class SocketModule {}
main.ts
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
import { Transport } from '#nestjs/microservices';
import { join } from 'path';
import helmet from 'helmet';
import { DocumentBuilder, SwaggerModule } from '#nestjs/swagger';
import * as dotenv from 'dotenv';
// import { Server } from 'http';
import { Server } from 'socket.io';
import * as express from 'express';
import { createServer } from 'http';
dotenv.config({ path: '.env' });
async function bootstrap(): Promise<void> {
const microservice = await NestFactory.createMicroservice(AppModule, {
transport: Transport.GRPC,
options: {
package: 'engine',
protoPath: join(__dirname, 'engine.proto'),
},
});
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle('Engine')
.setDescription('The engine API description')
.setVersion('v1')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('swagger', app, document);
const allowedOrigin = new RegExp(
JSON.parse(process.env.ALLOWED_ORIGIN).join('|'),
);
app.enableCors({
origin: allowedOrigin,
optionsSuccessStatus: 200,
});
app.use(helmet());
app.setGlobalPrefix('v1/api/', {
exclude: ['/health'],
});
await microservice.listen();
const expressApp = express();
const server = createServer(expressApp);
const io = new Server(server);
// set up the socket.io server to use the same port as the HTTP server
const PORT = process.env.PORT || 3000;
await app.listen(PORT);
}
bootstrap();
I tried many things but I thwy usually had errors, or didn't work. I am not sure if I did all right, so I will be glad to all kind of help and solutions.
I need to use socket.io, not websocket

Related

How to use React useContext with leaflet routing machine and react leaflet?

I'm trying to use a useContext hook inside a react-leaflet controlComponent but I have an error when my context fires the update function.
I use a react-leaflet controlComponent because of leaflet routing machine. I think the code + the error are better than word:
MainBoard.tsx
export const CartographyContext: React.Context<CartographyContextType> = React.createContext<CartographyContextType>({ positions: [] });
...
const routeSummaryValueContext = React.useMemo(
() => ({ routeSummary, setRouteSummary }),
[routeSummary]
);
const elevationProfileValueContext = React.useMemo(
() => ({ elevationProfile, setElevationProfile }),
[elevationProfile]
);
........
<CartographyContext.Provider value={{ positions, elevationProfileValueContext, routeSummaryValueContext, positionsValueContext, addPosition, changePosition }}>
.........
<RoutingMachine
orsOptions={{
....
}} />
..........
</CartographyContext.Provider>
RoutingMachine.tsx:
const CreateRoutineMachineLayer = (props: any) => {
const geoService = new GeoLocalisationService();
const cartographyContext: CartographyContextType = React.useContext<CartographyContextType>(CartographyContext);
const [routes, setRoutes] = React.useState<any[]>();
React.useEffect(() => {
if (routes) {
//The line which cause the error
cartographyContext.elevationProfileValueContext.setElevationProfile(geoService.getElevationProfile(decodePolyline(routes[0].geometry, true)));
const summary: RouteSummary = {
ascent: routes[0].routeSummary.ascent,
descent: routes[0].routeSummary.descent,
distance: routes[0].routeSummary.distance,
estimatedDuration: routes[0].routeSummary.duration
}
cartographyContext.routeSummaryValueContext.setRouteSummary(summary);
}
}, [routes]);
const { orsOptions } = props;
const instance = L.Routing.control({
router: new OpenRouteRouter(orsOptions),
lineOptions: {
styles: [{ color: "#3933ff", weight: 4 }],
extendToWaypoints: true,
missingRouteTolerance: 0
},
routeWhileDragging: true,
autoRoute: true,
geocoder: new geocoder.Geocoder(),
}).on('routesfound', (e) => {
setRoutes(e.routes);
});
useMapEvents({
click: (e: L.LeafletMouseEvent) => {
if (instance.getWaypoints().length === 2 && instance.getWaypoints()[0].latLng == null) {
instance.spliceWaypoints(0, 1, new L.Routing.Waypoint(e.latlng, null, {}));
} else if (instance.getWaypoints().length === 2 && instance.getWaypoints()[1].latLng == null) {
instance.spliceWaypoints(1, 1, new L.Routing.Waypoint(e.latlng, null, {}));
} else {
instance.spliceWaypoints(instance.getWaypoints().length, 0, new L.Routing.Waypoint(e.latlng, null, {}));
}
}
});
return instance;
};
const RoutingMachine = createControlComponent(CreateRoutineMachineLayer);
error :
g: React has detected a change in the order of Hooks called by ForwardRef(LeafComponent). 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. useRef useRef
3. useContext useRef
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
..............
Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.
I clearly doing something wrong here but I haven't found yet.
Thank you
Kind regards
Ok I found the good implementation :
const RoutingMachine: React.FC<RoutingMachineProps> = (props) => {
//const RoutineMachine = (props: any) => {
const geoService = new GeoLocalisationService();
const cartographyContext: CartographyContextType = React.useContext<CartographyContextType>(CartographyContext);
const [instance, setInstance] = React.useState<any>();
const [alreadyDisplayed, setAlreadyDisplayed] = React.useState(false);
const { orsOptions } = props;
const map = useMap();
//const instance = L.Routing.control({
React.useEffect(() => {
const instance = L.Routing.control({
router: new OpenRouteRouter(orsOptions),
lineOptions: {
styles: [{ color: "#3933ff", weight: 4 }],
extendToWaypoints: true,
missingRouteTolerance: 0
},
routeWhileDragging: true,
autoRoute: true,
geocoder: (L.Control as any).Geocoder.google({
apiKey: GOOGLE.googleMapApiKey,
}),
}).on('routesfound', (e) => {
const routes = e.routes;
cartographyContext.setElevationProfile(geoService.getElevationProfile(decodePolyline(routes[0].geometry, true)));
const summary: RouteSummary = {
ascent: routes[0].routeSummary.ascent,
descent: routes[0].routeSummary.descent,
distance: routes[0].routeSummary.distance,
estimatedDuration: routes[0].routeSummary.duration
}
cartographyContext.setRouteSummary(summary);
})
setInstance(instance);
instance.addTo(map);
}, []);
useMapEvents({
click: (e: L.LeafletMouseEvent) => {
if (instance) {
if (instance.getWaypoints().length === 2 && instance.getWaypoints()[0].latLng == null) {
instance.spliceWaypoints(0, 1, new L.Routing.Waypoint(e.latlng, null, {}));
} else if (instance.getWaypoints().length === 2 && instance.getWaypoints()[1].latLng == null) {
instance.spliceWaypoints(1, 1, new L.Routing.Waypoint(e.latlng, null, {}));
} else {
instance.spliceWaypoints(instance.getWaypoints().length, 0, new L.Routing.Waypoint(e.latlng, null, {}));
}
}
}
});
return null;
};
export default RoutingMachine;

apollo graphql network errors

I have tried to resolve this network errors but it has no possible and I do not know what is causing this. This is my apollo server index:
const mongoose = require('mongoose')
const {ObjectId} = require('mongodb')
const { createServer } = require('http')
const { execute, subscribe } = require('graphql')
const { SubscriptionServer } = require('subscriptions-transport-ws')
const { makeExecutableSchema } = require ('#graphql-tools/schema')
const express = require('express')
const { ApolloServer } = require('apollo-server-express')
const {resolvers,typeDefs} = require('./graphql')
const jwt = require('jsonwebtoken')
const {onConnect,onDisconnect} = require('./controllers/User')
require('dotenv').config()
const graphqlUploadExpress = require('graphql-upload/graphqlUploadExpress.js')
const { EventEmitter } = require('events')
const { PubSub } =require('graphql-subscriptions')
const { RedisPubSub } =require('graphql-redis-subscriptions')
const Redis = require('ioredis')
const
{
ApolloServerPluginDrainHttpServer,
ApolloServerPluginLandingPageGraphQLPlayground,
ApolloServerPluginLandingPageLocalDefault
} = require('apollo-server-core')
const { WebSocketServer} = require('ws')
const {useServer } = require('graphql-ws/lib/use/ws')
const path = require('path')
const bodyParser = require('body-parser')
const biggerEventEmitter = new EventEmitter();
biggerEventEmitter.setMaxListeners(0);
const options = {
host: process.env.REDIS_DOMAIN_NAME,
port: process.env.PORT_NUMBER,
password:process.env.REDIS_PASSWORD,
retryStrategy: times => {
// reconnect after
return Math.min(times * 50, 2000);
}
};
const pubsub = process.env.NODE_ENV === 'development' ? new PubSub({eventEmitter: biggerEventEmitter}) : new RedisPubSub({
publisher: new Redis(options),
subscriber: new Redis(options)
});
mongoose.connect(process.env.BBDD,
{},(err,_)=>
{
if(err)
{
console.log("Error de conexion")
}
else
{
console.log("Conexion Base de datos Correcta")
server()
}
})
async function server()
{
const app = express()
const httpServer = createServer(app)
const schema = makeExecutableSchema({ typeDefs, resolvers })
const PORT = process.env.APP_PORT
const getDynamicContext = async (ctx, msg, args) => {
if (ctx.connectionParams.authToken) {
const user = jwt.verify(ctx.connectionParams.authToken.replace("Bearer ", ""),process.env.KEY);
return { user, pubsub};
}
return { user: null };
};
const wsServer = new WebSocketServer(
{
server: httpServer,
path: '/graphql'
})
const serverCleanup = useServer({
schema,
context: (ctx, msg, args) => {
return getDynamicContext(ctx, msg, args)
},
onConnect: async (ctx) => {
console.log('onConnect');
let connectionParams = ctx.connectionParams
try
{
if (connectionParams.authToken)
{
const user = jwt.verify(connectionParams.authToken.replace("Bearer ", ""),process.env.KEY)
await onConnect(user.id,pubsub)
return { user , pubsub}
}
}
catch(error)
{
throw new Error('Missing auth token!')
}
},
async onDisconnect(context)
{
console.log('onDisconnect');
try
{
if(context.connectionParams&&context.connectionParams.authToken)
{
const user = jwt.verify(context.connectionParams.authToken.replace("Bearer ", ""),process.env.KEY)
await onDisconnect(user.id,pubsub)
}
}
catch(error)
{
/* throw new Error('Missing context!') */
}
}, }, wsServer)
const server = new ApolloServer(
{
schema,
persistedQueries:false,
context: async ({ req ,connection }) =>
{
let authorization = req.headers.authorization
try
{
if(authorization)
{
user = jwt.verify(authorization.replace("Bearer ", ""),process.env.KEY)
return{
user,
pubsub
}
}
}
catch (error)
{
throw new Error("Token invalido");
}
},
csrfPrevention: true,
cache: 'bounded',
plugins: [ApolloServerPluginDrainHttpServer({ httpServer }),
ApolloServerPluginLandingPageLocalDefault({ embed: true }),
{
async serverWillStart() {
return {
async drainServer() {
await serverCleanup.dispose();
},
};
},
}]
})
app.use(graphqlUploadExpress())
await server.start()
server.applyMiddleware({ app })
httpServer.listen(process.env.PORT||4000, () => {
console.log(
`Server is now running on http://localhost:${process.env.PORT||4000}${server.graphqlPath}`,
);
});
}
And this is my apollo client config:
import {ApolloClient,createHttpLink,defaultDataIdFromObject,InMemoryCache,split} from '#apollo/client'
import {WebSocketLink} from '#apollo/client/link/ws'
import { getMainDefinition } from '#apollo/client/utilities'
import { setContext } from "apollo-link-context"
import {createUploadLink} from 'apollo-upload-client'
import {getToken, getUpdatedTokenApi} from '../utils/auth'
import { GraphQLWsLink } from '#apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
import { from, HttpLink } from '#apollo/client';
import { RetryLink } from '#apollo/client/link/retry';
import { disableFragmentWarnings } from 'graphql-tag';
disableFragmentWarnings()
const type = () =>
{
if(window.location.pathname.startsWith(`/${process.env.ADMIN_DEV}`))
{
return 'admin'
}
else
{
return null
}
}
const link = (e)=>
{
switch (e) {
case 1:
return 'https://unglo.herokuapp.com/graphql'
case 2:
return 'http://localhost:4000/graphql'
default:
break;
}
}
const ws_Link = (e)=>
{
switch (e) {
case 1:
return 'wss://unglo.herokuapp.com/graphql'
case 2:
return 'ws://localhost:4000/graphql'
default:
break;
}
}
import { onError } from "#apollo/client/link/error";
// Log any GraphQL errors or network error that occurred
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
if (networkError) console.log(`[Network error]: ${networkError}`);
});
const token = getToken(type())
const updatedToken = getUpdatedTokenApi()
const httpLink = new createUploadLink({
uri: link(2),
headers: {
'Apollo-Require-Preflight': 'true',
},
});
const wsLink = new GraphQLWsLink(createClient(
{
url: ws_Link(2),
connectionParams:
{
authToken: token ? `Bearer ${token}` : updatedToken ? `Bearer ${updatedToken}` : "",
},
lazy:true,
}
))
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink,
errorLink
);
const authMiddleware = setContext((_, { headers }) =>
{
return {
headers:
{
...headers,
Authorization: token ? `Bearer ${token}` :updatedToken ? `Bearer ${updatedToken}` : "",
},
}
})
const client = new ApolloClient
({
ssrMode: true,
connectToDevTools:true,
cache: new InMemoryCache({
}),
link:authMiddleware.concat(splitLink),
})
export default client
And these are errors:
I have tried removing all apollo cliente queries and errors persists and google console dont show error details
Please if any body know about this kind of errors it shoud be helpfull

React Redux state undefined in mapStateToProps

I am having trouble with state being undefined in mapStateToProps in my React Redux app. The only way I can get it to work is to use store.getState(), but I know this is not the correct way to do it. If I log the state to the console, I get undefined (and if I try to map state to properties, I also get undefined). I am stumped as to why this is happening. I feel like I am missing something fundamental, but I just can't put my finger on it. I know using Redux would not be practical normally for a simple app like this, but I just wanted to practise using it. Any help would be appreciated!
This is my mapStateToProps function:
const mapStateToProps = (state) => {
console.log(state); //Returns undefined
tempState = store.getState(); //Why do I have to do this?
return {
text: tempState.reduxText,
author: tempState.reduxAuthor,
backgroundColor: tempState.reduxBackgroundColor,
buttonColor: tempState.reduxButtonColor,
textColor: tempState.reduxTextColor,
tweetURL: tempState.reduxTweetURL,
textFade: tempState.reduxTextFade
}
}
These are my actions and action creators:
const CHANGE_QUOTE_ACTION = 'CHANGE_QUOTE_ACTION';
const CHANGE_QUOTE_TRANSITION = 'CHANGE_QUOTE_TRANSITION';
const changeQuoteActionCreator = () => {
return {
type: CHANGE_QUOTE_ACTION,
payload: {
reduxText: quoteArr[quoteRandomIndex][0],
reduxAuthor: quoteArr[quoteRandomIndex][1],
reduxTweetURL: 'https://twitter.com/intent/tweet?text=\"' + quoteArr[quoteRandomIndex][0] + '\" ' + quoteArr[quoteRandomIndex][1],
reduxTextFade: 'textVisible '
}
}
}
const changeQuoteTransitionActionCreator = () => {
while (quoteArr[quoteRandomIndex][0] == store.getState().reduxText) {
quoteRandomIndex = Math.floor(Math.random() * 10);
}
while ('container-fluid ' + colorArr[colorRandomIndex] + '-color' == store.getState().reduxBackgroundColor) {
colorRandomIndex = Math.floor(Math.random() * 8);
};
return {
type: CHANGE_QUOTE_TRANSITION,
payload: {
reduxBackgroundColor: 'container-fluid ' + colorArr[colorRandomIndex] + '-color',
reduxButtonColor: 'btn btn-outline shadow-none text-white ' + colorArr[colorRandomIndex] + '-color ' + colorArr[colorRandomIndex] + '-hoverColor',
reduxTextColor: colorArr[colorRandomIndex] + '-textColor',
reduxTextFade: 'textInvisible'
}
}
}
const asyncChangeQuoteActionCreator = () => {
return function (dispatch) {
dispatch(changeQuoteTransitionActionCreator());
setTimeout(function () {
dispatch(changeQuoteActionCreator());
}, 1000);
};
}
This is my reducer:
initialReduxState = {
reduxText: '',
reduxAuthor: '',
reduxBackgroundColor: 'container-fluid ' + colorArr[initialColorRandomIndex] + '-color',
reduxButtonColor: 'btn btn-outline shadow-none text-white ' + colorArr[initialColorRandomIndex] + '-color ' + colorArr[initialColorRandomIndex] + '-hoverColor',
reduxTextColor: colorArr[initialColorRandomIndex] + '-textColor',
reduxTweetURL: ''
}
//Redux reducer
const changeQuoteReducer = (state = initialReduxState, action) => {
switch (action.type) {
case CHANGE_QUOTE_ACTION:
return Object.assign({}, state, { reduxText: action.payload.reduxText, reduxAuthor: action.payload.reduxAuthor, reduxTweetURL: action.payload.reduxTweetURL, reduxTextFade: action.payload.reduxTextFade });
case CHANGE_QUOTE_TRANSITION:
return Object.assign({}, state, { reduxBackgroundColor: action.payload.reduxBackgroundColor, reduxButtonColor: action.payload.reduxButtonColor, reduxTextColor: action.payload.reduxTextColor, reduxTextFade: action.payload.reduxTextFade })
default:
return state;
}
}
This is connecting to the store:
const store = Redux.createStore(
changeQuoteReducer,
Redux.applyMiddleware(ReduxThunk.default)
);
const Provider = ReactRedux.Provider;
const connect = ReactRedux.connect;
This is mapDispatchToProps:
const mapDispatchToProps = (dispatch) => {
return {
changeQuoteDispatch: () => {
dispatch(asyncChangeQuoteActionCreator())
}
}
}
Subscribing to the store, dispatching to the store and connecting Redux to React:
store.subscribe(mapStateToProps);
store.dispatch(mapDispatchToProps);
const Container = connect(mapStateToProps, mapDispatchToProps)(Presentational);

How to make Compass in nativescript when i am unable to find north direction?

I am working on nativescript , but There are serious lack of libraries in it. I am not able to find north direction.
i have tried plugin
import * as geolocation from "nativescript-geolocation";
import { Accuracy } from "tns-core-modules/ui/enums";
test:function() {
var a = geolocation.getCurrentLocation({ desiredAccuracy: Accuracy.high, maximumAge: 5000, timeout: 20000 })
;
a.then( return_a => {
console.log("this------------------------------->",return_a);
//distance(return_a,);
var degree = angleFromCoordinate(return_a.latitude,return_a.longitude , 21.4225,39.8262);
console.log(degree);
this.gaugeValue = degree;//return_a.verticalAccuracy
});
}
});
function angleFromCoordinate( lat1, long1, lat2, long2) {
var dLon = (long2 - long1);
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
var brng = Math.atan2(y, x);
brng = brng * 180 / Math.PI;
brng = (brng + 360) % 360;
brng = 360 - brng; // count degrees counter-clockwise - remove to make clockwise
return brng;
}
There is direction property also available.but it is always -1 .
i am using Typescript , javascript as template language.
Here I found the solution. You need to do it manually.
import * as app from "tns-core-modules/application";
import { isAndroid, isIOS } from "tns-core-modules/platform";
declare const android: any;
declare const CLLocationManager: any;
export class MyClass {
private sensorUpdate: any;
private sensorManager: any;
startHeadingUpdates() {
if (this.sensorManager || this.sensorUpdate) {
return;
}
if (isIOS) {
this.sensorManager = CLLocationManager.alloc().init();
if (this.sensorManager.headingAvailable) {
this.sensorManager.startUpdatingHeading();
this.sensorUpdate = setInterval(() => {
console.log(this.sensorManager.heading.trueHeading);
}, 100);
} else {
console.log("Heading not available.");
}
return;
}
if (isAndroid) {
this.sensorManager = app.android.foregroundActivity.getSystemService(
android.content.Context.SENSOR_SERVICE
);
this.sensorUpdate = new android.hardware.SensorEventListener({
onAccuracyChanged: (sensor: any, accuracy: any) => {
// console.log(accuracy)
},
onSensorChanged: (event: any) => {
console.log(event.values[0]);
}
});
const orientationSensor = this.sensorManager.getDefaultSensor(
android.hardware.Sensor.TYPE_ORIENTATION
);
this.sensorManager.registerListener(
this.sensorUpdate,
orientationSensor,
android.hardware.SensorManager.SENSOR_DELAY_UI
);
}
}
stopUpdatingHeading() {
if (!this.sensorManager || !this.sensorUpdate) {
return;
}
if (isIOS) {
this.sensorManager.stopUpdatingHeading();
clearInterval(this.sensorUpdate);
this.sensorManager = null;
return;
}
if (isAndroid) {
this.sensorManager.unregisterListener(this.sensorUpdate);
this.sensorManager = null;
}
}
}

Node.js getitem from dynamoDB and pass variable

I'm working on some labmda code in Node.js, and I want to pass an item gotten from DynamoDB with getitem to some code. Here's what I have:
const Alexa = require('ask-sdk');
const AWS = require ('aws-sdk');
AWS.config.update({region: 'us-east-1'});
//replace dynamo later with dynamo
dynamodb = new AWS.DynamoDB();
//const appId = 'REPLACE WITH YOUR SKILL APPLICATION ID';
const date = new Date(Date.now()).toString();
const date2 = date.substring(0,16);
const time = date.substring(16,24);
const LaunchRequestHandler = {
canHandle(handlerInput) {
//first we assign the requestEnvelope request to the request variable
const request = handlerInput.requestEnvelope.request;
//conditions to determine the requests this handler can handle
//now using the request variable, we return true if it equals the one we want
//in this case LaunchRequest
return request.type === 'LaunchRequest'
},
handle(handlerInput) {
//execution logic for the handler
// ie What exactly do we do
const speechOutput =
"Welcome to Track it, you can tell me who you lent things to, \
or where you put an item. For example I lent the saw to Mike, or I put the saw in the workshop."
return handlerInput.responseBuilder
.speak(speechOutput)
.getResponse();
}
}
const GaveIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'GaveIntent';
},
handle(handlerInput,event) {
// setting variable attributes to handle things like counters
const attributes = handlerInput.attributesManager.getSessionAttributes();
// personName and itemName are pulling the slots information from the intent
const personName = handlerInput.requestEnvelope.request.intent.slots.lenderPerson.value;
const itemName = handlerInput.requestEnvelope.request.intent.slots.storedObject.value;
const currentUser = handlerInput.requestEnvelope.session.user.userId;
//begin DB code
var params = {
TableName: 'TrackItDB',
Item: {
'userID' : {S: currentUser},
'storedObject' : {S: itemName},
'lenderPerson' : {S: personName},
'objectStatus' : {S: 'lent'},
'transactionDate': {S: date},
},
ConditionExpression: 'attribute_not_exists(storedObject)'
};
console.log(params);
// putItem in database only if it doesn't already exist
dynamodb.putItem(params, function(err, data) {
if (err) {
console.log("Error", err);
console.log("That item already exists");
} else {
console.log("Success", data);
}
});
console.log(personName);
console.log(itemName);
console.log(currentUser);
const speechOutput = 'You Gave ' + personName + ' the ' + itemName;
return handlerInput.responseBuilder
.speak(speechOutput)
.withSimpleCard('Track It', speechOutput)
.getResponse();
}
};
const PutIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'PutIntent';
},
handle(handlerInput) {
const itemName = handlerInput.requestEnvelope.request.intent.slots.storedObject.value;
const LocationName = handlerInput.requestEnvelope.request.intent.slots.storageLocation.value;
const currentUser = handlerInput.requestEnvelope.session.user.userId;
//begin DB code
var params = {
TableName: 'TrackItDB',
Item: {
'userID' : {S: currentUser},
'storedObject' : {S: itemName},
'lenderPerson' : {S: LocationName},
'objectStatus' : {S: 'stored'},
'transactionDate': {S: date},
},
ConditionExpression: 'attribute_not_exists(storedObject)'
};
dynamodb.putItem(params, function(err, data) {
if (err) {
console.log("Error", err);
console.log("That item already exists");
}
else {
console.log("Success", data);
}
});
//end DB code
const speechOutput = 'You put the ' + itemName + ' in the ' + LocationName;
return handlerInput.responseBuilder
.speak(speechOutput)
.withSimpleCard('Hello World', speechOutput)
.getResponse();
}
};
const WhereIsIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'WhereIsIntent';
},
handle(handlerInput) {
const itemName = handlerInput.requestEnvelope.request.intent.slots.storedObject.value;
const currentUser = handlerInput.requestEnvelope.session.user.userId;
// begin DB query
var params = {
Key: {
"userID": {
S: currentUser
},
"storedObject": {
S: itemName
}
},
TableName: "TrackItDB"
};
// End DB Query
dynamodb.getItem(params, function(err, data) {
if (err) {
console.log("Error", err);
}// an error occurred
else {
console.log("Success", data); // successful response
const LocationName = data.Item.lenderPerson.S;
const speechOutput = 'Your ' + itemName + ' is in the ' + LocationName;
return handlerInput.responseBuilder
.speak(speechOutput)
.withSimpleCard('Hello World', speechOutput)
.getResponse();
}
});
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speechOutput = 'Welcome to Track it, you can tell me who you lent things to, or where you put an item. For example I lent the saw to Mike, or I put the saw in the workshop.';
return handlerInput.responseBuilder
.speak(speechOutput)
.reprompt(speechOutput)
.withSimpleCard('Hello World', speechOutput)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
|| handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speechOutput = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speechOutput)
.withSimpleCard('Hello World', speechOutput)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
//any cleanup logic goes here
return handlerInput.responseBuilder.getResponse();
}
};
const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
.addRequestHandlers(
LaunchRequestHandler,
GaveIntentHandler,
PutIntentHandler,
WhereIsIntentHandler,
HelpIntentHandler,
SessionEndedRequestHandler,
CancelAndStopIntentHandler
)
.lambda()
I'm trying to pass the "itemName and LocationName to the const speechOutput variable so I can have Alexa speak it for me.
It will work in the console log, but not later outside the getitem function. FYI, I know I shouldn't have the const speechOutput twice, and it isn't like that in my code; I just put it there to show what I'm trying to do.
You need to move the responseBuilder code snippet within the getItem function' else part.
Do not declare the const speechOutput twice.
handle(handlerInput) {
const itemName =
handlerInput.requestEnvelope.request.intent.slots.storedObject.value;
const currentUser =
handlerInput.requestEnvelope.session.user.userId;
// Begin database query
var params = {
Key: {
"userID": {
S: currentUser
},
"storedObject": {
S: itemName
}
},
TableName: "TrackItDB"
};
// End DB Query
//const speechOutput = 'test'
dynamodb.getItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} // An error occurred
else {
console.log("Success", data); // Successful
// response
const LocationName = data.Item.lenderPerson.S;
const speechOutput = 'Your ' + itemName + ' is in the ' +
LocationName;
// Speak the output
return handlerInput.responseBuilder
.speak(speechOutput)
.withSimpleCard('Hello, World!', speechOutput)
.getResponse();
console.log(speechOutput);
}
});
//const speechOutput = 'Your ' + itemName + ' is in the ' +
LocationName;
}

Resources