Google Assistant Input to Python Output - javascript

the question is pretty straight forward. I would like to control a drone (Bitcraze Crazyflie), using a Google Home. The Input is: "Drone fly to x3 y4", processed as usual by Firebase etc. Resulting in the Google Assistant Output: "Flying to x3 y4", but also an Ouput in e.g. JSON format, to navigate the drone. Because the drone works with Python, this is the preferable Output language.
EDIT Added more Context
Currently I'm using an node server running this code:
'use strict';
// Import the Dialogflow module from the Actions on Google client library.
const {dialogflow} = require('actions-on-google');
// Import the firebase-functions package for deployment.
const functions = require('firebase-functions');
// Instantiate the Dialogflow client.
const app = dialogflow({debug: true});
// Handle the Dialogflow intent named 'fly'.
// The intent collects parameters named 'xaxis, yaxis'.
app.intent('fly', (conv, {xaxis,yaxis}) => {
const xAxis = xaxis;
const yAxis = yaxis;
// Respond with the user's coordinates and end the conversation.
conv.close('Roger that, flying to ' + xAxis + ", " + yAxis);
});
// Set the DialogflowApp object to handle the HTTPS POST request.
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
Now I would like to get the const xAxis and yAxis and use them in a Python program. I've tried using
process.stdout.write(xAxis + yAxis);
Listening in Python with something like
out = sensor.stdout.read(1)
but the code will be run on the Google Server, so local port listening does not work.
Thanks for your help.

The best approach is having another machine on GCP rather than communicate with your home PC. You'll learn more and have an easier time, in the long run, building solutions. As I'm more familiar with AWS rather than GCP, I can't cite the network/security components you need to configure but the docs say you don't have to. So, in theory, it should be just about spinning up another compute machine with your Python code running on it.
Were you to decide on speaking to your home PC, you'll need to forward ports on your router. It is, currently, acting as a firewall for your LAN devices and doesn't permit outside machines initiating connections to your internal addresses. e.g. your GCP machine initiating a connection to your home PC. The other way around is permitted, by default. If you think about it, your router has one WAN IP address but your LAN can have multiple devices (multiple LAN IPs). If your GCP machine connects to your router WAN IP at port 8080, to which LAN IP should it connect? You have to help your router and explicitly tell it.
Once you have a networking solution in place, you can debug the connectivity itself (server can talk to client) by using netcat (nc/ncat, depending on Linux distro). Netcat is a versatile networking tool with which you can purely open connections (before you add in your program to the debugging stack) and assure the networking part of your solution is working as intended.
nc -v <destination_ip> <port>
Simple.
This should get you to where you want to be. A working connection between your GCP drone controller and the Python processor machine.
Bonus - If you want a quick way to have your machine (PC or otherwise) listen on a port, you can use Python's built-in HTTP file server module with
python -m http.server 8080
This will serve files from the directory you ran this command. So, keep that in mind if you're open to the world.
Or, a simple "echo server", using netcat.
nc -v -l 8080
Lastly, for a solid Python HTTP API framework, I highly recommend FastAPI. It allows quickly writing a HTTP API server with, for example, a POST method that your GCP drone controller can call. It has the great bonus of generating both interactive OpenAPI docs, example, for your code and, using 3rd party tools from Swagger (that you can see in the example linked), generate server/client/testing "boiler plate" code. Did I also mention their docs are great?

Related

Excel Javascript Add-in Deployment On Local Network

I have developed an Excel Javascript Add-in on my machine using the yeoman generator. The add-in itself works fine when I start it up on my client with npm start. I can use the add-in on any port I want provided I change all the ports in the config files etc. However, we now want to delpoy this add-in on our local server to make it available to several users.
I have noticed that every time I change the location of the project e.g. from my machine to the server the application will start up but Excel will give me the error message "ADD-IN ERROR Sorry, we can't load the add-in. Please make sure you have network and/or Internet connectivity. Click "Retry" once you are back online". My work around for now is to create a new app on the server and copy the html, js and css file to the taskpane folder. When I now start up the new app it'll work fine.
For the second issue I haven't found a solution/understood the behaviour. When I create an app with the yeoman generator on our server (MS server 2019) and start it up it can be reached via e.g. localhost:3000 on the server but not via :3000 or :3000. It runs fine when I access it from the server itself.
I have opened the inbound and outbound port 3000 on the server to allow https communication. In a next step I added the manifest to the windows 365 admin console and added myself as user. When I open Excel from my machine (client side) the excel add-in will be available in the insert ribbon but won't load and I get the same error message as described above "ADD-IN ERROR Sorry, we can't load the add-in. Please make sure you have network and/or Internet connectivity. Click "Retry" once you are back online"
The following troubleshooting steps have been performed. I checked whether I can reach the add-in url via web browser but the connection timed out. When I check on the server side whether the app is listening I get the below result.
TCP 127.0.0.1:3000 0.0.0.0 Listening 40776
I'm not sure but I think the app should list on e.g. 0.0.0.0:3000 to capture inbound traffic from the client side. Is there a way to change this add-in (app) behaviour on the server when creating/starting up the app with the yeoman generator? I have checked the webpack.config.js file but I couldn't find any way to change that behaviour.
Any idea/help is appreciated.
Thanks!
I believe this is precisely the intended configuration of the yeoman development environment. It spins up the webpack dev (NodeJS) server, which by default only listens to the localhost / loopback address.
From here:
https://webpack.js.org/configuration/dev-server/#devserverhost
It looks like you could hand modify your webpack.config.js file to include a
host: '0.0.0.0' entry under the devServer listing.
The other item you might need to change is
https://webpack.js.org/configuration/dev-server/#devserverallowedhosts
As I believe this defaults to 'auto' which would only allow connections from the local computer.

registering socket IO to vite for sveltekit

I have written a few apps using svelte and sapper and thought I would give sveltekit a go.
All in all it works, but I am now running into the issue of registering a worker on ther server.
Basically I am trying to add socket.io to my app because I want to be able to send and receive data from the server. With sapper this wasn't really an issue because you had the server.js file where you could connect socket.io to the polka/express server. But I cannot find any equivalent in sveltekit and vite.
I experimented a bit and I can create a new socket.io server in a route, but that will lead to a bunch of new problems, such as it being on a separate port and causing cors issues.
So I am wondering is this possible with sveltekit and how do you get access to the underlying server?
The #sveltejs/adapter-node also builds express/polka compatible middleware which is exposed as build/middelwares.js which you can import into a custom /server.cjs:
const {
assetsMiddleware,
prerenderedMiddleware,
kitMiddleware,
} = require("./build/middlewares.js");
...
app.use(assetsMiddleware, prerenderedMiddleware, kitMiddleware);
The node adaptor also has an entryPoint option, which allows bundling the custom server into the build, but I ran into issues using this approach.
Adapters are not used during development (aka npx svelte-kit dev).
But using the svelte.config.js you're able to inject socket.io into the vite server:
...
kit: {
...
vite: {
plugins: [
{
name: "sveltekit-socket-io",
configureServer(server) {
const io = new Server(server.httpServer);
...
},
},
],
},
},
Note: the dev server needs to be restarted to apply changes in the server code.
You could use entr to automate that.
You cannot connect to a polka/express server because depending on the adapter you choose there can be no polka/express server used - if you deploy to a serverless platform for example. Sockets for serverless are not so easy to implement and their implementation depend on the provider.
You are raising an important concern but right now I'm afraid this is not possible - someone corrects me if I'm wrong.
What you still can do is to write your front with SvelteKit, build it as a static/SPA/node application and then use your build from your own polka/express server. You lose the swift development experience offered by SvelteKit though, since your development will be parted in two: first the client, then the server.
EDIT
You can also use a data-pusher third service. They are straightforward to use but not necessarily free. Here is a list of data-pusher services from the Vercel page:
Ably
Pusher
PubNub
Firebase Realtime Database
TalkJS
SendBird
Supabase

How to give the server port to client

I have a node server with several node projects. I use nginx to get them all responding on port 80. Now, this works for the initial http request. For the websockets, I need to use the direct server port. To keep everything alive while developing I would like to try this, projects will have a dev and live version. Once de dev is stable, I will copy it to the live folder. The live folder is runned by a systemctl script where I define a difrent port to the live version so I can dev without taking the live down. The problem I encounter now is, how can I get the running server port in my client side Javascript so that the dev page connect to the dev port and visa versa?
currently I'm only using express, socket.io and mysql. I have no further npm packages installed. I searched allot but there is not to mush I can find. I found how to connect the socket to the page url but I cannot use that because that URL will always be on port 80. Further I found allot of huge packages that has no use for me since the original page is just static, the dynamics all run over websockets.
Is there any way to parse the port number in the clients .js file like I could do fairly easy in php? And if so, what would be the most efficient way. I could let javascript check if the page uses the live or dev URL but I would prefer not to hardcode my dev URL into JS where it is for everyone to see.
run a third node.js socket.io server program, all your clients connect to this server first.
In this simple node.js program, determine the type of clients by any means. e.g. different user id for dev/production users
send the server url and port to your client according to its type (dev or production)
you may also use this technique to separate your users to different production servers.

Configure Node.js app based on machine type or IDE flags

I want to be able to do different things on my server when running on a web server or running on localhost, like disabling logs or connecting to different data stores.
Is there any way to configure a Node.js app differently based on some IDE definitions (specifically WebStorm in this case) or identify the machine a Node.js express server is running on - and more specifically detecting if the server is running on Azure or on localhost.
The standard way to do this in Node is to use an environment variable that identifies each unique deployment config, combined with custom settings that map to each of those configs:
Here's a good SO topic on that:
environment configs in Node
Combined with the above, in Azure you would define the NODE_ENV variable in Application settings to denote that you're running in Azure, something like this:
In your code you check the value of process.env.NODE_ENV and use the appropriate action based on whether you're in Azure, on localhost, or some other environment as appropriate for your needs.
Here's a small code sample that demonstrates further:
github sample
Good luck!

Azure Web Site starting my Hapi Node.js site with socket protocol

Whenever I deploy my Hapi.js web application to azure, it starts the server using the socket protocol (see output below).
socket:\\.\pipe\b5c0af85-9393-4dcb-bd9a-3ba9b41ed6fb
GET /
GET /{param*}
GET /api/employees
POST /api/employees
GET /api/employees/{id}
PUT /api/employees/{id}
DELETE /api/employees/{id}
POST /api/worklog
GET /login
POST /login
Hapi server started # socket:\\.\pipe\b5c0af85-9393-4dcb-bd9a-3ba9b41ed6fb
150914/214730.270, [response], socket:\\.\pipe\b5c0af85-9393-4dcb-bd9a-3ba9b41ed6fb: [1;32mget[0m / {} [32m200[0m (316ms)
However, whenever I am running this locally, it starts using http... I have not run into this issue using express or loopback, only Hapi. Is there some sort of configuration that I am missing? This is the server.connection function:
var server = new Hapi.Server();
var host = process.env.host || '0.0.0.0';
var port = process.env.port || 3000;
server.connection({host: host, port: port});
The reason this is a big deal is because I cannot pass socket://*<mydoamin>* to google as a callback URI for OAuth.
You shouldn't need to pass socket://<domain> to google, you'd pass the normal https://yourDomain.com or even the https://yourSiteName.azurewebsites.net to Google for OAuth callback and it should work as you would expect.
The fact that the node application is listening on a pipe rather than a normal tcp socket is just an implementation detail of iisnode. Basically the problem is that node has it's own webserver so you can't use it with other webservers like IIS, Apache, nginx, etc. iisnode bridges the gap between IIS and node in that it allows IIS to listen to the HTTP port on the machine 80 and when IIS gets a request on that port, it just forwards it to the node process that's listening on a named pipe. This allows you to manage your sites in IIS as you normally would on a Windows Server machine, while actually writing your app in node.
You can think of it as 2 webservers running on the box, one (IIS) is acting as a proxy for the other (node) where all the work is actually happening. The fact that the iisnode developer chose to use a named pipe instead of a normal tcp socket is odd (though kind of understandable since you can't easily reserve a port per se as you can a pipe), but it's the way it is.

Categories